Really clean up all the emitter loadstores on ARM. If a ARM device supports VFPv4, then it supports IDIVA, so handle that in CPUDetect.

This commit is contained in:
Ryan Houdek 2013-03-14 01:50:38 +00:00
parent 202e2fa5c8
commit c93f7760ce
4 changed files with 28 additions and 108 deletions

View File

@ -154,8 +154,10 @@ std::string CPUInfo::Summarize()
if (bVFPv3) sum += ", VFPv3"; if (bVFPv3) sum += ", VFPv3";
if (bTLS) sum += ", TLS"; if (bTLS) sum += ", TLS";
if (bVFPv4) sum += ", VFPv4"; if (bVFPv4) sum += ", VFPv4";
if (bIDIVa) sum += ", IDIVa"; // On some buggy kernels(Qualcomm) they show that they support VFPv4 but not IDIVa
if (bIDIVt) sum += ", IDIVt"; // All VFPv4 CPUs will support IDIVa
if (bIDIVa || bVFPv4) sum += ", IDIVa";
if (bIDIVt || bVFPv4) sum += ", IDIVt";
return sum; return sum;
} }

View File

@ -176,7 +176,7 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
} else { } else {
// Use literal pool for ARMv6. // Use literal pool for ARMv6.
AddNewLit(val); AddNewLit(val);
LDRLIT(reg, 0, 0); // To be backpatched later LDR(reg, _PC); // To be backpatched later
} }
} }
} }
@ -608,39 +608,6 @@ 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 src, ARMReg dest, s16 op2)
{
// Qualcomm chipsets get /really/ angry if you don't use index, even if the offset is zero.
// bool Index = op2 != 0 ? true : false;
bool Index = true;
bool Add = op2 >= 0 ? true : false;
u32 imm = abs(op2);
Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (src << 16) | (dest << 12) | imm);
}
void ARMXEmitter::STR (ARMReg result, ARMReg base, s16 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, s16 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) void ARMXEmitter::LDREX(ARMReg dest, ARMReg base)
{ {
Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F); Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F);
@ -681,7 +648,7 @@ const char *LoadStoreNames[] = { "STR",
"LDRSH", "LDRSH",
}; };
void ARMXEmitter::WriteNewStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd) void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool RegAdd)
{ {
s32 op = LoadStoreOps[Op][Rm.GetType()]; // Type always decided by last operand s32 op = LoadStoreOps[Op][Rm.GetType()]; // Type always decided by last operand
u32 Data; u32 Data;
@ -726,12 +693,14 @@ void ARMXEmitter::WriteNewStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bo
switch (Rm.GetType()) switch (Rm.GetType())
{ {
case TYPE_IMM: case TYPE_IMM:
{
s32 Temp = (s32)Rm.Value; s32 Temp = (s32)Rm.Value;
Data = abs(Temp); Data = abs(Temp);
// The offset is encoded differently on this one. // The offset is encoded differently on this one.
if (SpecialOp) if (SpecialOp)
Data = (Data & 0xF0 << 4) | (Data & 0xF); Data = (Data & 0xF0 << 4) | (Data & 0xF);
if (Temp >= 0) ImmAdd = true; if (Temp >= 0) Add = true;
}
break; break;
case TYPE_REG: case TYPE_REG:
case TYPE_IMMSREG: case TYPE_IMMSREG:
@ -756,49 +725,14 @@ void ARMXEmitter::WriteNewStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bo
Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data); Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data);
} }
void ARMXEmitter::LDR (ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x41, src, dest, op);} void ARMXEmitter::LDR (ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(1, dest, base, op2, RegAdd);}
void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op) 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);}
u8 Imm = op.Imm8(); void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(6, dest, base, op2, RegAdd);}
Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F)); 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::LDRSH(ARMReg dest, ARMReg src, Operand2 op) 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);}
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, s16 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));
}
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::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList) void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList)
{ {

View File

@ -352,9 +352,7 @@ private:
u32 condition; u32 condition;
std::vector<LiteralPool> currentLitPool; std::vector<LiteralPool> currentLitPool;
void WriteStoreOp(u32 op, ARMReg src, ARMReg dest, s16 op2); void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
void WriteNewStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
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);
@ -497,28 +495,14 @@ public:
void MRS (ARMReg dest); void MRS (ARMReg dest);
// Memory load/store operations // Memory load/store operations
void LDR (ARMReg dest, ARMReg src, s16 op2 = 0); void LDR (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRH (ARMReg dest, ARMReg src, Operand2 op2 = 0); void LDRB (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRSH(ARMReg dest, ARMReg src, Operand2 op2 = 0); void LDRH (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRB (ARMReg dest, ARMReg src, s16 op2 = 0); void LDRSB(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDRSB(ARMReg dest, ARMReg src, Operand2 op2 = 0); void LDRSH(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
// Offset adds to the base register in LDR void STR (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDR (ARMReg dest, ARMReg base, Operand2 op2, bool Index, bool Add); void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
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, s16 op2 = 0);
void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0);
void STRB (ARMReg result, ARMReg base, s16 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 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, ...);

View File

@ -72,7 +72,7 @@ void JitArmAsmRoutineManager::Generate()
MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache()); MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache());
// Confirmed That this loads the base iCache Location correctly 08-04-12 // Confirmed That this loads the base iCache Location correctly 08-04-12
LDR(R12, R14, R12, true, true); // R12 contains iCache[PC & JIT_ICACHE_MASK] here LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
// R12 Confirmed this is the correct iCache Location loaded. // R12 Confirmed this is the correct iCache Location loaded.
TST(R12, 0xFC); // Test to see if it is a JIT block. TST(R12, 0xFC); // Test to see if it is a JIT block.
@ -82,7 +82,7 @@ void JitArmAsmRoutineManager::Generate()
// LDR R14 right here to get CodePointers()[0] pointer. // LDR R14 right here to get CodePointers()[0] pointer.
REV(R12, R12); // Reversing this gives us our JITblock. REV(R12, R12); // Reversing this gives us our JITblock.
LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
LDR(R14, R14, R12, true, true); // Load the block address in to R14 LDR(R14, R14, R12); // Load the block address in to R14
B(R14); B(R14);