home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / djgpp / emu387 / emumath.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-09  |  5.6 KB  |  312 lines

  1. #include "emu.h"
  2. #include "const.h"
  3.  
  4. extern "C" void shld(void *);
  5. extern "C" void shrd(void *);
  6.  
  7. extern void normalize(reg& r);
  8.  
  9. void r_uadd(reg& a, reg& b, reg& s) // signs ignored
  10. {
  11.   reg t;
  12.   int dif = a.exp - b.exp;
  13.   if (!dif) dif = a.sigh - b.sigh;
  14.   if (!dif) dif = a.sigl - b.sigl;
  15.   if (dif > 0)
  16.   {
  17.     r_mov(a, s);
  18.     r_mov(b, t);
  19.   }
  20.   else
  21.   {
  22.     r_mov(b, s);
  23.     r_mov(a, t);
  24.   }
  25.   if (s.exp - t.exp > 64)
  26.     return;
  27.   while (t.exp < s.exp)
  28.   {
  29.     t.exp ++;
  30.     shrd(&t.sigl);
  31.   }
  32.   unsigned short *ss, *ts;
  33.   unsigned long tmp;
  34.   ss = (unsigned short *)&s.sigl;
  35.   ts = (unsigned short *)&t.sigl;
  36.   tmp = 0;
  37.   for (int i=4; i>0; i--)
  38.   {
  39.     tmp += (unsigned long)*ss + (unsigned long)*ts;
  40.     *ss = tmp;
  41.     ss++;
  42.     ts++;
  43.     tmp >>= 16;
  44.   }
  45.   if (tmp)
  46.   {
  47.     shrd(&s.sigl);
  48.     s.exp++;
  49.     s.sigh |= 0x80000000;
  50.   }
  51.   if (!(s.sigh | s.sigl))
  52.   {
  53.     s.exp = 0;
  54.     s.tag = TW_Z;
  55.   }
  56.   else
  57.   {
  58.     while (!(s.sigh & 0x80000000))
  59.     {
  60.       if (s.exp == 0)
  61.         return;
  62.       shld(&s.sigl);
  63.       s.exp--;
  64.     }
  65.   }
  66. }
  67.  
  68. void r_usub(reg& a, reg& b, reg& d) // a > b
  69. {
  70.   reg t;
  71.   r_mov(a, d);
  72.   r_mov(b, t);
  73.  
  74.   if (d.exp - t.exp > 64)
  75.     return;
  76.   while (t.exp < d.exp)
  77.   {
  78.     t.exp ++;
  79.     shrd(&t.sigl);
  80.   }
  81.   unsigned short *ss, *ts;
  82.   long tmp;
  83.   ss = (unsigned short *)&d.sigl;
  84.   ts = (unsigned short *)&t.sigl;
  85.   tmp = 0;
  86.   for (int i=4; i>0; i--)
  87.   {
  88.     tmp += (long)*ss - (long)*ts;
  89.     *ss = tmp;
  90.     ss++;
  91.     ts++;
  92.     tmp /= 65536;
  93.   }
  94.   if (!(d.sigh | d.sigl))
  95.   {
  96.     d.exp = 0;
  97.     d.tag = TW_Z;
  98.   }
  99.   else
  100.   {
  101.     while (!(d.sigh & 0x80000000))
  102.     {
  103.       if (d.exp == 0)
  104.         return;
  105.       shld(&d.sigl);
  106.       d.exp--;
  107.     }
  108.   }
  109. }
  110.  
  111. void r_add(reg& a, reg& b, reg& s)
  112. {
  113.   if (a.tag == TW_Z)
  114.     return r_mov(b, s);
  115.   if (b.tag == TW_Z)
  116.     return r_mov(a, s);
  117.   if (a.tag == TW_S)
  118.     return r_mov(a, s);
  119.   if (b.tag == TW_S)
  120.     return r_mov(b, s);
  121.  
  122.   switch (a.sign*2 + b.sign)
  123.   {
  124.     case 0: // P + P
  125.     case 3: // N + N
  126.       r_uadd(a, b, s);
  127.       s.sign = a.sign;
  128.       break;
  129.     case 1: // P + N
  130.       b.sign ^= SIGN_POS^SIGN_NEG;
  131.       r_sub(a, b, s);
  132.       break;
  133.     case 2: // N + P
  134.       a.sign ^= SIGN_POS^SIGN_NEG;
  135.       r_sub(b, a, s);
  136.       break;
  137.   }
  138. }
  139.  
  140. void r_sub(reg& a, reg& b, reg& d)
  141. {
  142.   if (b.tag == TW_Z)
  143.     return r_mov(a, d);
  144.   if (a.tag == TW_Z)
  145.   {
  146.     r_mov(b, d);
  147.     d.sign ^= SIGN_POS^SIGN_NEG;
  148.     return;
  149.   }
  150.   if (a.tag == TW_S)
  151.     return r_mov(a, d);
  152.   if (b.tag == TW_S)
  153.   {
  154.     r_mov(b, d);
  155.     d.sign ^= SIGN_POS^SIGN_NEG;
  156.     return;
  157.   }
  158.  
  159.   int mdif;
  160.   mdif = a.exp - b.exp;
  161.   if (!mdif)
  162.     mdif = a.sigh - b.sigh;
  163.   if (!mdif)
  164.     mdif = a.sigl - b.sigl;
  165.  
  166.   switch (a.sign*2 + b.sign)
  167.   {
  168.     case 0: // P - P
  169.     case 3: // N - N
  170.       if (mdif > 0)
  171.       {
  172.         r_usub(a, b, d);
  173.         d.sign = a.sign;
  174.       }
  175.       else
  176.       {
  177.         r_usub(b, a, d);
  178.         d.sign = a.sign ^= SIGN_POS^SIGN_NEG;
  179.       }
  180.       break;
  181.     case 1: // P - N
  182.       r_uadd(a, b, d);
  183.       d.sign = SIGN_POS;
  184.       break;
  185.     case 2: // N - P
  186.       r_uadd(a, b, d);
  187.       d.sign = SIGN_NEG;
  188.       break;
  189.   }
  190. }
  191.  
  192. void r_mul(reg& a, reg& b, reg& s)
  193. {
  194.   if (a.tag == TW_Z)
  195.   {
  196.     r_mov(CONST_Z, s);
  197.   }
  198.   else if (b.tag == TW_Z)
  199.   {
  200.     r_mov(CONST_Z, s);
  201.   }
  202.   else if (a.tag == TW_S)
  203.   {
  204.     r_mov(a, s);
  205.   }
  206.   else if (b.tag == TW_S)
  207.   {
  208.     r_mov(b, s);
  209.   }
  210.   else
  211.   {
  212.     unsigned short sl[9], carry[10];
  213.     unsigned short *as = (unsigned short *)(&a.sigl);
  214.     unsigned short *bs = (unsigned short *)(&b.sigl);
  215.     unsigned long l, sum;
  216.     int ai, bi;
  217.     for (ai=0; ai<8; ai++)
  218.       sl[ai] = carry[ai] = 0;
  219.     for (ai = 0; ai < 4; ai++)
  220.       for (bi = 0; bi < 4; bi++)
  221.       {
  222.         l = as[ai] * bs[bi];
  223.  
  224.         sum = sl[ai+bi] + (l & 0xffff);
  225.         sl[ai+bi] = sum & 0xffff;
  226.  
  227.         sum = sl[ai+bi+1] + (l>>16) + (sum>>16);
  228.         sl[ai+bi+1] = sum & 0xffff;
  229.  
  230.         carry[ai+bi+2] += sum>>16;
  231.       }
  232.     for (ai=0; ai<8; ai++)
  233.     {
  234.       if (carry[ai])
  235.       {
  236.         sum = sl[ai] + carry[ai];
  237.         sl[ai] = sum & 0xffff;
  238.         carry[ai+1] += sum>>16;
  239.       }
  240.     }
  241.     s.sigl = *(long *)(sl+4);
  242.     s.sigh = *(long *)(sl+6);
  243.     s.exp = a.exp + b.exp - EXP_BIAS + 1;
  244.     s.tag = TW_V;
  245.   }
  246.   if (a.sign == b.sign)
  247.     s.sign = SIGN_POS;
  248.   else
  249.     s.sign = SIGN_NEG;
  250.   normalize(s);
  251. }
  252.  
  253. void r_div(reg& a, reg& b, reg& q)
  254. {
  255.   if (a.tag == TW_S)
  256.   {
  257.     if (val_same(a, CONST_PINF))
  258.       r_mov(a, q);
  259.     else if (val_same(a, CONST_NINF))
  260.       r_mov(a, q);
  261.   }
  262.   else if (b.tag == TW_S)
  263.   {
  264.     if (val_same(b, CONST_PINF))
  265.       r_mov(CONST_Z, q);
  266.     else if (val_same(b, CONST_NINF))
  267.       r_mov(CONST_Z, q);
  268.   }
  269.   else if (a.tag == TW_Z)
  270.   {
  271.     r_mov(a, q);
  272.   }
  273.   else if (b.tag == TW_Z)
  274.   {
  275.     exception(EX_Z);
  276.   }
  277.   else
  278.   {
  279.     q.exp = a.exp - b.exp + EXP_BIAS;
  280.     if (q.exp > EXP_MAX)
  281.       r_mov(CONST_PINF, q);
  282.     else if (q.exp <= 0)
  283.       r_mov(CONST_Z, q);
  284.     else
  285.     {
  286.       unsigned long long al, bl, ql, f;
  287.       int i;
  288.       al = *(unsigned long long *)(&a.sigl);
  289.       bl = *(unsigned long long *)(&b.sigl);
  290.       ql = 0;
  291.       f = (unsigned long long)1 << 63;
  292.       for (i=0; i<64; i++)
  293.       {
  294.         if (al >= bl)
  295.         {
  296.           al -= bl;
  297.           ql += f;
  298.         }
  299.         bl >>= 1;
  300.         f >>= 1;
  301.       }
  302.       *(unsigned long long *)(&q.sigl) = ql;
  303.       q.tag = TW_V;
  304.     }
  305.   }
  306.   if (a.sign == b.sign)
  307.     q.sign = SIGN_POS;
  308.   else
  309.     q.sign = SIGN_NEG;
  310.   normalize(q);
  311. }
  312.