mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 01:00:01 +00:00
ARMJIT: Implement VLDM/VSTM load/store combinations and use in armjit. Also add them to disassembler.
This commit is contained in:
parent
8276cac6a4
commit
30a6a5d10f
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user