fpu_trig.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:41k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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