mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge branch 'vfpucc'
This commit is contained in:
commit
836820b41e
5 changed files with 31 additions and 19 deletions
|
@ -287,7 +287,7 @@ void Jit::BranchFPFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
|
|||
if (!likely && delaySlotIsNice)
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
|
||||
gpr.MapReg(MIPS_REG_FPCOND, 0);
|
||||
gpr.MapReg(MIPS_REG_FPCOND);
|
||||
TST(gpr.R(MIPS_REG_FPCOND), Operand2(1, TYPE_IMM));
|
||||
|
||||
ArmGen::FixupBranch ptr;
|
||||
|
@ -340,7 +340,7 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
|
|||
u32 targetAddr = js.compilerPC + offset + 4;
|
||||
|
||||
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||
|
||||
|
||||
// Sometimes there's a VFPU branch in a delay slot (Disgaea 2: Dark Hero Days, Zettai Hero Project, La Pucelle)
|
||||
// The behavior is undefined - the CPU may take the second branch even if the first one passes.
|
||||
// However, it does consistently try each branch, which these games seem to expect.
|
||||
|
@ -354,8 +354,8 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
|
|||
|
||||
int imm3 = (op >> 18) & 7;
|
||||
|
||||
LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]));
|
||||
TST(R0, Operand2(1 << imm3, TYPE_IMM));
|
||||
gpr.MapReg(MIPS_REG_VFPUCC);
|
||||
TST(gpr.R(MIPS_REG_VFPUCC), Operand2(1 << imm3, TYPE_IMM));
|
||||
|
||||
ArmGen::FixupBranch ptr;
|
||||
js.inDelaySlot = true;
|
||||
|
|
|
@ -1018,8 +1018,13 @@ namespace MIPSComp
|
|||
} else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc
|
||||
// In case we have a saved prefix.
|
||||
FlushPrefixV();
|
||||
gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY);
|
||||
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128));
|
||||
if (imm - 128 == VFPU_CTRL_CC) {
|
||||
gpr.MapDirtyIn(rt, MIPS_REG_VFPUCC);
|
||||
MOV(gpr.R(rt), gpr.R(MIPS_REG_VFPUCC));
|
||||
} else {
|
||||
gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY);
|
||||
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128));
|
||||
}
|
||||
} else {
|
||||
//ERROR - maybe need to make this value too an "interlock" value?
|
||||
ERROR_LOG(CPU, "mfv - invalid register %i", imm);
|
||||
|
@ -1033,8 +1038,13 @@ namespace MIPSComp
|
|||
fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT);
|
||||
VMOV(fpr.V(imm), gpr.R(rt));
|
||||
} else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc //currentMIPS->vfpuCtrl[imm - 128] = R(rt);
|
||||
gpr.MapReg(rt);
|
||||
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128));
|
||||
if (imm - 128 == VFPU_CTRL_CC) {
|
||||
gpr.MapDirtyIn(MIPS_REG_VFPUCC, rt);
|
||||
MOV(gpr.R(MIPS_REG_VFPUCC), rt);
|
||||
} else {
|
||||
gpr.MapReg(rt);
|
||||
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, vfpuCtrl) + 4 * (imm - 128));
|
||||
}
|
||||
//gpr.BindToRegister(rt, true, false);
|
||||
//MOV(32, M(¤tMIPS->vfpuCtrl[imm - 128]), gpr.R(rt));
|
||||
|
||||
|
@ -1496,7 +1506,7 @@ namespace MIPSComp
|
|||
if (n == 1) {
|
||||
MOVI2R(R0, 0x31);
|
||||
} else {
|
||||
MOVI2R(R0, 1 << i);
|
||||
MOVI2R(R0, 1); // 1 << i, but i == 0
|
||||
}
|
||||
} else {
|
||||
ORR(R0, R0, 1 << i);
|
||||
|
@ -1514,17 +1524,16 @@ namespace MIPSComp
|
|||
SetCC(CC_EQ);
|
||||
ORR(R0, R0, 1 << 5);
|
||||
SetCC(CC_AL);
|
||||
|
||||
|
||||
CMP(R0, 0);
|
||||
SetCC(CC_NEQ);
|
||||
ORR(R0, R0, 1 << 4);
|
||||
SetCC(CC_AL);
|
||||
}
|
||||
|
||||
LDR(R1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]));
|
||||
BIC(R1, R1, affected_bits);
|
||||
ORR(R1, R1, R0);
|
||||
STR(R1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]));
|
||||
gpr.MapReg(MIPS_REG_VFPUCC, MAP_DIRTY);
|
||||
BIC(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), affected_bits);
|
||||
ORR(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), R0);
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
@ -1555,8 +1564,8 @@ namespace MIPSComp
|
|||
// Test one bit of CC. This bit decides whether none or all subregisters are copied.
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_DIRTY);
|
||||
fpr.MapRegsAndSpillLockV(sregs, sz, 0);
|
||||
LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]));
|
||||
TST(R0, 1 << imm3);
|
||||
gpr.MapReg(MIPS_REG_VFPUCC);
|
||||
TST(gpr.R(MIPS_REG_VFPUCC), 1 << imm3);
|
||||
SetCC(tf ? CC_EQ : CC_NEQ);
|
||||
for (int i = 0; i < n; i++) {
|
||||
VMOV(fpr.V(dregs[i]), fpr.V(sregs[i]));
|
||||
|
@ -1566,9 +1575,9 @@ namespace MIPSComp
|
|||
// Look at the bottom four bits of CC to individually decide if the subregisters should be copied.
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_DIRTY);
|
||||
fpr.MapRegsAndSpillLockV(sregs, sz, 0);
|
||||
LDR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]));
|
||||
gpr.MapReg(MIPS_REG_VFPUCC);
|
||||
for (int i = 0; i < n; i++) {
|
||||
TST(R0, 1 << i);
|
||||
TST(gpr.R(MIPS_REG_VFPUCC), 1 << i);
|
||||
SetCC(tf ? CC_EQ : CC_NEQ);
|
||||
VMOV(fpr.V(dregs[i]), fpr.V(sregs[i]));
|
||||
SetCC(CC_AL);
|
||||
|
|
|
@ -571,6 +571,8 @@ int ArmRegCache::GetMipsRegOffset(MIPSGPReg r) {
|
|||
return offsetof(MIPSState, lo);
|
||||
case MIPS_REG_FPCOND:
|
||||
return offsetof(MIPSState, fpcond);
|
||||
case MIPS_REG_VFPUCC:
|
||||
return offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_CC]);
|
||||
default:
|
||||
ERROR_LOG_REPORT(JIT, "bad mips register %i", r);
|
||||
return 0; // or what?
|
||||
|
|
|
@ -31,7 +31,7 @@ using namespace ArmGen;
|
|||
// R11 = base pointer
|
||||
|
||||
enum {
|
||||
TOTAL_MAPPABLE_MIPSREGS = 35,
|
||||
TOTAL_MAPPABLE_MIPSREGS = 36,
|
||||
};
|
||||
|
||||
typedef int MIPSReg;
|
||||
|
|
|
@ -69,6 +69,7 @@ enum MIPSGPReg
|
|||
MIPS_REG_HI = 32,
|
||||
MIPS_REG_LO = 33,
|
||||
MIPS_REG_FPCOND = 34,
|
||||
MIPS_REG_VFPUCC = 35,
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
Loading…
Add table
Reference in a new issue