VirtualBox

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

最後變更 在這個檔案從95282是 94678,由 vboxsync 提交於 3 年 前

libs/softfloat: Implemented a 387-style fscale function. bugref:9898

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

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