home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / msdos / djgpp / emu387 / e17.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-27  |  5.3 KB  |  309 lines

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