Merge branch 'master' into perfqueries.
Conflicts: Source/Core/VideoCommon/Src/VideoConfig.h Source/Core/VideoCommon/VideoCommon.vcxproj.filters Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
This commit is contained in:
commit
7682ed22c6
886 files changed
+69167
-56567
No files matched your search
@@ -0,0 +1,160 @@
|
||||
// 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"
|
||||
|
||||
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 *fp;
|
||||
|
||||
fp = fopen(procfile, "r");
|
||||
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 *fp;
|
||||
|
||||
fp = fopen(procfile, "r");
|
||||
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 *fp;
|
||||
|
||||
fp = fopen(procfile, "r");
|
||||
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");
|
||||
// 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
@@ -0,0 +1,589 @@
|
||||
// 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
|
||||
|
||||
#undef _IP
|
||||
#undef R0
|
||||
#undef _SP
|
||||
#undef _LR
|
||||
#undef _PC
|
||||
|
||||
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(u8 shift, ShiftType type, ARMReg base)// 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;
|
||||
}
|
||||
const 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;
|
||||
}
|
||||
}
|
||||
const 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);
|
||||
}
|
||||
const 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;
|
||||
}
|
||||
const u32 Rm()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
|
||||
return Value;
|
||||
}
|
||||
|
||||
const u32 Imm5()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
|
||||
return ((Value & 0x0000001F) << 7);
|
||||
}
|
||||
const u32 Imm8()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
|
||||
return Value & 0xFF;
|
||||
}
|
||||
const 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);
|
||||
}
|
||||
const u32 Imm12()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
|
||||
return (Value & 0x00000FFF);
|
||||
}
|
||||
|
||||
const 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);
|
||||
}
|
||||
const u32 Imm16()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||
return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
|
||||
}
|
||||
const u32 Imm16Low()
|
||||
{
|
||||
return Imm16();
|
||||
}
|
||||
const u32 Imm16High() // Returns high 16bits
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||
return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
|
||||
}
|
||||
const u32 Imm24()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||
return (Value & 0x0FFFFFFF);
|
||||
}
|
||||
// NEON and ASIMD specific
|
||||
const u32 Imm8ASIMD()
|
||||
{
|
||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
|
||||
return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
|
||||
}
|
||||
const 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
|
||||
};
|
||||
|
||||
typedef const u8* JumpTarget;
|
||||
|
||||
class ARMXEmitter
|
||||
{
|
||||
friend struct OpArg; // for Write8 etc
|
||||
private:
|
||||
u8 *code, *startcode;
|
||||
u8 *lastCacheFlushEnd;
|
||||
u32 condition;
|
||||
|
||||
void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2);
|
||||
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);
|
||||
|
||||
|
||||
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 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 SBC (ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
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 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);
|
||||
// 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 src, Operand2 op2 = 0);
|
||||
// Offset adds to the base register in LDR
|
||||
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0);
|
||||
void LDRB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
void STR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
// Offset adds on to the destination register in STR
|
||||
void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
|
||||
void STRB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
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);
|
||||
// dest contains the result if the instruction managed to store the value
|
||||
void STREX(ARMReg dest, 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, u16 offset);
|
||||
void VSTR(ARMReg Src, ARMReg Base, u16 offset);
|
||||
void VCMP(ARMReg Vd, ARMReg Vm);
|
||||
// Compares against zero
|
||||
void VCMP(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 VMOV(ARMReg Dest, ARMReg Src, bool high);
|
||||
void VMOV(ARMReg Dest, ARMReg Src);
|
||||
|
||||
void QuickCallFunction(ARMReg scratchreg, void *func);
|
||||
// Utility functions
|
||||
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
|
||||
void ARMABI_MOVI2M(Operand2 op, Operand2 val);
|
||||
}; // 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()
|
||||
{
|
||||
FreeMemoryPages(region, region_size);
|
||||
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_
|
||||
@@ -19,7 +19,9 @@
|
||||
#include "DebugInterface.h"
|
||||
#include "BreakPoints.h"
|
||||
#include "../../Core/Src/PowerPC/JitCommon/JitBase.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
||||
{
|
||||
@@ -110,12 +112,17 @@ void BreakPoints::Remove(u32 em_address)
|
||||
|
||||
void BreakPoints::Clear()
|
||||
{
|
||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||
if (jit)
|
||||
{
|
||||
if (jit)
|
||||
jit->GetBlockCache()->InvalidateICache(i->iAddress, 4);
|
||||
m_BreakPoints.erase(i);
|
||||
std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
|
||||
[](const TBreakPoint& bp)
|
||||
{
|
||||
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
m_BreakPoints.clear();
|
||||
}
|
||||
|
||||
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CDUtils.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include <memory> // for std::unique_ptr
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif __APPLE__
|
||||
|
||||
@@ -25,7 +25,8 @@ enum CPUVendor
|
||||
{
|
||||
VENDOR_INTEL = 0,
|
||||
VENDOR_AMD = 1,
|
||||
VENDOR_OTHER = 2,
|
||||
VENDOR_ARM = 2,
|
||||
VENDOR_OTHER = 3,
|
||||
};
|
||||
|
||||
struct CPUInfo
|
||||
@@ -55,6 +56,26 @@ struct CPUInfo
|
||||
bool bAES;
|
||||
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();
|
||||
|
||||
@@ -155,10 +155,10 @@ public:
|
||||
Do(stringLen);
|
||||
|
||||
switch (mode) {
|
||||
case MODE_READ: x = (wchar_t*)*ptr; break;
|
||||
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: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); 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;
|
||||
}
|
||||
|
||||
@@ -60,11 +60,6 @@ private:
|
||||
#undef STACKALIGN
|
||||
#define STACKALIGN __attribute__((__force_align_arg_pointer__))
|
||||
#endif
|
||||
// We use wxWidgets on OS X only if it is version 2.9+ with Cocoa support.
|
||||
#ifdef __WXOSX_COCOA__
|
||||
#define HAVE_WX 1
|
||||
#define USE_WX 1 // Use wxGLCanvas
|
||||
#endif
|
||||
|
||||
#elif defined _WIN32
|
||||
|
||||
@@ -86,8 +81,9 @@ private:
|
||||
#define GC_ALIGNED16_DECL(x) __declspec(align(16)) x
|
||||
#define GC_ALIGNED64_DECL(x) __declspec(align(64)) x
|
||||
|
||||
// Since it is always around on windows
|
||||
// Since they are always around on windows
|
||||
#define HAVE_WX 1
|
||||
#define HAVE_OPENAL 1
|
||||
|
||||
#define HAVE_PORTAUDIO 1
|
||||
|
||||
@@ -137,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__
|
||||
@@ -148,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.
|
||||
@@ -159,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
|
||||
|
||||
@@ -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,6 +60,8 @@ _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
|
||||
@@ -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);}
|
||||
@@ -161,7 +172,6 @@ inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 3
|
||||
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);}
|
||||
|
||||
} // Namespace Common
|
||||
|
||||
#endif // _COMMONFUNCS_H_
|
||||
@@ -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"
|
||||
@@ -89,11 +94,11 @@
|
||||
#define MAIL_LOGS_DIR LOGS_DIR DIR_SEP "Mail"
|
||||
#define SHADERS_DIR "Shaders"
|
||||
#define WII_SYSCONF_DIR "shared2" DIR_SEP "sys"
|
||||
#define THEMES_DIR "Themes"
|
||||
|
||||
// Filenames
|
||||
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
||||
#define DOLPHIN_CONFIG "Dolphin.ini"
|
||||
#define DSP_CONFIG "DSP.ini"
|
||||
#define DEBUGGER_CONFIG "Debugger.ini"
|
||||
#define LOGGER_CONFIG "Logger.ini"
|
||||
|
||||
@@ -128,6 +133,7 @@
|
||||
#define WII_EUR_SETTING "setting-eur.txt"
|
||||
#define WII_USA_SETTING "setting-usa.txt"
|
||||
#define WII_JAP_SETTING "setting-jpn.txt"
|
||||
#define WII_KOR_SETTING "setting-kor.txt"
|
||||
|
||||
#define GECKO_CODE_HANDLER "codehandler.bin"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
virtual void step() {}
|
||||
virtual void runToBreakpoint() {}
|
||||
virtual void breakNow() {}
|
||||
virtual void insertBLR(unsigned int /*address*/, unsigned int) {}
|
||||
virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {}
|
||||
virtual void showJitResults(unsigned int /*address*/) {};
|
||||
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
|
||||
virtual std::string getDescription(unsigned int /*address*/) = 0;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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
|
||||
@@ -25,6 +25,7 @@
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "FileSearch.h"
|
||||
|
||||
@@ -72,36 +73,36 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
|
||||
|
||||
|
||||
#else
|
||||
size_t dot_pos = _searchString.rfind(".");
|
||||
// TODO: super lame/broken
|
||||
|
||||
if (dot_pos == std::string::npos)
|
||||
return;
|
||||
auto end_match(_searchString);
|
||||
|
||||
// assuming we have a "*.blah"-like pattern
|
||||
if (!end_match.empty() && end_match[0] == '*')
|
||||
end_match.erase(0, 1);
|
||||
|
||||
// ugly
|
||||
if (end_match == ".*")
|
||||
end_match.clear();
|
||||
|
||||
std::string ext = _searchString.substr(dot_pos);
|
||||
DIR* dir = opendir(_strPath.c_str());
|
||||
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
dirent* dp;
|
||||
|
||||
while (true)
|
||||
while (auto const dp = readdir(dir))
|
||||
{
|
||||
dp = readdir(dir);
|
||||
std::string found(dp->d_name);
|
||||
|
||||
if (!dp)
|
||||
break;
|
||||
|
||||
std::string s(dp->d_name);
|
||||
|
||||
if ( (!ext.compare(".*") && s.compare(".") && s.compare("..")) ||
|
||||
((s.size() > ext.size()) && (!strcasecmp(s.substr(s.size() - ext.size()).c_str(), ext.c_str())) ))
|
||||
if ((found != ".") && (found != "..")
|
||||
&& (found.size() >= end_match.size())
|
||||
&& std::equal(end_match.rbegin(), end_match.rend(), found.rbegin()))
|
||||
{
|
||||
std::string full_name;
|
||||
if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR)
|
||||
full_name = _strPath + s;
|
||||
full_name = _strPath + found;
|
||||
else
|
||||
full_name = _strPath + DIR_SEP + s;
|
||||
full_name = _strPath + DIR_SEP + found;
|
||||
|
||||
m_FileNames.push_back(full_name);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef S_ISDIR
|
||||
@@ -196,8 +197,9 @@ bool CreateFullPath(const std::string &fullPath)
|
||||
// we're done, yay!
|
||||
if (position == fullPath.npos)
|
||||
return true;
|
||||
|
||||
std::string subPath = fullPath.substr(0, position);
|
||||
|
||||
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
|
||||
std::string const subPath(fullPath.substr(0, position + 1));
|
||||
if (!File::IsDirectory(subPath))
|
||||
File::CreateDir(subPath);
|
||||
|
||||
@@ -299,7 +301,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
|
||||
ERROR_LOG(COMMON,
|
||||
"Copy: failed reading from source, %s --> %s: %s",
|
||||
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
|
||||
return false;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,13 +312,19 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
|
||||
ERROR_LOG(COMMON,
|
||||
"Copy: failed writing to output, %s --> %s: %s",
|
||||
srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg());
|
||||
return false;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
// close flushs
|
||||
fclose(input);
|
||||
fclose(output);
|
||||
return true;
|
||||
bail:
|
||||
if (input)
|
||||
fclose(input);
|
||||
if (output)
|
||||
fclose(output);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -506,12 +514,24 @@ bool DeleteDirRecursively(const std::string &directory)
|
||||
if (IsDirectory(newPath))
|
||||
{
|
||||
if (!DeleteDirRecursively(newPath))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
closedir(dirp);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File::Delete(newPath))
|
||||
{
|
||||
#ifndef _WIN32
|
||||
closedir(dirp);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -643,15 +663,15 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
|
||||
if (paths[D_USER_IDX].empty())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// TODO: use GetExeDirectory() here instead of ROOT_DIR so that if the cwd is changed we still have the correct paths?
|
||||
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
|
||||
paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
|
||||
#else
|
||||
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")) + 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;
|
||||
@@ -673,9 +693,9 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
|
||||
paths[D_DUMPDSP_IDX] = paths[D_USER_IDX] + DUMP_DSP_DIR DIR_SEP;
|
||||
paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
|
||||
paths[D_MAILLOGS_IDX] = paths[D_USER_IDX] + MAIL_LOGS_DIR DIR_SEP;
|
||||
paths[D_THEMES_IDX] = paths[D_USER_IDX] + THEMES_DIR DIR_SEP;
|
||||
paths[D_WIISYSCONF_IDX] = paths[D_WIIUSER_IDX] + WII_SYSCONF_DIR DIR_SEP;
|
||||
paths[F_DOLPHINCONFIG_IDX] = paths[D_CONFIG_IDX] + DOLPHIN_CONFIG;
|
||||
paths[F_DSPCONFIG_IDX] = paths[D_CONFIG_IDX] + DSP_CONFIG;
|
||||
paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG;
|
||||
paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG;
|
||||
paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG;
|
||||
@@ -756,6 +776,24 @@ IOFile::~IOFile()
|
||||
Close();
|
||||
}
|
||||
|
||||
IOFile::IOFile(IOFile&& other)
|
||||
: m_file(NULL), m_good(true)
|
||||
{
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
IOFile& IOFile::operator=(IOFile&& other)
|
||||
{
|
||||
IOFile((IOFile&&)other).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void IOFile::Swap(IOFile& other)
|
||||
{
|
||||
std::swap(m_file, other.m_file);
|
||||
std::swap(m_good, other.m_good);
|
||||
}
|
||||
|
||||
bool IOFile::Open(const std::string& filename, const char openmode[])
|
||||
{
|
||||
Close();
|
||||
|
||||
@@ -50,8 +50,8 @@ enum {
|
||||
D_LOGS_IDX,
|
||||
D_MAILLOGS_IDX,
|
||||
D_WIISYSCONF_IDX,
|
||||
D_THEMES_IDX,
|
||||
F_DOLPHINCONFIG_IDX,
|
||||
F_DSPCONFIG_IDX,
|
||||
F_DEBUGGERCONFIG_IDX,
|
||||
F_LOGGERCONFIG_IDX,
|
||||
F_MAINLOG_IDX,
|
||||
@@ -150,7 +150,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str);
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
// and make forgetting an fclose() harder
|
||||
class IOFile : NonCopyable
|
||||
class IOFile
|
||||
{
|
||||
public:
|
||||
IOFile();
|
||||
@@ -158,6 +158,11 @@ public:
|
||||
IOFile(const std::string& filename, const char openmode[]);
|
||||
|
||||
~IOFile();
|
||||
|
||||
IOFile(IOFile&& other);
|
||||
IOFile& operator=(IOFile&& other);
|
||||
|
||||
void Swap(IOFile& other);
|
||||
|
||||
bool Open(const std::string& filename, const char openmode[]);
|
||||
bool Close();
|
||||
@@ -212,6 +217,7 @@ public:
|
||||
void Clear() { m_good = true; std::clearerr(m_file); }
|
||||
|
||||
private:
|
||||
IOFile(const IOFile&) /*= delete*/;
|
||||
IOFile& operator=(const IOFile&) /*= delete*/;
|
||||
|
||||
std::FILE* m_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()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
// Increment this every time you change shader generation code.
|
||||
enum
|
||||
{
|
||||
LINEAR_DISKCACHE_VER = 6975
|
||||
LINEAR_DISKCACHE_VER = 6979
|
||||
};
|
||||
|
||||
// On disk format:
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "Host.h"
|
||||
#endif
|
||||
#include "LogManager.h"
|
||||
#include "ConsoleListener.h"
|
||||
#include "Timer.h"
|
||||
@@ -132,7 +135,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -114,23 +107,6 @@ u32 ClassifyFloat(float fvalue)
|
||||
|
||||
} // 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)
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <vector>
|
||||
#include "FPURoundMode.h"
|
||||
|
||||
namespace MathUtil
|
||||
{
|
||||
@@ -147,17 +147,6 @@ 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))
|
||||
|
||||
@@ -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,16 +38,47 @@ 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);
|
||||
unlink(ram_temp_file);
|
||||
ftruncate(fd, size);
|
||||
if (ftruncate(fd, size) < 0)
|
||||
ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
@@ -118,8 +153,7 @@ u8* MemArena::Find4GBBase()
|
||||
}
|
||||
return base;
|
||||
#else
|
||||
void* base = mmap(0, 0x31000000, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED, -1, 0);
|
||||
void* base = mmap(0, 0x31000000, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
PanicAlert("Failed to map 1 GB of memory space: %s", strerror(errno));
|
||||
return 0;
|
||||
|
||||
@@ -117,8 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
|
||||
void* ptr = _aligned_malloc(size,alignment);
|
||||
#else
|
||||
void* ptr = NULL;
|
||||
posix_memalign(&ptr, alignment, size);
|
||||
;
|
||||
#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,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <unistd.h> // for unlink()
|
||||
#endif
|
||||
|
||||
/* believe me, you *don't* want to change these constants !! */
|
||||
/* Believe me, you *don't* want to change these constants !! */
|
||||
#define BYTES_PER_SECTOR 512
|
||||
#define RESERVED_SECTORS 32
|
||||
#define BACKUP_BOOT_SECTOR 6
|
||||
@@ -52,15 +52,15 @@
|
||||
#define POKES(p,v) ( BYTE_(p,0) = (u8)(v), BYTE_(p,1) = (u8)((v) >> 8) )
|
||||
#define POKEW(p,v) ( BYTE_(p,0) = (u8)(v), BYTE_(p,1) = (u8)((v) >> 8), BYTE_(p,2) = (u8)((v) >> 16), BYTE_(p,3) = (u8)((v) >> 24) )
|
||||
|
||||
static u8 s_boot_sector [ BYTES_PER_SECTOR ]; /* boot sector */
|
||||
static u8 s_boot_sector [ BYTES_PER_SECTOR ]; /* Boot sector */
|
||||
static u8 s_fsinfo_sector [ BYTES_PER_SECTOR ]; /* FS Info sector */
|
||||
static u8 s_fat_head [ BYTES_PER_SECTOR ]; /* first FAT sector */
|
||||
static u8 s_fat_head [ BYTES_PER_SECTOR ]; /* First FAT sector */
|
||||
|
||||
/* this is the date and time when creating the disk */
|
||||
static int get_serial_id()
|
||||
/* This is the date and time when creating the disk */
|
||||
static unsigned int get_serial_id()
|
||||
{
|
||||
u16 lo, hi;
|
||||
time_t now = time(NULL);
|
||||
time_t now = time(nullptr);
|
||||
struct tm tm = gmtime( &now )[0];
|
||||
|
||||
lo = (u16)(tm.tm_mday + ((tm.tm_mon+1) << 8) + (tm.tm_sec << 8));
|
||||
@@ -69,7 +69,7 @@ static int get_serial_id()
|
||||
return lo + (hi << 16);
|
||||
}
|
||||
|
||||
static int get_sectors_per_cluster(u64 disk_size)
|
||||
static unsigned int get_sectors_per_cluster(u64 disk_size)
|
||||
{
|
||||
u64 disk_MB = disk_size/(1024*1024);
|
||||
|
||||
@@ -88,60 +88,60 @@ static int get_sectors_per_cluster(u64 disk_size)
|
||||
return 32;
|
||||
}
|
||||
|
||||
static int get_sectors_per_fat(u64 disk_size, int sectors_per_cluster)
|
||||
static unsigned int get_sectors_per_fat(u64 disk_size, u32 sectors_per_cluster)
|
||||
{
|
||||
u64 divider;
|
||||
|
||||
/* weird computation from MS - see fatgen103.doc for details */
|
||||
disk_size -= RESERVED_SECTORS * BYTES_PER_SECTOR; /* don't count 32 reserved sectors */
|
||||
disk_size /= BYTES_PER_SECTOR; /* disk size in sectors */
|
||||
/* Weird computation from MS - see fatgen103.doc for details */
|
||||
disk_size -= RESERVED_SECTORS * BYTES_PER_SECTOR; /* Don't count 32 reserved sectors */
|
||||
disk_size /= BYTES_PER_SECTOR; /* Disk size in sectors */
|
||||
divider = ((256 * sectors_per_cluster) + NUM_FATS) / 2;
|
||||
|
||||
return (int)( (disk_size + (divider-1)) / divider );
|
||||
return (u32)( (disk_size + (divider-1)) / divider );
|
||||
}
|
||||
|
||||
static void boot_sector_init(u8* boot, u8* info, u64 disk_size, const char* label)
|
||||
{
|
||||
int sectors_per_cluster = get_sectors_per_cluster(disk_size);
|
||||
int sectors_per_fat = get_sectors_per_fat(disk_size, sectors_per_cluster);
|
||||
int sectors_per_disk = (int)(disk_size / BYTES_PER_SECTOR);
|
||||
int serial_id = get_serial_id();
|
||||
int free_count;
|
||||
u32 sectors_per_cluster = get_sectors_per_cluster(disk_size);
|
||||
u32 sectors_per_fat = get_sectors_per_fat(disk_size, sectors_per_cluster);
|
||||
u32 sectors_per_disk = (u32)(disk_size / BYTES_PER_SECTOR);
|
||||
u32 serial_id = get_serial_id();
|
||||
u32 free_count;
|
||||
|
||||
if (label == NULL)
|
||||
if (label == nullptr)
|
||||
label = "DOLPHINSD";
|
||||
|
||||
POKEB(boot, 0xeb);
|
||||
POKEB(boot+1, 0x5a);
|
||||
POKEB(boot+2, 0x90);
|
||||
strcpy( (char*)boot + 3, "MSWIN4.1" );
|
||||
POKES( boot + 0x0b, BYTES_PER_SECTOR ); /* sector size */
|
||||
POKEB( boot + 0xd, sectors_per_cluster ); /* sectors per cluster */
|
||||
POKES( boot + 0xe, RESERVED_SECTORS ); /* reserved sectors before first FAT */
|
||||
POKEB( boot + 0x10, NUM_FATS ); /* number of FATs */
|
||||
POKES( boot + 0x11, 0 ); /* max root directory entries for FAT12/FAT16, 0 for FAT32 */
|
||||
POKES( boot + 0x13, 0 ); /* total sectors, 0 to use 32-bit value at offset 0x20 */
|
||||
POKEB( boot + 0x15, 0xF8 ); /* media descriptor, 0xF8 == hard disk */
|
||||
POKES( boot + 0x0b, BYTES_PER_SECTOR ); /* Sector size */
|
||||
POKEB( boot + 0xd, sectors_per_cluster ); /* Sectors per cluster */
|
||||
POKES( boot + 0xe, RESERVED_SECTORS ); /* Reserved sectors before first FAT */
|
||||
POKEB( boot + 0x10, NUM_FATS ); /* Number of FATs */
|
||||
POKES( boot + 0x11, 0 ); /* Max root directory entries for FAT12/FAT16, 0 for FAT32 */
|
||||
POKES( boot + 0x13, 0 ); /* Total sectors, 0 to use 32-bit value at offset 0x20 */
|
||||
POKEB( boot + 0x15, 0xF8 ); /* Media descriptor, 0xF8 == hard disk */
|
||||
POKES( boot + 0x16, 0 ); /* Sectors per FAT for FAT12/16, 0 for FAT32 */
|
||||
POKES( boot + 0x18, 9 ); /* Sectors per track (whatever) */
|
||||
POKES( boot + 0x1a, 2 ); /* Number of heads (whatever) */
|
||||
POKEW( boot + 0x1c, 0 ); /* Hidden sectors */
|
||||
POKEW( boot + 0x20, sectors_per_disk ); /* Total sectors */
|
||||
|
||||
/* extension */
|
||||
/* Extension */
|
||||
POKEW( boot + 0x24, sectors_per_fat ); /* Sectors per FAT */
|
||||
POKES( boot + 0x28, 0 ); /* FAT flags */
|
||||
POKES( boot + 0x2a, 0 ); /* version */
|
||||
POKEW( boot + 0x2c, 2 ); /* cluster number of root directory start */
|
||||
POKES( boot + 0x30, 1 ); /* sector number of FS information sector */
|
||||
POKES( boot + 0x32, BACKUP_BOOT_SECTOR ); /* sector number of a copy of this boot sector */
|
||||
POKEB( boot + 0x40, 0x80 ); /* physical drive number */
|
||||
POKEB( boot + 0x42, 0x29 ); /* extended boot signature ?? */
|
||||
POKEW( boot + 0x43, serial_id ); /* serial ID */
|
||||
POKES( boot + 0x2a, 0 ); /* Version */
|
||||
POKEW( boot + 0x2c, 2 ); /* Cluster number of root directory start */
|
||||
POKES( boot + 0x30, 1 ); /* Sector number of FS information sector */
|
||||
POKES( boot + 0x32, BACKUP_BOOT_SECTOR ); /* Sector number of a copy of this boot sector */
|
||||
POKEB( boot + 0x40, 0x80 ); /* Physical drive number */
|
||||
POKEB( boot + 0x42, 0x29 ); /* Extended boot signature ?? */
|
||||
POKEW( boot + 0x43, serial_id ); /* Serial ID */
|
||||
strncpy( (char*)boot + 0x47, label, 11 ); /* Volume Label */
|
||||
memcpy( boot + 0x52, "FAT32 ", 8 ); /* FAT system type, padded with 0x20 */
|
||||
|
||||
POKEB( boot + BYTES_PER_SECTOR-2, 0x55 ); /* boot sector signature */
|
||||
POKEB( boot + BYTES_PER_SECTOR-2, 0x55 ); /* Boot sector signature */
|
||||
POKEB( boot + BYTES_PER_SECTOR-1, 0xAA );
|
||||
|
||||
/* FSInfo sector */
|
||||
@@ -149,25 +149,25 @@ static void boot_sector_init(u8* boot, u8* info, u64 disk_size, const char* labe
|
||||
|
||||
POKEW( info + 0, 0x41615252 );
|
||||
POKEW( info + 484, 0x61417272 );
|
||||
POKEW( info + 488, free_count ); /* number of free clusters */
|
||||
POKEW( info + 492, 3 ); /* next free clusters, 0-1 reserved, 2 is used for the root dir */
|
||||
POKEW( info + 488, free_count ); /* Number of free clusters */
|
||||
POKEW( info + 492, 3 ); /* Next free clusters, 0-1 reserved, 2 is used for the root dir */
|
||||
POKEW( info + 508, 0xAA550000 );
|
||||
}
|
||||
|
||||
static void fat_init(u8* fat)
|
||||
{
|
||||
POKEW( fat, 0x0ffffff8 ); /* reserve cluster 1, media id in low byte */
|
||||
POKEW( fat + 4, 0x0fffffff ); /* reserve cluster 2 */
|
||||
POKEW( fat + 8, 0x0fffffff ); /* end of clust chain for root dir */
|
||||
POKEW( fat, 0x0ffffff8 ); /* Reserve cluster 1, media id in low byte */
|
||||
POKEW( fat + 4, 0x0fffffff ); /* Reserve cluster 2 */
|
||||
POKEW( fat + 8, 0x0fffffff ); /* End of cluster chain for root dir */
|
||||
}
|
||||
|
||||
|
||||
static int write_sector(FILE* file, u8* sector)
|
||||
static unsigned int write_sector(FILE* file, u8* sector)
|
||||
{
|
||||
return fwrite(sector, 1, 512, file) != 512;
|
||||
}
|
||||
|
||||
static int write_empty(FILE* file, u64 count)
|
||||
static unsigned int write_empty(FILE* file, u64 count)
|
||||
{
|
||||
static u8 empty[64*1024];
|
||||
|
||||
@@ -188,8 +188,8 @@ static int write_empty(FILE* file, u64 count)
|
||||
|
||||
bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
|
||||
{
|
||||
int sectors_per_fat;
|
||||
int sectors_per_disk;
|
||||
u32 sectors_per_fat;
|
||||
u32 sectors_per_disk;
|
||||
FILE* f;
|
||||
|
||||
// Convert MB to bytes
|
||||
@@ -200,21 +200,21 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
// pretty unlikely to overflow.
|
||||
sectors_per_disk = (int)(disk_size / 512);
|
||||
// Pretty unlikely to overflow.
|
||||
sectors_per_disk = (u32)(disk_size / 512);
|
||||
sectors_per_fat = get_sectors_per_fat(disk_size, get_sectors_per_cluster(disk_size));
|
||||
|
||||
boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, NULL );
|
||||
boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr);
|
||||
fat_init(s_fat_head);
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
if (!f)
|
||||
{
|
||||
ERROR_LOG(COMMON, "could not create file '%s', aborting...\n", filename);
|
||||
ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* here's the layout:
|
||||
/* Here's the layout:
|
||||
*
|
||||
* boot_sector
|
||||
* fsinfo_sector
|
||||
@@ -251,7 +251,7 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
|
||||
return true;
|
||||
|
||||
FailWrite:
|
||||
ERROR_LOG(COMMON, "could not write to '%s', aborting...\n", filename);
|
||||
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);
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// 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 _SETUP_H_
|
||||
#define _SETUP_H_
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// File description:
|
||||
// Compilation settings. I avoid placing this in Common.h or some place where lots of files needs
|
||||
// to be rebuilt if any of these settings are changed. I'd rather have it in as few files as possible.
|
||||
// This file can be kept on the ignore list in your SVN program. It allows local optional settings
|
||||
// depending on what works on your computer.
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Settings:
|
||||
|
||||
// This may remove sound artifacts in Wario Land Shake It and perhaps other games
|
||||
//#define SETUP_AVOID_SOUND_ARTIFACTS
|
||||
|
||||
// Build with playback rerecording options
|
||||
//#define RERECORDING
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
#endif // _SETUP_H_
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -318,9 +318,12 @@ public:
|
||||
|
||||
mutex_type* release()
|
||||
{
|
||||
return mutex();
|
||||
auto const ret = mutex();
|
||||
|
||||
pm = NULL;
|
||||
owns = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool owns_lock() const
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -69,7 +69,8 @@ std::string StringFromFormat(const char* format, ...)
|
||||
delete[] buf;
|
||||
#else
|
||||
va_start(args, format);
|
||||
vasprintf(&buf, format, args);
|
||||
if (vasprintf(&buf, format, args) < 0)
|
||||
ERROR_LOG(COMMON, "Unable to allocate memory for string");
|
||||
va_end(args);
|
||||
|
||||
std::string temp = buf;
|
||||
@@ -262,25 +263,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)
|
||||
@@ -302,8 +303,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;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Setup.h"
|
||||
#include "Thread.h"
|
||||
#include "Common.h"
|
||||
|
||||
@@ -106,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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -97,12 +97,6 @@ void Timer::AddTimeDifference()
|
||||
m_StartTime += GetTimeDifference();
|
||||
}
|
||||
|
||||
// Wind back the starting time to a custom time
|
||||
void Timer::WindBackStartingTime(u64 WindBack)
|
||||
{
|
||||
m_StartTime += WindBack;
|
||||
}
|
||||
|
||||
// Get the time elapsed since the Start()
|
||||
u64 Timer::GetTimeElapsed()
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
// The time difference is always returned in milliseconds, regardless of alternative internal representation
|
||||
u64 GetTimeDifference();
|
||||
void AddTimeDifference();
|
||||
void WindBackStartingTime(u64 WindBack);
|
||||
|
||||
static void IncreaseResolution();
|
||||
static void RestoreResolution();
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
#include "../../../Plugins/Plugin_VideoDX9/Src/VideoBackend.h"
|
||||
#include "../../../Plugins/Plugin_VideoDX11/Src/VideoBackend.h"
|
||||
#endif
|
||||
#ifndef USE_GLES
|
||||
#include "../../../Plugins/Plugin_VideoOGL/Src/VideoBackend.h"
|
||||
#endif
|
||||
#include "../../../Plugins/Plugin_VideoSoftware/Src/VideoBackend.h"
|
||||
|
||||
std::vector<VideoBackend*> g_available_video_backends;
|
||||
@@ -41,7 +43,7 @@ static bool IsGteVista()
|
||||
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
|
||||
return VerifyVersionInfo(&osvi, VER_MAJORVERSION, dwlConditionMask);
|
||||
return VerifyVersionInfo(&osvi, VER_MAJORVERSION, dwlConditionMask) != FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -52,7 +54,9 @@ void VideoBackend::PopulateList()
|
||||
if (IsGteVista())
|
||||
g_available_video_backends.push_back(new DX11::VideoBackend);
|
||||
#endif
|
||||
#ifndef USE_GLES
|
||||
g_available_video_backends.push_back(new OGL::VideoBackend);
|
||||
#endif
|
||||
g_available_video_backends.push_back(new SW::VideoSoftware);
|
||||
|
||||
g_video_backend = g_available_video_backends.front();
|
||||
@@ -69,6 +73,9 @@ 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();
|
||||
|
||||
for (std::vector<VideoBackend*>::const_iterator it = g_available_video_backends.begin(); it != g_available_video_backends.end(); ++it)
|
||||
if (name == (*it)->GetName())
|
||||
g_video_backend = *it;
|
||||
|
||||
@@ -139,6 +139,8 @@ public:
|
||||
|
||||
// the implementation needs not do synchronization logic, because calls to it are surrounded by PauseAndLock now
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
|
||||
virtual void CheckInvalidState() = 0;
|
||||
};
|
||||
|
||||
extern std::vector<VideoBackend*> g_available_video_backends;
|
||||
@@ -180,9 +182,15 @@ class VideoBackendHardware : public VideoBackend
|
||||
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock=true);
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
bool m_invalid;
|
||||
|
||||
public:
|
||||
void CheckInvalidState();
|
||||
|
||||
protected:
|
||||
void InitializeShared();
|
||||
void InvalidState();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
File renamed without changes.
@@ -31,12 +31,9 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
||||
info.hasImmediate = false;
|
||||
info.isMemoryWrite = false;
|
||||
|
||||
int addressSize = 8;
|
||||
u8 modRMbyte = 0;
|
||||
u8 sibByte = 0;
|
||||
bool hasModRM = false;
|
||||
bool hasSIBbyte = false;
|
||||
bool hasDisplacement = false;
|
||||
|
||||
int displacementSize = 0;
|
||||
|
||||
@@ -47,7 +44,6 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
||||
}
|
||||
else if (*codePtr == 0x67)
|
||||
{
|
||||
addressSize = 4;
|
||||
codePtr++;
|
||||
}
|
||||
|
||||
@@ -113,7 +109,6 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
||||
info.otherReg = (sibByte & 7);
|
||||
if (rex & 2) info.scaledReg += 8;
|
||||
if (rex & 1) info.otherReg += 8;
|
||||
hasSIBbyte = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -122,7 +117,6 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
|
||||
}
|
||||
if (mrm.mod == 1 || mrm.mod == 2)
|
||||
{
|
||||
hasDisplacement = true;
|
||||
if (mrm.mod == 1)
|
||||
displacementSize = 1;
|
||||
else
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
#else
|
||||
|
||||
//#include <config/i386/cpuid.h>
|
||||
#ifndef _M_GENERIC
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined __FreeBSD__
|
||||
#include <sys/types.h>
|
||||
@@ -39,7 +41,9 @@
|
||||
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
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__ (
|
||||
@@ -173,9 +177,7 @@ void CPUInfo::Detect()
|
||||
if (max_ex_fn >= 0x80000001) {
|
||||
// Check for more features.
|
||||
__cpuid(cpu_id, 0x80000001);
|
||||
bool cmp_legacy = false;
|
||||
if (cpu_id[2] & 1) bLAHFSAHF64 = true;
|
||||
if (cpu_id[2] & 2) cmp_legacy = true; //wtf is this?
|
||||
if ((cpu_id[3] >> 29) & 1) bLongMode = true;
|
||||
}
|
||||
|
||||
@@ -207,14 +209,7 @@ void CPUInfo::Detect()
|
||||
// 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 (HTT) sum += StringFromFormat(" (%i logical threads per physical core)", logical_cpu_count);
|
||||
}
|
||||
std::string sum(cpu_string);
|
||||
if (bSSE) sum += ", SSE";
|
||||
if (bSSE2) sum += ", SSE2";
|
||||
if (bSSE3) sum += ", SSE3";
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
#include "CPUDetect.h"
|
||||
|
||||
namespace Gen
|
||||
@@ -870,7 +870,6 @@ void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest,
|
||||
//shift can be either imm8 or cl
|
||||
void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift)
|
||||
{
|
||||
bool writeImm = false;
|
||||
if (dest.IsImm())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHRD - can't use imms as destination");
|
||||
@@ -901,7 +900,6 @@ void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift)
|
||||
|
||||
void XEmitter::SHLD(int bits, OpArg dest, OpArg src, OpArg shift)
|
||||
{
|
||||
bool writeImm = false;
|
||||
if (dest.IsImm())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHLD - can't use imms as destination");
|
||||
@@ -1070,8 +1068,10 @@ void XEmitter::XOR (int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(t
|
||||
void XEmitter::MOV (int bits, const OpArg &a1, const OpArg &a2)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#ifndef _M_X64
|
||||
_assert_msg_(DYNA_REC, !a1.IsSimpleReg() || !a2.IsSimpleReg() || a1.GetSimpleReg() != a2.GetSimpleReg(), "Redundant MOV @ %p - bug in JIT?",
|
||||
code);
|
||||
code);
|
||||
#endif
|
||||
#endif
|
||||
WriteNormalOp(this, bits, nrmMOV, a1, a2);
|
||||
}
|
||||
|
||||
@@ -757,7 +757,7 @@ public:
|
||||
region_size = 0;
|
||||
}
|
||||
|
||||
bool IsInCodeSpace(u8 *ptr)
|
||||
bool IsInSpace(u8 *ptr)
|
||||
{
|
||||
return ptr >= region && ptr < region + region_size;
|
||||
}
|
||||
|
||||
@@ -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[4]) | 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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in new issue
Block a user