Make the (V)LDR/(V)STR instructions support negative offsets. This fixes a bug where Arm Jit couldn't load the top 33 FPRs. Also makes it so the core can access all GPRs, FPRs, and SPRs in ppcState. This increases VPS 15-20 on SSBM intro movie on ODROIDX
This commit is contained in:
parent
2095641af0
commit
d6558e1c31
|
@ -533,15 +533,15 @@ void ARMXEmitter::MRS (ARMReg dest)
|
||||||
Write32(condition | (16 << 20) | (15 << 16) | (dest << 12));
|
Write32(condition | (16 << 20) | (15 << 16) | (dest << 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMXEmitter::WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2)
|
void ARMXEmitter::WriteStoreOp(u32 op, ARMReg dest, ARMReg src, s16 op2)
|
||||||
{
|
{
|
||||||
if (op2.GetData() == 0) // set the preindex bit, but not the W bit!
|
bool Index = op2 != 0 ? true : false;
|
||||||
Write32(condition | 0x01800000 | (op << 20) | (dest << 16) | (src << 12) | op2.Imm12());
|
bool Add = op2 >= 0 ? true : false;
|
||||||
else
|
u32 imm = abs(op2);
|
||||||
Write32(condition | (op << 20) | (3 << 23) | (dest << 16) | (src << 12) | op2.Imm12());
|
Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (src << 12) | imm);
|
||||||
}
|
}
|
||||||
void ARMXEmitter::STR (ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x40, dest, src, op);}
|
void ARMXEmitter::STR (ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x40, dest, src, op);}
|
||||||
void ARMXEmitter::STRB(ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x44, dest, src, op);}
|
void ARMXEmitter::STRB(ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x44, dest, src, op);}
|
||||||
void ARMXEmitter::STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add)
|
void ARMXEmitter::STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add)
|
||||||
{
|
{
|
||||||
Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (base << 12) | offset);
|
Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (base << 12) | offset);
|
||||||
|
@ -564,13 +564,13 @@ void ARMXEmitter::SVC(Operand2 op)
|
||||||
Write32(condition | (0x0F << 24) | op.Imm24());
|
Write32(condition | (0x0F << 24) | op.Imm24());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMXEmitter::LDR (ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x41, src, dest, op);}
|
void ARMXEmitter::LDR (ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x41, src, dest, op);}
|
||||||
void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op)
|
void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op)
|
||||||
{
|
{
|
||||||
u8 Imm = op.Imm8();
|
u8 Imm = op.Imm8();
|
||||||
Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F));
|
Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F));
|
||||||
}
|
}
|
||||||
void ARMXEmitter::LDRB(ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x45, src, dest, op);}
|
void ARMXEmitter::LDRB(ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x45, src, dest, op);}
|
||||||
|
|
||||||
void ARMXEmitter::LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add)
|
void ARMXEmitter::LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add)
|
||||||
{
|
{
|
||||||
|
@ -661,14 +661,18 @@ void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||||
|
|
||||||
// VFP Specific
|
// VFP Specific
|
||||||
|
|
||||||
void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, u16 offset)
|
void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset)
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");
|
_assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");
|
||||||
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR");
|
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR");
|
||||||
_assert_msg_(DYNA_REC, (offset & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough");
|
|
||||||
|
|
||||||
if (offset & 0xC03) {
|
bool Add = offset >= 0 ? true : false;
|
||||||
ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", offset);
|
u32 imm = abs(offset);
|
||||||
|
|
||||||
|
_assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough");
|
||||||
|
|
||||||
|
if (imm & 0xC03) {
|
||||||
|
ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool single_reg = Dest < D0;
|
bool single_reg = Dest < D0;
|
||||||
|
@ -677,24 +681,28 @@ void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, u16 offset)
|
||||||
|
|
||||||
if (single_reg)
|
if (single_reg)
|
||||||
{
|
{
|
||||||
Write32(NO_COND | (0x1B << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
|
Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
|
||||||
| ((Dest & 0x1E) << 11) | (10 << 8) | (offset >> 2));
|
| ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write32(NO_COND | (0x1B << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
|
Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
|
||||||
| ((Dest & 0xF) << 12) | (11 << 8) | (offset >> 2));
|
| ((Dest & 0xF) << 12) | (11 << 8) | (imm >> 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 offset)
|
void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, s16 offset)
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR");
|
_assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR");
|
||||||
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR");
|
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR");
|
||||||
_assert_msg_(DYNA_REC, (offset & 0xC03) == 0, "VSTR: Offset needs to be word aligned");
|
|
||||||
|
|
||||||
if (offset & 0xC03) {
|
bool Add = offset >= 0 ? true : false;
|
||||||
ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", offset);
|
u32 imm = abs(offset);
|
||||||
|
|
||||||
|
_assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VSTR: Offset needs to be word aligned and small enough");
|
||||||
|
|
||||||
|
if (imm & 0xC03) {
|
||||||
|
ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool single_reg = Src < D0;
|
bool single_reg = Src < D0;
|
||||||
|
@ -703,14 +711,14 @@ void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, u16 offset)
|
||||||
|
|
||||||
if (single_reg)
|
if (single_reg)
|
||||||
{
|
{
|
||||||
Write32(NO_COND | (0x1B << 23) | ((Src & 0x1) << 22) | (Base << 16) \
|
Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Src & 0x1) << 22) | (Base << 16) \
|
||||||
| ((Src & 0x1E) << 11) | (10 << 8) | (offset >> 2));
|
| ((Src & 0x1E) << 11) | (10 << 8) | (imm >> 2));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write32(NO_COND | (0x1B << 23) | ((Src & 0x10) << 18) | (Base << 16) \
|
Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Src & 0x10) << 18) | (Base << 16) \
|
||||||
| ((Src & 0xF) << 12) | (11 << 8) | (offset >> 2));
|
| ((Src & 0xF) << 12) | (11 << 8) | (imm >> 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm)
|
void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm)
|
||||||
|
|
|
@ -208,7 +208,7 @@ public:
|
||||||
Value = base;
|
Value = base;
|
||||||
Type = TYPE_IMMSREG;
|
Type = TYPE_IMMSREG;
|
||||||
}
|
}
|
||||||
const u32 GetData()
|
u32 GetData()
|
||||||
{
|
{
|
||||||
switch(Type)
|
switch(Type)
|
||||||
{
|
{
|
||||||
|
@ -225,45 +225,45 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const u32 IMMSR() // IMM shifted register
|
u32 IMMSR() // IMM shifted register
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register");
|
_assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register");
|
||||||
return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value);
|
return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value);
|
||||||
}
|
}
|
||||||
const u32 RSR() // Register shifted register
|
u32 RSR() // Register shifted register
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course");
|
_assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course");
|
||||||
return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value;
|
return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value;
|
||||||
}
|
}
|
||||||
const u32 Rm()
|
u32 Rm()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
|
_assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 Imm5()
|
u32 Imm5()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
|
||||||
return ((Value & 0x0000001F) << 7);
|
return ((Value & 0x0000001F) << 7);
|
||||||
}
|
}
|
||||||
const u32 Imm8()
|
u32 Imm8()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
|
||||||
return Value & 0xFF;
|
return Value & 0xFF;
|
||||||
}
|
}
|
||||||
const u32 Imm8Rot() // IMM8 with Rotation
|
u32 Imm8Rot() // IMM8 with Rotation
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
|
||||||
_assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation);
|
_assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation);
|
||||||
return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF);
|
return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF);
|
||||||
}
|
}
|
||||||
const u32 Imm12()
|
u32 Imm12()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
|
||||||
return (Value & 0x00000FFF);
|
return (Value & 0x00000FFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 Imm12Mod()
|
u32 Imm12Mod()
|
||||||
{
|
{
|
||||||
// This is a IMM12 with the top four bits being rotation and the
|
// 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
|
// bottom eight being a IMM. This is for instructions that need to
|
||||||
|
@ -273,32 +273,32 @@ public:
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM");
|
||||||
return ((Rotation & 0xF) << 8) | (Value & 0xFF);
|
return ((Rotation & 0xF) << 8) | (Value & 0xFF);
|
||||||
}
|
}
|
||||||
const u32 Imm16()
|
u32 Imm16()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||||
return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
|
return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
|
||||||
}
|
}
|
||||||
const u32 Imm16Low()
|
u32 Imm16Low()
|
||||||
{
|
{
|
||||||
return Imm16();
|
return Imm16();
|
||||||
}
|
}
|
||||||
const u32 Imm16High() // Returns high 16bits
|
u32 Imm16High() // Returns high 16bits
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||||
return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
|
return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
|
||||||
}
|
}
|
||||||
const u32 Imm24()
|
u32 Imm24()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
|
||||||
return (Value & 0x0FFFFFFF);
|
return (Value & 0x0FFFFFFF);
|
||||||
}
|
}
|
||||||
// NEON and ASIMD specific
|
// NEON and ASIMD specific
|
||||||
const u32 Imm8ASIMD()
|
u32 Imm8ASIMD()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
|
||||||
return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
|
return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
|
||||||
}
|
}
|
||||||
const u32 Imm8VFP()
|
u32 Imm8VFP()
|
||||||
{
|
{
|
||||||
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM");
|
_assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM");
|
||||||
return ((Value & 0xF0) << 12) | (Value & 0xF);
|
return ((Value & 0xF0) << 12) | (Value & 0xF);
|
||||||
|
@ -337,7 +337,7 @@ private:
|
||||||
u8 *lastCacheFlushEnd;
|
u8 *lastCacheFlushEnd;
|
||||||
u32 condition;
|
u32 condition;
|
||||||
|
|
||||||
void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2);
|
void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, s16 op2);
|
||||||
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
|
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, ARMReg op2);
|
||||||
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
|
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
|
||||||
|
@ -467,16 +467,16 @@ public:
|
||||||
void MRS (ARMReg dest);
|
void MRS (ARMReg dest);
|
||||||
|
|
||||||
// Memory load/store operations
|
// Memory load/store operations
|
||||||
void LDR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
void LDR (ARMReg dest, ARMReg src, s16 op2 = 0);
|
||||||
// Offset adds to the base register in LDR
|
// Offset adds to the base register in LDR
|
||||||
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||||
void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0);
|
void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0);
|
||||||
void LDRB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
void LDRB(ARMReg dest, ARMReg src, s16 op2 = 0);
|
||||||
void STR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
void STR (ARMReg dest, ARMReg src, s16 op2 = 0);
|
||||||
// Offset adds on to the destination register in STR
|
// Offset adds on to the destination register in STR
|
||||||
void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||||
|
|
||||||
void STRB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
void STRB(ARMReg dest, ARMReg src, s16 op2 = 0);
|
||||||
void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
|
void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
|
||||||
void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
|
void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
|
||||||
|
|
||||||
|
@ -499,8 +499,8 @@ public:
|
||||||
void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||||
|
|
||||||
// VFP Only
|
// VFP Only
|
||||||
void VLDR(ARMReg Dest, ARMReg Base, u16 offset);
|
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
|
||||||
void VSTR(ARMReg Src, ARMReg Base, u16 offset);
|
void VSTR(ARMReg Src, ARMReg Base, s16 offset);
|
||||||
void VCMP(ARMReg Vd, ARMReg Vm);
|
void VCMP(ARMReg Vd, ARMReg Vm);
|
||||||
// Compares against zero
|
// Compares against zero
|
||||||
void VCMP(ARMReg Vd);
|
void VCMP(ARMReg Vd);
|
||||||
|
|
|
@ -100,7 +100,7 @@ void JitArm::HLEFunction(UGeckoInstruction _inst)
|
||||||
MOVI2R(R1, _inst.hex);
|
MOVI2R(R1, _inst.hex);
|
||||||
QuickCallFunction(R14, (void*)&HLE::Execute);
|
QuickCallFunction(R14, (void*)&HLE::Execute);
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, npc));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, npc));
|
||||||
WriteExitDestInR(rA);
|
WriteExitDestInR(rA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ void JitArm::DoDownCount()
|
||||||
}
|
}
|
||||||
void JitArm::WriteExitDestInR(ARMReg Reg)
|
void JitArm::WriteExitDestInR(ARMReg Reg)
|
||||||
{
|
{
|
||||||
STR(R9, Reg, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, Reg, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
Cleanup();
|
Cleanup();
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
MOVI2R(Reg, (u32)asm_routines.dispatcher);
|
MOVI2R(Reg, (u32)asm_routines.dispatcher);
|
||||||
|
@ -170,7 +170,7 @@ void JitArm::WriteExitDestInR(ARMReg Reg)
|
||||||
}
|
}
|
||||||
void JitArm::WriteRfiExitDestInR(ARMReg Reg)
|
void JitArm::WriteRfiExitDestInR(ARMReg Reg)
|
||||||
{
|
{
|
||||||
STR(R9, Reg, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, Reg, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
Cleanup();
|
Cleanup();
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ void JitArm::WriteExit(u32 destination, int exit_num)
|
||||||
{
|
{
|
||||||
ARMReg A = gpr.GetReg(false);
|
ARMReg A = gpr.GetReg(false);
|
||||||
MOVI2R(A, destination);
|
MOVI2R(A, destination);
|
||||||
STR(R9, A, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, A, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
MOVI2R(A, (u32)asm_routines.dispatcher);
|
MOVI2R(A, (u32)asm_routines.dispatcher);
|
||||||
B(A);
|
B(A);
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,6 @@ void JitArm::Break(UGeckoInstruction inst)
|
||||||
const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
|
const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
|
||||||
{
|
{
|
||||||
int blockSize = code_buf->GetSize();
|
int blockSize = code_buf->GetSize();
|
||||||
|
|
||||||
// Memory exception on instruction fetch
|
// Memory exception on instruction fetch
|
||||||
bool memory_exception = false;
|
bool memory_exception = false;
|
||||||
|
|
||||||
|
@ -382,10 +381,10 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||||
ARMReg C = gpr.GetReg();
|
ARMReg C = gpr.GetReg();
|
||||||
Operand2 Shift(2, 10); // 1 << 13
|
Operand2 Shift(2, 10); // 1 << 13
|
||||||
MOVI2R(C, js.blockStart); // R3
|
MOVI2R(C, js.blockStart); // R3
|
||||||
LDR(A, R9, STRUCT_OFF(PowerPC::ppcState, msr));
|
LDR(A, R9, PPCSTATE_OFF(PowerPC::ppcState, msr));
|
||||||
TST(A, Shift);
|
TST(A, Shift);
|
||||||
FixupBranch b1 = B_CC(CC_NEQ);
|
FixupBranch b1 = B_CC(CC_NEQ);
|
||||||
STR(R9, C, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, C, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
MOVI2R(A, (u32)asm_routines.fpException);
|
MOVI2R(A, (u32)asm_routines.fpException);
|
||||||
B(A);
|
B(A);
|
||||||
SetJumpTarget(b1);
|
SetJumpTarget(b1);
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
if (Core::g_CoreStartupParameter.bJITOff || \
|
if (Core::g_CoreStartupParameter.bJITOff || \
|
||||||
Core::g_CoreStartupParameter.bJIT##type##Off) \
|
Core::g_CoreStartupParameter.bJIT##type##Off) \
|
||||||
{Default(inst); return;}
|
{Default(inst); return;}
|
||||||
|
#define PPCSTATE_OFF(str, elem) ((s32)STRUCT_OFF(PowerPC::ppcState, elem) - (s32)STRUCT_OFF(PowerPC::ppcState, spr[0]))
|
||||||
class JitArm : public JitBase, public ArmGen::ARMXCodeBlock
|
class JitArm : public JitBase, public ArmGen::ARMXCodeBlock
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -36,10 +36,9 @@ using namespace ArmGen;
|
||||||
void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||||
{
|
{
|
||||||
ARMXEmitter emit((u8 *)location);
|
ARMXEmitter emit((u8 *)location);
|
||||||
emit.MOVI2R(R10, (u32)&PC);
|
|
||||||
emit.MOVI2R(R11, address);
|
emit.MOVI2R(R11, address);
|
||||||
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
|
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
|
||||||
emit.STR(R10, R11);
|
emit.STR(R9, R11, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
emit.B(R12);
|
emit.B(R12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ void JitArm::sc(UGeckoInstruction inst)
|
||||||
|
|
||||||
ARMABI_MOVI2M((u32)&PC, js.compilerPC + 4); // Destroys R12 and R14
|
ARMABI_MOVI2M((u32)&PC, js.compilerPC + 4); // Destroys R12 and R14
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
ORR(rA, rA, EXCEPTION_SYSCALL);
|
ORR(rA, rA, EXCEPTION_SYSCALL);
|
||||||
STR(R9, rA, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
gpr.Unlock(rA);
|
gpr.Unlock(rA);
|
||||||
|
|
||||||
WriteExceptionExit();
|
WriteExceptionExit();
|
||||||
|
@ -78,25 +78,22 @@ void JitArm::rfi(UGeckoInstruction inst)
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
ARMReg rC = gpr.GetReg();
|
ARMReg rC = gpr.GetReg();
|
||||||
ARMReg rD = gpr.GetReg();
|
ARMReg rD = gpr.GetReg();
|
||||||
MOVI2R(rA, (u32)&MSR);
|
|
||||||
MOVI2R(rB, (~mask) & clearMSR13);
|
MOVI2R(rB, (~mask) & clearMSR13);
|
||||||
MOVI2R(rC, mask & clearMSR13);
|
MOVI2R(rC, mask & clearMSR13);
|
||||||
|
|
||||||
LDR(rD, rA);
|
LDR(rD, R9, PPCSTATE_OFF(PowerPC::ppcState, msr));
|
||||||
|
|
||||||
AND(rD, rD, rB); // rD = Masked MSR
|
AND(rD, rD, rB); // rD = Masked MSR
|
||||||
STR(rA, rD);
|
STR(R9, rD, PPCSTATE_OFF(PowerPC::ppcState, msr));
|
||||||
|
|
||||||
MOVI2R(rB, (u32)&SRR1);
|
LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_SRR1])); // rB contains SRR1 here
|
||||||
LDR(rB, rB); // rB contains SRR1 here
|
|
||||||
|
|
||||||
AND(rB, rB, rC); // rB contains masked SRR1 here
|
AND(rB, rB, rC); // rB contains masked SRR1 here
|
||||||
ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1
|
ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1
|
||||||
|
|
||||||
STR(rA, rB); // STR rB in to rA
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, msr)); // STR rB in to rA
|
||||||
|
|
||||||
MOVI2R(rA, (u32)&SRR0);
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_SRR0]));
|
||||||
LDR(rA, rA);
|
|
||||||
|
|
||||||
gpr.Unlock(rB, rC, rD);
|
gpr.Unlock(rB, rC, rD);
|
||||||
WriteRfiExitDestInR(rA); // rA gets unlocked here
|
WriteRfiExitDestInR(rA); // rA gets unlocked here
|
||||||
|
@ -116,8 +113,13 @@ void JitArm::bx(UGeckoInstruction inst)
|
||||||
// We must always process the following sentence
|
// We must always process the following sentence
|
||||||
// even if the blocks are merged by PPCAnalyst::Flatten().
|
// even if the blocks are merged by PPCAnalyst::Flatten().
|
||||||
if (inst.LK)
|
if (inst.LK)
|
||||||
ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
{
|
||||||
|
ARMReg rA = gpr.GetReg(false);
|
||||||
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
|
MOVI2R(rA, Jumpto);
|
||||||
|
STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
|
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||||
|
}
|
||||||
// If this is not the last instruction of a block,
|
// If this is not the last instruction of a block,
|
||||||
// we will skip the rest process.
|
// we will skip the rest process.
|
||||||
// Because PPCAnalyst::Flatten() merged the blocks.
|
// Because PPCAnalyst::Flatten() merged the blocks.
|
||||||
|
@ -164,10 +166,9 @@ void JitArm::bcx(UGeckoInstruction inst)
|
||||||
FixupBranch pCTRDontBranch;
|
FixupBranch pCTRDontBranch;
|
||||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
||||||
{
|
{
|
||||||
MOVI2R(rA, (u32)&CTR);
|
LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
LDR(rB, rA);
|
|
||||||
SUBS(rB, rB, 1);
|
SUBS(rB, rB, 1);
|
||||||
STR(rA, rB);
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
|
|
||||||
//SUB(32, M(&CTR), Imm8(1));
|
//SUB(32, M(&CTR), Imm8(1));
|
||||||
if (inst.BO & BO_BRANCH_IF_CTR_0)
|
if (inst.BO & BO_BRANCH_IF_CTR_0)
|
||||||
|
@ -179,7 +180,7 @@ void JitArm::bcx(UGeckoInstruction inst)
|
||||||
FixupBranch pConditionDontBranch;
|
FixupBranch pConditionDontBranch;
|
||||||
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
|
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
|
||||||
{
|
{
|
||||||
LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
||||||
TST(rA, 8 >> (inst.BI & 3));
|
TST(rA, 8 >> (inst.BI & 3));
|
||||||
|
|
||||||
//TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
|
//TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
|
||||||
|
@ -188,10 +189,15 @@ void JitArm::bcx(UGeckoInstruction inst)
|
||||||
else
|
else
|
||||||
pConditionDontBranch = B_CC(CC_NEQ); // Not Zero
|
pConditionDontBranch = B_CC(CC_NEQ); // Not Zero
|
||||||
}
|
}
|
||||||
gpr.Unlock(rA, rB);
|
|
||||||
if (inst.LK)
|
if (inst.LK)
|
||||||
ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12
|
{
|
||||||
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
|
MOVI2R(rB, Jumpto);
|
||||||
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
|
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12
|
||||||
|
}
|
||||||
|
gpr.Unlock(rA, rB);
|
||||||
|
|
||||||
u32 destination;
|
u32 destination;
|
||||||
if(inst.AA)
|
if(inst.AA)
|
||||||
destination = SignExt16(inst.BD << 2);
|
destination = SignExt16(inst.BD << 2);
|
||||||
|
@ -222,13 +228,18 @@ void JitArm::bcctrx(UGeckoInstruction inst)
|
||||||
// BO_2 == 1z1zz -> b always
|
// BO_2 == 1z1zz -> b always
|
||||||
|
|
||||||
//NPC = CTR & 0xfffffffc;
|
//NPC = CTR & 0xfffffffc;
|
||||||
if(inst.LK_3)
|
|
||||||
ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
MOVI2R(rA, (u32)&CTR);
|
|
||||||
|
if(inst.LK_3)
|
||||||
|
{
|
||||||
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
|
MOVI2R(rA, Jumpto);
|
||||||
|
STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
|
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||||
|
}
|
||||||
MVN(rB, 0x3); // 0xFFFFFFFC
|
MVN(rB, 0x3); // 0xFFFFFFFC
|
||||||
LDR(rA, rA);
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
AND(rA, rA, rB);
|
AND(rA, rA, rB);
|
||||||
gpr.Unlock(rB);
|
gpr.Unlock(rB);
|
||||||
WriteExitDestInR(rA);
|
WriteExitDestInR(rA);
|
||||||
|
@ -242,7 +253,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
|
|
||||||
LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
||||||
TST(rA, 8 >> (inst.BI & 3));
|
TST(rA, 8 >> (inst.BI & 3));
|
||||||
CCFlags branch;
|
CCFlags branch;
|
||||||
if (inst.BO_2 & BO_BRANCH_IF_TRUE)
|
if (inst.BO_2 & BO_BRANCH_IF_TRUE)
|
||||||
|
@ -251,17 +262,14 @@ void JitArm::bcctrx(UGeckoInstruction inst)
|
||||||
branch = CC_NEQ;
|
branch = CC_NEQ;
|
||||||
FixupBranch b = B_CC(branch);
|
FixupBranch b = B_CC(branch);
|
||||||
|
|
||||||
MOVI2R(rA, (u32)&CTR);
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
LDR(rA, rA);
|
|
||||||
MVN(rB, 0x3); // 0xFFFFFFFC
|
MVN(rB, 0x3); // 0xFFFFFFFC
|
||||||
AND(rA, rA, rB);
|
AND(rA, rA, rB);
|
||||||
|
|
||||||
if (inst.LK_3){
|
if (inst.LK_3){
|
||||||
ARMReg rC = gpr.GetReg(false);
|
|
||||||
u32 Jumpto = js.compilerPC + 4;
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
MOVI2R(rB, (u32)&LR);
|
MOVI2R(rB, Jumpto);
|
||||||
MOVI2R(rC, Jumpto);
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
STR(rB, rC);
|
|
||||||
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||||
}
|
}
|
||||||
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
|
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
|
||||||
|
@ -279,7 +287,11 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
||||||
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
|
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
|
||||||
if (inst.LK)
|
if (inst.LK)
|
||||||
{
|
{
|
||||||
ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
ARMReg rA = gpr.GetReg(false);
|
||||||
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
|
MOVI2R(rA, Jumpto);
|
||||||
|
STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
|
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -291,10 +303,9 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
||||||
FixupBranch pCTRDontBranch;
|
FixupBranch pCTRDontBranch;
|
||||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
|
||||||
{
|
{
|
||||||
MOVI2R(rA, (u32)&CTR);
|
LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
LDR(rB, rA);
|
|
||||||
SUBS(rB, rB, 1);
|
SUBS(rB, rB, 1);
|
||||||
STR(rA, rB);
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR]));
|
||||||
|
|
||||||
//SUB(32, M(&CTR), Imm8(1));
|
//SUB(32, M(&CTR), Imm8(1));
|
||||||
if (inst.BO & BO_BRANCH_IF_CTR_0)
|
if (inst.BO & BO_BRANCH_IF_CTR_0)
|
||||||
|
@ -306,7 +317,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
||||||
FixupBranch pConditionDontBranch;
|
FixupBranch pConditionDontBranch;
|
||||||
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
|
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
|
||||||
{
|
{
|
||||||
LDRB(rA, R9, STRUCT_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2));
|
||||||
TST(rA, 8 >> (inst.BI & 3));
|
TST(rA, 8 >> (inst.BI & 3));
|
||||||
//TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
|
//TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
|
||||||
if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch
|
if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch
|
||||||
|
@ -324,16 +335,13 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
||||||
|
|
||||||
//MOV(32, R(EAX), M(&LR));
|
//MOV(32, R(EAX), M(&LR));
|
||||||
//AND(32, R(EAX), Imm32(0xFFFFFFFC));
|
//AND(32, R(EAX), Imm32(0xFFFFFFFC));
|
||||||
MOVI2R(rA, (u32)&LR);
|
|
||||||
MVN(rB, 0x3); // 0xFFFFFFFC
|
MVN(rB, 0x3); // 0xFFFFFFFC
|
||||||
LDR(rA, rA);
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
AND(rA, rA, rB);
|
AND(rA, rA, rB);
|
||||||
if (inst.LK){
|
if (inst.LK){
|
||||||
ARMReg rC = gpr.GetReg(false);
|
|
||||||
u32 Jumpto = js.compilerPC + 4;
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
MOVI2R(rB, (u32)&LR);
|
MOVI2R(rB, Jumpto);
|
||||||
MOVI2R(rC, Jumpto);
|
STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR]));
|
||||||
STR(rB, rC);
|
|
||||||
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||||
}
|
}
|
||||||
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
|
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
|
||||||
|
|
|
@ -40,7 +40,7 @@ void JitArm::GenerateRC(int cr) {
|
||||||
SetCC(CC_MI); MOV(rB, 0x8); // Result < 0
|
SetCC(CC_MI); MOV(rB, 0x8); // Result < 0
|
||||||
SetCC();
|
SetCC();
|
||||||
|
|
||||||
STRB(R9, rB, STRUCT_OFF(PowerPC::ppcState, cr_fast) + cr);
|
STRB(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + cr);
|
||||||
gpr.Unlock(rB);
|
gpr.Unlock(rB);
|
||||||
}
|
}
|
||||||
void JitArm::ComputeRC(int cr) {
|
void JitArm::ComputeRC(int cr) {
|
||||||
|
@ -51,7 +51,7 @@ void JitArm::ComputeRC(int cr) {
|
||||||
SetCC(CC_GT); MOV(rB, 0x4); // Result > 0
|
SetCC(CC_GT); MOV(rB, 0x4); // Result > 0
|
||||||
SetCC();
|
SetCC();
|
||||||
|
|
||||||
STRB(R9, rB, STRUCT_OFF(PowerPC::ppcState, cr_fast) + cr);
|
STRB(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + cr);
|
||||||
gpr.Unlock(rB);
|
gpr.Unlock(rB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ void JitArm::cmpli(UGeckoInstruction inst)
|
||||||
SetCC(CC_HI); MOV(rA, 0x4); // Result > 0
|
SetCC(CC_HI); MOV(rA, 0x4); // Result > 0
|
||||||
SetCC();
|
SetCC();
|
||||||
|
|
||||||
STRB(R9, rA, STRUCT_OFF(PowerPC::ppcState, cr_fast) + crf);
|
STRB(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + crf);
|
||||||
gpr.Unlock(rA);
|
gpr.Unlock(rA);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ void JitArm::stwu(UGeckoInstruction inst)
|
||||||
|
|
||||||
// Check and set the update before writing since calling a function can
|
// Check and set the update before writing since calling a function can
|
||||||
// mess with the "special registers R11+ which may cause some issues.
|
// mess with the "special registers R11+ which may cause some issues.
|
||||||
LDR(Function, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(Function, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(Function, EXCEPTION_DSI);
|
CMP(Function, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotWrite = B_CC(CC_EQ);
|
FixupBranch DoNotWrite = B_CC(CC_EQ);
|
||||||
MOV(RA, Addr);
|
MOV(RA, Addr);
|
||||||
|
@ -198,7 +198,7 @@ void JitArm::lbz(UGeckoInstruction inst)
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
ARMReg RD = gpr.R(inst.RD);
|
ARMReg RD = gpr.R(inst.RD);
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(rA, EXCEPTION_DSI);
|
CMP(rA, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
||||||
#if FASTMEM
|
#if FASTMEM
|
||||||
|
@ -245,7 +245,7 @@ void JitArm::lhz(UGeckoInstruction inst)
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
ARMReg RD = gpr.R(inst.RD);
|
ARMReg RD = gpr.R(inst.RD);
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(rA, EXCEPTION_DSI);
|
CMP(rA, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
||||||
#if 0 // FASTMEM
|
#if 0 // FASTMEM
|
||||||
|
@ -295,7 +295,7 @@ void JitArm::lwz(UGeckoInstruction inst)
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
ARMReg RD = gpr.R(inst.RD);
|
ARMReg RD = gpr.R(inst.RD);
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(rA, EXCEPTION_DSI);
|
CMP(rA, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ void JitArm::lwzx(UGeckoInstruction inst)
|
||||||
|
|
||||||
ARMReg RB = gpr.R(inst.RB);
|
ARMReg RB = gpr.R(inst.RB);
|
||||||
ARMReg RD = gpr.R(inst.RD);
|
ARMReg RD = gpr.R(inst.RD);
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(rA, EXCEPTION_DSI);
|
CMP(rA, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
||||||
#if FASTMEM
|
#if FASTMEM
|
||||||
|
|
|
@ -40,7 +40,7 @@ void JitArm::lfs(UGeckoInstruction inst)
|
||||||
|
|
||||||
ARMReg rA = gpr.GetReg();
|
ARMReg rA = gpr.GetReg();
|
||||||
ARMReg rB = gpr.GetReg();
|
ARMReg rB = gpr.GetReg();
|
||||||
LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
CMP(rA, EXCEPTION_DSI);
|
CMP(rA, EXCEPTION_DSI);
|
||||||
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
FixupBranch DoNotLoad = B_CC(CC_EQ);
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,7 @@ void JitArm::mtspr(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, this is easy.
|
// OK, this is easy.
|
||||||
ARMReg rA = gpr.GetReg(false);
|
STR(R9, RD, PPCSTATE_OFF(PowerPC::ppcState, spr) + iIndex * 4);
|
||||||
MOVI2R(rA, (u32)&PowerPC::ppcState.spr);
|
|
||||||
STR(rA, RD, iIndex * 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm::mfspr(UGeckoInstruction inst)
|
void JitArm::mfspr(UGeckoInstruction inst)
|
||||||
|
@ -91,9 +89,7 @@ void JitArm::mfspr(UGeckoInstruction inst)
|
||||||
Default(inst);
|
Default(inst);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
ARMReg rA = gpr.GetReg(false);
|
LDR(RD, R9, PPCSTATE_OFF(PowerPC::ppcState, spr) + iIndex * 4);
|
||||||
MOVI2R(rA, (u32)&PowerPC::ppcState.spr);
|
|
||||||
LDR(RD, rA, iIndex * 4);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,9 +99,6 @@ void JitArm::mtmsr(UGeckoInstruction inst)
|
||||||
// Don't interpret this, if we do we get thrown out
|
// Don't interpret this, if we do we get thrown out
|
||||||
//JITDISABLE(SystemRegisters)
|
//JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
ARMReg rA = gpr.GetReg();
|
STR(R9, gpr.R(inst.RS), PPCSTATE_OFF(PowerPC::ppcState, msr));
|
||||||
MOVI2R(rA, (u32)&MSR);
|
|
||||||
STR(rA, gpr.R(inst.RS));
|
|
||||||
gpr.Unlock(rA);
|
|
||||||
WriteExit(js.compilerPC + 4, 0);
|
WriteExit(js.compilerPC + 4, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ void JitArmAsmRoutineManager::Generate()
|
||||||
PUSH(2, R11, _LR); // R11 is frame pointer in Debug.
|
PUSH(2, R11, _LR); // R11 is frame pointer in Debug.
|
||||||
|
|
||||||
MOVI2R(R0, (u32)&CoreTiming::downcount);
|
MOVI2R(R0, (u32)&CoreTiming::downcount);
|
||||||
MOVI2R(R9, (u32)&PowerPC::ppcState);
|
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
|
||||||
|
|
||||||
FixupBranch skipToRealDispatcher = B();
|
FixupBranch skipToRealDispatcher = B();
|
||||||
dispatcher = GetCodePtr();
|
dispatcher = GetCodePtr();
|
||||||
|
@ -63,7 +63,7 @@ void JitArmAsmRoutineManager::Generate()
|
||||||
|
|
||||||
// This block of code gets the address of the compiled block of code
|
// This block of code gets the address of the compiled block of code
|
||||||
// It runs though to the compiling portion if it isn't found
|
// It runs though to the compiling portion if it isn't found
|
||||||
LDR(R12, R9, STRUCT_OFF(PowerPC::ppcState, pc));// Load the current PC into R12
|
LDR(R12, R9, PPCSTATE_OFF(PowerPC::ppcState, pc));// Load the current PC into R12
|
||||||
|
|
||||||
MOVI2R(R14, JIT_ICACHE_MASK); // Potential for optimization
|
MOVI2R(R14, JIT_ICACHE_MASK); // Potential for optimization
|
||||||
AND(R12, R12, R14); // R12 contains PC & JIT_ICACHE_MASK here.
|
AND(R12, R12, R14); // R12 contains PC & JIT_ICACHE_MASK here.
|
||||||
|
@ -92,7 +92,7 @@ void JitArmAsmRoutineManager::Generate()
|
||||||
// If we get to this point, that means that we don't have the block cached to execute
|
// If we get to this point, that means that we don't have the block cached to execute
|
||||||
// So call ArmJit to compile the block and then execute it.
|
// So call ArmJit to compile the block and then execute it.
|
||||||
MOVI2R(R14, (u32)&Jit);
|
MOVI2R(R14, (u32)&Jit);
|
||||||
LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, pc));
|
LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
BL(R14);
|
BL(R14);
|
||||||
|
|
||||||
B(dispatcherNoCheck);
|
B(dispatcherNoCheck);
|
||||||
|
@ -100,12 +100,12 @@ void JitArmAsmRoutineManager::Generate()
|
||||||
// fpException()
|
// fpException()
|
||||||
// Floating Point Exception Check, Jumped to if false
|
// Floating Point Exception Check, Jumped to if false
|
||||||
fpException = GetCodePtr();
|
fpException = GetCodePtr();
|
||||||
LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
|
ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
|
||||||
STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, Exceptions));
|
STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, Exceptions));
|
||||||
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
|
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
|
||||||
LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, npc));
|
LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, npc));
|
||||||
STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
B(dispatcher);
|
B(dispatcher);
|
||||||
|
|
||||||
SetJumpTarget(bail);
|
SetJumpTarget(bail);
|
||||||
|
@ -116,11 +116,11 @@ void JitArmAsmRoutineManager::Generate()
|
||||||
|
|
||||||
// Does exception checking
|
// Does exception checking
|
||||||
testExceptions = GetCodePtr();
|
testExceptions = GetCodePtr();
|
||||||
LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, pc));
|
LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, npc));
|
STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, npc));
|
||||||
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
|
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
|
||||||
LDR(R0, R9, STRUCT_OFF(PowerPC::ppcState, npc));
|
LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, npc));
|
||||||
STR(R9, R0, STRUCT_OFF(PowerPC::ppcState, pc));
|
STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, pc));
|
||||||
// Check the state pointer to see if we are exiting
|
// Check the state pointer to see if we are exiting
|
||||||
// Gets checked on every exception check
|
// Gets checked on every exception check
|
||||||
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
|
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Jit.h"
|
||||||
#include "JitFPRCache.h"
|
#include "JitFPRCache.h"
|
||||||
|
|
||||||
ArmFPRCache::ArmFPRCache()
|
ArmFPRCache::ArmFPRCache()
|
||||||
|
@ -122,7 +123,7 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
|
||||||
for (u8 a = 0; a < NUMPPCREG; ++a)
|
for (u8 a = 0; a < NUMPPCREG; ++a)
|
||||||
if (ArmCRegs[a].PPCReg == 33)
|
if (ArmCRegs[a].PPCReg == 33)
|
||||||
{
|
{
|
||||||
u16 offset = STRUCT_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0);
|
u16 offset = PPCSTATE_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0);
|
||||||
if (preLoad)
|
if (preLoad)
|
||||||
emit->VLDR(ArmCRegs[a].Reg, R9, offset);
|
emit->VLDR(ArmCRegs[a].Reg, R9, offset);
|
||||||
ArmCRegs[a].PPCReg = preg;
|
ArmCRegs[a].PPCReg = preg;
|
||||||
|
@ -131,10 +132,10 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
|
||||||
return ArmCRegs[a].Reg;
|
return ArmCRegs[a].Reg;
|
||||||
}
|
}
|
||||||
// Alright, we couldn't get a free space, dump that least used register
|
// Alright, we couldn't get a free space, dump that least used register
|
||||||
u16 offsetOld = STRUCT_OFF(PowerPC::ppcState, ps) + (ArmCRegs[Num].PPCReg * 16) + (ArmCRegs[Num].PS1 ? 8 : 0);
|
u16 offsetOld = PPCSTATE_OFF(PowerPC::ppcState, ps) + (ArmCRegs[Num].PPCReg * 16) + (ArmCRegs[Num].PS1 ? 8 : 0);
|
||||||
emit->VSTR(ArmCRegs[Num].Reg, R9, offsetOld);
|
emit->VSTR(ArmCRegs[Num].Reg, R9, offsetOld);
|
||||||
|
|
||||||
u16 offsetNew = STRUCT_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0);
|
u16 offsetNew = PPCSTATE_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0);
|
||||||
if (preLoad)
|
if (preLoad)
|
||||||
emit->VLDR(ArmCRegs[Num].Reg, R9, offsetNew);
|
emit->VLDR(ArmCRegs[Num].Reg, R9, offsetNew);
|
||||||
ArmCRegs[Num].PPCReg = preg;
|
ArmCRegs[Num].PPCReg = preg;
|
||||||
|
@ -159,7 +160,7 @@ void ArmFPRCache::Flush()
|
||||||
for(u8 a = 0; a < NUMPPCREG; ++a)
|
for(u8 a = 0; a < NUMPPCREG; ++a)
|
||||||
if (ArmCRegs[a].PPCReg != 33)
|
if (ArmCRegs[a].PPCReg != 33)
|
||||||
{
|
{
|
||||||
u16 offset = STRUCT_OFF(PowerPC::ppcState, ps) + (ArmCRegs[a].PPCReg * 16) + (ArmCRegs[a].PS1 ? 8 : 0);
|
u16 offset = PPCSTATE_OFF(PowerPC::ppcState, ps) + (ArmCRegs[a].PPCReg * 16) + (ArmCRegs[a].PS1 ? 8 : 0);
|
||||||
emit->VSTR(ArmCRegs[a].Reg, R9, offset);
|
emit->VSTR(ArmCRegs[a].Reg, R9, offset);
|
||||||
ArmCRegs[a].PPCReg = 33;
|
ArmCRegs[a].PPCReg = 33;
|
||||||
ArmCRegs[a].LastLoad = 0;
|
ArmCRegs[a].LastLoad = 0;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Jit.h"
|
||||||
#include "JitRegCache.h"
|
#include "JitRegCache.h"
|
||||||
|
|
||||||
ArmRegCache::ArmRegCache()
|
ArmRegCache::ArmRegCache()
|
||||||
|
@ -141,14 +142,14 @@ ARMReg ArmRegCache::R(u32 preg)
|
||||||
for (u8 a = 0; a < NUMPPCREG; ++a)
|
for (u8 a = 0; a < NUMPPCREG; ++a)
|
||||||
if (ArmCRegs[a].PPCReg == 33)
|
if (ArmCRegs[a].PPCReg == 33)
|
||||||
{
|
{
|
||||||
emit->LDR(ArmCRegs[a].Reg, R9, STRUCT_OFF(PowerPC::ppcState, gpr) + preg * 4);
|
emit->LDR(ArmCRegs[a].Reg, R9, PPCSTATE_OFF(PowerPC::ppcState, gpr) + preg * 4);
|
||||||
ArmCRegs[a].PPCReg = preg;
|
ArmCRegs[a].PPCReg = preg;
|
||||||
ArmCRegs[a].LastLoad = 0;
|
ArmCRegs[a].LastLoad = 0;
|
||||||
return ArmCRegs[a].Reg;
|
return ArmCRegs[a].Reg;
|
||||||
}
|
}
|
||||||
// Alright, we couldn't get a free space, dump that least used register
|
// Alright, we couldn't get a free space, dump that least used register
|
||||||
emit->STR(R9, ArmCRegs[Num].Reg, STRUCT_OFF(PowerPC::ppcState, gpr) + ArmCRegs[Num].PPCReg * 4);
|
emit->STR(R9, ArmCRegs[Num].Reg, PPCSTATE_OFF(PowerPC::ppcState, gpr) + ArmCRegs[Num].PPCReg * 4);
|
||||||
emit->LDR(ArmCRegs[Num].Reg, R9, STRUCT_OFF(PowerPC::ppcState, gpr) + preg * 4);
|
emit->LDR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(PowerPC::ppcState, gpr) + preg * 4);
|
||||||
ArmCRegs[Num].PPCReg = preg;
|
ArmCRegs[Num].PPCReg = preg;
|
||||||
ArmCRegs[Num].LastLoad = 0;
|
ArmCRegs[Num].LastLoad = 0;
|
||||||
return ArmCRegs[Num].Reg;
|
return ArmCRegs[Num].Reg;
|
||||||
|
@ -159,7 +160,7 @@ void ArmRegCache::Flush()
|
||||||
for(u8 a = 0; a < NUMPPCREG; ++a)
|
for(u8 a = 0; a < NUMPPCREG; ++a)
|
||||||
if (ArmCRegs[a].PPCReg != 33)
|
if (ArmCRegs[a].PPCReg != 33)
|
||||||
{
|
{
|
||||||
emit->STR(R9, ArmCRegs[a].Reg, STRUCT_OFF(PowerPC::ppcState, gpr) + ArmCRegs[a].PPCReg * 4);
|
emit->STR(R9, ArmCRegs[a].Reg, PPCSTATE_OFF(PowerPC::ppcState, gpr) + ArmCRegs[a].PPCReg * 4);
|
||||||
ArmCRegs[a].PPCReg = 33;
|
ArmCRegs[a].PPCReg = 33;
|
||||||
ArmCRegs[a].LastLoad = 0;
|
ArmCRegs[a].LastLoad = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue