ARMJIT: Implement VLDM/VSTM load/store combinations and use in armjit. Also add them to disassembler.

This commit is contained in:
Sacha 2014-03-07 02:52:36 +10:00
parent 8276cac6a4
commit 30a6a5d10f
4 changed files with 123 additions and 19 deletions

View File

@ -1026,6 +1026,11 @@ void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegLi
{
Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList);
}
void ARMXEmitter::WriteVRegStoreOp(u32 op, ARMReg Rn, bool Double, bool WriteBack, ARMReg Vd, u8 numregs)
{
ARMReg Dest = SubBase(Vd);
Write32(condition | (op << 20) | (WriteBack << 21) | (Rn << 16) | ((Dest & 0x1) << 22) | ((Dest & 0x1E) << 11) | ((0xA | Double) << 8) | (numregs << Double) );
}
void ARMXEmitter::STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
{
u16 RegList = 0;
@ -1287,6 +1292,26 @@ void ARMXEmitter::VCMPE(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(13, Vd, D4, Vm); }
void ARMXEmitter::VCMP(ARMReg Vd){ WriteVFPDataOp(12, Vd, D5, D0); }
void ARMXEmitter::VCMPE(ARMReg Vd){ WriteVFPDataOp(13, Vd, D5, D0); }
void ARMXEmitter::VLDMIA(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs)
{
WriteVRegStoreOp(0x80 | 0x40 | 0x8 | 1, dest, false, WriteBack, firstreg, numregs);
}
void ARMXEmitter::VSTMIA(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs)
{
WriteVRegStoreOp(0x80 | 0x40 | 0x8, dest, false, WriteBack, firstreg, numregs);
}
void ARMXEmitter::VLDMDB(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs)
{
WriteVRegStoreOp(0x80 | 0x040 | 0x10 | 1, dest, false, WriteBack, firstreg, numregs);
}
void ARMXEmitter::VSTMDB(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs)
{
WriteVRegStoreOp(0x80 | 0x040 | 0x10, dest, false, WriteBack, firstreg, numregs);
}
void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset)
{
_assert_msg_(JIT, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");

View File

@ -392,6 +392,7 @@ private:
void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
void WriteVRegStoreOp(u32 op, ARMReg dest, bool Double, bool WriteBack, ARMReg firstreg, u8 numregs);
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);
@ -584,6 +585,10 @@ public:
void VSUB(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
// VFP Only
void VLDMIA(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs);
void VSTMIA(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs);
void VLDMDB(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs);
void VSTMDB(ARMReg dest, bool WriteBack, ARMReg firstreg, int numregs);
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
void VSTR(ARMReg Src, ARMReg Base, s16 offset);
void VCMP(ARMReg Vd, ARMReg Vm);

View File

@ -364,16 +364,32 @@ namespace MIPSComp
skip = B_CC(CC_EQ);
}
for (int i = 0; i < 4; i++)
VLDR(fpr.V(vregs[i]), R0, i * 4);
bool consecutive = true;
for (int i = 0; i < 3 && consecutive; i++)
if ((fpr.V(vregs[i]) + 1) != fpr.V(vregs[i+1]))
consecutive = false;
if (consecutive) {
VLDMIA(R0, false, fpr.V(vregs[0]), 4);
} else {
for (int i = 0; i < 4; i++)
VLDR(fpr.V(vregs[i]), R0, i * 4);
}
if (doCheck) {
SetJumpTarget(skip);
SetCC(CC_AL);
}
#else
for (int i = 0; i < 4; i++)
VLDR(fpr.V(vregs[i]), R0, i * 4);
bool consecutive = true;
for (int i = 0; i < 3 && consecutive; i++)
if ((fpr.V(vregs[i]) + 1) != fpr.V(vregs[i+1]))
consecutive = false;
if (consecutive) {
VLDMIA(R0, false, fpr.V(vregs[0]), 4);
} else {
for (int i = 0; i < 4; i++)
VLDR(fpr.V(vregs[i]), R0, i * 4);
}
if (doCheck) {
SetCC(CC_EQ);
@ -413,16 +429,32 @@ namespace MIPSComp
skip = B_CC(CC_EQ);
}
for (int i = 0; i < 4; i++)
VSTR(fpr.V(vregs[i]), R0, i * 4);
bool consecutive = true;
for (int i = 0; i < 3 && consecutive; i++)
if ((fpr.V(vregs[i]) + 1) != fpr.V(vregs[i+1]))
consecutive = false;
if (consecutive) {
VSTMIA(R0, false, fpr.V(vregs[0]), 4);
} else {
for (int i = 0; i < 4; i++)
VSTR(fpr.V(vregs[i]), R0, i * 4);
}
if (doCheck) {
SetJumpTarget(skip);
SetCC(CC_AL);
}
#else
for (int i = 0; i < 4; i++)
VSTR(fpr.V(vregs[i]), R0, i * 4);
bool consecutive = true;
for (int i = 0; i < 3 && consecutive; i++)
if ((fpr.V(vregs[i]) + 1) != fpr.V(vregs[i+1]))
consecutive = false;
if (consecutive) {
VSTMIA(R0, false, fpr.V(vregs[0]), 4);
} else {
for (int i = 0; i < 4; i++)
VSTR(fpr.V(vregs[i]), R0, i * 4);
}
if (doCheck) {
SetCC(CC_AL);
@ -1812,8 +1844,7 @@ namespace MIPSComp
VMOV(R0, fpr.V(sreg));
QuickCallFunction(R1, negSin ? (void *)&SinCosNegSin : (void *)&SinCos);
gpr.SetRegImm(R0, (u32)(&sincostemp[0]));
VLDR(S0, R0, 0);
VLDR(S1, R0, 4);
VLDMIA(R0, false, S0, 2);
char what[4] = {'0', '0', '0', '0'};
if (((imm >> 2) & 3) == (imm & 3)) {

View File

@ -125,18 +125,61 @@ bool DisasmVFP(uint32_t op, char *text) {
#else
const char *cond = CCFlagsStr[op >> 28];
switch ((op >> 24) & 0xF) {
case 0xD:
// VLDR/VSTR
case 0xC:
// VLDMIA/VSTMIA
{
int base = (op >> 16) & 0xF;
bool add = (op >> 23) & 1;
int freg = ((op >> 11) & 0x1E) | ((op >> 22) & 1);
int offset = (op & 0xFF) << 2;
if (!add) offset = -offset;
bool vldr = (op >> 20) & 1;
bool single_reg = ((op >> 8) & 0xF) == 10;
int freg = ((op >> 11) & 0x1E) | ((op >> 22) & 1);
int base = (op >> 16) & 0xF;
bool load = (op >> 20) & 1;
bool writeback = (op >> 21) & 1;
int numregs = op & 0xF;
bool add = (op >> 23) & 1;
if (add && writeback && load && base == 13) {
if (single_reg)
sprintf(text, "VPOP%s {s%i-s%i}", cond, freg, freg-1+numregs);
else
sprintf(text, "VPOP%s {d%i-d%i}", cond, freg, freg-1+(numregs/2));
return true;
}
if (single_reg)
sprintf(text, "%s%s r%i%s, {s%i-s%i}", load ? "VLDMIA" : "VSTMIA", cond, base, writeback ? "!":"", freg, freg-1+numregs);
else
sprintf(text, "%s%s r%i%s, {d%i-d%i}", load ? "VLDMIA" : "VSTMIA", cond, base, writeback ? "!":"", freg, freg-1+(numregs/2));
return true;
}
case 0xD:
// VLDR/VSTR/VLDMDB/VSTMDB
{
bool single_reg = ((op >> 8) & 0xF) == 10;
int freg = ((op >> 11) & 0x1E) | ((op >> 22) & 1);
int base = (op >> 16) & 0xF;
bool load = (op >> 20) & 1;
bool add = (op >> 23) & 1;
bool writeback = (op >> 21) & 1;
if (writeback) { // Multiple
int numregs = op & 0xF;
if (!add && !load && base == 13) {
if (single_reg)
sprintf(text, "VPUSH%s {s%i-s%i}", cond, freg, freg-1+numregs);
else
sprintf(text, "VPUSH%s {d%i-d%i}", cond, freg, freg-1+(numregs/2));
return true;
}
if (single_reg)
sprintf(text, "%s%s r%i, {s%i-s%i}", load ? "VLDMDB" : "VSTMDB", cond, base, freg, freg-1+numregs);
else
sprintf(text, "%s%s r%i, {d%i-d%i}", load ? "VLDMDB" : "VSTMDB", cond, base, freg, freg-1+(numregs/2));
} else {
int offset = (op & 0xFF) << 2;
if (!add) offset = -offset;
sprintf(text, "%s%s s%i, [r%i, #%i]", load ? "VLDR" : "VSTR", cond, freg, base, offset);
}
sprintf(text, "%s%s s%i, [r%i, #%i]", vldr ? "VLDR" : "VSTR", cond, freg, base, offset);
return true;
}