Fix up VCVT function to recognise the difference in encoding for to_int and to_float. There is no 'round to zero' option for to_float. cvt.s.w and cvt.w.s should be unsigned.

This commit is contained in:
Sacha 2013-03-01 13:45:22 +10:00
parent 059abc0d69
commit 6d3c89e354
3 changed files with 13 additions and 10 deletions

View File

@ -1032,12 +1032,15 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
}
}
void ARMXEmitter::VCVT(bool to_integer, bool is_signed, bool round_to_zero, ARMReg Sd, ARMReg Sm)
void ARMXEmitter::VCVT(ARMReg Sd, ARMReg Sm, bool to_integer, bool is_signed, bool round_to_zero = false)
{
bool op = to_integer ? round_to_zero : is_signed;
bool op2 = to_integer ? is_signed : 0;
Sd = SubBase(Sd);
Sm = SubBase(Sm);
Write32(NO_COND | (0x1D << 23) | ((Sd & 0x1) << 22) | (0x7 << 19) | (to_integer << 18) | (is_signed << 16) \
| ((Sd & 0x1E) << 11) | (round_to_zero << 7) | (0x29 << 6) | ((Sm & 0x1) << 5) | (Sm >> 1));
Write32(NO_COND | (0x1D << 23) | ((Sd & 0x1) << 22) | (0x7 << 19) | (to_integer << 18) | (op2 << 16) \
| ((Sd & 0x1E) << 11) | (op << 7) | (0x29 << 6) | ((Sm & 0x1) << 5) | (Sm >> 1));
}
}

View File

@ -515,7 +515,7 @@ public:
void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
void VMOV(ARMReg Dest, ARMReg Src, bool high);
void VMOV(ARMReg Dest, ARMReg Src);
void VCVT(bool to_integer, bool is_signed, bool round_to_zero, ARMReg Sd, ARMReg Sm);
void VCVT(ARMReg Sd, ARMReg Sm, bool to_integer, bool is_signed, bool round_to_zero);
void QuickCallFunction(ARMReg scratchreg, void *func);
// Utility functions

View File

@ -179,33 +179,33 @@ void Jit::Comp_FPU2op(u32 op)
break;
case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
fpr.MapDirtyIn(fd, fs);
VCVT(true, true, false, fpr.R(fd), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), true, true, false);
break;
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
fpr.MapDirtyIn(fd, fs);
VCVT(true, true, true, fpr.R(fd), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), true, true, true);
break;
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
fpr.MapDirtyIn(fd, fs);
MOVI2R(R0, 0x3F000000); // 0.5f
VMOV(S0, R0);
VADD(S0,fpr.R(fs),S0);
VCVT(true, true, false, fpr.R(fd), S0);
VCVT(fpr.R(fd), S0, true, true, false);
break;
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
fpr.MapDirtyIn(fd, fs);
MOVI2R(R0, 0x3F000000); // 0.5f
VMOV(S0, R0);
VSUB(S0,fpr.R(fs),S0);
VCVT(true, true, false, fpr.R(fd), S0);
VCVT(fpr.R(fd), S0, true, true, false);
break;
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
fpr.MapDirtyIn(fd, fs);
VCVT(false, false, true, fpr.R(fd), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), false, false);
break;
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
fpr.MapDirtyIn(fd, fs);
VCVT(true, false, true, fpr.R(fd), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), true, false, true);
break;
default:
DISABLE;