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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "emu.h"
  4. #include "const.h"
  5.  
  6. int modrm;
  7.  
  8. char saw[256*8];
  9.  
  10. int status_word = 0;
  11. int control_word = 0x77e;
  12. reg regs[8] = {
  13.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  14.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  15.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  16.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  17.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  18.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  19.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  20.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  21. };
  22. int top = 0;
  23.  
  24. FUNC esc_table[64] = {
  25.   emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
  26.   emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
  27.   emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
  28.   emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
  29.   emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
  30.   emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
  31.   emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
  32.   emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
  33. };
  34.  
  35. int emu_initted = 0;
  36.  
  37. void emu_entry()
  38. {
  39.   if (emu_initted != 0x12345678)
  40.   {
  41.     emu_initted = 0x12345678;
  42.     eprintf(
  43.     "Installing the 80387 Emulator.  Copyright (C) 1991 DJ Delorie.\n"
  44.     "WARNING: This is a TEST version of this emulator.  If it doesn't work,\n"
  45.     "then don't use it.  Not all of the opcodes are implemented, and the\n"
  46.     "ones that are may not work right in extreme cases.  Use at your own risk.\n"
  47.     );
  48.   }
  49. //  eprintf("eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x\n", eax, ebx, ecx, edx);
  50. //  eprintf("esi=0x%08x edi=0x%08x ebp=0x%08x eip=0x%08x\n", esi, edi, ebp, eip);
  51.   if (*eip == 0x66) // operand size - we know what size we need
  52.     eip++;
  53.   if (*eip == 0x9b) // fwait
  54.     return;
  55. //  int see = ((int)(eip[0] & 7) << 8) | eip[1];
  56. //  if (saw[see] != 42)
  57. //  {
  58. //    eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
  59. //    eprintf(" s%d\n", eip[1]&7);
  60. //    saw[see] = 42;
  61. //  }
  62.   int esc_value = *eip++ & 7;
  63.   modrm = *eip++;
  64.   esc_value |= (modrm & 070);
  65.   (esc_table[esc_value])();
  66. //  emu_printall();
  67. }
  68.  
  69. void emu_bad()
  70. {
  71.   eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
  72.   if (eip[-1] > 0277)
  73.     eprintf(" %02x", eip[-1]);
  74.   else
  75.     eprintf(" /%d", (eip[-1]>>3)&7);
  76.   eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
  77.   if (eip[-1] > 0277)
  78.     eprintf(" s%d", eip[-1]&7);
  79.   eprintf("\n");
  80.   exception(EX_I);
  81. }
  82.  
  83. void emu_printall()
  84. {
  85.   static char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
  86.   status_word = status_word & ~SW_TOP;
  87.   status_word += (top&7) * SW_TOPS;
  88.   eprintf("  SW: 0x%04x  top=%d cc=%d%d%d%d    ", status_word, top&7,
  89.     status_word & SW_C3?1:0, status_word & SW_C2?1:0,
  90.     status_word & SW_C1?1:0, status_word & SW_C0?1:0);
  91.   eprintf("CW: 0x%04x\n", control_word);
  92.   for (int i=0; i<8; i++)
  93.   {
  94.     reg *r = &st(i);
  95.     switch (r->tag)
  96.     {
  97.       case TW_E:
  98.         continue;
  99.         eprintf("st(%d)                                ", i);
  100.         break;
  101.       case TW_Z:
  102.         eprintf("st(%d) %c .0000 0000 0000 0000         ",
  103.                 i, r->sign ? '-' : '+');
  104.         break;
  105.       case TW_S:
  106.       case TW_V:
  107.         eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
  108.           r->sign ? '-' : '+',
  109.           (long)(r->sigh >> 16),
  110.           (long)(r->sigh & 0xFFFF),
  111.           (long)(r->sigl >> 16),
  112.           (long)(r->sigl & 0xFFFF),
  113.           r->exp - EXP_BIAS + 1);
  114.     }
  115.     eprintf("%s\n", tag_desc[r->tag]);
  116.   }
  117.   fflush(stderr);
  118. }
  119.  
  120. static struct {
  121.   int type;
  122.   char *name;
  123. } ex_names[] = {
  124.   EX_SO, "stack overflow",
  125.   EX_SU, "stack underflow",
  126.   EX_P, "loss of precision",
  127.   EX_U, "underflow",
  128.   EX_O, "overflow",
  129.   EX_Z, "divide by zero",
  130.   EX_D, "denormalized operand",
  131.   EX_I, "invalid operation",
  132.   0,0
  133. };
  134.  
  135. void exception(int n)
  136. {
  137.   int i;
  138.   status_word |= n;
  139.   if (n == EX_SU)
  140.     status_word &= ~SW_C1;
  141.   for (i=0; ex_names[i].type; i++)
  142.     if (ex_names[i].type == n)
  143.       break;
  144.   if (ex_names[i].type)
  145.     eprintf("80387 Exception: %s!\n", ex_names[i].name);
  146.   else
  147.     eprintf("80387 Exception: 0x%04x!\n", n);
  148.   if (~control_word & n & CW_EXM)
  149.   {
  150.     emu_printall();
  151.     asm("movl $0x4cff,%eax");
  152.     asm("int $0x21");
  153.   }
  154. }
  155.  
  156. void setcc(int cc)
  157. {
  158.   status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
  159.   status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
  160. }
  161.  
  162. int full()
  163. {
  164.   if (st(7).tag != TW_E)
  165.   {
  166.     exception(EX_SO);
  167.     top--;
  168.     r_mov(CONST_NAN, st(0));
  169.     return 1;
  170.   }
  171.   return 0;
  172. }
  173.  
  174. int empty(int i)
  175. {
  176.   if (st(i).tag == TW_E)
  177.   {
  178.     exception(EX_SU);
  179.     return 1;
  180.   }
  181.   return 0;
  182. }
  183.  
  184. static int sregval(int reg, int mod)
  185. {
  186.   switch (reg)
  187.   {
  188.     case 0: return eax;
  189.     case 1: return ecx;
  190.     case 2: return edx;
  191.     case 3: return ebx;
  192.     case 4: return (mod==-1) ? 0 : esp;
  193.     case 5: return mod ? ebp : 0; // data
  194.     case 6: return esi;
  195.     case 7: return edi;
  196.   }
  197. }
  198.  
  199. static int scale[] = { 1, 2, 4, 8 };
  200.  
  201. static int getsib()
  202. {
  203.   int mod = modrm >> 6;
  204.   int sib = *eip++;
  205.   int ss = sib>>6;
  206.   int index = (sib>>3) & 7;
  207.   int base = sib & 7;
  208.   int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
  209.   int rv2;
  210.   switch (mod)
  211.   {
  212.     case 1:
  213.       rv2 = *(signed char *)eip++;
  214.       rv += rv2;
  215.       break;
  216.     case 0:
  217.       if (base != 5)
  218.         break;
  219.     case 2:
  220.       ((unsigned char *)&rv2)[0] = *eip++;
  221.       ((unsigned char *)&rv2)[1] = *eip++;
  222.       ((unsigned char *)&rv2)[2] = *eip++;
  223.       ((unsigned char *)&rv2)[3] = *eip++;
  224.       rv += rv2;
  225.       break;
  226.   }
  227.   return rv;
  228. }
  229.  
  230. static int regval(int reg, int mod)
  231. {
  232.   switch (reg)
  233.   {
  234.     case 0: return eax;
  235.     case 1: return ecx;
  236.     case 2: return edx;
  237.     case 3: return ebx;
  238.     case 4: return getsib();
  239.     case 5: return mod ? ebp : 0; // data
  240.     case 6: return esi;
  241.     case 7: return edi;
  242.   }
  243. }
  244.  
  245. void *get_modrm()
  246. {
  247.   int mod = modrm>>6;
  248.   int rm = modrm & 7;
  249.   int rv;
  250.   switch (mod)
  251.   {
  252.     case 0:
  253.       if (rm == 5)
  254.       {
  255.         ((unsigned char *)&rv)[0] = *eip++;
  256.         ((unsigned char *)&rv)[1] = *eip++;
  257.         ((unsigned char *)&rv)[2] = *eip++;
  258.         ((unsigned char *)&rv)[3] = *eip++;
  259.       }
  260.       else
  261.         rv = regval(rm, mod);
  262.       break;
  263.     case 1:
  264.       if (rm != 4)
  265.         rv = (*(signed char *)eip++) + regval(rm, mod);
  266.       else
  267.         rv = regval(rm, mod);
  268.       break;
  269.     case 2:
  270.       if (rm != 4)
  271.       {
  272.         ((unsigned char *)&rv)[0] = *eip++;
  273.         ((unsigned char *)&rv)[1] = *eip++;
  274.         ((unsigned char *)&rv)[2] = *eip++;
  275.         ((unsigned char *)&rv)[3] = *eip++;
  276.         rv += regval(rm, mod);
  277.       }
  278.       else
  279.         rv = regval(rm, mod);
  280.       break;
  281.     case 3:
  282.       eprintf("Attempt to get address from mod = 3\n");
  283.       exit(1);
  284.   }
  285. //  eprintf("modrm returning 0x%x\n", rv);
  286.   return (void *)rv;
  287. }
  288.