From 86f6e78c6f536ce91583294e219f84477005a3d9 Mon Sep 17 00:00:00 2001 From: Chih-Min Chao Date: Sun, 19 Apr 2020 23:53:58 -0700 Subject: sf: add f16_to_[u]i16 use f16_to_[u]i]3 and handle overflow and underflow range for 16bit integer Signed-off-by: Chih-Min Chao --- softfloat/f16_to_i16.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++ softfloat/f16_to_ui16.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ softfloat/softfloat.h | 2 + softfloat/softfloat.mk.in | 2 + softfloat/specialize.h | 7 ++++ 5 files changed, 209 insertions(+) create mode 100644 softfloat/f16_to_i16.c create mode 100644 softfloat/f16_to_ui16.c (limited to 'softfloat') diff --git a/softfloat/f16_to_i16.c b/softfloat/f16_to_i16.c new file mode 100644 index 0000000..b05cd8c --- /dev/null +++ b/softfloat/f16_to_i16.c @@ -0,0 +1,101 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast16_t f16_to_i16( float16_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui16_f16 uA; + uint_fast16_t uiA; + bool sign; + int_fast8_t exp; + uint_fast16_t frac; + int_fast32_t sig32; + int_fast8_t shiftDist; + bool do_round = true; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF16UI( uiA ); + exp = expF16UI( uiA ); + frac = fracF16UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x1F ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + frac ? i16_fromNaN + : sign ? i16_fromNegOverflow : i16_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if ( exp ) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ( 0 <= shiftDist ) { + sig32 <<= shiftDist; + sig32 = sign ? -sig32 : sig32; + do_round = false; + } else { + shiftDist = exp - 0x0D; + if ( 0 < shiftDist ) + sig32 <<= shiftDist; + } + } + + if (do_round) + sig32 = softfloat_roundToI32( + sign, (uint_fast32_t) sig32, roundingMode, exact); + + if (sig32 > INT16_MAX) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + return i16_fromPosOverflow; + } else if (sig32 < INT16_MIN) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + return i16_fromNegOverflow; + } else { + return sig32; + } +} + diff --git a/softfloat/f16_to_ui16.c b/softfloat/f16_to_ui16.c new file mode 100644 index 0000000..652daff --- /dev/null +++ b/softfloat/f16_to_ui16.c @@ -0,0 +1,97 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast16_t f16_to_ui16( float16_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui16_f16 uA; + uint_fast16_t uiA; + bool sign; + int_fast8_t exp; + uint_fast16_t frac; + uint_fast32_t sig32; + int_fast8_t shiftDist; + bool do_round = true; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF16UI( uiA ); + exp = expF16UI( uiA ); + frac = fracF16UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x1F ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + frac ? ui16_fromNaN + : sign ? ui16_fromNegOverflow : ui16_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if ( exp ) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ( (0 <= shiftDist) && !sign ) { + sig32 << shiftDist; + do_round = false; + } else { + shiftDist = exp - 0x0D; + if ( 0 < shiftDist ) + sig32 <<= shiftDist; + } + } + + if (do_round) + sig32 = softfloat_roundToUI32( sign, sig32, roundingMode, exact ); + + if (sig32 > UINT16_MAX) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + return ui16_fromPosOverflow; + } else { + return sig32; + } + +} + diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index 540d2fb..c93c3c5 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -141,8 +141,10 @@ void i64_to_f128M( int64_t, float128_t * ); /*---------------------------------------------------------------------------- | 16-bit (half-precision) floating-point operations. *----------------------------------------------------------------------------*/ +uint_fast16_t f16_to_ui16( float16_t, uint_fast8_t, bool ); uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool ); uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool ); +int_fast16_t f16_to_i16( float16_t, uint_fast8_t, bool ); int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool ); int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool ); uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool ); diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 0ca17cd..90ce30c 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -56,10 +56,12 @@ softfloat_c_srcs = \ f16_to_f128.c \ f16_to_f32.c \ f16_to_f64.c \ + f16_to_i16.c \ f16_to_i32.c \ f16_to_i32_r_minMag.c \ f16_to_i64.c \ f16_to_i64_r_minMag.c \ + f16_to_ui16.c \ f16_to_ui32.c \ f16_to_ui32_r_minMag.c \ f16_to_ui64.c \ diff --git a/softfloat/specialize.h b/softfloat/specialize.h index 629d518..8bd9857 100644 --- a/softfloat/specialize.h +++ b/softfloat/specialize.h @@ -55,6 +55,13 @@ extern "C" { | The values to return on conversions to 32-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ +#define ui16_fromPosOverflow 0xFFFF +#define ui16_fromNegOverflow 0 +#define ui16_fromNaN 0xFFFF +#define i16_fromPosOverflow 0x7FFF +#define i16_fromNegOverflow (-0x7FFF - 1) +#define i16_fromNaN 0x7FFF + #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0 #define ui32_fromNaN 0xFFFFFFFF -- cgit v1.1