Linux-2.6.12-rc2
[pandora-kernel.git] / arch / i386 / math-emu / fpu_trig.c
1 /*---------------------------------------------------------------------------+
2  |  fpu_trig.c                                                               |
3  |                                                                           |
4  | Implementation of the FPU "transcendental" functions.                     |
5  |                                                                           |
6  | Copyright (C) 1992,1993,1994,1997,1999                                    |
7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
8  |                       Australia.  E-mail   billm@melbpc.org.au            |
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 static void rem_kernel(unsigned long long st0, unsigned long long *y,
21                        unsigned long long st1,
22                        unsigned long long q, int n);
23
24 #define BETTER_THAN_486
25
26 #define FCOS  4
27
28 /* Used only by fptan, fsin, fcos, and fsincos. */
29 /* This routine produces very accurate results, similar to
30    using a value of pi with more than 128 bits precision. */
31 /* Limited measurements show no results worse than 64 bit precision
32    except for the results for arguments close to 2^63, where the
33    precision of the result sometimes degrades to about 63.9 bits */
34 static int trig_arg(FPU_REG *st0_ptr, int even)
35 {
36   FPU_REG tmp;
37   u_char tmptag;
38   unsigned long long q;
39   int old_cw = control_word, saved_status = partial_status;
40   int tag, st0_tag = TAG_Valid;
41
42   if ( exponent(st0_ptr) >= 63 )
43     {
44       partial_status |= SW_C2;     /* Reduction incomplete. */
45       return -1;
46     }
47
48   control_word &= ~CW_RC;
49   control_word |= RC_CHOP;
50
51   setpositive(st0_ptr);
52   tag = FPU_u_div(st0_ptr, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
53                   SIGN_POS);
54
55   FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't overflow
56                                    to 2^64 */
57   q = significand(&tmp);
58   if ( q )
59     {
60       rem_kernel(significand(st0_ptr),
61                  &significand(&tmp),
62                  significand(&CONST_PI2),
63                  q, exponent(st0_ptr) - exponent(&CONST_PI2));
64       setexponent16(&tmp, exponent(&CONST_PI2));
65       st0_tag = FPU_normalize(&tmp);
66       FPU_copy_to_reg0(&tmp, st0_tag);
67     }
68
69   if ( (even && !(q & 1)) || (!even && (q & 1)) )
70     {
71       st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2, FULL_PRECISION);
72
73 #ifdef BETTER_THAN_486
74       /* So far, the results are exact but based upon a 64 bit
75          precision approximation to pi/2. The technique used
76          now is equivalent to using an approximation to pi/2 which
77          is accurate to about 128 bits. */
78       if ( (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) || (q > 1) )
79         {
80           /* This code gives the effect of having pi/2 to better than
81              128 bits precision. */
82
83           significand(&tmp) = q + 1;
84           setexponent16(&tmp, 63);
85           FPU_normalize(&tmp);
86           tmptag =
87             FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS,
88                       exponent(&CONST_PI2extra) + exponent(&tmp));
89           setsign(&tmp, getsign(&CONST_PI2extra));
90           st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
91           if ( signnegative(st0_ptr) )
92             {
93               /* CONST_PI2extra is negative, so the result of the addition
94                  can be negative. This means that the argument is actually
95                  in a different quadrant. The correction is always < pi/2,
96                  so it can't overflow into yet another quadrant. */
97               setpositive(st0_ptr);
98               q++;
99             }
100         }
101 #endif /* BETTER_THAN_486 */
102     }
103 #ifdef BETTER_THAN_486
104   else
105     {
106       /* So far, the results are exact but based upon a 64 bit
107          precision approximation to pi/2. The technique used
108          now is equivalent to using an approximation to pi/2 which
109          is accurate to about 128 bits. */
110       if ( ((q > 0) && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
111            || (q > 1) )
112         {
113           /* This code gives the effect of having p/2 to better than
114              128 bits precision. */
115
116           significand(&tmp) = q;
117           setexponent16(&tmp, 63);
118           FPU_normalize(&tmp);         /* This must return TAG_Valid */
119           tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION,
120                              SIGN_POS,
121                              exponent(&CONST_PI2extra) + exponent(&tmp));
122           setsign(&tmp, getsign(&CONST_PI2extra));
123           st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), (int)&tmp,
124                             FULL_PRECISION);
125           if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) &&
126               ((st0_ptr->sigh > CONST_PI2.sigh)
127                || ((st0_ptr->sigh == CONST_PI2.sigh)
128                    && (st0_ptr->sigl > CONST_PI2.sigl))) )
129             {
130               /* CONST_PI2extra is negative, so the result of the
131                  subtraction can be larger than pi/2. This means
132                  that the argument is actually in a different quadrant.
133                  The correction is always < pi/2, so it can't overflow
134                  into yet another quadrant. */
135               st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2,
136                                 FULL_PRECISION);
137               q++;
138             }
139         }
140     }
141 #endif /* BETTER_THAN_486 */
142
143   FPU_settag0(st0_tag);
144   control_word = old_cw;
145   partial_status = saved_status & ~SW_C2;     /* Reduction complete. */
146
147   return (q & 3) | even;
148 }
149
150
151 /* Convert a long to register */
152 static void convert_l2reg(long const *arg, int deststnr)
153 {
154   int tag;
155   long num = *arg;
156   u_char sign;
157   FPU_REG *dest = &st(deststnr);
158
159   if (num == 0)
160     {
161       FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
162       return;
163     }
164
165   if (num > 0)
166     { sign = SIGN_POS; }
167   else
168     { num = -num; sign = SIGN_NEG; }
169
170   dest->sigh = num;
171   dest->sigl = 0;
172   setexponent16(dest, 31);
173   tag = FPU_normalize(dest);
174   FPU_settagi(deststnr, tag);
175   setsign(dest, sign);
176   return;
177 }
178
179
180 static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
181 {
182   if ( st0_tag == TAG_Empty )
183     FPU_stack_underflow();  /* Puts a QNaN in st(0) */
184   else if ( st0_tag == TW_NaN )
185     real_1op_NaN(st0_ptr);       /* return with a NaN in st(0) */
186 #ifdef PARANOID
187   else
188     EXCEPTION(EX_INTERNAL|0x0112);
189 #endif /* PARANOID */
190 }
191
192
193 static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
194 {
195   int isNaN;
196
197   switch ( st0_tag )
198     {
199     case TW_NaN:
200       isNaN = (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000);
201       if ( isNaN && !(st0_ptr->sigh & 0x40000000) )   /* Signaling ? */
202         {
203           EXCEPTION(EX_Invalid);
204           if ( control_word & CW_Invalid )
205             {
206               /* The masked response */
207               /* Convert to a QNaN */
208               st0_ptr->sigh |= 0x40000000;
209               push();
210               FPU_copy_to_reg0(st0_ptr, TAG_Special);
211             }
212         }
213       else if ( isNaN )
214         {
215           /* A QNaN */
216           push();
217           FPU_copy_to_reg0(st0_ptr, TAG_Special);
218         }
219       else
220         {
221           /* pseudoNaN or other unsupported */
222           EXCEPTION(EX_Invalid);
223           if ( control_word & CW_Invalid )
224             {
225               /* The masked response */
226               FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
227               push();
228               FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
229             }
230         }
231       break;              /* return with a NaN in st(0) */
232 #ifdef PARANOID
233     default:
234       EXCEPTION(EX_INTERNAL|0x0112);
235 #endif /* PARANOID */
236     }
237 }
238
239
240 /*---------------------------------------------------------------------------*/
241
242 static void f2xm1(FPU_REG *st0_ptr, u_char tag)
243 {
244   FPU_REG a;
245
246   clear_C1();
247
248   if ( tag == TAG_Valid )
249     {
250       /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */
251       if ( exponent(st0_ptr) < 0 )
252         {
253         denormal_arg:
254
255           FPU_to_exp16(st0_ptr, &a);
256
257           /* poly_2xm1(x) requires 0 < st(0) < 1. */
258           poly_2xm1(getsign(st0_ptr), &a, st0_ptr);
259         }
260       set_precision_flag_up();   /* 80486 appears to always do this */
261       return;
262     }
263
264   if ( tag == TAG_Zero )
265     return;
266
267   if ( tag == TAG_Special )
268     tag = FPU_Special(st0_ptr);
269
270   switch ( tag )
271     {
272     case TW_Denormal:
273       if ( denormal_operand() < 0 )
274         return;
275       goto denormal_arg;
276     case TW_Infinity:
277       if ( signnegative(st0_ptr) )
278         {
279           /* -infinity gives -1 (p16-10) */
280           FPU_copy_to_reg0(&CONST_1, TAG_Valid);
281           setnegative(st0_ptr);
282         }
283       return;
284     default:
285       single_arg_error(st0_ptr, tag);
286     }
287 }
288
289
290 static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
291 {
292   FPU_REG *st_new_ptr;
293   int q;
294   u_char arg_sign = getsign(st0_ptr);
295
296   /* Stack underflow has higher priority */
297   if ( st0_tag == TAG_Empty )
298     {
299       FPU_stack_underflow();  /* Puts a QNaN in st(0) */
300       if ( control_word & CW_Invalid )
301         {
302           st_new_ptr = &st(-1);
303           push();
304           FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
305         }
306       return;
307     }
308
309   if ( STACK_OVERFLOW )
310     { FPU_stack_overflow(); return; }
311
312   if ( st0_tag == TAG_Valid )
313     {
314       if ( exponent(st0_ptr) > -40 )
315         {
316           if ( (q = trig_arg(st0_ptr, 0)) == -1 )
317             {
318               /* Operand is out of range */
319               return;
320             }
321
322           poly_tan(st0_ptr);
323           setsign(st0_ptr, (q & 1) ^ (arg_sign != 0));
324           set_precision_flag_up();  /* We do not really know if up or down */
325         }
326       else
327         {
328           /* For a small arg, the result == the argument */
329           /* Underflow may happen */
330
331         denormal_arg:
332
333           FPU_to_exp16(st0_ptr, st0_ptr);
334       
335           st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
336           FPU_settag0(st0_tag);
337         }
338       push();
339       FPU_copy_to_reg0(&CONST_1, TAG_Valid);
340       return;
341     }
342
343   if ( st0_tag == TAG_Zero )
344     {
345       push();
346       FPU_copy_to_reg0(&CONST_1, TAG_Valid);
347       setcc(0);
348       return;
349     }
350
351   if ( st0_tag == TAG_Special )
352     st0_tag = FPU_Special(st0_ptr);
353
354   if ( st0_tag == TW_Denormal )
355     {
356       if ( denormal_operand() < 0 )
357         return;
358
359       goto denormal_arg;
360     }
361
362   if ( st0_tag == TW_Infinity )
363     {
364       /* The 80486 treats infinity as an invalid operand */
365       if ( arith_invalid(0) >= 0 )
366         {
367           st_new_ptr = &st(-1);
368           push();
369           arith_invalid(0);
370         }
371       return;
372     }
373
374   single_arg_2_error(st0_ptr, st0_tag);
375 }
376
377
378 static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
379 {
380   FPU_REG *st_new_ptr;
381   u_char sign;
382   register FPU_REG *st1_ptr = st0_ptr;  /* anticipate */
383
384   if ( STACK_OVERFLOW )
385     {  FPU_stack_overflow(); return; }
386
387   clear_C1();
388
389   if ( st0_tag == TAG_Valid )
390     {
391       long e;
392
393       push();
394       sign = getsign(st1_ptr);
395       reg_copy(st1_ptr, st_new_ptr);
396       setexponent16(st_new_ptr, exponent(st_new_ptr));
397
398     denormal_arg:
399
400       e = exponent16(st_new_ptr);
401       convert_l2reg(&e, 1);
402       setexponentpos(st_new_ptr, 0);
403       setsign(st_new_ptr, sign);
404       FPU_settag0(TAG_Valid);       /* Needed if arg was a denormal */
405       return;
406     }
407   else if ( st0_tag == TAG_Zero )
408     {
409       sign = getsign(st0_ptr);
410
411       if ( FPU_divide_by_zero(0, SIGN_NEG) < 0 )
412         return;
413
414       push();
415       FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
416       setsign(st_new_ptr, sign);
417       return;
418     }
419
420   if ( st0_tag == TAG_Special )
421     st0_tag = FPU_Special(st0_ptr);
422
423   if ( st0_tag == TW_Denormal )
424     {
425       if (denormal_operand() < 0 )
426         return;
427
428       push();
429       sign = getsign(st1_ptr);
430       FPU_to_exp16(st1_ptr, st_new_ptr);
431       goto denormal_arg;
432     }
433   else if ( st0_tag == TW_Infinity )
434     {
435       sign = getsign(st0_ptr);
436       setpositive(st0_ptr);
437       push();
438       FPU_copy_to_reg0(&CONST_INF, TAG_Special);
439       setsign(st_new_ptr, sign);
440       return;
441     }
442   else if ( st0_tag == TW_NaN )
443     {
444       if ( real_1op_NaN(st0_ptr) < 0 )
445         return;
446
447       push();
448       FPU_copy_to_reg0(st0_ptr, TAG_Special);
449       return;
450     }
451   else if ( st0_tag == TAG_Empty )
452     {
453       /* Is this the correct behaviour? */
454       if ( control_word & EX_Invalid )
455         {
456           FPU_stack_underflow();
457           push();
458           FPU_stack_underflow();
459         }
460       else
461         EXCEPTION(EX_StackUnder);
462     }
463 #ifdef PARANOID
464   else
465     EXCEPTION(EX_INTERNAL | 0x119);
466 #endif /* PARANOID */
467 }
468
469
470 static void fdecstp(void)
471 {
472   clear_C1();
473   top--;
474 }
475
476 static void fincstp(void)
477 {
478   clear_C1();
479   top++;
480 }
481
482
483 static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
484 {
485   int expon;
486
487   clear_C1();
488
489   if ( st0_tag == TAG_Valid )
490     {
491       u_char tag;
492       
493       if (signnegative(st0_ptr))
494         {
495           arith_invalid(0);  /* sqrt(negative) is invalid */
496           return;
497         }
498
499       /* make st(0) in  [1.0 .. 4.0) */
500       expon = exponent(st0_ptr);
501
502     denormal_arg:
503
504       setexponent16(st0_ptr, (expon & 1));
505
506       /* Do the computation, the sign of the result will be positive. */
507       tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS);
508       addexponent(st0_ptr, expon >> 1);
509       FPU_settag0(tag);
510       return;
511     }
512
513   if ( st0_tag == TAG_Zero )
514     return;
515
516   if ( st0_tag == TAG_Special )
517     st0_tag = FPU_Special(st0_ptr);
518
519   if ( st0_tag == TW_Infinity )
520     {
521       if ( signnegative(st0_ptr) )
522         arith_invalid(0);  /* sqrt(-Infinity) is invalid */
523       return;
524     }
525   else if ( st0_tag == TW_Denormal )
526     {
527       if (signnegative(st0_ptr))
528         {
529           arith_invalid(0);  /* sqrt(negative) is invalid */
530           return;
531         }
532
533       if ( denormal_operand() < 0 )
534         return;
535
536       FPU_to_exp16(st0_ptr, st0_ptr);
537
538       expon = exponent16(st0_ptr);
539
540       goto denormal_arg;
541     }
542
543   single_arg_error(st0_ptr, st0_tag);
544
545 }
546
547
548 static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
549 {
550   int flags, tag;
551
552   if ( st0_tag == TAG_Valid )
553     {
554       u_char sign;
555
556     denormal_arg:
557
558       sign = getsign(st0_ptr);
559
560       if (exponent(st0_ptr) > 63)
561         return;
562
563       if ( st0_tag == TW_Denormal )
564         {
565           if (denormal_operand() < 0 )
566             return;
567         }
568
569       /* Fortunately, this can't overflow to 2^64 */
570       if ( (flags = FPU_round_to_int(st0_ptr, st0_tag)) )
571         set_precision_flag(flags);
572
573       setexponent16(st0_ptr, 63);
574       tag = FPU_normalize(st0_ptr);
575       setsign(st0_ptr, sign);
576       FPU_settag0(tag);
577       return;
578     }
579
580   if ( st0_tag == TAG_Zero )
581     return;
582
583   if ( st0_tag == TAG_Special )
584     st0_tag = FPU_Special(st0_ptr);
585
586   if ( st0_tag == TW_Denormal )
587     goto denormal_arg;
588   else if ( st0_tag == TW_Infinity )
589     return;
590   else
591     single_arg_error(st0_ptr, st0_tag);
592 }
593
594
595 static int fsin(FPU_REG *st0_ptr, u_char tag)
596 {
597   u_char arg_sign = getsign(st0_ptr);
598
599   if ( tag == TAG_Valid )
600     {
601       int q;
602
603       if ( exponent(st0_ptr) > -40 )
604         {
605           if ( (q = trig_arg(st0_ptr, 0)) == -1 )
606             {
607               /* Operand is out of range */
608               return 1;
609             }
610
611           poly_sine(st0_ptr);
612           
613           if (q & 2)
614             changesign(st0_ptr);
615
616           setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign);
617
618           /* We do not really know if up or down */
619           set_precision_flag_up();
620           return 0;
621         }
622       else
623         {
624           /* For a small arg, the result == the argument */
625           set_precision_flag_up();  /* Must be up. */
626           return 0;
627         }
628     }
629
630   if ( tag == TAG_Zero )
631     {
632       setcc(0);
633       return 0;
634     }
635
636   if ( tag == TAG_Special )
637     tag = FPU_Special(st0_ptr);
638
639   if ( tag == TW_Denormal )
640     {
641       if ( denormal_operand() < 0 )
642         return 1;
643
644       /* For a small arg, the result == the argument */
645       /* Underflow may happen */
646       FPU_to_exp16(st0_ptr, st0_ptr);
647       
648       tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
649
650       FPU_settag0(tag);
651
652       return 0;
653     }
654   else if ( tag == TW_Infinity )
655     {
656       /* The 80486 treats infinity as an invalid operand */
657       arith_invalid(0);
658       return 1;
659     }
660   else
661     {
662       single_arg_error(st0_ptr, tag);
663       return 1;
664     }
665 }
666
667
668 static int f_cos(FPU_REG *st0_ptr, u_char tag)
669 {
670   u_char st0_sign;
671
672   st0_sign = getsign(st0_ptr);
673
674   if ( tag == TAG_Valid )
675     {
676       int q;
677
678       if ( exponent(st0_ptr) > -40 )
679         {
680           if ( (exponent(st0_ptr) < 0)
681               || ((exponent(st0_ptr) == 0)
682                   && (significand(st0_ptr) <= 0xc90fdaa22168c234LL)) )
683             {
684               poly_cos(st0_ptr);
685
686               /* We do not really know if up or down */
687               set_precision_flag_down();
688           
689               return 0;
690             }
691           else if ( (q = trig_arg(st0_ptr, FCOS)) != -1 )
692             {
693               poly_sine(st0_ptr);
694
695               if ((q+1) & 2)
696                 changesign(st0_ptr);
697
698               /* We do not really know if up or down */
699               set_precision_flag_down();
700           
701               return 0;
702             }
703           else
704             {
705               /* Operand is out of range */
706               return 1;
707             }
708         }
709       else
710         {
711         denormal_arg:
712
713           setcc(0);
714           FPU_copy_to_reg0(&CONST_1, TAG_Valid);
715 #ifdef PECULIAR_486
716           set_precision_flag_down();  /* 80486 appears to do this. */
717 #else
718           set_precision_flag_up();  /* Must be up. */
719 #endif /* PECULIAR_486 */
720           return 0;
721         }
722     }
723   else if ( tag == TAG_Zero )
724     {
725       FPU_copy_to_reg0(&CONST_1, TAG_Valid);
726       setcc(0);
727       return 0;
728     }
729
730   if ( tag == TAG_Special )
731     tag = FPU_Special(st0_ptr);
732
733   if ( tag == TW_Denormal )
734     {
735       if ( denormal_operand() < 0 )
736         return 1;
737
738       goto denormal_arg;
739     }
740   else if ( tag == TW_Infinity )
741     {
742       /* The 80486 treats infinity as an invalid operand */
743       arith_invalid(0);
744       return 1;
745     }
746   else
747     {
748       single_arg_error(st0_ptr, tag);  /* requires st0_ptr == &st(0) */
749       return 1;
750     }
751 }
752
753
754 static void fcos(FPU_REG *st0_ptr, u_char st0_tag)
755 {
756   f_cos(st0_ptr, st0_tag);
757 }
758
759
760 static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
761 {
762   FPU_REG *st_new_ptr;
763   FPU_REG arg;
764   u_char tag;
765
766   /* Stack underflow has higher priority */
767   if ( st0_tag == TAG_Empty )
768     {
769       FPU_stack_underflow();  /* Puts a QNaN in st(0) */
770       if ( control_word & CW_Invalid )
771         {
772           st_new_ptr = &st(-1);
773           push();
774           FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
775         }
776       return;
777     }
778
779   if ( STACK_OVERFLOW )
780     { FPU_stack_overflow(); return; }
781
782   if ( st0_tag == TAG_Special )
783     tag = FPU_Special(st0_ptr);
784   else
785     tag = st0_tag;
786
787   if ( tag == TW_NaN )
788     {
789       single_arg_2_error(st0_ptr, TW_NaN);
790       return;
791     }
792   else if ( tag == TW_Infinity )
793     {
794       /* The 80486 treats infinity as an invalid operand */
795       if ( arith_invalid(0) >= 0 )
796         {
797           /* Masked response */
798           push();
799           arith_invalid(0);
800         }
801       return;
802     }
803
804   reg_copy(st0_ptr, &arg);
805   if ( !fsin(st0_ptr, st0_tag) )
806     {
807       push();
808       FPU_copy_to_reg0(&arg, st0_tag);
809       f_cos(&st(0), st0_tag);
810     }
811   else
812     {
813       /* An error, so restore st(0) */
814       FPU_copy_to_reg0(&arg, st0_tag);
815     }
816 }
817
818
819 /*---------------------------------------------------------------------------*/
820 /* The following all require two arguments: st(0) and st(1) */
821
822 /* A lean, mean kernel for the fprem instructions. This relies upon
823    the division and rounding to an integer in do_fprem giving an
824    exact result. Because of this, rem_kernel() needs to deal only with
825    the least significant 64 bits, the more significant bits of the
826    result must be zero.
827  */
828 static void rem_kernel(unsigned long long st0, unsigned long long *y,
829                        unsigned long long st1,
830                        unsigned long long q, int n)
831 {
832   int dummy;
833   unsigned long long x;
834
835   x = st0 << n;
836
837   /* Do the required multiplication and subtraction in the one operation */
838
839   /* lsw x -= lsw st1 * lsw q */
840   asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1"
841                 :"=m" (((unsigned *)&x)[0]), "=m" (((unsigned *)&x)[1]),
842                 "=a" (dummy)
843                 :"2" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[0])
844                 :"%dx");
845   /* msw x -= msw st1 * lsw q */
846   asm volatile ("mull %3; subl %%eax,%0"
847                 :"=m" (((unsigned *)&x)[1]), "=a" (dummy)
848                 :"1" (((unsigned *)&st1)[1]), "m" (((unsigned *)&q)[0])
849                 :"%dx");
850   /* msw x -= lsw st1 * msw q */
851   asm volatile ("mull %3; subl %%eax,%0"
852                 :"=m" (((unsigned *)&x)[1]), "=a" (dummy)
853                 :"1" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[1])
854                 :"%dx");
855
856   *y = x;
857 }
858
859
860 /* Remainder of st(0) / st(1) */
861 /* This routine produces exact results, i.e. there is never any
862    rounding or truncation, etc of the result. */
863 static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
864 {
865   FPU_REG *st1_ptr = &st(1);
866   u_char st1_tag = FPU_gettagi(1);
867
868   if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
869     {
870       FPU_REG tmp, st0, st1;
871       u_char st0_sign, st1_sign;
872       u_char tmptag;
873       int tag;
874       int old_cw;
875       int expdif;
876       long long q;
877       unsigned short saved_status;
878       int cc;
879
880     fprem_valid:
881       /* Convert registers for internal use. */
882       st0_sign = FPU_to_exp16(st0_ptr, &st0);
883       st1_sign = FPU_to_exp16(st1_ptr, &st1);
884       expdif = exponent16(&st0) - exponent16(&st1);
885
886       old_cw = control_word;
887       cc = 0;
888
889       /* We want the status following the denorm tests, but don't want
890          the status changed by the arithmetic operations. */
891       saved_status = partial_status;
892       control_word &= ~CW_RC;
893       control_word |= RC_CHOP;
894
895       if ( expdif < 64 )
896         {
897           /* This should be the most common case */
898
899           if ( expdif > -2 )
900             {
901               u_char sign = st0_sign ^ st1_sign;
902               tag = FPU_u_div(&st0, &st1, &tmp,
903                               PR_64_BITS | RC_CHOP | 0x3f,
904                               sign);
905               setsign(&tmp, sign);
906
907               if ( exponent(&tmp) >= 0 )
908                 {
909                   FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
910                                                    overflow to 2^64 */
911                   q = significand(&tmp);
912
913                   rem_kernel(significand(&st0),
914                              &significand(&tmp),
915                              significand(&st1),
916                              q, expdif);
917
918                   setexponent16(&tmp, exponent16(&st1));
919                 }
920               else
921                 {
922                   reg_copy(&st0, &tmp);
923                   q = 0;
924                 }
925
926               if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
927                 {
928                   /* We may need to subtract st(1) once more,
929                      to get a result <= 1/2 of st(1). */
930                   unsigned long long x;
931                   expdif = exponent16(&st1) - exponent16(&tmp);
932                   if ( expdif <= 1 )
933                     {
934                       if ( expdif == 0 )
935                         x = significand(&st1) - significand(&tmp);
936                       else /* expdif is 1 */
937                         x = (significand(&st1) << 1) - significand(&tmp);
938                       if ( (x < significand(&tmp)) ||
939                           /* or equi-distant (from 0 & st(1)) and q is odd */
940                           ((x == significand(&tmp)) && (q & 1) ) )
941                         {
942                           st0_sign = ! st0_sign;
943                           significand(&tmp) = x;
944                           q++;
945                         }
946                     }
947                 }
948
949               if (q & 4) cc |= SW_C0;
950               if (q & 2) cc |= SW_C3;
951               if (q & 1) cc |= SW_C1;
952             }
953           else
954             {
955               control_word = old_cw;
956               setcc(0);
957               return;
958             }
959         }
960       else
961         {
962           /* There is a large exponent difference ( >= 64 ) */
963           /* To make much sense, the code in this section should
964              be done at high precision. */
965           int exp_1, N;
966           u_char sign;
967
968           /* prevent overflow here */
969           /* N is 'a number between 32 and 63' (p26-113) */
970           reg_copy(&st0, &tmp);
971           tmptag = st0_tag;
972           N = (expdif & 0x0000001f) + 32;  /* This choice gives results
973                                               identical to an AMD 486 */
974           setexponent16(&tmp, N);
975           exp_1 = exponent16(&st1);
976           setexponent16(&st1, 0);
977           expdif -= N;
978
979           sign = getsign(&tmp) ^ st1_sign;
980           tag = FPU_u_div(&tmp, &st1, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
981                           sign);
982           setsign(&tmp, sign);
983
984           FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
985                                            overflow to 2^64 */
986
987           rem_kernel(significand(&st0),
988                      &significand(&tmp),
989                      significand(&st1),
990                      significand(&tmp),
991                      exponent(&tmp)
992                      ); 
993           setexponent16(&tmp, exp_1 + expdif);
994
995           /* It is possible for the operation to be complete here.
996              What does the IEEE standard say? The Intel 80486 manual
997              implies that the operation will never be completed at this
998              point, and the behaviour of a real 80486 confirms this.
999            */
1000           if ( !(tmp.sigh | tmp.sigl) )
1001             {
1002               /* The result is zero */
1003               control_word = old_cw;
1004               partial_status = saved_status;
1005               FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
1006               setsign(&st0, st0_sign);
1007 #ifdef PECULIAR_486
1008               setcc(SW_C2);
1009 #else
1010               setcc(0);
1011 #endif /* PECULIAR_486 */
1012               return;
1013             }
1014           cc = SW_C2;
1015         }
1016
1017       control_word = old_cw;
1018       partial_status = saved_status;
1019       tag = FPU_normalize_nuo(&tmp);
1020       reg_copy(&tmp, st0_ptr);
1021
1022       /* The only condition to be looked for is underflow,
1023          and it can occur here only if underflow is unmasked. */
1024       if ( (exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
1025           && !(control_word & CW_Underflow) )
1026         {
1027           setcc(cc);
1028           tag = arith_underflow(st0_ptr);
1029           setsign(st0_ptr, st0_sign);
1030           FPU_settag0(tag);
1031           return;
1032         }
1033       else if ( (exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero) )
1034         {
1035           stdexp(st0_ptr);
1036           setsign(st0_ptr, st0_sign);
1037         }
1038       else
1039         {
1040           tag = FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
1041         }
1042       FPU_settag0(tag);
1043       setcc(cc);
1044
1045       return;
1046     }
1047
1048   if ( st0_tag == TAG_Special )
1049     st0_tag = FPU_Special(st0_ptr);
1050   if ( st1_tag == TAG_Special )
1051     st1_tag = FPU_Special(st1_ptr);
1052
1053   if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
1054             || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
1055             || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
1056     {
1057       if ( denormal_operand() < 0 )
1058         return;
1059       goto fprem_valid;
1060     }
1061   else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
1062     {
1063       FPU_stack_underflow();
1064       return;
1065     }
1066   else if ( st0_tag == TAG_Zero )
1067     {
1068       if ( st1_tag == TAG_Valid )
1069         {
1070           setcc(0); return;
1071         }
1072       else if ( st1_tag == TW_Denormal )
1073         {
1074           if ( denormal_operand() < 0 )
1075             return;
1076           setcc(0); return;
1077         }
1078       else if ( st1_tag == TAG_Zero )
1079         { arith_invalid(0); return; } /* fprem(?,0) always invalid */
1080       else if ( st1_tag == TW_Infinity )
1081         { setcc(0); return; }
1082     }
1083   else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
1084     {
1085       if ( st1_tag == TAG_Zero )
1086         {
1087           arith_invalid(0); /* fprem(Valid,Zero) is invalid */
1088           return;
1089         }
1090       else if ( st1_tag != TW_NaN )
1091         {
1092           if ( ((st0_tag == TW_Denormal) || (st1_tag == TW_Denormal))
1093                && (denormal_operand() < 0) )
1094             return;
1095
1096           if ( st1_tag == TW_Infinity )
1097             {
1098               /* fprem(Valid,Infinity) is o.k. */
1099               setcc(0); return;
1100             }
1101         }
1102     }
1103   else if ( st0_tag == TW_Infinity )
1104     {
1105       if ( st1_tag != TW_NaN )
1106         {
1107           arith_invalid(0); /* fprem(Infinity,?) is invalid */
1108           return;
1109         }
1110     }
1111
1112   /* One of the registers must contain a NaN if we got here. */
1113
1114 #ifdef PARANOID
1115   if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
1116       EXCEPTION(EX_INTERNAL | 0x118);
1117 #endif /* PARANOID */
1118
1119   real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr);
1120
1121 }
1122
1123
1124 /* ST(1) <- ST(1) * log ST;  pop ST */
1125 static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
1126 {
1127   FPU_REG *st1_ptr = &st(1), exponent;
1128   u_char st1_tag = FPU_gettagi(1);
1129   u_char sign;
1130   int e, tag;
1131
1132   clear_C1();
1133
1134   if ( (st0_tag == TAG_Valid) && (st1_tag == TAG_Valid) )
1135     {
1136     both_valid:
1137       /* Both regs are Valid or Denormal */
1138       if ( signpositive(st0_ptr) )
1139         {
1140           if ( st0_tag == TW_Denormal )
1141             FPU_to_exp16(st0_ptr, st0_ptr);
1142           else
1143             /* Convert st(0) for internal use. */
1144             setexponent16(st0_ptr, exponent(st0_ptr));
1145
1146           if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
1147             {
1148               /* Special case. The result can be precise. */
1149               u_char esign;
1150               e = exponent16(st0_ptr);
1151               if ( e >= 0 )
1152                 {
1153                   exponent.sigh = e;
1154                   esign = SIGN_POS;
1155                 }
1156               else
1157                 {
1158                   exponent.sigh = -e;
1159                   esign = SIGN_NEG;
1160                 }
1161               exponent.sigl = 0;
1162               setexponent16(&exponent, 31);
1163               tag = FPU_normalize_nuo(&exponent);
1164               stdexp(&exponent);
1165               setsign(&exponent, esign);
1166               tag = FPU_mul(&exponent, tag, 1, FULL_PRECISION);
1167               if ( tag >= 0 )
1168                 FPU_settagi(1, tag);
1169             }
1170           else
1171             {
1172               /* The usual case */
1173               sign = getsign(st1_ptr);
1174               if ( st1_tag == TW_Denormal )
1175                 FPU_to_exp16(st1_ptr, st1_ptr);
1176               else
1177                 /* Convert st(1) for internal use. */
1178                 setexponent16(st1_ptr, exponent(st1_ptr));
1179               poly_l2(st0_ptr, st1_ptr, sign);
1180             }
1181         }
1182       else
1183         {
1184           /* negative */
1185           if ( arith_invalid(1) < 0 )
1186             return;
1187         }
1188
1189       FPU_pop();
1190
1191       return;
1192     }
1193
1194   if ( st0_tag == TAG_Special )
1195     st0_tag = FPU_Special(st0_ptr);
1196   if ( st1_tag == TAG_Special )
1197     st1_tag = FPU_Special(st1_ptr);
1198
1199   if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
1200     {
1201       FPU_stack_underflow_pop(1);
1202       return;
1203     }
1204   else if ( (st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal) )
1205     {
1206       if ( st0_tag == TAG_Zero )
1207         {
1208           if ( st1_tag == TAG_Zero )
1209             {
1210               /* Both args zero is invalid */
1211               if ( arith_invalid(1) < 0 )
1212                 return;
1213             }
1214           else
1215             {
1216               u_char sign;
1217               sign = getsign(st1_ptr)^SIGN_NEG;
1218               if ( FPU_divide_by_zero(1, sign) < 0 )
1219                 return;
1220
1221               setsign(st1_ptr, sign);
1222             }
1223         }
1224       else if ( st1_tag == TAG_Zero )
1225         {
1226           /* st(1) contains zero, st(0) valid <> 0 */
1227           /* Zero is the valid answer */
1228           sign = getsign(st1_ptr);
1229           
1230           if ( signnegative(st0_ptr) )
1231             {
1232               /* log(negative) */
1233               if ( arith_invalid(1) < 0 )
1234                 return;
1235             }
1236           else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1237             return;
1238           else
1239             {
1240               if ( exponent(st0_ptr) < 0 )
1241                 sign ^= SIGN_NEG;
1242
1243               FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
1244               setsign(st1_ptr, sign);
1245             }
1246         }
1247       else
1248         {
1249           /* One or both operands are denormals. */
1250           if ( denormal_operand() < 0 )
1251             return;
1252           goto both_valid;
1253         }
1254     }
1255   else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
1256     {
1257       if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
1258         return;
1259     }
1260   /* One or both arg must be an infinity */
1261   else if ( st0_tag == TW_Infinity )
1262     {
1263       if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) )
1264         {
1265           /* log(-infinity) or 0*log(infinity) */
1266           if ( arith_invalid(1) < 0 )
1267             return;
1268         }
1269       else
1270         {
1271           u_char sign = getsign(st1_ptr);
1272
1273           if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
1274             return;
1275
1276           FPU_copy_to_reg1(&CONST_INF, TAG_Special);
1277           setsign(st1_ptr, sign);
1278         }
1279     }
1280   /* st(1) must be infinity here */
1281   else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
1282             && ( signpositive(st0_ptr) ) )
1283     {
1284       if ( exponent(st0_ptr) >= 0 )
1285         {
1286           if ( (exponent(st0_ptr) == 0) &&
1287               (st0_ptr->sigh == 0x80000000) &&
1288               (st0_ptr->sigl == 0) )
1289             {
1290               /* st(0) holds 1.0 */
1291               /* infinity*log(1) */
1292               if ( arith_invalid(1) < 0 )
1293                 return;
1294             }
1295           /* else st(0) is positive and > 1.0 */
1296         }
1297       else
1298         {
1299           /* st(0) is positive and < 1.0 */
1300
1301           if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1302             return;
1303
1304           changesign(st1_ptr);
1305         }
1306     }
1307   else
1308     {
1309       /* st(0) must be zero or negative */
1310       if ( st0_tag == TAG_Zero )
1311         {
1312           /* This should be invalid, but a real 80486 is happy with it. */
1313
1314 #ifndef PECULIAR_486
1315           sign = getsign(st1_ptr);
1316           if ( FPU_divide_by_zero(1, sign) < 0 )
1317             return;
1318 #endif /* PECULIAR_486 */
1319
1320           changesign(st1_ptr);
1321         }
1322       else if ( arith_invalid(1) < 0 )    /* log(negative) */
1323         return;
1324     }
1325
1326   FPU_pop();
1327 }
1328
1329
1330 static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
1331 {
1332   FPU_REG *st1_ptr = &st(1);
1333   u_char st1_tag = FPU_gettagi(1);
1334   int tag;
1335
1336   clear_C1();
1337   if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
1338     {
1339     valid_atan:
1340
1341       poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);
1342
1343       FPU_pop();
1344
1345       return;
1346     }
1347
1348   if ( st0_tag == TAG_Special )
1349     st0_tag = FPU_Special(st0_ptr);
1350   if ( st1_tag == TAG_Special )
1351     st1_tag = FPU_Special(st1_ptr);
1352
1353   if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
1354             || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
1355             || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
1356     {
1357       if ( denormal_operand() < 0 )
1358         return;
1359
1360       goto valid_atan;
1361     }
1362   else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
1363     {
1364       FPU_stack_underflow_pop(1);
1365       return;
1366     }
1367   else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
1368     {
1369       if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 )
1370           FPU_pop();
1371       return;
1372     }
1373   else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )
1374     {
1375       u_char sign = getsign(st1_ptr);
1376       if ( st0_tag == TW_Infinity )
1377         {
1378           if ( st1_tag == TW_Infinity )
1379             {
1380               if ( signpositive(st0_ptr) )
1381                 {
1382                   FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);
1383                 }
1384               else
1385                 {
1386                   setpositive(st1_ptr);
1387                   tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr,
1388                                   FULL_PRECISION, SIGN_POS,
1389                                   exponent(&CONST_PI4), exponent(&CONST_PI2));
1390                   if ( tag >= 0 )
1391                     FPU_settagi(1, tag);
1392                 }
1393             }
1394           else
1395             {
1396               if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
1397                 return;
1398
1399               if ( signpositive(st0_ptr) )
1400                 {
1401                   FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
1402                   setsign(st1_ptr, sign);   /* An 80486 preserves the sign */
1403                   FPU_pop();
1404                   return;
1405                 }
1406               else
1407                 {
1408                   FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
1409                 }
1410             }
1411         }
1412       else
1413         {
1414           /* st(1) is infinity, st(0) not infinity */
1415           if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1416             return;
1417
1418           FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
1419         }
1420       setsign(st1_ptr, sign);
1421     }
1422   else if ( st1_tag == TAG_Zero )
1423     {
1424       /* st(0) must be valid or zero */
1425       u_char sign = getsign(st1_ptr);
1426
1427       if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1428         return;
1429
1430       if ( signpositive(st0_ptr) )
1431         {
1432           /* An 80486 preserves the sign */
1433           FPU_pop();
1434           return;
1435         }
1436
1437       FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
1438       setsign(st1_ptr, sign);
1439     }
1440   else if ( st0_tag == TAG_Zero )
1441     {
1442       /* st(1) must be TAG_Valid here */
1443       u_char sign = getsign(st1_ptr);
1444
1445       if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
1446         return;
1447
1448       FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
1449       setsign(st1_ptr, sign);
1450     }
1451 #ifdef PARANOID
1452   else
1453     EXCEPTION(EX_INTERNAL | 0x125);
1454 #endif /* PARANOID */
1455
1456   FPU_pop();
1457   set_precision_flag_up();  /* We do not really know if up or down */
1458 }
1459
1460
1461 static void fprem(FPU_REG *st0_ptr, u_char st0_tag)
1462 {
1463   do_fprem(st0_ptr, st0_tag, RC_CHOP);
1464 }
1465
1466
1467 static void fprem1(FPU_REG *st0_ptr, u_char st0_tag)
1468 {
1469   do_fprem(st0_ptr, st0_tag, RC_RND);
1470 }
1471
1472
1473 static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
1474 {
1475   u_char sign, sign1;
1476   FPU_REG *st1_ptr = &st(1), a, b;
1477   u_char st1_tag = FPU_gettagi(1);
1478
1479   clear_C1();
1480   if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
1481     {
1482     valid_yl2xp1:
1483
1484       sign = getsign(st0_ptr);
1485       sign1 = getsign(st1_ptr);
1486
1487       FPU_to_exp16(st0_ptr, &a);
1488       FPU_to_exp16(st1_ptr, &b);
1489
1490       if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) )
1491         return;
1492
1493       FPU_pop();
1494       return;
1495     }
1496
1497   if ( st0_tag == TAG_Special )
1498     st0_tag = FPU_Special(st0_ptr);
1499   if ( st1_tag == TAG_Special )
1500     st1_tag = FPU_Special(st1_ptr);
1501
1502   if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
1503             || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
1504             || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
1505     {
1506       if ( denormal_operand() < 0 )
1507         return;
1508
1509       goto valid_yl2xp1;
1510     }
1511   else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
1512     {
1513       FPU_stack_underflow_pop(1);
1514       return;
1515     }
1516   else if ( st0_tag == TAG_Zero )
1517     {
1518       switch ( st1_tag )
1519         {
1520         case TW_Denormal:
1521           if ( denormal_operand() < 0 )
1522             return;
1523
1524         case TAG_Zero:
1525         case TAG_Valid:
1526           setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
1527           FPU_copy_to_reg1(st0_ptr, st0_tag);
1528           break;
1529
1530         case TW_Infinity:
1531           /* Infinity*log(1) */
1532           if ( arith_invalid(1) < 0 )
1533             return;
1534           break;
1535
1536         case TW_NaN:
1537           if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
1538             return;
1539           break;
1540
1541         default:
1542 #ifdef PARANOID
1543           EXCEPTION(EX_INTERNAL | 0x116);
1544           return;
1545 #endif /* PARANOID */
1546           break;
1547         }
1548     }
1549   else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
1550     {
1551       switch ( st1_tag )
1552         {
1553         case TAG_Zero:
1554           if ( signnegative(st0_ptr) )
1555             {
1556               if ( exponent(st0_ptr) >= 0 )
1557                 {
1558                   /* st(0) holds <= -1.0 */
1559 #ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
1560                   changesign(st1_ptr);
1561 #else
1562                   if ( arith_invalid(1) < 0 )
1563                     return;
1564 #endif /* PECULIAR_486 */
1565                 }
1566               else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1567                 return;
1568               else
1569                 changesign(st1_ptr);
1570             }
1571           else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1572             return;
1573           break;
1574
1575         case TW_Infinity:
1576           if ( signnegative(st0_ptr) )
1577             {
1578               if ( (exponent(st0_ptr) >= 0) &&
1579                   !((st0_ptr->sigh == 0x80000000) &&
1580                     (st0_ptr->sigl == 0)) )
1581                 {
1582                   /* st(0) holds < -1.0 */
1583 #ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
1584                   changesign(st1_ptr);
1585 #else
1586                   if ( arith_invalid(1) < 0 ) return;
1587 #endif /* PECULIAR_486 */
1588                 }
1589               else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1590                 return;
1591               else
1592                 changesign(st1_ptr);
1593             }
1594           else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1595             return;
1596           break;
1597
1598         case TW_NaN:
1599           if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
1600             return;
1601         }
1602
1603     }
1604   else if ( st0_tag == TW_NaN )
1605     {
1606       if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
1607         return;
1608     }
1609   else if ( st0_tag == TW_Infinity )
1610     {
1611       if ( st1_tag == TW_NaN )
1612         {
1613           if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
1614             return;
1615         }
1616       else if ( signnegative(st0_ptr) )
1617         {
1618 #ifndef PECULIAR_486
1619           /* This should have higher priority than denormals, but... */
1620           if ( arith_invalid(1) < 0 )  /* log(-infinity) */
1621             return;
1622 #endif /* PECULIAR_486 */
1623           if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
1624             return;
1625 #ifdef PECULIAR_486
1626           /* Denormal operands actually get higher priority */
1627           if ( arith_invalid(1) < 0 )  /* log(-infinity) */
1628             return;
1629 #endif /* PECULIAR_486 */
1630         }
1631       else if ( st1_tag == TAG_Zero )
1632         {
1633           /* log(infinity) */
1634           if ( arith_invalid(1) < 0 )
1635             return;
1636         }
1637         
1638       /* st(1) must be valid here. */
1639
1640       else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
1641         return;
1642
1643       /* The Manual says that log(Infinity) is invalid, but a real
1644          80486 sensibly says that it is o.k. */
1645       else
1646         {
1647           u_char sign = getsign(st1_ptr);
1648           FPU_copy_to_reg1(&CONST_INF, TAG_Special);
1649           setsign(st1_ptr, sign);
1650         }
1651     }
1652 #ifdef PARANOID
1653   else
1654     {
1655       EXCEPTION(EX_INTERNAL | 0x117);
1656       return;
1657     }
1658 #endif /* PARANOID */
1659
1660   FPU_pop();
1661   return;
1662
1663 }
1664
1665
1666 static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
1667 {
1668   FPU_REG *st1_ptr = &st(1);
1669   u_char st1_tag = FPU_gettagi(1);
1670   int old_cw = control_word;
1671   u_char sign = getsign(st0_ptr);
1672
1673   clear_C1();
1674   if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
1675     {
1676       long scale;
1677       FPU_REG tmp;
1678
1679       /* Convert register for internal use. */
1680       setexponent16(st0_ptr, exponent(st0_ptr));
1681
1682     valid_scale:
1683
1684       if ( exponent(st1_ptr) > 30 )
1685         {
1686           /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */
1687
1688           if ( signpositive(st1_ptr) )
1689             {
1690               EXCEPTION(EX_Overflow);
1691               FPU_copy_to_reg0(&CONST_INF, TAG_Special);
1692             }
1693           else
1694             {
1695               EXCEPTION(EX_Underflow);
1696               FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
1697             }
1698           setsign(st0_ptr, sign);
1699           return;
1700         }
1701
1702       control_word &= ~CW_RC;
1703       control_word |= RC_CHOP;
1704       reg_copy(st1_ptr, &tmp);
1705       FPU_round_to_int(&tmp, st1_tag);      /* This can never overflow here */
1706       control_word = old_cw;
1707       scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl;
1708       scale += exponent16(st0_ptr);
1709
1710       setexponent16(st0_ptr, scale);
1711
1712       /* Use FPU_round() to properly detect under/overflow etc */
1713       FPU_round(st0_ptr, 0, 0, control_word, sign);
1714
1715       return;
1716     }
1717
1718   if ( st0_tag == TAG_Special )
1719     st0_tag = FPU_Special(st0_ptr);
1720   if ( st1_tag == TAG_Special )
1721     st1_tag = FPU_Special(st1_ptr);
1722
1723   if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
1724     {
1725       switch ( st1_tag )
1726         {
1727         case TAG_Valid:
1728           /* st(0) must be a denormal */
1729           if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1730             return;
1731
1732           FPU_to_exp16(st0_ptr, st0_ptr);  /* Will not be left on stack */
1733           goto valid_scale;
1734
1735         case TAG_Zero:
1736           if ( st0_tag == TW_Denormal )
1737             denormal_operand();
1738           return;
1739
1740         case TW_Denormal:
1741           denormal_operand();
1742           return;
1743
1744         case TW_Infinity:
1745           if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
1746             return;
1747
1748           if ( signpositive(st1_ptr) )
1749             FPU_copy_to_reg0(&CONST_INF, TAG_Special);
1750           else
1751             FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
1752           setsign(st0_ptr, sign);
1753           return;
1754
1755         case TW_NaN:
1756           real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1757           return;
1758         }
1759     }
1760   else if ( st0_tag == TAG_Zero )
1761     {
1762       switch ( st1_tag )
1763         {
1764         case TAG_Valid:
1765         case TAG_Zero:
1766           return;
1767
1768         case TW_Denormal:
1769           denormal_operand();
1770           return;
1771
1772         case TW_Infinity:
1773           if ( signpositive(st1_ptr) )
1774             arith_invalid(0); /* Zero scaled by +Infinity */
1775           return;
1776
1777         case TW_NaN:
1778           real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1779           return;
1780         }
1781     }
1782   else if ( st0_tag == TW_Infinity )
1783     {
1784       switch ( st1_tag )
1785         {
1786         case TAG_Valid:
1787         case TAG_Zero:
1788           return;
1789
1790         case TW_Denormal:
1791           denormal_operand();
1792           return;
1793
1794         case TW_Infinity:
1795           if ( signnegative(st1_ptr) )
1796             arith_invalid(0); /* Infinity scaled by -Infinity */
1797           return;
1798
1799         case TW_NaN:
1800           real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1801           return;
1802         }
1803     }
1804   else if ( st0_tag == TW_NaN )
1805     {
1806       if ( st1_tag != TAG_Empty )
1807         { real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; }
1808     }
1809
1810 #ifdef PARANOID
1811   if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) )
1812     {
1813       EXCEPTION(EX_INTERNAL | 0x115);
1814       return;
1815     }
1816 #endif
1817
1818   /* At least one of st(0), st(1) must be empty */
1819   FPU_stack_underflow();
1820
1821 }
1822
1823
1824 /*---------------------------------------------------------------------------*/
1825
1826 static FUNC_ST0 const trig_table_a[] = {
1827   f2xm1, fyl2x, fptan, fpatan,
1828   fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp
1829 };
1830
1831 void FPU_triga(void)
1832 {
1833   (trig_table_a[FPU_rm])(&st(0), FPU_gettag0());
1834 }
1835
1836
1837 static FUNC_ST0 const trig_table_b[] =
1838   {
1839     fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos
1840   };
1841
1842 void FPU_trigb(void)
1843 {
1844   (trig_table_b[FPU_rm])(&st(0), FPU_gettag0());
1845 }