1 /*============================================================================
2 This source file is an extension to the SoftFloat IEC/IEEE Floating-point
3 Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
4 floating point emulation.
6 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
7 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
8 RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
9 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
10 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
11 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
12 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
13 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
15 Derivative works are acceptable, even for commercial purposes, so long as
16 (1) the source code for the derivative work includes prominent notice that
17 the work is derivative, and (2) the source code includes prominent notice with
18 these four paragraphs for those parts of this code that are retained.
19 =============================================================================*/
21 /*============================================================================
22 * Written for Bochs (x86 achitecture simulator) by
23 * Stanislav Shwartsman [sshwarts at sourceforge net]
24 * ==========================================================================*/
26 #include "softfloatx80.h"
27 #include "softfloat-round-pack.h"
28 #define USE_estimateDiv128To64
29 #include "softfloat-macros.h"
31 /* executes single exponent reduction cycle */
32 static Bit64u
remainder_kernel(Bit64u aSig0
, Bit64u bSig
, int expDiff
, Bit64u
*zSig0
, Bit64u
*zSig1
)
37 shortShift128Left(aSig1
, aSig0
, expDiff
, &aSig1
, &aSig0
);
38 Bit64u q
= estimateDiv128To64(aSig1
, aSig0
, bSig
);
39 mul64To128(bSig
, q
, &term0
, &term1
);
40 sub128(aSig1
, aSig0
, term0
, term1
, zSig1
, zSig0
);
41 while ((Bit64s
)(*zSig1
) < 0) {
43 add128(*zSig1
, *zSig0
, 0, bSig
, zSig1
, zSig0
);
48 static floatx80
do_fprem(floatx80 a
, floatx80 b
, Bit64u
&q
, int rounding_mode
, float_status_t
&status
)
50 Bit32s aExp
, bExp
, zExp
, expDiff
;
51 Bit64u aSig0
, aSig1
, bSig
;
55 // handle unsupported extended double-precision floating encodings
56 if (floatx80_is_unsupported(a
) || floatx80_is_unsupported(b
))
58 float_raise(status
, float_flag_invalid
);
59 return floatx80_default_nan
;
62 aSig0
= extractFloatx80Frac(a
);
63 aExp
= extractFloatx80Exp(a
);
64 aSign
= extractFloatx80Sign(a
);
65 bSig
= extractFloatx80Frac(b
);
66 bExp
= extractFloatx80Exp(b
);
69 if ((Bit64u
) (aSig0
<<1)
70 || ((bExp
== 0x7FFF) && (Bit64u
) (bSig
<<1)))
72 return propagateFloatx80NaN(a
, b
, status
);
77 if ((Bit64u
) (bSig
<<1)) return propagateFloatx80NaN(a
, b
, status
);
83 float_raise(status
, float_flag_invalid
);
84 return floatx80_default_nan
;
86 float_raise(status
, float_flag_denormal
);
87 normalizeFloatx80Subnormal(bSig
, &bExp
, &bSig
);
90 if ((Bit64u
) (aSig0
<<1) == 0) return a
;
91 float_raise(status
, float_flag_denormal
);
92 normalizeFloatx80Subnormal(aSig0
, &aExp
, &aSig0
);
94 expDiff
= aExp
- bExp
;
98 int n
= (expDiff
& 0x1f) | 0x20;
99 remainder_kernel(aSig0
, bSig
, n
, &aSig0
, &aSig1
);
108 return (a
.fraction
& BX_CONST64(0x8000000000000000)) ?
109 packFloatx80(aSign
, aExp
, aSig0
) : a
;
110 shift128Right(aSig0
, 0, 1, &aSig0
, &aSig1
);
115 q
= remainder_kernel(aSig0
, bSig
, expDiff
, &aSig0
, &aSig1
);
124 if (rounding_mode
== float_round_nearest_even
)
127 shift128Right(bSig
, 0, 1, &term0
, &term1
);
129 if (! lt128(aSig0
, aSig1
, term0
, term1
))
131 int lt
= lt128(term0
, term1
, aSig0
, aSig1
);
132 int eq
= eq128(aSig0
, aSig1
, term0
, term1
);
134 if ((eq
&& (q
& 1)) || lt
) {
138 if (lt
) sub128(bSig
, 0, aSig0
, aSig1
, &aSig0
, &aSig1
);
143 return normalizeRoundAndPackFloatx80(80, aSign
, zExp
, aSig0
, aSig1
, status
);
146 /*----------------------------------------------------------------------------
147 | Returns the remainder of the extended double-precision floating-point value
148 | `a' with respect to the corresponding value `b'. The operation is performed
149 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
150 *----------------------------------------------------------------------------*/
152 floatx80
floatx80_ieee754_remainder(floatx80 a
, floatx80 b
, Bit64u
&q
, float_status_t
&status
)
154 return do_fprem(a
, b
, q
, float_round_nearest_even
, status
);
157 /*----------------------------------------------------------------------------
158 | Returns the remainder of the extended double-precision floating-point value
159 | `a' with respect to the corresponding value `b'. Unlike previous function
160 | the function does not compute the remainder specified in the IEC/IEEE
161 | Standard for Binary Floating-Point Arithmetic. This function operates
162 | differently from the previous function in the way that it rounds the
163 | quotient of 'a' divided by 'b' to an integer.
164 *----------------------------------------------------------------------------*/
166 floatx80
floatx80_remainder(floatx80 a
, floatx80 b
, Bit64u
&q
, float_status_t
&status
)
168 return do_fprem(a
, b
, q
, float_round_to_zero
, status
);