Skip to content

Commit

Permalink
fpu/softfloat: Partial support for ARM Alternative half-precision
Browse files Browse the repository at this point in the history
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.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
stsquad authored and rth7680 committed May 17, 2018
1 parent 0acb9e7 commit ca3a3d5
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions fpu/softfloat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 below 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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ca3a3d5

Please sign in to comment.