From 0922db6062dbcccecb5b2ea7bcc181337f6d7efb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 17 Mar 2015 00:54:56 +0100 Subject: [PATCH] ARM64: Some FP work. --- Common/Arm64Emitter.cpp | 5 + Common/Arm64Emitter.h | 1 + Core/MIPS/ARM/ArmCompFPU.cpp | 2 - Core/MIPS/ARM64/Arm64CompFPU.cpp | 169 ++++++++++++++++++++++++++++-- Core/MIPS/ARM64/Arm64RegCache.cpp | 2 +- Core/MIPS/ARM64/Arm64RegCache.h | 2 +- Core/MIPS/MIPSTables.cpp | 64 +++++------ Core/Util/DisArm64.cpp | 50 +++++++-- UI/DevScreens.cpp | 24 +++-- UI/DevScreens.h | 3 + 10 files changed, 267 insertions(+), 55 deletions(-) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 850269cdac..99fec9cfd4 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -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) diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index e996eca329..e7576966e1 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -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); diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index e10de3955d..977a1d54c3 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -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); diff --git a/Core/MIPS/ARM64/Arm64CompFPU.cpp b/Core/MIPS/ARM64/Arm64CompFPU.cpp index f37ade6581..2707603798 100644 --- a/Core/MIPS/ARM64/Arm64CompFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompFPU.cpp @@ -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) diff --git a/Core/MIPS/ARM64/Arm64RegCache.cpp b/Core/MIPS/ARM64/Arm64RegCache.cpp index 97c54b6fd3..e401a94055 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.cpp +++ b/Core/MIPS/ARM64/Arm64RegCache.cpp @@ -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); } diff --git a/Core/MIPS/ARM64/Arm64RegCache.h b/Core/MIPS/ARM64/Arm64RegCache.h index d89833890d..c66149e5b9 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.h +++ b/Core/MIPS/ARM64/Arm64RegCache.h @@ -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); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 07b8bd18dd..1f86b0abc5 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -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, diff --git a/Core/Util/DisArm64.cpp b/Core/Util/DisArm64.cpp index d0052a0e60..29183cdbb5 100644 --- a/Core/Util/DisArm64.cpp +++ b/Core/Util/DisArm64.cpp @@ -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) { diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 9f68026f4e..23375b801f 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -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(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; } diff --git a/UI/DevScreens.h b/UI/DevScreens.h index 2ef2f3c33b..d527cd922b 100644 --- a/UI/DevScreens.h +++ b/UI/DevScreens.h @@ -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);