diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 44edbf75..4f90447a 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -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 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 7a715e9e..953ff7d3 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -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 diff --git a/qemu/arm.h b/qemu/arm.h index 5418b130..8aa7bf3d 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -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 diff --git a/qemu/armeb.h b/qemu/armeb.h index 2215a10b..8a2d8067 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -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 diff --git a/qemu/header_gen.py b/qemu/header_gen.py index bcf6c8c1..28c06529 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -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', diff --git a/qemu/m68k.h b/qemu/m68k.h index 3b03b3d9..492e5419 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -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 diff --git a/qemu/mips.h b/qemu/mips.h index 6a6436c1..2aced154 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -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 diff --git a/qemu/mips64.h b/qemu/mips64.h index a0234b41..5916cf39 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -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 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index b96f1712..3b236896 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -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 diff --git a/qemu/mipsel.h b/qemu/mipsel.h index e29b3324..46a6c89f 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -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 diff --git a/qemu/powerpc.h b/qemu/powerpc.h index c403b134..11399a0f 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -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 diff --git a/qemu/sparc.h b/qemu/sparc.h index f944c375..c046b5ef 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -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 diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 922fe413..29153aef 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -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 diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index e0433ff1..e2f36174 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -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. diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index 524e013d..c9002bca 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -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) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index d9701590..45ac5a5c 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -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: diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 3966ccec..ce746b01 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -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