diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index b310b89363..99b2a40f9e 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -56,6 +56,32 @@ namespace MIPSComp { + + void Jit::SetR0ToEffectiveAddress(int rs, s16 offset) { + Operand2 op2; + if (offset) { + bool negated; + if (TryMakeOperand2_AllowNegation(offset, op2, &negated)) { + if (!negated) + ADD(R0, gpr.R(rs), op2); + else + SUB(R0, gpr.R(rs), op2); + } else { + // Try to avoid using MOVT + if (offset < 0) { + ARMABI_MOVI2R(R0, (u32)(-offset)); + SUB(R0, gpr.R(rs), R0); + } else { + ARMABI_MOVI2R(R0, (u32)offset); + ADD(R0, gpr.R(rs), R0); + } + } + BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF + } else { + BIC(R0, gpr.R(rs), Operand2(0xC0, 4)); // &= 0x3FFFFFFF + } + } + void Jit::Comp_ITypeMem(u32 op) { int offset = (signed short)(op&0xFFFF); @@ -82,28 +108,7 @@ namespace MIPSComp ARMABI_MOVI2R(R0, addr); } else { gpr.MapDirtyIn(rt, rs); - Operand2 op2; - if (offset) { - bool negated; - if (TryMakeOperand2_AllowNegation(offset, op2, &negated)) { - if (!negated) - ADD(R0, gpr.R(rs), op2); - else - SUB(R0, gpr.R(rs), op2); - } else { - // Try to avoid using MOVT - if (offset < 0) { - ARMABI_MOVI2R(R0, (u32)(-offset)); - SUB(R0, gpr.R(rs), R0); - } else { - ARMABI_MOVI2R(R0, (u32)offset); - ADD(R0, gpr.R(rs), R0); - } - } - BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - } else { - BIC(R0, gpr.R(rs), Operand2(0xC0, 4)); // &= 0x3FFFFFFF - } + SetR0ToEffectiveAddress(rs, offset); } if (o == 35) { LDR(gpr.R(rt), R11, R0, true, true); @@ -131,28 +136,7 @@ namespace MIPSComp ARMABI_MOVI2R(R0, addr); } else { gpr.MapInIn(rt, rs); - Operand2 op2; - if (offset) { - bool negated; - if (TryMakeOperand2_AllowNegation(offset, op2, &negated)) { - if (!negated) - ADD(R0, gpr.R(rs), op2); - else - SUB(R0, gpr.R(rs), op2); - } else { - // Try to avoid using MOVT - if (offset < 0) { - ARMABI_MOVI2R(R0, (u32)(-offset)); - SUB(R0, gpr.R(rs), R0); - } else { - ARMABI_MOVI2R(R0, (u32)offset); - ADD(R0, gpr.R(rs), R0); - } - } - BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - } else { - BIC(R0, gpr.R(rs), Operand2(0xC0, 4)); // &= 0x3FFFFFFF - } + SetR0ToEffectiveAddress(rs, offset); } if (o == 43) { STR(R0, gpr.R(rt), R11, true, true); diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index b434446b68..336841a17a 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -14,8 +14,15 @@ #define _POS ((op>>6 ) & 0x1F) #define _SIZE ((op>>11 ) & 0x1F) +// #define CONDITIONAL_DISABLE Comp_Generic(op); return; +#define CONDITIONAL_DISABLE ; +#define DISABLE Comp_Generic(op); return; namespace MIPSComp { + void Jit::Comp_SVQ(u32 op) + { + DISABLE; + } } \ No newline at end of file diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 072d40ae04..a6d6191939 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -86,6 +86,8 @@ public: void Comp_FPU2op(u32 op); void Comp_mxc1(u32 op); + void Comp_SVQ(u32 op); + ArmJitBlockCache *GetBlockCache() { return &blocks; } void ClearCache(); @@ -122,6 +124,9 @@ private: void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters); */ + // Utils + void SetR0ToEffectiveAddress(int rs, s16 offset); + ArmJitBlockCache blocks; ArmJitOptions jo; ArmJitState js; diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index f815365c2e..59d76337f0 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -150,8 +150,8 @@ const MIPSInstruction tableImmediate[64] = //xxxxxx ..... INSTR("lv.s", &Jit::Comp_Generic, Dis_SV, Int_SV, IS_VFPU), {-2}, // HIT THIS IN WIPEOUT {VFPU4Jump}, - INSTR("lv", &Jit::Comp_Generic, Dis_SVLRQ, Int_SVQ, IS_VFPU), - INSTR("lv.q", &Jit::Comp_Generic, Dis_SVQ, Int_SVQ, IS_VFPU), //copU + INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU), + INSTR("lv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU), //copU {VFPU5}, //56 INSTR("sc", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0), @@ -160,8 +160,8 @@ const MIPSInstruction tableImmediate[64] = //xxxxxx ..... {-2}, //60 {VFPU6}, - INSTR("sv", &Jit::Comp_Generic, Dis_SVLRQ, Int_SVQ, IS_VFPU), //copU - INSTR("sv.q", &Jit::Comp_Generic, Dis_SVQ, Int_SVQ, IS_VFPU), + INSTR("sv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU), //copU + INSTR("sv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU), INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU), }; diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index cf1015f28b..7ba55a120a 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -25,6 +25,62 @@ #define V(i) (currentMIPS->v[i]) #define VI(i) (*(u32*)(&(currentMIPS->v[i]))) +void GetVectorRegs(u8 regs[4], VectorSize N, int vectorReg) { + int mtx = (vectorReg >> 2) & 7; + int col = vectorReg & 3; + int row = 0; + int length = 0; + int transpose = (vectorReg>>5) & 1; + + switch (N) + { + case V_Single: transpose = 0; row=(vectorReg>>5)&3; length = 1; break; + case V_Pair: row=(vectorReg>>5)&2; length = 2; break; + case V_Triple: row=(vectorReg>>6)&1; length = 3; break; + case V_Quad: row=(vectorReg>>5)&2; length = 4; break; + } + + for (int i = 0; i < length; i++) + { + int index = mtx * 4; + if (transpose) + index += ((row+i)&3) + col*32; + else + index += col + ((row+i)&3)*32; + regs[i] = index; + } +} + +void GetMatrixRegs(u8 regs[16], MatrixSize N, int matrixReg) { + int mtx = (matrixReg >> 2) & 7; + int col = matrixReg & 3; + + int row = 0; + int side = 0; + + switch (N) + { + case M_2x2: row = (matrixReg>>5)&2; side = 2; break; + case M_3x3: row = (matrixReg>>6)&1; side = 3; break; + case M_4x4: row = (matrixReg>>5)&2; side = 4; break; + } + + int transpose = (matrixReg>>5) & 1; + + for (int i = 0; i < side; i++) + { + for (int j = 0; j < side; j++) + { + int index = mtx * 4; + if (transpose) + index += ((row+i)&3) + ((col+j)&3)*32; + else + index += ((col+j)&3) + ((row+i)&3)*32; + regs[j*4 + i] = index; + } + } +} + void ReadVector(float *rd, VectorSize size, int reg) { int mtx = (reg >> 2) & 7; diff --git a/Core/MIPS/MIPSVFPUUtils.h b/Core/MIPS/MIPSVFPUUtils.h index 0c9307decd..ac63805a9e 100644 --- a/Core/MIPS/MIPSVFPUUtils.h +++ b/Core/MIPS/MIPSVFPUUtils.h @@ -57,6 +57,9 @@ void WriteMatrix(const float *rs, MatrixSize size, int reg); void WriteVector(const float *rs, VectorSize N, int reg); void ReadVector(float *rd, VectorSize N, int reg); +void GetVectorRegs(u8 regs[4], VectorSize N, int vectorReg); +void GetMatrixRegs(u8 regs[16], MatrixSize N, int matrixReg); + VectorSize GetVecSize(u32 op); MatrixSize GetMtxSize(u32 op); VectorSize GetHalfVectorSize(VectorSize sz); diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index fddc4bc419..ea719b8e20 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -16,9 +16,11 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "../../MemMap.h" +#include "../../Config.h" #include "../MIPSAnalyst.h" #include "Jit.h" +#include "../MIPSVFPUUtils.h" #include "RegCache.h" // All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. @@ -38,8 +40,91 @@ #define _POS ((op>>6 ) & 0x1F) #define _SIZE ((op>>11 ) & 0x1F) +using namespace Gen; namespace MIPSComp { +void Jit::Comp_SVQ(u32 op) +{ + int imm = (signed short)(op&0xFFFC); + int rs = _RS; + int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5); + + switch (op >> 26) + { + case 54: //lv.q + { + if (!g_Config.bFastMemory) { + DISABLE; + } + gpr.BindToRegister(rs, true, true); + + u8 vregs[4]; + GetVectorRegs(vregs, V_Quad, vt); + + MOV(32, R(EAX), gpr.R(rs)); + // Just copy 4 words the easiest way while not wasting registers. +#ifndef _M_X64 + AND(32, R(EAX), Imm32(0x3FFFFFFF)); +#endif + // MOVSS to prime any crazy cache mechanism that might assume that there's a float somewhere... + for (int i = 0; i < 4; i++) { +#ifdef _M_X64 + MOVSS((X64Reg)(XMM0 + i), MComplex(RBX, EAX, 1, i * 4 + imm)); +#else + MOVSS((X64Reg)(XMM0 + i), MDisp(EAX, (u32)(Memory::base + i * 4 + imm))); +#endif + } + + // It would be pretty nice to have these in registers for the next instruction... + // Even if we don't use real SIMD there's still 8 or 16 scalar float registers. + for (int i = 0; i < 4; i++) { + MOVSS(M((void *)&mips_->v[vregs[i]]), (X64Reg)(XMM0 + i)); + } + gpr.UnlockAll(); + } + break; + + case 62: //sv.q + { + if (!g_Config.bFastMemory) { + DISABLE; + } + gpr.BindToRegister(rs, true, true); + + u8 vregs[4]; + GetVectorRegs(vregs, V_Quad, vt); + + MOV(32, R(EAX), gpr.R(rs)); + // Just copy 4 words the easiest way while not wasting registers. +#ifndef _M_X64 + AND(32, R(EAX), Imm32(0x3FFFFFFF)); +#endif + // MOVSS to prime any crazy cache mechanism that might assume that there's a float somewhere... + + // It would be pretty nice to have these in registers for the next instruction... + // Even if we don't use real SIMD there's still 8 or 16 scalar float registers. + for (int i = 0; i < 4; i++) { + MOVSS((X64Reg)(XMM0 + i), M((void *)&mips_->v[vregs[i]])); + } + + for (int i = 0; i < 4; i++) { +#ifdef _M_X64 + MOVSS(MComplex(RBX, EAX, 1, i * 4 + imm), (X64Reg)(XMM0 + i)); +#else + MOVSS(MDisp(EAX, (u32)(Memory::base + i * 4 + imm)), (X64Reg)(XMM0 + i)); +#endif + } + + gpr.UnlockAll(); + } + break; + + default: + DISABLE; + break; + } +} + } \ No newline at end of file diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index beb0438918..5b14dd768d 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -109,6 +109,8 @@ public: void Comp_FPU2op(u32 op); void Comp_mxc1(u32 op); + void Comp_SVQ(u32 op); + JitBlockCache *GetBlockCache() { return &blocks; } AsmRoutineManager &Asm() { return asm_; }