Message ID | 20230826160242.312052-5-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_ftou(CPUTriCoreState *env, uint32_t arg) > +{ > + float32 f_arg = make_float32(arg); > + uint32_t result; > + int32_t flags = 0; > + > + if (float32_is_any_nan(f_arg)) { > + result = 0; > + flags |= float_flag_invalid; > + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { > + result = 0; > + flags = float_flag_invalid; > + } else { > + result = float32_to_uint32(f_arg, &env->fp_status); > + flags = f_get_excp_flags(env); > + } You should allow softfloat to diagnose the special cases, and negative -> 0 is standard behaviour. Therefore: result = float32_to_uint32(f_arg, status); flags = f_get_excp_flags(); if (flags) { if ((flags & float_flag_invalid) && !(get_float_exception_flags() & float_flag_invalid_cvti)) { /* invalid without cvti is nan input */ result = 0; } f_update_psw_flags(...); } else { fs = 0; } r~
On Sat, Aug 26, 2023 at 09:50:51PM -0700, Richard Henderson wrote: > On 8/26/23 09:02, Bastian Koppelmann wrote: > > +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) > > +{ > > + float32 f_arg = make_float32(arg); > > + uint32_t result; > > + int32_t flags = 0; > > + > > + if (float32_is_any_nan(f_arg)) { > > + result = 0; > > + flags |= float_flag_invalid; > > + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { > > + result = 0; > > + flags = float_flag_invalid; > > + } else { > > + result = float32_to_uint32(f_arg, &env->fp_status); > > + flags = f_get_excp_flags(env); > > + } > > You should allow softfloat to diagnose the special cases, and negative -> 0 > is standard behaviour. Therefore: You're right. However, there is one special case, negative -> 0 ought to raise float_flags_invalid. All that has already been done for ftouz, so I will match that implementation. Cheers, Bastian
On 8/27/23 04:07, Bastian Koppelmann wrote: > On Sat, Aug 26, 2023 at 09:50:51PM -0700, Richard Henderson wrote: >> On 8/26/23 09:02, Bastian Koppelmann wrote: >>> +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) >>> +{ >>> + float32 f_arg = make_float32(arg); >>> + uint32_t result; >>> + int32_t flags = 0; >>> + >>> + if (float32_is_any_nan(f_arg)) { >>> + result = 0; >>> + flags |= float_flag_invalid; >>> + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { >>> + result = 0; >>> + flags = float_flag_invalid; >>> + } else { >>> + result = float32_to_uint32(f_arg, &env->fp_status); >>> + flags = f_get_excp_flags(env); >>> + } >> >> You should allow softfloat to diagnose the special cases, and negative -> 0 >> is standard behaviour. Therefore: > > You're right. However, there is one special case, negative -> 0 ought to raise > float_flags_invalid. https://gitlab.com/qemu-project/qemu/-/blob/master/fpu/softfloat-parts.c.inc?ref_type=heads#L1162 Already done. As I say, this is all standard IEEE behaviour. r~
On Sun, Aug 27, 2023 at 07:49:52AM -0700, Richard Henderson wrote: > On 8/27/23 04:07, Bastian Koppelmann wrote: > > On Sat, Aug 26, 2023 at 09:50:51PM -0700, Richard Henderson wrote: > > > On 8/26/23 09:02, Bastian Koppelmann wrote: > > > > +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) > > > > +{ > > > > + float32 f_arg = make_float32(arg); > > > > + uint32_t result; > > > > + int32_t flags = 0; > > > > + > > > > + if (float32_is_any_nan(f_arg)) { > > > > + result = 0; > > > > + flags |= float_flag_invalid; > > > > + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { > > > > + result = 0; > > > > + flags = float_flag_invalid; > > > > + } else { > > > > + result = float32_to_uint32(f_arg, &env->fp_status); > > > > + flags = f_get_excp_flags(env); > > > > + } > > > > > > You should allow softfloat to diagnose the special cases, and negative -> 0 > > > is standard behaviour. Therefore: > > > > You're right. However, there is one special case, negative -> 0 ought to raise > > float_flags_invalid. > > https://gitlab.com/qemu-project/qemu/-/blob/master/fpu/softfloat-parts.c.inc?ref_type=heads#L1162 Lets say the exponent is negative and the sign is negative, then we raise float_flag_inexact and we never reach the code you mentioned here. However, TriCore HW raises float_flag_invalid as well in that case. This is what I'm catching with float32_lt_quiet() in the same manner as ftouz. Cheers, Bastian
On 8/27/23 09:36, Bastian Koppelmann wrote: > On Sun, Aug 27, 2023 at 07:49:52AM -0700, Richard Henderson wrote: >> On 8/27/23 04:07, Bastian Koppelmann wrote: >>> On Sat, Aug 26, 2023 at 09:50:51PM -0700, Richard Henderson wrote: >>>> On 8/26/23 09:02, Bastian Koppelmann wrote: >>>>> +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) >>>>> +{ >>>>> + float32 f_arg = make_float32(arg); >>>>> + uint32_t result; >>>>> + int32_t flags = 0; >>>>> + >>>>> + if (float32_is_any_nan(f_arg)) { >>>>> + result = 0; >>>>> + flags |= float_flag_invalid; >>>>> + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { >>>>> + result = 0; >>>>> + flags = float_flag_invalid; >>>>> + } else { >>>>> + result = float32_to_uint32(f_arg, &env->fp_status); >>>>> + flags = f_get_excp_flags(env); >>>>> + } >>>> >>>> You should allow softfloat to diagnose the special cases, and negative -> 0 >>>> is standard behaviour. Therefore: >>> >>> You're right. However, there is one special case, negative -> 0 ought to raise >>> float_flags_invalid. >> >> https://gitlab.com/qemu-project/qemu/-/blob/master/fpu/softfloat-parts.c.inc?ref_type=heads#L1162 > > Lets say the exponent is negative and the sign is negative, then we raise > float_flag_inexact and we never reach the code you mentioned here. However, > TriCore HW raises float_flag_invalid as well in that case. This is what I'm > catching with float32_lt_quiet() in the same manner as ftouz. Hmph. Buggy hardware. You'd better document this special case, that less-than-zero is detected before rounding. I presume -0.0 does not raise invalid, that the bug does not extend that far? r~
On Sun, Aug 27, 2023 at 11:32:03AM -0700, Richard Henderson wrote: > On 8/27/23 09:36, Bastian Koppelmann wrote: > > On Sun, Aug 27, 2023 at 07:49:52AM -0700, Richard Henderson wrote: > > > On 8/27/23 04:07, Bastian Koppelmann wrote: > > > > On Sat, Aug 26, 2023 at 09:50:51PM -0700, Richard Henderson wrote: > > > > > On 8/26/23 09:02, Bastian Koppelmann wrote: > > > > > > +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) > > > > > > +{ > > > > > > + float32 f_arg = make_float32(arg); > > > > > > + uint32_t result; > > > > > > + int32_t flags = 0; > > > > > > + > > > > > > + if (float32_is_any_nan(f_arg)) { > > > > > > + result = 0; > > > > > > + flags |= float_flag_invalid; > > > > > > + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { > > > > > > + result = 0; > > > > > > + flags = float_flag_invalid; > > > > > > + } else { > > > > > > + result = float32_to_uint32(f_arg, &env->fp_status); > > > > > > + flags = f_get_excp_flags(env); > > > > > > + } > > > > > > > > > > You should allow softfloat to diagnose the special cases, and negative -> 0 > > > > > is standard behaviour. Therefore: > > > > > > > > You're right. However, there is one special case, negative -> 0 ought to raise > > > > float_flags_invalid. > > > > > > https://gitlab.com/qemu-project/qemu/-/blob/master/fpu/softfloat-parts.c.inc?ref_type=heads#L1162 > > > > Lets say the exponent is negative and the sign is negative, then we raise > > float_flag_inexact and we never reach the code you mentioned here. However, > > TriCore HW raises float_flag_invalid as well in that case. This is what I'm > > catching with float32_lt_quiet() in the same manner as ftouz. > > Hmph. Buggy hardware. You'd better document this special case, > that less-than-zero is detected before rounding. Will do. I'll do the same for ftouz. > > I presume -0.0 does not raise invalid, that the bug does not extend that far? Yes, -0.0 does not raise invalid. Cheers, Bastian
diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index cb7ee7dd35..ceacb6657e 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -429,6 +429,31 @@ uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg) return result; } +uint32_t helper_ftou(CPUTriCoreState *env, uint32_t arg) +{ + float32 f_arg = make_float32(arg); + uint32_t result; + int32_t flags = 0; + + if (float32_is_any_nan(f_arg)) { + result = 0; + flags |= float_flag_invalid; + } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { + result = 0; + flags = float_flag_invalid; + } else { + result = float32_to_uint32(f_arg, &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_ftouz(CPUTriCoreState *env, uint32_t arg) { float32 f_arg = make_float32(arg); diff --git a/target/tricore/helper.h b/target/tricore/helper.h index 190645413a..827fbaa692 100644 --- a/target/tricore/helper.h +++ b/target/tricore/helper.h @@ -114,6 +114,7 @@ DEF_HELPER_2(ftoi, i32, env, i32) DEF_HELPER_2(itof, i32, env, i32) DEF_HELPER_2(utof, i32, env, i32) DEF_HELPER_2(ftoiz, i32, env, i32) +DEF_HELPER_2(ftou, i32, env, i32) DEF_HELPER_2(ftouz, i32, env, i32) DEF_HELPER_2(updfl, void, env, i32) /* dvinit */ diff --git a/target/tricore/translate.c b/target/tricore/translate.c index bb7dad75d6..fb9a7113a8 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -6273,6 +6273,9 @@ static void decode_rr_divide(DisasContext *ctx) case OPC2_32_RR_ITOF: gen_helper_itof(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; + case OPC2_32_RR_FTOU: + gen_helper_ftou(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); + break; case OPC2_32_RR_FTOUZ: gen_helper_ftouz(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1]); break; diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target index 7a7d73a60c..e6ed5c56f2 100644 --- a/tests/tcg/tricore/Makefile.softmmu-target +++ b/tests/tcg/tricore/Makefile.softmmu-target @@ -15,6 +15,7 @@ TESTS += test_dvstep.asm.tst TESTS += test_fadd.asm.tst TESTS += test_fmul.asm.tst TESTS += test_ftoi.asm.tst +TESTS += test_ftou.asm.tst TESTS += test_imask.asm.tst TESTS += test_insert.asm.tst TESTS += test_ld_bu.asm.tst diff --git a/tests/tcg/tricore/asm/test_ftou.S b/tests/tcg/tricore/asm/test_ftou.S new file mode 100644 index 0000000000..10f106ad62 --- /dev/null +++ b/tests/tcg/tricore/asm/test_ftou.S @@ -0,0 +1,12 @@ +#include "macros.h" +.text +.global _start +_start: + TEST_D_D(ftou, 1, 0x00000000, 0x1733f6c2) + TEST_D_D(ftou, 2, 0x00000000, 0x2c9d9cdc) + TEST_D_D(ftou, 3, 0xffffffff, 0x56eb7395) + TEST_D_D(ftou, 4, 0x79900800, 0x4ef32010) + TEST_D_D(ftou, 5, 0x0353f510, 0x4c54fd44) + + TEST_PASSFAIL +
Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> --- target/tricore/fpu_helper.c | 25 +++++++++++++++++++++++ target/tricore/helper.h | 1 + target/tricore/translate.c | 3 +++ tests/tcg/tricore/Makefile.softmmu-target | 1 + tests/tcg/tricore/asm/test_ftou.S | 12 +++++++++++ 5 files changed, 42 insertions(+) create mode 100644 tests/tcg/tricore/asm/test_ftou.S