VirtualBox

source: vbox/trunk/src/libs/softfloat-3e/source/extF80_scale_extF80.c@ 99863

Last change on this file since 99863 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: extF80_scale_extF80.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * SoftFloat - 387-style fscale.
4 */
5
6/*
7 * Copyright (C) 2022-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include "platform.h"
33#include "internals.h"
34#include "specialize.h"
35#include "softfloat.h"
36#include <iprt/assert.h>
37#include <iprt/asm.h>
38
39
40/**
41 * Wrapper around softfloat_propagateNaNExtF80UI that returns extFloat80_t
42 * and takes fully unpacked input.
43 */
44DECLINLINE(extFloat80_t)
45softfloat_extF80_propagateNaN(bool fSignA, int_fast32_t iExpA, uint_fast64_t uSigA,
46 bool fSignB, int_fast32_t iExpB, uint_fast64_t uSigB SOFTFLOAT_STATE_DECL_COMMA)
47{
48 struct uint128 uiZ = softfloat_propagateNaNExtF80UI(packToExtF80UI64(fSignA, iExpA), uSigA,
49 packToExtF80UI64(fSignB, iExpB), uSigB SOFTFLOAT_STATE_ARG_COMMA);
50 union extF80M_extF80 Ret;
51 Ret.fM.signExp = uiZ.v64;
52 Ret.fM.signif = uiZ.v0;
53 return Ret.f;
54}
55
56
57/**
58 * This performs a function similar to extF80_to_i32_r_minMag, but returns
59 * proper MIN/MAX values and no NaNs.
60 *
61 * ASSUMES the input is normalized.
62 *
63 * @returns Values in the range -2^24...+2^24.
64 */
65static int_fast32_t convertToInt(bool fSign, uint_fast64_t uSig, int_fast32_t iExp)
66{
67 iExp -= RTFLOAT80U_EXP_BIAS;
68 if (iExp < 0)
69 return 0;
70
71 /* Restrict the range to -2^24...+2^24 to prevent overflows during scaling. */
72 if (iExp >= 24)
73 return fSign ? INT32_MIN / 128 : INT32_MAX / 128;
74
75 int_fast32_t iRet = (int_fast32_t)(uSig >> (63 - iExp));
76 if (fSign)
77 return -iRet;
78 return iRet;
79}
80
81
82/**
83 * VBox: scale @a a by 2^truncateToInt(@a b)
84 *
85 * This function accepts and deals correctly with denormals (pseudo and
86 * otherwise).
87 */
88extFloat80_t extF80_scale_extF80(extFloat80_t a, extFloat80_t b, softfloat_state_t *pState)
89{
90 static union extF80M_extF80 const s_extF80Indefinite = EXTF80M_EXTF80_INIT(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
91 static union extF80M_extF80 const s_aExtF80Zero[2] =
92 {
93 EXTF80M_EXTF80_INIT3_C(0, 0, 0), EXTF80M_EXTF80_INIT3_C(1, 0, 0),
94 };
95 static union extF80M_extF80 const s_aExtF80Infinity[2] =
96 {
97 EXTF80M_EXTF80_INIT3(0, RT_BIT_64(63), RTFLOAT80U_EXP_MAX),
98 EXTF80M_EXTF80_INIT3(1, RT_BIT_64(63), RTFLOAT80U_EXP_MAX),
99 };
100
101 /*
102 * Unpack the input.
103 */
104 bool const fSignA = signExtF80UI64(a.signExp);
105 int_fast32_t iExpA = expExtF80UI64(a.signExp);
106 uint_fast64_t uSigA = a.signif;
107
108 bool const fSignB = signExtF80UI64(b.signExp);
109 int_fast32_t iExpB = expExtF80UI64(b.signExp);
110 uint_fast64_t uSigB = b.signif;
111
112 /*
113 * Deal with funny input.
114 */
115 /* Invalid first. We ASSUME subnormals are rejected here. */
116 if ( RTFLOAT80U_IS_387_INVALID_EX(uSigA, iExpA)
117 || RTFLOAT80U_IS_387_INVALID_EX(uSigB, iExpB))
118 {
119 softfloat_raiseFlags(softfloat_flag_invalid, pState);
120 return s_extF80Indefinite.f;
121 }
122
123 /* Then NaNs and indefinites (special NaNs): */
124 if ( RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uSigA, iExpA)
125 || RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uSigB, iExpB))
126 return softfloat_extF80_propagateNaN(fSignA, iExpA, uSigA, fSignB, iExpB, uSigB, pState);
127
128 /* Normalize denormal inputs: */
129 if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uSigA, iExpA))
130 {
131 softfloat_raiseFlags(softfloat_flag_denormal, pState);
132 if (uSigA & RT_BIT_64(63))
133 iExpA = 1; /* -16382 */
134 else
135 {
136 /* We must return the denormal a value unchanged when b=zero, intel 10980XE
137 does this at least. Where-as pseudo-denormals are normalized. Go figure. */
138 if (RTFLOAT80U_IS_ZERO_EX(uSigB, iExpB))
139 return a;
140 iExpA = 64 - ASMBitLastSetU64(uSigA);
141 uSigA <<= iExpA;
142 iExpA = 1 - iExpA; /* -16382 - shift */
143 }
144 }
145
146 if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uSigB, iExpB))
147 {
148 softfloat_raiseFlags(softfloat_flag_denormal, pState);
149 if (uSigB & RT_BIT_64(63))
150 iExpB = 1; /* -16382 */
151 else
152 {
153 iExpB = 64 - ASMBitLastSetU64(uSigB);
154 uSigB <<= iExpB;
155 iExpB = 1 - iExpB; /* -16382 - shift */
156 }
157 }
158
159 /* Infinities and zeros: If a is Zero or Infinity, return it as-is unless
160 b=-Infinity & a=+/-Infinity or b=+Infinity & a=+/-zero when we have to
161 raise #I and return indefinite instead.
162
163 Note! If b is zero, don't, because pseudo-denormals should be returned
164 normalized (intel does that at least). Excpetion is b=zero and
165 a=denormal, which is handled above. */
166 if ( RTFLOAT80U_IS_INF_EX(uSigA, iExpA)
167 || RTFLOAT80U_IS_ZERO_EX(uSigA, iExpA))
168 {
169 if (RTFLOAT80U_IS_INF_EX(uSigB, iExpB) && fSignB == RTFLOAT80U_IS_INF_EX(uSigA, iExpA))
170 {
171 softfloat_raiseFlags(softfloat_flag_invalid, pState);
172 return s_extF80Indefinite.f;
173 }
174 return a;
175 }
176
177 if (RTFLOAT80U_IS_INF_EX(uSigB, iExpB))
178 {
179 if (fSignB)
180 return s_aExtF80Zero[fSignA].f;
181 return s_aExtF80Infinity[fSignA].f;
182 }
183
184 /*
185 * Convert b to an integer and do the scaling.
186 */
187 int_fast32_t iScaleFactor = convertToInt(fSignB, uSigB, iExpB);
188 int_fast32_t iScaledExp = iExpA + iScaleFactor;
189 return softfloat_normRoundPackToExtF80(fSignA, iScaledExp, uSigA, 0 /*sigExtra*/, 80 /*precision*/, pState);
190}
191
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette