diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 452c9b707f..5bcfd618d7 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -1156,13 +1156,39 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src) void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags) { bool single_reg = (Dest < D0) && (Source < D0); + bool single_double = !single_reg && (Source < D0 || Dest < D0); + bool single_to_double = Source < D0; int op = ((flags & TO_INT) ? (flags & ROUND_TO_ZERO) : (flags & IS_SIGNED)) ? 1 : 0; int op2 = ((flags & TO_INT) ? (flags & IS_SIGNED) : 0) ? 1 : 0; Dest = SubBase(Dest); Source = SubBase(Source); - if (single_reg) + if (single_double) { + // S32<->F64 + if ((flags & TO_INT) || (flags & TO_FLOAT)) + { + if (single_to_double) + { + Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x7 << 19) \ + | ((Dest & 0xF) << 12) | (op << 7) | (0x2D << 6) | ((Source & 0x1) << 5) | (Source >> 1)); + } else { + Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \ + | ((Dest & 0x1E) << 11) | (op << 7) | (0x2D << 6) | ((Source & 0x10) << 1) | (Source & 0xF)); + } + } + // F32<->F64 + else { + if (single_to_double) + { + Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | (0x7 << 16) \ + | ((Dest & 0xF) << 12) | (0x2F << 6) | ((Source & 0x1) << 5) | (Source >> 1)); + } else { + Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x3 << 20) | (0x7 << 16) \ + | ((Dest & 0x1E) << 11) | (0x2B << 6) | ((Source & 0x10) << 1) | (Source & 0xF)); + } + } + } else if (single_reg) { Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \ | ((Dest & 0x1E) << 11) | (op << 7) | (0x29 << 6) | ((Source & 0x1) << 5) | (Source >> 1)); } else { diff --git a/Core/MIPS/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index d42fe1785b..59b5e7a7bd 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -382,12 +382,6 @@ namespace MIPSComp void Jit::Comp_Special3(u32 op) { CONDITIONAL_DISABLE; - - bool useUBFXandBFI = false; - - if (!cpu_info.bArmV7) { - // useUBFXandBFI = true; - } int rs = _RS; int rt = _RT; @@ -409,11 +403,8 @@ namespace MIPSComp return; } - // Reported to break Disgaea. - DISABLE; - gpr.MapDirtyIn(rt, rs); - if (useUBFXandBFI) { + if (cpu_info.bArmV7) { UBFX(gpr.R(rt), gpr.R(rs), pos, size); } else { MOV(gpr.R(rt), Operand2(gpr.R(rs), ST_LSR, pos)); @@ -440,9 +431,9 @@ namespace MIPSComp } else { - if (useUBFXandBFI) { + if (cpu_info.bArmV7) { gpr.MapDirtyIn(rt, rs, false); - BFI(gpr.R(rt), gpr.R(rs), pos, size); + BFI(gpr.R(rt), gpr.R(rs), pos, size-pos); } else { gpr.MapDirtyIn(rt, rs, false); ANDI2R(R0, gpr.R(rs), sourcemask, R1); @@ -554,40 +545,44 @@ namespace MIPSComp break; case 26: //div - DISABLE; - gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); if (cpu_info.bIDIVa) { + gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); SDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt)); MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO)); SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0)); } else { + DISABLE; + gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); VMOV(S0, gpr.R(rs)); VMOV(S1, gpr.R(rt)); VCVT(D0, S0, TO_FLOAT | IS_SIGNED); VCVT(D1, S1, TO_FLOAT | IS_SIGNED); VDIV(D0, D0, D1); - VCVT(gpr.R(MIPSREG_LO), D0, TO_INT | IS_SIGNED); + VCVT(S0, D0, TO_INT); + VMOV(gpr.R(MIPSREG_LO), S0); MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO)); SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0)); } break; case 27: //divu - DISABLE; - gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); if (cpu_info.bIDIVa) { + gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); UDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt)); MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO)); SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0)); } else { + DISABLE; + gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt); VMOV(S0, gpr.R(rs)); VMOV(S1, gpr.R(rt)); VCVT(D0, S0, TO_FLOAT); VCVT(D1, S1, TO_FLOAT); VDIV(D0, D0, D1); - VCVT(gpr.R(MIPSREG_LO), D0, TO_INT); + VCVT(S0, D0, TO_INT); + VMOV(gpr.R(MIPSREG_LO), S0); MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO)); SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0)); }