This source file includes following definitions.
- trig_arg
- convert_l2reg
- single_arg_error
- single_arg_2_error
- f2xm1
- fptan
- fxtract
- fdecstp
- fincstp
- fsqrt_
- frndint_
- fsin
- f_cos
- fcos
- fsincos
- rem_kernel
- do_fprem
- fyl2x
- fpatan
- fprem
- fprem1
- fyl2xp1
- fscale
- trig_a
- trig_b
1
2
3
4
5
6
7
8
9
10
11
12
13 #include "fpu_system.h"
14 #include "exception.h"
15 #include "fpu_emu.h"
16 #include "status_w.h"
17 #include "control_w.h"
18 #include "reg_constant.h"
19
20
21 static void rem_kernel(unsigned long long st0, unsigned long long *y,
22 unsigned long long st1,
23 unsigned long long q, int n);
24
25 #define BETTER_THAN_486
26
27 #define FCOS 4
28
29
30
31
32
33
34
35
36
37
38 static int trig_arg(FPU_REG *X, int even)
39 {
40 FPU_REG tmp;
41 unsigned long long q;
42 int old_cw = control_word, saved_status = partial_status;
43
44 if ( X->exp >= EXP_BIAS + 63 )
45 {
46 partial_status |= SW_C2;
47 return -1;
48 }
49
50 control_word &= ~CW_RC;
51 control_word |= RC_CHOP;
52
53 reg_div(X, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
54 round_to_int(&tmp);
55
56 q = significand(&tmp);
57 if ( q )
58 {
59 rem_kernel(significand(X),
60 &significand(&tmp),
61 significand(&CONST_PI2),
62 q, X->exp - CONST_PI2.exp);
63 tmp.exp = CONST_PI2.exp;
64 normalize(&tmp);
65 reg_move(&tmp, X);
66 }
67
68 #ifdef FPTAN
69 if ( even == FPTAN )
70 {
71 if ( ((X->exp >= EXP_BIAS) ||
72 ((X->exp == EXP_BIAS-1)
73 && (X->sigh >= 0xc90fdaa2))) ^ (q & 1) )
74 even = FCOS;
75 else
76 even = 0;
77 }
78 #endif FPTAN
79
80 if ( (even && !(q & 1)) || (!even && (q & 1)) )
81 {
82 reg_sub(&CONST_PI2, X, X, FULL_PRECISION);
83 #ifdef BETTER_THAN_486
84
85
86
87
88 if ( (X->exp <= CONST_PI2extra.exp + 64) || (q > 1) )
89 {
90
91
92 significand(&tmp) = q + 1;
93 tmp.exp = EXP_BIAS + 63;
94 tmp.tag = TW_Valid;
95 normalize(&tmp);
96 reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
97 reg_add(X, &tmp, X, FULL_PRECISION);
98 if ( X->sign == SIGN_NEG )
99 {
100
101
102
103
104 X->sign = SIGN_POS;
105 q++;
106 }
107 }
108 #endif BETTER_THAN_486
109 }
110 #ifdef BETTER_THAN_486
111 else
112 {
113
114
115
116
117 if ( ((q > 0) && (X->exp <= CONST_PI2extra.exp + 64)) || (q > 1) )
118 {
119
120
121 significand(&tmp) = q;
122 tmp.exp = EXP_BIAS + 63;
123 tmp.tag = TW_Valid;
124 normalize(&tmp);
125 reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
126 reg_sub(X, &tmp, X, FULL_PRECISION);
127 if ( (X->exp == CONST_PI2.exp) &&
128 ((X->sigh > CONST_PI2.sigh)
129 || ((X->sigh == CONST_PI2.sigh)
130 && (X->sigl > CONST_PI2.sigl))) )
131 {
132
133
134
135
136
137 reg_sub(&CONST_PI, X, X, FULL_PRECISION);
138 q++;
139 }
140 }
141 }
142 #endif BETTER_THAN_486
143
144 control_word = old_cw;
145 partial_status = saved_status & ~SW_C2;
146
147 return (q & 3) | even;
148 }
149
150
151
152 void convert_l2reg(long const *arg, FPU_REG *dest)
153 {
154 long num = *arg;
155
156 if (num == 0)
157 { reg_move(&CONST_Z, dest); return; }
158
159 if (num > 0)
160 dest->sign = SIGN_POS;
161 else
162 { num = -num; dest->sign = SIGN_NEG; }
163
164 dest->sigh = num;
165 dest->sigl = 0;
166 dest->exp = EXP_BIAS + 31;
167 dest->tag = TW_Valid;
168 normalize(dest);
169 }
170
171
172 static void single_arg_error(FPU_REG *st0_ptr)
173 {
174 switch ( st0_ptr->tag )
175 {
176 case TW_NaN:
177 if ( !(st0_ptr->sigh & 0x40000000) )
178 {
179 EXCEPTION(EX_Invalid);
180 if ( control_word & CW_Invalid )
181 st0_ptr->sigh |= 0x40000000;
182 }
183 break;
184 case TW_Empty:
185 stack_underflow();
186 break;
187 #ifdef PARANOID
188 default:
189 EXCEPTION(EX_INTERNAL|0x0112);
190 #endif PARANOID
191 }
192 }
193
194
195 static void single_arg_2_error(FPU_REG *st0_ptr)
196 {
197 FPU_REG *st_new_ptr;
198
199 switch ( st0_ptr->tag )
200 {
201 case TW_NaN:
202 if ( !(st0_ptr->sigh & 0x40000000) )
203 {
204 EXCEPTION(EX_Invalid);
205 if ( control_word & CW_Invalid )
206 {
207
208
209 st0_ptr->sigh |= 0x40000000;
210 st_new_ptr = &st(-1);
211 push();
212 reg_move(&st(1), st_new_ptr);
213 }
214 }
215 else
216 {
217
218 st_new_ptr = &st(-1);
219 push();
220 reg_move(&st(1), st_new_ptr);
221 }
222 break;
223 #ifdef PARANOID
224 default:
225 EXCEPTION(EX_INTERNAL|0x0112);
226 #endif PARANOID
227 }
228 }
229
230
231
232
233 static void f2xm1(FPU_REG *st0_ptr)
234 {
235 clear_C1();
236 switch ( st0_ptr->tag )
237 {
238 case TW_Valid:
239 {
240 if ( st0_ptr->exp >= 0 )
241 {
242
243 }
244 #ifdef DENORM_OPERAND
245 else if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
246 return;
247 #endif DENORM_OPERAND
248 else
249 {
250
251 poly_2xm1(st0_ptr, st0_ptr);
252 }
253 if ( st0_ptr->exp <= EXP_UNDER )
254 {
255
256
257
258 arith_underflow(st0_ptr);
259 }
260 set_precision_flag_up();
261 return;
262 }
263 case TW_Zero:
264 return;
265 case TW_Infinity:
266 if ( st0_ptr->sign == SIGN_NEG )
267 {
268
269 reg_move(&CONST_1, st0_ptr);
270 st0_ptr->sign = SIGN_NEG;
271 }
272 return;
273 default:
274 single_arg_error(st0_ptr);
275 }
276 }
277
278
279 static void fptan(FPU_REG *st0_ptr)
280 {
281 char st0_tag = st0_ptr->tag;
282 FPU_REG *st_new_ptr;
283 int q;
284 char arg_sign = st0_ptr->sign;
285
286
287 if ( st0_tag == TW_Empty )
288 {
289 stack_underflow();
290 if ( control_word & CW_Invalid )
291 {
292 st_new_ptr = &st(-1);
293 push();
294 stack_underflow();
295 }
296 return;
297 }
298
299 if ( STACK_OVERFLOW )
300 { stack_overflow(); return; }
301
302 switch ( st0_tag )
303 {
304 case TW_Valid:
305 if ( st0_ptr->exp > EXP_BIAS - 40 )
306 {
307 st0_ptr->sign = SIGN_POS;
308 if ( (q = trig_arg(st0_ptr, 0)) != -1 )
309 {
310 poly_tan(st0_ptr, st0_ptr);
311 st0_ptr->sign = (q & 1) ^ arg_sign;
312 }
313 else
314 {
315
316 st0_ptr->sign = arg_sign;
317 return;
318 }
319 set_precision_flag_up();
320 }
321 else
322 {
323
324
325
326 if ( st0_ptr->exp <= EXP_UNDER )
327 {
328 #ifdef DENORM_OPERAND
329 if ( denormal_operand() )
330 return;
331 #endif DENORM_OPERAND
332
333
334
335 if ( arith_underflow(st0_ptr) )
336 return;
337 }
338 set_precision_flag_down();
339 }
340 push();
341 reg_move(&CONST_1, st_new_ptr);
342 return;
343 break;
344 case TW_Infinity:
345
346 arith_invalid(st0_ptr);
347 if ( control_word & CW_Invalid )
348 {
349 st_new_ptr = &st(-1);
350 push();
351 arith_invalid(st_new_ptr);
352 }
353 return;
354 case TW_Zero:
355 push();
356 reg_move(&CONST_1, st_new_ptr);
357 setcc(0);
358 break;
359 default:
360 single_arg_2_error(st0_ptr);
361 break;
362 }
363 }
364
365
366 static void fxtract(FPU_REG *st0_ptr)
367 {
368 char st0_tag = st0_ptr->tag;
369 FPU_REG *st_new_ptr;
370 register FPU_REG *st1_ptr = st0_ptr;
371
372 if ( STACK_OVERFLOW )
373 { stack_overflow(); return; }
374 clear_C1();
375 if ( !(st0_tag ^ TW_Valid) )
376 {
377 long e;
378
379 #ifdef DENORM_OPERAND
380 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
381 return;
382 #endif DENORM_OPERAND
383
384 push();
385 reg_move(st1_ptr, st_new_ptr);
386 st_new_ptr->exp = EXP_BIAS;
387 e = st1_ptr->exp - EXP_BIAS;
388 convert_l2reg(&e, st1_ptr);
389 return;
390 }
391 else if ( st0_tag == TW_Zero )
392 {
393 char sign = st0_ptr->sign;
394 if ( divide_by_zero(SIGN_NEG, st0_ptr) )
395 return;
396 push();
397 reg_move(&CONST_Z, st_new_ptr);
398 st_new_ptr->sign = sign;
399 return;
400 }
401 else if ( st0_tag == TW_Infinity )
402 {
403 char sign = st0_ptr->sign;
404 st0_ptr->sign = SIGN_POS;
405 push();
406 reg_move(&CONST_INF, st_new_ptr);
407 st_new_ptr->sign = sign;
408 return;
409 }
410 else if ( st0_tag == TW_NaN )
411 {
412 if ( real_2op_NaN(st0_ptr, st0_ptr, st0_ptr) )
413 return;
414 push();
415 reg_move(st1_ptr, st_new_ptr);
416 return;
417 }
418 else if ( st0_tag == TW_Empty )
419 {
420
421 if ( control_word & EX_Invalid )
422 {
423 stack_underflow();
424 push();
425 stack_underflow();
426 }
427 else
428 EXCEPTION(EX_StackUnder);
429 }
430 #ifdef PARANOID
431 else
432 EXCEPTION(EX_INTERNAL | 0x119);
433 #endif PARANOID
434 }
435
436
437 static void fdecstp(FPU_REG *st0_ptr)
438 {
439 clear_C1();
440 top--;
441 }
442
443 static void fincstp(FPU_REG *st0_ptr)
444 {
445 clear_C1();
446 top++;
447 }
448
449
450 static void fsqrt_(FPU_REG *st0_ptr)
451 {
452 char st0_tag = st0_ptr->tag;
453
454 clear_C1();
455 if ( !(st0_tag ^ TW_Valid) )
456 {
457 int expon;
458
459 if (st0_ptr->sign == SIGN_NEG)
460 {
461 arith_invalid(st0_ptr);
462 return;
463 }
464
465 #ifdef DENORM_OPERAND
466 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
467 return;
468 #endif DENORM_OPERAND
469
470 expon = st0_ptr->exp - EXP_BIAS;
471 st0_ptr->exp = EXP_BIAS + (expon & 1);
472
473 wm_sqrt(st0_ptr, control_word);
474
475 st0_ptr->exp += expon >> 1;
476 st0_ptr->sign = SIGN_POS;
477 }
478 else if ( st0_tag == TW_Zero )
479 return;
480 else if ( st0_tag == TW_Infinity )
481 {
482 if ( st0_ptr->sign == SIGN_NEG )
483 arith_invalid(st0_ptr);
484 return;
485 }
486 else
487 { single_arg_error(st0_ptr); return; }
488
489 }
490
491
492 static void frndint_(FPU_REG *st0_ptr)
493 {
494 char st0_tag = st0_ptr->tag;
495 int flags;
496
497 if ( !(st0_tag ^ TW_Valid) )
498 {
499 if (st0_ptr->exp > EXP_BIAS+63)
500 return;
501
502 #ifdef DENORM_OPERAND
503 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
504 return;
505 #endif DENORM_OPERAND
506
507
508 if ( (flags = round_to_int(st0_ptr)) )
509 set_precision_flag(flags);
510
511 st0_ptr->exp = EXP_BIAS + 63;
512 normalize(st0_ptr);
513 return;
514 }
515 else if ( (st0_tag == TW_Zero) || (st0_tag == TW_Infinity) )
516 return;
517 else
518 single_arg_error(st0_ptr);
519 }
520
521
522 static void fsin(FPU_REG *st0_ptr)
523 {
524 char st0_tag = st0_ptr->tag;
525 char arg_sign = st0_ptr->sign;
526
527 if ( st0_tag == TW_Valid )
528 {
529 FPU_REG rv;
530 int q;
531
532 if ( st0_ptr->exp > EXP_BIAS - 40 )
533 {
534 st0_ptr->sign = SIGN_POS;
535 if ( (q = trig_arg(st0_ptr, 0)) != -1 )
536 {
537
538 poly_sine(st0_ptr, &rv);
539
540 if (q & 2)
541 rv.sign ^= SIGN_POS ^ SIGN_NEG;
542 rv.sign ^= arg_sign;
543 reg_move(&rv, st0_ptr);
544
545
546 set_precision_flag_up();
547 return;
548 }
549 else
550 {
551
552 st0_ptr->sign = arg_sign;
553 return;
554 }
555 }
556 else
557 {
558
559
560
561 if ( st0_ptr->exp <= EXP_UNDER )
562 {
563 #ifdef DENORM_OPERAND
564 if ( denormal_operand() )
565 return;
566 #endif DENORM_OPERAND
567
568
569
570 arith_underflow(st0_ptr);
571 return;
572 }
573
574 set_precision_flag_up();
575 }
576 }
577 else if ( st0_tag == TW_Zero )
578 {
579 setcc(0);
580 return;
581 }
582 else if ( st0_tag == TW_Infinity )
583 {
584
585 arith_invalid(st0_ptr);
586 return;
587 }
588 else
589 single_arg_error(st0_ptr);
590 }
591
592
593 static int f_cos(FPU_REG *arg)
594 {
595 char arg_sign = arg->sign;
596
597 if ( arg->tag == TW_Valid )
598 {
599 FPU_REG rv;
600 int q;
601
602 if ( arg->exp > EXP_BIAS - 40 )
603 {
604 arg->sign = SIGN_POS;
605 if ( (arg->exp < EXP_BIAS)
606 || ((arg->exp == EXP_BIAS)
607 && (significand(arg) <= 0xc90fdaa22168c234LL)) )
608 {
609 poly_cos(arg, &rv);
610 reg_move(&rv, arg);
611
612
613 set_precision_flag_down();
614
615 return 0;
616 }
617 else if ( (q = trig_arg(arg, FCOS)) != -1 )
618 {
619 poly_sine(arg, &rv);
620
621 if ((q+1) & 2)
622 rv.sign ^= SIGN_POS ^ SIGN_NEG;
623 reg_move(&rv, arg);
624
625
626 set_precision_flag_down();
627
628 return 0;
629 }
630 else
631 {
632
633 arg->sign = arg_sign;
634 return 1;
635 }
636 }
637 else
638 {
639 #ifdef DENORM_OPERAND
640 if ( (arg->exp <= EXP_UNDER) && (denormal_operand()) )
641 return 1;
642 #endif DENORM_OPERAND
643
644 setcc(0);
645 reg_move(&CONST_1, arg);
646 #ifdef PECULIAR_486
647 set_precision_flag_down();
648 #else
649 set_precision_flag_up();
650 #endif PECULIAR_486
651 return 0;
652 }
653 }
654 else if ( arg->tag == TW_Zero )
655 {
656 reg_move(&CONST_1, arg);
657 setcc(0);
658 return 0;
659 }
660 else if ( arg->tag == TW_Infinity )
661 {
662
663 arith_invalid(arg);
664 return 1;
665 }
666 else
667 {
668 single_arg_error(arg);
669 return 1;
670 }
671 }
672
673
674 static void fcos(FPU_REG *st0_ptr)
675 {
676 f_cos(st0_ptr);
677 }
678
679
680 static void fsincos(FPU_REG *st0_ptr)
681 {
682 char st0_tag = st0_ptr->tag;
683 FPU_REG *st_new_ptr;
684 FPU_REG arg;
685
686
687 if ( st0_tag == TW_Empty )
688 {
689 stack_underflow();
690 if ( control_word & CW_Invalid )
691 {
692 st_new_ptr = &st(-1);
693 push();
694 stack_underflow();
695 }
696 return;
697 }
698
699 if ( STACK_OVERFLOW )
700 { stack_overflow(); return; }
701
702 if ( st0_tag == TW_NaN )
703 {
704 single_arg_2_error(st0_ptr);
705 return;
706 }
707 else if ( st0_tag == TW_Infinity )
708 {
709
710 if ( !arith_invalid(st0_ptr) )
711 {
712
713 push();
714 arith_invalid(st_new_ptr);
715 }
716 return;
717 }
718
719 reg_move(st0_ptr,&arg);
720 if ( !f_cos(&arg) )
721 {
722 fsin(st0_ptr);
723 push();
724 reg_move(&arg,st_new_ptr);
725 }
726
727 }
728
729
730
731
732
733
734
735
736
737
738
739 static void rem_kernel(unsigned long long st0, unsigned long long *y,
740 unsigned long long st1,
741 unsigned long long q, int n)
742 {
743 unsigned long long x;
744
745 x = st0 << n;
746
747
748 asm volatile ("movl %2,%%eax; mull %4; subl %%eax,%0; sbbl %%edx,%1;
749 movl %3,%%eax; mull %4; subl %%eax,%1;
750 movl %2,%%eax; mull %5; subl %%eax,%1;"
751 :"=m" (x), "=m" (((unsigned *)&x)[1])
752 :"m" (st1),"m" (((unsigned *)&st1)[1]),
753 "m" (q),"m" (((unsigned *)&q)[1])
754 :"%ax","%dx");
755
756 *y = x;
757 }
758
759
760
761
762
763 static void do_fprem(FPU_REG *st0_ptr, int round)
764 {
765 FPU_REG *st1_ptr = &st(1);
766 char st1_tag = st1_ptr->tag;
767 char st0_tag = st0_ptr->tag;
768 char sign = st0_ptr->sign;
769
770 if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
771 {
772 FPU_REG tmp;
773 int old_cw = control_word;
774 int expdif = st0_ptr->exp - st1_ptr->exp;
775 long long q;
776 unsigned short saved_status;
777 int cc = 0;
778
779 #ifdef DENORM_OPERAND
780 if ( ((st0_ptr->exp <= EXP_UNDER) ||
781 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
782 return;
783 #endif DENORM_OPERAND
784
785
786
787 saved_status = partial_status;
788 control_word &= ~CW_RC;
789 control_word |= RC_CHOP;
790
791 if (expdif < 64)
792 {
793
794
795 if ( expdif > -2 )
796 {
797 reg_div(st0_ptr, st1_ptr, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
798
799 if ( tmp.exp >= EXP_BIAS )
800 {
801 round_to_int(&tmp);
802
803 q = significand(&tmp);
804
805 rem_kernel(significand(st0_ptr),
806 &significand(&tmp),
807 significand(st1_ptr),
808 q, expdif);
809
810 tmp.exp = st1_ptr->exp;
811 }
812 else
813 {
814 reg_move(st0_ptr, &tmp);
815 q = 0;
816 }
817 tmp.sign = sign;
818
819 if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
820 {
821
822
823 unsigned long long x;
824 expdif = st1_ptr->exp - tmp.exp;
825 if ( expdif <= 1 )
826 {
827 if ( expdif == 0 )
828 x = significand(st1_ptr) - significand(&tmp);
829 else
830 x = (significand(st1_ptr) << 1) - significand(&tmp);
831 if ( (x < significand(&tmp)) ||
832
833 ((x == significand(&tmp)) && (q & 1) ) )
834 {
835 tmp.sign ^= (SIGN_POS^SIGN_NEG);
836 significand(&tmp) = x;
837 q++;
838 }
839 }
840 }
841
842 if (q & 4) cc |= SW_C0;
843 if (q & 2) cc |= SW_C3;
844 if (q & 1) cc |= SW_C1;
845 }
846 else
847 {
848 control_word = old_cw;
849 setcc(0);
850 return;
851 }
852 }
853 else
854 {
855
856
857
858 int exp_1;
859
860
861
862 reg_move(st0_ptr, &tmp);
863 tmp.exp = EXP_BIAS + 56;
864 exp_1 = st1_ptr->exp; st1_ptr->exp = EXP_BIAS;
865 expdif -= 56;
866
867 reg_div(&tmp, st1_ptr, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
868 st1_ptr->exp = exp_1;
869
870 round_to_int(&tmp);
871
872 rem_kernel(significand(st0_ptr),
873 &significand(&tmp),
874 significand(st1_ptr),
875 significand(&tmp),
876 tmp.exp - EXP_BIAS
877 );
878 tmp.exp = exp_1 + expdif;
879 tmp.sign = sign;
880
881
882
883
884
885
886 if ( !(tmp.sigh | tmp.sigl) )
887 {
888
889 control_word = old_cw;
890 partial_status = saved_status;
891 reg_move(&CONST_Z, st0_ptr);
892 st0_ptr->sign = sign;
893 #ifdef PECULIAR_486
894 setcc(SW_C2);
895 #else
896 setcc(0);
897 #endif PECULIAR_486
898 return;
899 }
900 cc = SW_C2;
901 }
902
903 control_word = old_cw;
904 partial_status = saved_status;
905 normalize_nuo(&tmp);
906 reg_move(&tmp, st0_ptr);
907 setcc(cc);
908
909
910
911 if ( (st0_ptr->exp <= EXP_UNDER) && (st0_ptr->tag != TW_Zero)
912 && !(control_word & CW_Underflow) )
913 arith_underflow(st0_ptr);
914
915 return;
916 }
917 else if ( (st0_tag == TW_Empty) | (st1_tag == TW_Empty) )
918 {
919 stack_underflow();
920 return;
921 }
922 else if ( st0_tag == TW_Zero )
923 {
924 if ( st1_tag == TW_Valid )
925 {
926 #ifdef DENORM_OPERAND
927 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
928 return;
929 #endif DENORM_OPERAND
930
931 setcc(0); return;
932 }
933 else if ( st1_tag == TW_Zero )
934 { arith_invalid(st0_ptr); return; }
935 else if ( st1_tag == TW_Infinity )
936 { setcc(0); return; }
937 }
938 else if ( st0_tag == TW_Valid )
939 {
940 if ( st1_tag == TW_Zero )
941 {
942 arith_invalid(st0_ptr);
943 return;
944 }
945 else if ( st1_tag != TW_NaN )
946 {
947 #ifdef DENORM_OPERAND
948 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
949 return;
950 #endif DENORM_OPERAND
951
952 if ( st1_tag == TW_Infinity )
953 {
954
955 setcc(0); return;
956 }
957 }
958 }
959 else if ( st0_tag == TW_Infinity )
960 {
961 if ( st1_tag != TW_NaN )
962 {
963 arith_invalid(st0_ptr);
964 return;
965 }
966 }
967
968
969
970 #ifdef PARANOID
971 if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
972 EXCEPTION(EX_INTERNAL | 0x118);
973 #endif PARANOID
974
975 real_2op_NaN(st1_ptr, st0_ptr, st0_ptr);
976
977 }
978
979
980
981 static void fyl2x(FPU_REG *st0_ptr)
982 {
983 char st0_tag = st0_ptr->tag;
984 FPU_REG *st1_ptr = &st(1), exponent;
985 char st1_tag = st1_ptr->tag;
986 int e;
987
988 clear_C1();
989 if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
990 {
991 if ( st0_ptr->sign == SIGN_POS )
992 {
993 #ifdef DENORM_OPERAND
994 if ( ((st0_ptr->exp <= EXP_UNDER) ||
995 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
996 return;
997 #endif DENORM_OPERAND
998
999 if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
1000 {
1001
1002 e = st0_ptr->exp - EXP_BIAS;
1003 if ( e > 0 )
1004 {
1005 exponent.sigh = e;
1006 exponent.sign = SIGN_POS;
1007 }
1008 else
1009 {
1010 exponent.sigh = -e;
1011 exponent.sign = SIGN_NEG;
1012 }
1013 exponent.sigl = 0;
1014 exponent.exp = EXP_BIAS + 31;
1015 exponent.tag = TW_Valid;
1016 normalize_nuo(&exponent);
1017 reg_mul(&exponent, st1_ptr, st1_ptr, FULL_PRECISION);
1018 }
1019 else
1020 {
1021
1022 poly_l2(st0_ptr, st1_ptr, st1_ptr);
1023 if ( st1_ptr->exp <= EXP_UNDER )
1024 {
1025
1026
1027
1028 arith_underflow(st1_ptr);
1029 }
1030 else
1031 set_precision_flag_up();
1032 }
1033 pop();
1034 return;
1035 }
1036 else
1037 {
1038
1039 if ( !arith_invalid(st1_ptr) )
1040 pop();
1041 return;
1042 }
1043 }
1044 else if ( (st0_tag == TW_Empty) || (st1_tag == TW_Empty) )
1045 {
1046 stack_underflow_pop(1);
1047 return;
1048 }
1049 else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
1050 {
1051 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1052 pop();
1053 return;
1054 }
1055 else if ( (st0_tag <= TW_Zero) && (st1_tag <= TW_Zero) )
1056 {
1057
1058 if ( st0_tag == TW_Zero )
1059 {
1060 if ( st1_tag == TW_Zero )
1061 {
1062
1063 if ( !arith_invalid(st1_ptr) )
1064 pop();
1065 }
1066 #ifdef PECULIAR_486
1067
1068
1069
1070 else if ( st0_ptr->tag == TW_Infinity )
1071 {
1072 reg_move(&CONST_INF, st1_ptr);
1073 pop();
1074 }
1075 #endif PECULIAR_486
1076 else
1077 {
1078 if ( !divide_by_zero(st1_ptr->sign^SIGN_NEG^SIGN_POS, st1_ptr) )
1079 pop();
1080 }
1081 return;
1082 }
1083 else
1084 {
1085
1086
1087 char sign = st1_ptr->sign;
1088
1089 if ( st0_ptr->sign == SIGN_NEG )
1090 {
1091
1092 if ( !arith_invalid(st1_ptr) )
1093 pop();
1094 return;
1095 }
1096
1097 #ifdef DENORM_OPERAND
1098 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1099 return;
1100 #endif DENORM_OPERAND
1101
1102 if ( st0_ptr->exp < EXP_BIAS ) sign ^= SIGN_NEG^SIGN_POS;
1103 pop(); st0_ptr = &st(0);
1104 reg_move(&CONST_Z, st0_ptr);
1105 st0_ptr->sign = sign;
1106 return;
1107 }
1108 }
1109
1110 else if ( st0_tag == TW_Infinity )
1111 {
1112 if ( (st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero) )
1113 {
1114
1115 if ( !arith_invalid(st1_ptr) )
1116 pop();
1117 return;
1118 }
1119 else
1120 {
1121 char sign = st1_ptr->sign;
1122
1123 #ifdef DENORM_OPERAND
1124 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1125 return;
1126 #endif DENORM_OPERAND
1127
1128 pop(); st0_ptr = &st(0);
1129 reg_move(&CONST_INF, st0_ptr);
1130 st0_ptr->sign = sign;
1131 return;
1132 }
1133 }
1134
1135 else if ( (st0_tag == TW_Valid) && (st0_ptr->sign == SIGN_POS) )
1136 {
1137 if ( st0_ptr->exp >= EXP_BIAS )
1138 {
1139 if ( (st0_ptr->exp == EXP_BIAS) &&
1140 (st0_ptr->sigh == 0x80000000) &&
1141 (st0_ptr->sigl == 0) )
1142 {
1143
1144
1145 if ( !arith_invalid(st1_ptr) )
1146 pop();
1147 return;
1148 }
1149
1150 pop();
1151 }
1152 else
1153 {
1154
1155
1156 #ifdef DENORM_OPERAND
1157 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1158 return;
1159 #endif DENORM_OPERAND
1160
1161 st1_ptr->sign ^= SIGN_NEG;
1162 pop();
1163 }
1164 return;
1165 }
1166 else
1167 {
1168
1169 if ( st0_ptr->tag == TW_Zero )
1170 {
1171
1172 #ifndef PECULIAR_486
1173 if ( !divide_by_zero(st1_ptr->sign, st1_ptr) )
1174 #endif PECULIAR_486
1175 {
1176 st1_ptr->sign ^= SIGN_NEG^SIGN_POS;
1177 pop();
1178 }
1179 }
1180 else
1181 {
1182
1183 if ( !arith_invalid(st1_ptr) )
1184 pop();
1185 }
1186 return;
1187 }
1188 }
1189
1190
1191 static void fpatan(FPU_REG *st0_ptr)
1192 {
1193 char st0_tag = st0_ptr->tag;
1194 FPU_REG *st1_ptr = &st(1);
1195 char st1_tag = st1_ptr->tag;
1196
1197 clear_C1();
1198 if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
1199 {
1200 #ifdef DENORM_OPERAND
1201 if ( ((st0_ptr->exp <= EXP_UNDER) ||
1202 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
1203 return;
1204 #endif DENORM_OPERAND
1205
1206 poly_atan(st0_ptr, st1_ptr, st1_ptr);
1207
1208 if ( st1_ptr->exp <= EXP_UNDER )
1209 {
1210
1211
1212
1213 arith_underflow(st1_ptr);
1214 pop();
1215 return;
1216 }
1217 }
1218 else if ( (st0_tag == TW_Empty) || (st1_tag == TW_Empty) )
1219 {
1220 stack_underflow_pop(1);
1221 return;
1222 }
1223 else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
1224 {
1225 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1226 pop();
1227 return;
1228 }
1229 else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )
1230 {
1231 char sign = st1_ptr->sign;
1232 if ( st0_tag == TW_Infinity )
1233 {
1234 if ( st1_tag == TW_Infinity )
1235 {
1236 if ( st0_ptr->sign == SIGN_POS )
1237 { reg_move(&CONST_PI4, st1_ptr); }
1238 else
1239 reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION);
1240 }
1241 else
1242 {
1243 #ifdef DENORM_OPERAND
1244 if ( st1_tag != TW_Zero )
1245 {
1246 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1247 return;
1248 }
1249 #endif DENORM_OPERAND
1250
1251 if ( st0_ptr->sign == SIGN_POS )
1252 {
1253 reg_move(&CONST_Z, st1_ptr);
1254 st1_ptr->sign = sign;
1255 pop();
1256 return;
1257 }
1258 else
1259 reg_move(&CONST_PI, st1_ptr);
1260 }
1261 }
1262 else
1263 {
1264
1265 #ifdef DENORM_OPERAND
1266 if ( st0_tag != TW_Zero )
1267 {
1268 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1269 return;
1270 }
1271 #endif DENORM_OPERAND
1272
1273 reg_move(&CONST_PI2, st1_ptr);
1274 }
1275 st1_ptr->sign = sign;
1276 }
1277 else if ( st1_tag == TW_Zero )
1278 {
1279
1280 char sign = st1_ptr->sign;
1281
1282 #ifdef DENORM_OPERAND
1283 if ( st0_tag != TW_Zero )
1284 {
1285 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1286 return;
1287 }
1288 #endif DENORM_OPERAND
1289
1290 if ( st0_ptr->sign == SIGN_POS )
1291 { pop(); return; }
1292 else
1293 reg_move(&CONST_PI, st1_ptr);
1294 st1_ptr->sign = sign;
1295 }
1296 else if ( st0_tag == TW_Zero )
1297 {
1298
1299 char sign = st1_ptr->sign;
1300
1301 #ifdef DENORM_OPERAND
1302 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1303 return;
1304 #endif DENORM_OPERAND
1305
1306 reg_move(&CONST_PI2, st1_ptr);
1307 st1_ptr->sign = sign;
1308 }
1309 #ifdef PARANOID
1310 else
1311 EXCEPTION(EX_INTERNAL | 0x125);
1312 #endif PARANOID
1313
1314 pop();
1315 set_precision_flag_up();
1316 }
1317
1318
1319 static void fprem(FPU_REG *st0_ptr)
1320 {
1321 do_fprem(st0_ptr, RC_CHOP);
1322 }
1323
1324
1325 static void fprem1(FPU_REG *st0_ptr)
1326 {
1327 do_fprem(st0_ptr, RC_RND);
1328 }
1329
1330
1331 static void fyl2xp1(FPU_REG *st0_ptr)
1332 {
1333 char st0_tag = st0_ptr->tag, sign;
1334 FPU_REG *st1_ptr = &st(1);
1335 char st1_tag = st1_ptr->tag;
1336
1337 clear_C1();
1338 if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
1339 {
1340 #ifdef DENORM_OPERAND
1341 if ( ((st0_ptr->exp <= EXP_UNDER) ||
1342 (st1_ptr->exp <= EXP_UNDER)) && denormal_operand() )
1343 return;
1344 #endif DENORM_OPERAND
1345
1346 if ( poly_l2p1(st0_ptr, st1_ptr, st1_ptr) )
1347 {
1348 #ifdef PECULIAR_486
1349 st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
1350 #else
1351 if ( arith_invalid(st1_ptr) )
1352 return;
1353 #endif PECULIAR_486
1354 }
1355 if ( st1_ptr->exp <= EXP_UNDER )
1356 {
1357
1358
1359
1360 sign = st1_ptr->sign;
1361 arith_underflow(st1_ptr);
1362 st1_ptr->sign = sign;
1363 }
1364 else
1365 set_precision_flag_up();
1366 pop();
1367 return;
1368 }
1369 else if ( (st0_tag == TW_Empty) | (st1_tag == TW_Empty) )
1370 {
1371 stack_underflow_pop(1);
1372 return;
1373 }
1374 else if ( st0_tag == TW_Zero )
1375 {
1376 if ( st1_tag <= TW_Zero )
1377 {
1378 #ifdef DENORM_OPERAND
1379 if ( (st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) &&
1380 (denormal_operand()) )
1381 return;
1382 #endif DENORM_OPERAND
1383
1384 st0_ptr->sign ^= st1_ptr->sign;
1385 reg_move(st0_ptr, st1_ptr);
1386 }
1387 else if ( st1_tag == TW_Infinity )
1388 {
1389
1390 if ( !arith_invalid(st1_ptr) )
1391 pop();
1392 return;
1393 }
1394 else if ( st1_tag == TW_NaN )
1395 {
1396 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1397 pop();
1398 return;
1399 }
1400 #ifdef PARANOID
1401 else
1402 {
1403 EXCEPTION(EX_INTERNAL | 0x116);
1404 return;
1405 }
1406 #endif PARANOID
1407 pop(); return;
1408 }
1409 else if ( st0_tag == TW_Valid )
1410 {
1411 if ( st1_tag == TW_Zero )
1412 {
1413 if ( st0_ptr->sign == SIGN_NEG )
1414 {
1415 if ( st0_ptr->exp >= EXP_BIAS )
1416 {
1417
1418 #ifdef PECULIAR_486
1419 st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
1420 #else
1421 if ( arith_invalid(st1_ptr) ) return;
1422 #endif PECULIAR_486
1423 pop(); return;
1424 }
1425 #ifdef DENORM_OPERAND
1426 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1427 return;
1428 #endif DENORM_OPERAND
1429 st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
1430 pop(); return;
1431 }
1432 #ifdef DENORM_OPERAND
1433 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1434 return;
1435 #endif DENORM_OPERAND
1436 pop(); return;
1437 }
1438 if ( st1_tag == TW_Infinity )
1439 {
1440 if ( st0_ptr->sign == SIGN_NEG )
1441 {
1442 if ( (st0_ptr->exp >= EXP_BIAS) &&
1443 !((st0_ptr->sigh == 0x80000000) &&
1444 (st0_ptr->sigl == 0)) )
1445 {
1446
1447 #ifdef PECULIAR_486
1448 st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
1449 #else
1450 if ( arith_invalid(st1_ptr) ) return;
1451 #endif PECULIAR_486
1452 pop(); return;
1453 }
1454 #ifdef DENORM_OPERAND
1455 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1456 return;
1457 #endif DENORM_OPERAND
1458 st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
1459 pop(); return;
1460 }
1461 #ifdef DENORM_OPERAND
1462 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1463 return;
1464 #endif DENORM_OPERAND
1465 pop(); return;
1466 }
1467 if ( st1_tag == TW_NaN )
1468 {
1469 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1470 pop();
1471 return;
1472 }
1473 }
1474 else if ( st0_tag == TW_NaN )
1475 {
1476 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1477 pop();
1478 return;
1479 }
1480 else if ( st0_tag == TW_Infinity )
1481 {
1482 if ( st1_tag == TW_NaN )
1483 {
1484 if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
1485 pop();
1486 return;
1487 }
1488 else if ( st0_ptr->sign == SIGN_NEG )
1489 {
1490 int exponent = st1_ptr->exp;
1491 #ifndef PECULIAR_486
1492
1493 if ( arith_invalid(st1_ptr) )
1494 return;
1495 #endif PECULIAR_486
1496 #ifdef DENORM_OPERAND
1497 if ( st1_tag != TW_Zero )
1498 {
1499 if ( (exponent <= EXP_UNDER) && (denormal_operand()) )
1500 return;
1501 }
1502 #endif DENORM_OPERAND
1503 #ifdef PECULIAR_486
1504
1505 if ( arith_invalid(st1_ptr) )
1506 return;
1507 #endif PECULIAR_486
1508 pop();
1509 return;
1510 }
1511 else if ( st1_tag == TW_Zero )
1512 {
1513
1514 if ( !arith_invalid(st1_ptr) )
1515 pop();
1516 return;
1517 }
1518
1519
1520
1521 #ifdef DENORM_OPERAND
1522 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1523 return;
1524 #endif DENORM_OPERAND
1525
1526
1527
1528 { char sign = st1_ptr->sign;
1529 reg_move(&CONST_INF, st1_ptr);
1530 st1_ptr->sign = sign;
1531 }
1532 pop();
1533 return;
1534 }
1535 #ifdef PARANOID
1536 else
1537 {
1538 EXCEPTION(EX_INTERNAL | 0x117);
1539 }
1540 #endif PARANOID
1541 }
1542
1543
1544 static void fscale(FPU_REG *st0_ptr)
1545 {
1546 char st0_tag = st0_ptr->tag;
1547 FPU_REG *st1_ptr = &st(1);
1548 char st1_tag = st1_ptr->tag;
1549 int old_cw = control_word;
1550 char sign = st0_ptr->sign;
1551
1552 clear_C1();
1553 if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
1554 {
1555 long scale;
1556 FPU_REG tmp;
1557
1558 #ifdef DENORM_OPERAND
1559 if ( ((st0_ptr->exp <= EXP_UNDER) ||
1560 (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
1561 return;
1562 #endif DENORM_OPERAND
1563
1564 if ( st1_ptr->exp > EXP_BIAS + 30 )
1565 {
1566
1567 char sign;
1568
1569 if ( st1_ptr->sign == SIGN_POS )
1570 {
1571 EXCEPTION(EX_Overflow);
1572 sign = st0_ptr->sign;
1573 reg_move(&CONST_INF, st0_ptr);
1574 st0_ptr->sign = sign;
1575 }
1576 else
1577 {
1578 EXCEPTION(EX_Underflow);
1579 sign = st0_ptr->sign;
1580 reg_move(&CONST_Z, st0_ptr);
1581 st0_ptr->sign = sign;
1582 }
1583 return;
1584 }
1585
1586 control_word &= ~CW_RC;
1587 control_word |= RC_CHOP;
1588 reg_move(st1_ptr, &tmp);
1589 round_to_int(&tmp);
1590 control_word = old_cw;
1591 scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl;
1592 scale += st0_ptr->exp;
1593 st0_ptr->exp = scale;
1594
1595
1596 round_reg(st0_ptr, 0, control_word);
1597
1598 return;
1599 }
1600 else if ( st0_tag == TW_Valid )
1601 {
1602 if ( st1_tag == TW_Zero )
1603 {
1604
1605 #ifdef DENORM_OPERAND
1606 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1607 return;
1608 #endif DENORM_OPERAND
1609
1610 return;
1611 }
1612 if ( st1_tag == TW_Infinity )
1613 {
1614 #ifdef DENORM_OPERAND
1615 if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1616 return;
1617 #endif DENORM_OPERAND
1618
1619 if ( st1_ptr->sign == SIGN_POS )
1620 { reg_move(&CONST_INF, st0_ptr); }
1621 else
1622 reg_move(&CONST_Z, st0_ptr);
1623 st0_ptr->sign = sign;
1624 return;
1625 }
1626 if ( st1_tag == TW_NaN )
1627 { real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
1628 }
1629 else if ( st0_tag == TW_Zero )
1630 {
1631 if ( st1_tag == TW_Valid )
1632 {
1633
1634 #ifdef DENORM_OPERAND
1635 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1636 return;
1637 #endif DENORM_OPERAND
1638
1639 return;
1640 }
1641 else if ( st1_tag == TW_Zero ) { return; }
1642 else if ( st1_tag == TW_Infinity )
1643 {
1644 if ( st1_ptr->sign == SIGN_NEG )
1645 return;
1646 else
1647 {
1648 arith_invalid(st0_ptr);
1649 return;
1650 }
1651 }
1652 else if ( st1_tag == TW_NaN )
1653 { real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
1654 }
1655 else if ( st0_tag == TW_Infinity )
1656 {
1657 if ( st1_tag == TW_Valid )
1658 {
1659
1660 #ifdef DENORM_OPERAND
1661 if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
1662 return;
1663 #endif DENORM_OPERAND
1664
1665 return;
1666 }
1667 if ( ((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS))
1668 || (st1_tag == TW_Zero) )
1669 return;
1670 else if ( st1_tag == TW_Infinity )
1671 {
1672 arith_invalid(st0_ptr);
1673 return;
1674 }
1675 else if ( st1_tag == TW_NaN )
1676 { real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
1677 }
1678 else if ( st0_tag == TW_NaN )
1679 {
1680 if ( st1_tag != TW_Empty )
1681 { real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
1682 }
1683
1684 #ifdef PARANOID
1685 if ( !((st0_tag == TW_Empty) || (st1_tag == TW_Empty)) )
1686 {
1687 EXCEPTION(EX_INTERNAL | 0x115);
1688 return;
1689 }
1690 #endif
1691
1692
1693 stack_underflow();
1694
1695 }
1696
1697
1698
1699
1700 static FUNC_ST0 const trig_table_a[] = {
1701 f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp
1702 };
1703
1704 void trig_a(void)
1705 {
1706 (trig_table_a[FPU_rm])(&st(0));
1707 }
1708
1709
1710 static FUNC_ST0 const trig_table_b[] =
1711 {
1712 fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, fsin, fcos
1713 };
1714
1715 void trig_b(void)
1716 {
1717 (trig_table_b[FPU_rm])(&st(0));
1718 }