From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/libs/softfloat-3e/source/extF80_scale_extF80.c | 191 +++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/libs/softfloat-3e/source/extF80_scale_extF80.c (limited to 'src/libs/softfloat-3e/source/extF80_scale_extF80.c') diff --git a/src/libs/softfloat-3e/source/extF80_scale_extF80.c b/src/libs/softfloat-3e/source/extF80_scale_extF80.c new file mode 100644 index 00000000..bb61034e --- /dev/null +++ b/src/libs/softfloat-3e/source/extF80_scale_extF80.c @@ -0,0 +1,191 @@ +/* $Id: extF80_scale_extF80.c $ */ +/** @file + * SoftFloat - 387-style fscale. + */ + +/* + * Copyright (C) 2022-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" +#include +#include + + +/** + * Wrapper around softfloat_propagateNaNExtF80UI that returns extFloat80_t + * and takes fully unpacked input. + */ +DECLINLINE(extFloat80_t) +softfloat_extF80_propagateNaN(bool fSignA, int_fast32_t iExpA, uint_fast64_t uSigA, + bool fSignB, int_fast32_t iExpB, uint_fast64_t uSigB SOFTFLOAT_STATE_DECL_COMMA) +{ + struct uint128 uiZ = softfloat_propagateNaNExtF80UI(packToExtF80UI64(fSignA, iExpA), uSigA, + packToExtF80UI64(fSignB, iExpB), uSigB SOFTFLOAT_STATE_ARG_COMMA); + union extF80M_extF80 Ret; + Ret.fM.signExp = uiZ.v64; + Ret.fM.signif = uiZ.v0; + return Ret.f; +} + + +/** + * This performs a function similar to extF80_to_i32_r_minMag, but returns + * proper MIN/MAX values and no NaNs. + * + * ASSUMES the input is normalized. + * + * @returns Values in the range -2^24...+2^24. + */ +static int_fast32_t convertToInt(bool fSign, uint_fast64_t uSig, int_fast32_t iExp) +{ + iExp -= RTFLOAT80U_EXP_BIAS; + if (iExp < 0) + return 0; + + /* Restrict the range to -2^24...+2^24 to prevent overflows during scaling. */ + if (iExp >= 24) + return fSign ? INT32_MIN / 128 : INT32_MAX / 128; + + int_fast32_t iRet = (int_fast32_t)(uSig >> (63 - iExp)); + if (fSign) + return -iRet; + return iRet; +} + + +/** + * VBox: scale @a a by 2^truncateToInt(@a b) + * + * This function accepts and deals correctly with denormals (pseudo and + * otherwise). + */ +extFloat80_t extF80_scale_extF80(extFloat80_t a, extFloat80_t b, softfloat_state_t *pState) +{ + static union extF80M_extF80 const s_extF80Indefinite = EXTF80M_EXTF80_INIT(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + static union extF80M_extF80 const s_aExtF80Zero[2] = + { + EXTF80M_EXTF80_INIT3_C(0, 0, 0), EXTF80M_EXTF80_INIT3_C(1, 0, 0), + }; + static union extF80M_extF80 const s_aExtF80Infinity[2] = + { + EXTF80M_EXTF80_INIT3(0, RT_BIT_64(63), RTFLOAT80U_EXP_MAX), + EXTF80M_EXTF80_INIT3(1, RT_BIT_64(63), RTFLOAT80U_EXP_MAX), + }; + + /* + * Unpack the input. + */ + bool const fSignA = signExtF80UI64(a.signExp); + int_fast32_t iExpA = expExtF80UI64(a.signExp); + uint_fast64_t uSigA = a.signif; + + bool const fSignB = signExtF80UI64(b.signExp); + int_fast32_t iExpB = expExtF80UI64(b.signExp); + uint_fast64_t uSigB = b.signif; + + /* + * Deal with funny input. + */ + /* Invalid first. We ASSUME subnormals are rejected here. */ + if ( RTFLOAT80U_IS_387_INVALID_EX(uSigA, iExpA) + || RTFLOAT80U_IS_387_INVALID_EX(uSigB, iExpB)) + { + softfloat_raiseFlags(softfloat_flag_invalid, pState); + return s_extF80Indefinite.f; + } + + /* Then NaNs and indefinites (special NaNs): */ + if ( RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uSigA, iExpA) + || RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uSigB, iExpB)) + return softfloat_extF80_propagateNaN(fSignA, iExpA, uSigA, fSignB, iExpB, uSigB, pState); + + /* Normalize denormal inputs: */ + if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uSigA, iExpA)) + { + softfloat_raiseFlags(softfloat_flag_denormal, pState); + if (uSigA & RT_BIT_64(63)) + iExpA = 1; /* -16382 */ + else + { + /* We must return the denormal a value unchanged when b=zero, intel 10980XE + does this at least. Where-as pseudo-denormals are normalized. Go figure. */ + if (RTFLOAT80U_IS_ZERO_EX(uSigB, iExpB)) + return a; + iExpA = 64 - ASMBitLastSetU64(uSigA); + uSigA <<= iExpA; + iExpA = 1 - iExpA; /* -16382 - shift */ + } + } + + if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uSigB, iExpB)) + { + softfloat_raiseFlags(softfloat_flag_denormal, pState); + if (uSigB & RT_BIT_64(63)) + iExpB = 1; /* -16382 */ + else + { + iExpB = 64 - ASMBitLastSetU64(uSigB); + uSigB <<= iExpB; + iExpB = 1 - iExpB; /* -16382 - shift */ + } + } + + /* Infinities and zeros: If a is Zero or Infinity, return it as-is unless + b=-Infinity & a=+/-Infinity or b=+Infinity & a=+/-zero when we have to + raise #I and return indefinite instead. + + Note! If b is zero, don't, because pseudo-denormals should be returned + normalized (intel does that at least). Excpetion is b=zero and + a=denormal, which is handled above. */ + if ( RTFLOAT80U_IS_INF_EX(uSigA, iExpA) + || RTFLOAT80U_IS_ZERO_EX(uSigA, iExpA)) + { + if (RTFLOAT80U_IS_INF_EX(uSigB, iExpB) && fSignB == RTFLOAT80U_IS_INF_EX(uSigA, iExpA)) + { + softfloat_raiseFlags(softfloat_flag_invalid, pState); + return s_extF80Indefinite.f; + } + return a; + } + + if (RTFLOAT80U_IS_INF_EX(uSigB, iExpB)) + { + if (fSignB) + return s_aExtF80Zero[fSignA].f; + return s_aExtF80Infinity[fSignA].f; + } + + /* + * Convert b to an integer and do the scaling. + */ + int_fast32_t iScaleFactor = convertToInt(fSignB, uSigB, iExpB); + int_fast32_t iScaledExp = iExpA + iScaleFactor; + return softfloat_normRoundPackToExtF80(fSignA, iScaledExp, uSigA, 0 /*sigExtra*/, 80 /*precision*/, pState); +} + -- cgit v1.2.3