home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 359_11 / patch5.000 / EMU387 / E17.CC < prev    next >
C/C++ Source or Header  |  1991-09-11  |  5KB  |  298 lines

  1. #include "emu.h"
  2. #include "rmov.h"
  3. #include "const.h"
  4.  
  5. extern "C" void shld(void *);
  6. extern "C" void shrd(void *);
  7.  
  8. int fprem_do(reg& quot, reg& div, int round) // remainder of st() / st(1)
  9. {
  10.   int rv;
  11.   int old_cw = control_word;
  12.   control_word &= ~CW_RC;
  13.   control_word |= round;
  14.   int expdif = quot.exp - div.exp;
  15.   if (expdif < 64)
  16.   {
  17.     reg tmp, tmp2;
  18.     r_div(quot, div, tmp);
  19.     long q;
  20.     r_mov(tmp, &q);
  21.     r_mov(&q, tmp);
  22.     r_mul(div, tmp, tmp2);
  23.     r_sub(quot, tmp2, tmp);
  24.     r_mov(tmp, quot);
  25.     rv = q & 7;
  26.   }
  27.   else
  28.   {
  29.     reg tmp, tmp2;
  30.     setcc(SW_C2);
  31.     r_div(st, div, tmp);
  32.     int old_exp = tmp.exp;
  33.     tmp.exp &= 31;
  34.     long q;
  35.     r_mov(tmp, &q);
  36.     r_mov(&q, tmp);
  37.     tmp.exp = old_exp;
  38.     r_mul(div, tmp, tmp2);
  39.     r_sub(quot, tmp2, tmp);
  40.     r_mov(tmp, quot);
  41.     rv = -1;
  42.   }
  43.   control_word = old_cw;
  44.   return rv;;
  45. }
  46.  
  47. void fprem()
  48. {
  49.   if (empty(1))
  50.     return;
  51.   int q = fprem_do(st(), st(1), RC_CHOP);
  52.   if (q == -1)
  53.     setcc(SW_C2);
  54.   else
  55.   {
  56.     int c = 0;
  57.     if (q&4) c |= SW_C3;
  58.     if (q&2) c |= SW_C1;
  59.     if (q&1) c |= SW_C0;
  60.     setcc(c);
  61.   }
  62. }
  63.  
  64. void fyl2xp1()
  65. {
  66.   if (empty())
  67.     return;
  68.   reg frac2, sum, div, term, pow, temp;
  69.   r_mov(st(), frac2);
  70.   r_add(st(), CONST_2, div);
  71.   r_div(frac2, div, sum);
  72.   r_mul(sum, sum, frac2);
  73.   r_mul(sum, st(1), pow);
  74.   for (long i=3; i<15; i+=2)
  75.   {
  76.     r_mul(pow, frac2, temp);
  77.     r_mov(temp, pow);
  78.     r_mov(&i, div);
  79.     r_div(temp, div, term);
  80.     r_add(term, sum, temp);
  81.     r_mov(temp, sum);
  82.   }
  83.   r_div(sum, CONST_LN2, temp);
  84.   temp.exp++;
  85.   r_mov(temp, st(1));
  86.   st().tag = TW_E;
  87.   top++;
  88. }
  89.  
  90. void fsqrt()
  91. {
  92.   if (empty())
  93.     return;
  94.   if (st().tag == TW_Z)
  95.     return;
  96.   if (st().exp == EXP_MAX)
  97.     return;
  98.   if (st().sign == SIGN_NEG)
  99.     return exception(EX_I);
  100.  
  101.   unsigned long long val = *(unsigned long long *)(&st().sigl);
  102.   unsigned long long result = 0;
  103.   unsigned long long side = 0;
  104.   unsigned long long left = 0;
  105.   int digit = 0;
  106.   int i;
  107.   if (st().exp & 1)
  108.   {
  109.     shrd(&val);
  110.     st().exp++;
  111.   }
  112.   int exp = (st().exp - EXP_BIAS - 1)/2 - 64;
  113.   while (!(((long *)&result)[1] & 0x80000000))
  114.   {
  115.     left = (left << 2) + (val >> 62);
  116.     shld(&val);
  117.     shld(&val);
  118.     if (left >= side*2 + 1)
  119.     {
  120.       left -= side*2+1;
  121.       side = (side+1)*2;
  122.       shld(&result);
  123.       result |= 1;
  124.     }
  125.     else
  126.     {
  127.       side *= 2;
  128.       shld(&result);
  129.     }
  130.     exp++;
  131.   }
  132.   st().exp = exp + EXP_BIAS;
  133.   st().sigl = result & 0xffffffff;
  134.   st().sigh = result >> 32;
  135.   st().tag = TW_V;
  136. }
  137.  
  138. void fsincos()
  139. {
  140.   if (empty())
  141.     return;
  142.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  143.  
  144.   if (q & 1)
  145.   {
  146.     reg tmp;
  147.     r_sub(CONST_PI2, st(), tmp);
  148.     r_mov(tmp, st());
  149.   }
  150.  
  151.   reg x2, val, rv, tmp, t2;
  152.   reg valc, rvc, tmpc;
  153.   r_mov(st(), val);
  154.   r_mul(st(), val, x2);
  155.   r_mov(val, rv);
  156.   r_mov(CONST_1, valc);
  157.   r_mov(valc, rvc);
  158.  
  159.  
  160.   for (int i=0; i<11; i++)
  161.   {
  162.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  163.     valc.sign ^= SIGN_POS ^ SIGN_NEG;
  164.     r_mul(x2, val, tmp);
  165.     r_mul(x2, valc, tmpc);
  166.     long c = ((i<<1)+2) * ((i<<1)+3);
  167.     r_mov(&c, t2);
  168.     r_div(tmp, t2, val);
  169.     c = ((i<<1)+1) * ((i<<1)+2);
  170.     r_mov(&c, t2);
  171.     r_div(tmpc, t2, valc);
  172.     r_add(val, rv, tmp);
  173.     r_mov(tmp, rv);
  174.     r_add(valc, rvc, tmpc);
  175.     r_mov(tmpc, rvc);
  176.   }
  177.   setcc(0);
  178.  
  179.   if (q & 2)
  180.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  181.   r_mov(rv, st());
  182.  
  183.   top--;
  184.   register int qq = q & 3;
  185.   if ((qq == 1) || (qq == 2))
  186.     rvc.sign ^= SIGN_POS ^ SIGN_NEG;
  187.   r_mov(rvc, st());
  188. }
  189.  
  190. void frndint()
  191. {
  192.   if (empty())
  193.     return;
  194.   long long tmp;
  195.   if (st().exp > EXP_BIAS+62)
  196.     return;
  197.   r_mov(st(), &tmp);
  198.   r_mov(&tmp, st());
  199. }
  200.  
  201. void fscale()
  202. {
  203.   long scale;
  204.   if (empty(1))
  205.     return;
  206.   r_mov(st(1), &scale);
  207.   st().exp += scale;
  208. }
  209.  
  210. void fsin()
  211. {
  212.   if (empty())
  213.     return;
  214.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  215.  
  216.   if (q & 1)
  217.   {
  218.     reg tmp;
  219.     r_sub(CONST_PI2, st(), tmp);
  220.     r_mov(tmp, st());
  221.   }
  222.  
  223.   reg x2, val, rv, tmp, t2;
  224.   r_mov(st(), val);
  225.   r_mul(st(), val, x2);
  226.   r_mov(val, rv);
  227.  
  228.  
  229.   for (int i=0; i<11; i++)
  230.   {
  231.     long c = ((i<<1)+2) * ((i<<1)+3);
  232.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  233.     r_mul(x2, val, tmp);
  234.     r_mov(&c, t2);
  235.     r_div(tmp, t2, val);
  236.     r_add(val, rv, tmp);
  237.     r_mov(tmp, rv);
  238.   }
  239.   setcc(0);
  240.   if (q & 2)
  241.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  242.   r_mov(rv, st());
  243. }
  244.  
  245. void fcos()
  246. {
  247.   if (empty())
  248.     return;
  249.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  250.  
  251.   if (q & 1)
  252.   {
  253.     reg tmp;
  254.     r_sub(CONST_PI2, st(), tmp);
  255.     r_mov(tmp, st());
  256.   }
  257.  
  258.   reg x2, val, rv, tmp, t2;
  259.   r_mov(st(), val);
  260.   r_mul(st(), val, x2);
  261.   r_mov(CONST_1, val);
  262.   r_mov(val, rv);
  263.  
  264.  
  265.   for (int i=0; i<11; i++)
  266.   {
  267.     long c = ((i<<1)+1) * ((i<<1)+2);
  268.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  269.     r_mul(x2, val, tmp);
  270.     r_mov(&c, t2);
  271.     r_div(tmp, t2, val);
  272.     r_add(val, rv, tmp);
  273.     r_mov(tmp, rv);
  274.   }
  275.   setcc(0);
  276.   register int qq = q & 3;
  277.   if ((qq == 1) || (qq == 2))
  278.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  279.   r_mov(rv, st());
  280. }
  281.  
  282. FUNC emu_17_table[] = {
  283.   fprem, fyl2xp1, fsqrt, fsincos, frndint, fscale, fsin, fcos
  284. };
  285.  
  286. void emu_17()
  287. {
  288.   if (modrm > 0277)
  289.   {
  290.     (emu_17_table[modrm&7])();
  291.   }
  292.   else
  293.   {
  294.     // fstcw m16int
  295.     *(short *)get_modrm() = control_word;
  296.   }
  297. }
  298.