home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libemu / emu387.cc next >
Encoding:
C/C++ Source or Header  |  1996-09-19  |  62.4 KB  |  3,534 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <signal.h>
  5. #include <setjmp.h>
  6.  
  7. extern char __libemu_ident_string[];
  8. static char *id = __libemu_ident_string;
  9.  
  10. #define EXP_BIAS 16383
  11. #define EXP_MAX 32766
  12.  
  13. #define SIGN_POS    0
  14. #define SIGN_NEG    1
  15.  
  16. #define TW_V    0    // valid
  17. #define TW_Z    1    // zero
  18. #define TW_S    2    // special
  19. #define TW_E    3    // empty
  20.  
  21. #define EX_SO    0x02C1    // stack overflow
  22. #define EX_SU    0x00C1    // stack underflow
  23. #define EX_P    0x00A0    // loss of precision
  24. #define EX_U    0x0090    // underflow
  25. #define EX_O    0x0088    // overflow
  26. #define EX_Z    0x0084    // divide by zero
  27. #define EX_D    0x0082    // denormalized operand
  28. #define EX_I    0x0081    // invalid operation
  29.  
  30. #define SW_B    0x8000    // backward compatibility (=ES)
  31. #define SW_C3    0x4000    // condition bit 3
  32. #define SW_TOP    0x3800    // top of stack
  33. #define SW_TOPS 0x0800    // scale for TOS
  34. #define SW_C2    0x0400    // condition bit 2
  35. #define SW_C1    0x0200    // condition bit 1
  36. #define SW_C0    0x0100    // condition bit 0
  37. #define SW_ES    0x0080    // exception summary
  38. #define SW_SF    0x0040    // stack fault
  39. #define SW_PE    0x0020    // loss of precision
  40. #define SW_UE    0x0010    // underflow
  41. #define SW_OE    0x0008    // overflow
  42. #define SW_ZE    0x0004    // divide by zero
  43. #define SW_DE    0x0002    // denormalized operand
  44. #define SW_IE    0x0001    // invalid operation
  45.  
  46. #define CW_RC    0x0C00    // rounding control
  47. #define CW_PC    0x0300    // precision control
  48. #define CW_PM    0x0020    // precision mask
  49. #define CW_UM    0x0010    // underflow mask
  50. #define CW_OM    0x0008    // overflow mask
  51. #define CW_ZM    0x0004    // divide by zero mask
  52. #define CW_DM    0x0002    // denormalized operand mask
  53. #define CW_IM    0x0001    // invalid operation mask
  54. #define CW_EXM    0x007f    // all masks
  55.  
  56. #define RC_RND    0x0000
  57. #define RC_DOWN    0x0400
  58. #define RC_UP    0x0800
  59. #define RC_CHOP    0x0C00
  60.  
  61. #define COMP_A_GT_B    1
  62. #define COMP_A_EQ_B    2
  63. #define COMP_A_LT_B    3
  64. #define COMP_NOCOMP    4
  65. #define COMP_NAN    0x40
  66. #define COMP_SNAN    0x80
  67.  
  68. #define NAN_NONE 0
  69. #define NAN_SNAN 1
  70. #define NAN_QNAN 2
  71.  
  72. struct reg {
  73.   char sign;
  74.   char tag;
  75.   short exp;
  76.   unsigned sigl;
  77.   unsigned sigh;
  78. };
  79.  
  80. typedef void (*FUNC)();
  81.  
  82. static int modrm;
  83. static unsigned eax;
  84. static unsigned ebx;
  85. static unsigned ecx;
  86. static unsigned edx;
  87. static unsigned esi;
  88. static unsigned edi;
  89. static unsigned ebp;
  90. static unsigned esp;
  91. static unsigned char *eip;
  92.  
  93. static jmp_buf jumpbuf;
  94.  
  95. static int status_word = 0;
  96. static int control_word = 0x77e;
  97. static reg regs[8] = {
  98.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  99.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  100.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  101.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  102.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  103.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  104.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  105.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  106. };
  107. static int top = 0;
  108.  
  109. static reg CONST_1 = { SIGN_POS, TW_V, EXP_BIAS, 0x00000000, 0x80000000 };
  110. static reg CONST_L2T = { SIGN_POS, TW_V, EXP_BIAS+1, 0xcd1b8afe, 0xd49a784b };
  111. static reg CONST_L2E = { SIGN_POS, TW_V, EXP_BIAS, 0x5c17f0bc, 0xb8aa3b29 };
  112. static reg CONST_PI = { SIGN_POS, TW_V, EXP_BIAS+1, 0x2168c235, 0xc90fdaa2 };
  113. static reg CONST_PI2 = { SIGN_POS, TW_V, EXP_BIAS, 0x2168c235, 0xc90fdaa2 };
  114. static reg CONST_LG2 = { SIGN_POS, TW_V, EXP_BIAS-2, 0xfbcff799, 0x9a209a84 };
  115. static reg CONST_LN2 = { SIGN_POS, TW_V, EXP_BIAS-1, 0xd1cf79ac, 0xb17217f7 };
  116. static reg CONST_Z = { SIGN_POS, TW_Z, 0, 0x0, 0x0 };
  117.  
  118. static reg CONST_PINF = { SIGN_POS, TW_S, EXP_MAX+1, 0x00000000, 0x80000000 };
  119. static reg CONST_NINF = { SIGN_NEG, TW_S, EXP_MAX+1, 0x00000000, 0x80000000 };
  120. static reg CONST_NAN = { SIGN_NEG, TW_S, EXP_MAX+1, 0x00000000, 0xC0000000 };
  121.  
  122. inline reg& st(int which=0) { return regs[(top+which)&7]; }
  123.  
  124. extern "C" _write(int,void*,int);
  125.  
  126. static inline int val_same(reg& a, reg& b)
  127. {
  128.   if (a.sign != b.sign || a.exp != b.exp || a.sigl != b.sigl || a.sigh != b.sigh)
  129.     return 0;
  130.   return 1;
  131. }
  132.  
  133. static inline int is_zero(reg a)
  134. {
  135.   return (a.exp == 0 && a.sigl == 0 && a.sigh == 0);
  136. }
  137.  
  138. #ifndef eprintf
  139. static void eprintf(const char *f, ...)
  140. {
  141.   char buf[1000];
  142.   vsprintf(buf, f, (&f)+1);
  143.   _write(1, buf, strlen(buf));
  144. }
  145. #endif
  146.  
  147. /* extern "C" void djshld(void *); */
  148. #define djshld(q) ((*(long long unsigned *)(q)) <<= 1)
  149. #define djshrd(q) ((*(long long unsigned *)(q)) >>= 1)
  150.  
  151. static int nan_type(reg& r)
  152. {
  153.   if (r.exp != EXP_MAX+1)
  154.     return NAN_NONE;
  155.   if (r.sigh & 0x40000000)
  156.     return NAN_QNAN;
  157.   return NAN_SNAN;
  158. }
  159.  
  160. static int compare(reg& a, reg& b)
  161. {
  162.   int a_inf, b_inf; // 0=no, 1=pos, -1=neg
  163.   a_inf = 0;
  164.   if (val_same(a, CONST_PINF))
  165.     a_inf = 1;
  166.   else if (val_same(a, CONST_NINF))
  167.     a_inf = -1;
  168.   b_inf = 0;
  169.   if (val_same(b, CONST_PINF))
  170.     b_inf = 1;
  171.   else if (val_same(b, CONST_NINF))
  172.     b_inf = -1;
  173.   if (a_inf || b_inf)
  174.   {
  175.     if (a_inf == 1)
  176.       if (b_inf == 1)
  177.         return COMP_A_EQ_B;
  178.       else
  179.         return COMP_A_GT_B;
  180.     if (b_inf == 1)
  181.       return COMP_A_LT_B;
  182.  
  183.     if (a_inf == -1)
  184.       if (b_inf == -1)
  185.         return COMP_A_EQ_B;
  186.       else
  187.         return COMP_A_LT_B;
  188.     if (b_inf == -1)
  189.       return COMP_A_GT_B;
  190.   }
  191.   int a_nan = nan_type(a);
  192.   int b_nan = nan_type(b);
  193.   if (a_nan || b_nan)
  194.   {
  195.     if ((a_nan == NAN_SNAN) || (b_nan == NAN_SNAN))
  196.       return COMP_NOCOMP | COMP_SNAN | COMP_NAN;
  197.     return COMP_NOCOMP | COMP_NAN;
  198.   }
  199.   if (a.sign != b.sign)
  200.   {
  201.     if ((a.tag == TW_Z) && (b.tag == TW_Z))
  202.       return COMP_A_EQ_B;
  203.     if (a.sign == SIGN_POS)
  204.       return COMP_A_GT_B;
  205.     return COMP_A_LT_B;
  206.   }
  207.   while (!(a.sigh & 0x80000000))
  208.   {
  209.     if (!a.exp)
  210.       break;
  211.     djshld(&a.sigl);
  212.     a.exp--;
  213.   }
  214.   while (!(b.sigh & 0x80000000))
  215.   {
  216.     if (!b.exp)
  217.       break;
  218.     djshld(&b.sigl);
  219.     b.exp--;
  220.   }
  221.   int diff = a.exp - b.exp;
  222.   if (diff == 0) diff = a.sigh - b.sigh;
  223.   if (diff == 0) diff = a.sigl - b.sigl;
  224.   if (a.sign == SIGN_NEG)
  225.     diff = -diff;
  226.   if (diff > 0) return COMP_A_GT_B;
  227.   if (diff < 0) return COMP_A_LT_B;
  228.   return COMP_A_EQ_B;
  229. }
  230.  
  231. static void emu_printall()
  232. {
  233.   static const char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
  234.   status_word = status_word & ~SW_TOP;
  235.   status_word += (top&7) * SW_TOPS;
  236.   eprintf("  SW: 0x%04x  top=%d cc=%d%d%d%d    ", status_word, top&7,
  237.     status_word & SW_C3?1:0, status_word & SW_C2?1:0,
  238.     status_word & SW_C1?1:0, status_word & SW_C0?1:0);
  239.   eprintf("CW: 0x%04x\r\n", control_word);
  240.   for (int i=0; i<8; i++)
  241.   {
  242.     reg *r = &st(i);
  243.     switch (r->tag)
  244.     {
  245.       case TW_E:
  246.         continue;
  247.         eprintf("st(%d)                                ", i);
  248.         break;
  249.       case TW_Z:
  250.         eprintf("st(%d) %c .0000 0000 0000 0000         ",
  251.                 i, r->sign ? '-' : '+');
  252.         break;
  253.       case TW_S:
  254.       case TW_V:
  255.         eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
  256.           r->sign ? '-' : '+',
  257.           (long)(r->sigh >> 16),
  258.           (long)(r->sigh & 0xFFFF),
  259.           (long)(r->sigl >> 16),
  260.           (long)(r->sigl & 0xFFFF),
  261.           r->exp - EXP_BIAS + 1);
  262.     }
  263.     eprintf("%s\r\n", tag_desc[r->tag]);
  264.   }
  265. }
  266.  
  267. static struct {
  268.   int type;
  269.   const char *name;
  270. } ex_names[] = {
  271.   { EX_SO, "stack overflow" },
  272.   { EX_SU, "stack underflow" },
  273.   { EX_P, "loss of precision" },
  274.   { EX_U, "underflow" },
  275.   { EX_O, "overflow" },
  276.   { EX_Z, "divide by zero" },
  277.   { EX_D, "denormalized operand" },
  278.   { EX_I, "invalid operation" },
  279.   { 0,0 }
  280. };
  281.  
  282. static void exception(int n)
  283. {
  284.   int i;
  285.   status_word |= n;
  286.   if (n == EX_SU)
  287.     status_word &= ~SW_C1;
  288.   for (i=0; ex_names[i].type; i++)
  289.     if (ex_names[i].type == n)
  290.       break;
  291.   if (~control_word & n & CW_EXM)
  292.   {
  293.     if (ex_names[i].type)
  294.       eprintf("80387 Exception: %s!\r\n", ex_names[i].name);
  295.     else
  296.       eprintf("80387 Exception: 0x%04x!\r\n", n);
  297.     emu_printall();
  298.     
  299.     longjmp(jumpbuf,1);
  300.   }
  301. }
  302.  
  303. static void emu_bad()
  304. {
  305.   eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
  306.   if (eip[-1] > 0277)
  307.     eprintf(" %02x", eip[-1]);
  308.   else
  309.     eprintf(" /%d", (eip[-1]>>3)&7);
  310.   eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
  311.   if (eip[-1] > 0277)
  312.     eprintf(" s%d", eip[-1]&7);
  313.   eprintf("\r\n");
  314.   exception(EX_I);
  315. }
  316.  
  317. static void setcc(int cc)
  318. {
  319.   status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
  320.   status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
  321. }
  322.  
  323. static int full()
  324. {
  325.   if (st(7).tag != TW_E)
  326.   {
  327.     exception(EX_SO);
  328.     top--;
  329.     st(0) = CONST_NAN;
  330.     return 1;
  331.   }
  332.   return 0;
  333. }
  334.  
  335. static int empty(int i=0)
  336. {
  337.   if (st(i).tag == TW_E)
  338.   {
  339.     exception(EX_SU);
  340.     return 1;
  341.   }
  342.   return 0;
  343. }
  344.  
  345. static int sregval(int reg1, int mod)
  346. {
  347.   switch (reg1)
  348.   {
  349.     case 0: return eax;
  350.     case 1: return ecx;
  351.     case 2: return edx;
  352.     case 3: return ebx;
  353.     case 4: return (mod==-1) ? 0 : esp;
  354.     case 5: return mod ? ebp : 0; // data
  355.     case 6: return esi;
  356.     case 7: return edi;
  357.   }
  358.   return 0;
  359. }
  360.  
  361. static int scale[] = { 1, 2, 4, 8 };
  362.  
  363. static int getsib()
  364. {
  365.   int mod = modrm >> 6;
  366.   int sib = *eip++;
  367.   int ss = sib>>6;
  368.   int index = (sib>>3) & 7;
  369.   int base = sib & 7;
  370.   int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
  371.   int rv2;
  372.   switch (mod)
  373.   {
  374.     case 1:
  375.       rv2 = *(signed char *)eip++;
  376.       rv += rv2;
  377.       break;
  378.     case 0:
  379.       if (base != 5)
  380.         break;
  381.     case 2:
  382.       ((unsigned char *)&rv2)[0] = *eip++;
  383.       ((unsigned char *)&rv2)[1] = *eip++;
  384.       ((unsigned char *)&rv2)[2] = *eip++;
  385.       ((unsigned char *)&rv2)[3] = *eip++;
  386.       rv += rv2;
  387.       break;
  388.   }
  389.   return rv;
  390. }
  391.  
  392. static int regval(int reg1, int mod)
  393. {
  394.   switch (reg1)
  395.   {
  396.     case 0: return eax;
  397.     case 1: return ecx;
  398.     case 2: return edx;
  399.     case 3: return ebx;
  400.     case 4: return getsib();
  401.     case 5: return mod ? ebp : 0; // data
  402.     case 6: return esi;
  403.     case 7: return edi;
  404.   }
  405.   return 0;
  406. }
  407.  
  408. static void *get_modrm()
  409. {
  410.   int mod = modrm>>6;
  411.   int rm = modrm & 7;
  412.   int rv;
  413.   switch (mod)
  414.   {
  415.     case 0:
  416.       if (rm == 5)
  417.       {
  418.         ((unsigned char *)&rv)[0] = *eip++;
  419.         ((unsigned char *)&rv)[1] = *eip++;
  420.         ((unsigned char *)&rv)[2] = *eip++;
  421.         ((unsigned char *)&rv)[3] = *eip++;
  422.       }
  423.       else
  424.         rv = regval(rm, mod);
  425.       break;
  426.     case 1:
  427.       if (rm != 4)
  428.         rv = (*(signed char *)eip++) + regval(rm, mod);
  429.       else
  430.         rv = regval(rm, mod);
  431.       break;
  432.     case 2:
  433.       if (rm != 4)
  434.       {
  435.         ((unsigned char *)&rv)[0] = *eip++;
  436.         ((unsigned char *)&rv)[1] = *eip++;
  437.         ((unsigned char *)&rv)[2] = *eip++;
  438.         ((unsigned char *)&rv)[3] = *eip++;
  439.         rv += regval(rm, mod);
  440.       }
  441.       else
  442.         rv = regval(rm, mod);
  443.       break;
  444.     case 3:
  445.       eprintf("Attempt to get address from mod = 3\r\n");
  446.       longjmp(jumpbuf,1);
  447.   }
  448. //  eprintf("modrm returning 0x%x\r\n", rv);
  449.   return (void *)rv;
  450. }
  451.  
  452.  
  453.  
  454. static void r_uadd(reg& a, reg& b, reg& s) // signs ignored
  455. {
  456.   reg t;
  457.   int dif = a.exp - b.exp;
  458.   if (!dif) dif = a.sigh - b.sigh;
  459.   if (!dif) dif = a.sigl - b.sigl;
  460.   if (dif > 0)
  461.   {
  462.     s = a;
  463.     t = b;
  464.   }
  465.   else
  466.   {
  467.     s = b;
  468.     t = a;
  469.   }
  470.   if (s.exp - t.exp > 64)
  471.     return;
  472.   while (t.exp < s.exp)
  473.   {
  474.     t.exp ++;
  475.     djshrd(&t.sigl);
  476.   }
  477.   unsigned short *ss, *ts;
  478.   unsigned long tmp;
  479.   ss = (unsigned short *)&s.sigl;
  480.   ts = (unsigned short *)&t.sigl;
  481.   tmp = 0;
  482.   for (int i=4; i>0; i--)
  483.   {
  484.     tmp += (unsigned long)*ss + (unsigned long)*ts;
  485.     *ss = tmp;
  486.     ss++;
  487.     ts++;
  488.     tmp >>= 16;
  489.   }
  490.   if (tmp)
  491.   {
  492.     djshrd(&s.sigl);
  493.     s.exp++;
  494.     s.sigh |= 0x80000000;
  495.   }
  496.   if (!(s.sigh | s.sigl))
  497.   {
  498.     s.exp = 0;
  499.     s.tag = TW_Z;
  500.   }
  501.   else
  502.   {
  503.     while (!(s.sigh & 0x80000000))
  504.     {
  505.       if (s.exp == 0)
  506.         return;
  507.       djshld(&s.sigl);
  508.       s.exp--;
  509.     }
  510.   }
  511. }
  512.  
  513. static void r_usub(reg& a, reg& b, reg& d) // a > b
  514. {
  515.   reg t;
  516.   d = a;
  517.   t = b;
  518.  
  519.   if (d.exp - t.exp > 64)
  520.     return;
  521.   while (t.exp < d.exp)
  522.   {
  523.     t.exp ++;
  524.     djshrd(&t.sigl);
  525.   }
  526.   unsigned short *ss, *ts;
  527.   long tmp;
  528.   ss = (unsigned short *)&d.sigl;
  529.   ts = (unsigned short *)&t.sigl;
  530.   tmp = 0;
  531.   for (int i=4; i>0; i--)
  532.   {
  533.     tmp += (long)*ss - (long)*ts;
  534.     *ss = tmp;
  535.     ss++;
  536.     ts++;
  537.     tmp >>= 16;
  538.   }
  539.   if (!(d.sigh | d.sigl))
  540.   {
  541.     d.exp = 0;
  542.     d.tag = TW_Z;
  543.   }
  544.   else
  545.   {
  546.     while (!(d.sigh & 0x80000000))
  547.     {
  548.       if (d.exp == 0)
  549.         return;
  550.       djshld(&d.sigl);
  551.       d.exp--;
  552.     }
  553.   }
  554. }
  555.  
  556. static void r_sub(reg& a, reg& b, reg& d)
  557. {
  558.   if (b.tag == TW_Z)
  559.   {
  560.     d = a;
  561.     return;
  562.   }
  563.   if (a.tag == TW_Z)
  564.   {
  565.     d = b;
  566.     d.sign ^= SIGN_POS^SIGN_NEG;
  567.     return;
  568.   }
  569.   if (a.tag == TW_S)
  570.   {
  571.     d = a;
  572.     return;
  573.   }
  574.   if (b.tag == TW_S)
  575.   {
  576.     d = b;
  577.     d.sign ^= SIGN_POS^SIGN_NEG;
  578.     return;
  579.   }
  580.  
  581.   int mdif;
  582.   mdif = a.exp - b.exp;
  583.   if (!mdif)
  584.     mdif = a.sigh - b.sigh;
  585.   if (!mdif)
  586.     mdif = a.sigl - b.sigl;
  587.  
  588.   switch (a.sign*2 + b.sign)
  589.   {
  590.     case 0: // P - P
  591.     case 3: // N - N
  592.       if (mdif > 0)
  593.       {
  594.         r_usub(a, b, d);
  595.         d.sign = a.sign;
  596.       }
  597.       else
  598.       {
  599.         r_usub(b, a, d);
  600.         d.sign = a.sign ^ SIGN_POS^SIGN_NEG;
  601.       }
  602.       break;
  603.     case 1: // P - N
  604.       r_uadd(a, b, d);
  605.       d.sign = SIGN_POS;
  606.       break;
  607.     case 2: // N - P
  608.       r_uadd(a, b, d);
  609.       d.sign = SIGN_NEG;
  610.       break;
  611.   }
  612. }
  613.  
  614. static void r_add(reg& a, reg& b, reg& s)
  615. {
  616.   char old_sign;
  617.   if (a.tag == TW_Z)
  618.   {
  619.     s = b;
  620.     return;
  621.   }
  622.   if (b.tag == TW_Z)
  623.   {
  624.     s = a;
  625.     return;
  626.   }
  627.   if (a.tag == TW_S)
  628.   {
  629.     s = a;
  630.     return;
  631.   }
  632.   if (b.tag == TW_S)
  633.   {
  634.     s = b;
  635.     return;
  636.   }
  637.  
  638.   switch (a.sign*2 + b.sign)
  639.   {
  640.     case 0: // P + P
  641.     case 3: // N + N
  642.       r_uadd(a, b, s);
  643.       s.sign = a.sign;
  644.       break;
  645.     case 1: // P + N
  646.       old_sign = b.sign;
  647.       b.sign ^= SIGN_POS^SIGN_NEG;
  648.       r_sub(a, b, s);
  649.       b.sign = old_sign;
  650.       break;
  651.     case 2: // N + P
  652.       old_sign = a.sign;
  653.       a.sign ^= SIGN_POS^SIGN_NEG;
  654.       r_sub(b, a, s);
  655.       a.sign = old_sign;
  656.       break;
  657.   }
  658. }
  659.  
  660. static void normalize(reg& r)
  661. {
  662.   if (!(r.sigl | r.sigh))
  663.   {
  664.     r.exp = 0;
  665.     r.tag = TW_Z;
  666.     return;
  667.   }
  668.   if (r.exp > EXP_MAX)
  669.   {
  670.     r.tag = TW_S;
  671.     return;
  672.   }
  673.   while (!(r.sigh & 0x80000000))
  674.   {
  675.     if (r.exp == 0)
  676.       return;
  677.     djshld(&r.sigl);
  678.     r.exp--;
  679.   }
  680. }
  681.  
  682. static void r_mul(reg& a, reg& b, reg& s)
  683. {
  684.   if (a.tag == TW_Z)
  685.   {
  686.     s = CONST_Z;
  687.   }
  688.   else if (b.tag == TW_Z)
  689.   {
  690.     s = CONST_Z;
  691.   }
  692.   else if (a.tag == TW_S)
  693.   {
  694.     s = a;
  695.   }
  696.   else if (b.tag == TW_S)
  697.   {
  698.     s = b;
  699.   }
  700.   else
  701.   {
  702.     unsigned short sl[9], carry[10];
  703.     unsigned short *as = (unsigned short *)(&a.sigl);
  704.     unsigned short *bs = (unsigned short *)(&b.sigl);
  705.     unsigned long l, sum;
  706.     int ai, bi;
  707.     for (ai=0; ai<8; ai++)
  708.       sl[ai] = carry[ai] = 0;
  709.     for (ai = 0; ai < 4; ai++)
  710.       for (bi = 0; bi < 4; bi++)
  711.       {
  712.         l = as[ai] * bs[bi];
  713.  
  714.         sum = sl[ai+bi] + (l & 0xffff);
  715.         sl[ai+bi] = sum & 0xffff;
  716.  
  717.         sum = sl[ai+bi+1] + (l>>16) + (sum>>16);
  718.         sl[ai+bi+1] = sum & 0xffff;
  719.  
  720.         carry[ai+bi+2] += sum>>16;
  721.       }
  722.     for (ai=0; ai<8; ai++)
  723.     {
  724.       if (carry[ai])
  725.       {
  726.         sum = sl[ai] + carry[ai];
  727.         sl[ai] = sum & 0xffff;
  728.         carry[ai+1] += sum>>16;
  729.       }
  730.     }
  731.     s.sigl = *(long *)(sl+4);
  732.     s.sigh = *(long *)(sl+6);
  733.     s.exp = a.exp + b.exp - EXP_BIAS + 1;
  734.     s.tag = TW_V;
  735.   }
  736.   if (a.sign == b.sign)
  737.     s.sign = SIGN_POS;
  738.   else
  739.     s.sign = SIGN_NEG;
  740.   normalize(s);
  741. }
  742.  
  743. static void r_div(reg& a, reg& b, reg& q)
  744. {
  745.   if (a.tag == TW_S)
  746.   {
  747.     if (val_same(a, CONST_PINF))
  748.       q = a;
  749.     else if (val_same(a, CONST_NINF))
  750.       q = a;
  751.   }
  752.   else if (b.tag == TW_S)
  753.   {
  754.     if (val_same(b, CONST_PINF))
  755.       q = CONST_Z;
  756.     else if (val_same(b, CONST_NINF))
  757.       q = CONST_Z;
  758.   }
  759.   else if (a.tag == TW_Z)
  760.   {
  761.     q = a;
  762.   }
  763.   else if (b.tag == TW_Z)
  764.   {
  765.     exception(EX_Z);
  766.   }
  767.   else
  768.   {
  769.     q.exp = a.exp - b.exp + EXP_BIAS;
  770.     if (q.exp > EXP_MAX)
  771.       q = CONST_PINF;
  772.     else if (q.exp <= 0)
  773.       q = CONST_Z;
  774.     else
  775.     {
  776.       unsigned long long al, bl, ql, f;
  777.       int i;
  778.       al = *(unsigned long long *)(&a.sigl);
  779.       bl = *(unsigned long long *)(&b.sigl);
  780.       ql = 0;
  781.       f = (unsigned long long)1 << 63;
  782.       for (i=0; i<64; i++)
  783.       {
  784.         if (al >= bl)
  785.         {
  786.           al -= bl;
  787.           ql += f;
  788.         }
  789.         bl >>= 1;
  790.         f >>= 1;
  791.       }
  792.       *(unsigned long long *)(&q.sigl) = ql;
  793.       q.tag = TW_V;
  794.     }
  795.   }
  796.   if (a.sign == b.sign)
  797.     q.sign = SIGN_POS;
  798.   else
  799.     q.sign = SIGN_NEG;
  800.   normalize(q);
  801. }
  802.  
  803. static void r_mov(long double *s, reg& d)
  804. {
  805.   unsigned long *sp = (unsigned long *)s;
  806.   if (sp[2] & 0x8000)
  807.     d.sign = SIGN_NEG;
  808.   else
  809.     d.sign = SIGN_POS;
  810.   d.exp = sp[2] & 0x7fff;
  811.   d.sigh = sp[1];
  812.   d.sigl = sp[0];
  813.   d.tag = TW_V;
  814.   normalize(d);
  815. }
  816.  
  817. static void r_mov(double *s, reg& d)
  818. {
  819.   unsigned m64 = ((unsigned *)s)[1];
  820.   unsigned l64 = ((unsigned *)s)[0];
  821.   if (m64 & 0x80000000)
  822.     d.sign = SIGN_NEG;
  823.   else
  824.     d.sign = SIGN_POS;
  825.   if (!((m64 & 0x7fffffff) | (l64)))
  826.   {
  827.     int c = d.sign;
  828.     d = CONST_Z;
  829.     d.sign = c;
  830.     return;
  831.   }
  832.   d.exp = (int)((m64>>20)&0x7ff) - 1023 + EXP_BIAS;
  833.   d.sigh = ((m64 & 0xfffff)<<11) | 0x80000000;
  834.   d.sigh |= l64 >> 21;
  835.   d.sigl = l64 << 11;
  836.   d.tag = TW_V;
  837.   if ((m64 & 0x7ff00000) == 0x7ff00000)
  838.     d.exp = EXP_MAX+1;
  839.   normalize(d);
  840. }
  841.  
  842. static void r_mov(float *s, reg& d)
  843. {
  844.   unsigned m32 = *(unsigned *)s;
  845.   if (m32 & 0x80000000)
  846.     d.sign = SIGN_NEG;
  847.   else
  848.     d.sign = SIGN_POS;
  849.   if (!(m32 & 0x7fffffff))
  850.   {
  851.     int c = d.sign;
  852.     d = CONST_Z;
  853.     d.sign = c;
  854.     return;
  855.   }
  856.   d.exp = (int)((m32>>23)&0xff) - 127 + EXP_BIAS;
  857.   d.sigh = ((m32 & 0x7fffff)<<8) | 0x80000000;
  858.   d.sigl = 0;
  859.   d.tag = TW_V;
  860.   if ((m32 & 0x7f800000) == 0x7f800000)
  861.     d.exp = EXP_MAX+1;
  862.   normalize(d);
  863. }
  864.  
  865. static void r_mov(long long *_s, reg& d)
  866. {
  867.   long long s = *_s;
  868.   if (s == 0)
  869.   {
  870.     d = CONST_Z;
  871.     return;
  872.   }
  873.  
  874.   if (s > 0)
  875.     d.sign = SIGN_POS;
  876.   else
  877.   {
  878.     s = -s;
  879.     d.sign = SIGN_NEG;
  880.   }
  881.  
  882.   int e = EXP_BIAS + 63;
  883.   while (s >= 0)
  884.   {
  885.     djshld(&s);
  886.     e -= 1;
  887.   }
  888.   d.sigh = s >> 32;
  889.   d.sigl = s;
  890.   d.exp = e;
  891.   d.tag = TW_V;
  892.   normalize(d);
  893. }
  894.  
  895. static void r_mov(long *_s, reg& d)
  896. {
  897.   long s = *_s;
  898.   if (s == 0)
  899.   {
  900.     d = CONST_Z;
  901.     return;
  902.   }
  903.  
  904.   if (s > 0)
  905.     d.sign = SIGN_POS;
  906.   else
  907.   {
  908.     s = -s;
  909.     d.sign = SIGN_NEG;
  910.   }
  911.  
  912.   int e = EXP_BIAS + 31;
  913.   while (!(s & 0x80000000))
  914.   {
  915.     s <<= 1;
  916.     e -= 1;
  917.   }
  918.   d.sigh = s;
  919.   d.sigl = 0;
  920.   d.exp = e;
  921.   d.tag = TW_V;
  922.   normalize(d);
  923. }
  924.  
  925. static void r_mov(short *_s, reg& d)
  926. {
  927.   int s = *_s;
  928.   if (s == 0)
  929.   {
  930.     d = CONST_Z;
  931.     return;
  932.   }
  933.  
  934.   if (s > 0)
  935.     d.sign = SIGN_POS;
  936.   else
  937.   {
  938.     s = -s;
  939.     d.sign = SIGN_NEG;
  940.   }
  941.  
  942.   int e = EXP_BIAS + 15;
  943.   while (!(s & 0x8000))
  944.   {
  945.     s <<= 1;
  946.     e -= 1;
  947.   }
  948.   d.sigh = s << 16;
  949.   d.sigl = 0;
  950.   d.exp = e;
  951.   d.tag = TW_V;
  952.   normalize(d);
  953. }
  954.  
  955. static void r_mov(char *s, reg& d)
  956. {
  957.   int side=1, pos=8;
  958.   long long l;
  959.   l = 0;
  960.   for (int i=0; i<18; i++)
  961.   {
  962.     l *= 10;
  963.     switch (side)
  964.     {
  965.       case 0:
  966.         l += s[pos] & 0x0f;
  967.         side = 1;
  968.         pos--;
  969.         break;
  970.       case 1:
  971.         l += s[pos] >> 4;
  972.         side = 0;
  973.         break;
  974.     }
  975.   }
  976.   r_mov(&l, d);
  977.   if (s[9] & 0x80)
  978.     d.sign = SIGN_NEG;
  979. }
  980.  
  981. //=============================================================================
  982.  
  983. static void round_to_int(reg& r) // r gets mangled such that sig is int, sign
  984. {
  985.   int more_than_half = 0;
  986.   int half_or_more = 0;
  987.   if (r.tag == TW_Z)
  988.   {
  989.     return;
  990.   }
  991.   while (r.exp < EXP_BIAS+62)
  992.   {
  993.     if (r.sigl & 1)
  994.       more_than_half = 1;
  995.     djshrd(&r.sigl);
  996.     r.exp++;
  997.   }
  998.   while (r.exp < EXP_BIAS+63)
  999.   {
  1000.     if (r.sigl & 1)
  1001.       half_or_more = 1;
  1002.     djshrd(&r.sigl);
  1003.     r.exp++;
  1004.   }
  1005.   if (r.exp > EXP_BIAS+63)
  1006.   {
  1007.     r.sigl = r.sigh = ~0;
  1008.     return;
  1009.   }
  1010.   switch (control_word & CW_RC)
  1011.   {
  1012.     case RC_RND:
  1013.       if (half_or_more)
  1014.         if (more_than_half) // nearest
  1015.           (*(long long *)(&r.sigl)) ++;
  1016.         else
  1017.           if (r.sigl & 1) // odd?
  1018.             (*(long long *)(&r.sigl)) ++;
  1019.       break;
  1020.     case RC_DOWN:
  1021.       if ((half_or_more||more_than_half) && r.sign)
  1022.         (*(long long *)(&r.sigl)) ++;
  1023.       break;
  1024.     case RC_UP:
  1025.       if ((half_or_more||more_than_half) && !r.sign)
  1026.         (*(long long *)(&r.sigl)) ++;
  1027.       break;
  1028.     case RC_CHOP:
  1029.       break;
  1030.   }
  1031. }
  1032.  
  1033. static void r_mov(reg& s, long double *d)
  1034. {
  1035.   ((short *)d)[4] = s.exp + s.sign*0x8000;
  1036.   ((long *)d)[0] = s.sigl;
  1037.   ((long *)d)[1] = s.sigh;
  1038. }
  1039.  
  1040. static void r_mov(reg& s, double *d)
  1041. {
  1042.   unsigned long *l = (unsigned long *)d;
  1043.   if (s.tag == TW_Z)
  1044.   {
  1045.     l[0] = 0;
  1046.     l[1] = 0;
  1047.   }
  1048.   else
  1049.   {
  1050.     l[0] = (s.sigl >> 11) | (s.sigh << 21);
  1051.     l[1] = ((s.sigh >> 11) & 0xfffff) | (((s.exp-EXP_BIAS+1023) & 0x7ff) << 20);
  1052.   }
  1053.   if (s.sign)
  1054.     l[1] |= 0x80000000;
  1055. }
  1056.  
  1057. static void r_mov(reg& s, float *d)
  1058. {
  1059.   long f;
  1060.   if (s.tag == TW_Z)
  1061.   {
  1062.     f = 0;
  1063.   }
  1064.   else
  1065.   {
  1066.     f = (s.sigh >> 8) & 0x007fffff;
  1067.     f |= ((s.exp-EXP_BIAS+127) & 0xff) << 23;
  1068.   }
  1069.   if (s.sign)
  1070.     f |= 0x80000000;
  1071.   *(long *)d = f;
  1072. }
  1073.  
  1074. static void r_mov(reg& s, long long *d)
  1075. {
  1076.   reg t;
  1077.   t = s;
  1078.   round_to_int(t);
  1079.   ((long *)d)[0] = t.sigl;
  1080.   ((long *)d)[1] = t.sigh;
  1081.   if (t.sign)
  1082.     *d = - *d;
  1083. }
  1084.  
  1085. static void r_mov(reg& s, long *d)
  1086. {
  1087.   reg t;
  1088.   t = s;
  1089.   round_to_int(t);
  1090.   if (t.sigh || (t.sigl & 0x80000000))
  1091.     *d = -1;
  1092.   else
  1093.     *d = s.sign ? -t.sigl : t.sigl;
  1094. }
  1095.  
  1096. static void r_mov(reg& s, short *d)
  1097. {
  1098.   reg t;
  1099.   t = s;
  1100.   round_to_int(t);
  1101.   if (t.sigh || (t.sigl & 0xFFFF8000))
  1102.     *d = -1;
  1103.   else
  1104.     *d = s.sign ? -t.sigl : t.sigl;
  1105. }
  1106.  
  1107. static void r_mov(reg& s, char *d)
  1108. {
  1109.   reg t;
  1110.   t = s;
  1111.   round_to_int(t);
  1112.   long long ll = *(long long *)(&t.sigl);
  1113.   int side = 0;
  1114.   int r, i;
  1115.   for (i=0; i<10; i++)
  1116.     d[i] = 0;
  1117.   int pos=0;
  1118.   for (i=0; i<18; i++)
  1119.   {
  1120.     r = ll % 10;
  1121.     ll /= 10;
  1122.     if (side)
  1123.     {
  1124.       d[pos] |= r << 4;
  1125.       side = 0;
  1126.       pos++;
  1127.     }
  1128.     else
  1129.     {
  1130.       d[pos] |= r;
  1131.       side = 1;
  1132.     }
  1133.   }
  1134.   if (s.sign == SIGN_NEG)
  1135.     d[9] = 0x80;
  1136. }
  1137.  
  1138. static void emu_00()
  1139. {
  1140.   if (empty())
  1141.     return;
  1142.   if (modrm > 0277)
  1143.   {
  1144.     // fadd st,st(i)
  1145.     int i = modrm & 7;
  1146.     if (empty(i))
  1147.       return;
  1148.     reg tmp;
  1149.     r_add(st(), st(i), tmp);
  1150.     st() = tmp;
  1151.     return;
  1152.   }
  1153.   else
  1154.   {
  1155.     // fadd m32real
  1156.     reg t1, t2;
  1157.     r_mov((float *)get_modrm(), t1);
  1158.     r_add(t1, st(), t2);
  1159.     st() = t2;
  1160.   }
  1161. }
  1162.  
  1163. static void emu_01()
  1164. {
  1165.   if (empty())
  1166.     return;
  1167.   if (modrm > 0277)
  1168.   {
  1169.     // fmul st,st(i)
  1170.     int i = modrm & 7;
  1171.     if (empty(i))
  1172.       return;
  1173.     reg t;
  1174.     r_mul(st(), st(i), t);
  1175.     st() = t;
  1176.   }
  1177.   else
  1178.   {
  1179.     // fmul m32real
  1180.     reg t, t2;
  1181.     r_mov((float *)get_modrm(), t);
  1182.     r_mul(st(), t, t2);
  1183.     st() = t2;
  1184.   }
  1185. }
  1186.  
  1187. static void emu_02()
  1188. {
  1189.   if (empty())
  1190.     return;
  1191.   if (modrm > 0277)
  1192.   {
  1193.     // fcom st(i)
  1194.     if (empty(modrm&7))
  1195.     {
  1196.       setcc(SW_C3|SW_C2|SW_C0);
  1197.       return;
  1198.     }
  1199.     int c = compare(st(), st(modrm&7));
  1200.     int f;
  1201.     if (c & COMP_NAN)
  1202.     {
  1203.       exception(EX_I);
  1204.       f = SW_C3 | SW_C2 | SW_C0;
  1205.     }
  1206.     else
  1207.       switch (c)
  1208.       {
  1209.         case COMP_A_LT_B:
  1210.           f = SW_C0;
  1211.           break;
  1212.         case COMP_A_EQ_B:
  1213.           f = SW_C3;
  1214.           break;
  1215.         case COMP_A_GT_B:
  1216.           f = 0;
  1217.           break;
  1218.         case COMP_NOCOMP:
  1219.           f = SW_C3 | SW_C2 | SW_C0;
  1220.           break;
  1221.       }
  1222.     setcc(f);
  1223.     
  1224.   }
  1225.   else
  1226.   {
  1227.     // fcom m32real
  1228.     reg t;
  1229.     r_mov((float *)get_modrm(), t);
  1230.     int c = compare(st(), t);
  1231.     int f;
  1232.     if (c & COMP_NAN)
  1233.     {
  1234.       exception(EX_I);
  1235.       f = SW_C3 | SW_C2 | SW_C0;
  1236.     }
  1237.     else
  1238.       switch (c)
  1239.       {
  1240.         case COMP_A_LT_B:
  1241.           f = SW_C0;
  1242.           break;
  1243.         case COMP_A_EQ_B:
  1244.           f = SW_C3;
  1245.           break;
  1246.         case COMP_A_GT_B:
  1247.           f = 0;
  1248.           break;
  1249.         case COMP_NOCOMP:
  1250.           f = SW_C3 | SW_C2 | SW_C0;
  1251.           break;
  1252.       }
  1253.     setcc(f);
  1254.   }
  1255. }
  1256.  
  1257. static void emu_03()
  1258. {
  1259.   if (empty())
  1260.     return;
  1261.   if (modrm > 0277)
  1262.   {
  1263.     // fcomp st(i)
  1264.     if (empty(modrm&7))
  1265.     {
  1266.       setcc(SW_C3|SW_C2|SW_C0);
  1267.       return;
  1268.     }
  1269.     int c = compare(st(), st(modrm&7));
  1270.     st().tag = TW_E;
  1271.     top++;
  1272.     int f;
  1273.     if (c & COMP_NAN)
  1274.     {
  1275.       exception(EX_I);
  1276.       f = SW_C3 | SW_C2 | SW_C0;
  1277.     }
  1278.     else
  1279.       switch (c)
  1280.       {
  1281.         case COMP_A_LT_B:
  1282.           f = SW_C0;
  1283.           break;
  1284.         case COMP_A_EQ_B:
  1285.           f = SW_C3;
  1286.           break;
  1287.         case COMP_A_GT_B:
  1288.           f = 0;
  1289.           break;
  1290.         case COMP_NOCOMP:
  1291.           f = SW_C3 | SW_C2 | SW_C0;
  1292.           break;
  1293.       }
  1294.     setcc(f);
  1295.     
  1296.   }
  1297.   else
  1298.   {
  1299.     // fcom m32real
  1300.     reg t;
  1301.     r_mov((float *)get_modrm(), t);
  1302.     int c = compare(st(), t);
  1303.     st().tag = TW_E;
  1304.     top++;
  1305.     int f;
  1306.     if (c & COMP_NAN)
  1307.     {
  1308.       exception(EX_I);
  1309.       f = SW_C3 | SW_C2 | SW_C0;
  1310.     }
  1311.     else
  1312.       switch (c)
  1313.       {
  1314.         case COMP_A_LT_B:
  1315.           f = SW_C0;
  1316.           break;
  1317.         case COMP_A_EQ_B:
  1318.           f = SW_C3;
  1319.           break;
  1320.         case COMP_A_GT_B:
  1321.           f = 0;
  1322.           break;
  1323.         case COMP_NOCOMP:
  1324.           f = SW_C3 | SW_C2 | SW_C0;
  1325.           break;
  1326.       }
  1327.     setcc(f);
  1328.   }
  1329. }
  1330.  
  1331. static void emu_04()
  1332. {
  1333.   if (empty())
  1334.     return;
  1335.   if (modrm > 0277)
  1336.   {
  1337.     // fsub st,st(i)
  1338.     int i = modrm & 7;
  1339.     if (empty(i))
  1340.       return;
  1341.     reg tmp;
  1342.     r_sub(st(), st(i), tmp);
  1343.     st() = tmp;
  1344.     return;
  1345.   }
  1346.   else
  1347.   {
  1348.     // fsub m32real
  1349.     reg t1, t2;
  1350.     r_mov((float *)get_modrm(), t1);
  1351.     r_sub(st(), t1, t2);
  1352.     st() = t2;
  1353.   }
  1354. }
  1355.  
  1356. static void emu_05()
  1357. {
  1358.   if (empty())
  1359.     return;
  1360.   if (modrm > 0277)
  1361.   {
  1362.     // fsubr st,st(i)
  1363.     int i = modrm & 7;
  1364.     if (empty(i))
  1365.       return;
  1366.     reg tmp;
  1367.     r_sub(st(i), st(), tmp);
  1368.     st() = tmp;
  1369.     return;
  1370.   }
  1371.   else
  1372.   {
  1373.     // fsubr m32real
  1374.     reg t1, t2;
  1375.     r_mov((float *)get_modrm(), t1);
  1376.     r_sub(t1, st(), t2);
  1377.     st() = t2;
  1378.   }
  1379. }
  1380.  
  1381. static void emu_06()
  1382. {
  1383.   if (empty())
  1384.     return;
  1385.   if (modrm > 0277)
  1386.   {
  1387.     // fdiv st,st(i)
  1388.     int i = modrm & 7;
  1389.     if (empty(i))
  1390.       return;
  1391.     reg t;
  1392.     r_div(st(), st(i), t);
  1393.     st() = t;
  1394.   }
  1395.   else
  1396.   {
  1397.     // fdiv m32real
  1398.     reg t, t2;
  1399.     r_mov((float *)get_modrm(), t);
  1400.     r_div(st(), t, t2);
  1401.     st() = t2;
  1402.   }
  1403. }
  1404.  
  1405. static void emu_07()
  1406. {
  1407.   if (empty())
  1408.     return;
  1409.   if (modrm > 0277)
  1410.   {
  1411.     // fdivr st,st(i)
  1412.     int i = modrm & 7;
  1413.     if (empty(i))
  1414.       return;
  1415.     reg t;
  1416.     r_div(st(i), st(), t);
  1417.     st() = t;
  1418.   }
  1419.   else
  1420.   {
  1421.     // fdivr m32real
  1422.     reg t, t2;
  1423.     r_mov((float *)get_modrm(), t);
  1424.     r_div(t, st(), t2);
  1425.     st() = t2;
  1426.   }
  1427. }
  1428.  
  1429. static void emu_10()
  1430. {
  1431.   if (full())
  1432.     return;
  1433.   if (modrm > 0277)
  1434.   {
  1435.     // fld st(i)
  1436.     int i = modrm & 7;
  1437.     if (empty(i))
  1438.       return;
  1439.     st(7) = st(i);
  1440.     top--;
  1441.     return;
  1442.   }
  1443.   else
  1444.   {
  1445.     // fld m32real
  1446.     top--;
  1447.     r_mov((float *)get_modrm(), st());
  1448.   }
  1449. }
  1450.  
  1451. static void emu_11()
  1452. {
  1453.   if (empty())
  1454.     return;
  1455.   if (modrm > 0277)
  1456.   {
  1457.     // fxch st(i)
  1458.     int i = modrm & 7;
  1459.     if (empty(i))
  1460.       return;
  1461.     reg t;
  1462.     t = st();
  1463.     st() = st(i);
  1464.     st(i) = t;
  1465.   }
  1466.   else
  1467.   {
  1468.     emu_bad();
  1469.   }
  1470. }
  1471.  
  1472. static void fnop()
  1473. {
  1474. }
  1475.  
  1476. static FUNC emu_12_table[] = {
  1477.   fnop, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad
  1478. };
  1479.  
  1480. static void emu_12()
  1481. {
  1482.   if (modrm > 0277)
  1483.   {
  1484.     (emu_12_table[modrm&7])();
  1485.   }
  1486.   else
  1487.   {
  1488.     // fst m32real
  1489.     if (empty())
  1490.       return;
  1491.     r_mov(st(), (float *)get_modrm());
  1492.   }
  1493. }
  1494.  
  1495. static void emu_13()
  1496. {
  1497.   if (modrm > 0277)
  1498.   {
  1499.     emu_bad();
  1500.   }
  1501.   else
  1502.   {
  1503.     // fstp m32real
  1504.     if (empty())
  1505.       return;
  1506.     r_mov(st(), (float *)get_modrm());
  1507.     st().tag = TW_E;
  1508.     top++;
  1509.   }
  1510. }
  1511.  
  1512. static void fchs()
  1513. {
  1514.   if (empty())
  1515.     return;
  1516.   st().sign ^= SIGN_POS^SIGN_NEG;
  1517.   status_word &= ~SW_C1;
  1518. }
  1519.  
  1520. static void fabs()
  1521. {
  1522.   if (empty())
  1523.     return;
  1524.   st().sign = SIGN_POS;
  1525.   status_word &= ~SW_C1;
  1526. }
  1527.  
  1528. static void ftst()
  1529. {
  1530.   switch (st().tag)
  1531.   {
  1532.     case TW_Z:
  1533.       setcc(SW_C3);
  1534.       break;
  1535.     case TW_V:
  1536.       if (st().sign == SIGN_POS)
  1537.         setcc(0);
  1538.       else
  1539.         setcc(SW_C0);
  1540.       break;
  1541.     case TW_S:
  1542.       if (val_same(st(), CONST_PINF))
  1543.       {
  1544.         setcc(0);
  1545.         break;
  1546.       }
  1547.       else if (val_same(st(), CONST_NINF))
  1548.       {
  1549.         setcc(SW_C3);
  1550.         break;
  1551.       }
  1552.       setcc(SW_C0|SW_C2|SW_C3);
  1553.       exception(EX_I);
  1554.       break;
  1555.     case TW_E:
  1556.       setcc(SW_C0|SW_C2|SW_C3);
  1557.       exception(EX_SU);
  1558.       break;
  1559.   }
  1560. }
  1561.  
  1562. static void fxam()
  1563. {
  1564.   int c=0;
  1565.   switch (st().tag)
  1566.   {
  1567.     case TW_E:
  1568.       c = SW_C3|SW_C0;
  1569.       break;
  1570.     case TW_Z:
  1571.       c = SW_C3;
  1572.       break;
  1573.     case TW_V:
  1574.       if (st().sigh & 0x80000000)
  1575.         c = SW_C2;
  1576.       else
  1577.         c = SW_C3|SW_C2;
  1578.       break;
  1579.     case TW_S:
  1580.       if (val_same(st(), CONST_NAN))
  1581.         c = SW_C0;
  1582.       else if (val_same(st(), CONST_PINF))
  1583.         c = SW_C2|SW_C0;
  1584.       else if (val_same(st(), CONST_NINF))
  1585.         c = SW_C2|SW_C0;
  1586.       break;
  1587.   }
  1588.   if (st().sign == SIGN_NEG)
  1589.     c |= SW_C1;
  1590.   setcc(c);
  1591. }
  1592.  
  1593. static FUNC emu_14_table[] = {
  1594.   fchs, fabs, emu_bad, emu_bad, ftst, fxam, emu_bad, emu_bad
  1595. };
  1596.  
  1597. static void emu_14()
  1598. {
  1599.   if (modrm > 0277)
  1600.   {
  1601.     (emu_14_table[modrm&7])();
  1602.   }
  1603.   else
  1604.   {
  1605.     //
  1606.     emu_bad();
  1607.   }
  1608. }
  1609.  
  1610. static void fld_const(reg &c)
  1611. {
  1612.   if (full())
  1613.     return;
  1614.   top--;
  1615.   st() = c;
  1616.   status_word &= ~SW_C1;
  1617. }
  1618.  
  1619. static void fld1()
  1620. {
  1621.   fld_const(CONST_1);
  1622. }
  1623.  
  1624. static void fldl2t()
  1625. {
  1626.   fld_const(CONST_L2T);
  1627. }
  1628.  
  1629. static void fldl2e()
  1630. {
  1631.   fld_const(CONST_L2E);
  1632. }
  1633.  
  1634. static void fldpi()
  1635. {
  1636.   fld_const(CONST_PI);
  1637. }
  1638.  
  1639. static void fldlg2()
  1640. {
  1641.   fld_const(CONST_LG2);
  1642. }
  1643.  
  1644. static void fldln2()
  1645. {
  1646.   fld_const(CONST_LN2);
  1647. }
  1648.  
  1649. static void fldz()
  1650. {
  1651.   fld_const(CONST_Z);
  1652. }
  1653.  
  1654. static FUNC emu_15_table[] = {
  1655.   fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, emu_bad
  1656. };
  1657.  
  1658. static void emu_15()
  1659. {
  1660.   if (modrm > 0277)
  1661.   {
  1662.     (emu_15_table[modrm&7])();
  1663.   }
  1664.   else
  1665.   {
  1666.     // fldcw
  1667.     control_word = *(short *)get_modrm();
  1668.   }
  1669. }
  1670.  
  1671. static void f2xm1()
  1672. {
  1673.   if (empty())
  1674.     return;
  1675.   reg xloga, val, rv, bottom, tmp;
  1676.   long i;
  1677.  
  1678.   r_mul(CONST_LN2, st(), xloga);
  1679.   val = xloga;
  1680.   rv = xloga;
  1681.  
  1682.   for (i=2; i<16; i++)
  1683.   {
  1684.     r_mov(&i, bottom);
  1685.     r_mul(val, xloga, tmp);
  1686.     r_div(tmp, bottom, val);
  1687.     r_add(val, rv, tmp);
  1688.     rv = tmp;
  1689.   }
  1690.   st() = rv;
  1691. }
  1692.  
  1693. // logb(x) = loga(x) / loga(b)
  1694. // log2(x) = loge(x) / loge(2)
  1695.  
  1696. static void fyl2x()
  1697. {
  1698.   if (empty())
  1699.     return;
  1700.   reg z, x, nom, denom, xsquare, term, temp, sum, pow;
  1701.   long exponent;
  1702.   reg CONST_SQRT2 = { SIGN_POS, TW_V, EXP_BIAS, 0xf9de6000, 0xb504f333 };
  1703.  
  1704.   z = st();
  1705.   if ((z.tag != TW_V) || (z.sign != SIGN_POS)) {
  1706.     return exception(EX_I); // not valid, zero or negative
  1707.   }  
  1708.   exponent = (long)(z.exp - EXP_BIAS);
  1709.   z.exp=EXP_BIAS;
  1710.   if (compare(z, CONST_SQRT2) == COMP_A_GT_B) {
  1711.     (z.exp)--;
  1712.     exponent++;
  1713.   }
  1714.  
  1715.   r_sub(z, CONST_1, nom);
  1716.   r_add(z, CONST_1, denom);
  1717.   r_div(nom, denom, x);
  1718.   pow = x;
  1719.   sum = x;
  1720.   r_mul(x, x, xsquare);
  1721.   
  1722.   for (long i=3; i<25; i+=2)
  1723.   {
  1724.     r_mul(pow, xsquare, temp);
  1725.     pow = temp;
  1726.  
  1727.     r_mov(&i, denom);
  1728.     r_div(pow, denom, term);
  1729.  
  1730.     r_add(term, sum, temp);
  1731.     sum = temp;
  1732.   }
  1733.   r_div(sum, CONST_LN2, temp);
  1734.   temp.exp++;
  1735.   if (exponent) {
  1736.     r_mov(&exponent, term);
  1737.     r_add(term, temp, sum);
  1738.   } else {
  1739.     sum = temp;
  1740.   }
  1741.  
  1742.   r_mul(sum, st(1), temp);
  1743.   st(1) = temp;
  1744.   st().tag = TW_E;
  1745.   top++;
  1746. }
  1747.  
  1748. static int fprem_do(reg& quot, reg& div1, int round) // remainder of st() / st(1)
  1749. {
  1750.   int rv;
  1751.   int old_cw = control_word;
  1752.   control_word &= ~CW_RC;
  1753.   control_word |= round;
  1754.   int expdif = quot.exp - div1.exp;
  1755.   if (expdif < 64)
  1756.   {
  1757.     reg tmp, tmp2;
  1758.     r_div(quot, div1, tmp);
  1759.     long q;
  1760.     r_mov(tmp, &q);
  1761.     r_mov(&q, tmp);
  1762.     r_mul(div1, tmp, tmp2);
  1763.     r_sub(quot, tmp2, tmp);
  1764.     quot = tmp;
  1765.     rv = q & 7;
  1766.   }
  1767.   else
  1768.   {
  1769.     reg tmp, tmp2;
  1770.     setcc(SW_C2);
  1771.     r_div(st(), div1, tmp);
  1772.     int old_exp = tmp.exp;
  1773.     tmp.exp &= 31;
  1774.     long q;
  1775.     r_mov(tmp, &q);
  1776.     r_mov(&q, tmp);
  1777.     tmp.exp = old_exp;
  1778.     r_mul(div1, tmp, tmp2);
  1779.     r_sub(quot, tmp2, tmp);
  1780.     quot = tmp;
  1781.     rv = -1;
  1782.   }
  1783.   control_word = old_cw;
  1784.   return rv;;
  1785. }
  1786.  
  1787. static void fsincos()
  1788. {
  1789.   if (empty())
  1790.     return;
  1791.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  1792.  
  1793.   if (q & 1)
  1794.   {
  1795.     reg tmp;
  1796.     r_sub(CONST_PI2, st(), tmp);
  1797.     st() = tmp;
  1798.   }
  1799.  
  1800.   reg x2, val, rv, tmp, t2;
  1801.   reg valc, rvc, tmpc;
  1802.   val = st();
  1803.   r_mul(st(), val, x2);
  1804.   rv = val;
  1805.   valc = CONST_1;
  1806.   rvc = valc;
  1807.  
  1808.  
  1809.   for (int i=0; i<11; i++)
  1810.   {
  1811.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  1812.     valc.sign ^= SIGN_POS ^ SIGN_NEG;
  1813.     r_mul(x2, val, tmp);
  1814.     r_mul(x2, valc, tmpc);
  1815.     long c = ((i<<1)+2) * ((i<<1)+3);
  1816.     r_mov(&c, t2);
  1817.     r_div(tmp, t2, val);
  1818.     c = ((i<<1)+1) * ((i<<1)+2);
  1819.     r_mov(&c, t2);
  1820.     r_div(tmpc, t2, valc);
  1821.     r_add(val, rv, tmp);
  1822.     rv = tmp;
  1823.     r_add(valc, rvc, tmpc);
  1824.     rvc = tmpc;
  1825.   }
  1826.   setcc(0);
  1827.  
  1828.   if (q & 2)
  1829.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  1830.   st() = rv;
  1831.  
  1832.   top--;
  1833.   register int qq = q & 3;
  1834.   if ((qq == 1) || (qq == 2))
  1835.     rvc.sign ^= SIGN_POS ^ SIGN_NEG;
  1836.   st() = rvc;
  1837. }
  1838.  
  1839. static void fptan()
  1840. {
  1841.   fsincos();
  1842.   if (empty(1))
  1843.     return;
  1844.   reg tmp;
  1845.   r_div(st(1), st(), tmp);
  1846.   st(1) = tmp;
  1847.   st() = CONST_1;
  1848. }
  1849.  
  1850. static void fpatan()
  1851. {
  1852.   if (empty(1))
  1853.     return;
  1854.   if (is_zero(st()))
  1855.   {
  1856.     // Propagate sign of numerator
  1857.     char num_sign = st(1).sign;
  1858.     st(1) = CONST_PI2;
  1859.     st(1).sign = num_sign;
  1860.     st().tag = TW_E;
  1861.     top++;
  1862.     return;
  1863.   }
  1864.  
  1865.   if (is_zero(st(1)))
  1866.   {
  1867.     // Check for sign of denominator
  1868.     // st(1) = CONST_Z;
  1869.     st(1) = (st(0).sign == SIGN_NEG) ? CONST_PI : CONST_Z;
  1870.     st().tag = TW_E;
  1871.     top++;
  1872.     return;
  1873.   }
  1874.   reg x2, sum, term, pow, temp;
  1875.   int quadrant = 0;
  1876.   if (st(1).sign == SIGN_NEG)
  1877.     quadrant |= 1;
  1878.   if (st(0).sign == SIGN_NEG)
  1879.     quadrant |= 2;
  1880.   st(1).sign = st().sign = SIGN_POS;
  1881.   if (compare(st(1), st()) == COMP_A_GT_B)
  1882.   {
  1883.     quadrant |= 4;
  1884.     temp = st(1);
  1885.     st(1) = st();
  1886.     st() = temp;
  1887.   }
  1888.  
  1889.   r_div(st(1), st(), sum);
  1890.   r_mul(sum, sum, x2);
  1891.   pow = sum;
  1892.  
  1893.   x2.sign ^= SIGN_POS^SIGN_NEG;
  1894.  
  1895.   for (long i=3; i<25; i+=2)
  1896.   {
  1897.     r_mul(pow, x2, temp);
  1898.     pow = temp;
  1899.     r_mov(&i, temp);
  1900.     r_div(pow, temp, term);
  1901.     r_add(sum, term, temp);
  1902.     sum = temp;
  1903.   }
  1904.  
  1905.   if (quadrant & 4)
  1906.   {
  1907.     r_sub(CONST_PI2, sum, temp);
  1908.     sum = temp;
  1909.   }
  1910.   if (quadrant & 2)
  1911.   {
  1912.     r_sub(CONST_PI, sum, temp);
  1913.     sum = temp;
  1914.   }
  1915.   if (quadrant & 1)
  1916.     sum.sign ^= SIGN_POS^SIGN_NEG;
  1917.  
  1918.   st(1) = sum;
  1919.   st().tag = TW_E;
  1920.   top++;
  1921. }
  1922.  
  1923. static void fxtract()
  1924. {
  1925.   if (empty())
  1926.     return;
  1927.   if (full())
  1928.     return;
  1929.   top--;
  1930.   st() = st(1);
  1931.   st().exp = EXP_BIAS;
  1932.   long e = st(1).exp - EXP_BIAS;
  1933.   r_mov(&e, st(1));
  1934. }
  1935.  
  1936. static void fprem1()
  1937. {
  1938.   if (empty(1))
  1939.     return;
  1940.   int q = fprem_do(st(), st(1), RC_RND);
  1941.   if (q == -1)
  1942.     setcc(SW_C2);
  1943.   else
  1944.   {
  1945.     int c = 0;
  1946.     if (q&4) c |= SW_C3;
  1947.     if (q&2) c |= SW_C1;
  1948.     if (q&1) c |= SW_C0;
  1949.     setcc(c);
  1950.   }
  1951. }
  1952.  
  1953. static void fdecstp()
  1954. {
  1955.   top--;
  1956. }
  1957.  
  1958. static void fincstp()
  1959. {
  1960.   top++;
  1961. }
  1962.  
  1963. static FUNC emu_16_table[] = {
  1964.   f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp
  1965. };
  1966.  
  1967. static void emu_16()
  1968. {
  1969.   if (modrm > 0277)
  1970.   {
  1971.     (emu_16_table[modrm&7])();
  1972.   }
  1973.   else
  1974.   {
  1975.     emu_bad();
  1976.   }
  1977. }
  1978.  
  1979. static void fprem()
  1980. {
  1981.   if (empty(1))
  1982.     return;
  1983.   int q = fprem_do(st(), st(1), RC_CHOP);
  1984.   if (q == -1)
  1985.     setcc(SW_C2);
  1986.   else
  1987.   {
  1988.     int c = 0;
  1989.     if (q&4) c |= SW_C3;
  1990.     if (q&2) c |= SW_C1;
  1991.     if (q&1) c |= SW_C0;
  1992.     setcc(c);
  1993.   }
  1994. }
  1995.  
  1996. void fyl2x();
  1997.  
  1998. static void fyl2xp1()
  1999. {
  2000.   reg newx;
  2001.   r_add(st(), CONST_1, newx);
  2002.   st() = newx;
  2003.   fyl2x();
  2004. }
  2005.  
  2006. static void fsqrt()
  2007. {
  2008.   if (empty())
  2009.     return;
  2010.   if (st().tag == TW_Z)
  2011.     return;
  2012.   if (st().exp == EXP_MAX)
  2013.     return;
  2014.   if (st().sign == SIGN_NEG)
  2015.     return exception(EX_I);
  2016.  
  2017.   unsigned long long val = *(unsigned long long *)(&st().sigl);
  2018.   unsigned long long result = 0;
  2019.   unsigned long long side = 0;
  2020.   unsigned long long left = 0;
  2021.   if (st().exp & 1)
  2022.   {
  2023.     djshrd(&val);
  2024.     st().exp++;
  2025.   }
  2026.   int exp = (st().exp - EXP_BIAS - 1)/2 - 64;
  2027.   while (!(((long *)&result)[1] & 0x80000000))
  2028.   {
  2029.     left = (left << 2) + (((unsigned *)&val)[1] >> 30);
  2030.     djshld(&val);
  2031.     djshld(&val);
  2032.     if (left >= side*2 + 1)
  2033.     {
  2034.       left -= side*2+1;
  2035.       side = (side+1)*2;
  2036.       djshld(&result);
  2037.       result |= 1;
  2038.     }
  2039.     else
  2040.     {
  2041.       side *= 2;
  2042.       djshld(&result);
  2043.     }
  2044.     exp++;
  2045.   }
  2046.   st().exp = exp + EXP_BIAS;
  2047.   st().sigl = result & 0xffffffff;
  2048.   st().sigh = result >> 32;
  2049.   st().tag = TW_V;
  2050. }
  2051.  
  2052. static void frndint()
  2053. {
  2054.   if (empty())
  2055.     return;
  2056.   long long tmp;
  2057.   if (st().exp > EXP_BIAS+62)
  2058.     return;
  2059.   r_mov(st(), &tmp);
  2060.   r_mov(&tmp, st());
  2061. }
  2062.  
  2063. static void fscale()
  2064. {
  2065.   long scale1;
  2066.   if (empty(1))
  2067.     return;
  2068.   r_mov(st(1), &scale1);
  2069.   st().exp += scale1;
  2070. }
  2071.  
  2072. static void fsin()
  2073. {
  2074.   if (empty())
  2075.     return;
  2076.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  2077.  
  2078.   if (q & 1)
  2079.   {
  2080.     reg tmp;
  2081.     r_sub(CONST_PI2, st(), tmp);
  2082.     st() = tmp;
  2083.   }
  2084.  
  2085.   reg x2, val, rv, tmp, t2;
  2086.   val = st();
  2087.   r_mul(st(), val, x2);
  2088.   rv = val;
  2089.  
  2090.  
  2091.   for (int i=0; i<11; i++)
  2092.   {
  2093.     long c = ((i<<1)+2) * ((i<<1)+3);
  2094.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  2095.     r_mul(x2, val, tmp);
  2096.     r_mov(&c, t2);
  2097.     r_div(tmp, t2, val);
  2098.     r_add(val, rv, tmp);
  2099.     rv = tmp;
  2100.   }
  2101.   setcc(0);
  2102.   if (q & 2)
  2103.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  2104.   st() = rv;
  2105. }
  2106.  
  2107. static void fcos()
  2108. {
  2109.   if (empty())
  2110.     return;
  2111.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  2112.  
  2113.   if (q & 1)
  2114.   {
  2115.     reg tmp;
  2116.     r_sub(CONST_PI2, st(), tmp);
  2117.     st() = tmp;
  2118.   }
  2119.  
  2120.   reg x2, val, rv, tmp, t2;
  2121.   val = st();
  2122.   r_mul(st(), val, x2);
  2123.   val = CONST_1;
  2124.   rv = val;
  2125.  
  2126.  
  2127.   for (int i=0; i<11; i++)
  2128.   {
  2129.     long c = ((i<<1)+1) * ((i<<1)+2);
  2130.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  2131.     r_mul(x2, val, tmp);
  2132.     r_mov(&c, t2);
  2133.     r_div(tmp, t2, val);
  2134.     r_add(val, rv, tmp);
  2135.     rv = tmp;
  2136.   }
  2137.   setcc(0);
  2138.   register int qq = q & 3;
  2139.   if ((qq == 1) || (qq == 2))
  2140.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  2141.   st() = rv;
  2142. }
  2143.  
  2144. static FUNC emu_17_table[] = {
  2145.   fprem, fyl2xp1, fsqrt, fsincos, frndint, fscale, fsin, fcos
  2146. };
  2147.  
  2148. static void emu_17()
  2149. {
  2150.   if (modrm > 0277)
  2151.   {
  2152.     (emu_17_table[modrm&7])();
  2153.   }
  2154.   else
  2155.   {
  2156.     // fstcw m16int
  2157.     *(short *)get_modrm() = control_word;
  2158.   }
  2159. }
  2160.  
  2161. static void emu_20()
  2162. {
  2163.   if (empty())
  2164.     return;
  2165.   if (modrm > 0277)
  2166.   {
  2167.     emu_bad();
  2168.   }
  2169.   else
  2170.   {
  2171.     // fiadd m32int
  2172.     reg t1, t2;
  2173.     r_mov((long *)get_modrm(), t1);
  2174.     r_add(st(), t1, t2);
  2175.     st() = t2;
  2176.   }
  2177. }
  2178.  
  2179. static void emu_21()
  2180. {
  2181.   if (empty())
  2182.     return;
  2183.   if (modrm > 0277)
  2184.   {
  2185.     //
  2186.     emu_bad();
  2187.   }
  2188.   else
  2189.   {
  2190.     // fimul m32int
  2191.     reg t, t2;
  2192.     r_mov((long *)get_modrm(), t);
  2193.     r_mul(st(), t, t2);
  2194.     st() = t2;
  2195.   }
  2196. }
  2197.  
  2198. static void emu_22()
  2199. {
  2200.   if (empty())
  2201.     return;
  2202.   if (modrm > 0277)
  2203.   {
  2204.     emu_bad();
  2205.   }
  2206.   else
  2207.   {
  2208.     // ficom m32int
  2209.     reg t;
  2210.     r_mov((long *)get_modrm(), t);
  2211.     int c = compare(st(), t);
  2212.     int f;
  2213.     if (c & COMP_NAN)
  2214.     {
  2215.       exception(EX_I);
  2216.       f = SW_C3 | SW_C2 | SW_C0;
  2217.     }
  2218.     else
  2219.       switch (c)
  2220.       {
  2221.         case COMP_A_LT_B:
  2222.           f = SW_C0;
  2223.           break;
  2224.         case COMP_A_EQ_B:
  2225.           f = SW_C3;
  2226.           break;
  2227.         case COMP_A_GT_B:
  2228.           f = 0;
  2229.           break;
  2230.         case COMP_NOCOMP:
  2231.           f = SW_C3 | SW_C2 | SW_C0;
  2232.           break;
  2233.       }
  2234.     setcc(f);
  2235.   }
  2236. }
  2237.  
  2238. static void emu_23()
  2239. {
  2240.   if (empty())
  2241.     return;
  2242.   if (modrm > 0277)
  2243.   {
  2244.     emu_bad();
  2245.   }
  2246.   else
  2247.   {
  2248.     // ficomp m32int
  2249.     reg t;
  2250.     r_mov((long *)get_modrm(), t);
  2251.     int c = compare(st(), t);
  2252.     st().tag = TW_E;
  2253.     top++;
  2254.     int f;
  2255.     if (c & COMP_NAN)
  2256.     {
  2257.       exception(EX_I);
  2258.       f = SW_C3 | SW_C2 | SW_C0;
  2259.     }
  2260.     else
  2261.       switch (c)
  2262.       {
  2263.         case COMP_A_LT_B:
  2264.           f = SW_C0;
  2265.           break;
  2266.         case COMP_A_EQ_B:
  2267.           f = SW_C3;
  2268.           break;
  2269.         case COMP_A_GT_B:
  2270.           f = 0;
  2271.           break;
  2272.         case COMP_NOCOMP:
  2273.           f = SW_C3 | SW_C2 | SW_C0;
  2274.           break;
  2275.       }
  2276.     setcc(f);
  2277.   }
  2278. }
  2279.  
  2280. static void emu_24()
  2281. {
  2282.   if (empty())
  2283.     return;
  2284.   if (modrm > 0277)
  2285.   {
  2286.     emu_bad();
  2287.   }
  2288.   else
  2289.   {
  2290.     // fisub m32int
  2291.     reg t1, t2;
  2292.     r_mov((long *)get_modrm(), t1);
  2293.     r_sub(st(), t1, t2);
  2294.     st() = t2;
  2295.   }
  2296. }
  2297.  
  2298. static void emu_25()
  2299. {
  2300.   if (empty())
  2301.     return;
  2302.   if (modrm > 0277)
  2303.   {
  2304.     // fucompp
  2305.     if ((modrm&7) != 1)
  2306.       emu_bad();
  2307.     else
  2308.     {
  2309.     if (empty(modrm&7))
  2310.     {
  2311.       setcc(SW_C3|SW_C2|SW_C0);
  2312.       return;
  2313.     }
  2314.     int c = compare(st(), st(1));
  2315.     st().tag = TW_E;
  2316.     top++;
  2317.     st().tag = TW_E;
  2318.     top++;
  2319.     int f;
  2320.     if (c & COMP_SNAN)
  2321.     {
  2322.       exception(EX_I);
  2323.       f = SW_C3 | SW_C2 | SW_C0;
  2324.     }
  2325.     else
  2326.       switch (c)
  2327.       {
  2328.         case COMP_A_LT_B:
  2329.           f = SW_C0;
  2330.           break;
  2331.         case COMP_A_EQ_B:
  2332.           f = SW_C3;
  2333.           break;
  2334.         case COMP_A_GT_B:
  2335.           f = 0;
  2336.           break;
  2337.         case COMP_NOCOMP:
  2338.           f = SW_C3 | SW_C2 | SW_C0;
  2339.           break;
  2340.       }
  2341.     setcc(f);
  2342.     }
  2343.   }
  2344.   else
  2345.   {
  2346.     // fisubr m32int
  2347.     reg t1, t2;
  2348.     r_mov((long *)get_modrm(), t1);
  2349.     r_sub(t1, st(), t2);
  2350.     st() = t2;
  2351.   }
  2352. }
  2353.  
  2354. static void emu_26()
  2355. {
  2356.   if (empty())
  2357.     return;
  2358.   if (modrm > 0277)
  2359.   {
  2360.     //
  2361.     emu_bad();
  2362.   }
  2363.   else
  2364.   {
  2365.     // fidiv m32int
  2366.     reg t, t2;
  2367.     r_mov((long *)get_modrm(), t);
  2368.     r_div(st(), t, t2);
  2369.     st() = t2;
  2370.   }
  2371. }
  2372.  
  2373. static void emu_27()
  2374. {
  2375.   if (empty())
  2376.     return;
  2377.   if (modrm > 0277)
  2378.   {
  2379.     //
  2380.     emu_bad();
  2381.   }
  2382.   else
  2383.   {
  2384.     // fidivr m32int
  2385.     reg t, t2;
  2386.     r_mov((long *)get_modrm(), t);
  2387.     r_div(t, st(), t2);
  2388.     st() = t2;
  2389.   }
  2390. }
  2391.  
  2392. static void emu_30()
  2393. {
  2394.   if (full())
  2395.     return;
  2396.   if (modrm > 0277)
  2397.   {
  2398.     emu_bad();
  2399.   }
  2400.   else
  2401.   {
  2402.     // fild m32int
  2403.     top--;
  2404.     r_mov((long *)get_modrm(), st());
  2405.   }
  2406. }
  2407.  
  2408. static void emu_31()
  2409. {
  2410.   void emu_bad();
  2411.   emu_bad();
  2412. }
  2413.  
  2414. static void emu_32()
  2415. {
  2416.   if (empty())
  2417.     return;
  2418.   if (modrm > 0277)
  2419.   {
  2420.     //
  2421.     emu_bad();
  2422.   }
  2423.   else
  2424.   {
  2425.     // fist m32int
  2426.     r_mov(st(), (long *)get_modrm());
  2427.   }
  2428. }
  2429.  
  2430. static void emu_33()
  2431. {
  2432.   if (empty())
  2433.     return;
  2434.   if (modrm > 0277)
  2435.   {
  2436.     //
  2437.     emu_bad();
  2438.   }
  2439.   else
  2440.   {
  2441.     // fistp m32int
  2442.     r_mov(st(), (long *)get_modrm());
  2443.     st().tag = TW_E;
  2444.     top++;
  2445.   }
  2446. }
  2447.  
  2448. static void fclex()
  2449. {
  2450.   status_word &= ~(SW_B|SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE);
  2451. }
  2452.  
  2453. static void finit()
  2454. {
  2455.   control_word = 0x037e;
  2456.   status_word = 0;
  2457.   top = 0;
  2458.   for (int r=0; r<8; r++)
  2459.   {
  2460.     regs[r].sign = 0;
  2461.     regs[r].tag = TW_E;
  2462.     regs[r].exp = 0;
  2463.     regs[r].sigh = 0;
  2464.     regs[r].sigl = 0;
  2465.   }
  2466. }
  2467.  
  2468. static FUNC emu_34_table[] = {
  2469.   emu_bad, emu_bad, fclex, finit, emu_bad, emu_bad, emu_bad, emu_bad
  2470. };
  2471.  
  2472. static void emu_34()
  2473. {
  2474.   if (modrm > 0277)
  2475.   {
  2476.     (emu_34_table[modrm&7])();
  2477.   }
  2478.   else
  2479.   {
  2480.     //
  2481.     emu_bad();
  2482.   }
  2483. }
  2484.  
  2485. static void emu_35()
  2486. {
  2487.   if (full())
  2488.     return;
  2489.   if (modrm > 0277)
  2490.   {
  2491.     emu_bad();
  2492.   }
  2493.   else
  2494.   {
  2495.     // fld m80real
  2496.     top--;
  2497.     r_mov((long double *)get_modrm(), st());
  2498.   }
  2499. }
  2500.  
  2501. static void emu_36()
  2502. {
  2503.   void emu_bad();
  2504.   emu_bad();
  2505. }
  2506.  
  2507. static void emu_37()
  2508. {
  2509.   if (modrm > 0277)
  2510.   {
  2511.     emu_bad();
  2512.   }
  2513.   else
  2514.   {
  2515.     // fstp m80real
  2516.     if (empty())
  2517.       return;
  2518.     r_mov(st(), (long double *)get_modrm());
  2519.     st().tag = TW_E;
  2520.     top++;
  2521.   }
  2522. }
  2523.  
  2524. static void emu_40()
  2525. {
  2526.   if (empty())
  2527.     return;
  2528.   if (modrm > 0277)
  2529.   {
  2530.     // fadd st(i),st
  2531.     int i = modrm & 7;
  2532.     if (empty(i))
  2533.       return;
  2534.     reg tmp;
  2535.     r_add(st(), st(i), tmp);
  2536.     st(i) = tmp;
  2537.     return;
  2538.   }
  2539.   else
  2540.   {
  2541.     // fadd m64real
  2542.     reg t1, t2;
  2543.     r_mov((double *)get_modrm(), t1);
  2544.     r_add(t1, st(), t2);
  2545.     st() = t2;
  2546.   }
  2547. }
  2548.  
  2549. static void emu_41()
  2550. {
  2551.   if (empty())
  2552.     return;
  2553.   if (modrm > 0277)
  2554.   {
  2555.     // fmul st(i),st
  2556.     int i = modrm & 7;
  2557.     if (empty(i))
  2558.       return;
  2559.     reg t;
  2560.     r_mul(st(i), st(), t);
  2561.     st(i) = t;
  2562.   }
  2563.   else
  2564.   {
  2565.     // fmul m64real
  2566.     reg t, t2;
  2567.     r_mov((double *)get_modrm(), t);
  2568.     r_mul(st(), t, t2);
  2569.     st() = t2;
  2570.   }
  2571. }
  2572.  
  2573. static void emu_42()
  2574. {
  2575.   if (empty())
  2576.     return;
  2577.   if (modrm > 0277)
  2578.   {
  2579.     // 
  2580.     emu_bad();
  2581.   }
  2582.   else
  2583.   {
  2584.     // fcom m64real
  2585.     reg t;
  2586.     r_mov((double *)get_modrm(), t);
  2587.     int c = compare(st(), t);
  2588.     int f;
  2589.     if (c & COMP_NAN)
  2590.     {
  2591.       exception(EX_I);
  2592.       f = SW_C3 | SW_C2 | SW_C0;
  2593.     }
  2594.     else
  2595.       switch (c)
  2596.       {
  2597.         case COMP_A_LT_B:
  2598.           f = SW_C0;
  2599.           break;
  2600.         case COMP_A_EQ_B:
  2601.           f = SW_C3;
  2602.           break;
  2603.         case COMP_A_GT_B:
  2604.           f = 0;
  2605.           break;
  2606.         case COMP_NOCOMP:
  2607.           f = SW_C3 | SW_C2 | SW_C0;
  2608.           break;
  2609.       }
  2610.     setcc(f);
  2611.   }
  2612. }
  2613.  
  2614. static void emu_43()
  2615. {
  2616.   if (empty())
  2617.     return;
  2618.   if (modrm > 0277)
  2619.   {
  2620.     emu_bad();
  2621.   }
  2622.   else
  2623.   {
  2624.     // fcomp m64real
  2625.     reg t;
  2626.     r_mov((double *)get_modrm(), t);
  2627.     int c = compare(st(), t);
  2628.     st().tag = TW_E;
  2629.     top++;
  2630.     int f;
  2631.     if (c & COMP_NAN)
  2632.     {
  2633.       exception(EX_I);
  2634.       f = SW_C3 | SW_C2 | SW_C0;
  2635.     }
  2636.     else
  2637.       switch (c)
  2638.       {
  2639.         case COMP_A_LT_B:
  2640.           f = SW_C0;
  2641.           break;
  2642.         case COMP_A_EQ_B:
  2643.           f = SW_C3;
  2644.           break;
  2645.         case COMP_A_GT_B:
  2646.           f = 0;
  2647.           break;
  2648.         case COMP_NOCOMP:
  2649.           f = SW_C3 | SW_C2 | SW_C0;
  2650.           break;
  2651.       }
  2652.     setcc(f);
  2653.   }
  2654. }
  2655.  
  2656. static void emu_44()
  2657. {
  2658.   if (empty())
  2659.     return;
  2660.   if (modrm > 0277)
  2661.   {
  2662.     // fsub st(i),st
  2663.     int i = modrm & 7;
  2664.     if (empty(i))
  2665.       return;
  2666.     reg tmp;
  2667.     r_sub(st(), st(i), tmp);
  2668.     st(i) = tmp;
  2669.     return;
  2670.   }
  2671.   else
  2672.   {
  2673.     // fsub m64real
  2674.     reg t1, t2;
  2675.     r_mov((double *)get_modrm(), t1);
  2676.     r_sub(st(), t1, t2);
  2677.     st() = t2;
  2678.   }
  2679. }
  2680.  
  2681. static void emu_45()
  2682. {
  2683.   if (empty())
  2684.     return;
  2685.   if (modrm > 0277)
  2686.   {
  2687.     // fsubr st(i),st
  2688.     int i = modrm & 7;
  2689.     if (empty(i))
  2690.       return;
  2691.     reg tmp;
  2692.     r_sub(st(i), st(), tmp);
  2693.     st(i) = tmp;
  2694.     return;
  2695.   }
  2696.   else
  2697.   {
  2698.     // fsubr m64real
  2699.     reg t1, t2;
  2700.     r_mov((double *)get_modrm(), t1);
  2701.     r_sub(t1, st(), t2);
  2702.     st() = t2;
  2703.   }
  2704. }
  2705.  
  2706. static void emu_46()
  2707. {
  2708.   if (empty())
  2709.     return;
  2710.   if (modrm > 0277)
  2711.   {
  2712.     // fdivr st(i),st
  2713.     int i = modrm&7;
  2714.     if (empty(i))
  2715.       return;
  2716.     reg t;
  2717.     r_div(st(), st(i), t);
  2718.     st(i) = t;
  2719.   }
  2720.   else
  2721.   {
  2722.     // fdiv m64real
  2723.     reg t, t2;
  2724.     r_mov((double *)get_modrm(), t);
  2725.     r_div(st(), t, t2);
  2726.     st() = t2;
  2727.   }
  2728. }
  2729.  
  2730. static void emu_47()
  2731. {
  2732.   if (empty())
  2733.     return;
  2734.   if (modrm > 0277)
  2735.   {
  2736.     // fdiv st(i),st
  2737.     reg t;
  2738.     int i = modrm & 7;
  2739.     if (empty(i))
  2740.       return;
  2741.     r_div(st(i), st(0), t);
  2742.     st(i) = t;
  2743.   }
  2744.   else
  2745.   {
  2746.     // fdivr m64real
  2747.     reg t, t2;
  2748.     r_mov((double *)get_modrm(), t);
  2749.     r_div(t, st(), t2);
  2750.     st() = t2;
  2751.   }
  2752. }
  2753.  
  2754. static void emu_50()
  2755. {
  2756.   if (full())
  2757.     return;
  2758.   if (modrm > 0277)
  2759.   {
  2760.     // ffree st(i)
  2761.     int i = modrm & 7;
  2762.     st(i).tag = TW_E;
  2763.   }
  2764.   else
  2765.   {
  2766.     // fld m64real
  2767.     top--;
  2768.     r_mov((double *)get_modrm(), st());
  2769.   }
  2770. }
  2771.  
  2772. static void emu_51()
  2773. {
  2774.   void emu_bad();
  2775.   emu_bad();
  2776. }
  2777.  
  2778. static void emu_52()
  2779. {
  2780.   if (modrm > 0277)
  2781.   {
  2782.     st(modrm&7) = st();
  2783.   }
  2784.   else
  2785.   {
  2786.     // fst m64real
  2787.     if (empty())
  2788.       return;
  2789.     r_mov(st(), (double *)get_modrm());
  2790.   }
  2791. }
  2792.  
  2793. static void emu_53()
  2794. {
  2795.   if (modrm > 0277)
  2796.   {
  2797.     // fstp st(i)
  2798.     st(modrm&7) = st();
  2799.     st().tag = TW_E;
  2800.     top++;
  2801.   }
  2802.   else
  2803.   {
  2804.     // fstp m64real
  2805.     if (empty())
  2806.       return;
  2807.     r_mov(st(), (double *)get_modrm());
  2808.     st().tag = TW_E;
  2809.     top++;
  2810.   }
  2811. }
  2812.  
  2813. static void emu_54()
  2814. {
  2815.   if (modrm > 0277)
  2816.   {
  2817.     // fucom st(i)
  2818.     if (empty())
  2819.       return;
  2820.     if (empty(modrm&7))
  2821.     {
  2822.       setcc(SW_C3|SW_C2|SW_C0);
  2823.       return;
  2824.     }
  2825.     int c = compare(st(), st(modrm&7));
  2826.     int f;
  2827.     if (c & COMP_SNAN)
  2828.     {
  2829.       exception(EX_I);
  2830.       f = SW_C3 | SW_C2 | SW_C0;
  2831.     }
  2832.     else
  2833.       switch (c)
  2834.       {
  2835.         case COMP_A_LT_B:
  2836.           f = SW_C0;
  2837.           break;
  2838.         case COMP_A_EQ_B:
  2839.           f = SW_C3;
  2840.           break;
  2841.         case COMP_A_GT_B:
  2842.           f = 0;
  2843.           break;
  2844.         case COMP_NOCOMP:
  2845.           f = SW_C3 | SW_C2 | SW_C0;
  2846.           break;
  2847.       }
  2848.     setcc(f);
  2849.     
  2850.   }
  2851.   else
  2852.   {
  2853.     // frestor
  2854.     void *addr = get_modrm();
  2855.     int i, tag_word;
  2856.  
  2857.     control_word = *(int *)(addr+0) & 0xffff;
  2858.     status_word = *(int *)(addr+4) & 0xffff;
  2859.     tag_word = *(int *)(addr+8) & 0xffff;
  2860.     top = (status_word / SW_TOPS) & 3;
  2861.     for (i=0; i<8; i++)
  2862.     {
  2863.       r_mov((long double *)(addr + 0x1c + 10), st(i));
  2864.       st(i).tag = (tag_word >> (((i+top)&7)*2)) & 3;
  2865.     }
  2866.   }
  2867. }
  2868.  
  2869. static void emu_55()
  2870. {
  2871.   if (empty())
  2872.     return;
  2873.   if (modrm > 0277)
  2874.   {
  2875.     // fucomp st(i)
  2876.     if (empty(modrm&7))
  2877.     {
  2878.       setcc(SW_C3|SW_C2|SW_C0);
  2879.       return;
  2880.     }
  2881.     int c = compare(st(), st(modrm&7));
  2882.     st().tag = TW_E;
  2883.     top++;
  2884.     int f;
  2885.     if (c & COMP_SNAN)
  2886.     {
  2887.       exception(EX_I);
  2888.       f = SW_C3 | SW_C2 | SW_C0;
  2889.     }
  2890.     else
  2891.       switch (c)
  2892.       {
  2893.         case COMP_A_LT_B:
  2894.           f = SW_C0;
  2895.           break;
  2896.         case COMP_A_EQ_B:
  2897.           f = SW_C3;
  2898.           break;
  2899.         case COMP_A_GT_B:
  2900.           f = 0;
  2901.           break;
  2902.         case COMP_NOCOMP:
  2903.           f = SW_C3 | SW_C2 | SW_C0;
  2904.           break;
  2905.       }
  2906.     setcc(f);
  2907.     
  2908.   }
  2909.   else
  2910.   {
  2911.     emu_bad();
  2912.   }
  2913. }
  2914.  
  2915. static void emu_56() /* fsave */
  2916. {
  2917.   void *addr = get_modrm();
  2918.   int i, tag_word=0;
  2919.  
  2920.   status_word = status_word & ~SW_TOP;
  2921.   status_word += (top&7) * SW_TOPS;
  2922.  
  2923.   *(int *)(addr+0) = control_word & 0xffff;
  2924.   *(int *)(addr+4) = status_word & 0xffff;
  2925.   for (i=0; i<8; i++)
  2926.   {
  2927.     tag_word |= (st(i).tag << (((i+top)&7)*2));
  2928.     r_mov(st(i), (long double *)(addr + 0x1c + i*10));
  2929.   }
  2930.   *(int *)(addr+8) = tag_word & 0xffff;
  2931. }
  2932.  
  2933. static void emu_57()
  2934. {
  2935.   if (modrm > 0277)
  2936.   {
  2937.     //
  2938.     emu_bad();
  2939.   }
  2940.   else
  2941.   {
  2942.     // fstsw m2byte
  2943.     status_word &= ~SW_TOP;
  2944.     status_word |= (top&7) * SW_TOPS;
  2945.     *(short *)get_modrm() = status_word;
  2946.   }
  2947. }
  2948.  
  2949. static void emu_60()
  2950. {
  2951.   if (empty())
  2952.     return;
  2953.   if (modrm > 0277)
  2954.   {
  2955.     // faddp st(i),st
  2956.     int i = modrm & 7;
  2957.     if (empty(i))
  2958.       return;
  2959.     reg tmp;
  2960.     r_add(st(), st(i), tmp);
  2961.     st(i) = tmp;
  2962.     st().tag = TW_E;
  2963.     top++;
  2964.     return;
  2965.   }
  2966.   else
  2967.   {
  2968.     // fiadd m16int
  2969.     reg t1, t2;
  2970.     r_mov((short *)get_modrm(), t1);
  2971.     r_add(st(), t1, t2);
  2972.     st() = t2;
  2973.   }
  2974. }
  2975.  
  2976. static void emu_61()
  2977. {
  2978.   if (empty())
  2979.     return;
  2980.   if (modrm > 0277)
  2981.   {
  2982.     // fmulp st(i),st
  2983.     int i = modrm & 7;
  2984.     if (empty(i))
  2985.       return;
  2986.     reg t;
  2987.     r_mul(st(i), st(), t);
  2988.     st(i) = t;
  2989.     st().tag = TW_E;
  2990.     top++;
  2991.   }
  2992.   else
  2993.   {
  2994.     // fimul m16int
  2995.     reg t, t2;
  2996.     r_mov((short *)get_modrm(), t);
  2997.     r_mul(st(), t, t2);
  2998.     st() = t2;
  2999.   }
  3000. }
  3001.  
  3002. static void emu_62()
  3003. {
  3004.   if (empty())
  3005.     return;
  3006.   if (modrm > 0277)
  3007.   {
  3008.     emu_bad();
  3009.   }
  3010.   else
  3011.   {
  3012.     // ficom m16int
  3013.     reg t;
  3014.     r_mov((short *)get_modrm(), t);
  3015.     int c = compare(st(), t);
  3016.     int f;
  3017.     if (c & COMP_NAN)
  3018.     {
  3019.       exception(EX_I);
  3020.       f = SW_C3 | SW_C2 | SW_C0;
  3021.     }
  3022.     else
  3023.       switch (c)
  3024.       {
  3025.         case COMP_A_LT_B:
  3026.           f = SW_C0;
  3027.           break;
  3028.         case COMP_A_EQ_B:
  3029.           f = SW_C3;
  3030.           break;
  3031.         case COMP_A_GT_B:
  3032.           f = 0;
  3033.           break;
  3034.         case COMP_NOCOMP:
  3035.           f = SW_C3 | SW_C2 | SW_C0;
  3036.           break;
  3037.       }
  3038.     setcc(f);
  3039.   }
  3040. }
  3041.  
  3042. static void emu_63()
  3043. {
  3044.   if (empty())
  3045.     return;
  3046.   if (modrm > 0277)
  3047.   {
  3048.     // fcompp
  3049.     if ((modrm&7) != 1)
  3050.       return emu_bad();
  3051.     if (empty(1))
  3052.     {
  3053.       setcc(SW_C3|SW_C2|SW_C0);
  3054.       return;
  3055.     }
  3056.     int c = compare(st(), st(1));
  3057.     int f;
  3058.     st().tag = TW_E;
  3059.     top++;
  3060.     st().tag = TW_E;
  3061.     top++;
  3062.     if (c & COMP_NAN)
  3063.     {
  3064.       exception(EX_I);
  3065.       f = SW_C3 | SW_C2 | SW_C0;
  3066.     }
  3067.     else
  3068.       switch (c)
  3069.       {
  3070.         case COMP_A_LT_B:
  3071.           f = SW_C0;
  3072.           break;
  3073.         case COMP_A_EQ_B:
  3074.           f = SW_C3;
  3075.           break;
  3076.         case COMP_A_GT_B:
  3077.           f = 0;
  3078.           break;
  3079.         case COMP_NOCOMP:
  3080.           f = SW_C3 | SW_C2 | SW_C0;
  3081.           break;
  3082.       }
  3083.     setcc(f);
  3084.     
  3085.   }
  3086.   else
  3087.   {
  3088.     // ficomp m16int
  3089.     reg t;
  3090.     r_mov((short *)get_modrm(), t);
  3091.     int c = compare(st(), t);
  3092.     st().tag = TW_E;
  3093.     top++;
  3094.     int f;
  3095.     if (c & COMP_NAN)
  3096.     {
  3097.       exception(EX_I);
  3098.       f = SW_C3 | SW_C2 | SW_C0;
  3099.     }
  3100.     else
  3101.       switch (c)
  3102.       {
  3103.         case COMP_A_LT_B:
  3104.           f = SW_C0;
  3105.           break;
  3106.         case COMP_A_EQ_B:
  3107.           f = SW_C3;
  3108.           break;
  3109.         case COMP_A_GT_B:
  3110.           f = 0;
  3111.           break;
  3112.         case COMP_NOCOMP:
  3113.           f = SW_C3 | SW_C2 | SW_C0;
  3114.           break;
  3115.       }
  3116.     setcc(f);
  3117.   }
  3118. }
  3119.  
  3120. static void emu_64()
  3121. {
  3122.   if (empty())
  3123.     return;
  3124.   if (modrm > 0277)
  3125.   {
  3126.     // fsubp st(i),st
  3127.     int i = modrm & 7;
  3128.     if (empty(i))
  3129.       return;
  3130.     reg tmp;
  3131.     r_sub(st(), st(i), tmp);
  3132.     st(i) = tmp;
  3133.     st().tag = TW_E;
  3134.     top++;
  3135.     return;
  3136.   }
  3137.   else
  3138.   {
  3139.     // fisub m16int
  3140.     reg t1, t2;
  3141.     r_mov((short *)get_modrm(), t1);
  3142.     r_sub(st(), t1, t2);
  3143.     st() = t2;
  3144.   }
  3145. }
  3146.  
  3147. static void emu_65()
  3148. {
  3149.   if (empty())
  3150.     return;
  3151.   if (modrm > 0277)
  3152.   {
  3153.     // fsubr st(i),st
  3154.     int i = modrm & 7;
  3155.     if (empty(i))
  3156.       return;
  3157.     reg tmp;
  3158.     r_sub(st(i), st(), tmp);
  3159.     st(i) = tmp;
  3160.     st().tag = TW_E;
  3161.     top++;
  3162.     return;
  3163.   }
  3164.   else
  3165.   {
  3166.     // fisubr m16int
  3167.     reg t1, t2;
  3168.     r_mov((short *)get_modrm(), t1);
  3169.     r_sub(t1, st(), t2);
  3170.     st() = t2;
  3171.   }
  3172. }
  3173.  
  3174. static void emu_66()
  3175. {
  3176.   if (empty())
  3177.     return;
  3178.   if (modrm > 0277)
  3179.   {
  3180.     // fdivrp st(i),st
  3181.     int i = modrm & 7;
  3182.     if (empty(i))
  3183.       return;
  3184.     reg t;
  3185.     r_div(st(), st(i), t);
  3186.     st(i) = t;
  3187.     st().tag = TW_E;
  3188.     top++;
  3189.   }
  3190.   else
  3191.   {
  3192.     // fidiv m16int
  3193.     reg t, t2;
  3194.     r_mov((short *)get_modrm(), t);
  3195.     r_div(st(), t, t2);
  3196.     st() = t2;
  3197.   }
  3198. }
  3199.  
  3200. static void emu_67()
  3201. {
  3202.   if (empty())
  3203.     return;
  3204.   if (modrm > 0277)
  3205.   {
  3206.     // fdivp st(i),st
  3207.     reg t;
  3208.     int i = modrm & 7;
  3209.     if (empty(i))
  3210.       return;
  3211.     r_div(st(i), st(), t);
  3212.     st(i) = t;
  3213.     st().tag = TW_E;
  3214.     top++;
  3215.   }
  3216.   else
  3217.   {
  3218.     // fidiv m16int
  3219.     reg t, t2;
  3220.     r_mov((short *)get_modrm(), t);
  3221.     r_div(t, st(), t2);
  3222.     st() = t2;
  3223.   }
  3224. }
  3225.  
  3226. static void emu_70()
  3227. {
  3228.   if (full())
  3229.     return;
  3230.   if (modrm > 0277)
  3231.   {
  3232.     emu_bad();
  3233.   }
  3234.   else
  3235.   {
  3236.     // fild m16int
  3237.     top--;
  3238.     r_mov((short *)get_modrm(), st());
  3239.   }
  3240. }
  3241.  
  3242. static void emu_71()
  3243. {
  3244.   void emu_bad();
  3245.   emu_bad();
  3246. }
  3247.  
  3248.  
  3249. static void emu_72()
  3250. {
  3251.   if (empty())
  3252.     return;
  3253.   if (modrm > 0277)
  3254.   {
  3255.     //
  3256.     emu_bad();
  3257.   }
  3258.   else
  3259.   {
  3260.     // fist m16int
  3261.     r_mov(st(), (short *)get_modrm());
  3262.   }
  3263. }
  3264.  
  3265. static void emu_73()
  3266. {
  3267.   if (empty())
  3268.     return;
  3269.   if (modrm > 0277)
  3270.   {
  3271.     //
  3272.     emu_bad();
  3273.   }
  3274.   else
  3275.   {
  3276.     // fistp m16int
  3277.     r_mov(st(), (short *)get_modrm());
  3278.     st().tag = TW_E;
  3279.     top++;
  3280.   }
  3281. }
  3282.  
  3283. static void fstsw_ax()
  3284. {
  3285.   status_word &= ~SW_TOP;
  3286.   status_word |= (top&7) * SW_TOPS;
  3287.   eax &= 0xffff0000;
  3288.   eax |= status_word;
  3289. }
  3290.  
  3291. static FUNC emu_74_table[] = {
  3292.   fstsw_ax, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad
  3293. };
  3294.  
  3295. static void emu_74()
  3296. {
  3297.   if (modrm > 0277)
  3298.   {
  3299.     (emu_74_table[modrm&7])();
  3300.   }
  3301.   else
  3302.   {
  3303.     // fbld m80dec
  3304.     if (full())
  3305.       return;
  3306.     top--;
  3307.     r_mov((char *)get_modrm(), st());
  3308.   }
  3309. }
  3310.  
  3311. static void emu_75()
  3312. {
  3313.   if (full())
  3314.     return;
  3315.   if (modrm > 0277)
  3316.   {
  3317.     emu_bad();
  3318.   }
  3319.   else
  3320.   {
  3321.     // fild m80int
  3322.     top--;
  3323.     r_mov((long long *)get_modrm(), st());
  3324.   }
  3325. }
  3326.  
  3327. static void emu_76()
  3328. {
  3329.   if (st().tag == TW_E)
  3330.     exception(EX_SU);
  3331.   if (modrm > 0277)
  3332.   {
  3333.     emu_bad();
  3334.   }
  3335.   else
  3336.   {
  3337.     // fbstp
  3338.     r_mov(st(), (char *)get_modrm());
  3339.     st().tag = TW_E;
  3340.     top++;
  3341.   }
  3342. }
  3343.  
  3344. static void emu_77()
  3345. {
  3346.   if (empty())
  3347.     return;
  3348.   if (modrm > 0277)
  3349.   {
  3350.     //
  3351.     emu_bad();
  3352.   }
  3353.   else
  3354.   {
  3355.     // fistp m32int
  3356.     r_mov(st(), (long long *)get_modrm());
  3357.     st().tag = TW_E;
  3358.     top++;
  3359.   }
  3360. }
  3361.  
  3362. #ifndef TEST
  3363. #define TEST 0
  3364. #endif
  3365.  
  3366. extern void emu_install();
  3367. extern void emu_printall();
  3368.  
  3369. #if TEST
  3370.  
  3371. double a=10, b=16;
  3372. float f=3.3;
  3373. int i=3;
  3374.  
  3375. static void test()
  3376. {
  3377.   asm("fldl _b");
  3378.   asm("fldl _a");
  3379.   emu_printall();
  3380.   asm("fdivr %st,%st(1)");
  3381.   emu_printall();
  3382. }
  3383.  
  3384. #endif
  3385.  
  3386. #if 0
  3387. main()
  3388. {
  3389. #if TEST
  3390.   test();
  3391. #endif
  3392.   emu_install();
  3393. #if TEST
  3394.   test();
  3395. #endif
  3396. }
  3397. #endif
  3398.  
  3399. #if 0
  3400. char saw[256*8];
  3401.  
  3402. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  3403. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  3404. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  3405. char *fop_9[]  = { "*fxch st,%GF" };
  3406. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  3407. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  3408. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  3409.                    "fldlg2", "fldln2", "fldz", 0 };
  3410. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  3411.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  3412. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  3413.                    "frndint", "fscale", "fsin", "fcos" };
  3414. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  3415. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  3416. char *fop_32[] = { "*fadd %GF,st" };
  3417. char *fop_33[] = { "*fmul %GF,st" };
  3418. char *fop_36[] = { "*fsubr %GF,st" };
  3419. char *fop_37[] = { "*fsub %GF,st" };
  3420. char *fop_38[] = { "*fdivr %GF,st" };
  3421. char *fop_39[] = { "*fdiv %GF,st" };
  3422. char *fop_40[] = { "*ffree %GF" };
  3423. char *fop_42[] = { "*fst %GF" };
  3424. char *fop_43[] = { "*fstp %GF" };
  3425. char *fop_44[] = { "*fucom %GF" };
  3426. char *fop_45[] = { "*fucomp %GF" };
  3427. char *fop_48[] = { "*faddp %GF,st" };
  3428. char *fop_49[] = { "*fmulp %GF,st" };
  3429. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  3430. char *fop_52[] = { "*fsubrp %GF,st" };
  3431. char *fop_53[] = { "*fsubp %GF,st" };
  3432. char *fop_54[] = { "*fdivrp %GF,st" };
  3433. char *fop_55[] = { "*fdivp %GF,st" };
  3434. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  3435.  
  3436. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  3437.   0, 0, 0, 0, 0, 0, 0, 0,
  3438.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  3439.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  3440.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  3441.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  3442.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  3443.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  3444.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  3445.   };
  3446.  
  3447. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  3448. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  3449.        "fsub", "fsubr", "fdiv", "fdivr",
  3450. /*08*/ "fld", 0, "fst", "fstp",
  3451.        "fldenv", "fldcw", "fstenv", "fstcw",
  3452. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  3453.        "fisub", "fisubr", "fidiv", "fidivr",
  3454. /*24*/ "fild", 0, "fist", "fistp",
  3455.        "frstor", "fldt", 0, "fstpt",
  3456. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  3457.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  3458. /*40*/ "fldq", 0, "fstq", "fstpq",
  3459.        0, 0, "fsave", "fstsww",
  3460. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  3461.        "fisubw", "fisubrw", "fidivw", "fidivr",
  3462. /*56*/ "fildw", 0, "fistw", "fistpw",
  3463.        "fbldt", "fildq", "fbstpt", "fistpq"
  3464.   };
  3465. #endif
  3466.  
  3467. static FUNC esc_table[64] = {
  3468.   emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
  3469.   emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
  3470.   emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
  3471.   emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
  3472.   emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
  3473.   emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
  3474.   emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
  3475.   emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
  3476. };
  3477.  
  3478. extern "C" int _emu_entry(jmp_buf _exception_state);
  3479.  
  3480. int _emu_entry(jmp_buf _exception_state)
  3481. {
  3482.   int jmpval;
  3483.   eip = (char *) _exception_state->__eip;
  3484.   eax = _exception_state->__eax;
  3485.   ebx = _exception_state->__ebx;
  3486.   ecx = _exception_state->__ecx;
  3487.   edx = _exception_state->__edx;
  3488.   esi = _exception_state->__esi;
  3489.   edi = _exception_state->__edi;
  3490.   ebp = _exception_state->__ebp;
  3491.   esp = _exception_state->__esp;
  3492.   if (*eip == 0x66) // operand size - we know what size we need
  3493.     eip++;
  3494.   if (*eip == 0x9b) // fwait
  3495.   {
  3496. //    _exception_state->__eip++;
  3497.     return 0;
  3498.   }
  3499.   jmpval = setjmp(jumpbuf);
  3500.   if(jmpval)
  3501.     return 1;           /* Emulator failed for some reason */
  3502. #if 0
  3503.   int see = ((int)(eip[0] & 7) << 8) | eip[1];
  3504.   if (saw[see] != 42)
  3505.   {
  3506.     eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
  3507.     eprintf(" s%d  ", eip[1]&7);
  3508.     int esc = ((eip[0]<<3)&070) | ((eip[1]>>3)&007);
  3509.     int modrm = eip[1];
  3510.     if ((modrm>>6) == 3)
  3511.       if (fspecial[esc])
  3512.         if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  3513.             eprintf("%s\r\n", fspecial[esc][0]+1);
  3514.         else if (fspecial[esc][modrm&7])
  3515.             eprintf("%s\r\n", fspecial[esc][modrm&7]);
  3516.         else
  3517.           eprintf("<invalid>\r\n");
  3518.       else
  3519.         eprintf("%s st(i)\r\n", floatops[esc]);
  3520.     else
  3521.       eprintf("%s st(i)\r\n", floatops[esc]);
  3522.     saw[see] = 42;
  3523.   }
  3524. #endif
  3525.   int esc_value = *eip++ & 7;
  3526.   modrm = *eip++;
  3527.   esc_value |= (modrm & 070);
  3528.   (esc_table[esc_value])();
  3529. //  emu_printall();
  3530.   _exception_state->__eip = (unsigned long) eip;
  3531.   _exception_state->__eax = eax;
  3532.   return 0;
  3533. }
  3534.