Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fp_arith.c
Go to the documentation of this file.
1 /*
2 
3  fp_arith.c: floating-point math routines for the Linux-m68k
4  floating point emulator.
5 
6  Copyright (c) 1998-1999 David Huggins-Daines.
7 
8  Somewhat based on the AlphaLinux floating point emulator, by David
9  Mosberger-Tang.
10 
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
13  your convenience.
14  */
15 
16 #include "fp_emu.h"
17 #include "multi_arith.h"
18 #include "fp_arith.h"
19 
20 const struct fp_ext fp_QNaN =
21 {
22  .exp = 0x7fff,
23  .mant = { .m64 = ~0 }
24 };
25 
26 const struct fp_ext fp_Inf =
27 {
28  .exp = 0x7fff,
29 };
30 
31 /* let's start with the easy ones */
32 
33 struct fp_ext *
34 fp_fabs(struct fp_ext *dest, struct fp_ext *src)
35 {
36  dprint(PINSTR, "fabs\n");
37 
38  fp_monadic_check(dest, src);
39 
40  dest->sign = 0;
41 
42  return dest;
43 }
44 
45 struct fp_ext *
46 fp_fneg(struct fp_ext *dest, struct fp_ext *src)
47 {
48  dprint(PINSTR, "fneg\n");
49 
50  fp_monadic_check(dest, src);
51 
52  dest->sign = !dest->sign;
53 
54  return dest;
55 }
56 
57 /* Now, the slightly harder ones */
58 
59 /* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
60  FDSUB, and FCMP instructions. */
61 
62 struct fp_ext *
63 fp_fadd(struct fp_ext *dest, struct fp_ext *src)
64 {
65  int diff;
66 
67  dprint(PINSTR, "fadd\n");
68 
69  fp_dyadic_check(dest, src);
70 
71  if (IS_INF(dest)) {
72  /* infinity - infinity == NaN */
73  if (IS_INF(src) && (src->sign != dest->sign))
74  fp_set_nan(dest);
75  return dest;
76  }
77  if (IS_INF(src)) {
78  fp_copy_ext(dest, src);
79  return dest;
80  }
81 
82  if (IS_ZERO(dest)) {
83  if (IS_ZERO(src)) {
84  if (src->sign != dest->sign) {
85  if (FPDATA->rnd == FPCR_ROUND_RM)
86  dest->sign = 1;
87  else
88  dest->sign = 0;
89  }
90  } else
91  fp_copy_ext(dest, src);
92  return dest;
93  }
94 
95  dest->lowmant = src->lowmant = 0;
96 
97  if ((diff = dest->exp - src->exp) > 0)
98  fp_denormalize(src, diff);
99  else if ((diff = -diff) > 0)
100  fp_denormalize(dest, diff);
101 
102  if (dest->sign == src->sign) {
103  if (fp_addmant(dest, src))
104  if (!fp_addcarry(dest))
105  return dest;
106  } else {
107  if (dest->mant.m64 < src->mant.m64) {
108  fp_submant(dest, src, dest);
109  dest->sign = !dest->sign;
110  } else
111  fp_submant(dest, dest, src);
112  }
113 
114  return dest;
115 }
116 
117 /* fp_fsub: Implements the kernel of the FSUB, FSSUB, and FDSUB
118  instructions.
119 
120  Remember that the arguments are in assembler-syntax order! */
121 
122 struct fp_ext *
123 fp_fsub(struct fp_ext *dest, struct fp_ext *src)
124 {
125  dprint(PINSTR, "fsub ");
126 
127  src->sign = !src->sign;
128  return fp_fadd(dest, src);
129 }
130 
131 
132 struct fp_ext *
133 fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
134 {
135  dprint(PINSTR, "fcmp ");
136 
137  FPDATA->temp[1] = *dest;
138  src->sign = !src->sign;
139  return fp_fadd(&FPDATA->temp[1], src);
140 }
141 
142 struct fp_ext *
143 fp_ftst(struct fp_ext *dest, struct fp_ext *src)
144 {
145  dprint(PINSTR, "ftst\n");
146 
147  (void)dest;
148 
149  return src;
150 }
151 
152 struct fp_ext *
153 fp_fmul(struct fp_ext *dest, struct fp_ext *src)
154 {
155  union fp_mant128 temp;
156  int exp;
157 
158  dprint(PINSTR, "fmul\n");
159 
160  fp_dyadic_check(dest, src);
161 
162  /* calculate the correct sign now, as it's necessary for infinities */
163  dest->sign = src->sign ^ dest->sign;
164 
165  /* Handle infinities */
166  if (IS_INF(dest)) {
167  if (IS_ZERO(src))
168  fp_set_nan(dest);
169  return dest;
170  }
171  if (IS_INF(src)) {
172  if (IS_ZERO(dest))
173  fp_set_nan(dest);
174  else
175  fp_copy_ext(dest, src);
176  return dest;
177  }
178 
179  /* Of course, as we all know, zero * anything = zero. You may
180  not have known that it might be a positive or negative
181  zero... */
182  if (IS_ZERO(dest) || IS_ZERO(src)) {
183  dest->exp = 0;
184  dest->mant.m64 = 0;
185  dest->lowmant = 0;
186 
187  return dest;
188  }
189 
190  exp = dest->exp + src->exp - 0x3ffe;
191 
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);
199 
200  /* now, do a 64-bit multiply with expansion */
201  fp_multiplymant(&temp, dest, src);
202 
203  /* normalize it back to 64 bits and stuff it back into the
204  destination struct */
205  if ((long)temp.m32[0] > 0) {
206  exp--;
207  fp_putmant128(dest, &temp, 1);
208  } else
209  fp_putmant128(dest, &temp, 0);
210 
211  if (exp >= 0x7fff) {
212  fp_set_ovrflw(dest);
213  return dest;
214  }
215  dest->exp = exp;
216  if (exp < 0) {
218  fp_denormalize(dest, -exp);
219  }
220 
221  return dest;
222 }
223 
224 /* fp_fdiv: Implements the "kernel" of the FDIV, FSDIV, FDDIV and
225  FSGLDIV instructions.
226 
227  Note that the order of the operands is counter-intuitive: instead
228  of src / dest, the result is actually dest / src. */
229 
230 struct fp_ext *
231 fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
232 {
233  union fp_mant128 temp;
234  int exp;
235 
236  dprint(PINSTR, "fdiv\n");
237 
238  fp_dyadic_check(dest, src);
239 
240  /* calculate the correct sign now, as it's necessary for infinities */
241  dest->sign = src->sign ^ dest->sign;
242 
243  /* Handle infinities */
244  if (IS_INF(dest)) {
245  /* infinity / infinity = NaN (quiet, as always) */
246  if (IS_INF(src))
247  fp_set_nan(dest);
248  /* infinity / anything else = infinity (with approprate sign) */
249  return dest;
250  }
251  if (IS_INF(src)) {
252  /* anything / infinity = zero (with appropriate sign) */
253  dest->exp = 0;
254  dest->mant.m64 = 0;
255  dest->lowmant = 0;
256 
257  return dest;
258  }
259 
260  /* zeroes */
261  if (IS_ZERO(dest)) {
262  /* zero / zero = NaN */
263  if (IS_ZERO(src))
264  fp_set_nan(dest);
265  /* zero / anything else = zero */
266  return dest;
267  }
268  if (IS_ZERO(src)) {
269  /* anything / zero = infinity (with appropriate sign) */
271  dest->exp = 0x7fff;
272  dest->mant.m64 = 0;
273 
274  return dest;
275  }
276 
277  exp = dest->exp - src->exp + 0x3fff;
278 
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);
286 
287  /* now, do the 64-bit divide */
288  fp_dividemant(&temp, dest, src);
289 
290  /* normalize it back to 64 bits and stuff it back into the
291  destination struct */
292  if (!temp.m32[0]) {
293  exp--;
294  fp_putmant128(dest, &temp, 32);
295  } else
296  fp_putmant128(dest, &temp, 31);
297 
298  if (exp >= 0x7fff) {
299  fp_set_ovrflw(dest);
300  return dest;
301  }
302  dest->exp = exp;
303  if (exp < 0) {
305  fp_denormalize(dest, -exp);
306  }
307 
308  return dest;
309 }
310 
311 struct fp_ext *
312 fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
313 {
314  int exp;
315 
316  dprint(PINSTR, "fsglmul\n");
317 
318  fp_dyadic_check(dest, src);
319 
320  /* calculate the correct sign now, as it's necessary for infinities */
321  dest->sign = src->sign ^ dest->sign;
322 
323  /* Handle infinities */
324  if (IS_INF(dest)) {
325  if (IS_ZERO(src))
326  fp_set_nan(dest);
327  return dest;
328  }
329  if (IS_INF(src)) {
330  if (IS_ZERO(dest))
331  fp_set_nan(dest);
332  else
333  fp_copy_ext(dest, src);
334  return dest;
335  }
336 
337  /* Of course, as we all know, zero * anything = zero. You may
338  not have known that it might be a positive or negative
339  zero... */
340  if (IS_ZERO(dest) || IS_ZERO(src)) {
341  dest->exp = 0;
342  dest->mant.m64 = 0;
343  dest->lowmant = 0;
344 
345  return dest;
346  }
347 
348  exp = dest->exp + src->exp - 0x3ffe;
349 
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);
354 
355  if (exp >= 0x7fff) {
356  fp_set_ovrflw(dest);
357  return dest;
358  }
359  dest->exp = exp;
360  if (exp < 0) {
362  fp_denormalize(dest, -exp);
363  }
364 
365  return dest;
366 }
367 
368 struct fp_ext *
369 fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
370 {
371  int exp;
372  unsigned long quot, rem;
373 
374  dprint(PINSTR, "fsgldiv\n");
375 
376  fp_dyadic_check(dest, src);
377 
378  /* calculate the correct sign now, as it's necessary for infinities */
379  dest->sign = src->sign ^ dest->sign;
380 
381  /* Handle infinities */
382  if (IS_INF(dest)) {
383  /* infinity / infinity = NaN (quiet, as always) */
384  if (IS_INF(src))
385  fp_set_nan(dest);
386  /* infinity / anything else = infinity (with approprate sign) */
387  return dest;
388  }
389  if (IS_INF(src)) {
390  /* anything / infinity = zero (with appropriate sign) */
391  dest->exp = 0;
392  dest->mant.m64 = 0;
393  dest->lowmant = 0;
394 
395  return dest;
396  }
397 
398  /* zeroes */
399  if (IS_ZERO(dest)) {
400  /* zero / zero = NaN */
401  if (IS_ZERO(src))
402  fp_set_nan(dest);
403  /* zero / anything else = zero */
404  return dest;
405  }
406  if (IS_ZERO(src)) {
407  /* anything / zero = infinity (with appropriate sign) */
409  dest->exp = 0x7fff;
410  dest->mant.m64 = 0;
411 
412  return dest;
413  }
414 
415  exp = dest->exp - src->exp + 0x3fff;
416 
417  dest->mant.m32[0] &= 0xffffff00;
418  src->mant.m32[0] &= 0xffffff00;
419 
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 */
426  } else {
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 */
430  exp--;
431  }
432 
433  if (exp >= 0x7fff) {
434  fp_set_ovrflw(dest);
435  return dest;
436  }
437  dest->exp = exp;
438  if (exp < 0) {
440  fp_denormalize(dest, -exp);
441  }
442 
443  return dest;
444 }
445 
446 /* fp_roundint: Internal rounding function for use by several of these
447  emulated instructions.
448 
449  This one rounds off the fractional part using the rounding mode
450  specified. */
451 
452 static void fp_roundint(struct fp_ext *dest, int mode)
453 {
454  union fp_mant64 oldmant;
455  unsigned long mask;
456 
457  if (!fp_normalize_ext(dest))
458  return;
459 
460  /* infinities and zeroes */
461  if (IS_INF(dest) || IS_ZERO(dest))
462  return;
463 
464  /* first truncate the lower bits */
465  oldmant = dest->mant;
466  switch (dest->exp) {
467  case 0 ... 0x3ffe:
468  dest->mant.m64 = 0;
469  break;
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)
474  return;
475  break;
476  case 0x401f ... 0x403e:
477  dest->mant.m32[1] &= 0xffffffffU << (0x403e - dest->exp);
478  if (oldmant.m32[1] == dest->mant.m32[1])
479  return;
480  break;
481  default:
482  return;
483  }
485 
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.
491 
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) */
497 
498  switch (mode) {
499  case FPCR_ROUND_RN:
500  switch (dest->exp) {
501  case 0 ... 0x3ffd:
502  return;
503  case 0x3ffe:
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))
509  return;
510  break;
511  case 0x3fff ... 0x401d:
512  mask = 1 << (0x401d - dest->exp);
513  if (!(oldmant.m32[0] & mask))
514  return;
515  if (oldmant.m32[0] & (mask << 1))
516  break;
517  if (!(oldmant.m32[0] << (dest->exp - 0x3ffd)) &&
518  !oldmant.m32[1])
519  return;
520  break;
521  case 0x401e:
522  if (!(oldmant.m32[1] >= 0))
523  return;
524  if (oldmant.m32[0] & 1)
525  break;
526  if (!(oldmant.m32[1] << 1))
527  return;
528  break;
529  case 0x401f ... 0x403d:
530  mask = 1 << (0x403d - dest->exp);
531  if (!(oldmant.m32[1] & mask))
532  return;
533  if (oldmant.m32[1] & (mask << 1))
534  break;
535  if (!(oldmant.m32[1] << (dest->exp - 0x401d)))
536  return;
537  break;
538  default:
539  return;
540  }
541  break;
542  case FPCR_ROUND_RZ:
543  return;
544  default:
545  if (dest->sign ^ (mode - FPCR_ROUND_RM))
546  break;
547  return;
548  }
549 
550  switch (dest->exp) {
551  case 0 ... 0x3ffe:
552  dest->exp = 0x3fff;
553  dest->mant.m64 = 1ULL << 63;
554  break;
555  case 0x3fff ... 0x401e:
556  mask = 1 << (0x401e - dest->exp);
557  if (dest->mant.m32[0] += mask)
558  break;
559  dest->mant.m32[0] = 0x80000000;
560  dest->exp++;
561  break;
562  case 0x401f ... 0x403e:
563  mask = 1 << (0x403e - dest->exp);
564  if (dest->mant.m32[1] += mask)
565  break;
566  if (dest->mant.m32[0] += 1)
567  break;
568  dest->mant.m32[0] = 0x80000000;
569  dest->exp++;
570  break;
571  }
572 }
573 
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) */
577 
578 static struct fp_ext *
579 modrem_kernel(struct fp_ext *dest, struct fp_ext *src, int mode)
580 {
581  struct fp_ext tmp;
582 
583  fp_dyadic_check(dest, src);
584 
585  /* Infinities and zeros */
586  if (IS_INF(dest) || IS_ZERO(src)) {
587  fp_set_nan(dest);
588  return dest;
589  }
590  if (IS_ZERO(dest) || IS_INF(src))
591  return dest;
592 
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);
597  fp_fmul(&tmp, src);
598  fp_fsub(dest, &tmp);
599 
600  /* set the quotient byte */
601  fp_set_quotient((dest->mant.m64 & 0x7f) | (dest->sign << 7));
602  return dest;
603 }
604 
605 /* fp_fmod: Implements the kernel of the FMOD instruction.
606 
607  Again, the argument order is backwards. The result, as defined in
608  the Motorola manuals, is:
609 
610  fmod(src,dest) = (dest - (src * floor(dest / src))) */
611 
612 struct fp_ext *
613 fp_fmod(struct fp_ext *dest, struct fp_ext *src)
614 {
615  dprint(PINSTR, "fmod\n");
616  return modrem_kernel(dest, src, FPCR_ROUND_RZ);
617 }
618 
619 /* fp_frem: Implements the kernel of the FREM instruction.
620 
621  frem(src,dest) = (dest - (src * round(dest / src)))
622  */
623 
624 struct fp_ext *
625 fp_frem(struct fp_ext *dest, struct fp_ext *src)
626 {
627  dprint(PINSTR, "frem\n");
628  return modrem_kernel(dest, src, FPCR_ROUND_RN);
629 }
630 
631 struct fp_ext *
632 fp_fint(struct fp_ext *dest, struct fp_ext *src)
633 {
634  dprint(PINSTR, "fint\n");
635 
636  fp_copy_ext(dest, src);
637 
638  fp_roundint(dest, FPDATA->rnd);
639 
640  return dest;
641 }
642 
643 struct fp_ext *
644 fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
645 {
646  dprint(PINSTR, "fintrz\n");
647 
648  fp_copy_ext(dest, src);
649 
650  fp_roundint(dest, FPCR_ROUND_RZ);
651 
652  return dest;
653 }
654 
655 struct fp_ext *
656 fp_fscale(struct fp_ext *dest, struct fp_ext *src)
657 {
658  int scale, oldround;
659 
660  dprint(PINSTR, "fscale\n");
661 
662  fp_dyadic_check(dest, src);
663 
664  /* Infinities */
665  if (IS_INF(src)) {
666  fp_set_nan(dest);
667  return dest;
668  }
669  if (IS_INF(dest))
670  return dest;
671 
672  /* zeroes */
673  if (IS_ZERO(src) || IS_ZERO(dest))
674  return dest;
675 
676  /* Source exponent out of range */
677  if (src->exp >= 0x400c) {
678  fp_set_ovrflw(dest);
679  return dest;
680  }
681 
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;
687 
688  /* new exponent */
689  scale += dest->exp;
690 
691  if (scale >= 0x7fff) {
692  fp_set_ovrflw(dest);
693  } else if (scale <= 0) {
695  fp_denormalize(dest, -scale);
696  } else
697  dest->exp = scale;
698 
699  return dest;
700 }
701