mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 06:05:31 +00:00
target/arm: Fix float16 to/from int16
The instruction "ucvtf v0.4h, v04h, #2", with input 0x8000u, overflows the intermediate float16 to infinity before we have a chance to scale the output. Use float64 as the intermediate type so that no input argument (uint32_t in this case) can overflow or round before scaling. Given the declared argument, the signed int32_t function has the same problem. When converting from float16 to integer, using u/int32_t instead of u/int16_t means that the bounding is incorrect. Backports commit 88808a022c06f98d81cd3f2d105a5734c5614839 from qemu
This commit is contained in:
parent
e403957a5e
commit
67740bbc7f
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_aarch64
|
||||
#define helper_vfp_toshd helper_vfp_toshd_aarch64
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_aarch64
|
||||
#define helper_vfp_toshh helper_vfp_toshh_aarch64
|
||||
#define helper_vfp_toshs helper_vfp_toshs_aarch64
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_aarch64
|
||||
#define helper_vfp_tosid helper_vfp_tosid_aarch64
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_aarch64
|
||||
#define helper_vfp_touhd helper_vfp_touhd_aarch64
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_aarch64
|
||||
#define helper_vfp_touhh helper_vfp_touhh_aarch64
|
||||
#define helper_vfp_touhs helper_vfp_touhs_aarch64
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_aarch64
|
||||
#define helper_vfp_touid helper_vfp_touid_aarch64
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_aarch64eb
|
||||
#define helper_vfp_toshd helper_vfp_toshd_aarch64eb
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_aarch64eb
|
||||
#define helper_vfp_toshh helper_vfp_toshh_aarch64eb
|
||||
#define helper_vfp_toshs helper_vfp_toshs_aarch64eb
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_aarch64eb
|
||||
#define helper_vfp_tosid helper_vfp_tosid_aarch64eb
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_aarch64eb
|
||||
#define helper_vfp_touhd helper_vfp_touhd_aarch64eb
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_aarch64eb
|
||||
#define helper_vfp_touhh helper_vfp_touhh_aarch64eb
|
||||
#define helper_vfp_touhs helper_vfp_touhs_aarch64eb
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_aarch64eb
|
||||
#define helper_vfp_touid helper_vfp_touid_aarch64eb
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_arm
|
||||
#define helper_vfp_toshd helper_vfp_toshd_arm
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_arm
|
||||
#define helper_vfp_toshh helper_vfp_toshh_arm
|
||||
#define helper_vfp_toshs helper_vfp_toshs_arm
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_arm
|
||||
#define helper_vfp_tosid helper_vfp_tosid_arm
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_arm
|
||||
#define helper_vfp_touhd helper_vfp_touhd_arm
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_arm
|
||||
#define helper_vfp_touhh helper_vfp_touhh_arm
|
||||
#define helper_vfp_touhs helper_vfp_touhs_arm
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_arm
|
||||
#define helper_vfp_touid helper_vfp_touid_arm
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_armeb
|
||||
#define helper_vfp_toshd helper_vfp_toshd_armeb
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_armeb
|
||||
#define helper_vfp_toshh helper_vfp_toshh_armeb
|
||||
#define helper_vfp_toshs helper_vfp_toshs_armeb
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_armeb
|
||||
#define helper_vfp_tosid helper_vfp_tosid_armeb
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_armeb
|
||||
#define helper_vfp_touhd helper_vfp_touhd_armeb
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_armeb
|
||||
#define helper_vfp_touhh helper_vfp_touhh_armeb
|
||||
#define helper_vfp_touhs helper_vfp_touhs_armeb
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_armeb
|
||||
#define helper_vfp_touid helper_vfp_touid_armeb
|
||||
|
|
|
@ -1707,6 +1707,7 @@ symbols = (
|
|||
'helper_vfp_subs',
|
||||
'helper_vfp_toshd',
|
||||
'helper_vfp_toshd_round_to_zero',
|
||||
'helper_vfp_toshh',
|
||||
'helper_vfp_toshs',
|
||||
'helper_vfp_toshs_round_to_zero',
|
||||
'helper_vfp_tosid',
|
||||
|
@ -1724,6 +1725,7 @@ symbols = (
|
|||
'helper_vfp_tosqs',
|
||||
'helper_vfp_touhd',
|
||||
'helper_vfp_touhd_round_to_zero',
|
||||
'helper_vfp_touhh',
|
||||
'helper_vfp_touhs',
|
||||
'helper_vfp_touhs_round_to_zero',
|
||||
'helper_vfp_touid',
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_m68k
|
||||
#define helper_vfp_toshd helper_vfp_toshd_m68k
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_m68k
|
||||
#define helper_vfp_toshh helper_vfp_toshh_m68k
|
||||
#define helper_vfp_toshs helper_vfp_toshs_m68k
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_m68k
|
||||
#define helper_vfp_tosid helper_vfp_tosid_m68k
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_m68k
|
||||
#define helper_vfp_touhd helper_vfp_touhd_m68k
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_m68k
|
||||
#define helper_vfp_touhh helper_vfp_touhh_m68k
|
||||
#define helper_vfp_touhs helper_vfp_touhs_m68k
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_m68k
|
||||
#define helper_vfp_touid helper_vfp_touid_m68k
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_mips
|
||||
#define helper_vfp_toshd helper_vfp_toshd_mips
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_mips
|
||||
#define helper_vfp_toshh helper_vfp_toshh_mips
|
||||
#define helper_vfp_toshs helper_vfp_toshs_mips
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_mips
|
||||
#define helper_vfp_tosid helper_vfp_tosid_mips
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_mips
|
||||
#define helper_vfp_touhd helper_vfp_touhd_mips
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_mips
|
||||
#define helper_vfp_touhh helper_vfp_touhh_mips
|
||||
#define helper_vfp_touhs helper_vfp_touhs_mips
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_mips
|
||||
#define helper_vfp_touid helper_vfp_touid_mips
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_mips64
|
||||
#define helper_vfp_toshd helper_vfp_toshd_mips64
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_mips64
|
||||
#define helper_vfp_toshh helper_vfp_toshh_mips64
|
||||
#define helper_vfp_toshs helper_vfp_toshs_mips64
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_mips64
|
||||
#define helper_vfp_tosid helper_vfp_tosid_mips64
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_mips64
|
||||
#define helper_vfp_touhd helper_vfp_touhd_mips64
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_mips64
|
||||
#define helper_vfp_touhh helper_vfp_touhh_mips64
|
||||
#define helper_vfp_touhs helper_vfp_touhs_mips64
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_mips64
|
||||
#define helper_vfp_touid helper_vfp_touid_mips64
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_mips64el
|
||||
#define helper_vfp_toshd helper_vfp_toshd_mips64el
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_mips64el
|
||||
#define helper_vfp_toshh helper_vfp_toshh_mips64el
|
||||
#define helper_vfp_toshs helper_vfp_toshs_mips64el
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_mips64el
|
||||
#define helper_vfp_tosid helper_vfp_tosid_mips64el
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_mips64el
|
||||
#define helper_vfp_touhd helper_vfp_touhd_mips64el
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_mips64el
|
||||
#define helper_vfp_touhh helper_vfp_touhh_mips64el
|
||||
#define helper_vfp_touhs helper_vfp_touhs_mips64el
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_mips64el
|
||||
#define helper_vfp_touid helper_vfp_touid_mips64el
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_mipsel
|
||||
#define helper_vfp_toshd helper_vfp_toshd_mipsel
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_mipsel
|
||||
#define helper_vfp_toshh helper_vfp_toshh_mipsel
|
||||
#define helper_vfp_toshs helper_vfp_toshs_mipsel
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_mipsel
|
||||
#define helper_vfp_tosid helper_vfp_tosid_mipsel
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_mipsel
|
||||
#define helper_vfp_touhd helper_vfp_touhd_mipsel
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_mipsel
|
||||
#define helper_vfp_touhh helper_vfp_touhh_mipsel
|
||||
#define helper_vfp_touhs helper_vfp_touhs_mipsel
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_mipsel
|
||||
#define helper_vfp_touid helper_vfp_touid_mipsel
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_powerpc
|
||||
#define helper_vfp_toshd helper_vfp_toshd_powerpc
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_powerpc
|
||||
#define helper_vfp_toshh helper_vfp_toshh_powerpc
|
||||
#define helper_vfp_toshs helper_vfp_toshs_powerpc
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_powerpc
|
||||
#define helper_vfp_tosid helper_vfp_tosid_powerpc
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_powerpc
|
||||
#define helper_vfp_touhd helper_vfp_touhd_powerpc
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_powerpc
|
||||
#define helper_vfp_touhh helper_vfp_touhh_powerpc
|
||||
#define helper_vfp_touhs helper_vfp_touhs_powerpc
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_powerpc
|
||||
#define helper_vfp_touid helper_vfp_touid_powerpc
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_sparc
|
||||
#define helper_vfp_toshd helper_vfp_toshd_sparc
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_sparc
|
||||
#define helper_vfp_toshh helper_vfp_toshh_sparc
|
||||
#define helper_vfp_toshs helper_vfp_toshs_sparc
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_sparc
|
||||
#define helper_vfp_tosid helper_vfp_tosid_sparc
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_sparc
|
||||
#define helper_vfp_touhd helper_vfp_touhd_sparc
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_sparc
|
||||
#define helper_vfp_touhh helper_vfp_touhh_sparc
|
||||
#define helper_vfp_touhs helper_vfp_touhs_sparc
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_sparc
|
||||
#define helper_vfp_touid helper_vfp_touid_sparc
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_sparc64
|
||||
#define helper_vfp_toshd helper_vfp_toshd_sparc64
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_sparc64
|
||||
#define helper_vfp_toshh helper_vfp_toshh_sparc64
|
||||
#define helper_vfp_toshs helper_vfp_toshs_sparc64
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_sparc64
|
||||
#define helper_vfp_tosid helper_vfp_tosid_sparc64
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_sparc64
|
||||
#define helper_vfp_touhd helper_vfp_touhd_sparc64
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_sparc64
|
||||
#define helper_vfp_touhh helper_vfp_touhh_sparc64
|
||||
#define helper_vfp_touhs helper_vfp_touhs_sparc64
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_sparc64
|
||||
#define helper_vfp_touid helper_vfp_touid_sparc64
|
||||
|
|
|
@ -10676,11 +10676,60 @@ VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
|
|||
VFP_CONV_FIX(uh, s, 32, 32, uint16)
|
||||
VFP_CONV_FIX(ul, s, 32, 32, uint32)
|
||||
VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
|
||||
VFP_CONV_FIX_A64(sl, h, 16, 32, int32)
|
||||
VFP_CONV_FIX_A64(ul, h, 16, 32, uint32)
|
||||
|
||||
#undef VFP_CONV_FIX
|
||||
#undef VFP_CONV_FIX_FLOAT
|
||||
#undef VFP_CONV_FLOAT_FIX_ROUND
|
||||
#undef VFP_CONV_FIX_A64
|
||||
|
||||
/* Conversion to/from f16 can overflow to infinity before/after scaling.
|
||||
* Therefore we convert to f64 (which does not round), scale,
|
||||
* and then convert f64 to f16 (which may round).
|
||||
*/
|
||||
|
||||
static float16 do_postscale_fp16(float64 f, int shift, float_status *fpst)
|
||||
{
|
||||
return float64_to_float16(float64_scalbn(f, -shift, fpst), true, fpst);
|
||||
}
|
||||
|
||||
float16 HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
|
||||
{
|
||||
return do_postscale_fp16(int32_to_float64(x, fpst), shift, fpst);
|
||||
}
|
||||
|
||||
float16 HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
|
||||
{
|
||||
return do_postscale_fp16(uint32_to_float64(x, fpst), shift, fpst);
|
||||
}
|
||||
|
||||
static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
|
||||
{
|
||||
if (unlikely(float16_is_any_nan(f))) {
|
||||
float_raise(float_flag_invalid, fpst);
|
||||
return 0;
|
||||
} else {
|
||||
int old_exc_flags = get_float_exception_flags(fpst);
|
||||
float64 ret;
|
||||
|
||||
ret = float16_to_float64(f, true, fpst);
|
||||
ret = float64_scalbn(ret, shift, fpst);
|
||||
old_exc_flags |= get_float_exception_flags(fpst)
|
||||
& float_flag_input_denormal;
|
||||
set_float_exception_flags(old_exc_flags, fpst);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HELPER(vfp_toshh)(float16 x, uint32_t shift, void *fpst)
|
||||
{
|
||||
return float64_to_int16(do_prescale_fp16(x, shift, fpst), fpst);
|
||||
}
|
||||
|
||||
uint32_t HELPER(vfp_touhh)(float16 x, uint32_t shift, void *fpst)
|
||||
{
|
||||
return float64_to_uint16(do_prescale_fp16(x, shift, fpst), fpst);
|
||||
}
|
||||
|
||||
/* Set the current fp rounding mode and return the old one.
|
||||
* The argument is a softfloat float_round_ value.
|
||||
|
|
|
@ -151,8 +151,8 @@ DEF_HELPER_3(vfp_toshd_round_to_zero, i64, f64, i32, ptr)
|
|||
DEF_HELPER_3(vfp_tosld_round_to_zero, i64, f64, i32, ptr)
|
||||
DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
|
||||
DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
|
||||
DEF_HELPER_3(vfp_toulh, i32, f16, i32, ptr)
|
||||
DEF_HELPER_3(vfp_toslh, i32, f16, i32, ptr)
|
||||
DEF_HELPER_3(vfp_touhh, i32, f16, i32, ptr)
|
||||
DEF_HELPER_3(vfp_toshh, i32, f16, i32, ptr)
|
||||
DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
|
||||
DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
|
||||
DEF_HELPER_3(vfp_tosqs, i64, f32, i32, ptr)
|
||||
|
|
|
@ -7632,9 +7632,9 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
|
|||
switch (size) {
|
||||
case MO_16:
|
||||
if (is_u) {
|
||||
fn = gen_helper_vfp_toulh;
|
||||
fn = gen_helper_vfp_touhh;
|
||||
} else {
|
||||
fn = gen_helper_vfp_toslh;
|
||||
fn = gen_helper_vfp_toshh;
|
||||
}
|
||||
break;
|
||||
case MO_32:
|
||||
|
|
|
@ -1701,6 +1701,7 @@
|
|||
#define helper_vfp_subs helper_vfp_subs_x86_64
|
||||
#define helper_vfp_toshd helper_vfp_toshd_x86_64
|
||||
#define helper_vfp_toshd_round_to_zero helper_vfp_toshd_round_to_zero_x86_64
|
||||
#define helper_vfp_toshh helper_vfp_toshh_x86_64
|
||||
#define helper_vfp_toshs helper_vfp_toshs_x86_64
|
||||
#define helper_vfp_toshs_round_to_zero helper_vfp_toshs_round_to_zero_x86_64
|
||||
#define helper_vfp_tosid helper_vfp_tosid_x86_64
|
||||
|
@ -1718,6 +1719,7 @@
|
|||
#define helper_vfp_tosqs helper_vfp_tosqs_x86_64
|
||||
#define helper_vfp_touhd helper_vfp_touhd_x86_64
|
||||
#define helper_vfp_touhd_round_to_zero helper_vfp_touhd_round_to_zero_x86_64
|
||||
#define helper_vfp_touhh helper_vfp_touhh_x86_64
|
||||
#define helper_vfp_touhs helper_vfp_touhs_x86_64
|
||||
#define helper_vfp_touhs_round_to_zero helper_vfp_touhs_round_to_zero_x86_64
|
||||
#define helper_vfp_touid helper_vfp_touid_x86_64
|
||||
|
|
Loading…
Reference in a new issue