Message ID | 20230826160242.312052-6-kbastian@mail.uni-paderborn.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TriCore 1.6.2 insn and bugfixes | expand |
On 8/26/23 09:02, Bastian Koppelmann wrote: > +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) > +{ > + float32 f_arg = make_float32(arg); > + uint32_t result = 0; > + int32_t flags = 0; > + > + if (float32_is_infinity(f_arg)) { > + if (float32_is_neg(f_arg)) { > + return HP_NEG_INFINITY; > + } else { > + return HP_POS_INFINITY; > + } > + } else if (float32_is_any_nan(f_arg)) { > + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { > + flags |= float_flag_invalid; > + } > + result = float16_set_sign(result, arg >> 31); > + result = deposit32(result, 10, 5, 0x1f); > + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); > + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); > + if (extract32(result, 0, 10) == 0) { > + result |= (1 << 8); > + } > + } else { > + set_flush_to_zero(0, &env->fp_status); > + result = float32_to_float16(f_arg, true, &env->fp_status); > + set_flush_to_zero(1, &env->fp_status); > + flags = f_get_excp_flags(env); > + } All of this is standard behaviour. All you need is the final else case. > + set_float_detect_tininess(true, &env->fp_status); s/true/float_tininess_before_rounding/ r~
On Sat, Aug 26, 2023 at 09:55:05PM -0700, Richard Henderson wrote: > On 8/26/23 09:02, Bastian Koppelmann wrote: > > +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) > > +{ > > + float32 f_arg = make_float32(arg); > > + uint32_t result = 0; > > + int32_t flags = 0; > > + > > + if (float32_is_infinity(f_arg)) { > > + if (float32_is_neg(f_arg)) { > > + return HP_NEG_INFINITY; > > + } else { > > + return HP_POS_INFINITY; > > + } > > + } else if (float32_is_any_nan(f_arg)) { > > + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { > > + flags |= float_flag_invalid; > > + } > > + result = float16_set_sign(result, arg >> 31); > > + result = deposit32(result, 10, 5, 0x1f); > > + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); > > + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); > > + if (extract32(result, 0, 10) == 0) { > > + result |= (1 << 8); > > + } > > + } else { > > + set_flush_to_zero(0, &env->fp_status); > > + result = float32_to_float16(f_arg, true, &env->fp_status); > > + set_flush_to_zero(1, &env->fp_status); > > + flags = f_get_excp_flags(env); > > + } > > All of this is standard behaviour. All you need is the final else case. Unfortunately not quite. For NANs the top 2 and lower 8 output mantissa bits need to be set to the top 2 and lower 8 input mantissa bits respectively. This behaviour is unique to ftohp and hptof, so I don't think we should specialize it in parts64_default_nan(). Cheers, Bastian
On 8/27/23 00:09, Bastian Koppelmann wrote: > On Sat, Aug 26, 2023 at 09:55:05PM -0700, Richard Henderson wrote: >> On 8/26/23 09:02, Bastian Koppelmann wrote: >>> +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) >>> +{ >>> + float32 f_arg = make_float32(arg); >>> + uint32_t result = 0; >>> + int32_t flags = 0; >>> + >>> + if (float32_is_infinity(f_arg)) { >>> + if (float32_is_neg(f_arg)) { >>> + return HP_NEG_INFINITY; >>> + } else { >>> + return HP_POS_INFINITY; >>> + } >>> + } else if (float32_is_any_nan(f_arg)) { >>> + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { >>> + flags |= float_flag_invalid; >>> + } >>> + result = float16_set_sign(result, arg >> 31); >>> + result = deposit32(result, 10, 5, 0x1f); >>> + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); >>> + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); >>> + if (extract32(result, 0, 10) == 0) { >>> + result |= (1 << 8); >>> + } >>> + } else { >>> + set_flush_to_zero(0, &env->fp_status); >>> + result = float32_to_float16(f_arg, true, &env->fp_status); >>> + set_flush_to_zero(1, &env->fp_status); >>> + flags = f_get_excp_flags(env); >>> + } >> >> All of this is standard behaviour. All you need is the final else case. > > Unfortunately not quite. For NANs the top 2 and lower 8 output mantissa bits need to be > set to the top 2 and lower 8 input mantissa bits respectively. This behaviour is > unique to ftohp and hptof, so I don't think we should specialize it in > parts64_default_nan(). Ah, whereas softfloat grabs the top 10 mantissa bits. This could use a comment to that effect. Certainly you don't need to special case infinity though. r~
diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index ceacb6657e..3db2341ac0 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -27,6 +27,8 @@ #define SQRT_NAN 0x7fc00004 #define DIV_NAN 0x7fc00008 #define MUL_NAN 0x7fc00002 +#define HP_NEG_INFINITY 0xfc00 +#define HP_POS_INFINITY 0x7c00 #define FPU_FS PSW_USB_C #define FPU_FI PSW_USB_V #define FPU_FV PSW_USB_SV @@ -373,6 +375,45 @@ uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) return (uint32_t)result; } +uint32_t helper_ftohp(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result = 0; + int32_t flags = 0; + + if (float32_is_infinity(f_arg)) { + if (float32_is_neg(f_arg)) { + return HP_NEG_INFINITY; + } else { + return HP_POS_INFINITY; + } + } else if (float32_is_any_nan(f_arg)) { + if (float32_is_signaling_nan(f_arg, &env->fp_status)) { + flags |= float_flag_invalid; + } + result = float16_set_sign(result, arg >> 31); + result = deposit32(result, 10, 5, 0x1f); + result = deposit32(result, 8, 2, extract32(arg, 21, 2)); + result = deposit32(result, 0, 8, extract32(arg, 0, 8)); + if (extract32(result, 0, 10) == 0) { + result |= (1 << 8); + } + } else { + set_flush_to_zero(0, &env->fp_status); + result = float32_to_float16(f_arg, true, &env->fp_status); + set_flush_to_zero(1, &env->fp_status); + flags = f_get_excp_flags(env); + } + + if (flags) { + f_update_psw_flags(env, flags); + } else { + env->FPU_FS = 0; + } + + return result; +} + uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) { float32 f_result; diff --git a/target/tricore/helper.c b/target/tricore/helper.c index e615c3d6d4..6ccb52fea7 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -137,6 +137,7 @@ void fpu_set_state(CPUTriCoreState *env) set_flush_inputs_to_zero(1, &env->fp_status); set_flush_to_zero(1, &env->fp_status); + set_float_detect_tininess(true, &env->fp_status); set_default_nan_mode(1, &env->fp_status); } diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 827fbaa692..dcc5a492b3 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -111,6 +111,7 @@ DEF_HELPER_4(fmsub, i32, env, i32, i32, i32) DEF_HELPER_3(fcmp, i32, env, i32, i32) DEF_HELPER_2(qseed, i32, env, i32) DEF_HELPER_2(ftoi, i32, env, i32) +DEF_HELPER_2(ftohp, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index fb9a7113a8..d94c273f89 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6264,6 +6264,13 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_DIV_F: gen_helper_fdiv(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; + case OPC2_32_RR_FTOHP: + if (has_feature(ctx, TRICORE_FEATURE_162)) { + gen_helper_ftohp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + } else { + generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC); + } + break; case OPC2_32_RR_CMP_F: gen_helper_fcmp(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]); break; diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h index f070571665..29e655a667 100644 --- a/target/tricore/tricore-opcodes.h +++ b/target/tricore/tricore-opcodes.h @@ -1152,6 +1152,7 @@ enum { OPC2_32_RR_ITOF = 0x14, OPC2_32_RR_CMP_F = 0x00, OPC2_32_RR_FTOIZ = 0x13, + OPC2_32_RR_FTOHP = 0x25, /* 1.6.2 only */ OPC2_32_RR_FTOQ31 = 0x11, OPC2_32_RR_FTOQ31Z = 0x18, OPC2_32_RR_FTOU = 0x12, diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index e6ed5c56f2..f4a27a83e4 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -14,6 +14,7 @@ TESTS += test_dextr.asm.tst TESTS += test_dvstep.asm.tst TESTS += test_fadd.asm.tst TESTS += test_fmul.asm.tst +TESTS += test_ftohp.asm.tst TESTS += test_ftoi.asm.tst TESTS += test_ftou.asm.tst TESTS += test_imask.asm.tst diff --git a/tests/tcg/tricore/asm/test_ftohp.S b/tests/tcg/tricore/asm/test_ftohp.S new file mode 100644 index 0000000000..9e23141c1e --- /dev/null +++ b/tests/tcg/tricore/asm/test_ftohp.S @@ -0,0 +1,14 @@ +#include "macros.h" +.text +.global _start +_start: + TEST_D_D(ftohp, 1, 0xffff, 0xffffffff) + TEST_D_D(ftohp, 2, 0xfc00, 0xff800000) + TEST_D_D(ftohp, 3, 0x7c00, 0x7f800000) + TEST_D_D(ftohp, 4, 0x0, 0x0) + TEST_D_D(ftohp, 5, 0x5, 0x34a43580) + + #TEST_D_D_PSW(ftohp, 6, 0x400, 0x8c000b80, 0x387fee74) + + TEST_PASSFAIL +
reported in https://gitlab.com/qemu-project/qemu/-/issues/1667 Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 41 +++++++++++++++++++++++ target/tricore/helper.c | 1 + target/tricore/helper.h | 1 + target/tricore/translate.c | 7 ++++ target/tricore/tricore-opcodes.h | 1 + tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_ftohp.S | 14 ++++++++ 7 files changed, 66 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_ftohp.S