3 fp_arith.c: floating-point math routines for the Linux-m68k
4 floating point emulator.
6 Copyright (c) 1998-1999 David Huggins-Daines.
8 Somewhat based on the AlphaLinux floating point emulator, by David
11 You may copy, modify, and redistribute this file under the terms of
12 the GNU General Public License, version 2, or any later version, at
17 #include "multi_arith.h"
20 const struct fp_ext fp_QNaN
=
26 const struct fp_ext fp_Inf
=
31 /* let's start with the easy ones */
34 fp_fabs(struct fp_ext
*dest
, struct fp_ext
*src
)
36 dprint(PINSTR
, "fabs\n");
38 fp_monadic_check(dest
, src
);
46 fp_fneg(struct fp_ext
*dest
, struct fp_ext
*src
)
48 dprint(PINSTR
, "fneg\n");
50 fp_monadic_check(dest
, src
);
52 dest
->sign
= !dest
->sign
;
57 /* Now, the slightly harder ones */
59 /* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
60 FDSUB, and FCMP instructions. */
63 fp_fadd(struct fp_ext
*dest
, struct fp_ext
*src
)
67 dprint(PINSTR
, "fadd\n");
69 fp_dyadic_check(dest
, src
);
72 /* infinity - infinity == NaN */
73 if (IS_INF(src
) && (src
->sign
!= dest
->sign
))
78 fp_copy_ext(dest
, src
);
84 if (src
->sign
!= dest
->sign
) {
85 if (FPDATA
->rnd
== FPCR_ROUND_RM
)
91 fp_copy_ext(dest
, src
);
95 dest
->lowmant
= src
->lowmant
= 0;
97 if ((diff
= dest
->exp
- src
->exp
) > 0)
98 fp_denormalize(src
, diff
);
99 else if ((diff
= -diff
) > 0)
100 fp_denormalize(dest
, diff
);
102 if (dest
->sign
== src
->sign
) {
103 if (fp_addmant(dest
, src
))
104 if (!fp_addcarry(dest
))
107 if (dest
->mant
.m64
< src
->mant
.m64
) {
108 fp_submant(dest
, src
, dest
);
109 dest
->sign
= !dest
->sign
;
111 fp_submant(dest
, dest
, src
);
117 /* fp_fsub: Implements the kernel of the FSUB, FSSUB, and FDSUB
120 Remember that the arguments are in assembler-syntax order! */
123 fp_fsub(struct fp_ext
*dest
, struct fp_ext
*src
)
125 dprint(PINSTR
, "fsub ");
127 src
->sign
= !src
->sign
;
128 return fp_fadd(dest
, src
);
133 fp_fcmp(struct fp_ext
*dest
, struct fp_ext
*src
)
135 dprint(PINSTR
, "fcmp ");
137 FPDATA
->temp
[1] = *dest
;
138 src
->sign
= !src
->sign
;
139 return fp_fadd(&FPDATA
->temp
[1], src
);
143 fp_ftst(struct fp_ext
*dest
, struct fp_ext
*src
)
145 dprint(PINSTR
, "ftst\n");
153 fp_fmul(struct fp_ext
*dest
, struct fp_ext
*src
)
155 union fp_mant128 temp
;
158 dprint(PINSTR
, "fmul\n");
160 fp_dyadic_check(dest
, src
);
162 /* calculate the correct sign now, as it's necessary for infinities */
163 dest
->sign
= src
->sign
^ dest
->sign
;
165 /* Handle infinities */
175 fp_copy_ext(dest
, src
);
179 /* Of course, as we all know, zero * anything = zero. You may
180 not have known that it might be a positive or negative
182 if (IS_ZERO(dest
) || IS_ZERO(src
)) {
190 exp
= dest
->exp
+ src
->exp
- 0x3ffe;
192 /* shift up the mantissa for denormalized numbers,
193 so that the highest bit is set, this makes the
194 shift of the result below easier */
195 if ((long)dest
->mant
.m32
[0] >= 0)
196 exp
-= fp_overnormalize(dest
);
197 if ((long)src
->mant
.m32
[0] >= 0)
198 exp
-= fp_overnormalize(src
);
200 /* now, do a 64-bit multiply with expansion */
201 fp_multiplymant(&temp
, dest
, src
);
203 /* normalize it back to 64 bits and stuff it back into the
204 destination struct */
205 if ((long)temp
.m32
[0] > 0) {
207 fp_putmant128(dest
, &temp
, 1);
209 fp_putmant128(dest
, &temp
, 0);
217 fp_set_sr(FPSR_EXC_UNFL
);
218 fp_denormalize(dest
, -exp
);
224 /* fp_fdiv: Implements the "kernel" of the FDIV, FSDIV, FDDIV and
225 FSGLDIV instructions.
227 Note that the order of the operands is counter-intuitive: instead
228 of src / dest, the result is actually dest / src. */
231 fp_fdiv(struct fp_ext
*dest
, struct fp_ext
*src
)
233 union fp_mant128 temp
;
236 dprint(PINSTR
, "fdiv\n");
238 fp_dyadic_check(dest
, src
);
240 /* calculate the correct sign now, as it's necessary for infinities */
241 dest
->sign
= src
->sign
^ dest
->sign
;
243 /* Handle infinities */
245 /* infinity / infinity = NaN (quiet, as always) */
248 /* infinity / anything else = infinity (with approprate sign) */
252 /* anything / infinity = zero (with appropriate sign) */
262 /* zero / zero = NaN */
265 /* zero / anything else = zero */
269 /* anything / zero = infinity (with appropriate sign) */
270 fp_set_sr(FPSR_EXC_DZ
);
277 exp
= dest
->exp
- src
->exp
+ 0x3fff;
279 /* shift up the mantissa for denormalized numbers,
280 so that the highest bit is set, this makes lots
281 of things below easier */
282 if ((long)dest
->mant
.m32
[0] >= 0)
283 exp
-= fp_overnormalize(dest
);
284 if ((long)src
->mant
.m32
[0] >= 0)
285 exp
-= fp_overnormalize(src
);
287 /* now, do the 64-bit divide */
288 fp_dividemant(&temp
, dest
, src
);
290 /* normalize it back to 64 bits and stuff it back into the
291 destination struct */
294 fp_putmant128(dest
, &temp
, 32);
296 fp_putmant128(dest
, &temp
, 31);
304 fp_set_sr(FPSR_EXC_UNFL
);
305 fp_denormalize(dest
, -exp
);
312 fp_fsglmul(struct fp_ext
*dest
, struct fp_ext
*src
)
316 dprint(PINSTR
, "fsglmul\n");
318 fp_dyadic_check(dest
, src
);
320 /* calculate the correct sign now, as it's necessary for infinities */
321 dest
->sign
= src
->sign
^ dest
->sign
;
323 /* Handle infinities */
333 fp_copy_ext(dest
, src
);
337 /* Of course, as we all know, zero * anything = zero. You may
338 not have known that it might be a positive or negative
340 if (IS_ZERO(dest
) || IS_ZERO(src
)) {
348 exp
= dest
->exp
+ src
->exp
- 0x3ffe;
350 /* do a 32-bit multiply */
351 fp_mul64(dest
->mant
.m32
[0], dest
->mant
.m32
[1],
352 dest
->mant
.m32
[0] & 0xffffff00,
353 src
->mant
.m32
[0] & 0xffffff00);
361 fp_set_sr(FPSR_EXC_UNFL
);
362 fp_denormalize(dest
, -exp
);
369 fp_fsgldiv(struct fp_ext
*dest
, struct fp_ext
*src
)
372 unsigned long quot
, rem
;
374 dprint(PINSTR
, "fsgldiv\n");
376 fp_dyadic_check(dest
, src
);
378 /* calculate the correct sign now, as it's necessary for infinities */
379 dest
->sign
= src
->sign
^ dest
->sign
;
381 /* Handle infinities */
383 /* infinity / infinity = NaN (quiet, as always) */
386 /* infinity / anything else = infinity (with approprate sign) */
390 /* anything / infinity = zero (with appropriate sign) */
400 /* zero / zero = NaN */
403 /* zero / anything else = zero */
407 /* anything / zero = infinity (with appropriate sign) */
408 fp_set_sr(FPSR_EXC_DZ
);
415 exp
= dest
->exp
- src
->exp
+ 0x3fff;
417 dest
->mant
.m32
[0] &= 0xffffff00;
418 src
->mant
.m32
[0] &= 0xffffff00;
420 /* do the 32-bit divide */
421 if (dest
->mant
.m32
[0] >= src
->mant
.m32
[0]) {
422 fp_sub64(dest
->mant
, src
->mant
);
423 fp_div64(quot
, rem
, dest
->mant
.m32
[0], 0, src
->mant
.m32
[0]);
424 dest
->mant
.m32
[0] = 0x80000000 | (quot
>> 1);
425 dest
->mant
.m32
[1] = (quot
& 1) | rem
; /* only for rounding */
427 fp_div64(quot
, rem
, dest
->mant
.m32
[0], 0, src
->mant
.m32
[0]);
428 dest
->mant
.m32
[0] = quot
;
429 dest
->mant
.m32
[1] = rem
; /* only for rounding */
439 fp_set_sr(FPSR_EXC_UNFL
);
440 fp_denormalize(dest
, -exp
);
446 /* fp_roundint: Internal rounding function for use by several of these
447 emulated instructions.
449 This one rounds off the fractional part using the rounding mode
452 static void fp_roundint(struct fp_ext
*dest
, int mode
)
454 union fp_mant64 oldmant
;
457 if (!fp_normalize_ext(dest
))
460 /* infinities and zeroes */
461 if (IS_INF(dest
) || IS_ZERO(dest
))
464 /* first truncate the lower bits */
465 oldmant
= dest
->mant
;
470 case 0x3fff ... 0x401e:
471 dest
->mant
.m32
[0] &= 0xffffffffU
<< (0x401e - dest
->exp
);
472 dest
->mant
.m32
[1] = 0;
473 if (oldmant
.m64
== dest
->mant
.m64
)
476 case 0x401f ... 0x403e:
477 dest
->mant
.m32
[1] &= 0xffffffffU
<< (0x403e - dest
->exp
);
478 if (oldmant
.m32
[1] == dest
->mant
.m32
[1])
484 fp_set_sr(FPSR_EXC_INEX2
);
486 /* We might want to normalize upwards here... however, since
487 we know that this is only called on the output of fp_fdiv,
488 or with the input to fp_fint or fp_fintrz, and the inputs
489 to all these functions are either normal or denormalized
490 (no subnormals allowed!), there's really no need.
492 In the case of fp_fdiv, observe that 0x80000000 / 0xffff =
493 0xffff8000, and the same holds for 128-bit / 64-bit. (i.e. the
494 smallest possible normal dividend and the largest possible normal
495 divisor will still produce a normal quotient, therefore, (normal
496 << 64) / normal is normal in all cases) */
504 /* As noted above, the input is always normal, so the
505 guard bit (bit 63) is always set. therefore, the
506 only case in which we will NOT round to 1.0 is when
507 the input is exactly 0.5. */
508 if (oldmant
.m64
== (1ULL << 63))
511 case 0x3fff ... 0x401d:
512 mask
= 1 << (0x401d - dest
->exp
);
513 if (!(oldmant
.m32
[0] & mask
))
515 if (oldmant
.m32
[0] & (mask
<< 1))
517 if (!(oldmant
.m32
[0] << (dest
->exp
- 0x3ffd)) &&
522 if (oldmant
.m32
[1] & 0x80000000)
524 if (oldmant
.m32
[0] & 1)
526 if (!(oldmant
.m32
[1] << 1))
529 case 0x401f ... 0x403d:
530 mask
= 1 << (0x403d - dest
->exp
);
531 if (!(oldmant
.m32
[1] & mask
))
533 if (oldmant
.m32
[1] & (mask
<< 1))
535 if (!(oldmant
.m32
[1] << (dest
->exp
- 0x401d)))
545 if (dest
->sign
^ (mode
- FPCR_ROUND_RM
))
553 dest
->mant
.m64
= 1ULL << 63;
555 case 0x3fff ... 0x401e:
556 mask
= 1 << (0x401e - dest
->exp
);
557 if (dest
->mant
.m32
[0] += mask
)
559 dest
->mant
.m32
[0] = 0x80000000;
562 case 0x401f ... 0x403e:
563 mask
= 1 << (0x403e - dest
->exp
);
564 if (dest
->mant
.m32
[1] += mask
)
566 if (dest
->mant
.m32
[0] += 1)
568 dest
->mant
.m32
[0] = 0x80000000;
574 /* modrem_kernel: Implementation of the FREM and FMOD instructions
575 (which are exactly the same, except for the rounding used on the
576 intermediate value) */
578 static struct fp_ext
*
579 modrem_kernel(struct fp_ext
*dest
, struct fp_ext
*src
, int mode
)
583 fp_dyadic_check(dest
, src
);
585 /* Infinities and zeros */
586 if (IS_INF(dest
) || IS_ZERO(src
)) {
590 if (IS_ZERO(dest
) || IS_INF(src
))
593 /* FIXME: there is almost certainly a smarter way to do this */
594 fp_copy_ext(&tmp
, dest
);
595 fp_fdiv(&tmp
, src
); /* NOTE: src might be modified */
596 fp_roundint(&tmp
, mode
);
600 /* set the quotient byte */
601 fp_set_quotient((dest
->mant
.m64
& 0x7f) | (dest
->sign
<< 7));
605 /* fp_fmod: Implements the kernel of the FMOD instruction.
607 Again, the argument order is backwards. The result, as defined in
608 the Motorola manuals, is:
610 fmod(src,dest) = (dest - (src * floor(dest / src))) */
613 fp_fmod(struct fp_ext
*dest
, struct fp_ext
*src
)
615 dprint(PINSTR
, "fmod\n");
616 return modrem_kernel(dest
, src
, FPCR_ROUND_RZ
);
619 /* fp_frem: Implements the kernel of the FREM instruction.
621 frem(src,dest) = (dest - (src * round(dest / src)))
625 fp_frem(struct fp_ext
*dest
, struct fp_ext
*src
)
627 dprint(PINSTR
, "frem\n");
628 return modrem_kernel(dest
, src
, FPCR_ROUND_RN
);
632 fp_fint(struct fp_ext
*dest
, struct fp_ext
*src
)
634 dprint(PINSTR
, "fint\n");
636 fp_copy_ext(dest
, src
);
638 fp_roundint(dest
, FPDATA
->rnd
);
644 fp_fintrz(struct fp_ext
*dest
, struct fp_ext
*src
)
646 dprint(PINSTR
, "fintrz\n");
648 fp_copy_ext(dest
, src
);
650 fp_roundint(dest
, FPCR_ROUND_RZ
);
656 fp_fscale(struct fp_ext
*dest
, struct fp_ext
*src
)
660 dprint(PINSTR
, "fscale\n");
662 fp_dyadic_check(dest
, src
);
673 if (IS_ZERO(src
) || IS_ZERO(dest
))
676 /* Source exponent out of range */
677 if (src
->exp
>= 0x400c) {
682 /* src must be rounded with round to zero. */
683 oldround
= FPDATA
->rnd
;
684 FPDATA
->rnd
= FPCR_ROUND_RZ
;
685 scale
= fp_conv_ext2long(src
);
686 FPDATA
->rnd
= oldround
;
691 if (scale
>= 0x7fff) {
693 } else if (scale
<= 0) {
694 fp_set_sr(FPSR_EXC_UNFL
);
695 fp_denormalize(dest
, -scale
);