ARM64: Some FP work.

This commit is contained in:
Henrik Rydgard committed 2015-04-06 18:13:11 +02:00
1 parent d2c746dd64
commit 0922db6062
10 files changed
+267 -55

No files matched your search

+5
View File
@@ -2573,6 +2573,11 @@ void ARM64FloatEmitter::FNEG(ARM64Reg Rd, ARM64Reg Rn)
{
EmitScalar1Source(0, 0, IsDouble(Rd), 2, Rd, Rn);
}
void ARM64FloatEmitter::FSQRT(ARM64Reg Rd, ARM64Reg Rn)
{
EmitScalar1Source(0, 0, IsDouble(Rd), 3, Rd, Rn);
}
// Scalar - 2 Source
void ARM64FloatEmitter::FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
+1
View File
@@ -737,6 +737,7 @@ public:
// Scalar - 1 Source
void FABS(ARM64Reg Rd, ARM64Reg Rn);
void FNEG(ARM64Reg Rd, ARM64Reg Rn);
void FSQRT(ARM64Reg Rd, ARM64Reg Rn);
// Scalar - 2 Source
void FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
-2
View File
@@ -130,7 +130,6 @@ void ArmJit::Comp_FPULS(MIPSOpcode op)
VLDR(fpr.R(ft), R0, 0);
if (doCheck) {
SetJumpTarget(skip);
SetCC(CC_AL);
}
#else
VLDR(fpr.R(ft), R0, 0);
@@ -174,7 +173,6 @@ void ArmJit::Comp_FPULS(MIPSOpcode op)
VSTR(fpr.R(ft), R0, 0);
if (doCheck) {
SetJumpTarget(skip2);
SetCC(CC_AL);
}
#else
VSTR(fpr.R(ft), R0, 0);
+163 -6
View File
@@ -44,14 +44,11 @@
#define CONDITIONAL_DISABLE ;
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp
{
namespace MIPSComp {
using namespace Arm64Gen;
using namespace Arm64JitConstants;
void Arm64Jit::Comp_FPU3op(MIPSOpcode op)
{
// DISABLE;
void Arm64Jit::Comp_FPU3op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int ft = _FT;
@@ -72,7 +69,73 @@ void Arm64Jit::Comp_FPU3op(MIPSOpcode op)
void Arm64Jit::Comp_FPULS(MIPSOpcode op)
{
DISABLE;
CONDITIONAL_DISABLE;
// Surprisingly, these work fine alraedy.
s32 offset = (s16)(op & 0xFFFF);
int ft = _FT;
MIPSGPReg rs = _RS;
// u32 addr = R(rs) + offset;
// logBlocks = 1;
bool doCheck = false;
switch (op >> 26) {
case 49: //FI(ft) = Memory::Read_U32(addr); break; //lwc1
fpr.SpillLock(ft);
fpr.MapReg(ft, MAP_NOINIT | MAP_DIRTY);
if (gpr.IsImm(rs)) {
u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
gpr.SetRegImm(SCRATCH1_64, (uintptr_t)(Memory::base + addr));
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
SetScratch1ToEffectiveAddress(rs, offset);
} else {
SetCCAndSCRATCH1ForSafeAddress(rs, offset, SCRATCH2);
doCheck = true;
}
ADD(SCRATCH1_64, SCRATCH1_64, MEMBASEREG);
}
FixupBranch skip;
if (doCheck) {
skip = B(CC_EQ);
}
LDR(INDEX_UNSIGNED, fpr.R(ft), SCRATCH1_64, 0);
if (doCheck) {
SetJumpTarget(skip);
}
fpr.ReleaseSpillLocksAndDiscardTemps();
break;
case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1
fpr.MapReg(ft);
if (gpr.IsImm(rs)) {
u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
gpr.SetRegImm(SCRATCH1_64, addr + (uintptr_t)(Memory::base));
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
SetScratch1ToEffectiveAddress(rs, offset);
} else {
SetCCAndSCRATCH1ForSafeAddress(rs, offset, SCRATCH2);
doCheck = true;
}
ADD(SCRATCH1_64, SCRATCH1_64, MEMBASEREG);
}
FixupBranch skip2;
if (doCheck) {
skip2 = B(CC_EQ);
}
STR(INDEX_UNSIGNED, fpr.R(ft), SCRATCH1_64, 0);
if (doCheck) {
SetJumpTarget(skip2);
}
break;
default:
Comp_Generic(op);
return;
}
}
void Arm64Jit::Comp_FPUComp(MIPSOpcode op) {
@@ -80,7 +143,101 @@ void Arm64Jit::Comp_FPUComp(MIPSOpcode op) {
}
void Arm64Jit::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// These don't work for some reason.
DISABLE;
int fs = _FS;
int fd = _FD;
// TODO: Most of these mishandle infinity/NAN.
// Maybe we can try to track per reg if they *could* be INF/NAN to optimize out?
switch (op & 0x3f) {
case 4: //F(fd) = sqrtf(F(fs)); break; //sqrt
fpr.MapDirtyIn(fd, fs);
fp.FSQRT(fpr.R(fd), fpr.R(fs));
break;
case 5: //F(fd) = fabsf(F(fs)); break; //abs
fpr.MapDirtyIn(fd, fs);
fp.FABS(fpr.R(fd), fpr.R(fs));
break;
case 6: //F(fd) = F(fs); break; //mov
fpr.MapDirtyIn(fd, fs);
fp.FMOV(fpr.R(fd), fpr.R(fs));
break;
case 7: //F(fd) = -F(fs); break; //neg
fpr.MapDirtyIn(fd, fs);
fp.FNEG(fpr.R(fd), fpr.R(fs));
break;
/*
case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
RestoreRoundingMode();
fpr.MapDirtyIn(fd, fs);
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
break;
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
fpr.MapDirtyIn(fd, fs);
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
break;
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
{
RestoreRoundingMode();
fpr.MapDirtyIn(fd, fs);
VMRS(SCRATCHREG2);
// Assume we're always in round-to-nearest mode.
ORR(SCRATCHREG1, SCRATCHREG2, AssumeMakeOperand2(1 << 22));
VMSR(SCRATCHREG1);
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
// Set the rounding mode back. TODO: Keep it? Dirty?
VMSR(SCRATCHREG2);
break;
}
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
{
RestoreRoundingMode();
fpr.MapDirtyIn(fd, fs);
VMRS(SCRATCHREG2);
// Assume we're always in round-to-nearest mode.
ORR(SCRATCHREG1, SCRATCHREG2, AssumeMakeOperand2(2 << 22));
VMSR(SCRATCHREG1);
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
// Set the rounding mode back. TODO: Keep it? Dirty?
VMSR(SCRATCHREG2);
break;
}
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
fpr.MapDirtyIn(fd, fs);
VCVT(fpr.R(fd), fpr.R(fs), TO_FLOAT | IS_SIGNED);
break;
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
fpr.MapDirtyIn(fd, fs);
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
break;
*/
default:
DISABLE;
}
}
void Arm64Jit::Comp_mxc1(MIPSOpcode op)
+1 -1
View File
@@ -68,7 +68,7 @@ bool Arm64RegCache::IsMapped(MIPSGPReg mipsReg) {
return mr[mipsReg].loc == ML_ARMREG;
}
void Arm64RegCache::SetRegImm(ARM64Reg reg, u32 imm) {
void Arm64RegCache::SetRegImm(ARM64Reg reg, u64 imm) {
// On ARM64, at least Cortex A57, good old MOVT/MOVW (MOVK in 64-bit) is really fast.
emit_->MOVI2R(reg, imm);
}
+1 -1
View File
@@ -106,7 +106,7 @@ public:
bool IsImm(MIPSGPReg reg) const;
u32 GetImm(MIPSGPReg reg) const;
// Optimally set a register to an imm value (possibly using another register.)
void SetRegImm(Arm64Gen::ARM64Reg reg, u32 imm);
void SetRegImm(Arm64Gen::ARM64Reg reg, u64 imm);
// Returns an ARM register containing the requested MIPS register.
Arm64Gen::ARM64Reg MapReg(MIPSGPReg reg, int mapFlags = 0);
+32 -32
View File
@@ -166,7 +166,7 @@ const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ...............
INSTR("cache", JITFUNC(Comp_Cache), Dis_Cache, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR),
//48
INSTR("ll", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD),
INSTR("lwc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|MEMTYPE_FLOAT),
INSTR("lwc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|MEMTYPE_FLOAT|IS_FPU),
INSTR("lv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT),
INVALID, // HIT THIS IN WIPEOUT
ENCODING(VFPU4Jump),
@@ -175,7 +175,7 @@ const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ...............
ENCODING(VFPU5),
//56
INSTR("sc", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_IMM16|IN_RS_ADDR|IN_OTHER|IN_RT|OUT_RT|OUT_MEM|MEMTYPE_WORD),
INSTR("swc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_MEM|MEMTYPE_FLOAT), //copU
INSTR("swc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_MEM|MEMTYPE_FLOAT|IS_FPU), //copU
INSTR("sv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_MEM|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT),
INVALID,
//60
@@ -466,20 +466,20 @@ const MIPSInstruction tableCop1BC[32] = // 010001 01000 xxxxx ................
const MIPSInstruction tableCop1S[64] = // 010001 10000 ..... ..... ..... xxxxxx
{
INSTR("add.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT),
INSTR("sub.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT),
INSTR("mul.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT),
INSTR("div.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT),
INSTR("sqrt.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("abs.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("mov.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("neg.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("add.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT|IS_FPU),
INSTR("sub.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT|IS_FPU),
INSTR("mul.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT|IS_FPU),
INSTR("div.s", JITFUNC(Comp_FPU3op), Dis_FPU3op, Int_FPU3op, OUT_FD|IN_FS|IN_FT|IS_FPU),
INSTR("sqrt.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("abs.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("mov.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("neg.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
//8
INVALID, INVALID, INVALID, INVALID,
INSTR("round.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("trunc.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("ceil.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("floor.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("round.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("trunc.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("ceil.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INSTR("floor.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
//16
INVALID_X_8,
//24
@@ -487,29 +487,29 @@ const MIPSInstruction tableCop1S[64] = // 010001 10000 ..... ..... ..... xxxxxx
//32
INVALID, INVALID, INVALID, INVALID,
//36
INSTR("cvt.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("cvt.w.s", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INVALID,
INSTR("dis.int", JITFUNC(Comp_Generic), Dis_Generic, Int_Interrupt, 0),
INVALID,
//40
INVALID_X_8,
//48 - 010001 10000 ..... ..... ..... 11xxxx
INSTR("c.f", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.un", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.eq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ueq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.olt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ult", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ole", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ule", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.sf", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ngle",JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.seq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ngl", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.lt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.nge", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.le", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.ngt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG),
INSTR("c.f", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG|IS_FPU),
INSTR("c.un", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.eq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ueq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.olt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ult", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ole", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ule", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.sf", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG|IS_FPU),
INSTR("c.ngle",JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.seq", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ngl", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.lt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.nge", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.le", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
INSTR("c.ngt", JITFUNC(Comp_FPUComp), Dis_FPUComp, Int_FPUComp, IN_FS|IN_FT|OUT_FPUFLAG|IS_FPU),
};
const MIPSInstruction tableCop1W[64] = // 010001 10100 ..... ..... ..... xxxxxx
@@ -522,7 +522,7 @@ const MIPSInstruction tableCop1W[64] = // 010001 10100 ..... ..... ..... xxxxxx
//24
INVALID_X_8,
//32
INSTR("cvt.s.w", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS),
INSTR("cvt.s.w", JITFUNC(Comp_FPU2op), Dis_FPU2op, Int_FPU2op, OUT_FD|IN_FS|IS_FPU),
INVALID, INVALID, INVALID,
//36
INVALID,
+44 -6
View File
@@ -143,7 +143,7 @@ static void LoadStore(uint32_t w, uint64_t addr, Instruction *instr) {
int option = (w >> 13) & 0x7;
int opc = (w >> 22) & 0x3;
char r = size == 3 ? 'x' : 'w';
const char *opname[4] = { "str", "ldr", "(unk)", "(unk)" };
const char *opname[4] = { "str", "ldr", "str", "ldr" };
const char *sizeSuffix[4] = { "b", "w", "", "" };
if (((w >> 21) & 1) == 1) {
@@ -152,13 +152,26 @@ static void LoadStore(uint32_t w, uint64_t addr, Instruction *instr) {
return;
} else if (((w >> 27) & 7) == 7) {
int V = (w >> 26) & 1;
bool index_unsigned = ((w >> 24) & 3) == 1;
int imm12 = SignExtend12((w >> 10) & 0xFFF) << size;
if (V == 0) {
bool index_unsigned = ((w >> 24) & 3) == 1;
int imm12 = SignExtend12((w >> 10) & 0xFFF) << size;
// Integer type
if (index_unsigned) {
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, [x%d + %d]", opname[opc], sizeSuffix[size], r, Rt, Rn, imm12);
return;
}
} else {
// FP/Vector type
char vr = '!';
if (opc == 3 && size == 0) {
vr = 'q';
} else {
vr = "bhsd"[size];
}
if (index_unsigned) {
snprintf(instr->text, sizeof(instr->text), "%s %c%d, [x%d + %d]", opname[opc], vr, Rt, Rn, imm12);
return;
}
}
}
snprintf(instr->text, sizeof(instr->text), "(LS %08x)", w);
@@ -196,10 +209,13 @@ static void DataProcessingRegister(uint32_t w, uint64_t addr, Instruction *instr
// Logical (shifted register)
int shift = (w >> 22) & 0x3;
int imm6 = (w >> 10) & 0x3f;
int N = (w >> 20) & 1;
int N = (w >> 21) & 1;
int opc = (((w >> 29) & 3) << 1) | N;
const char *opnames[8] = { "and", "bic", "orr", "orn", "eor", "eon", "ands", "bics" };
if (imm6 == 0) {
if (opc == 3 && Rn == 31) {
// Special case for MOV (which is constructed from an ORR)
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d", opnames[opc], r, Rd, r, Rm);
} else if (imm6 == 0) {
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d", opnames[opc], r, Rd, r, Rn, r, Rm);
} else {
snprintf(instr->text, sizeof(instr->text), "(logical-shifted-register %08x", w);
@@ -214,7 +230,29 @@ static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) {
}
static void FPandASIMD2(uint32_t w, uint64_t addr, Instruction *instr) {
snprintf(instr->text, sizeof(instr->text), "(FP2 %08x)", w);
int Rd = w & 0x1f;
int Rn = (w >> 5) & 0x1f;
int Rm = (w >> 16) & 0x1f;
int type = (w >> 22) & 0x3;
if ((w >> 24) == 0x1E) {
if (((w >> 10) & 0x39f) == 0x810) {
const char *opnames[4] = { "fmov", "fabs", "fneg", "fsqrt" };
int opc = (w >> 15) & 0x3;
snprintf(instr->text, sizeof(instr->text), "%s !%d, !%d (%08x)", opnames[opc], Rd, Rn, w);
} else if (((w >> 10) & 3) == 2) {
// FP data-proc (2 source)
int opc = (w >> 12) & 0xf;
if (type == 0 || type == 1) {
const char *opnames[9] = { "fmul", "fdiv", "fadd", "fsub", "fmax", "fmin", "fmaxnm", "fminnm", "fnmul" };
char r = 's';
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d", opnames[opc], r, Rd, r, Rn, r, Rm);
} else {
snprintf(instr->text, sizeof(instr->text), "(FP2 %08x)", w);
}
}
} else {
snprintf(instr->text, sizeof(instr->text), "(FP2 %08x)", w);
}
}
static void DisassembleInstruction(uint32_t w, uint64_t addr, Instruction *instr) {
+17 -7
View File
@@ -565,7 +565,8 @@ void JitCompareScreen::CreateViews() {
leftColumn->Add(new Choice(de->T("Prev")))->OnClick.Handle(this, &JitCompareScreen::OnPrevBlock);
leftColumn->Add(new Choice(de->T("Next")))->OnClick.Handle(this, &JitCompareScreen::OnNextBlock);
leftColumn->Add(new Choice(de->T("Random")))->OnClick.Handle(this, &JitCompareScreen::OnRandomBlock);
leftColumn->Add(new Choice(de->T("Random VFPU")))->OnClick.Handle(this, &JitCompareScreen::OnRandomVFPUBlock);
leftColumn->Add(new Choice(de->T("FPU")))->OnClick.Handle(this, &JitCompareScreen::OnRandomFPUBlock);
leftColumn->Add(new Choice(de->T("VFPU")))->OnClick.Handle(this, &JitCompareScreen::OnRandomVFPUBlock);
leftColumn->Add(new Choice(d->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
blockName_ = leftColumn->Add(new TextView(de->T("No block")));
blockAddr_ = leftColumn->Add(new TextEdit("", "", new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
@@ -698,24 +699,34 @@ UI::EventReturn JitCompareScreen::OnRandomBlock(UI::EventParams &e) {
}
UI::EventReturn JitCompareScreen::OnRandomVFPUBlock(UI::EventParams &e) {
OnRandomBlock(IS_VFPU);
return UI::EVENT_DONE;
}
UI::EventReturn JitCompareScreen::OnRandomFPUBlock(UI::EventParams &e) {
OnRandomBlock(IS_FPU);
return UI::EVENT_DONE;
}
void JitCompareScreen::OnRandomBlock(int flag) {
if (!MIPSComp::jit) {
return UI::EVENT_DONE;
return;
}
JitBlockCache *blockCache = MIPSComp::jit->GetBlockCache();
int numBlocks = blockCache->GetNumBlocks();
if (numBlocks > 0) {
bool anyVFPU = false;
bool anyWanted = false;
int tries = 0;
while (!anyVFPU && tries < 10000) {
while (!anyWanted && tries < 10000) {
currentBlock_ = rand() % numBlocks;
const JitBlock *b = blockCache->GetBlock(currentBlock_);
for (u32 addr = b->originalAddress; addr <= b->originalAddress + b->originalSize; addr += 4) {
MIPSOpcode opcode = Memory::Read_Instruction(addr);
if (MIPSGetInfo(opcode) & IS_VFPU) {
if (MIPSGetInfo(opcode) & flag) {
char temp[256];
MIPSDisAsm(opcode, addr, temp);
// INFO_LOG(HLE, "Stopping VFPU instruction: %s", temp);
anyVFPU = true;
anyWanted = true;
break;
}
}
@@ -723,7 +734,6 @@ UI::EventReturn JitCompareScreen::OnRandomVFPUBlock(UI::EventParams &e) {
}
}
UpdateDisasm();
return UI::EVENT_DONE;
}
+3
View File
@@ -120,7 +120,10 @@ public:
private:
void UpdateDisasm();
UI::EventReturn OnRandomBlock(UI::EventParams &e);
UI::EventReturn OnRandomFPUBlock(UI::EventParams &e);
UI::EventReturn OnRandomVFPUBlock(UI::EventParams &e);
void OnRandomBlock(int flag);
UI::EventReturn OnCurrentBlock(UI::EventParams &e);
UI::EventReturn OnSelectBlock(UI::EventParams &e);
UI::EventReturn OnPrevBlock(UI::EventParams &e);