1206917Smarius
2206917Smarius/*
3206917Smarius===============================================================================
4206917Smarius
5206917SmariusThis C source file is part of TestFloat, Release 2a, a package of programs
6206917Smariusfor testing the correctness of floating-point arithmetic complying to the
7206917SmariusIEC/IEEE Standard for Floating-Point.
8206917Smarius
9206917SmariusWritten by John R. Hauser.  More information is available through the Web
10206917Smariuspage `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11206917Smarius
12206917SmariusTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
13206917Smariushas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14206917SmariusTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
15206917SmariusPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16206917SmariusAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17206917Smarius
18206917SmariusDerivative works are acceptable, even for commercial purposes, so long as
19206917Smarius(1) they include prominent notice that the work is derivative, and (2) they
20206917Smariusinclude prominent notice akin to these four paragraphs for those parts of
21206917Smariusthis code that are retained.
22206917Smarius
23206917Smarius===============================================================================
24206917Smarius*/
25206917Smarius
26206917Smariusint8 slow_float_rounding_mode;
27206917Smariusint8 slow_float_exception_flags;
28206917Smariusint8 slow_float_detect_tininess;
29206917Smarius
30206917Smariustypedef struct {
31206917Smarius    bits32 a0, a1;
32206917Smarius} bits64X;
33206917Smarius
34206917Smariustypedef struct {
35206917Smarius    flag isNaN;
36206917Smarius    flag isInf;
37206917Smarius    flag isZero;
38206917Smarius    flag sign;
39206917Smarius    int16 exp;
40206917Smarius    bits64X sig;
41206917Smarius} floatX;
42206917Smarius
43206917Smariusstatic const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } };
44206917Smariusstatic const floatX floatXPositiveZero =
45206917Smarius    { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } };
46206917Smariusstatic const floatX floatXNegativeZero =
47206917Smarius    { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } };
48206917Smarius
49206917Smariusstatic bits64X shortShift64Left( bits64X a, int8 shiftCount )
50206917Smarius{
51206917Smarius    int8 negShiftCount;
52206917Smarius
53206917Smarius    negShiftCount = ( - shiftCount & 31 );
54206917Smarius    a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount );
55206917Smarius    a.a1 <<= shiftCount;
56206917Smarius    return a;
57206917Smarius
58206917Smarius}
59206917Smarius
60206917Smariusstatic bits64X shortShift64RightJamming( bits64X a, int8 shiftCount )
61206917Smarius{
62206917Smarius    int8 negShiftCount;
63206917Smarius    bits32 extra;
64206917Smarius
65206917Smarius    negShiftCount = ( - shiftCount & 31 );
66206917Smarius    extra = a.a1<<negShiftCount;
67206917Smarius    a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 );
68206917Smarius    a.a0 >>= shiftCount;
69206917Smarius    return a;
70206917Smarius
71206917Smarius}
72206917Smarius
73206917Smariusstatic bits64X neg64( bits64X a )
74206917Smarius{
75206917Smarius
76206917Smarius    if ( a.a1 == 0 ) {
77206917Smarius        a.a0 = - a.a0;
78206917Smarius    }
79206917Smarius    else {
80206917Smarius        a.a1 = - a.a1;
81206917Smarius        a.a0 = ~ a.a0;
82206917Smarius    }
83206917Smarius    return a;
84206917Smarius
85206917Smarius}
86206917Smarius
87206917Smariusstatic bits64X add64( bits64X a, bits64X b )
88206917Smarius{
89206917Smarius
90206917Smarius    a.a1 += b.a1;
91206917Smarius    a.a0 += b.a0 + ( a.a1 < b.a1 );
92206917Smarius    return a;
93206917Smarius
94206917Smarius}
95206917Smarius
96206917Smariusstatic flag eq64( bits64X a, bits64X b )
97206917Smarius{
98206917Smarius
99206917Smarius    return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 );
100206917Smarius
101206917Smarius}
102206917Smarius
103206917Smariusstatic flag le64( bits64X a, bits64X b )
104206917Smarius{
105206917Smarius
106206917Smarius    return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) );
107206917Smarius
108206917Smarius}
109206917Smarius
110206917Smariusstatic flag lt64( bits64X a, bits64X b )
111206917Smarius{
112206917Smarius
113206917Smarius    return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) );
114206917Smarius
115206917Smarius}
116206917Smarius
117206917Smariusstatic floatX roundFloatXTo24( flag isTiny, floatX zx )
118206917Smarius{
119206917Smarius
120206917Smarius    if ( zx.sig.a1 ) {
121206917Smarius        slow_float_exception_flags |= float_flag_inexact;
122206917Smarius        if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
123206917Smarius        switch ( slow_float_rounding_mode ) {
124206917Smarius         case float_round_nearest_even:
125206917Smarius            if ( zx.sig.a1 < 0x80000000 ) goto noIncrement;
126206917Smarius            if ( ( zx.sig.a1 == 0x80000000 ) && ! ( zx.sig.a0 & 1 ) ) {
127206917Smarius                goto noIncrement;
128206917Smarius            }
129206917Smarius            break;
130206917Smarius         case float_round_to_zero:
131206917Smarius            goto noIncrement;
132206917Smarius         case float_round_down:
133206917Smarius            if ( ! zx.sign ) goto noIncrement;
134206917Smarius            break;
135206917Smarius         case float_round_up:
136206917Smarius            if ( zx.sign ) goto noIncrement;
137206917Smarius            break;
138206917Smarius        }
139206917Smarius        ++zx.sig.a0;
140206917Smarius        if ( zx.sig.a0 == 0x01000000 ) {
141206917Smarius            zx.sig.a0 = 0x00800000;
142206917Smarius            ++zx.exp;
143206917Smarius        }
144206917Smarius    }
145206917Smarius noIncrement:
146206917Smarius    zx.sig.a1 = 0;
147206917Smarius    return zx;
148206917Smarius
149206917Smarius}
150206917Smarius
151206917Smariusstatic floatX roundFloatXTo53( flag isTiny, floatX zx )
152206917Smarius{
153206917Smarius    int8 roundBits;
154206917Smarius
155206917Smarius    roundBits = zx.sig.a1 & 7;
156206917Smarius    zx.sig.a1 -= roundBits;
157206917Smarius    if ( roundBits ) {
158206917Smarius        slow_float_exception_flags |= float_flag_inexact;
159206917Smarius        if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
160206917Smarius        switch ( slow_float_rounding_mode ) {
161206917Smarius         case float_round_nearest_even:
162206917Smarius            if ( roundBits < 4 ) goto noIncrement;
163206917Smarius            if ( ( roundBits == 4 ) && ! ( zx.sig.a1 & 8 ) ) goto noIncrement;
164206917Smarius            break;
165206917Smarius         case float_round_to_zero:
166206917Smarius            goto noIncrement;
167206917Smarius         case float_round_down:
168206917Smarius            if ( ! zx.sign ) goto noIncrement;
169206917Smarius            break;
170206917Smarius         case float_round_up:
171206917Smarius            if ( zx.sign ) goto noIncrement;
172206917Smarius            break;
173206917Smarius        }
174206917Smarius        zx.sig.a1 += 8;
175206917Smarius        zx.sig.a0 += ( zx.sig.a1 == 0 );
176206917Smarius        if ( zx.sig.a0 == 0x01000000 ) {
177206917Smarius            zx.sig.a0 = 0x00800000;
178206917Smarius            ++zx.exp;
179206917Smarius        }
180206917Smarius    }
181206917Smarius noIncrement:
182206917Smarius    return zx;
183206917Smarius
184206917Smarius}
185206917Smarius
186206917Smariusstatic floatX int32ToFloatX( int32 a )
187206917Smarius{
188206917Smarius    floatX ax;
189206917Smarius
190206917Smarius    ax.isNaN = FALSE;
191206917Smarius    ax.isInf = FALSE;
192206917Smarius    ax.sign = ( a < 0 );
193206917Smarius    ax.sig.a1 = ax.sign ? - a : a;
194206917Smarius    ax.sig.a0 = 0;
195206917Smarius    if ( a == 0 ) {
196206917Smarius        ax.isZero = TRUE;
197206917Smarius        return ax;
198206917Smarius    }
199206917Smarius    ax.isZero = FALSE;
200206917Smarius    ax.sig = shortShift64Left( ax.sig, 23 );
201206917Smarius    ax.exp = 32;
202206917Smarius    while ( ax.sig.a0 < 0x00800000 ) {
203206917Smarius        ax.sig = shortShift64Left( ax.sig, 1 );
204206917Smarius        --ax.exp;
205206917Smarius    }
206206917Smarius    return ax;
207206917Smarius
208206917Smarius}
209206917Smarius
210206917Smariusstatic int32 floatXToInt32( floatX ax )
211206917Smarius{
212206917Smarius    int8 savedExceptionFlags;
213206917Smarius    int16 shiftCount;
214206917Smarius    int32 z;
215206917Smarius
216206917Smarius    if ( ax.isInf || ax.isNaN ) {
217206917Smarius        slow_float_exception_flags |= float_flag_invalid;
218206917Smarius        return ( ax.isInf & ax.sign ) ? 0x80000000 : 0x7FFFFFFF;
219206917Smarius    }
220206917Smarius    if ( ax.isZero ) return 0;
221206917Smarius    savedExceptionFlags = slow_float_exception_flags;
222206917Smarius    shiftCount = 52 - ax.exp;
223206917Smarius    if ( 56 < shiftCount ) {
224206917Smarius        ax.sig.a1 = 1;
225206917Smarius        ax.sig.a0 = 0;
226206917Smarius    }
227206917Smarius    else {
228206917Smarius        while ( 0 < shiftCount ) {
229206917Smarius            ax.sig = shortShift64RightJamming( ax.sig, 1 );
230206917Smarius            --shiftCount;
231206917Smarius        }
232206917Smarius    }
233206917Smarius    ax = roundFloatXTo53( FALSE, ax );
234206917Smarius    ax.sig = shortShift64RightJamming( ax.sig, 3 );
235206917Smarius    z = ax.sig.a1;
236206917Smarius    if ( ax.sign ) z = - z;
237206917Smarius    if (    ( shiftCount < 0 )
238206917Smarius         || ax.sig.a0
239206917Smarius         || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) )
240206917Smarius       ) {
241206917Smarius        slow_float_exception_flags = savedExceptionFlags | float_flag_invalid;
242206917Smarius        return ax.sign ? 0x80000000 : 0x7FFFFFFF;
243206917Smarius    }
244206917Smarius    return z;
245206917Smarius
246206917Smarius}
247206917Smarius
248206917Smariusstatic floatX float32ToFloatX( float32 a )
249206917Smarius{
250206917Smarius    int16 expField;
251206917Smarius    floatX ax;
252206917Smarius
253206917Smarius    ax.isNaN = FALSE;
254206917Smarius    ax.isInf = FALSE;
255206917Smarius    ax.isZero = FALSE;
256206917Smarius    ax.sign = ( ( a & 0x80000000 ) != 0 );
257206917Smarius    expField = ( a>>23 ) & 0xFF;
258206917Smarius    ax.sig.a1 = 0;
259206917Smarius    ax.sig.a0 = a & 0x007FFFFF;
260206917Smarius    if ( expField == 0 ) {
261206917Smarius        if ( ax.sig.a0 == 0 ) {
262206917Smarius            ax.isZero = TRUE;
263206917Smarius        }
264206917Smarius        else {
265206917Smarius            expField = 1 - 0x7F;
266206917Smarius            do {
267206917Smarius                ax.sig.a0 <<= 1;
268206917Smarius                --expField;
269206917Smarius            } while ( ax.sig.a0 < 0x00800000 );
270206917Smarius            ax.exp = expField;
271206917Smarius        }
272206917Smarius    }
273206917Smarius    else if ( expField == 0xFF ) {
274206917Smarius        if ( ax.sig.a0 == 0 ) {
275206917Smarius            ax.isInf = TRUE;
276206917Smarius        }
277206917Smarius        else {
278206917Smarius            ax.isNaN = TRUE;
279206917Smarius        }
280206917Smarius    }
281206917Smarius    else {
282206917Smarius        ax.sig.a0 |= 0x00800000;
283206917Smarius        ax.exp = expField - 0x7F;
284206917Smarius    }
285206917Smarius    return ax;
286206917Smarius
287206917Smarius}
288206917Smarius
289206917Smariusstatic float32 floatXToFloat32( floatX zx )
290206917Smarius{
291206917Smarius    floatX savedZ;
292206917Smarius    flag isTiny;
293206917Smarius    int16 expField;
294206917Smarius    float32 z;
295206917Smarius
296206917Smarius    if ( zx.isZero ) return zx.sign ? 0x80000000 : 0;
297206917Smarius    if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000;
298206917Smarius    if ( zx.isNaN ) return 0xFFFFFFFF;
299206917Smarius    while ( 0x01000000 <= zx.sig.a0 ) {
300206917Smarius        zx.sig = shortShift64RightJamming( zx.sig, 1 );
301206917Smarius        ++zx.exp;
302206917Smarius    }
303206917Smarius    while ( zx.sig.a0 < 0x00800000 ) {
304206917Smarius        zx.sig = shortShift64Left( zx.sig, 1 );
305206917Smarius        --zx.exp;
306206917Smarius    }
307206917Smarius    savedZ = zx;
308206917Smarius    isTiny =
309206917Smarius           ( slow_float_detect_tininess == float_tininess_before_rounding )
310206917Smarius        && ( zx.exp + 0x7F <= 0 );
311206917Smarius    zx = roundFloatXTo24( isTiny, zx );
312206917Smarius    expField = zx.exp + 0x7F;
313206917Smarius    if ( 0xFF <= expField ) {
314206917Smarius        slow_float_exception_flags |=
315206917Smarius            float_flag_overflow | float_flag_inexact;
316206917Smarius        if ( zx.sign ) {
317206917Smarius            switch ( slow_float_rounding_mode ) {
318206917Smarius             case float_round_nearest_even:
319206917Smarius             case float_round_down:
320206917Smarius                z = 0xFF800000;
321206917Smarius                break;
322206917Smarius             case float_round_to_zero:
323206917Smarius             case float_round_up:
324206917Smarius                z = 0xFF7FFFFF;
325206917Smarius                break;
326206917Smarius            }
327206917Smarius        }
328206917Smarius        else {
329206917Smarius            switch ( slow_float_rounding_mode ) {
330206917Smarius             case float_round_nearest_even:
331206917Smarius             case float_round_up:
332206917Smarius                z = 0x7F800000;
333206917Smarius                break;
334206917Smarius             case float_round_to_zero:
335206917Smarius             case float_round_down:
336206917Smarius                z = 0x7F7FFFFF;
337206917Smarius                break;
338206917Smarius            }
339206917Smarius        }
340206917Smarius        return z;
341206917Smarius    }
342206917Smarius    if ( expField <= 0 ) {
343206917Smarius        isTiny = TRUE;
344206917Smarius        zx = savedZ;
345206917Smarius        expField = zx.exp + 0x7F;
346206917Smarius        if ( expField < -27 ) {
347206917Smarius            zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
348206917Smarius            zx.sig.a0 = 0;
349206917Smarius        }
350206917Smarius        else {
351206917Smarius            while ( expField <= 0 ) {
352206917Smarius                zx.sig = shortShift64RightJamming( zx.sig, 1 );
353206917Smarius                ++expField;
354206917Smarius            }
355206917Smarius        }
356206917Smarius        zx = roundFloatXTo24( isTiny, zx );
357206917Smarius        expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0;
358206917Smarius    }
359206917Smarius    z = expField;
360206917Smarius    z <<= 23;
361206917Smarius    if ( zx.sign ) z |= 0x80000000;
362206917Smarius    z |= zx.sig.a0 & 0x007FFFFF;
363206917Smarius    return z;
364206917Smarius
365206917Smarius}
366206917Smarius
367206917Smariusstatic floatX float64ToFloatX( float64 a )
368206917Smarius{
369206917Smarius    int16 expField;
370206917Smarius    floatX ax;
371206917Smarius
372206917Smarius    ax.isNaN = FALSE;
373206917Smarius    ax.isInf = FALSE;
374206917Smarius    ax.isZero = FALSE;
375206917Smarius#ifdef BITS64
376206917Smarius    ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 );
377206917Smarius    expField = ( a>>52 ) & 0x7FF;
378206917Smarius    ax.sig.a1 = a;
379206917Smarius    ax.sig.a0 = ( a>>32 ) & 0x000FFFFF;
380206917Smarius#else
381206917Smarius    ax.sign = ( ( a.high & 0x80000000 ) != 0 );
382206917Smarius    expField = ( a.high>>( 52 - 32 ) ) & 0x7FF;
383206917Smarius    ax.sig.a1 = a.low;
384206917Smarius    ax.sig.a0 = a.high & 0x000FFFFF;
385206917Smarius#endif
386206917Smarius    if ( expField == 0 ) {
387206917Smarius        if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
388206917Smarius            ax.isZero = TRUE;
389206917Smarius        }
390206917Smarius        else {
391206917Smarius            expField = 1 - 0x3FF;
392206917Smarius            do {
393206917Smarius                ax.sig = shortShift64Left( ax.sig, 1 );
394206917Smarius                --expField;
395206917Smarius            } while ( ax.sig.a0 < 0x00100000 );
396206917Smarius            ax.exp = expField;
397206917Smarius        }
398206917Smarius    }
399206917Smarius    else if ( expField == 0x7FF ) {
400206917Smarius        if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
401206917Smarius            ax.isInf = TRUE;
402206917Smarius        }
403206917Smarius        else {
404206917Smarius            ax.isNaN = TRUE;
405206917Smarius        }
406206917Smarius    }
407206917Smarius    else {
408206917Smarius        ax.exp = expField - 0x3FF;
409206917Smarius        ax.sig.a0 |= 0x00100000;
410206917Smarius    }
411206917Smarius    ax.sig = shortShift64Left( ax.sig, 3 );
412206917Smarius    return ax;
413206917Smarius
414206917Smarius}
415206917Smarius
416206917Smariusstatic float64 floatXToFloat64( floatX zx )
417206917Smarius{
418206917Smarius    floatX savedZ;
419206917Smarius    flag isTiny;
420206917Smarius    int16 expField;
421206917Smarius    float64 z;
422206917Smarius
423206917Smarius#ifdef BITS64
424206917Smarius    if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0;
425206917Smarius    if ( zx.isInf ) {
426206917Smarius        return
427206917Smarius              zx.sign ? LIT64( 0xFFF0000000000000 )
428206917Smarius            : LIT64( 0x7FF0000000000000 );
429206917Smarius    }
430206917Smarius    if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF );
431206917Smarius#else
432206917Smarius    if ( zx.isZero ) {
433206917Smarius        z.low = 0;
434206917Smarius        z.high = zx.sign ? 0x80000000 : 0;
435206917Smarius        return z;
436206917Smarius    }
437206917Smarius    if ( zx.isInf ) {
438206917Smarius        z.low = 0;
439206917Smarius        z.high = zx.sign ? 0xFFF00000 : 0x7FF00000;
440206917Smarius        return z;
441206917Smarius    }
442206917Smarius    if ( zx.isNaN ) {
443206917Smarius        z.high = z.low = 0xFFFFFFFF;
444206917Smarius        return z;
445206917Smarius    }
446206917Smarius#endif
447206917Smarius    while ( 0x01000000 <= zx.sig.a0 ) {
448206917Smarius        zx.sig = shortShift64RightJamming( zx.sig, 1 );
449206917Smarius        ++zx.exp;
450206917Smarius    }
451206917Smarius    while ( zx.sig.a0 < 0x00800000 ) {
452206917Smarius        zx.sig = shortShift64Left( zx.sig, 1 );
453206917Smarius        --zx.exp;
454206917Smarius    }
455206917Smarius    savedZ = zx;
456206917Smarius    isTiny =
457206917Smarius           ( slow_float_detect_tininess == float_tininess_before_rounding )
458206917Smarius        && ( zx.exp + 0x3FF <= 0 );
459206917Smarius    zx = roundFloatXTo53( isTiny, zx );
460206917Smarius    expField = zx.exp + 0x3FF;
461206917Smarius    if ( 0x7FF <= expField ) {
462206917Smarius        slow_float_exception_flags |=
463206917Smarius            float_flag_overflow | float_flag_inexact;
464206917Smarius#ifdef BITS64
465206917Smarius        if ( zx.sign ) {
466206917Smarius            switch ( slow_float_rounding_mode ) {
467206917Smarius             case float_round_nearest_even:
468206917Smarius             case float_round_down:
469206917Smarius                z = LIT64( 0xFFF0000000000000 );
470206917Smarius                break;
471206917Smarius             case float_round_to_zero:
472206917Smarius             case float_round_up:
473206917Smarius                z = LIT64( 0xFFEFFFFFFFFFFFFF );
474206917Smarius                break;
475206917Smarius            }
476206917Smarius        }
477206917Smarius        else {
478206917Smarius            switch ( slow_float_rounding_mode ) {
479206917Smarius             case float_round_nearest_even:
480206917Smarius             case float_round_up:
481206917Smarius                z = LIT64( 0x7FF0000000000000 );
482206917Smarius                break;
483206917Smarius             case float_round_to_zero:
484206917Smarius             case float_round_down:
485206917Smarius                z = LIT64( 0x7FEFFFFFFFFFFFFF );
486206917Smarius                break;
487206917Smarius            }
488206917Smarius        }
489206917Smarius#else
490206917Smarius        if ( zx.sign ) {
491206917Smarius            switch ( slow_float_rounding_mode ) {
492206917Smarius             case float_round_nearest_even:
493206917Smarius             case float_round_down:
494206917Smarius                z.low = 0;
495206917Smarius                z.high = 0xFFF00000;
496206917Smarius                break;
497206917Smarius             case float_round_to_zero:
498206917Smarius             case float_round_up:
499206917Smarius                z.low = 0xFFFFFFFF;
500206917Smarius                z.high = 0xFFEFFFFF;
501206917Smarius                break;
502206917Smarius            }
503206917Smarius        }
504206917Smarius        else {
505206917Smarius            switch ( slow_float_rounding_mode ) {
506206917Smarius             case float_round_nearest_even:
507206917Smarius             case float_round_up:
508206917Smarius                z.low = 0;
509206917Smarius                z.high = 0x7FF00000;
510206917Smarius                break;
511206917Smarius             case float_round_to_zero:
512206917Smarius             case float_round_down:
513206917Smarius                z.low = 0xFFFFFFFF;
514206917Smarius                z.high = 0x7FEFFFFF;
515206917Smarius                break;
516206917Smarius            }
517206917Smarius        }
518206917Smarius#endif
519206917Smarius        return z;
520206917Smarius    }
521206917Smarius    if ( expField <= 0 ) {
522206917Smarius        isTiny = TRUE;
523206917Smarius        zx = savedZ;
524206917Smarius        expField = zx.exp + 0x3FF;
525206917Smarius        if ( expField < -56 ) {
526206917Smarius            zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
527206917Smarius            zx.sig.a0 = 0;
528206917Smarius        }
529206917Smarius        else {
530206917Smarius            while ( expField <= 0 ) {
531206917Smarius                zx.sig = shortShift64RightJamming( zx.sig, 1 );
532206917Smarius                ++expField;
533206917Smarius            }
534206917Smarius        }
535206917Smarius        zx = roundFloatXTo53( isTiny, zx );
536206917Smarius        expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0;
537206917Smarius    }
538206917Smarius    zx.sig = shortShift64RightJamming( zx.sig, 3 );
539206917Smarius#ifdef BITS64
540206917Smarius    z = expField;
541206917Smarius    z <<= 52;
542206917Smarius    if ( zx.sign ) z |= LIT64( 0x8000000000000000 );
543206917Smarius    z |= ( ( (bits64) ( zx.sig.a0 & 0x000FFFFF ) )<<32 ) | zx.sig.a1;
544206917Smarius#else
545206917Smarius    z.low = zx.sig.a1;
546206917Smarius    z.high = expField;
547206917Smarius    z.high <<= 52 - 32;
548206917Smarius    if ( zx.sign ) z.high |= 0x80000000;
549206917Smarius    z.high |= zx.sig.a0 & 0x000FFFFF;
550206917Smarius#endif
551206917Smarius    return z;
552206917Smarius
553206917Smarius}
554206917Smarius
555206917Smariusstatic floatX floatXInvalid( void )
556206917Smarius{
557206917Smarius
558206917Smarius    slow_float_exception_flags |= float_flag_invalid;
559206917Smarius    return floatXNaN;
560206917Smarius
561206917Smarius}
562206917Smarius
563206917Smariusstatic floatX floatXRoundToInt( floatX ax )
564206917Smarius{
565206917Smarius    int16 shiftCount, i;
566206917Smarius
567206917Smarius    if ( ax.isNaN || ax.isInf ) return ax;
568206917Smarius    shiftCount = 52 - ax.exp;
569206917Smarius    if ( shiftCount <= 0 ) return ax;
570206917Smarius    if ( 55 < shiftCount ) {
571206917Smarius        ax.exp = 52;
572206917Smarius        ax.sig.a1 = ! ax.isZero;
573206917Smarius        ax.sig.a0 = 0;
574206917Smarius    }
575206917Smarius    else {
576206917Smarius        while ( 0 < shiftCount ) {
577206917Smarius            ax.sig = shortShift64RightJamming( ax.sig, 1 );
578206917Smarius            ++ax.exp;
579206917Smarius            --shiftCount;
580206917Smarius        }
581206917Smarius    }
582206917Smarius    ax = roundFloatXTo53( FALSE, ax );
583206917Smarius    if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
584206917Smarius    return ax;
585206917Smarius
586206917Smarius}
587206917Smarius
588206917Smariusstatic floatX floatXAdd( floatX ax, floatX bx )
589206917Smarius{
590206917Smarius    int16 expDiff;
591206917Smarius    floatX zx;
592206917Smarius
593206917Smarius    if ( ax.isNaN ) return ax;
594206917Smarius    if ( bx.isNaN ) return bx;
595206917Smarius    if ( ax.isInf && bx.isInf ) {
596206917Smarius        if ( ax.sign == bx.sign ) return ax;
597206917Smarius        return floatXInvalid();
598206917Smarius    }
599206917Smarius    if ( ax.isInf ) return ax;
600206917Smarius    if ( bx.isInf ) return bx;
601206917Smarius    if ( ax.isZero && bx.isZero ) {
602206917Smarius        if ( ax.sign == bx.sign ) return ax;
603206917Smarius        goto completeCancellation;
604206917Smarius    }
605206917Smarius    if (    ( ax.sign != bx.sign )
606206917Smarius         && ( ax.exp == bx.exp )
607206917Smarius         && eq64( ax.sig, bx.sig )
608206917Smarius       ) {
609206917Smarius completeCancellation:
610206917Smarius        return
611206917Smarius              ( slow_float_rounding_mode == float_round_down ) ?
612206917Smarius                  floatXNegativeZero
613206917Smarius            : floatXPositiveZero;
614206917Smarius    }
615206917Smarius    if ( ax.isZero ) return bx;
616206917Smarius    if ( bx.isZero ) return ax;
617206917Smarius    expDiff = ax.exp - bx.exp;
618206917Smarius    if ( expDiff < 0 ) {
619206917Smarius        zx = ax;
620206917Smarius        zx.exp = bx.exp;
621206917Smarius        if ( expDiff < -56 ) {
622206917Smarius            zx.sig.a1 = 1;
623206917Smarius            zx.sig.a0 = 0;
624206917Smarius        }
625206917Smarius        else {
626206917Smarius            while ( expDiff < 0 ) {
627206917Smarius                zx.sig = shortShift64RightJamming( zx.sig, 1 );
628206917Smarius                ++expDiff;
629206917Smarius            }
630206917Smarius        }
631206917Smarius        if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig );
632206917Smarius        zx.sign = bx.sign;
633206917Smarius        zx.sig = add64( zx.sig, bx.sig );
634206917Smarius    }
635206917Smarius    else {
636206917Smarius        zx = bx;
637206917Smarius        zx.exp = ax.exp;
638206917Smarius        if ( 56 < expDiff ) {
639206917Smarius            zx.sig.a1 = 1;
640206917Smarius            zx.sig.a0 = 0;
641206917Smarius        }
642206917Smarius        else {
643206917Smarius            while ( 0 < expDiff ) {
644206917Smarius                zx.sig = shortShift64RightJamming( zx.sig, 1 );
645206917Smarius                --expDiff;
646206917Smarius            }
647206917Smarius        }
648206917Smarius        if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig );
649206917Smarius        zx.sign = ax.sign;
650206917Smarius        zx.sig = add64( zx.sig, ax.sig );
651206917Smarius    }
652206917Smarius    if ( zx.sig.a0 & 0x80000000 ) {
653206917Smarius        zx.sig = neg64( zx.sig );
654206917Smarius        zx.sign = ! zx.sign;
655206917Smarius    }
656206917Smarius    return zx;
657206917Smarius
658206917Smarius}
659206917Smarius
660206917Smariusstatic floatX floatXMul( floatX ax, floatX bx )
661206917Smarius{
662206917Smarius    int8 bitNum;
663206917Smarius    floatX zx;
664206917Smarius
665206917Smarius    if ( ax.isNaN ) return ax;
666206917Smarius    if ( bx.isNaN ) return bx;
667206917Smarius    if ( ax.isInf ) {
668206917Smarius        if ( bx.isZero ) return floatXInvalid();
669206917Smarius        if ( bx.sign ) ax.sign = ! ax.sign;
670206917Smarius        return ax;
671206917Smarius    }
672206917Smarius    if ( bx.isInf ) {
673206917Smarius        if ( ax.isZero ) return floatXInvalid();
674206917Smarius        if ( ax.sign ) bx.sign = ! bx.sign;
675206917Smarius        return bx;
676206917Smarius    }
677206917Smarius    zx = ax;
678206917Smarius    zx.sign ^= bx.sign;
679206917Smarius    if ( ax.isZero || bx.isZero ) {
680206917Smarius        return zx.sign ? floatXNegativeZero : floatXPositiveZero;
681206917Smarius    }
682206917Smarius    zx.exp += bx.exp + 1;
683206917Smarius    zx.sig.a1 = 0;
684206917Smarius    zx.sig.a0 = 0;
685206917Smarius    for ( bitNum = 0; bitNum < 55; ++bitNum ) {
686206917Smarius        if ( bx.sig.a1 & 2 ) zx.sig = add64( zx.sig, ax.sig );
687206917Smarius        bx.sig = shortShift64RightJamming( bx.sig, 1 );
688206917Smarius        zx.sig = shortShift64RightJamming( zx.sig, 1 );
689206917Smarius    }
690206917Smarius    return zx;
691206917Smarius
692206917Smarius}
693206917Smarius
694206917Smariusstatic floatX floatXDiv( floatX ax, floatX bx )
695206917Smarius{
696206917Smarius    bits64X negBSig;
697206917Smarius    int8 bitNum;
698206917Smarius    floatX zx;
699206917Smarius
700206917Smarius    if ( ax.isNaN ) return ax;
701206917Smarius    if ( bx.isNaN ) return bx;
702206917Smarius    if ( ax.isInf ) {
703206917Smarius        if ( bx.isInf ) return floatXInvalid();
704206917Smarius        if ( bx.sign ) ax.sign = ! ax.sign;
705206917Smarius        return ax;
706206917Smarius    }
707206917Smarius    if ( bx.isZero ) {
708206917Smarius        if ( ax.isZero ) return floatXInvalid();
709206917Smarius        slow_float_exception_flags |= float_flag_divbyzero;
710206917Smarius        if ( ax.sign ) bx.sign = ! bx.sign;
711206917Smarius        bx.isZero = FALSE;
712206917Smarius        bx.isInf = TRUE;
713206917Smarius        return bx;
714206917Smarius    }
715206917Smarius    zx = ax;
716206917Smarius    zx.sign ^= bx.sign;
717206917Smarius    if ( ax.isZero || bx.isInf ) {
718206917Smarius        return zx.sign ? floatXNegativeZero : floatXPositiveZero;
719206917Smarius    }
720206917Smarius    zx.exp -= bx.exp + 1;
721206917Smarius    zx.sig.a1 = 0;
722206917Smarius    zx.sig.a0 = 0;
723206917Smarius    negBSig = neg64( bx.sig );
724206917Smarius    for ( bitNum = 0; bitNum < 56; ++bitNum ) {
725206917Smarius        if ( le64( bx.sig, ax.sig ) ) {
726206917Smarius            zx.sig.a1 |= 1;
727206917Smarius            ax.sig = add64( ax.sig, negBSig );
728206917Smarius        }
729206917Smarius        ax.sig = shortShift64Left( ax.sig, 1 );
730206917Smarius        zx.sig = shortShift64Left( zx.sig, 1 );
731206917Smarius    }
732206917Smarius    if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
733206917Smarius    return zx;
734206917Smarius
735206917Smarius}
736206917Smarius
737206917Smariusstatic floatX floatXRem( floatX ax, floatX bx )
738206917Smarius{
739206917Smarius    bits64X negBSig;
740206917Smarius    flag lastQuotientBit;
741206917Smarius    bits64X savedASig;
742206917Smarius
743206917Smarius    if ( ax.isNaN ) return ax;
744206917Smarius    if ( bx.isNaN ) return bx;
745206917Smarius    if ( ax.isInf || bx.isZero ) return floatXInvalid();
746206917Smarius    if ( ax.isZero || bx.isInf ) return ax;
747206917Smarius    --bx.exp;
748206917Smarius    if ( ax.exp < bx.exp ) return ax;
749206917Smarius    bx.sig = shortShift64Left( bx.sig, 1 );
750206917Smarius    negBSig = neg64( bx.sig );
751206917Smarius    while ( bx.exp < ax.exp ) {
752206917Smarius        if ( le64( bx.sig, ax.sig ) ) ax.sig = add64( ax.sig, negBSig );
753206917Smarius        ax.sig = shortShift64Left( ax.sig, 1 );
754206917Smarius        --ax.exp;
755206917Smarius    }
756206917Smarius    lastQuotientBit = le64( bx.sig, ax.sig );
757206917Smarius    if ( lastQuotientBit ) ax.sig = add64( ax.sig, negBSig );
758206917Smarius    savedASig = ax.sig;
759206917Smarius    ax.sig = neg64( add64( ax.sig, negBSig ) );
760206917Smarius    if ( lt64( ax.sig, savedASig ) ) {
761206917Smarius        ax.sign = ! ax.sign;
762206917Smarius    }
763206917Smarius    else if ( lt64( savedASig, ax.sig ) ) {
764206917Smarius        ax.sig = savedASig;
765206917Smarius    }
766206917Smarius    else {
767206917Smarius        if ( lastQuotientBit ) {
768206917Smarius            ax.sign = ! ax.sign;
769206917Smarius        }
770206917Smarius        else {
771206917Smarius            ax.sig = savedASig;
772206917Smarius        }
773206917Smarius    }
774206917Smarius    if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
775206917Smarius    return ax;
776206917Smarius
777206917Smarius}
778206917Smarius
779206917Smariusstatic floatX floatXSqrt( floatX ax )
780206917Smarius{
781206917Smarius    int8 bitNum;
782206917Smarius    bits64X bitSig, savedASig;
783206917Smarius    floatX zx;
784206917Smarius
785206917Smarius    if ( ax.isNaN || ax.isZero ) return ax;
786206917Smarius    if ( ax.sign ) return floatXInvalid();
787206917Smarius    if ( ax.isInf ) return ax;
788206917Smarius    zx = ax;
789206917Smarius    zx.exp >>= 1;
790206917Smarius    if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift64RightJamming( ax.sig, 1 );
791206917Smarius    zx.sig.a1 = 0;
792206917Smarius    zx.sig.a0 = 0;
793206917Smarius    bitSig.a1 = 0;
794206917Smarius    bitSig.a0 = 0x00800000;
795206917Smarius    for ( bitNum = 0; bitNum < 56; ++bitNum ) {
796206917Smarius        savedASig = ax.sig;
797206917Smarius        ax.sig = add64( ax.sig, neg64( zx.sig ) );
798206917Smarius        ax.sig = shortShift64Left( ax.sig, 1 );
799206917Smarius        ax.sig = add64( ax.sig, neg64( bitSig ) );
800206917Smarius        if ( ax.sig.a0 & 0x80000000 ) {
801206917Smarius            ax.sig = shortShift64Left( savedASig, 1 );
802206917Smarius        }
803206917Smarius        else {
804206917Smarius            zx.sig.a1 |= bitSig.a1;
805206917Smarius            zx.sig.a0 |= bitSig.a0;
806206917Smarius        }
807206917Smarius        bitSig = shortShift64RightJamming( bitSig, 1 );
808206917Smarius    }
809206917Smarius    if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
810206917Smarius    return zx;
811206917Smarius
812206917Smarius}
813206917Smarius
814206917Smariusstatic flag floatXEq( floatX ax, floatX bx )
815206917Smarius{
816206917Smarius
817206917Smarius    if ( ax.isNaN || bx.isNaN ) return FALSE;
818206917Smarius    if ( ax.isZero && bx.isZero ) return TRUE;
819206917Smarius    if ( ax.sign != bx.sign ) return FALSE;
820206917Smarius    if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf;
821206917Smarius    return ( ax.exp == bx.exp ) && eq64( ax.sig, bx.sig );
822206917Smarius
823206917Smarius}
824206917Smarius
825206917Smariusstatic flag floatXLe( floatX ax, floatX bx )
826206917Smarius{
827206917Smarius
828206917Smarius    if ( ax.isNaN || bx.isNaN ) return FALSE;
829206917Smarius    if ( ax.isZero && bx.isZero ) return TRUE;
830206917Smarius    if ( ax.sign != bx.sign ) return ax.sign;
831206917Smarius    if ( ax.sign ) {
832206917Smarius        if ( ax.isInf || bx.isZero ) return TRUE;
833206917Smarius        if ( bx.isInf || ax.isZero ) return FALSE;
834206917Smarius        if ( bx.exp < ax.exp ) return TRUE;
835206917Smarius        if ( ax.exp < bx.exp ) return FALSE;
836206917Smarius        return le64( bx.sig, ax.sig );
837206917Smarius    }
838206917Smarius    else {
839206917Smarius        if ( bx.isInf || ax.isZero ) return TRUE;
840206917Smarius        if ( ax.isInf || bx.isZero ) return FALSE;
841206917Smarius        if ( ax.exp < bx.exp ) return TRUE;
842206917Smarius        if ( bx.exp < ax.exp ) return FALSE;
843206917Smarius        return le64( ax.sig, bx.sig );
844206917Smarius    }
845206917Smarius
846206917Smarius}
847206917Smarius
848206917Smariusstatic flag floatXLt( floatX ax, floatX bx )
849206917Smarius{
850206917Smarius
851206917Smarius    if ( ax.isNaN || bx.isNaN ) return FALSE;
852206917Smarius    if ( ax.isZero && bx.isZero ) return FALSE;
853206917Smarius    if ( ax.sign != bx.sign ) return ax.sign;
854206917Smarius    if ( ax.isInf && bx.isInf ) return FALSE;
855206917Smarius    if ( ax.sign ) {
856206917Smarius        if ( ax.isInf || bx.isZero ) return TRUE;
857206917Smarius        if ( bx.isInf || ax.isZero ) return FALSE;
858206917Smarius        if ( bx.exp < ax.exp ) return TRUE;
859206917Smarius        if ( ax.exp < bx.exp ) return FALSE;
860206917Smarius        return lt64( bx.sig, ax.sig );
861206917Smarius    }
862206917Smarius    else {
863206917Smarius        if ( bx.isInf || ax.isZero ) return TRUE;
864206917Smarius        if ( ax.isInf || bx.isZero ) return FALSE;
865206917Smarius        if ( ax.exp < bx.exp ) return TRUE;
866206917Smarius        if ( bx.exp < ax.exp ) return FALSE;
867206917Smarius        return lt64( ax.sig, bx.sig );
868206917Smarius    }
869206917Smarius
870206917Smarius}
871206917Smarius
872206917Smariusfloat32 slow_int32_to_float32( int32 a )
873206917Smarius{
874206917Smarius
875206917Smarius    return floatXToFloat32( int32ToFloatX( a ) );
876206917Smarius
877206917Smarius}
878206917Smarius
879206917Smariusfloat64 slow_int32_to_float64( int32 a )
880206917Smarius{
881206917Smarius
882206917Smarius    return floatXToFloat64( int32ToFloatX( a ) );
883206917Smarius
884206917Smarius}
885206917Smarius
886206917Smariusint32 slow_float32_to_int32( float32 a )
887206917Smarius{
888206917Smarius
889206917Smarius    return floatXToInt32( float32ToFloatX( a ) );
890206917Smarius
891206917Smarius}
892206917Smarius
893206917Smariusint32 slow_float32_to_int32_round_to_zero( float32 a )
894206917Smarius{
895206917Smarius    int8 savedRoundingMode;
896206917Smarius    int32 z;
897206917Smarius
898206917Smarius    savedRoundingMode = slow_float_rounding_mode;
899206917Smarius    slow_float_rounding_mode = float_round_to_zero;
900206917Smarius    z = floatXToInt32( float32ToFloatX( a ) );
901206917Smarius    slow_float_rounding_mode = savedRoundingMode;
902206917Smarius    return z;
903206917Smarius
904206917Smarius}
905206917Smarius
906206917Smariusfloat64 slow_float32_to_float64( float32 a )
907206917Smarius{
908206917Smarius
909206917Smarius    return floatXToFloat64( float32ToFloatX( a ) );
910206917Smarius
911206917Smarius}
912206917Smarius
913206917Smariusfloat32 slow_float32_round_to_int( float32 a )
914206917Smarius{
915206917Smarius
916206917Smarius    return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) );
917206917Smarius
918206917Smarius}
919206917Smarius
920206917Smariusfloat32 slow_float32_add( float32 a, float32 b )
921206917Smarius{
922206917Smarius
923206917Smarius    return
924206917Smarius        floatXToFloat32(
925206917Smarius            floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
926206917Smarius
927206917Smarius}
928206917Smarius
929206917Smariusfloat32 slow_float32_sub( float32 a, float32 b )
930206917Smarius{
931206917Smarius
932206917Smarius    b ^= 0x80000000;
933206917Smarius    return
934206917Smarius        floatXToFloat32(
935206917Smarius            floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
936206917Smarius
937206917Smarius}
938206917Smarius
939206917Smariusfloat32 slow_float32_mul( float32 a, float32 b )
940206917Smarius{
941206917Smarius
942206917Smarius    return
943206917Smarius        floatXToFloat32(
944206917Smarius            floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) );
945206917Smarius
946206917Smarius}
947206917Smarius
948206917Smariusfloat32 slow_float32_div( float32 a, float32 b )
949206917Smarius{
950206917Smarius
951206917Smarius    return
952206917Smarius        floatXToFloat32(
953206917Smarius            floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) );
954206917Smarius
955206917Smarius}
956206917Smarius
957206917Smariusfloat32 slow_float32_rem( float32 a, float32 b )
958206917Smarius{
959206917Smarius
960206917Smarius    return
961206917Smarius        floatXToFloat32(
962206917Smarius            floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) );
963206917Smarius
964206917Smarius}
965206917Smarius
966206917Smariusfloat32 slow_float32_sqrt( float32 a )
967206917Smarius{
968206917Smarius
969206917Smarius    return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) );
970206917Smarius
971206917Smarius}
972206917Smarius
973206917Smariusflag slow_float32_eq( float32 a, float32 b )
974206917Smarius{
975206917Smarius
976206917Smarius    return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) );
977206917Smarius
978206917Smarius}
979206917Smarius
980206917Smariusflag slow_float32_le( float32 a, float32 b )
981206917Smarius{
982206917Smarius    floatX ax, bx;
983206917Smarius
984206917Smarius    ax = float32ToFloatX( a );
985206917Smarius    bx = float32ToFloatX( b );
986206917Smarius    if ( ax.isNaN || bx.isNaN ) {
987206917Smarius        slow_float_exception_flags |= float_flag_invalid;
988206917Smarius    }
989206917Smarius    return floatXLe( ax, bx );
990206917Smarius
991206917Smarius}
992206917Smarius
993206917Smariusflag slow_float32_lt( float32 a, float32 b )
994206917Smarius{
995206917Smarius    floatX ax, bx;
996206917Smarius
997206917Smarius    ax = float32ToFloatX( a );
998206917Smarius    bx = float32ToFloatX( b );
999206917Smarius    if ( ax.isNaN || bx.isNaN ) {
1000206917Smarius        slow_float_exception_flags |= float_flag_invalid;
1001206917Smarius    }
1002206917Smarius    return floatXLt( ax, bx );
1003206917Smarius
1004206917Smarius}
1005206917Smarius
1006206917Smariusflag slow_float32_eq_signaling( float32 a, float32 b )
1007206917Smarius{
1008206917Smarius    floatX ax, bx;
1009206917Smarius
1010206917Smarius    ax = float32ToFloatX( a );
1011206917Smarius    bx = float32ToFloatX( b );
1012206917Smarius    if ( ax.isNaN || bx.isNaN ) {
1013206917Smarius        slow_float_exception_flags |= float_flag_invalid;
1014206917Smarius    }
1015206917Smarius    return floatXEq( ax, bx );
1016206917Smarius
1017206917Smarius}
1018206917Smarius
1019206917Smariusflag slow_float32_le_quiet( float32 a, float32 b )
1020206917Smarius{
1021206917Smarius
1022206917Smarius    return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) );
1023206917Smarius
1024206917Smarius}
1025206917Smarius
1026206917Smariusflag slow_float32_lt_quiet( float32 a, float32 b )
1027206917Smarius{
1028206917Smarius
1029206917Smarius    return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) );
1030206917Smarius
1031206917Smarius}
1032206917Smarius
1033206917Smariusint32 slow_float64_to_int32( float64 a )
1034206917Smarius{
1035206917Smarius
1036206917Smarius    return floatXToInt32( float64ToFloatX( a ) );
1037206917Smarius
1038206917Smarius}
1039206917Smarius
1040206917Smariusint32 slow_float64_to_int32_round_to_zero( float64 a )
1041206917Smarius{
1042206917Smarius    int8 savedRoundingMode;
1043206917Smarius    int32 z;
1044206917Smarius
1045206917Smarius    savedRoundingMode = slow_float_rounding_mode;
1046206917Smarius    slow_float_rounding_mode = float_round_to_zero;
1047206917Smarius    z = floatXToInt32( float64ToFloatX( a ) );
1048206917Smarius    slow_float_rounding_mode = savedRoundingMode;
1049206917Smarius    return z;
1050206917Smarius
1051206917Smarius}
1052206917Smarius
1053206917Smariusfloat32 slow_float64_to_float32( float64 a )
1054206917Smarius{
1055206917Smarius
1056206917Smarius    return floatXToFloat32( float64ToFloatX( a ) );
1057206917Smarius
1058206917Smarius}
1059206917Smarius
1060206917Smariusfloat64 slow_float64_round_to_int( float64 a )
1061206917Smarius{
1062206917Smarius
1063206917Smarius    return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) );
1064206917Smarius
1065206917Smarius}
1066206917Smarius
1067206917Smariusfloat64 slow_float64_add( float64 a, float64 b )
1068206917Smarius{
1069206917Smarius
1070206917Smarius    return
1071206917Smarius        floatXToFloat64(
1072206917Smarius            floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1073206917Smarius
1074206917Smarius}
1075206917Smarius
1076206917Smariusfloat64 slow_float64_sub( float64 a, float64 b )
1077206917Smarius{
1078206917Smarius
1079206917Smarius#ifdef BITS64
1080206917Smarius    b ^= LIT64( 0x8000000000000000 );
1081206917Smarius#else
1082206917Smarius    b.high ^= 0x80000000;
1083206917Smarius#endif
1084206917Smarius    return
1085206917Smarius        floatXToFloat64(
1086206917Smarius            floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1087206917Smarius
1088206917Smarius}
1089206917Smarius
1090206917Smariusfloat64 slow_float64_mul( float64 a, float64 b )
1091206917Smarius{
1092206917Smarius
1093206917Smarius    return
1094206917Smarius        floatXToFloat64(
1095206917Smarius            floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1096206917Smarius
1097206917Smarius}
1098206917Smarius
1099206917Smariusfloat64 slow_float64_div( float64 a, float64 b )
1100206917Smarius{
1101206917Smarius
1102206917Smarius    return
1103206917Smarius        floatXToFloat64(
1104206917Smarius            floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1105206917Smarius
1106206917Smarius}
1107206917Smarius
1108206917Smariusfloat64 slow_float64_rem( float64 a, float64 b )
1109206917Smarius{
1110206917Smarius
1111206917Smarius    return
1112206917Smarius        floatXToFloat64(
1113206917Smarius            floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1114206917Smarius
1115206917Smarius}
1116206917Smarius
1117206917Smariusfloat64 slow_float64_sqrt( float64 a )
1118206917Smarius{
1119206917Smarius
1120206917Smarius    return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) );
1121206917Smarius
1122206917Smarius}
1123206917Smarius
1124206917Smariusflag slow_float64_eq( float64 a, float64 b )
1125206917Smarius{
1126206917Smarius
1127206917Smarius    return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) );
1128206917Smarius
1129206917Smarius}
1130206917Smarius
1131206917Smariusflag slow_float64_le( float64 a, float64 b )
1132206917Smarius{
1133206917Smarius    floatX ax, bx;
1134206917Smarius
1135206917Smarius    ax = float64ToFloatX( a );
1136206917Smarius    bx = float64ToFloatX( b );
1137206917Smarius    if ( ax.isNaN || bx.isNaN ) {
1138206917Smarius        slow_float_exception_flags |= float_flag_invalid;
1139206917Smarius    }
1140206917Smarius    return floatXLe( ax, bx );
1141206917Smarius
1142206917Smarius}
1143206917Smarius
1144206917Smariusflag slow_float64_lt( float64 a, float64 b )
1145206917Smarius{
1146206917Smarius    floatX ax, bx;
1147206917Smarius
1148206917Smarius    ax = float64ToFloatX( a );
1149206917Smarius    bx = float64ToFloatX( b );
1150206917Smarius    if ( ax.isNaN || bx.isNaN ) {
1151206917Smarius        slow_float_exception_flags |= float_flag_invalid;
1152206917Smarius    }
1153206917Smarius    return floatXLt( ax, bx );
1154206917Smarius
1155206917Smarius}
1156206917Smarius
1157206917Smariusflag slow_float64_eq_signaling( float64 a, float64 b )
1158206917Smarius{
1159206917Smarius    floatX ax, bx;
1160206917Smarius
1161206917Smarius    ax = float64ToFloatX( a );
1162206917Smarius    bx = float64ToFloatX( b );
1163206917Smarius    if ( ax.isNaN || bx.isNaN ) {
1164206917Smarius        slow_float_exception_flags |= float_flag_invalid;
1165206917Smarius    }
1166206917Smarius    return floatXEq( ax, bx );
1167206917Smarius
1168206917Smarius}
1169206917Smarius
1170206917Smariusflag slow_float64_le_quiet( float64 a, float64 b )
1171206917Smarius{
1172206917Smarius
1173206917Smarius    return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) );
1174206917Smarius
1175206917Smarius}
1176206917Smarius
1177206917Smariusflag slow_float64_lt_quiet( float64 a, float64 b )
1178206917Smarius{
1179206917Smarius
1180206917Smarius    return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) );
1181206917Smarius
1182206917Smarius}
1183206917Smarius
1184