diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp index e7d76c205c..f4df6bcd72 100644 --- a/Common/ArmCPUDetect.cpp +++ b/Common/ArmCPUDetect.cpp @@ -200,8 +200,10 @@ std::string CPUInfo::Summarize() if (bVFPv3) sum += ", VFPv3"; if (bTLS) sum += ", TLS"; if (bVFPv4) sum += ", VFPv4"; - if (bIDIVa) sum += ", IDIVa"; - if (bIDIVt) sum += ", IDIVt"; + // On some buggy kernels(Qualcomm) they show that they support VFPv4 but not IDIVa + // All VFPv4 CPUs will support IDIVa + if (bIDIVa || bVFPv4) sum += ", IDIVa"; + if (bIDIVt || bVFPv4) sum += ", IDIVt"; return sum; } diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 960e3f2a62..e2f55ccb74 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -176,7 +176,7 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize) } else { // Use literal pool for ARMv6. AddNewLit(val); - LDRLIT(reg, 0, 0); // To be backpatched later + LDR(reg, _PC); // To be backpatched later } } } @@ -606,36 +606,6 @@ void ARMXEmitter::MRS (ARMReg dest) Write32(condition | (16 << 20) | (15 << 16) | (dest << 12)); } -void ARMXEmitter::WriteStoreOp(u32 op, ARMReg src, ARMReg dest, Operand2 op2) -{ - if (op2.GetData() == 0) // set the preindex bit, but not the W bit! - Write32(condition | 0x01800000 | (op << 20) | (src << 16) | (dest << 12) | op2.Imm12()); - else - Write32(condition | (op << 20) | (3 << 23) | (src << 16) | (dest << 12) | op2.Imm12()); -} -void ARMXEmitter::STR (ARMReg result, ARMReg base, Operand2 op) { WriteStoreOp(0x40, base, result, op);} -void ARMXEmitter::STRH (ARMReg result, ARMReg base, Operand2 op) -{ - u8 Imm = op.Imm8(); - Write32(condition | (0x04 << 20) | (base << 16) | (result << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F)); -} -void ARMXEmitter::STRB (ARMReg result, ARMReg base, Operand2 op) { WriteStoreOp(0x44, base, result, op);} -void ARMXEmitter::STR (ARMReg result, ARMReg base, Operand2 op2, bool Index, bool Add) -{ - Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (result << 12) | op2.IMMSR()); -} -void ARMXEmitter::STR (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (result << 12) | offset); -} -void ARMXEmitter::STRH (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x00 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (result << 12) | (0xB << 4) | offset); -} -void ARMXEmitter::STRB (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x64 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (result << 12) | offset); -} void ARMXEmitter::LDREX(ARMReg dest, ARMReg base) { Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F); @@ -653,50 +623,115 @@ void ARMXEmitter::SVC(Operand2 op) { Write32(condition | (0x0F << 24) | op.Imm24()); } +// IMM, REG, IMMSREG, RSR +// -1 for invalid if the instruction doesn't support that +const s32 LoadStoreOps[][4] = { + {0x40, 0x60, 0x60, -1}, // STR + {0x41, 0x61, 0x61, -1}, // LDR + {0x44, 0x64, 0x64, -1}, // STRB + {0x45, 0x65, 0x65, -1}, // LDRB + // Special encodings + { 0x4, 0x0, -1, -1}, // STRH + { 0x5, 0x1, -1, -1}, // LDRH + { 0x5, 0x1, -1, -1}, // LDRSB + { 0x5, 0x1, -1, -1}, // LDRSH +}; +const char *LoadStoreNames[] = { + "STR", + "LDR", + "STRB", + "LDRB", + "STRH", + "LDRH", + "LDRSB", + "LDRSH", +}; -void ARMXEmitter::LDR (ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x41, src, dest, op);} -void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op) +void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool RegAdd) { - u8 Imm = op.Imm8(); - Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F)); -} -void ARMXEmitter::LDRSH(ARMReg dest, ARMReg src, Operand2 op) -{ - u8 Imm = op.Imm8(); - Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xF << 4) | (Imm & 0x0F)); -} -void ARMXEmitter::LDRB(ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x45, src, dest, op);} -void ARMXEmitter::LDRSB(ARMReg dest, ARMReg src, Operand2 op) -{ - u8 Imm = op.Imm8(); - Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xD << 4) | (Imm & 0x0F)); + s32 op = LoadStoreOps[Op][Rm.GetType()]; // Type always decided by last operand + u32 Data; + + // Qualcomm chipsets get /really/ angry if you don't use index, even if the offset is zero. + // Some of these encodings require Index at all times anyway. Doesn't really matter. + // bool Index = op2 != 0 ? true : false; + bool Index = true; + bool Add = false; + + // Special Encoding + bool SpecialOp = false; + bool Half = false; + bool SignedLoad = false; + + if (op == -1) + _assert_msg_(DYNA_REC, false, "%s does not support %d", LoadStoreNames[Op], Rm.GetType()); + + switch (Op) + { + case 4: // STRH + SpecialOp = true; + Half = true; + SignedLoad = false; + break; + case 5: // LDRH + SpecialOp = true; + Half = true; + SignedLoad = false; + break; + case 6: // LDRSB + SpecialOp = true; + Half = false; + SignedLoad = true; + break; + case 7: // LDRSH + SpecialOp = true; + Half = true; + SignedLoad = true; + break; + } + switch (Rm.GetType()) + { + case TYPE_IMM: + { + s32 Temp = (s32)Rm.Value; + Data = abs(Temp); + // The offset is encoded differently on this one. + if (SpecialOp) + Data = (Data & 0xF0 << 4) | (Data & 0xF); + if (Temp >= 0) Add = true; + } + break; + case TYPE_REG: + case TYPE_IMMSREG: + if (!SpecialOp) + { + Data = Rm.GetData(); + Add = RegAdd; + break; + } + default: + // RSR not supported for any of these + // We already have the warning above + BKPT(0x2); + return; + break; + } + if (SpecialOp) + { + // Add SpecialOp things + Data = (0x5 << 4) | (SignedLoad << 6) | (Half << 5) | Data; + } + Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data); } -void ARMXEmitter::LDR (ARMReg dest, ARMReg base, Operand2 op2, bool Index, bool Add) -{ - Write32(condition | (0x61 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | op2.IMMSR()); -} -void ARMXEmitter::LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x61 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | offset); -} -void ARMXEmitter::LDRH (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x01 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | (0xB << 4) | offset); -} -void ARMXEmitter::LDRSH(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x01 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | (0xF << 4) | offset); -} -void ARMXEmitter::LDRB (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x65 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | offset); -} -void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) -{ - Write32(condition | (0x01 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | (0xD << 4) | offset); -} -void ARMXEmitter::LDRLIT (ARMReg dest, u32 offset, bool Add) { Write32(condition | 0x05 << 24 | Add << 23 | 0x1F << 16 | dest << 12 | offset);} +void ARMXEmitter::LDR (ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(1, dest, base, op2, RegAdd);} +void ARMXEmitter::LDRB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(3, dest, base, op2, RegAdd);} +void ARMXEmitter::LDRH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(5, dest, base, op2, RegAdd);} +void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(6, dest, base, op2, RegAdd);} +void ARMXEmitter::LDRSH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(7, dest, base, op2, RegAdd);} +void ARMXEmitter::STR (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(0, result, base, op2, RegAdd);} +void ARMXEmitter::STRH (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(4, result, base, op2, RegAdd);} +void ARMXEmitter::STRB (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(2, result, base, op2, RegAdd);} void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList) { diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index d68a2390ad..9fbe8c5d4d 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -352,7 +352,7 @@ private: u32 condition; std::vector currentLitPool; - void WriteStoreOp(u32 op, ARMReg src, ARMReg dest, Operand2 op2); + void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd); void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList); void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2); void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2); @@ -495,28 +495,14 @@ public: void MRS (ARMReg dest); // Memory load/store operations - void LDR (ARMReg dest, ARMReg src, Operand2 op2 = 0); - void LDRH (ARMReg dest, ARMReg src, Operand2 op2 = 0); - void LDRSH(ARMReg dest, ARMReg src, Operand2 op2 = 0); - void LDRB (ARMReg dest, ARMReg src, Operand2 op2 = 0); - void LDRSB(ARMReg dest, ARMReg src, Operand2 op2 = 0); - // Offset adds to the base register in LDR - void LDR (ARMReg dest, ARMReg base, Operand2 op2, bool Index, bool Add); - void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); - void LDRH (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); - void LDRSH(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); - void LDRB (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); - void LDRSB(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); - void LDRLIT(ARMReg dest, u32 offset, bool Add); - - void STR (ARMReg result, ARMReg base, Operand2 op2 = 0); - void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0); - void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0); - // Offset adds on to the destination register in STR - void STR (ARMReg result, ARMReg base, Operand2 op2, bool Index, bool Add); - void STR (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add); - void STRH (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add); - void STRB (ARMReg result, ARMReg base, ARMReg offset, bool Index, bool Add); + void LDR (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void LDRB (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void LDRH (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void LDRSB(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void LDRSH(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void STR (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); + void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true); void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); diff --git a/Core/MIPS/ARM/ArmAsm.cpp b/Core/MIPS/ARM/ArmAsm.cpp index 9ea153b522..5d479ce18f 100644 --- a/Core/MIPS/ARM/ArmAsm.cpp +++ b/Core/MIPS/ARM/ArmAsm.cpp @@ -157,14 +157,14 @@ void Jit::GenerateFixedCode() LDR(R0, CTXREG, offsetof(MIPSState, pc)); BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - LDR(R0, R11, R0, true, true); + LDR(R0, R11, R0); AND(R1, R0, Operand2(0xFC, 4)); // rotation is to the right, in 2-bit increments. BIC(R0, R0, Operand2(0xFC, 4)); CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 4)); SetCC(CC_EQ); // IDEA - we have 26 bits, why not just use offsets from base of code? // Another idea: Shift the bloc number left by two in the op, this would let us do - // LDR(R0, R9, R0, true, true); here, replacing the next instructions. + // LDR(R0, R9, R0); here, replacing the next instructions. ADD(R0, R9, Operand2(R0, ST_LSL, 2)); LDR(R0, R0); B(R0); diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index 12a9117959..e8c7a4a4fb 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -124,15 +124,15 @@ namespace MIPSComp switch (o) { // Load - case 35: LDR (gpr.R(rt), R11, R0, true, true); break; - case 37: LDRH (gpr.R(rt), R11, R0, true, true); break; - case 33: LDRSH(gpr.R(rt), R11, R0, true, true); break; - case 36: LDRB (gpr.R(rt), R11, R0, true, true); break; - case 32: LDRSB(gpr.R(rt), R11, R0, true, true); break; + case 35: LDR (gpr.R(rt), R11, R0); break; + case 37: LDRH (gpr.R(rt), R11, R0); break; + case 33: LDRSH(gpr.R(rt), R11, R0); break; + case 36: LDRB (gpr.R(rt), R11, R0); break; + case 32: LDRSB(gpr.R(rt), R11, R0); break; // Store - case 43: STR (gpr.R(rt), R11, R0, true, true); break; - case 41: STRH (gpr.R(rt), R11, R0, true, true); break; - case 40: STRB (gpr.R(rt), R11, R0, true, true); break; + case 43: STR (gpr.R(rt), R11, R0); break; + case 41: STRH (gpr.R(rt), R11, R0); break; + case 40: STRB (gpr.R(rt), R11, R0); break; } } else { Comp_Generic(op); @@ -179,26 +179,26 @@ namespace MIPSComp // Load case 34: AND(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift); - LDR(R0, R11, R0, true, true); + LDR(R0, R11, R0); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift)); break; case 38: AND(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift)); - LDR(R0, R11, R0, true, true); + LDR(R0, R11, R0); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift)); break; // Store case 42: - LDR(R1, R11, R0, true, true); + LDR(R1, R11, R0); AND(R1, R1, 0xffffff00 << shift); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSR, 24 - shift)); - STR(R1, R11, R0, true, true); + STR(R1, R11, R0); break; case 46: - LDR(R1, R11, R0, true, true); + LDR(R1, R11, R0); AND(R1, R1, 0x00ffffff >> (24 - shift)); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSL, shift)); - STR(R1, R11, R0, true, true); + STR(R1, R11, R0); break; } } else { diff --git a/native b/native index 7f18e1faab..1ec67d5ac2 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 7f18e1faabd18381cf4a8ab85ff24bb6b9b7f89d +Subproject commit 1ec67d5ac2e52d2a1bc02b92645fefa78fca1e8b