Merge branch 'master' into wii-network

# By Ryan Houdek (185) and others
# Via degasus (12) and others
* master: (625 commits)
  Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds.
  Array overrun fixed in VertexShaderCache for the DX11 plugin.
  Fixed DSPTool build.
  Windows build fix
  Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031.
  VideoSoftware: Improve fog range adjustment by using less magic and more comments.
  revert RasterFont for VideoSoftware
  ogl: fix virtual xfb
  Windows build fix from web interface...
  Adjusted the audio loop criteria, using >= on the Wii and == on GC.  This fixes the audio static that occurred in Wii games after hours of play.
  Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check.
  VideoSoftware: Implement fog range adjustment, fixing issue 6147.
  implement 4xSSAA for OGL
  move ogl-only settings into backend
  Fix description of disable fog, and move it to enhancements tab.
  Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4.
  Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4.
  Forced the external exception check to occur sooner by changing the downcount.
  Mark the Direct3D9 backend deprecated.
  Prefer D3D11 and OpenGL over D3D9 by default.
  ...

Conflicts:
	CMakeLists.txt
	Source/Core/Common/Common.vcxproj.filters
	Source/Core/Common/Src/CommonPaths.h
	Source/Core/Core/Core.vcxproj.filters
	Source/Core/Core/Src/Core.cpp
	Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
	Source/VSProps/Dolphin.Win32.props
	Source/VSProps/Dolphin.x64.props
This commit is contained in:
skidau
2013-03-27 13:19:23 +11:00
615 changed files with 96239 additions and 97463 deletions

View File

@ -0,0 +1,167 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "CPUDetect.h"
#include "StringUtil.h"
#include "FileUtil.h"
const char procfile[] = "/proc/cpuinfo";
char *GetCPUString()
{
const char marker[] = "Hardware\t: ";
char *cpu_string = 0;
// Count the number of processor lines in /proc/cpuinfo
char buf[1024];
File::IOFile file(procfile, "r");
auto const fp = file.GetHandle();
if (!fp)
return 0;
while (fgets(buf, sizeof(buf), fp))
{
if (strncmp(buf, marker, sizeof(marker) - 1))
continue;
cpu_string = buf + sizeof(marker) - 1;
cpu_string = strndup(cpu_string, strlen(cpu_string) - 1); // Strip the newline
break;
}
return cpu_string;
}
bool CheckCPUFeature(const char *feature)
{
const char marker[] = "Features\t: ";
char buf[1024];
File::IOFile file(procfile, "r");
auto const fp = file.GetHandle();
if (!fp)
return 0;
while (fgets(buf, sizeof(buf), fp))
{
if (strncmp(buf, marker, sizeof(marker) - 1))
continue;
char *featurestring = buf + sizeof(marker) - 1;
char *token = strtok(featurestring, " ");
while (token != NULL)
{
if (strstr(token, feature))
return true;
token = strtok(NULL, " ");
}
}
return false;
}
int GetCoreCount()
{
const char marker[] = "processor\t: ";
int cores = 0;
char buf[1024];
File::IOFile file(procfile, "r");
auto const fp = file.GetHandle();
if (!fp)
return 0;
while (fgets(buf, sizeof(buf), fp))
{
if (strncmp(buf, marker, sizeof(marker) - 1))
continue;
++cores;
}
return cores;
}
CPUInfo cpu_info;
CPUInfo::CPUInfo() {
Detect();
}
// Detects the various cpu features
void CPUInfo::Detect()
{
// Set some defaults here
// When ARMv8 cpus come out, these need to be updated.
HTT = false;
OS64bit = false;
CPU64bit = false;
Mode64bit = false;
vendor = VENDOR_ARM;
// Get the information about the CPU
strncpy(cpu_string, GetCPUString(), sizeof(cpu_string));
num_cores = GetCoreCount();
bSwp = CheckCPUFeature("swp");
bHalf = CheckCPUFeature("half");
bThumb = CheckCPUFeature("thumb");
bFastMult = CheckCPUFeature("fastmult");
bVFP = CheckCPUFeature("vfp");
bEDSP = CheckCPUFeature("edsp");
bThumbEE = CheckCPUFeature("thumbee");
bNEON = CheckCPUFeature("neon");
bVFPv3 = CheckCPUFeature("vfpv3");
bTLS = CheckCPUFeature("tls");
bVFPv4 = CheckCPUFeature("vfpv4");
bIDIVa = CheckCPUFeature("idiva");
bIDIVt = CheckCPUFeature("idivt");
// On some buggy kernels(Qualcomm) they show that they support VFPv4 but not IDIVa
// All VFPv4 CPUs will support IDIVa
if (bVFPv4)
bIDIVa = bIDIVt = true;
// These two are ARMv8 specific.
bFP = CheckCPUFeature("fp");
bASIMD = CheckCPUFeature("asimd");
#if defined(__ARM_ARCH_7A__)
bArmV7 = true;
#else
bArmV7 = false;
#endif
}
// Turn the cpu info into a string we can show
std::string CPUInfo::Summarize()
{
std::string sum;
if (num_cores == 1)
sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
else
sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
if (bSwp) sum += ", SWP";
if (bHalf) sum += ", Half";
if (bThumb) sum += ", Thumb";
if (bFastMult) sum += ", FastMult";
if (bVFP) sum += ", VFP";
if (bEDSP) sum += ", EDSP";
if (bThumbEE) sum += ", ThumbEE";
if (bNEON) sum += ", NEON";
if (bVFPv3) sum += ", VFPv3";
if (bTLS) sum += ", TLS";
if (bVFPv4) sum += ", VFPv4";
if (bIDIVa) sum += ", IDIVa";
if (bIDIVt) sum += ", IDIVt";
return sum;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,637 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!!
#ifndef _DOLPHIN_ARM_CODEGEN_
#define _DOLPHIN_ARM_CODEGEN_
#include "Common.h"
#include "MemoryUtil.h"
#if defined(__SYMBIAN32__) || defined(PANDORA)
#include <signal.h>
#endif
#include <vector>
#undef _IP
#undef R0
#undef _SP
#undef _LR
#undef _PC
// VCVT flags
#define TO_FLOAT 0
#define TO_INT 1 << 0
#define IS_SIGNED 1 << 1
#define ROUND_TO_ZERO 1 << 2
namespace ArmGen
{
enum ARMReg
{
// GPRs
R0 = 0, R1, R2, R3, R4, R5,
R6, R7, R8, R9, R10, R11,
// SPRs
// R13 - R15 are SP, LR, and PC.
// Almost always referred to by name instead of register number
R12 = 12, R13 = 13, R14 = 14, R15 = 15,
_IP = 12, _SP = 13, _LR = 14, _PC = 15,
// VFP single precision registers
S0, S1, S2, S3, S4, S5, S6,
S7, S8, S9, S10, S11, S12, S13,
S14, S15, S16, S17, S18, S19, S20,
S21, S22, S23, S24, S25, S26, S27,
S28, S29, S30, S31,
// VFP Double Precision registers
D0, D1, D2, D3, D4, D5, D6, D7,
D8, D9, D10, D11, D12, D13, D14, D15,
D16, D17, D18, D19, D20, D21, D22, D23,
D24, D25, D26, D27, D28, D29, D30, D31,
// ASIMD Quad-Word registers
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7,
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
INVALID_REG = 0xFFFFFFFF
};
enum CCFlags
{
CC_EQ = 0, // Equal
CC_NEQ, // Not equal
CC_CS, // Carry Set
CC_CC, // Carry Clear
CC_MI, // Minus (Negative)
CC_PL, // Plus
CC_VS, // Overflow
CC_VC, // No Overflow
CC_HI, // Unsigned higher
CC_LS, // Unsigned lower or same
CC_GE, // Signed greater than or equal
CC_LT, // Signed less than
CC_GT, // Signed greater than
CC_LE, // Signed less than or equal
CC_AL, // Always (unconditional) 14
CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same
CC_LO = CC_CC, // Alias of CC_CC Unsigned lower
};
const u32 NO_COND = 0xE0000000;
enum ShiftType
{
ST_LSL = 0,
ST_ASL = 0,
ST_LSR = 1,
ST_ASR = 2,
ST_ROR = 3,
ST_RRX = 4
};
enum IntegerSize
{
I_I8 = 0,
I_I16,
I_I32,
I_I64
};
enum
{
NUMGPRs = 13,
};
class ARMXEmitter;
enum OpType
{
TYPE_IMM = 0,
TYPE_REG,
TYPE_IMMSREG,
TYPE_RSR,
TYPE_MEM
};
// This is no longer a proper operand2 class. Need to split up.
class Operand2
{
friend class ARMXEmitter;
protected:
u32 Value;
private:
OpType Type;
// IMM types
u8 Rotation; // Only for u8 values
// Register types
u8 IndexOrShift;
ShiftType Shift;
public:
OpType GetType()
{
return Type;
}
Operand2() {}
Operand2(u32 imm, OpType type = TYPE_IMM)
{
Type = type;
Value = imm;
Rotation = 0;
}
Operand2(ARMReg Reg)
{
Type = TYPE_REG;
Value = Reg;
Rotation = 0;
}
Operand2(u8 imm, u8 rotation)
{
Type = TYPE_IMM;
Value = imm;
Rotation = rotation;
}
Operand2(ARMReg base, ShiftType type, ARMReg shift) // RSR
{
Type = TYPE_RSR;
_assert_msg_(DYNA_REC, type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount");
IndexOrShift = shift;
Shift = type;
Value = base;
}
Operand2(ARMReg base, ShiftType type, u8 shift)// For IMM shifted register
{
if(shift == 32) shift = 0;
switch (type)
{
case ST_LSL:
_assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSL %u", shift);
break;
case ST_LSR:
_assert_msg_(DYNA_REC, shift <= 32, "Invalid Operand2: LSR %u", shift);
if (!shift)
type = ST_LSL;
if (shift == 32)
shift = 0;
break;
case ST_ASR:
_assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSR %u", shift);
if (!shift)
type = ST_LSL;
if (shift == 32)
shift = 0;
break;
case ST_ROR:
_assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: ROR %u", shift);
if (!shift)
type = ST_LSL;
break;
case ST_RRX:
_assert_msg_(DYNA_REC, shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount");
type = ST_ROR;
break;
}
IndexOrShift = shift;
Shift = type;
Value = base;
Type = TYPE_IMMSREG;
}
u32 GetData()
{
switch(Type)
{
case TYPE_IMM:
return Imm12Mod(); // This'll need to be changed later
case TYPE_REG:
return Rm();
case TYPE_IMMSREG:
return IMMSR();
case TYPE_RSR:
return RSR();
default:
_assert_msg_(DYNA_REC, false, "GetData with Invalid Type");
return 0;
}
}
u32 IMMSR() // IMM shifted register
{
_assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register");
return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value);
}
u32 RSR() // Register shifted register
{
_assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course");
return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value;
}
u32 Rm()
{
_assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
return Value;
}
u32 Imm5()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
return ((Value & 0x0000001F) << 7);
}
u32 Imm8()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
return Value & 0xFF;
}
u32 Imm8Rot() // IMM8 with Rotation
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
_assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation);
return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF);
}
u32 Imm12()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
return (Value & 0x00000FFF);
}
u32 Imm12Mod()
{
// This is a IMM12 with the top four bits being rotation and the
// bottom eight being a IMM. This is for instructions that need to
// expand a 8bit IMM to a 32bit value and gives you some rotation as
// well.
// Each rotation rotates to the right by 2 bits
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM");
return ((Rotation & 0xF) << 8) | (Value & 0xFF);
}
u32 Imm16()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
}
u32 Imm16Low()
{
return Imm16();
}
u32 Imm16High() // Returns high 16bits
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
}
u32 Imm24()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
return (Value & 0x0FFFFFFF);
}
// NEON and ASIMD specific
u32 Imm8ASIMD()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
}
u32 Imm8VFP()
{
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM");
return ((Value & 0xF0) << 12) | (Value & 0xF);
}
};
// Use these when you don't know if an imm can be represented as an operand2.
// This lets you generate both an optimal and a fallback solution by checking
// the return value, which will be false if these fail to find a Operand2 that
// represents your 32-bit imm value.
bool TryMakeOperand2(u32 imm, Operand2 &op2);
bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse);
bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
//usage: struct {int e;} s; STRUCT_OFFSET(s,e)
#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str)))
struct FixupBranch
{
u8 *ptr;
u32 condition; // Remembers our codition at the time
int type; //0 = B 1 = BL
};
struct LiteralPool
{
s32 loc;
u8* ldr_address;
u32 val;
};
typedef const u8* JumpTarget;
class ARMXEmitter
{
friend struct OpArg; // for Write8 etc
private:
u8 *code, *startcode;
u8 *lastCacheFlushEnd;
u32 condition;
std::vector<LiteralPool> currentLitPool;
void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
u32 EncodeVd(ARMReg Vd);
u32 EncodeVn(ARMReg Vn);
u32 EncodeVm(ARMReg Vm);
void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
// New Ops
void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false);
protected:
inline void Write32(u32 value) {*(u32*)code = value; code+=4;}
public:
ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) {
condition = CC_AL << 28;
}
ARMXEmitter(u8 *code_ptr) {
code = code_ptr;
lastCacheFlushEnd = code_ptr;
startcode = code_ptr;
condition = CC_AL << 28;
}
virtual ~ARMXEmitter() {}
void SetCodePtr(u8 *ptr);
void ReserveCodeSpace(u32 bytes);
const u8 *AlignCode16();
const u8 *AlignCodePage();
const u8 *GetCodePtr() const;
void FlushIcache();
void FlushIcacheSection(u8 *start, u8 *end);
u8 *GetWritableCodePtr();
void FlushLitPool();
void AddNewLit(u32 val);
CCFlags GetCC() { return CCFlags(condition >> 28); }
void SetCC(CCFlags cond = CC_AL);
// Special purpose instructions
// Dynamic Endian Switching
void SETEND(bool BE);
// Debug Breakpoint
void BKPT(u16 arg);
// Hint instruction
void YIELD();
// Do nothing
void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals)
#ifdef CALL
#undef CALL
#endif
// Branching
FixupBranch B();
FixupBranch B_CC(CCFlags Cond);
void B_CC(CCFlags Cond, const void *fnptr);
FixupBranch BL();
FixupBranch BL_CC(CCFlags Cond);
void SetJumpTarget(FixupBranch const &branch);
void B (const void *fnptr);
void B (ARMReg src);
void BL(const void *fnptr);
void BL(ARMReg src);
void PUSH(const int num, ...);
void POP(const int num, ...);
// New Data Ops
void AND (ARMReg Rd, ARMReg Rn, Operand2 Rm);
void ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm);
void EOR (ARMReg dest, ARMReg src, Operand2 op2);
void EORS(ARMReg dest, ARMReg src, Operand2 op2);
void SUB (ARMReg dest, ARMReg src, Operand2 op2);
void SUBS(ARMReg dest, ARMReg src, Operand2 op2);
void RSB (ARMReg dest, ARMReg src, Operand2 op2);
void RSBS(ARMReg dest, ARMReg src, Operand2 op2);
void ADD (ARMReg dest, ARMReg src, Operand2 op2);
void ADDS(ARMReg dest, ARMReg src, Operand2 op2);
void ADC (ARMReg dest, ARMReg src, Operand2 op2);
void ADCS(ARMReg dest, ARMReg src, Operand2 op2);
void LSL (ARMReg dest, ARMReg src, Operand2 op2);
void LSL (ARMReg dest, ARMReg src, ARMReg op2);
void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
void LSLS(ARMReg dest, ARMReg src, ARMReg op2);
void LSR (ARMReg dest, ARMReg src, Operand2 op2);
void SBC (ARMReg dest, ARMReg src, Operand2 op2);
void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
void RBIT(ARMReg dest, ARMReg src);
void REV (ARMReg dest, ARMReg src);
void REV16 (ARMReg dest, ARMReg src);
void RSC (ARMReg dest, ARMReg src, Operand2 op2);
void RSCS(ARMReg dest, ARMReg src, Operand2 op2);
void TST ( ARMReg src, Operand2 op2);
void TEQ ( ARMReg src, Operand2 op2);
void CMP ( ARMReg src, Operand2 op2);
void CMN ( ARMReg src, Operand2 op2);
void ORR (ARMReg dest, ARMReg src, Operand2 op2);
void ORRS(ARMReg dest, ARMReg src, Operand2 op2);
void MOV (ARMReg dest, Operand2 op2);
void MOVS(ARMReg dest, Operand2 op2);
void BIC (ARMReg dest, ARMReg src, Operand2 op2); // BIC = ANDN
void BICS(ARMReg dest, ARMReg src, Operand2 op2);
void MVN (ARMReg dest, Operand2 op2);
void MVNS(ARMReg dest, Operand2 op2);
void MOVW(ARMReg dest, Operand2 op2);
void MOVT(ARMReg dest, Operand2 op2, bool TopBits = false);
// UDIV and SDIV are only available on CPUs that have
// the idiva hardare capacity
void UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
void SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
void MUL (ARMReg dest, ARMReg src, ARMReg op2);
void MULS(ARMReg dest, ARMReg src, ARMReg op2);
void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
void SXTB(ARMReg dest, ARMReg op2);
void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0);
void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0);
void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width);
void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width);
void CLZ(ARMReg rd, ARMReg rm);
// Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...)
// Just need to put an underscore here, bit annoying.
void _MSR (bool nzcvq, bool g, Operand2 op2);
void _MSR (bool nzcvq, bool g, ARMReg src);
void MRS (ARMReg dest);
// Memory load/store operations
void LDR (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRB (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRH (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRSB(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRSH(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void STR (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
// Exclusive Access operations
void LDREX(ARMReg dest, ARMReg base);
// result contains the result if the instruction managed to store the value
void STREX(ARMReg result, ARMReg base, ARMReg op);
void DMB ();
void SVC(Operand2 op);
// NEON and ASIMD instructions
// None of these will be created with conditional since ARM
// is deprecating conditional execution of ASIMD instructions.
// ASIMD instructions don't even have a conditional encoding.
// Subtracts the base from the register to give us the real one
ARMReg SubBase(ARMReg Reg);
// NEON Only
void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
// VFP Only
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
void VSTR(ARMReg Src, ARMReg Base, s16 offset);
void VCMP(ARMReg Vd, ARMReg Vm);
void VCMPE(ARMReg Vd, ARMReg Vm);
// Compares against zero
void VCMP(ARMReg Vd);
void VCMPE(ARMReg Vd);
void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VSQRT(ARMReg Vd, ARMReg Vm);
// NEON and VFP
void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VABS(ARMReg Vd, ARMReg Vm);
void VNEG(ARMReg Vd, ARMReg Vm);
void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMLS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMOV(ARMReg Dest, ARMReg Src, bool high);
void VMOV(ARMReg Dest, ARMReg Src);
void VCVT(ARMReg Dest, ARMReg Src, int flags);
void VMRS_APSR();
void VMRS(ARMReg Rt);
void VMSR(ARMReg Rt);
void QuickCallFunction(ARMReg scratchreg, void *func);
// Wrapper around MOVT/MOVW with fallbacks.
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
void MOVI2F(ARMReg dest, float val, ARMReg tempReg);
void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
}; // class ARMXEmitter
// Everything that needs to generate X86 code should inherit from this.
// You get memory management for free, plus, you can use all the MOV etc functions without
// having to prefix them with gen-> or something similar.
class ARMXCodeBlock : public ARMXEmitter
{
protected:
u8 *region;
size_t region_size;
public:
ARMXCodeBlock() : region(NULL), region_size(0) {}
virtual ~ARMXCodeBlock() { if (region) FreeCodeSpace(); }
// Call this before you generate any code.
void AllocCodeSpace(int size)
{
region_size = size;
region = (u8*)AllocateExecutableMemory(region_size);
SetCodePtr(region);
}
// Always clear code space with breakpoints, so that if someone accidentally executes
// uninitialized, it just breaks into the debugger.
void ClearCodeSpace()
{
// x86/64: 0xCC = breakpoint
memset(region, 0xCC, region_size);
ResetCodePtr();
}
// Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
void FreeCodeSpace()
{
#ifndef __SYMBIAN32__
FreeMemoryPages(region, region_size);
#endif
region = NULL;
region_size = 0;
}
bool IsInSpace(u8 *ptr)
{
return ptr >= region && ptr < region + region_size;
}
// Cannot currently be undone. Will write protect the entire code region.
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect()
{
WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr()
{
SetCodePtr(region);
}
size_t GetSpaceLeft() const
{
return region_size - (GetCodePtr() - region);
}
};
} // namespace
#endif // _DOLPHIN_INTEL_CODEGEN_

View File

@ -27,9 +27,9 @@ class DebugInterface;
struct TBreakPoint
{
u32 iAddress;
u32 iAddress;
bool bOn;
bool bTemporary;
bool bTemporary;
};
struct TMemCheck
@ -96,9 +96,9 @@ public:
typedef std::vector<std::string> TMemChecksStr;
TMemChecks m_MemChecks;
const TMemChecks& GetMemChecks() { return m_MemChecks; }
TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mcs);

View File

@ -6,6 +6,7 @@
#include <memory> // for std::unique_ptr
#ifdef _WIN32
#include <windows.h>
#include "StringUtil.h"
#elif __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOBSD.h>
@ -25,7 +26,7 @@
#ifdef _WIN32
// takes a root drive path, returns true if it is a cdrom drive
bool is_cdrom(const char drive[])
bool is_cdrom(const TCHAR* drive)
{
return (DRIVE_CDROM == GetDriveType(drive));
}
@ -36,15 +37,15 @@ std::vector<std::string> cdio_get_devices()
std::vector<std::string> drives;
const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
std::unique_ptr<char[]> buff(new char[buffsize]);
if (GetLogicalDriveStrings(buffsize, buff.get()) == buffsize - 1)
std::vector<TCHAR> buff(buffsize);
if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
{
const char* drive = buff.get();
auto drive = buff.data();
while (*drive)
{
if (is_cdrom(drive))
{
std::string str(drive);
std::string str(TStrToUTF8(drive));
str.pop_back(); // we don't want the final backslash
drives.push_back(std::move(str));
}

View File

@ -25,19 +25,20 @@ enum CPUVendor
{
VENDOR_INTEL = 0,
VENDOR_AMD = 1,
VENDOR_OTHER = 2,
VENDOR_ARM = 2,
VENDOR_OTHER = 3,
};
struct CPUInfo
{
CPUVendor vendor;
char cpu_string[0x21];
char brand_string[0x41];
bool OS64bit;
bool CPU64bit;
bool Mode64bit;
bool HTT;
int num_cores;
int logical_cpu_count;
@ -56,9 +57,29 @@ struct CPUInfo
bool bLAHFSAHF64;
bool bLongMode;
// ARM specific CPUInfo
bool bSwp;
bool bHalf;
bool bThumb;
bool bFastMult;
bool bVFP;
bool bEDSP;
bool bThumbEE;
bool bNEON;
bool bVFPv3;
bool bTLS;
bool bVFPv4;
bool bIDIVa;
bool bIDIVt;
bool bArmV7; // enable MOVT, MOVW etc
// ARMv8 specific
bool bFP;
bool bASIMD;
// Call Detect()
explicit CPUInfo();
// Turn the cpu info into a string we can show
std::string Summarize();

View File

@ -29,6 +29,7 @@
#include <map>
#include <vector>
#include <list>
#include <deque>
#include <string>
@ -45,7 +46,8 @@ struct LinkedListItem : public T
class PointerWrap
{
public:
enum Mode {
enum Mode
{
MODE_READ = 1, // load
MODE_WRITE, // save
MODE_MEASURE, // calculate size
@ -57,124 +59,95 @@ public:
public:
PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {}
void SetMode(Mode mode_) {mode = mode_;}
Mode GetMode() const {return mode;}
u8 **GetPPtr() {return ptr;}
void SetMode(Mode mode_) { mode = mode_; }
Mode GetMode() const { return mode; }
u8** GetPPtr() { return ptr; }
void DoVoid(void *data, int size)
template <typename K, class V>
void Do(std::map<K, V>& x)
{
switch (mode) {
case MODE_READ: memcpy(data, *ptr, size); break;
case MODE_WRITE: memcpy(*ptr, data, size); break;
case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break;
default: break; // throw an error?
}
(*ptr) += size;
}
u32 count = (u32)x.size();
Do(count);
template<class T>
void Do(std::map<unsigned int, T> &x)
{
unsigned int number = (unsigned int)x.size();
Do(number);
switch (mode) {
switch (mode)
{
case MODE_READ:
for (x.clear(); count != 0; --count)
{
x.clear();
while (number > 0)
{
unsigned int first = 0;
Do(first);
T second;
Do(second);
x[first] = second;
--number;
}
std::pair<K, V> pair;
Do(pair.first);
Do(pair.second);
x.insert(pair);
}
break;
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY:
for (auto itr = x.begin(); itr != x.end(); ++itr)
{
typename std::map<unsigned int, T>::iterator itr = x.begin();
while (number > 0)
{
Do(itr->first);
Do(itr->second);
--number;
++itr;
}
Do(itr->first);
Do(itr->second);
}
break;
}
}
// Store vectors.
template<class T>
void Do(std::vector<T> &x)
template <typename T>
void DoContainer(T& x)
{
u32 vec_size = (u32)x.size();
Do(vec_size);
x.resize(vec_size);
DoArray(&x[0], vec_size);
u32 size = (u32)x.size();
Do(size);
x.resize(size);
for (auto itr = x.begin(); itr != x.end(); ++itr)
Do(*itr);
}
// Store deques.
template<class T>
void Do(std::deque<T> &x)
template <typename T>
void Do(std::vector<T>& x)
{
u32 deq_size = (u32)x.size();
Do(deq_size);
x.resize(deq_size);
u32 i;
for(i = 0; i < deq_size; i++)
DoVoid(&x[i],sizeof(T));
DoContainer(x);
}
// Store strings.
void Do(std::string &x)
template <typename T>
void Do(std::list<T>& x)
{
int stringLen = (int)x.length() + 1;
Do(stringLen);
DoContainer(x);
}
template <typename T>
void Do(std::deque<T>& x)
{
DoContainer(x);
}
template <typename T>
void Do(std::basic_string<T>& x)
{
DoContainer(x);
}
template <typename T>
void DoArray(T* x, u32 count)
{
for (u32 i = 0; i != count; ++i)
Do(x[i]);
}
template <typename T>
void Do(T& x)
{
// TODO: Bad, Do(some_non_POD) will compile and fail at runtime
// type_traits are not fully supported everywhere yet
switch (mode) {
case MODE_READ: x = (char*)*ptr; break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
case MODE_MEASURE: break;
case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break;
}
(*ptr) += stringLen;
DoVoid((void*)&x, sizeof(x));
}
void Do(std::wstring &x)
template <typename T>
void DoPointer(T*& x, T* const base)
{
int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
Do(stringLen);
switch (mode) {
case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
case MODE_MEASURE: break;
case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
}
(*ptr) += stringLen;
}
template<class T>
void DoArray(T *x, int count) {
DoVoid((void *)x, sizeof(T) * count);
}
template<class T>
void Do(T &x) {
DoVoid((void *)&x, sizeof(x));
}
template<class T>
void DoPointer(T* &x, T*const base) {
// pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range
s32 offset = x - base;
Do(offset);
@ -182,7 +155,8 @@ public:
x = base + offset;
}
template<class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
// Let's pretend std::list doesn't exist!
template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end=0)
{
LinkedListItem<T>* list_cur = list_start;
@ -242,25 +216,61 @@ public:
}
}
void DoMarker(const char* prevName, u32 arbitraryNumber=0x42)
void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42)
{
u32 cookie = arbitraryNumber;
Do(cookie);
if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
{
PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...",
prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
mode = PointerWrap::MODE_MEASURE;
}
}
};
private:
__forceinline void DoByte(u8& x)
{
switch (mode)
{
case MODE_READ:
x = **ptr;
break;
case MODE_WRITE:
**ptr = x;
break;
case MODE_MEASURE:
break;
case MODE_VERIFY:
_dbg_assert_msg_(COMMON, (x == **ptr),
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
x, x, &x, **ptr, **ptr, *ptr);
break;
default:
break;
}
++(*ptr);
}
void DoVoid(void *data, u32 size)
{
for(u32 i = 0; i != size; ++i)
DoByte(reinterpret_cast<u8*>(data)[i]);
}
};
class CChunkFileReader
{
public:
// Load file template
template<class T>
static bool Load(const std::string& _rFilename, int _Revision, T& _class)
static bool Load(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
@ -290,7 +300,7 @@ public:
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
return false;
}
// Check revision
if (header.Revision != _Revision)
{
@ -298,36 +308,35 @@ public:
header.Revision, _Revision);
return false;
}
// get size
const int sz = (int)(fileSize - headerSize);
const u32 sz = (u32)(fileSize - headerSize);
if (header.ExpectedSize != sz)
{
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
sz, header.ExpectedSize);
return false;
}
// read the state
u8* buffer = new u8[sz];
if (!pFile.ReadBytes(buffer, sz))
std::vector<u8> buffer(sz);
if (!pFile.ReadArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
return false;
}
u8 *ptr = buffer;
u8* ptr = &buffer[0];
PointerWrap p(&ptr, PointerWrap::MODE_READ);
_class.DoState(p);
delete[] buffer;
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
return true;
}
// Save file template
template<class T>
static bool Save(const std::string& _rFilename, int _Revision, T& _class)
static bool Save(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
File::IOFile pFile(_rFilename, "wb");
@ -346,13 +355,12 @@ public:
ptr = &buffer[0];
p.SetMode(PointerWrap::MODE_WRITE);
_class.DoState(p);
// Create header
SChunkHeader header;
header.Compress = 0;
header.Revision = _Revision;
header.ExpectedSize = (int)sz;
header.ExpectedSize = (u32)sz;
// Write to file
if (!pFile.WriteArray(&header, 1))
{
@ -360,23 +368,21 @@ public:
return false;
}
if (!pFile.WriteBytes(&buffer[0], sz))
if (!pFile.WriteArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
return false;
}
INFO_LOG(COMMON,"ChunkReader: Done writing %s",
_rFilename.c_str());
INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str());
return true;
}
private:
struct SChunkHeader
{
int Revision;
int Compress;
int ExpectedSize;
u32 Revision;
u32 ExpectedSize;
};
};

View File

@ -133,7 +133,9 @@ private:
// wxWidgets does not have a true dummy macro for this.
#define _trans(a) a
#if defined __GNUC__
#if defined _M_GENERIC
# define _M_SSE 0x0
#elif defined __GNUC__
# if defined __SSE4_2__
# define _M_SSE 0x402
# elif defined __SSE4_1__
@ -144,7 +146,7 @@ private:
# define _M_SSE 0x300
# endif
#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
# define _M_SSE 0x402
# define _M_SSE 0x402
#endif
// Host communication.
@ -155,7 +157,6 @@ enum HOST_COMM
WM_USER_CREATE,
WM_USER_SETCURSOR,
WM_USER_KEYDOWN,
WIIMOTE_DISCONNECT // Disconnect Wiimote
};
// Used for notification on emulation state

View File

@ -35,7 +35,7 @@ template<> struct CompileTimeAssert<true> {};
#define b32(x) (b16(x) | (b16(x) >>16) )
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
#if defined __GNUC__ && !defined __SSSE3__
#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC
#include <emmintrin.h>
static __inline __m128i __attribute__((__always_inline__))
_mm_shuffle_epi8(__m128i a, __m128i mask)
@ -60,15 +60,17 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
// go to debugger mode
#ifdef GEKKO
#define Crash()
#elif defined _M_GENERIC
#define Crash() { exit(1); }
#else
#define Crash() {asm ("int $3");}
#endif
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
inline u32 _rotl(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x << shift) | (x >> (32 - shift));
shift &= 31;
if (!shift) return x;
return (x << shift) | (x >> (32 - shift));
}
inline u64 _rotl64(u64 x, unsigned int shift){
@ -77,9 +79,9 @@ inline u64 _rotl64(u64 x, unsigned int shift){
}
inline u32 _rotr(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x >> shift) | (x << (32 - shift));
shift &= 31;
if (!shift) return x;
return (x >> shift) | (x << (32 - shift));
}
inline u64 _rotr64(u64 x, unsigned int shift){
@ -136,6 +138,15 @@ inline u8 swap8(u8 _data) {return _data;}
inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
#elif _M_ARM
#ifdef ANDROID
#undef swap16
#undef swap32
#undef swap64
#endif
inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
#elif __linux__
inline u16 swap16(u16 _data) {return bswap_16(_data);}
inline u32 swap32(u32 _data) {return bswap_32(_data);}
@ -162,6 +173,40 @@ inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);}
inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);}
inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);}
template <int count>
void swap(u8*);
template <>
inline void swap<1>(u8* data)
{}
template <>
inline void swap<2>(u8* data)
{
*reinterpret_cast<u16*>(data) = swap16(data);
}
template <>
inline void swap<4>(u8* data)
{
*reinterpret_cast<u32*>(data) = swap32(data);
}
template <>
inline void swap<8>(u8* data)
{
*reinterpret_cast<u64*>(data) = swap64(data);
}
template <typename T>
inline T FromBigEndian(T data)
{
//static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
return data;
}
} // Namespace Common
#endif // _COMMONFUNCS_H_

View File

@ -36,6 +36,9 @@
// You can use the File::GetUserPath() util for this
#define USERDATA_DIR "Contents/Resources/User"
#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin"
#elif defined ANDROID
#define USERDATA_DIR "user"
#define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu"
#else
#define USERDATA_DIR "user"
#ifdef USER_DIR
@ -52,6 +55,8 @@
#define SYSDATA_DIR "Contents/Resources/Sys"
#define SHARED_USER_DIR File::GetBundleDirectory() + \
DIR_SEP USERDATA_DIR DIR_SEP
#elif defined ANDROID
#define SYSDATA_DIR "/sdcard/dolphin-emu"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
@ -123,9 +128,9 @@
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
#define WII_STATE "state.dat"
#define WII_STATE "state.dat"
#define WII_SETTING "setting.txt"
#define WII_SETTING "setting.txt"
#define GECKO_CODE_HANDLER "codehandler.bin"

View File

@ -61,7 +61,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
SetConsoleTitle(Title);
SetConsoleTitle(UTF8ToTStr(Title).c_str());
// Set letter space
LetterSpace(80, 4000);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
@ -195,7 +195,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
static const int MAX_BYTES = 1024 * 16;
std::vector<std::array<CHAR, MAX_BYTES>> Str;
std::vector<std::array<TCHAR, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
@ -227,7 +227,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
LetterSpace(LBufWidth, LBufHeight);
ClearScreen(true);
ClearScreen(true);
coordScreen.Y = 0;
coordScreen.X = 0;
DWORD cCharsWritten = 0;
@ -270,7 +270,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
*/
DWORD cCharsWritten;
WORD Color;
switch (Level)
{
case NOTICE_LEVEL: // light green
@ -334,9 +334,9 @@ void ConsoleListener::ClearScreen(bool Cursor)
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console

View File

@ -37,6 +37,8 @@
#include <string.h>
#include <stdio.h>
#include "../FileUtil.h"
/*
* 32-bit integer manipulation macros (little endian)
*/
@ -301,7 +303,10 @@ int md5_file( char *path, unsigned char output[16] )
md5_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
File::IOFile file(path, "rb");
f = file.GetHandle();
if (f == NULL)
return( 1 );
md5_starts( &ctx );
@ -315,11 +320,9 @@ int md5_file( char *path, unsigned char output[16] )
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}

View File

@ -36,6 +36,8 @@
#include <string.h>
#include <stdio.h>
#include "../FileUtil.h"
/*
* 32-bit integer manipulation macros (big endian)
*/
@ -335,7 +337,10 @@ int sha1_file( char *path, unsigned char output[20] )
sha1_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
File::IOFile file(path, "rb");
f = file.GetHandle();
if (f == NULL)
return( 1 );
sha1_starts( &ctx );
@ -349,11 +354,9 @@ int sha1_file( char *path, unsigned char output[20] )
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}

View File

@ -17,6 +17,7 @@
#include <windows.h>
#include <stdio.h>
#include "ExtendedTrace.h"
#include "StringUtil.h"
using namespace std;
#include <tchar.h>
@ -274,13 +275,21 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
return ret;
}
void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
{
TCHAR symInfo[BUFFERSIZE] = _T("?");
TCHAR srcInfo[BUFFERSIZE] = _T("?");
GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
}
void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
{
STACKFRAME callStack;
BOOL bResult;
CONTEXT context;
TCHAR symInfo[BUFFERSIZE] = _T("?");
TCHAR srcInfo[BUFFERSIZE] = _T("?");
HANDLE hProcess = GetCurrentProcess();
// If it's not this thread, let's suspend it, and resume it at the end
@ -318,9 +327,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@ -341,9 +348,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
PrintFunctionAndSourceInfo(file, callStack);
}
@ -351,19 +356,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
ResumeThread( hThread );
}
void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
// TODO: remove when Common builds as unicode
size_t origsize = wcslen(lpszMessage) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE);
StackTrace(hThread, nstring, file, eip, esp, ebp );
}
void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
STACKFRAME callStack;
BOOL bResult;
@ -391,9 +384,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@ -414,10 +405,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
PrintFunctionAndSourceInfo(file, callStack);
}
if ( hThread != GetCurrentThread() )
@ -426,7 +414,8 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
char g_uefbuf[2048];
void etfprintf(FILE *file, const char *format, ...) {
void etfprintf(FILE *file, const char *format, ...)
{
va_list ap;
va_start(ap, format);
int len = vsprintf(g_uefbuf, format, ap);
@ -434,7 +423,8 @@ void etfprintf(FILE *file, const char *format, ...) {
va_end(ap);
}
void etfprint(FILE *file, const std::string &text) {
void etfprint(FILE *file, const std::string &text)
{
size_t len = text.length();
fwrite(text.data(), 1, len, file);
}

View File

@ -25,16 +25,15 @@
#pragma comment( lib, "imagehlp.lib" )
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
#define STACKTRACE(file) StackTrace( GetCurrentThread(), _T(""), file)
#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), _T(""), file, eip, esp, ebp)
#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
// class File;
BOOL InitSymInfo( PCSTR );
BOOL UninitSymInfo();
void StackTrace( HANDLE, LPCTSTR, FILE *file);
void StackTrace( HANDLE, LPCTSTR, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
void StackTrace(HANDLE, char const* msg, FILE *file);
void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
// functions by Masken
void etfprintf(FILE *file, const char *format, ...);
@ -44,10 +43,10 @@ extern char g_uefbuf[UEFBUFSIZE];
#else // not WIN32
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
#define STACKTRACE(file) ((void)0)
#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
#define STACKTRACE(file) ((void)0)
#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
#endif // WIN32

View File

@ -0,0 +1,52 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef FPU_ROUND_MODE_H_
#define FPU_ROUND_MODE_H_
#include "Common.h"
namespace FPURoundMode
{
enum RoundModes
{
ROUND_NEAR = 0,
ROUND_CHOP,
ROUND_UP,
ROUND_DOWN
};
enum PrecisionModes {
PREC_24 = 0,
PREC_53,
PREC_64
};
void SetRoundMode(u32 mode);
void SetPrecisionMode(u32 mode);
void SetSIMDMode(u32 mode);
/*
* There are two different flavors of float to int conversion:
* _mm_cvtps_epi32() and _mm_cvttps_epi32().
*
* The first rounds according to the MXCSR rounding bits.
* The second one always uses round towards zero.
*/
void SaveSIMDState();
void LoadSIMDState();
void LoadDefaultSIMDState();
}
#endif

View File

@ -51,7 +51,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
#ifdef _WIN32
WIN32_FIND_DATA findData;
HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData);
HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
if (FindFirst != INVALID_HANDLE_VALUE)
{
@ -62,7 +62,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
if (findData.cFileName[0] != '.')
{
std::string strFilename;
BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
m_FileNames.push_back(strFilename);
}
@ -112,7 +112,6 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
#endif
}
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
{
return m_FileNames;

View File

@ -41,10 +41,11 @@
#include <CoreFoundation/CFBundle.h>
#endif
#include <fstream>
#include <algorithm>
#include <sys/stat.h>
#include "StringUtil.h"
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
@ -81,7 +82,11 @@ bool Exists(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
#ifdef _WIN32
int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
#else
int result = stat64(copy.c_str(), &file_info);
#endif
return (result == 0);
}
@ -94,7 +99,11 @@ bool IsDirectory(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
#ifdef _WIN32
int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
#else
int result = stat64(copy.c_str(), &file_info);
#endif
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
@ -127,7 +136,7 @@ bool Delete(const std::string &filename)
}
#ifdef _WIN32
if (!DeleteFile(filename.c_str()))
if (!DeleteFile(UTF8ToTStr(filename).c_str()))
{
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
@ -149,7 +158,7 @@ bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
if (::CreateDirectory(path.c_str(), NULL))
if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@ -181,7 +190,7 @@ bool CreateFullPath(const std::string &fullPath)
{
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
if (File::Exists(fullPath))
{
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
@ -197,7 +206,7 @@ bool CreateFullPath(const std::string &fullPath)
// we're done, yay!
if (position == fullPath.npos)
return true;
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!File::IsDirectory(subPath))
@ -228,7 +237,7 @@ bool DeleteDir(const std::string &filename)
}
#ifdef _WIN32
if (::RemoveDirectory(filename.c_str()))
if (::RemoveDirectory(UTF8ToTStr(filename).c_str()))
return true;
#else
if (rmdir(filename.c_str()) == 0)
@ -257,7 +266,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE))
if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
@ -342,8 +351,13 @@ u64 GetSize(const std::string &filename)
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
return 0;
}
struct stat64 buf;
#ifdef _WIN32
if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0)
#else
if (stat64(filename.c_str(), &buf) == 0)
#endif
{
DEBUG_LOG(COMMON, "GetSize: %s: %lld",
filename.c_str(), (long long)buf.st_size);
@ -391,13 +405,13 @@ bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
FILE *pFile = fopen(filename.c_str(), "wb");
if (!pFile) {
if (!File::IOFile(filename, "wb"))
{
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
fclose(pFile);
return true;
}
@ -413,7 +427,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
@ -423,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
do
{
FSTEntry entry;
const std::string virtualName(ffd.cFileName);
const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
@ -472,7 +486,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
return foundEntries;
}
// Deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory)
{
@ -480,18 +494,18 @@ bool DeleteDirRecursively(const std::string &directory)
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return false;
}
// windows loop
do
{
const std::string virtualName = ffd.cFileName;
const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory.c_str());
@ -518,7 +532,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
return false;
}
}
@ -529,7 +543,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
return false;
}
}
@ -591,7 +605,7 @@ std::string GetCurrentDir()
if (!(dir = __getcwd(NULL, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
GetLastErrorMsg());
GetLastErrorMsg());
return NULL;
}
std::string strDir = dir;
@ -622,14 +636,14 @@ std::string GetBundleDirectory()
#endif
#ifdef _WIN32
std::string &GetExeDirectory()
std::string& GetExeDirectory()
{
static std::string DolphinPath;
if (DolphinPath.empty())
{
char Dolphin_exe_Path[2048];
GetModuleFileNameA(NULL, Dolphin_exe_Path, 2048);
DolphinPath = Dolphin_exe_Path;
TCHAR Dolphin_exe_Path[2048];
GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
DolphinPath = TStrToUTF8(Dolphin_exe_Path);
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
}
return DolphinPath;
@ -668,9 +682,10 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
else
paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
paths[D_USER_IDX] = std::string(getenv("HOME") ?
getenv("HOME") : getenv("PWD") ?
getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
#endif
INFO_LOG(COMMON, "GetUserPath: Setting user directory to %s:", paths[D_USER_IDX].c_str());
paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR;
@ -731,31 +746,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f)) // TODO: string::data() may not be contiguous
{
fclose(f);
return false;
}
fclose(f);
return true;
return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
FILE *f = fopen(filename, text_file ? "r" : "rb");
File::IOFile file(filename, text_file ? "r" : "rb");
auto const f = file.GetHandle();
if (!f)
return false;
size_t len = (size_t)GetSize(f);
char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len);
fclose(f);
delete [] buf;
return true;
str.resize(GetSize(f));
return file.ReadArray(&str[0], str.size());
}
IOFile::IOFile()
@ -799,7 +802,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
{
Close();
#ifdef _WIN32
fopen_s(&m_file, filename.c_str(), openmode);
_tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str());
#else
m_file = fopen(filename.c_str(), openmode);
#endif
@ -848,7 +851,7 @@ bool IOFile::Seek(s64 off, int origin)
}
u64 IOFile::Tell()
{
{
if (IsOpen())
return ftello(m_file);
else

View File

@ -25,6 +25,7 @@
#include <string.h>
#include "Common.h"
#include "StringUtil.h"
// User directory indices for GetUserPath
enum {
@ -227,4 +228,15 @@ private:
} // namespace
// To deal with Windows being dumb at unicode:
template <typename T>
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
{
#ifdef _WIN32
fstream.open(UTF8ToTStr(filename).c_str(), openmode);
#else
fstream.open(filename.c_str(), openmode);
#endif
}
#endif

View File

@ -0,0 +1,41 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "FPURoundMode.h"
// Generic, do nothing
namespace FPURoundMode
{
void SetRoundMode(u32 mode)
{
}
void SetPrecisionMode(u32 mode)
{
}
void SetSIMDMode(u32 mode)
{
}
void SaveSIMDState()
{
}
void LoadSIMDState()
{
}
void LoadDefaultSIMDState()
{
}
}

View File

@ -119,7 +119,7 @@ u32 HashEctor(const u8* ptr, int length)
inline u64 getblock(const u64 * p, int i)
{
return p[i];
return p[i];
}
//----------
@ -127,25 +127,25 @@ inline u64 getblock(const u64 * p, int i)
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
{
k1 *= c1;
k1 = _rotl64(k1,23);
k1 *= c2;
h1 ^= k1;
h1 += h2;
k1 *= c1;
k1 = _rotl64(k1,23);
k1 *= c2;
h1 ^= k1;
h1 += h2;
h2 = _rotl64(h2,41);
h2 = _rotl64(h2,41);
k2 *= c2;
k2 = _rotl64(k2,23);
k2 *= c1;
h2 ^= k2;
h2 += h1;
k2 *= c2;
k2 = _rotl64(k2,23);
k2 *= c1;
h2 ^= k2;
h2 += h1;
h1 = h1*3+0x52dce729;
h2 = h2*3+0x38495ab5;
h1 = h1*3+0x52dce729;
h2 = h2*3+0x38495ab5;
c1 = c1*5+0x7b7d159c;
c2 = c2*5+0x6bce6396;
c1 = c1*5+0x7b7d159c;
c2 = c2*5+0x6bce6396;
}
//----------
@ -153,87 +153,87 @@ inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
inline u64 fmix64(u64 k)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
return k;
return k;
}
u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
{
const u8 * data = (const u8*)src;
const int nblocks = len / 16;
const u8 * data = (const u8*)src;
const int nblocks = len / 16;
u32 Step = (len / 8);
if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
u64 h1 = 0x9368e53c2f6af274;
u64 h2 = 0x586dcd208f7cd3fd;
u64 h1 = 0x9368e53c2f6af274;
u64 h2 = 0x586dcd208f7cd3fd;
u64 c1 = 0x87c37b91114253d5;
u64 c2 = 0x4cf5ad432745937f;
u64 c1 = 0x87c37b91114253d5;
u64 c2 = 0x4cf5ad432745937f;
//----------
// body
//----------
// body
const u64 * blocks = (const u64 *)(data);
const u64 * blocks = (const u64 *)(data);
for(int i = 0; i < nblocks; i+=Step)
{
u64 k1 = getblock(blocks,i*2+0);
u64 k2 = getblock(blocks,i*2+1);
for(int i = 0; i < nblocks; i+=Step)
{
u64 k1 = getblock(blocks,i*2+0);
u64 k2 = getblock(blocks,i*2+1);
bmix64(h1,h2,k1,k2,c1,c2);
}
bmix64(h1,h2,k1,k2,c1,c2);
}
//----------
// tail
//----------
// tail
const u8 * tail = (const u8*)(data + nblocks*16);
const u8 * tail = (const u8*)(data + nblocks*16);
u64 k1 = 0;
u64 k2 = 0;
u64 k1 = 0;
u64 k2 = 0;
switch(len & 15)
{
case 15: k2 ^= u64(tail[14]) << 48;
case 14: k2 ^= u64(tail[13]) << 40;
case 13: k2 ^= u64(tail[12]) << 32;
case 12: k2 ^= u64(tail[11]) << 24;
case 11: k2 ^= u64(tail[10]) << 16;
case 10: k2 ^= u64(tail[ 9]) << 8;
case 9: k2 ^= u64(tail[ 8]) << 0;
switch(len & 15)
{
case 15: k2 ^= u64(tail[14]) << 48;
case 14: k2 ^= u64(tail[13]) << 40;
case 13: k2 ^= u64(tail[12]) << 32;
case 12: k2 ^= u64(tail[11]) << 24;
case 11: k2 ^= u64(tail[10]) << 16;
case 10: k2 ^= u64(tail[ 9]) << 8;
case 9: k2 ^= u64(tail[ 8]) << 0;
case 8: k1 ^= u64(tail[ 7]) << 56;
case 7: k1 ^= u64(tail[ 6]) << 48;
case 6: k1 ^= u64(tail[ 5]) << 40;
case 5: k1 ^= u64(tail[ 4]) << 32;
case 4: k1 ^= u64(tail[ 3]) << 24;
case 3: k1 ^= u64(tail[ 2]) << 16;
case 2: k1 ^= u64(tail[ 1]) << 8;
case 1: k1 ^= u64(tail[ 0]) << 0;
bmix64(h1,h2,k1,k2,c1,c2);
};
case 8: k1 ^= u64(tail[ 7]) << 56;
case 7: k1 ^= u64(tail[ 6]) << 48;
case 6: k1 ^= u64(tail[ 5]) << 40;
case 5: k1 ^= u64(tail[ 4]) << 32;
case 4: k1 ^= u64(tail[ 3]) << 24;
case 3: k1 ^= u64(tail[ 2]) << 16;
case 2: k1 ^= u64(tail[ 1]) << 8;
case 1: k1 ^= u64(tail[ 0]) << 0;
bmix64(h1,h2,k1,k2,c1,c2);
};
//----------
// finalization
//----------
// finalization
h2 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h1 += h2;
return h1;
return h1;
}
@ -262,11 +262,13 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
}
/* NOTE: This hash function is used for custom texture loading/dumping, so
it should not be changed, which would require all custom textures to be
recalculated for their new hash values. If the hashing function is
changed, make sure this one is still used when the legacy parameter is
true. */
/*
* NOTE: This hash function is used for custom texture loading/dumping, so
* it should not be changed, which would require all custom textures to be
* recalculated for their new hash values. If the hashing function is
* changed, make sure this one is still used when the legacy parameter is
* true.
*/
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
@ -282,11 +284,11 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
u64 k = data[0];
data+=Step;
k *= m;
k *= m;
k ^= k >> r;
k *= m;
k *= m;
h ^= k;
h *= m;
h *= m;
}
const u8 * data2 = (const u8*)end;
@ -453,9 +455,11 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
return *((u64 *)&out);
}
/* FIXME: The old 32-bit version of this hash made different hashes than the
64-bit version. Until someone can make a new version of the 32-bit one that
makes identical hashes, this is just a c/p of the 64-bit one. */
/*
* FIXME: The old 32-bit version of this hash made different hashes than the
* 64-bit version. Until someone can make a new version of the 32-bit one that
* makes identical hashes, this is just a c/p of the 64-bit one.
*/
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
@ -473,7 +477,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
data+=Step;
k *= m;
k ^= k >> r;
k *= m;
k *= m;
h ^= k;
h *= m;
}
@ -502,7 +506,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u64 GetHash64(const u8 *src, int len, u32 samples)
{
return ptrHashFunction(src, len, samples);
return ptrHashFunction(src, len, samples);
}
// sets the hash function used for the texture cache

View File

@ -25,6 +25,7 @@
#include <fstream>
#include <algorithm>
#include "FileUtil.h"
#include "StringUtil.h"
#include "IniFile.h"
@ -400,7 +401,7 @@ bool IniFile::Load(const char* filename)
// Open file
std::ifstream in;
in.open(filename, std::ios::in);
OpenFStream(in, filename, std::ios::in);
if (in.fail()) return false;
@ -452,7 +453,7 @@ bool IniFile::Load(const char* filename)
bool IniFile::Save(const char* filename)
{
std::ofstream out;
out.open(filename, std::ios::out);
OpenFStream(out, filename, std::ios::out);
if (out.fail())
{

View File

@ -21,11 +21,8 @@
#include "Common.h"
#include <fstream>
// Increment this every time you change shader generation code.
enum
{
LINEAR_DISKCACHE_VER = 6979
};
// defined in Version.cpp
extern const char *scm_rev_git_str;
// On disk format:
//header{
@ -74,7 +71,7 @@ public:
m_num_entries = 0;
// try opening for reading/writing
m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary);
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
m_file.seekg(0, std::ios::end);
std::fstream::pos_type end_pos = m_file.tellg();
@ -187,13 +184,15 @@ private:
{
Header()
: id(*(u32*)"DCAC")
, ver(LINEAR_DISKCACHE_VER)
, key_t_size(sizeof(K))
, value_t_size(sizeof(V))
{}
{
memcpy(ver, scm_rev_git_str, 40);
}
const u32 id, ver;
const u32 id;
const u16 key_t_size, value_t_size;
char ver[40];
} m_header;

View File

@ -17,6 +17,9 @@
#include <algorithm>
#ifdef ANDROID
#include "Host.h"
#endif
#include "LogManager.h"
#include "ConsoleListener.h"
#include "Timer.h"
@ -42,9 +45,9 @@ LogManager::LogManager()
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
@ -61,15 +64,15 @@ LogManager::LogManager()
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
m_Log[LogTypes::POWERPC] = new LogContainer("PowerPC", "IBM CPU");
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
m_Log[LogTypes::WII_IOB] = new LogContainer("WII_IOB", "WII IO Bridge");
m_Log[LogTypes::WII_IPC] = new LogContainer("WII_IPC", "WII IPC");
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
@ -83,7 +86,7 @@ LogManager::LogManager()
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
@ -136,7 +139,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
Common::Timer::GetTimeFormatted().c_str(),
file, line, level_to_char[(int)level],
log->GetShortName(), temp);
#ifdef ANDROID
Host_SysMessage(msg);
#endif
log->Trigger(level, msg);
}
@ -185,7 +190,7 @@ void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
FileLogListener::FileLogListener(const char *filename)
{
m_logfile.open(filename, std::ios::app);
OpenFStream(m_logfile, filename, std::ios::app);
SetEnable(true);
}

View File

@ -26,7 +26,7 @@
#include <set>
#include <string.h>
#define MAX_MESSAGES 8000
#define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024

View File

@ -21,13 +21,6 @@
#include <cmath>
#include <numeric>
namespace {
static u32 saved_sse_state = _mm_getcsr();
static const u32 default_sse_state = _mm_getcsr();
}
namespace MathUtil
{
@ -95,7 +88,7 @@ u32 ClassifyFloat(float fvalue)
else
{
// Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
@ -108,43 +101,26 @@ u32 ClassifyFloat(float fvalue)
//Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
}
}
}
} // namespace
void LoadDefaultSSEState()
{
_mm_setcsr(default_sse_state);
}
void LoadSSEState()
{
_mm_setcsr(saved_sse_state);
}
void SaveSSEState()
{
saved_sse_state = _mm_getcsr();
}
inline void MatrixMul(int n, const float *a, const float *b, float *result)
{
for (int i = 0; i < n; ++i)
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
for (int j = 0; j < n; ++j)
{
float temp = 0;
for (int k = 0; k < n; ++k)
float temp = 0;
for (int k = 0; k < n; ++k)
{
temp += a[i * n + k] * b[k * n + j];
}
result[i * n + j] = temp;
}
}
temp += a[i * n + k] * b[k * n + j];
}
result[i * n + j] = temp;
}
}
}
// Calculate sum of a float list
@ -155,94 +131,94 @@ float MathFloatVectorSum(const std::vector<float>& Vec)
void Matrix33::LoadIdentity(Matrix33 &mtx)
{
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f;
mtx.data[4] = 1.0f;
mtx.data[8] = 1.0f;
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f;
mtx.data[4] = 1.0f;
mtx.data[8] = 1.0f;
}
void Matrix33::RotateX(Matrix33 &mtx, float rad)
{
float s = sin(rad);
float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1;
mtx.data[4] = c;
mtx.data[5] = -s;
mtx.data[7] = s;
mtx.data[8] = c;
float s = sin(rad);
float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1;
mtx.data[4] = c;
mtx.data[5] = -s;
mtx.data[7] = s;
mtx.data[8] = c;
}
void Matrix33::RotateY(Matrix33 &mtx, float rad)
{
float s = sin(rad);
float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = c;
mtx.data[2] = s;
mtx.data[4] = 1;
mtx.data[6] = -s;
mtx.data[8] = c;
float s = sin(rad);
float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = c;
mtx.data[2] = s;
mtx.data[4] = 1;
mtx.data[6] = -s;
mtx.data[8] = c;
}
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
{
MatrixMul(3, a.data, b.data, result.data);
MatrixMul(3, a.data, b.data, result.data);
}
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
{
for (int i = 0; i < 3; ++i) {
result[i] = 0;
for (int k = 0; k < 3; ++k) {
result[i] += a.data[i * 3 + k] * vec[k];
}
}
for (int i = 0; i < 3; ++i) {
result[i] = 0;
for (int k = 0; k < 3; ++k) {
result[i] += a.data[i * 3 + k] * vec[k];
}
}
}
void Matrix44::LoadIdentity(Matrix44 &mtx)
{
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f;
mtx.data[5] = 1.0f;
mtx.data[10] = 1.0f;
mtx.data[15] = 1.0f;
memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f;
mtx.data[5] = 1.0f;
mtx.data[10] = 1.0f;
mtx.data[15] = 1.0f;
}
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
{
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
for (int j = 0; j < 3; ++j)
{
mtx.data[i * 4 + j] = m33.data[i * 3 + j];
}
}
mtx.data[i * 4 + j] = m33.data[i * 3 + j];
}
}
for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i)
{
mtx.data[i * 4 + 3] = 0;
mtx.data[i + 12] = 0;
}
mtx.data[15] = 1.0f;
mtx.data[i * 4 + 3] = 0;
mtx.data[i + 12] = 0;
}
mtx.data[15] = 1.0f;
}
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
{
for(int i = 0; i < 16; ++i) {
mtx.data[i] = mtxArray[i];
}
for(int i = 0; i < 16; ++i) {
mtx.data[i] = mtxArray[i];
}
}
void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
{
LoadIdentity(mtx);
mtx.data[3] = vec[0];
mtx.data[7] = vec[1];
mtx.data[11] = vec[2];
LoadIdentity(mtx);
mtx.data[3] = vec[0];
mtx.data[7] = vec[1];
mtx.data[11] = vec[2];
}
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
{
MatrixMul(4, a.data, b.data, result.data);
MatrixMul(4, a.data, b.data, result.data);
}

View File

@ -20,8 +20,8 @@
#include "Common.h"
#include <xmmintrin.h>
#include <vector>
#include "FPURoundMode.h"
namespace MathUtil
{
@ -117,6 +117,8 @@ struct Rectangle
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
{ }
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
T GetWidth() const { return abs(right - left); }
T GetHeight() const { return abs(bottom - top); }
@ -147,22 +149,32 @@ struct Rectangle
inline float pow2f(float x) {return x * x;}
inline double pow2(double x) {return x * x;}
/*
There are two different flavors of float to int conversion:
_mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds
according to the MXCSR rounding bits. The second one always
uses round towards zero.
*/
void SaveSSEState();
void LoadSSEState();
void LoadDefaultSSEState();
float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
// Rounds down. 0 -> undefined
inline u64 Log2(u64 val)
{
#if defined(__GNUC__)
return 63 - __builtin_clzll(val);
#elif defined(_MSC_VER) && defined(_M_X64)
unsigned long result = -1;
_BitScanReverse64(&result, val);
return result;
#else
u64 result = -1;
while (val != 0)
{
val >>= 1;
++result;
}
return result;
#endif
}
// Tiny matrix/vector library.
// Used for things like Free-Look in the gfx backend.
@ -170,32 +182,32 @@ float MathFloatVectorSum(const std::vector<float>&);
class Matrix33
{
public:
static void LoadIdentity(Matrix33 &mtx);
static void LoadIdentity(Matrix33 &mtx);
// set mtx to be a rotation matrix around the x axis
static void RotateX(Matrix33 &mtx, float rad);
// set mtx to be a rotation matrix around the y axis
static void RotateY(Matrix33 &mtx, float rad);
// set mtx to be a rotation matrix around the x axis
static void RotateX(Matrix33 &mtx, float rad);
// set mtx to be a rotation matrix around the y axis
static void RotateY(Matrix33 &mtx, float rad);
// set result = a x b
static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
// set result = a x b
static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
float data[9];
float data[9];
};
class Matrix44
{
public:
static void LoadIdentity(Matrix44 &mtx);
static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
static void Set(Matrix44 &mtx, const float mtxArray[16]);
static void LoadIdentity(Matrix44 &mtx);
static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
static void Set(Matrix44 &mtx, const float mtxArray[16]);
static void Translate(Matrix44 &mtx, const float vec[3]);
static void Translate(Matrix44 &mtx, const float vec[3]);
static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
float data[16];
float data[16];
};
#endif // _MATH_UTIL_H_

View File

@ -27,6 +27,10 @@
#include <unistd.h>
#include <cerrno>
#include <cstring>
#ifdef ANDROID
#include <sys/ioctl.h>
#include <linux/ashmem.h>
#endif
#endif
#if defined(__APPLE__)
@ -34,11 +38,41 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp";
#elif !defined(_WIN32) // non OSX unixes
static const char* ram_temp_file = "/dev/shm/gc_mem.tmp";
#endif
#ifdef ANDROID
#define ASHMEM_DEVICE "/dev/ashmem"
int AshmemCreateFileMapping(const char *name, size_t size)
{
int fd, ret;
fd = open(ASHMEM_DEVICE, O_RDWR);
if (fd < 0)
return fd;
// We don't really care if we can't set the name, it is optional
ret = ioctl(fd, ASHMEM_SET_NAME, name);
ret = ioctl(fd, ASHMEM_SET_SIZE, size);
if (ret < 0)
{
close(fd);
NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret);
return ret;
}
return fd;
}
#endif
void MemArena::GrabLowMemSpace(size_t size)
{
#ifdef _WIN32
hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
#elif defined(ANDROID)
fd = AshmemCreateFileMapping("Dolphin-emu", size);
if (fd < 0)
{
NOTICE_LOG(MEMMAP, "Ashmem allocation failed");
return;
}
#else
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);

View File

@ -117,9 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
void* ptr = _aligned_malloc(size,alignment);
#else
void* ptr = NULL;
#ifdef ANDROID
ptr = memalign(alignment, size);
#else
if (posix_memalign(&ptr, alignment, size) != 0)
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
;
#endif
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
@ -152,9 +155,7 @@ void FreeAlignedMemory(void* ptr)
if (ptr)
{
#ifdef _WIN32
_aligned_free(ptr);
_aligned_free(ptr);
#else
free(ptr);
#endif

View File

@ -31,7 +31,7 @@ const char* GetLastErrorMsg()
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL);
#else

View File

@ -102,15 +102,14 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
printf("%s\n", text);
return true;
printf("%s\n", text);
return true;
#endif
}

View File

@ -86,7 +86,8 @@ bool CheckTitleTIK(u64 _titleID)
static void CreateReplacementFile(std::string &filename)
{
std::ofstream replace(filename.c_str());
std::ofstream replace;
OpenFStream(replace, filename, std::ios_base::out);
replace <<"\" __22__\n";
replace << "* __2a__\n";
//replace << "/ __2f__\n";
@ -108,7 +109,8 @@ void ReadReplacements(replace_v& replacements)
if (!File::Exists(filename))
CreateReplacementFile(filename);
std::ifstream f(filename.c_str());
std::ifstream f;
OpenFStream(f, filename, std::ios_base::in);
char letter;
std::string replacement;

View File

@ -29,6 +29,7 @@
// Modified for Dolphin.
#include "SDCardUtil.h"
#include "FileUtil.h"
#include <time.h>
#include <stdio.h>
@ -190,7 +191,6 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
{
u32 sectors_per_fat;
u32 sectors_per_disk;
FILE* f;
// Convert MB to bytes
disk_size *= 1024 * 1024;
@ -207,7 +207,8 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr);
fat_init(s_fat_head);
f = fopen(filename, "wb");
File::IOFile file(filename, "wb");
FILE* const f = file.GetHandle();
if (!f)
{
ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename);
@ -247,13 +248,11 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat)) goto FailWrite;
fclose(f);
return true;
FailWrite:
ERROR_LOG(COMMON, "Could not write to '%s', aborting...\n", filename);
if (unlink(filename) < 0)
ERROR_LOG(COMMON, "unlink(%s) failed\n%s", filename, GetLastErrorMsg());
fclose(f);
return false;
}

View File

@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <condition_variable>
#include <condition_variable>
#else
@ -133,7 +133,7 @@ public:
// bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time,
// Predicate pred);
native_handle_type native_handle()
{
#ifdef USE_EVENTS

View File

@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <mutex>
#include <mutex>
#else

View File

@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
@ -88,7 +88,7 @@ public:
{
return !(*this == rhs);
}
bool operator<(const id& rhs) const
{
return m_thread < rhs.m_thread;

View File

@ -17,11 +17,21 @@
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include "Common.h"
#include "CommonPaths.h"
#include "StringUtil.h"
#ifdef _WIN32
#include <Windows.h>
#elif defined(ANDROID)
#else
#include <iconv.h>
#include <errno.h>
#endif
// faster than sscanf
bool AsciiToHex(const char* _szValue, u32& result)
{
@ -263,25 +273,25 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
const char HEX2DEC[256] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
/* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
/* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
/* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
/* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
/* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
/* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
};
std::string UriDecode(const std::string & sSrc)
@ -303,8 +313,8 @@ std::string UriDecode(const std::string & sSrc)
if (*pSrc == '%')
{
char dec1, dec2;
if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
&& -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
&& 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
@ -375,3 +385,137 @@ std::string UriEncode(const std::string & sSrc)
delete [] pStart;
return sResult;
}
#ifdef _WIN32
std::string UTF16ToUTF8(const std::wstring& input)
{
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
std::string output;
output.resize(size);
if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
output.clear();
return output;
}
std::wstring CPToUTF16(u32 code_page, const std::string& input)
{
auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
std::wstring output;
output.resize(size);
if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
output.clear();
return output;
}
std::wstring UTF8ToUTF16(const std::string& input)
{
return CPToUTF16(CP_UTF8, input);
}
std::string SHIFTJISToUTF8(const std::string& input)
{
return UTF16ToUTF8(CPToUTF16(932, input));
}
std::string CP1252ToUTF8(const std::string& input)
{
return UTF16ToUTF8(CPToUTF16(1252, input));
}
#else
template <typename T>
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
{
std::string result;
#if defined(ANDROID)
result = "Not implemented on Android!";
#else
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)-1 == conv_desc)
{
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
}
else
{
size_t const in_bytes = sizeof(T) * input.size();
size_t const out_buffer_size = 4 * in_bytes;
std::string out_buffer;
out_buffer.resize(out_buffer_size);
auto src_buffer = &input[0];
size_t src_bytes = in_bytes;
auto dst_buffer = &out_buffer[0];
size_t dst_bytes = out_buffer.size();
while (src_bytes != 0)
{
size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
&dst_buffer, &dst_bytes);
if ((size_t)-1 == iconv_result)
{
if (EILSEQ == errno || EINVAL == errno)
{
// Try to skip the bad character
if (src_bytes != 0)
{
--src_bytes;
++src_buffer;
}
}
else
{
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
break;
}
}
}
out_buffer.resize(out_buffer_size - dst_bytes);
out_buffer.swap(result);
iconv_close(conv_desc);
}
#endif
return result;
}
std::string CP1252ToUTF8(const std::string& input)
{
//return CodeToUTF8("CP1252//TRANSLIT", input);
//return CodeToUTF8("CP1252//IGNORE", input);
return CodeToUTF8("CP1252", input);
}
std::string SHIFTJISToUTF8(const std::string& input)
{
//return CodeToUTF8("CP932", input);
return CodeToUTF8("SJIS", input);
}
std::string UTF16ToUTF8(const std::wstring& input)
{
std::string result =
// CodeToUTF8("UCS-2", input);
// CodeToUTF8("UCS-2LE", input);
// CodeToUTF8("UTF-16", input);
CodeToUTF8("UTF-16LE", input);
// TODO: why is this needed?
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
return result;
}
#endif

View File

@ -97,4 +97,28 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc);
std::string CP1252ToUTF8(const std::string& str);
std::string SHIFTJISToUTF8(const std::string& str);
std::string UTF16ToUTF8(const std::wstring& str);
#ifdef _WIN32
std::wstring UTF8ToUTF16(const std::string& str);
#ifdef _UNICODE
inline std::string TStrToUTF8(const std::wstring& str)
{ return UTF16ToUTF8(str); }
inline std::wstring UTF8ToTStr(const std::string& str)
{ return UTF8ToUTF16(str); }
#else
inline std::string TStrToUTF8(const std::string& str)
{ return str; }
inline std::string UTF8ToTStr(const std::string& str)
{ return str; }
#endif
#endif
#endif // _STRINGUTIL_H_

View File

@ -105,7 +105,7 @@ void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
#ifdef __APPLE__
thread_policy_set(pthread_mach_thread_np(thread),
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
#elif defined __linux__ || defined BSD4_4
#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);

View File

@ -33,8 +33,6 @@
#define INFINITE 0xffffffff
#endif
#include <xmmintrin.h>
//for gettimeofday and struct time(spec|val)
#include <time.h>
#include <sys/time.h>
@ -64,7 +62,7 @@ public:
m_condvar.notify_one();
}
}
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);

View File

@ -50,3 +50,5 @@ const char *netplay_dolphin_ver = SCM_DESC_STR " M" NP_ARCH;
#else
const char *netplay_dolphin_ver = SCM_DESC_STR " L" NP_ARCH;
#endif
const char *scm_rev_git_str = SCM_REV_STR;

View File

@ -29,6 +29,7 @@
std::vector<VideoBackend*> g_available_video_backends;
VideoBackend* g_video_backend = NULL;
static VideoBackend* s_default_backend = NULL;
#ifdef _WIN32
// http://msdn.microsoft.com/en-us/library/ms725491.aspx
@ -49,17 +50,27 @@ static bool IsGteVista()
void VideoBackend::PopulateList()
{
VideoBackend* backends[4] = { NULL };
// D3D11 > OGL > D3D9 > SW
#ifdef _WIN32
g_available_video_backends.push_back(new DX9::VideoBackend);
g_available_video_backends.push_back(backends[2] = new DX9::VideoBackend);
if (IsGteVista())
g_available_video_backends.push_back(new DX11::VideoBackend);
g_available_video_backends.push_back(backends[0] = new DX11::VideoBackend);
#endif
#ifndef USE_GLES
g_available_video_backends.push_back(new OGL::VideoBackend);
g_available_video_backends.push_back(backends[1] = new OGL::VideoBackend);
#endif
g_available_video_backends.push_back(new SW::VideoSoftware);
g_available_video_backends.push_back(backends[3] = new SW::VideoSoftware);
g_video_backend = g_available_video_backends.front();
for (int i = 0; i < 4; ++i)
{
if (backends[i])
{
s_default_backend = g_video_backend = backends[i];
break;
}
}
}
void VideoBackend::ClearList()
@ -73,8 +84,8 @@ void VideoBackend::ClearList()
void VideoBackend::ActivateBackend(const std::string& name)
{
if (name.length() == 0) // If NULL, set it to the first one in the list. Expected behavior
g_video_backend = g_available_video_backends.front();
if (name.length() == 0) // If NULL, set it to the default backend (expected behavior)
g_video_backend = s_default_backend;
for (std::vector<VideoBackend*>::const_iterator it = g_available_video_backends.begin(); it != g_available_video_backends.end(); ++it)
if (name == (*it)->GetName())

View File

@ -22,6 +22,7 @@
#include <vector>
#include "ChunkFile.h"
#include "../../VideoCommon/Src/PerfQueryBase.h"
typedef void (*writeFn16)(const u16,const u32);
typedef void (*writeFn32)(const u32,const u32);
@ -96,17 +97,20 @@ public:
virtual void RunLoop(bool enable) = 0;
virtual std::string GetName() = 0;
virtual std::string GetDisplayName() { return GetName(); }
virtual void ShowConfig(void*) {}
virtual void Video_Prepare() = 0;
virtual void Video_EnterLoop() = 0;
virtual void Video_ExitLoop() = 0;
virtual void Video_Cleanup() = 0; // called from gl/d3d thread
virtual void Video_BeginField(u32, FieldType, u32, u32) = 0;
virtual void Video_EndField() = 0;
virtual u32 Video_AccessEFB(EFBAccessType, u32, u32, u32) = 0;
virtual u32 Video_GetQueryResult(PerfQueryType type) = 0;
virtual void Video_AddMessage(const char* pstr, unsigned int milliseconds) = 0;
virtual void Video_ClearMessages() = 0;
@ -156,8 +160,10 @@ class VideoBackendHardware : public VideoBackend
void Video_ExitLoop();
void Video_BeginField(u32, FieldType, u32, u32);
void Video_EndField();
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
u32 Video_GetQueryResult(PerfQueryType type);
void Video_AddMessage(const char* pstr, unsigned int milliseconds);
void Video_ClearMessages();
bool Video_Screenshot(const char* filename);

View File

@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "x64ABI.h"
using namespace Gen;
@ -226,11 +226,11 @@ void XEmitter::ABI_CallFunction(void *func) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -239,11 +239,11 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -266,11 +266,11 @@ void XEmitter::ABI_CallFunctionC(void *func, u32 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -280,11 +280,11 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -295,11 +295,11 @@ void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -310,11 +310,11 @@ void XEmitter::ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *par
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -326,11 +326,11 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 para
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -341,11 +341,11 @@ void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 p
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -356,11 +356,11 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -380,11 +380,11 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -396,11 +396,11 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}
@ -411,11 +411,11 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
CALL(func);
}
}

View File

@ -60,18 +60,18 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
codeByte = *codePtr++;
// Skip two-byte opcode byte
bool twoByte = false;
if(codeByte == 0x0F)
{
twoByte = true;
// Skip two-byte opcode byte
bool twoByte = false;
if(codeByte == 0x0F)
{
twoByte = true;
codeByte2 = *codePtr++;
}
}
if (!twoByte)
{
if ((codeByte & 0xF0) == 0x80 ||
((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
if ((codeByte & 0xF0) == 0x80 ||
((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
{
modRMbyte = *codePtr++;
hasModRM = true;
@ -79,20 +79,20 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
}
else
{
if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
(codeByte2 & 0xF0) == 0x30 ||
codeByte2 == 0x77 ||
(codeByte2 & 0xF0) == 0x80 ||
((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
(codeByte2 & 0xF8) == 0xC8)
{
// No mod R/M byte
}
else
{
if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
(codeByte2 & 0xF0) == 0x30 ||
codeByte2 == 0x77 ||
(codeByte2 & 0xF0) == 0x80 ||
((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
(codeByte2 & 0xF8) == 0xC8)
{
// No mod R/M byte
}
else
{
modRMbyte = *codePtr++;
hasModRM = true;
}
}
}
if (hasModRM)
@ -130,7 +130,7 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
info.displacement = *((s32 *)codePtr);
codePtr += displacementSize;
if (accessType == 1)
{
info.isMemoryWrite = true;

View File

@ -51,7 +51,7 @@ enum{
MOVZX_SHORT = 0xB7, //movzx on short
MOVSX_BYTE = 0xBE, //movsx on byte
MOVSX_SHORT = 0xBF, //movsx on short
MOVE_8BIT = 0xC6, //move 8-bit immediate
MOVE_8BIT = 0xC6, //move 8-bit immediate
MOVE_16_32BIT = 0xC7, //move 16 or 32-bit immediate
MOVE_REG_TO_MEM = 0x89, //move reg to memory
};

View File

@ -30,16 +30,20 @@
#else
//#include <config/i386/cpuid.h>
#ifndef _M_GENERIC
#include <xmmintrin.h>
#endif
#if defined __FreeBSD__
#include <sys/types.h>
#include <machine/cpufunc.h>
#else
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
unsigned int *ecx, unsigned int *edx)
{
#ifdef _LP64
#if defined _M_GENERIC
(*eax) = (*ebx) = (*ecx) = (*edx) = 0;
#elif defined _LP64
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to
// restored at the end of the asm block.
__asm__ (

View File

@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "x64ABI.h"
#include "CPUDetect.h"
namespace Gen
@ -51,13 +51,13 @@ static const NormalOpDef nops[11] =
enum NormalSSEOps
{
sseCMP = 0xC2,
sseADD = 0x58, //ADD
sseCMP = 0xC2,
sseADD = 0x58, //ADD
sseSUB = 0x5C, //SUB
sseAND = 0x54, //AND
sseANDN = 0x55, //ANDN
sseOR = 0x56,
sseXOR = 0x57,
sseOR = 0x56,
sseXOR = 0x57,
sseMUL = 0x59, //MUL,
sseDIV = 0x5E, //DIV
sseMIN = 0x5D, //MIN
@ -143,18 +143,18 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const
if (indexReg & 8) op |= 2;
if (offsetOrBaseReg & 8) op |= 1; //TODO investigate if this is dangerous
if (op != 0x40 ||
(bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
(opBits == 8 && (customOp & 0x10c) == 4)) {
(bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
(opBits == 8 && (customOp & 0x10c) == 4)) {
emit->Write8(op);
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x100) == 0 || bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x100) == 0 || opBits != 8);
} else {
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x10c) == 0 ||
(offsetOrBaseReg & 0x10c) == 0x104 ||
bits != 8);
(offsetOrBaseReg & 0x10c) == 0x104 ||
bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x10c) == 0 ||
(customOp & 0x10c) == 0x104 ||
opBits != 8);
(customOp & 0x10c) == 0x104 ||
opBits != 8);
}
#else
@ -969,15 +969,15 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
immToWrite = 8;
}
else if ((operand.scale == SCALE_IMM16 && bits == 16) ||
(operand.scale == SCALE_IMM32 && bits == 32) ||
(operand.scale == SCALE_IMM32 && bits == 64))
(operand.scale == SCALE_IMM32 && bits == 32) ||
(operand.scale == SCALE_IMM32 && bits == 64))
{
emit->Write8(nops[op].imm32);
immToWrite = bits == 16 ? 16 : 32;
}
else if ((operand.scale == SCALE_IMM8 && bits == 16) ||
(operand.scale == SCALE_IMM8 && bits == 32) ||
(operand.scale == SCALE_IMM8 && bits == 64))
(operand.scale == SCALE_IMM8 && bits == 32) ||
(operand.scale == SCALE_IMM8 && bits == 64))
{
emit->Write8(nops[op].simm8);
immToWrite = 8;
@ -1471,142 +1471,142 @@ void XEmitter::RTDSC() { Write8(0x0F); Write8(0x31); }
// helper routines for setting pointers
void XEmitter::CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
{
using namespace Gen;
using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
CALL(fnptr);
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
CALL(fnptr);
#else
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
CALL(fnptr);
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
CALL(fnptr);
#endif
#else
ABI_AlignStack(3 * 4);
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
ABI_AlignStack(3 * 4);
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
#ifdef _WIN32
// don't inc stack
// don't inc stack
#else
ABI_RestoreStack(3 * 4);
ABI_RestoreStack(3 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3)
{
using namespace Gen;
using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
CALL(fnptr);
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
CALL(fnptr);
#else
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
CALL(fnptr);
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
CALL(fnptr);
#endif
#else
ABI_AlignStack(4 * 4);
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
ABI_AlignStack(4 * 4);
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
#ifdef _WIN32
// don't inc stack
// don't inc stack
#else
ABI_RestoreStack(4 * 4);
ABI_RestoreStack(4 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
using namespace Gen;
using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
CALL(fnptr);
CALL(fnptr);
#else
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
MOV(32, R(R8), Imm32(arg4));
CALL(fnptr);
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
MOV(32, R(R8), Imm32(arg4));
CALL(fnptr);
#endif
#else
ABI_AlignStack(5 * 4);
PUSH(32, Imm32(arg4));
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
ABI_AlignStack(5 * 4);
PUSH(32, Imm32(arg4));
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
#ifdef _WIN32
// don't inc stack
// don't inc stack
#else
ABI_RestoreStack(5 * 4);
ABI_RestoreStack(5 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
{
using namespace Gen;
using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
CALL(fnptr);
CALL(fnptr);
#else
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
MOV(32, R(R8), Imm32(arg4));
MOV(32, R(R9), Imm32(arg5));
CALL(fnptr);
MOV(32, R(RDI), Imm32(arg0));
MOV(32, R(RSI), Imm32(arg1));
MOV(32, R(RDX), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg3));
MOV(32, R(R8), Imm32(arg4));
MOV(32, R(R9), Imm32(arg5));
CALL(fnptr);
#endif
#else
ABI_AlignStack(6 * 4);
PUSH(32, Imm32(arg5));
PUSH(32, Imm32(arg4));
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
ABI_AlignStack(6 * 4);
PUSH(32, Imm32(arg5));
PUSH(32, Imm32(arg4));
PUSH(32, Imm32(arg3));
PUSH(32, Imm32(arg2));
PUSH(32, Imm32(arg1));
PUSH(32, Imm32(arg0));
CALL(fnptr);
#ifdef _WIN32
// don't inc stack
// don't inc stack
#else
ABI_RestoreStack(6 * 4);
ABI_RestoreStack(6 * 4);
#endif
#endif
}
@ -1615,31 +1615,31 @@ void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32
// See header
void XEmitter::___CallCdeclImport3(void* impptr, u32 arg0, u32 arg1, u32 arg2) {
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport4(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3) {
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport5(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) {
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport6(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5) {
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, R(RCX), Imm32(arg0));
MOV(32, R(RDX), Imm32(arg1));
MOV(32, R(R8), Imm32(arg2));
MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
CALLptr(M(impptr));

View File

@ -757,7 +757,7 @@ public:
region_size = 0;
}
bool IsInCodeSpace(u8 *ptr)
bool IsInSpace(u8 *ptr)
{
return ptr >= region && ptr < region + region_size;
}
@ -766,7 +766,7 @@ public:
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect()
{
WriteProtectMemory(region, region_size, true);
WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr()

View File

@ -0,0 +1,120 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FPURoundMode.h"
#ifndef _WIN32
static const unsigned short FPU_ROUND_NEAR = 0 << 10;
static const unsigned short FPU_ROUND_DOWN = 1 << 10;
static const unsigned short FPU_ROUND_UP = 2 << 10;
static const unsigned short FPU_ROUND_CHOP = 3 << 10;
static const unsigned short FPU_ROUND_MASK = 3 << 10;
#include <xmmintrin.h>
#endif
const u32 MASKS = 0x1F80; // mask away the interrupts.
const u32 DAZ = 0x40;
const u32 FTZ = 0x8000;
namespace FPURoundMode
{
// Get the default SSE states here.
static u32 saved_sse_state = _mm_getcsr();
static const u32 default_sse_state = _mm_getcsr();
void SetRoundMode(u32 mode)
{
// Set FPU rounding mode to mimic the PowerPC's
#ifdef _M_IX86
// This shouldn't really be needed anymore since we use SSE
#ifdef _WIN32
const int table[4] =
{
_RC_NEAR,
_RC_CHOP,
_RC_UP,
_RC_DOWN
};
_set_controlfp(_MCW_RC, table[mode]);
#else
const unsigned short table[4] =
{
FPU_ROUND_NEAR,
FPU_ROUND_CHOP,
FPU_ROUND_UP,
FPU_ROUND_DOWN
};
unsigned short _mode;
asm ("fstcw %0" : "=m" (_mode) : );
_mode = (_mode & ~FPU_ROUND_MASK) | table[mode];
asm ("fldcw %0" : : "m" (_mode));
#endif
#endif
}
void SetPrecisionMode(u32 mode)
{
#ifdef _M_IX86
// sets the floating-point lib to 53-bit
// PowerPC has a 53bit floating pipeline only
// eg: sscanf is very sensitive
#ifdef _WIN32
_control87(_PC_53, MCW_PC);
#else
const unsigned short table[4] = {
0 << 8, // FPU_PREC_24
2 << 8, // FPU_PREC_53
3 << 8, // FPU_PREC_64
3 << 8, // FPU_PREC_MASK
};
unsigned short _mode;
asm ("fstcw %0" : : "m" (_mode));
_mode = (_mode & ~table[3]) | table[mode];
asm ("fldcw %0" : : "m" (_mode));
#endif
#else
//x64 doesn't need this - fpu is done with SSE
//but still - set any useful sse options here
#endif
}
void SetSIMDMode(u32 mode)
{
static const u32 ssetable[4] =
{
(0 << 13) | MASKS,
(3 << 13) | MASKS,
(2 << 13) | MASKS,
(1 << 13) | MASKS,
};
u32 csr = ssetable[mode];
_mm_setcsr(csr);
}
void SaveSIMDState()
{
saved_sse_state = _mm_getcsr();
}
void LoadSIMDState()
{
_mm_setcsr(saved_sse_state);
}
void LoadDefaultSIMDState()
{
_mm_setcsr(default_sse_state);
}
}

View File

@ -18,9 +18,8 @@
#include <map>
#include "Common.h"
#include "x64Emitter.h"
#include "MemoryUtil.h"
#include "ABI.h"
#include "x64ABI.h"
#include "Thunk.h"
#define THUNK_ARENA_SIZE 1024*1024*1