mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 00:10:31 +02:00
ARM32 IR JIT: Pass float helper arguments the softfp way where needed
Android's armeabi-v7a uses the softfp calling convention, where floats travel in R0/R1, not S0/S1. The math helper calls (vfpu_sin and the rest) only did the hard float version, so on Android they got garbage and returned it (broken 3D in Virtua Tennis: World Tour). Like the old ArmJit, check __ARM_PCS_VFP. With an armel softfp build under qemu, the fuzzer found 41 of 3000 cases where the JIT differed from the IR interpreter before this, and none after. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
74703b031e
commit
e920666d72
1 file changed
+16
-2
@@ -492,7 +492,8 @@ void ArmJitBackend::CompIR_FSat(IRInst inst) {
|
||||
void ArmJitBackend::CompIR_FSpecial(IRInst inst) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
// The argument goes in S0 and the result comes back there (hard float ABI.)
|
||||
// The argument goes in S0 and the result comes back there with the hard float ABI. With
|
||||
// softfp (Android's armeabi-v7a), floats are passed and returned in R0 (and R1.)
|
||||
auto loadArg = [&]() {
|
||||
regs_.FlushBeforeCall();
|
||||
WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER);
|
||||
@@ -502,10 +503,22 @@ void ArmJitBackend::CompIR_FSpecial(IRInst inst) {
|
||||
} else {
|
||||
VLDR(S0, CTXREG, offsetof(MIPSState, f) + inst.src1 * 4);
|
||||
}
|
||||
#if !defined(__ARM_PCS_VFP)
|
||||
VMOV(R0, S0);
|
||||
#endif
|
||||
};
|
||||
// Before anything else can use R0 and R1.
|
||||
auto resultToS0 = [&](bool twoFloats) {
|
||||
#if !defined(__ARM_PCS_VFP)
|
||||
VMOV(S0, R0);
|
||||
if (twoFloats)
|
||||
VMOV(S1, R1);
|
||||
#endif
|
||||
};
|
||||
auto callFuncF_F = [&](float (*func)(float)) {
|
||||
loadArg();
|
||||
QuickCallFunction(R12, func);
|
||||
resultToS0(false);
|
||||
regs_.MapFPR(inst.dest, MIPSMap::NOINIT);
|
||||
VMOV(regs_.F(inst.dest), S0);
|
||||
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
|
||||
@@ -549,9 +562,10 @@ void ArmJitBackend::CompIR_FSpecial(IRInst inst) {
|
||||
break;
|
||||
|
||||
case IROp::FSinCos:
|
||||
// The helper returns the sine and cosine packed into D0, which is S0 and S1.
|
||||
// The helper returns the sine and cosine packed into a double, which is S0 and S1.
|
||||
loadArg();
|
||||
QuickCallFunction(R12, &vfpu_sincos_packed);
|
||||
resultToS0(true);
|
||||
regs_.Map(inst);
|
||||
VMOV(regs_.F(inst.dest), S0);
|
||||
VMOV(regs_.F(inst.dest + 1), S1);
|
||||
|
||||
Reference in new issue
Block a user