mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
ARMJIT: Fix and use DIV, DIVU, INS and EXT (ARMv7 and VFPv4 implementations).
This commit is contained in:
parent
3587cef738
commit
a14a2fafa9
2 changed files with 40 additions and 19 deletions
|
@ -1156,13 +1156,39 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
|
||||||
void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags)
|
void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags)
|
||||||
{
|
{
|
||||||
bool single_reg = (Dest < D0) && (Source < D0);
|
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 op = ((flags & TO_INT) ? (flags & ROUND_TO_ZERO) : (flags & IS_SIGNED)) ? 1 : 0;
|
||||||
int op2 = ((flags & TO_INT) ? (flags & IS_SIGNED) : 0) ? 1 : 0;
|
int op2 = ((flags & TO_INT) ? (flags & IS_SIGNED) : 0) ? 1 : 0;
|
||||||
Dest = SubBase(Dest);
|
Dest = SubBase(Dest);
|
||||||
Source = SubBase(Source);
|
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) \
|
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));
|
| ((Dest & 0x1E) << 11) | (op << 7) | (0x29 << 6) | ((Source & 0x1) << 5) | (Source >> 1));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -382,12 +382,6 @@ namespace MIPSComp
|
||||||
void Jit::Comp_Special3(u32 op)
|
void Jit::Comp_Special3(u32 op)
|
||||||
{
|
{
|
||||||
CONDITIONAL_DISABLE;
|
CONDITIONAL_DISABLE;
|
||||||
|
|
||||||
bool useUBFXandBFI = false;
|
|
||||||
|
|
||||||
if (!cpu_info.bArmV7) {
|
|
||||||
// useUBFXandBFI = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
int rt = _RT;
|
int rt = _RT;
|
||||||
|
@ -409,11 +403,8 @@ namespace MIPSComp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reported to break Disgaea.
|
|
||||||
DISABLE;
|
|
||||||
|
|
||||||
gpr.MapDirtyIn(rt, rs);
|
gpr.MapDirtyIn(rt, rs);
|
||||||
if (useUBFXandBFI) {
|
if (cpu_info.bArmV7) {
|
||||||
UBFX(gpr.R(rt), gpr.R(rs), pos, size);
|
UBFX(gpr.R(rt), gpr.R(rs), pos, size);
|
||||||
} else {
|
} else {
|
||||||
MOV(gpr.R(rt), Operand2(gpr.R(rs), ST_LSR, pos));
|
MOV(gpr.R(rt), Operand2(gpr.R(rs), ST_LSR, pos));
|
||||||
|
@ -440,9 +431,9 @@ namespace MIPSComp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (useUBFXandBFI) {
|
if (cpu_info.bArmV7) {
|
||||||
gpr.MapDirtyIn(rt, rs, false);
|
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 {
|
} else {
|
||||||
gpr.MapDirtyIn(rt, rs, false);
|
gpr.MapDirtyIn(rt, rs, false);
|
||||||
ANDI2R(R0, gpr.R(rs), sourcemask, R1);
|
ANDI2R(R0, gpr.R(rs), sourcemask, R1);
|
||||||
|
@ -554,40 +545,44 @@ namespace MIPSComp
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 26: //div
|
case 26: //div
|
||||||
DISABLE;
|
|
||||||
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
|
||||||
if (cpu_info.bIDIVa)
|
if (cpu_info.bIDIVa)
|
||||||
{
|
{
|
||||||
|
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
||||||
SDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt));
|
SDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt));
|
||||||
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
||||||
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
||||||
} else {
|
} else {
|
||||||
|
DISABLE;
|
||||||
|
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
||||||
VMOV(S0, gpr.R(rs));
|
VMOV(S0, gpr.R(rs));
|
||||||
VMOV(S1, gpr.R(rt));
|
VMOV(S1, gpr.R(rt));
|
||||||
VCVT(D0, S0, TO_FLOAT | IS_SIGNED);
|
VCVT(D0, S0, TO_FLOAT | IS_SIGNED);
|
||||||
VCVT(D1, S1, TO_FLOAT | IS_SIGNED);
|
VCVT(D1, S1, TO_FLOAT | IS_SIGNED);
|
||||||
VDIV(D0, D0, D1);
|
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));
|
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
||||||
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 27: //divu
|
case 27: //divu
|
||||||
DISABLE;
|
|
||||||
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
|
||||||
if (cpu_info.bIDIVa)
|
if (cpu_info.bIDIVa)
|
||||||
{
|
{
|
||||||
|
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
||||||
UDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt));
|
UDIV(gpr.R(MIPSREG_LO), gpr.R(rs), gpr.R(rt));
|
||||||
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
||||||
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
||||||
} else {
|
} else {
|
||||||
|
DISABLE;
|
||||||
|
gpr.MapDirtyDirtyInIn(MIPSREG_LO, MIPSREG_HI, rs, rt);
|
||||||
VMOV(S0, gpr.R(rs));
|
VMOV(S0, gpr.R(rs));
|
||||||
VMOV(S1, gpr.R(rt));
|
VMOV(S1, gpr.R(rt));
|
||||||
VCVT(D0, S0, TO_FLOAT);
|
VCVT(D0, S0, TO_FLOAT);
|
||||||
VCVT(D1, S1, TO_FLOAT);
|
VCVT(D1, S1, TO_FLOAT);
|
||||||
VDIV(D0, D0, D1);
|
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));
|
MUL(R0, gpr.R(rt), gpr.R(MIPSREG_LO));
|
||||||
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
SUB(gpr.R(MIPSREG_HI), gpr.R(rs), Operand2(R0));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue