Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-6.1-pull-request...
[qemu/ar7.git] / fpu / softfloat-parts.c.inc
bloba897a5a743d3639794f328daec097976ec255656
1 /*
2  * QEMU float support
3  *
4  * The code in this source file is derived from release 2a of the SoftFloat
5  * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
6  * some later contributions) are provided under that license, as detailed below.
7  * It has subsequently been modified by contributors to the QEMU Project,
8  * so some portions are provided under:
9  *  the SoftFloat-2a license
10  *  the BSD license
11  *  GPL-v2-or-later
12  *
13  * Any future contributions to this file after December 1st 2014 will be
14  * taken to be licensed under the Softfloat-2a license unless specifically
15  * indicated otherwise.
16  */
18 static void partsN(return_nan)(FloatPartsN *a, float_status *s)
20     switch (a->cls) {
21     case float_class_snan:
22         float_raise(float_flag_invalid, s);
23         if (s->default_nan_mode) {
24             parts_default_nan(a, s);
25         } else {
26             parts_silence_nan(a, s);
27         }
28         break;
29     case float_class_qnan:
30         if (s->default_nan_mode) {
31             parts_default_nan(a, s);
32         }
33         break;
34     default:
35         g_assert_not_reached();
36     }
39 static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
40                                      float_status *s)
42     if (is_snan(a->cls) || is_snan(b->cls)) {
43         float_raise(float_flag_invalid, s);
44     }
46     if (s->default_nan_mode) {
47         parts_default_nan(a, s);
48     } else {
49         int cmp = frac_cmp(a, b);
50         if (cmp == 0) {
51             cmp = a->sign < b->sign;
52         }
54         if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
55             a = b;
56         }
57         if (is_snan(a->cls)) {
58             parts_silence_nan(a, s);
59         }
60     }
61     return a;
64 static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
65                                             FloatPartsN *c, float_status *s,
66                                             int ab_mask, int abc_mask)
68     int which;
70     if (unlikely(abc_mask & float_cmask_snan)) {
71         float_raise(float_flag_invalid, s);
72     }
74     which = pickNaNMulAdd(a->cls, b->cls, c->cls,
75                           ab_mask == float_cmask_infzero, s);
77     if (s->default_nan_mode || which == 3) {
78         /*
79          * Note that this check is after pickNaNMulAdd so that function
80          * has an opportunity to set the Invalid flag for infzero.
81          */
82         parts_default_nan(a, s);
83         return a;
84     }
86     switch (which) {
87     case 0:
88         break;
89     case 1:
90         a = b;
91         break;
92     case 2:
93         a = c;
94         break;
95     default:
96         g_assert_not_reached();
97     }
98     if (is_snan(a->cls)) {
99         parts_silence_nan(a, s);
100     }
101     return a;
105  * Canonicalize the FloatParts structure.  Determine the class,
106  * unbias the exponent, and normalize the fraction.
107  */
108 static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
109                                  const FloatFmt *fmt)
111     if (unlikely(p->exp == 0)) {
112         if (likely(frac_eqz(p))) {
113             p->cls = float_class_zero;
114         } else if (status->flush_inputs_to_zero) {
115             float_raise(float_flag_input_denormal, status);
116             p->cls = float_class_zero;
117             frac_clear(p);
118         } else {
119             int shift = frac_normalize(p);
120             p->cls = float_class_normal;
121             p->exp = fmt->frac_shift - fmt->exp_bias - shift + 1;
122         }
123     } else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
124         p->cls = float_class_normal;
125         p->exp -= fmt->exp_bias;
126         frac_shl(p, fmt->frac_shift);
127         p->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
128     } else if (likely(frac_eqz(p))) {
129         p->cls = float_class_inf;
130     } else {
131         frac_shl(p, fmt->frac_shift);
132         p->cls = (parts_is_snan_frac(p->frac_hi, status)
133                   ? float_class_snan : float_class_qnan);
134     }
138  * Round and uncanonicalize a floating-point number by parts. There
139  * are FRAC_SHIFT bits that may require rounding at the bottom of the
140  * fraction; these bits will be removed. The exponent will be biased
141  * by EXP_BIAS and must be bounded by [EXP_MAX-1, 0].
142  */
143 static void partsN(uncanon)(FloatPartsN *p, float_status *s,
144                             const FloatFmt *fmt)
146     const int exp_max = fmt->exp_max;
147     const int frac_shift = fmt->frac_shift;
148     const uint64_t frac_lsb = fmt->frac_lsb;
149     const uint64_t frac_lsbm1 = fmt->frac_lsbm1;
150     const uint64_t round_mask = fmt->round_mask;
151     const uint64_t roundeven_mask = fmt->roundeven_mask;
152     uint64_t inc;
153     bool overflow_norm;
154     int exp, flags = 0;
156     if (unlikely(p->cls != float_class_normal)) {
157         switch (p->cls) {
158         case float_class_zero:
159             p->exp = 0;
160             frac_clear(p);
161             return;
162         case float_class_inf:
163             g_assert(!fmt->arm_althp);
164             p->exp = fmt->exp_max;
165             frac_clear(p);
166             return;
167         case float_class_qnan:
168         case float_class_snan:
169             g_assert(!fmt->arm_althp);
170             p->exp = fmt->exp_max;
171             frac_shr(p, fmt->frac_shift);
172             return;
173         default:
174             break;
175         }
176         g_assert_not_reached();
177     }
179     switch (s->float_rounding_mode) {
180     case float_round_nearest_even:
181         overflow_norm = false;
182         inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1 ? frac_lsbm1 : 0);
183         break;
184     case float_round_ties_away:
185         overflow_norm = false;
186         inc = frac_lsbm1;
187         break;
188     case float_round_to_zero:
189         overflow_norm = true;
190         inc = 0;
191         break;
192     case float_round_up:
193         inc = p->sign ? 0 : round_mask;
194         overflow_norm = p->sign;
195         break;
196     case float_round_down:
197         inc = p->sign ? round_mask : 0;
198         overflow_norm = !p->sign;
199         break;
200     case float_round_to_odd:
201         overflow_norm = true;
202         inc = p->frac_lo & frac_lsb ? 0 : round_mask;
203         break;
204     default:
205         g_assert_not_reached();
206     }
208     exp = p->exp + fmt->exp_bias;
209     if (likely(exp > 0)) {
210         if (p->frac_lo & round_mask) {
211             flags |= float_flag_inexact;
212             if (frac_addi(p, p, inc)) {
213                 frac_shr(p, 1);
214                 p->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
215                 exp++;
216             }
217         }
218         frac_shr(p, frac_shift);
220         if (fmt->arm_althp) {
221             /* ARM Alt HP eschews Inf and NaN for a wider exponent.  */
222             if (unlikely(exp > exp_max)) {
223                 /* Overflow.  Return the maximum normal.  */
224                 flags = float_flag_invalid;
225                 exp = exp_max;
226                 frac_allones(p);
227             }
228         } else if (unlikely(exp >= exp_max)) {
229             flags |= float_flag_overflow | float_flag_inexact;
230             if (overflow_norm) {
231                 exp = exp_max - 1;
232                 frac_allones(p);
233             } else {
234                 p->cls = float_class_inf;
235                 exp = exp_max;
236                 frac_clear(p);
237             }
238         }
239     } else if (s->flush_to_zero) {
240         flags |= float_flag_output_denormal;
241         p->cls = float_class_zero;
242         exp = 0;
243         frac_clear(p);
244     } else {
245         bool is_tiny = s->tininess_before_rounding || exp < 0;
247         if (!is_tiny) {
248             FloatPartsN discard;
249             is_tiny = !frac_addi(&discard, p, inc);
250         }
252         frac_shrjam(p, 1 - exp);
254         if (p->frac_lo & round_mask) {
255             /* Need to recompute round-to-even/round-to-odd. */
256             switch (s->float_rounding_mode) {
257             case float_round_nearest_even:
258                 inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1
259                        ? frac_lsbm1 : 0);
260                 break;
261             case float_round_to_odd:
262                 inc = p->frac_lo & frac_lsb ? 0 : round_mask;
263                 break;
264             default:
265                 break;
266             }
267             flags |= float_flag_inexact;
268             frac_addi(p, p, inc);
269         }
271         exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) != 0;
272         frac_shr(p, frac_shift);
274         if (is_tiny && (flags & float_flag_inexact)) {
275             flags |= float_flag_underflow;
276         }
277         if (exp == 0 && frac_eqz(p)) {
278             p->cls = float_class_zero;
279         }
280     }
281     p->exp = exp;
282     float_raise(flags, s);
286  * Returns the result of adding or subtracting the values of the
287  * floating-point values `a' and `b'. The operation is performed
288  * according to the IEC/IEEE Standard for Binary Floating-Point
289  * Arithmetic.
290  */
291 static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
292                                    float_status *s, bool subtract)
294     bool b_sign = b->sign ^ subtract;
295     int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
297     if (a->sign != b_sign) {
298         /* Subtraction */
299         if (likely(ab_mask == float_cmask_normal)) {
300             if (parts_sub_normal(a, b)) {
301                 return a;
302             }
303             /* Subtract was exact, fall through to set sign. */
304             ab_mask = float_cmask_zero;
305         }
307         if (ab_mask == float_cmask_zero) {
308             a->sign = s->float_rounding_mode == float_round_down;
309             return a;
310         }
312         if (unlikely(ab_mask & float_cmask_anynan)) {
313             goto p_nan;
314         }
316         if (ab_mask & float_cmask_inf) {
317             if (a->cls != float_class_inf) {
318                 /* N - Inf */
319                 goto return_b;
320             }
321             if (b->cls != float_class_inf) {
322                 /* Inf - N */
323                 return a;
324             }
325             /* Inf - Inf */
326             float_raise(float_flag_invalid, s);
327             parts_default_nan(a, s);
328             return a;
329         }
330     } else {
331         /* Addition */
332         if (likely(ab_mask == float_cmask_normal)) {
333             parts_add_normal(a, b);
334             return a;
335         }
337         if (ab_mask == float_cmask_zero) {
338             return a;
339         }
341         if (unlikely(ab_mask & float_cmask_anynan)) {
342             goto p_nan;
343         }
345         if (ab_mask & float_cmask_inf) {
346             a->cls = float_class_inf;
347             return a;
348         }
349     }
351     if (b->cls == float_class_zero) {
352         g_assert(a->cls == float_class_normal);
353         return a;
354     }
356     g_assert(a->cls == float_class_zero);
357     g_assert(b->cls == float_class_normal);
358  return_b:
359     b->sign = b_sign;
360     return b;
362  p_nan:
363     return parts_pick_nan(a, b, s);
367  * Returns the result of multiplying the floating-point values `a' and
368  * `b'. The operation is performed according to the IEC/IEEE Standard
369  * for Binary Floating-Point Arithmetic.
370  */
371 static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
372                                 float_status *s)
374     int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
375     bool sign = a->sign ^ b->sign;
377     if (likely(ab_mask == float_cmask_normal)) {
378         FloatPartsW tmp;
380         frac_mulw(&tmp, a, b);
381         frac_truncjam(a, &tmp);
383         a->exp += b->exp + 1;
384         if (!(a->frac_hi & DECOMPOSED_IMPLICIT_BIT)) {
385             frac_add(a, a, a);
386             a->exp -= 1;
387         }
389         a->sign = sign;
390         return a;
391     }
393     /* Inf * Zero == NaN */
394     if (unlikely(ab_mask == float_cmask_infzero)) {
395         float_raise(float_flag_invalid, s);
396         parts_default_nan(a, s);
397         return a;
398     }
400     if (unlikely(ab_mask & float_cmask_anynan)) {
401         return parts_pick_nan(a, b, s);
402     }
404     /* Multiply by 0 or Inf */
405     if (ab_mask & float_cmask_inf) {
406         a->cls = float_class_inf;
407         a->sign = sign;
408         return a;
409     }
411     g_assert(ab_mask & float_cmask_zero);
412     a->cls = float_class_zero;
413     a->sign = sign;
414     return a;
418  * Returns the result of multiplying the floating-point values `a' and
419  * `b' then adding 'c', with no intermediate rounding step after the
420  * multiplication. The operation is performed according to the
421  * IEC/IEEE Standard for Binary Floating-Point Arithmetic 754-2008.
422  * The flags argument allows the caller to select negation of the
423  * addend, the intermediate product, or the final result. (The
424  * difference between this and having the caller do a separate
425  * negation is that negating externally will flip the sign bit on NaNs.)
427  * Requires A and C extracted into a double-sized structure to provide the
428  * extra space for the widening multiply.
429  */
430 static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
431                                    FloatPartsN *c, int flags, float_status *s)
433     int ab_mask, abc_mask;
434     FloatPartsW p_widen, c_widen;
436     ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
437     abc_mask = float_cmask(c->cls) | ab_mask;
439     /*
440      * It is implementation-defined whether the cases of (0,inf,qnan)
441      * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
442      * they return if they do), so we have to hand this information
443      * off to the target-specific pick-a-NaN routine.
444      */
445     if (unlikely(abc_mask & float_cmask_anynan)) {
446         return parts_pick_nan_muladd(a, b, c, s, ab_mask, abc_mask);
447     }
449     if (flags & float_muladd_negate_c) {
450         c->sign ^= 1;
451     }
453     /* Compute the sign of the product into A. */
454     a->sign ^= b->sign;
455     if (flags & float_muladd_negate_product) {
456         a->sign ^= 1;
457     }
459     if (unlikely(ab_mask != float_cmask_normal)) {
460         if (unlikely(ab_mask == float_cmask_infzero)) {
461             goto d_nan;
462         }
464         if (ab_mask & float_cmask_inf) {
465             if (c->cls == float_class_inf && a->sign != c->sign) {
466                 goto d_nan;
467             }
468             goto return_inf;
469         }
471         g_assert(ab_mask & float_cmask_zero);
472         if (c->cls == float_class_normal) {
473             *a = *c;
474             goto return_normal;
475         }
476         if (c->cls == float_class_zero) {
477             if (a->sign != c->sign) {
478                 goto return_sub_zero;
479             }
480             goto return_zero;
481         }
482         g_assert(c->cls == float_class_inf);
483     }
485     if (unlikely(c->cls == float_class_inf)) {
486         a->sign = c->sign;
487         goto return_inf;
488     }
490     /* Perform the multiplication step. */
491     p_widen.sign = a->sign;
492     p_widen.exp = a->exp + b->exp + 1;
493     frac_mulw(&p_widen, a, b);
494     if (!(p_widen.frac_hi & DECOMPOSED_IMPLICIT_BIT)) {
495         frac_add(&p_widen, &p_widen, &p_widen);
496         p_widen.exp -= 1;
497     }
499     /* Perform the addition step. */
500     if (c->cls != float_class_zero) {
501         /* Zero-extend C to less significant bits. */
502         frac_widen(&c_widen, c);
503         c_widen.exp = c->exp;
505         if (a->sign == c->sign) {
506             parts_add_normal(&p_widen, &c_widen);
507         } else if (!parts_sub_normal(&p_widen, &c_widen)) {
508             goto return_sub_zero;
509         }
510     }
512     /* Narrow with sticky bit, for proper rounding later. */
513     frac_truncjam(a, &p_widen);
514     a->sign = p_widen.sign;
515     a->exp = p_widen.exp;
517  return_normal:
518     if (flags & float_muladd_halve_result) {
519         a->exp -= 1;
520     }
521  finish_sign:
522     if (flags & float_muladd_negate_result) {
523         a->sign ^= 1;
524     }
525     return a;
527  return_sub_zero:
528     a->sign = s->float_rounding_mode == float_round_down;
529  return_zero:
530     a->cls = float_class_zero;
531     goto finish_sign;
533  return_inf:
534     a->cls = float_class_inf;
535     goto finish_sign;
537  d_nan:
538     float_raise(float_flag_invalid, s);
539     parts_default_nan(a, s);
540     return a;
544  * Returns the result of dividing the floating-point value `a' by the
545  * corresponding value `b'. The operation is performed according to
546  * the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
547  */
548 static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
549                                 float_status *s)
551     int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
552     bool sign = a->sign ^ b->sign;
554     if (likely(ab_mask == float_cmask_normal)) {
555         a->sign = sign;
556         a->exp -= b->exp + frac_div(a, b);
557         return a;
558     }
560     /* 0/0 or Inf/Inf => NaN */
561     if (unlikely(ab_mask == float_cmask_zero) ||
562         unlikely(ab_mask == float_cmask_inf)) {
563         float_raise(float_flag_invalid, s);
564         parts_default_nan(a, s);
565         return a;
566     }
568     /* All the NaN cases */
569     if (unlikely(ab_mask & float_cmask_anynan)) {
570         return parts_pick_nan(a, b, s);
571     }
573     a->sign = sign;
575     /* Inf / X */
576     if (a->cls == float_class_inf) {
577         return a;
578     }
580     /* 0 / X */
581     if (a->cls == float_class_zero) {
582         return a;
583     }
585     /* X / Inf */
586     if (b->cls == float_class_inf) {
587         a->cls = float_class_zero;
588         return a;
589     }
591     /* X / 0 => Inf */
592     g_assert(b->cls == float_class_zero);
593     float_raise(float_flag_divbyzero, s);
594     a->cls = float_class_inf;
595     return a;
599  * Rounds the floating-point value `a' to an integer, and returns the
600  * result as a floating-point value. The operation is performed
601  * according to the IEC/IEEE Standard for Binary Floating-Point
602  * Arithmetic.
604  * parts_round_to_int_normal is an internal helper function for
605  * normal numbers only, returning true for inexact but not directly
606  * raising float_flag_inexact.
607  */
608 static bool partsN(round_to_int_normal)(FloatPartsN *a, FloatRoundMode rmode,
609                                         int scale, int frac_size)
611     uint64_t frac_lsb, frac_lsbm1, rnd_even_mask, rnd_mask, inc;
612     int shift_adj;
614     scale = MIN(MAX(scale, -0x10000), 0x10000);
615     a->exp += scale;
617     if (a->exp < 0) {
618         bool one;
620         /* All fractional */
621         switch (rmode) {
622         case float_round_nearest_even:
623             one = false;
624             if (a->exp == -1) {
625                 FloatPartsN tmp;
626                 /* Shift left one, discarding DECOMPOSED_IMPLICIT_BIT */
627                 frac_add(&tmp, a, a);
628                 /* Anything remaining means frac > 0.5. */
629                 one = !frac_eqz(&tmp);
630             }
631             break;
632         case float_round_ties_away:
633             one = a->exp == -1;
634             break;
635         case float_round_to_zero:
636             one = false;
637             break;
638         case float_round_up:
639             one = !a->sign;
640             break;
641         case float_round_down:
642             one = a->sign;
643             break;
644         case float_round_to_odd:
645             one = true;
646             break;
647         default:
648             g_assert_not_reached();
649         }
651         frac_clear(a);
652         a->exp = 0;
653         if (one) {
654             a->frac_hi = DECOMPOSED_IMPLICIT_BIT;
655         } else {
656             a->cls = float_class_zero;
657         }
658         return true;
659     }
661     if (a->exp >= frac_size) {
662         /* All integral */
663         return false;
664     }
666     if (N > 64 && a->exp < N - 64) {
667         /*
668          * Rounding is not in the low word -- shift lsb to bit 2,
669          * which leaves room for sticky and rounding bit.
670          */
671         shift_adj = (N - 1) - (a->exp + 2);
672         frac_shrjam(a, shift_adj);
673         frac_lsb = 1 << 2;
674     } else {
675         shift_adj = 0;
676         frac_lsb = DECOMPOSED_IMPLICIT_BIT >> (a->exp & 63);
677     }
679     frac_lsbm1 = frac_lsb >> 1;
680     rnd_mask = frac_lsb - 1;
681     rnd_even_mask = rnd_mask | frac_lsb;
683     if (!(a->frac_lo & rnd_mask)) {
684         /* Fractional bits already clear, undo the shift above. */
685         frac_shl(a, shift_adj);
686         return false;
687     }
689     switch (rmode) {
690     case float_round_nearest_even:
691         inc = ((a->frac_lo & rnd_even_mask) != frac_lsbm1 ? frac_lsbm1 : 0);
692         break;
693     case float_round_ties_away:
694         inc = frac_lsbm1;
695         break;
696     case float_round_to_zero:
697         inc = 0;
698         break;
699     case float_round_up:
700         inc = a->sign ? 0 : rnd_mask;
701         break;
702     case float_round_down:
703         inc = a->sign ? rnd_mask : 0;
704         break;
705     case float_round_to_odd:
706         inc = a->frac_lo & frac_lsb ? 0 : rnd_mask;
707         break;
708     default:
709         g_assert_not_reached();
710     }
712     if (shift_adj == 0) {
713         if (frac_addi(a, a, inc)) {
714             frac_shr(a, 1);
715             a->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
716             a->exp++;
717         }
718         a->frac_lo &= ~rnd_mask;
719     } else {
720         frac_addi(a, a, inc);
721         a->frac_lo &= ~rnd_mask;
722         /* Be careful shifting back, not to overflow */
723         frac_shl(a, shift_adj - 1);
724         if (a->frac_hi & DECOMPOSED_IMPLICIT_BIT) {
725             a->exp++;
726         } else {
727             frac_add(a, a, a);
728         }
729     }
730     return true;
733 static void partsN(round_to_int)(FloatPartsN *a, FloatRoundMode rmode,
734                                  int scale, float_status *s,
735                                  const FloatFmt *fmt)
737     switch (a->cls) {
738     case float_class_qnan:
739     case float_class_snan:
740         parts_return_nan(a, s);
741         break;
742     case float_class_zero:
743     case float_class_inf:
744         break;
745     case float_class_normal:
746         if (parts_round_to_int_normal(a, rmode, scale, fmt->frac_size)) {
747             float_raise(float_flag_inexact, s);
748         }
749         break;
750     default:
751         g_assert_not_reached();
752     }
756  * Returns the result of converting the floating-point value `a' to
757  * the two's complement integer format. The conversion is performed
758  * according to the IEC/IEEE Standard for Binary Floating-Point
759  * Arithmetic---which means in particular that the conversion is
760  * rounded according to the current rounding mode. If `a' is a NaN,
761  * the largest positive integer is returned. Otherwise, if the
762  * conversion overflows, the largest integer with the same sign as `a'
763  * is returned.
765 static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
766                                      int scale, int64_t min, int64_t max,
767                                      float_status *s)
769     int flags = 0;
770     uint64_t r;
772     switch (p->cls) {
773     case float_class_snan:
774     case float_class_qnan:
775         flags = float_flag_invalid;
776         r = max;
777         break;
779     case float_class_inf:
780         flags = float_flag_invalid;
781         r = p->sign ? min : max;
782         break;
784     case float_class_zero:
785         return 0;
787     case float_class_normal:
788         /* TODO: N - 2 is frac_size for rounding; could use input fmt. */
789         if (parts_round_to_int_normal(p, rmode, scale, N - 2)) {
790             flags = float_flag_inexact;
791         }
793         if (p->exp <= DECOMPOSED_BINARY_POINT) {
794             r = p->frac_hi >> (DECOMPOSED_BINARY_POINT - p->exp);
795         } else {
796             r = UINT64_MAX;
797         }
798         if (p->sign) {
799             if (r <= -(uint64_t)min) {
800                 r = -r;
801             } else {
802                 flags = float_flag_invalid;
803                 r = min;
804             }
805         } else if (r > max) {
806             flags = float_flag_invalid;
807             r = max;
808         }
809         break;
811     default:
812         g_assert_not_reached();
813     }
815     float_raise(flags, s);
816     return r;