diff --git a/arch/inst/F/fadd.s.yaml b/arch/inst/F/fadd.s.yaml index 5553eedffa..98a28185fe 100644 --- a/arch/inst/F/fadd.s.yaml +++ b/arch/inst/F/fadd.s.yaml @@ -27,7 +27,8 @@ access: vu: always data_independent_timing: true operation(): | - RoundingMode mode = rm_to_mode(X[rm], $encoding); + check_f_ok($encoding); + RoundingMode mode = rm_to_mode(rm, $encoding); X[fd] = f32_add(X[fs1], X[fs2], mode); sail(): | diff --git a/arch/inst/F/fcvt.s.w.yaml b/arch/inst/F/fcvt.s.w.yaml index 9e0d646c01..f79c946b02 100644 --- a/arch/inst/F/fcvt.s.w.yaml +++ b/arch/inst/F/fcvt.s.w.yaml @@ -34,20 +34,8 @@ access: data_independent_timing: false operation(): | check_f_ok($encoding); - - Bits<32> int_value = X[rs1]; - - Bits<1> sign = int_value[31]; - RoundingMode rounding_mode = rm_to_mode(rm, $encoding); - - if ((int_value & 32'h7fff_ffff) == 0) { - X[fd] = (sign == 1) ? packToF32UI(1, 0x9E, 0) : 0; - } else { - Bits<32> absA = (sign == 1) ? -int_value : int_value; - X[fd] = softfloat_normRoundPackToF32( sign, 0x9C, absA, rounding_mode ); - } - + X[fd] = i32_to_f32(X[rs1], rounding_mode); mark_f_state_dirty(); sail(): | diff --git a/arch/inst/F/fcvt.s.wu.yaml b/arch/inst/F/fcvt.s.wu.yaml index 57fab4e22c..a0474330c6 100644 --- a/arch/inst/F/fcvt.s.wu.yaml +++ b/arch/inst/F/fcvt.s.wu.yaml @@ -3,9 +3,18 @@ $schema: "inst_schema.json#" kind: instruction name: fcvt.s.wu -long_name: No synopsis available. +long_name: Convert unsigned 32-bit integer to single-precision float description: | - No description available. + Converts a 32-bit unsigned integer in integer register _rs1_ into a floating-point number in + floating-point register _fd_. + + All floating-point to integer and integer to floating-point conversion instructions round + according to the _rm_ field. + A floating-point register can be initialized to floating-point positive zero using + `fcvt.s.w rd, x0`, which will never set any exception flags. + + All floating-point conversion instructions set the Inexact exception flag if the rounded + result differs from the operand value and the Invalid exception flag is not set. definedBy: F assembly: fd, xs1, rm encoding: @@ -24,7 +33,10 @@ access: vu: always data_independent_timing: true operation(): | - + check_f_ok($encoding); + RoundingMode rounding_mode = rm_to_mode(rm, $encoding); + X[fd] = ui32_to_f32(X[rs1], rounding_mode); + mark_f_state_dirty(); sail(): | { assert(sizeof(xlen) >= 64); diff --git a/arch/inst/F/fsub.s.yaml b/arch/inst/F/fsub.s.yaml index b0622f32ad..905c1a6b7e 100644 --- a/arch/inst/F/fsub.s.yaml +++ b/arch/inst/F/fsub.s.yaml @@ -27,7 +27,8 @@ access: vu: always data_independent_timing: true operation(): | - RoundingMode mode = rm_to_mode(X[rm], $encoding); + check_f_ok($encoding); + RoundingMode mode = rm_to_mode(rm, $encoding); X[fd] = f32_sub(X[fs1], X[fs2], mode); sail(): | { diff --git a/arch/isa/fp.idl b/arch/isa/fp.idl index c5386b455d..e49ce20585 100644 --- a/arch/isa/fp.idl +++ b/arch/isa/fp.idl @@ -882,3 +882,43 @@ function f32_sub { } } } + +function i32_to_f32 { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit signed integer to 32-bit floating point + } + body { + # sign of integer, it is 1 when negative + Bits<1> sign = a[31]; + if ((a & 0x7FFFFFFF) == 0) { + return (sign == 1) ? packToF32UI(1, 0x9E, 0) : packToF32UI(0, 0, 0); + } + U32 magnitude_of_A = returnMag(a); + return softfloat_normRoundPackToF32(sign, 0x9C, magnitude_of_A, mode); + } +} + +function ui32_to_f32 { + returns U32 + arguments + U32 a, + RoundingMode mode + description { + Converts 32-bit unsigned integer to 32-bit floating point + } + body { + # sign of integer, it is 1 when negative + if (a == 0) { + return a; + } + if (a[31] == 1) { + return softfloat_roundPackToF32(0, 0x9D, a>>1 | (a & 1), mode); + } else { + return softfloat_normRoundPackToF32(0, 0x9C, a, mode); + } + } +}