JIT - fctixx: Properly handle numbers > INT_MAX
This commit is contained in:
parent
ad5748f3e7
commit
ea89a5d179
|
@ -171,6 +171,19 @@ static inline vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
|||
v.u32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128d(double src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 2; ++i) {
|
||||
v.f64[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128d(double x, double y) {
|
||||
vec128_t v;
|
||||
v.f64[0] = x;
|
||||
v.f64[1] = y;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
|
|
|
@ -670,6 +670,9 @@ static const vec128_t xmm_consts[] = {
|
|||
0x80000000u),
|
||||
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
||||
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
||||
/* XMMIntMaxPS */ vec128f(float(INT_MAX)),
|
||||
/* XMMIntMaxPD */ vec128d(INT_MAX),
|
||||
/* XMMInt64MaxPD */ vec128d(double(INT64_MAX)),
|
||||
};
|
||||
|
||||
// First location to try and place constants.
|
||||
|
|
|
@ -89,6 +89,9 @@ enum XmmConst {
|
|||
XMMSignMaskF32,
|
||||
XMMShortMinPS,
|
||||
XMMShortMaxPS,
|
||||
XMMIntMaxPS,
|
||||
XMMIntMaxPD,
|
||||
XMMInt64MaxPD,
|
||||
};
|
||||
|
||||
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
|
||||
|
|
|
@ -1429,21 +1429,25 @@ struct CONVERT_I32_F32
|
|||
: Sequence<CONVERT_I32_F32, I<OPCODE_CONVERT, I32Op, F32Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
// TODO(benvanik): saturation check? cvtt* (trunc?)
|
||||
e.vcvtss2si(i.dest, i.src1);
|
||||
e.vminss(e.xmm0, i.src1, e.GetXmmConstPtr(XMMIntMaxPS));
|
||||
e.vcvtss2si(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
struct CONVERT_I32_F64
|
||||
: Sequence<CONVERT_I32_F64, I<OPCODE_CONVERT, I32Op, F64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
// TODO(benvanik): saturation check? cvtt* (trunc?)
|
||||
e.vcvttsd2si(i.dest, i.src1);
|
||||
// Intel returns 0x80000000 if the double value does not fit within an int32
|
||||
// PPC saturates the value instead.
|
||||
// So, we can clamp the double value to (double)0x7FFFFFFF.
|
||||
e.vminsd(e.xmm0, i.src1, e.GetXmmConstPtr(XMMIntMaxPD));
|
||||
e.vcvttsd2si(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
struct CONVERT_I64_F64
|
||||
: Sequence<CONVERT_I64_F64, I<OPCODE_CONVERT, I64Op, F64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
// TODO(benvanik): saturation check? cvtt* (trunc?)
|
||||
e.vcvttsd2si(i.dest, i.src1);
|
||||
e.vminsd(e.xmm0, i.src1, e.GetXmmConstPtr(XMMInt64MaxPD));
|
||||
e.vcvttsd2si(i.dest, e.xmm0);
|
||||
}
|
||||
};
|
||||
struct CONVERT_F32_I32
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
# Credits: These tests stolen from https://github.com/dolphin-emu/hwtests
|
||||
# +0
|
||||
test_fctiwz_1:
|
||||
#_ REGISTER_IN f0 0x0000000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x0000000000000000
|
||||
#_ REGISTER_OUT f1 0x0000000000000000
|
||||
|
||||
# -0
|
||||
test_fctiwz_2:
|
||||
#_ REGISTER_IN f0 0x8000000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x8000000000000000
|
||||
#_ REGISTER_OUT f1 0x0000000000000000
|
||||
|
||||
# smallest positive subnormal
|
||||
test_fctiwz_3:
|
||||
#_ REGISTER_IN f0 0x0000000000000001
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x0000000000000001
|
||||
#_ REGISTER_OUT f1 0x0000000000000000
|
||||
|
||||
# largest subnormal
|
||||
test_fctiwz_4:
|
||||
#_ REGISTER_IN f0 0x000fffffffffffff
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x000fffffffffffff
|
||||
#_ REGISTER_OUT f1 0x0000000000000000
|
||||
|
||||
# +1
|
||||
test_fctiwz_5:
|
||||
#_ REGISTER_IN f0 0x3ff0000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x3ff0000000000000
|
||||
#_ REGISTER_OUT f1 0x0000000000000001
|
||||
|
||||
# -1
|
||||
test_fctiwz_6:
|
||||
#_ REGISTER_IN f0 0xbff0000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0xbff0000000000000
|
||||
#_ REGISTER_OUT f1 0x00000000ffffffff
|
||||
|
||||
# -(2^31)
|
||||
test_fctiwz_7:
|
||||
#_ REGISTER_IN f0 0xc1e0000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0xc1e0000000000000
|
||||
#_ REGISTER_OUT f1 0x0000000080000000
|
||||
|
||||
# 2^31 - 1
|
||||
test_fctiwz_8:
|
||||
#_ REGISTER_IN f0 0x41dfffffffc00000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x41dfffffffc00000
|
||||
#_ REGISTER_OUT f1 0x000000007fffffff
|
||||
|
||||
# +infinity
|
||||
test_fctiwz_9:
|
||||
#_ REGISTER_IN f0 0x7ff0000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0x7ff0000000000000
|
||||
#_ REGISTER_OUT f1 0x000000007fffffff
|
||||
|
||||
# -infinity
|
||||
test_fctiwz_10:
|
||||
#_ REGISTER_IN f0 0xfff0000000000000
|
||||
fctiwz f1, f0
|
||||
blr
|
||||
#_ REGISTER_OUT f0 0xfff0000000000000
|
||||
#_ REGISTER_OUT f1 0x0000000080000000
|
||||
|
||||
# TODO(DrChat): Xenia doesn't handle NaNs yet.
|
||||
# # QNaN
|
||||
# test_fctiwz_11:
|
||||
# #_ REGISTER_IN f0 0xfff8000000000000
|
||||
# fctiwz f1, f0
|
||||
# blr
|
||||
# #_ REGISTER_OUT f0 0xfff8000000000000
|
||||
# #_ REGISTER_OUT f1 0x0000000080000000
|
||||
#
|
||||
# # SNaN
|
||||
# test_fctiwz_12:
|
||||
# #_ REGISTER_IN f0 0xfff4000000000000
|
||||
# fctiwz f1, f0
|
||||
# blr
|
||||
# #_ REGISTER_OUT f0 0xfff4000000000000
|
||||
# #_ REGISTER_OUT f1 0x0000000080000000
|
Loading…
Reference in New Issue