diff mbox series

[v5,13/28] fpu/softfloat: Partial support for ARM Alternative half-precision

Message ID 20180514221219.7091-14-richard.henderson@linaro.org
State Superseded
Headers show
Series softfloat patch roundup | expand

Commit Message

Richard Henderson May 14, 2018, 10:12 p.m. UTC
From: Alex Bennée <alex.bennee@linaro.org>


For float16 ARM supports an alternative half-precision format which
sacrifices the ability to represent NaN/Inf in return for a higher
dynamic range.  The new FloatFmt flag, arm_althp, is then used to
modify the behaviour of canonicalize and round_canonical with respect
to representation and exception raising.

Usage of this new flag waits until we re-factor float-to-float conversions.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>


---
v3
  - squash NaN to 0 if destination is AHP F16
v4
  - handle inf -> ahp max in float_to_float not round_canonical
  - assert no nan and inf for ahp in round_canonical
  - check ahp before snan in float_to_float
v5
  - split out canonicalize and round_canonical changes from the rest
---
 fpu/softfloat.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

-- 
2.17.0

Comments

Peter Maydell May 15, 2018, 10:52 a.m. UTC | #1
On 14 May 2018 at 23:12, Richard Henderson <richard.henderson@linaro.org> wrote:
> From: Alex Bennée <alex.bennee@linaro.org>

>

> For float16 ARM supports an alternative half-precision format which

> sacrifices the ability to represent NaN/Inf in return for a higher

> dynamic range.  The new FloatFmt flag, arm_althp, is then used to

> modify the behaviour of canonicalize and round_canonical with respect

> to representation and exception raising.

>

> Usage of this new flag waits until we re-factor float-to-float conversions.

>

> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

>

> ---

> v3

>   - squash NaN to 0 if destination is AHP F16

> v4

>   - handle inf -> ahp max in float_to_float not round_canonical

>   - assert no nan and inf for ahp in round_canonical

>   - check ahp before snan in float_to_float

> v5

>   - split out canonicalize and round_canonical changes from the rest

> ---

>  fpu/softfloat.c | 19 ++++++++++++++++---

>  1 file changed, 16 insertions(+), 3 deletions(-)

>

> diff --git a/fpu/softfloat.c b/fpu/softfloat.c

> index 41253c6749..55d0d01ec3 100644

> --- a/fpu/softfloat.c

> +++ b/fpu/softfloat.c

> @@ -220,8 +220,10 @@ typedef struct {

>   *   frac_shift: shift to normalise the fraction with DECOMPOSED_BINARY_POINT

>   * The following are computed based the size of fraction

>   *   frac_lsb: least significant bit of fraction

> - *   fram_lsbm1: the bit bellow the least significant bit (for rounding)

> + *   frac_lsbm1: the bit bellow the least significant bit (for rounding)


"below"

>   *   round_mask/roundeven_mask: masks used for rounding

> + * The following optional modifiers are available:

> + *   arm_althp: handle ARM Alternative Half Precision

>   */


Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>


thanks
-- PMM
diff mbox series

Patch

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 41253c6749..55d0d01ec3 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -220,8 +220,10 @@  typedef struct {
  *   frac_shift: shift to normalise the fraction with DECOMPOSED_BINARY_POINT
  * The following are computed based the size of fraction
  *   frac_lsb: least significant bit of fraction
- *   fram_lsbm1: the bit bellow the least significant bit (for rounding)
+ *   frac_lsbm1: the bit bellow the least significant bit (for rounding)
  *   round_mask/roundeven_mask: masks used for rounding
+ * The following optional modifiers are available:
+ *   arm_althp: handle ARM Alternative Half Precision
  */
 typedef struct {
     int exp_size;
@@ -233,6 +235,7 @@  typedef struct {
     uint64_t frac_lsbm1;
     uint64_t round_mask;
     uint64_t roundeven_mask;
+    bool arm_althp;
 } FloatFmt;
 
 /* Expand fields based on the size of exponent and fraction */
@@ -324,7 +327,7 @@  static inline float64 float64_pack_raw(FloatParts p)
 static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
                                float_status *status)
 {
-    if (part.exp == parm->exp_max) {
+    if (part.exp == parm->exp_max && !parm->arm_althp) {
         if (part.frac == 0) {
             part.cls = float_class_inf;
         } else {
@@ -413,7 +416,15 @@  static FloatParts round_canonical(FloatParts p, float_status *s,
             }
             frac >>= frac_shift;
 
-            if (unlikely(exp >= exp_max)) {
+            if (parm->arm_althp) {
+                /* ARM Alt HP eschews Inf and NaN for a wider exponent.  */
+                if (unlikely(exp > exp_max)) {
+                    /* Overflow.  Return the maximum normal.  */
+                    flags = float_flag_invalid;
+                    exp = exp_max;
+                    frac = -1;
+                }
+            } else if (unlikely(exp >= exp_max)) {
                 flags |= float_flag_overflow | float_flag_inexact;
                 if (overflow_norm) {
                     exp = exp_max - 1;
@@ -464,12 +475,14 @@  static FloatParts round_canonical(FloatParts p, float_status *s,
 
     case float_class_inf:
     do_inf:
+        assert(!parm->arm_althp);
         exp = exp_max;
         frac = 0;
         break;
 
     case float_class_qnan:
     case float_class_snan:
+        assert(!parm->arm_althp);
         exp = exp_max;
         frac >>= parm->frac_shift;
         break;