On Fri, 15 Feb 2019 at 19:23, Richard Henderson <richard.hender...@linaro.org> wrote: > > Note that float16_to_float32 rightly squashes SNaN to QNaN. > But of course pickNaNMulAdd, for ARM, selects SNaNs first. > So we have to preserve SNaN long enough for the correct NaN > to be selected. Thus float16_to_float32_by_bits. > > Signed-off-by: Richard Henderson <richard.hender...@linaro.org> > ---
> +/* > + * Convert float16 to float32, raising no exceptions and > + * preserving exceptional values, including SNaN. > + * This is effectively an unpack+repack operation. > + */ > +static float32 float16_to_float32_by_bits(uint32_t f16) > +{ > + const int f16_bias = 15; > + const int f32_bias = 127; > + uint32_t sign = extract32(f16, 15, 1); > + uint32_t exp = extract32(f16, 10, 5); > + uint32_t frac = extract32(f16, 0, 10); > + > + if (exp == 0x1f) { > + /* Inf or NaN */ > + exp = 0xff; > + } else if (exp == 0) { > + /* Zero or denormal. */ > + if (frac != 0) { > + /* > + * Denormal; these are all normal float32. > + * Shift the fraction so that the msb is at bit 11, > + * then remove bit 11 as the implicit bit of the > + * normalized float32. Note that we still go through > + * the shift for normal numbers below, to put the > + * float32 fraction at the right place. > + */ > + int shift = clz32(frac) - 21; > + frac = (frac << shift) & 0x3ff; > + exp = f32_bias - f16_bias - shift + 1; > + } > + } else { > + /* Normal number; adjust the bias. */ > + exp += f32_bias - f16_bias; > + } > + sign <<= 31; > + exp <<= 23; > + frac <<= 23 - 10; > + > + return sign | exp | frac; > +} Shouldn't we be observing FPCR.FZ16 here and flushing denormal float16 inputs to zero if it's set ? (In the pseudocode this happens in FPUnpackBase, called from FPUnpack.) NB: this might be awkward because for A64 we need to use the fpstatus with FZ16 in it (vfp.fp_status_f16) for the float16 inputs, but the one with the normal FZ bit (vfp.fp_status) for the float32 input. thanks -- PMM