Sonic's ArmEmitter changes (cross-project merge from Dolphin)

This commit is contained in:
Sacha 2013-03-14 12:47:29 +10:00
parent 79823fa049
commit 529803e429
6 changed files with 136 additions and 113 deletions

View File

@ -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;
}

View File

@ -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)
{

View File

@ -352,7 +352,7 @@ private:
u32 condition;
std::vector<LiteralPool> 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, ...);

View File

@ -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);

View File

@ -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 {

2
native

@ -1 +1 @@
Subproject commit 7f18e1faabd18381cf4a8ab85ff24bb6b9b7f89d
Subproject commit 1ec67d5ac2e52d2a1bc02b92645fefa78fca1e8b