mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
ARM64: Some FP work.
This commit is contained in:
1 parent
d2c746dd64
commit
0922db6062
10 files changed
+267
-55
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user