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