home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 October / VPR9710A.ISO / BENCH / DJ1SRC_K / 105 / DEBUG.C < prev    next >
C/C++ Source or Header  |  1997-05-02  |  42KB  |  1,780 lines

  1.  
  2. /* This is file DEBUG.C */
  3. /*
  4.    ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  5.    **
  6.    ** This file is distributed under the terms listed in the document
  7.    ** "copying.dj", available from DJ Delorie at the address above.
  8.    ** A copy of "copying.dj" should accompany this file; if not, a copy
  9.    ** should be available from where this file was obtained.  This file
  10.    ** may not be distributed without a verbatim copy of "copying.dj".
  11.    **
  12.    ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  13.    ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14.  */
  15. /* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp) 
  16.    for reduce binary size and for dead code elimination.
  17.    and merged debug.c, unassmbl.c and unassmbl.h
  18.  */
  19. /* History:175,26 */
  20.  
  21. #include <stdarg.h>
  22. #include "build.h"
  23.  
  24. extern int was_exception, have_80387;
  25. jmp_buf back_to_debugger;
  26. int can_longjmp = 0;
  27. void go_til_stop(void);
  28. extern int exception_handler(void);
  29. extern void go32(void);
  30.  
  31. #if DEBUGGER
  32. static
  33. #endif
  34. void go_til_stop(void)
  35. {
  36.     tss_ptr = &a_tss;
  37.     while (1) {
  38.         go32();
  39.         if (!was_exception)
  40.             return;
  41.         if (exception_handler())
  42.             return;
  43.     }
  44. }
  45.  
  46. #if DEBUGGER
  47. extern void __fastcall syms_listwild(char *pattern);
  48. extern void __pascal tssprint(TSS * t);
  49. extern void save_npx(void);
  50. extern word32 dr[8];
  51. extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
  52.  
  53. static void print_reason(void);
  54.  
  55. /* merged from unassmbl.h */
  56. static word32 __pascal unassemble(word32 v, int showregs);
  57. static void __pascal ua_str(char *s);
  58.  
  59. static int last_unassemble_unconditional;
  60. static int last_unassemble_jump;
  61. static int last_unassemble_extra_lines;
  62.  
  63. typedef struct {
  64.     char *cp;
  65.     int t;
  66. } item;
  67.  
  68. static void __pascal my_getline(char *buf, char *lasttoken)
  69. {
  70.     int idx, i, ch;
  71.     if (use_ansi)
  72.         printf("\033[0;32m");
  73.     mono_attr = MONO_NORMAL;
  74.     printf(">> %s", lasttoken);
  75.     for (i = 0; lasttoken[i]; i++)
  76.         mputchar(8);
  77.     while (!bioskey(1));
  78.     for (i = 0; lasttoken[i]; i++)
  79.         mputchar(' ');
  80.     for (i = 0; lasttoken[i]; i++)
  81.         mputchar(8);
  82.     idx = 0;
  83.     if (use_ansi)
  84.         printf("\033[1;33m");
  85.     mono_attr = MONO_BOLD;
  86.     while (1) {
  87.         ch = bioskey(0) & 0xff;
  88.         switch (ch) {
  89.         case 10:
  90.         case 13:
  91.             buf[idx] = 0;
  92.             if (!idx && lasttoken[0])
  93.                 printf("\r  \r");
  94.             else
  95.                 mputchar('\n');
  96.             if (use_ansi)
  97.                 printf("\033[0m");
  98.             mono_attr = MONO_NORMAL;
  99.             return;
  100.         case 27:
  101.             while (idx) {
  102.                 printf("\b \b");
  103.                 idx--;
  104.             }
  105.             break;
  106.         case 8:
  107.             if (idx) {
  108.                 printf("\b \b");
  109.                 idx--;
  110.             }
  111.             break;
  112.         default:
  113.             mputchar(ch);
  114.             buf[idx++] = ch;
  115.             break;
  116.         }
  117.     }
  118. }
  119.  
  120. typedef enum {
  121.     Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
  122.     DUMP, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
  123.     CLS
  124. };
  125.  
  126. extern struct {
  127.     char *name;
  128.     int size;
  129.     int ofs;
  130. } regs[];
  131.  
  132. static item cmds[] =
  133. {
  134.     {"g", CONT},
  135.     {"go", CONT},
  136.     {"cont", CONT},
  137.     {"c", CONT},
  138.     {"step", STEP},
  139.     {"s", STEP},
  140.     {"next", NEXT},
  141.     {"n", NEXT},
  142.     {"regs", REGS},
  143.     {"r", REGS},
  144.     {"set", SET},
  145.     {"help", HELP},
  146.     {"h", HELP},
  147.     {"?", HELP},
  148.     {"list", LIST},
  149.     {"l", LIST},
  150.     {"u", LIST},
  151.     {"dump", DUMP},
  152.     {"d", DUMP},
  153.     {"da", DUMP_A},
  154.     {"db", DUMP_B},
  155.     {"dw", DUMP_W},
  156.     {"dd", DUMP},
  157.     {"quit", QUIT},
  158.     {"q", QUIT},
  159.     {"break", BREAK},
  160.     {"b", BREAK},
  161.     {"status", STATUS},
  162.     {"where", WHERE},
  163.     {"whereis", WHEREIS},
  164.     {"npx", XNPX},
  165.     {"cls", CLS},
  166.     {0, 0}};
  167.  
  168. extern int debug_mode;
  169.  
  170. void debugger(void)
  171. {
  172.     static char buf[140], token[10], buf2[140], lasttoken[140];
  173.     char *name;
  174.     int i, n, s, len, rem_cmd, cmd, found;
  175.     word32 vaddr, v, rem_v, olddr7;
  176.     int32 delta;
  177.  
  178.     dr0 = dr1 = dr2 = ARENA;
  179.     dr3 = syms_name2val("_main") + ARENA;
  180.     if (undefined_symbol)
  181.         dr3 = tss_ptr->tss_eip + ARENA;
  182.     rem_cmd = Zero;
  183.     lasttoken[0] = 0;
  184.     setjmp(back_to_debugger);
  185.     can_longjmp = 1;
  186.     while (1) {
  187.         if (debug_mode) {
  188.             int found;
  189.             my_getline(buf, lasttoken);
  190.             token[0] = 0;
  191.             if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
  192.                 buf[0] = 0;
  193.             if (token[0])
  194.                 strcpy(lasttoken, token);
  195.             cmd = rem_cmd;
  196.             found = 0;
  197.             for (i = 0; cmds[i].cp; i++)
  198.                 if (!strcmp(cmds[i].cp, token)) {
  199.                     cmd = cmds[i].t;
  200.                     found = 1;
  201.                 }
  202.             if (!found && token[0])
  203.                 cmd = Unknown;
  204.             if (rem_cmd != cmd)
  205.                 vaddr = tss_ptr->tss_eip;
  206.         } else {
  207.             cmd = CONT;
  208.             debug_mode = 1;
  209.         }
  210.         switch (cmd) {
  211.         case HELP:
  212.             printf("Commands:\n"
  213.                    "go <v>\tg\tgo, stop at <v>\n"
  214.                    "cont\tc\tcontinue execution\n"
  215.                    "step\ts\tstep through current instruction\n"
  216.                    "next\tn\tstep to next instruction\n"
  217.                    "list\tl u\tlist instructions (takes addr, count)\n"
  218.                    "dump\td\tdump memory (takes addr, count)\n"
  219.                    "break\tb\tset breakpoint (takes which, addr)\n"
  220.                    "status\t\tbreakpoint status\n"
  221.                    "regs\tr\tprint registers\n"
  222.                    "set\t\tset register/memory\n"
  223.                    "npx\t\tdisplay 80387 contents\n"
  224.                    "where\t\tdisplay list of active functions\n"
  225.                    "whereis\t\tfind a symbol/location (takes wildcard or value)\n"
  226.                    "cls\t\tclear screen\n"
  227.                    "help\th,?\tprint help\n"
  228.                    "quit\tq\tquit\n");
  229.             break;
  230.         case CONT:
  231.             sscanf(buf, "%s", buf);
  232.             if (buf[0]) {
  233.                 v = syms_name2val(buf);
  234.                 if (undefined_symbol)
  235.                     break;
  236.                 dr3 = v + ARENA;
  237.                 dr7 |= 0xc0;
  238.             } else
  239.                 dr7 &= ~0xc0;
  240.             olddr7 = dr7;
  241.             dr7 = 0;
  242.             tss_ptr->tss_eflags |= 0x0100;
  243.             go_til_stop();
  244.             dr7 = olddr7;
  245.             if (tss_ptr->tss_irqn == 1) {
  246.                 tss_ptr->tss_eflags &= ~0x0100;
  247.                 tss_ptr->tss_eflags |= 0x10000L;
  248.                 go_til_stop();
  249.                 if (tss_ptr->tss_irqn == 1)
  250.                     tssprint(tss_ptr);
  251.             }
  252.             print_reason();
  253.             dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  254.             break;
  255.         case STEP:
  256.             if (rem_cmd != cmd)
  257.                 n = 1;
  258.             sscanf(buf, "%d", &n);
  259.             tss_ptr->tss_eflags |= 0x0100;
  260.             for (i = 0; i < n; i++) {
  261.                 olddr7 = dr7;
  262.                 dr7 = 0;
  263.                 go_til_stop();
  264.                 dr7 = olddr7;
  265.                 print_reason();
  266.                 dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  267.                 if (tss_ptr->tss_irqn != 1)
  268.                     break;
  269.             }
  270.             tss_ptr->tss_eflags &= ~0x0100;
  271.             break;
  272.         case NEXT:
  273.             if (rem_cmd != cmd)
  274.                 n = 1;
  275.             sscanf(buf, "%d", &n);
  276.             for (i = 0; i < n; i++) {
  277.                 olddr7 = dr7;
  278.                 dr7 &= ~0xc0;
  279.                 dr7 |= 0xc0;
  280.                 if (last_unassemble_unconditional ||
  281.                     last_unassemble_jump)
  282.                     tss_ptr->tss_eflags |= 0x0100;    /* step */
  283.                 else
  284.                     tss_ptr->tss_eflags &= ~0x0100;
  285.                 go_til_stop();
  286.                 dr7 = olddr7;
  287.                 print_reason();
  288.                 dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  289.                 if (tss_ptr->tss_irqn != 1)
  290.                     break;
  291.             }
  292.             tss_ptr->tss_eflags &= ~0x0100;
  293.             break;
  294.         case WHERE:
  295.             v = tss_ptr->tss_ebp;
  296.             vaddr = tss_ptr->tss_eip;
  297.             printf("%#08lx %s", vaddr, syms_val2name(vaddr, (word32 *) & delta));
  298.             name = syms_val2line(vaddr, &i, 0);
  299.             if (name)
  300.                 printf(", line %d in file %s", i, name);
  301.             else if (delta)
  302.                 printf("%+ld", delta);
  303.             mputchar('\n');
  304.             do {
  305.                 if (!v)
  306.                     break;
  307.                 rem_v = peek32(v + ARENA);
  308.                 if (!rem_v)
  309.                     break;
  310.                 vaddr = peek32(v + ARENA + 4);
  311.                 printf("%#08lx %s", vaddr, syms_val2name(vaddr, (word32 *) & delta));
  312.                 name = syms_val2line(vaddr, &i, 0);
  313.                 if (name)
  314.                     printf(", line %d in file %s", i, name);
  315.                 else if (delta)
  316.                     printf("%+ld", delta);
  317.                 mputchar('\n');
  318.                 v = rem_v;
  319.             } while ((v >= tss_ptr->tss_esp) && (v < 0x90000000L));
  320.             break;
  321.         case WHEREIS:
  322.             sscanf(buf, "%s", buf2);
  323.             if (strpbrk(buf2, "*?")) {
  324.                 syms_listwild(buf2);
  325.                 break;
  326.             }
  327.             if (buf2[0])
  328.                 vaddr = syms_name2val(buf2);
  329.             if (undefined_symbol)
  330.                 break;
  331.             name = syms_val2name(vaddr, (word32 *) & delta);
  332.             printf("%#08lx %s", vaddr, name);
  333.             if (delta)
  334.                 printf("+%lx", delta);
  335.             name = syms_val2line(vaddr, &i, 0);
  336.             if (name)
  337.                 printf(", line %d in file %s", i, name);
  338.             mputchar('\n');
  339.             break;
  340.         case LIST:
  341.             if (rem_cmd != cmd)
  342.                 n = 10;
  343.             buf2[0] = 0;
  344.             sscanf(buf, "%s %d", buf2, &n);
  345.             if (buf2[0] && strcmp(buf2, "."))
  346.                 vaddr = syms_name2val(buf2);
  347.             if (undefined_symbol)
  348.                 break;
  349.             for (i = 0; i < n; i++) {
  350.                 vaddr = unassemble(vaddr, 0);
  351.                 i += last_unassemble_extra_lines;
  352. /*          if (last_unassemble_unconditional)
  353.    break; */
  354.             }
  355.             break;
  356.         case DUMP_A:
  357.             buf2[0] = 0;
  358.             sscanf(buf, "%s %d", buf2, &n);
  359.             if (buf2[0])
  360.                 vaddr = syms_name2val(buf2);
  361.             if (undefined_symbol)
  362.                 break;
  363.             while (1) {
  364.                 word8 ch;
  365.                 if (!page_is_valid(vaddr + ARENA)) {
  366.                     printf("<bad address>\n");
  367.                     break;
  368.                 }
  369.                 ch = peek8(vaddr + ARENA);
  370.                 if (!ch) {
  371.                     mputchar('\n');
  372.                     break;
  373.                 }
  374.                 if (ch < ' ')
  375.                     printf("^%c", ch + '@');
  376.                 else if ((ch >= ' ') && (ch < 0x7f))
  377.                     mputchar(ch);
  378.                 else if (ch == 0x7f)
  379.                     printf("^?");
  380.                 else if ((ch >= 0x80) && (ch < 0xa0))
  381.                     printf("M-^%c", ch - 0x80 + '@');
  382.                 else if (ch >= 0xa0)
  383.                     printf("M-%c", ch - 0x80);
  384.                 vaddr++;
  385.             }
  386.             break;
  387.         case DUMP:
  388.         case DUMP_B:
  389.         case DUMP_W:
  390.             if (rem_cmd != cmd)
  391.                 n = 4;
  392.             buf2[0] = 0;
  393.             sscanf(buf, "%s %d", buf2, &n);
  394.             if (buf2[0])
  395.                 vaddr = syms_name2val(buf2);
  396.             if (undefined_symbol)
  397.                 break;
  398.             s = 0;
  399.             len = n + (int)(~((vaddr & 15) / 4 - 1) & 3);
  400.             for (i = -(int)(vaddr & 15) / 4; i < len; i++) {
  401.                 if (!(s & 3))
  402.                     printf("%#08lx:", vaddr + i * 4);
  403.                 if ((i >= 0) && (i < n))
  404.                     printf(" %#08lx", peek32(vaddr + i * 4 + ARENA));
  405.                 else
  406.                     printf("           ");
  407.                 if ((s & 3) == 3) {
  408.                     int j, c;
  409.                     printf("  ");
  410.                     for (j = 0; j < 16; j++)
  411.                         if ((j + i * 4 - 12 >= 0) && (j + i * 4 - 12 < n * 4)) {
  412.                             c = peek8(vaddr + j + i * 4 - 12 + ARENA);
  413.                             if (c < ' ')
  414.                                 mputchar('.');
  415.                             else
  416.                                 mputchar(c);
  417.                         } else
  418.                             mputchar(' ');
  419.                     printf("\n");
  420.                 }
  421.                 s++;
  422.             }
  423.             if (s & 3)
  424.                 printf("\n");
  425.             vaddr += n * 4;
  426.             break;
  427.         case BREAK:
  428.             vaddr = n = 0;
  429.             buf2[0] = 0;
  430.             sscanf(buf, "%d %s", &n, buf2);
  431.             if (buf2[0])
  432.                 vaddr = syms_name2val(buf2);
  433.             if (undefined_symbol)
  434.                 break;
  435.             dr[n] = vaddr + ARENA;
  436.             if (!vaddr)
  437.                 dr7 &= ~(2 << (n * 2));
  438.             else
  439.                 dr7 |= 2 << (n * 2);
  440.         case STATUS:
  441.             s = 0;
  442.             for (n = 0; n < 4; n++) {
  443.                 s = 1;
  444.                 name = syms_val2name(dr[n] - ARENA, (word32 *) & delta);
  445.                 printf("  dr%d  %s", n, name);
  446.                 if (delta)
  447.                     printf("+%#lx", delta);
  448.                 if (name[0] != '0')
  449.                     printf(" (%#lx)", dr[n] - ARENA);
  450.                 if (!(dr7 & (3 << (n * 2))))
  451.                     printf(" (disabled)");
  452.                 mputchar('\n');
  453.             }
  454.             if (!s)
  455.                 printf("  No breakpoints set\n");
  456.             break;
  457.         case REGS:
  458.             tssprint(tss_ptr);
  459.             unassemble(tss_ptr->tss_eip, 0);
  460.             break;
  461.         case SET:
  462.             cmd = Zero;
  463.             lasttoken[0] = 0;
  464.             buf2[0] = 0;
  465.             len = sscanf(buf, "%s %s", buf2, buf);
  466.             if (!buf2[0])
  467.                 break;
  468.             if (len > 1) {
  469.                 v = syms_name2val(buf);
  470.                 if (undefined_symbol)
  471.                     break;
  472.             }
  473.             found = 0;
  474.             for (i = 0; regs[i].name; i++)
  475.                 if (!strcmp(regs[i].name, buf2)) {
  476.                     found = 1;
  477.                     if (len > 1) {
  478.                         switch (regs[i].size) {
  479.                         case 1:
  480.                             *(word8 *) ((word8 *) tss_ptr + regs[i].ofs) = (word8) v;
  481.                             break;
  482.                         case 2:
  483.                             *(word16 *) ((word8 *) tss_ptr + regs[i].ofs) = (word16) v;
  484.                             break;
  485.                         case 4:
  486.                             *(word32 *) ((word8 *) tss_ptr + regs[i].ofs) = v;
  487.                             break;
  488.                         }
  489.                     } else {
  490.                         switch (regs[i].size) {
  491.                         case 1:
  492.                             printf("%02x ", *(word8 *) ((word8 *) tss_ptr + regs[i].ofs));
  493.                             my_getline(buf, "");
  494.                             if (buf[0]) {
  495.                                 v = syms_name2val(buf);
  496.                                 if (undefined_symbol)
  497.                                     break;
  498.                                 *(word8 *) ((word8 *) tss_ptr + regs[i].ofs) = (word8) v;
  499.                             }
  500.                             break;
  501.                         case 2:
  502.                             printf("%04x ", *(word16 *) ((word16 *) tss_ptr + regs[i].ofs));
  503.                             my_getline(buf, "");
  504.                             if (buf[0]) {
  505.                                 v = syms_name2val(buf);
  506.                                 if (undefined_symbol)
  507.                                     break;
  508.                                 *(word16 *) ((word16 *) tss_ptr + regs[i].ofs) = (word16) v;
  509.                             }
  510.                             break;
  511.                         case 4:
  512.                             printf("%08lx ", *(word32 *) ((word32 *) tss_ptr + regs[i].ofs));
  513.                             my_getline(buf, "");
  514.                             if (buf[0]) {
  515.                                 v = syms_name2val(buf);
  516.                                 if (undefined_symbol)
  517.                                     break;
  518.                                 *(word32 *) ((word32 *) tss_ptr + regs[i].ofs) = v;
  519.                             }
  520.                             break;
  521.                         }
  522.                     }
  523.                     break;
  524.                 }
  525.             if (found)
  526.                 break;
  527.             vaddr = syms_name2val(buf2);
  528.             if (undefined_symbol)
  529.                 break;
  530.             if (len < 2) {
  531.                 v = syms_name2val(buf);
  532.                 if (undefined_symbol)
  533.                     break;
  534.                 poke32(vaddr, v);
  535.             }
  536.             while (1) {
  537.                 printf("%#08lx %#08lx", vaddr, peek32(vaddr + ARENA));
  538.                 my_getline(buf, "");
  539.                 if (buf[0]) {
  540.                     if (!strcmp(buf, "."))
  541.                         break;
  542.                     poke32(vaddr + ARENA, syms_name2val(buf));
  543.                 }
  544.                 vaddr += 4;
  545.             }
  546.             break;
  547.         case XNPX:
  548.             if (!have_80387) {
  549.                 printf("No 80387 present\n");
  550.                 break;
  551.             }
  552.             save_npx();
  553.             printf("Control: %#04lx  Status: %#04lx  Tag: %#04lx\n",
  554.                    npx.control, npx.status, npx.tag);
  555.             for (i = 0; i < 8; i++) {
  556.                 double d;
  557.                 int tag, ex;
  558.                 int tos = (npx.status >> 11) & 7;
  559.                 printf("st(%d)  ", i);
  560.                 if (npx.reg[i].sign)
  561.                     mputchar('-');
  562.                 else
  563.                     mputchar('+');
  564.                 printf(" %04x %04x %04x %04x e %04x    ",
  565.                        npx.reg[i].sig3,
  566.                        npx.reg[i].sig2,
  567.                        npx.reg[i].sig1,
  568.                        npx.reg[i].sig0,
  569.                        npx.reg[i].exponent);
  570.                 tag = (npx.tag >> (((i + tos) % 8) * 2)) & 3;
  571.                 switch (tag) {
  572.                 case 0:
  573.                     printf("Valid");
  574.                     ex = (int)npx.reg[i].exponent - 16382;
  575.                     if ((ex < 1000) && (ex > -1000)) {
  576. #define D1 65536.0L
  577.                         d = npx.reg[i].sig3 / D1 + npx.reg[i].sig2 / D1 / D1 + npx.reg[i].sig1 / D1 / D1 / D1;
  578.                         d = ldexp(d, ex);
  579.                         if (npx.reg[i].sign)
  580.                             d = -d;
  581.                         printf("  %.16lg\n", d);
  582.                     } else
  583.                         printf("  (too big to display)\n");
  584.                     break;
  585.                 case 1:
  586.                     printf("Zero\n");
  587.                     break;
  588.                 case 2:
  589.                     printf("Special\n");
  590.                     break;
  591.                 case 3:
  592.                     printf("Empty\n");
  593.                     break;
  594.                 }
  595.             }
  596.             break;
  597.         case CLS:
  598.             if (use_mono)
  599.                 mputchar(12);
  600.             else {
  601.                 _AH = 15;
  602.                 geninterrupt(0x10);
  603.                 _AH = 0;
  604.                 geninterrupt(0x10);
  605.                 mputchar('\n');
  606.             }
  607.             break;
  608.         case QUIT:
  609.             return;
  610.         case Zero:
  611.             break;
  612.         default:
  613.             printf("Unknown command\n");
  614.             lasttoken[0] = 0;
  615.             cmd = Zero;
  616.             break;
  617.         }
  618.         if (undefined_symbol) {
  619.             lasttoken[0] = 0;
  620.             cmd = Zero;
  621.             undefined_symbol = 0;
  622.         }
  623.         rem_cmd = cmd;
  624.         debug_mode = 1;
  625.     }
  626. }
  627.  
  628. static void print_reason(void)
  629. {
  630.     int n, i;
  631.     i = tss_ptr->tss_irqn;
  632.     if ((i == 0x21) && ((tss_ptr->tss_eax & 0xff00) == 0x4c00)) {
  633.         tss_ptr->tss_eip -= 2;    /* point to int 21h */
  634.         return;
  635.     }
  636.     if (use_ansi)
  637.         printf("\033[1;34m");
  638.     mono_attr = MONO_BOLD;
  639.     if (i != 1) {
  640.         tssprint(tss_ptr);
  641.         if (tss_ptr != &a_tss) {
  642.             printf("internal error: tss_ptr NOT a_tss\n");
  643.         }
  644.         if (i == 0x79)
  645.             printf("Keyboard interrupt\n");
  646.         else if (i == 0x75) {
  647.             save_npx();
  648.             printf("Numeric Exception (");
  649.             if ((npx.status & 0x0241) == 0x0241)
  650.                 printf("stack overflow");
  651.             else if ((npx.status & 0x0241) == 0x0041)
  652.                 printf("stack underflow");
  653.             else if (npx.status & 1)
  654.                 printf("invalid operation");
  655.             else if (npx.status & 2)
  656.                 printf("denormal operand");
  657.             else if (npx.status & 4)
  658.                 printf("divide by zero");
  659.             else if (npx.status & 8)
  660.                 printf("overflow");
  661.             else if (npx.status & 16)
  662.                 printf("underflow");
  663.             else if (npx.status & 32)
  664.                 printf("loss of precision");
  665.             printf(") at eip=%#08lx\n", npx.eip);
  666.             unassemble(npx.eip, 0);
  667.         } else {
  668.             printf("exception %d (%#02x) occurred", i, i);
  669.             if ((i == 8) || ((i >= 10) && (i <= 14)))
  670.                 printf(", error code=%#lx", tss_ptr->tss_error);
  671.             mputchar('\n');
  672.         }
  673.     }
  674.     for (n = 0; n < 3; n++)
  675.         if ((dr6 & (1 << n)) && (dr7 & (3 << (n * 2))))
  676.             printf("breakpoint %d hit\n", n);
  677.     if (use_ansi)
  678.         printf("\033[0m");
  679.     mono_attr = MONO_NORMAL;
  680. }
  681.  
  682. /* This is file UNASSMBL.C */
  683. static int seg_size = 32;
  684.  
  685. static word8 buf[20];
  686. static word32 vaddr;
  687. static int bufp, bufe;
  688. static char ubuf[100], *ubufp;
  689. static int col;
  690.  
  691. /* Percent tokens in strings:
  692.    First char after '%':
  693.    A - direct address
  694.    C - reg of r/m picks control register
  695.    D - reg of r/m picks debug register
  696.    E - r/m picks operand
  697.    F - flags register
  698.    G - reg of r/m picks general register
  699.    I - immediate data
  700.    J - relative IP offset
  701.    M - r/m picks memory
  702.    O - no r/m, offset only
  703.    R - mod of r/m picks register only
  704.    S - reg of r/m picks segment register
  705.    T - reg of r/m picks test register
  706.    X - DS:ESI
  707.    Y - ES:EDI
  708.    2 - prefix of two-byte opcode
  709.    e - put in 'e' if use32 (second char is part of reg name)
  710.    put in 'w' for use16 or 'd' for use32 (second char is 'w')
  711.    f - floating point (second char is esc value)
  712.    g - do r/m group 'n'
  713.    p - prefix
  714.    s - size override (second char is a,o)
  715.    Second char after '%':
  716.    a - two words in memory (BOUND)
  717.    b - byte
  718.    c - byte or word
  719.    d - dword
  720.    p - 32 or 48 bit pointer
  721.    s - six byte pseudo-descriptor
  722.    v - word or dword
  723.    w - word
  724.    F - use floating regs in mod/rm
  725.    1-8 - group number, esc value, etc
  726.  */
  727.  
  728. static char *opmap1[] =
  729. {
  730. /* 0 */
  731.     "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  732.     "add al,%Ib", "add %eax,%Iv", "push es", "pop es",
  733.     "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  734.     "or al,%Ib", "or %eax,%Iv", "push cs", "%2 ",
  735. /* 1 */
  736.     "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  737.     "adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss",
  738.     "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  739.     "sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds",
  740. /* 2 */
  741.     "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  742.     "and al,%Ib", "and %eax,%Iv", "%pe", "daa",
  743.     "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  744.     "sub al,%Ib", "sub %eax,%Iv", "%pc", "das",
  745. /* 3 */
  746.     "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  747.     "xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa",
  748.     "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  749.     "cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas",
  750. /* 4 */
  751.     "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  752.     "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  753.     "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  754.     "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  755. /* 5 */
  756.     "push %eax", "push %ecx", "push %edx", "push %ebx",
  757.     "push %esp", "push %ebp", "push %esi", "push %edi",
  758.     "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  759.     "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  760. /* 6 */
  761.     "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  762.     "%pf", "%pg", "%so", "%sa",
  763.     "push %Iv", "imul %Gv=%Ev*%Iv", "push %Ib", "imul %Gv=%Ev*%Ib",
  764.     "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  765. /* 7 */
  766.     "jo %Jb", "jno %Jb", "jnc %Jb", "jc %Jb",
  767.     "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  768.     "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  769.     "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  770. /* 8 */
  771.     "%g1 %Eb,%Ib", "%g1 %Ev,%Iv", "mov al,%Ib", "%g1 %Ev,%Ib",
  772.     "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  773.     "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  774.     "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  775. /* 9 */
  776.     "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  777.     "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  778.     "cbw", "cwd", "call %Ap", "fwait",
  779.     "push %eflags", "pop %eflags", "sahf", "lahf",
  780. /* a */
  781.     "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  782.     "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  783.     "test al,%Ib", "test %eax,%Iv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  784.     "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  785. /* b */
  786.     "mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib",
  787.     "mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib",
  788.     "mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv",
  789.     "mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv",
  790. /* c */
  791.     "%g2 %Eb,%Ib", "%g2 %Ev,%Ib", "ret %Iw", "ret",
  792.     "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv",
  793.     "enter %Iw,%Ib", "leave", "retf %Iw", "retf",
  794.     "int 3", "int %Ib", "into", "iret",
  795. /* d */
  796.     "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  797.     "aam", "aad", 0, "xlat",
  798.     "%f0", "%f1", "%f2", "%f3",
  799.     "%f4", "%f5", "%f6", "%f7",
  800. /* e */
  801.     "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  802.     "in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax",
  803.     "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  804.     "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  805. /* f */
  806.     "lock %p ", 0, "repne %p ", "rep(e) %p ",
  807.     "hlt", "cmc", "%g3", "%g0",
  808.     "clc", "stc", "cli", "sti",
  809.     "cld", "std", "%g4", "%g5"
  810. };
  811.  
  812. static char *second[] =
  813. {
  814. /* 0 */
  815.     "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  816.     0, 0, 0, 0, 0, 0, 0, 0,
  817. /* 1 */
  818.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  819. /* 2 */
  820.     "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  821.     "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  822.     0, 0, 0, 0, 0, 0, 0, 0,
  823. /* 3 */
  824.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  825.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  826.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  827.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  828.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  829. /* 8 */
  830.     "jo %Jv", "jno %Jv", "jnc %Jv", "jc %Jv",
  831.     "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  832.     "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  833.     "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  834. /* 9 */
  835.     "seto %Eb", "setno %Eb", "setnc %Eb", "setc %Eb",
  836.     "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  837.     "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb",
  838.     "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  839. /* a */
  840.     "push fs", "pop fs", 0, "bt %Ev,%Gv",
  841.     "shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0,
  842.     "push gs", "pop gs", 0, "bts %Ev,%Gv",
  843.     "shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  844. /* b */
  845.     0, 0, "lss %Mp", "btr %Ev,%Gv",
  846.     "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  847.     0, 0, "%g8 %Ev,%Ib", "btc %Ev,%Gv",
  848.     "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  849. /* c */
  850.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  851.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  852.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  853.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  854. };
  855.  
  856. static char *groups[][8] =
  857. {                                /* group 0 is group 3 for %Ev set */
  858.     {"test %Ev,%Iv", "test %Ev,%Iv,", "not %Ev", "neg %Ev",
  859.      "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev"},
  860.     {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"},
  861.     {"rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar"},
  862.     {"test %Eb,%Ib", "test %Eb,%Ib,", "not %Eb", "neg %Eb",
  863.      "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb"},
  864.     {"inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0},
  865.     {"inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  866.      "jmp %Ev", "jmp %Ep", "push %Ev", 0},
  867.     {"sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  868.      "verr %Ew", "verw %Ew", 0, 0},
  869.     {"sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  870.      "smsw %Ew", 0, "lmsw %Ew", 0},
  871.     {0, 0, 0, 0, "bt", "bts", "btr", "btc"}
  872. };
  873.  
  874. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  875. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  876. static char *f0[] =
  877. {0, 0, 0, 0, 0, 0, 0, 0};
  878. static char *fop_9[] =
  879. {"*fxch st,%GF"};
  880. static char *fop_10[] =
  881. {"fnop", 0, 0, 0, 0, 0, 0, 0};
  882. static char *fop_12[] =
  883. {"fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0};
  884. static char *fop_13[] =
  885. {"fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz", 0};
  886. static char *fop_14[] =
  887. {"f2xm1", "fyl2x", "fptan", "fpatan", "fxtract", "fprem1", "fdecstp", "fincstp"};
  888. static char *fop_15[] =
  889. {"fprem", "fyl2xp1", "fsqrt", "fsincos", "frndint", "fscale", "fsin", "fcos"};
  890. static char *fop_21[] =
  891. {0, "fucompp", 0, 0, 0, 0, 0, 0};
  892. static char *fop_28[] =
  893. {0, 0, "fclex", "finit", 0, 0, 0, 0};
  894. static char *fop_32[] =
  895. {"*fadd %GF,st"};
  896. static char *fop_33[] =
  897. {"*fmul %GF,st"};
  898. static char *fop_36[] =
  899. {"*fsubr %GF,st"};
  900. static char *fop_37[] =
  901. {"*fsub %GF,st"};
  902. static char *fop_38[] =
  903. {"*fdivr %GF,st"};
  904. static char *fop_39[] =
  905. {"*fdiv %GF,st"};
  906. static char *fop_40[] =
  907. {"*ffree %GF"};
  908. static char *fop_42[] =
  909. {"*fst %GF"};
  910. static char *fop_43[] =
  911. {"*fstp %GF"};
  912. static char *fop_44[] =
  913. {"*fucom %GF"};
  914. static char *fop_45[] =
  915. {"*fucomp %GF"};
  916. static char *fop_48[] =
  917. {"*faddp %GF,st"};
  918. static char *fop_49[] =
  919. {"*fmulp %GF,st"};
  920. static char *fop_51[] =
  921. {0, "fcompp", 0, 0, 0, 0, 0, 0};
  922. static char *fop_52[] =
  923. {"*fsubrp %GF,st"};
  924. static char *fop_53[] =
  925. {"*fsubp %GF,st"};
  926. static char *fop_54[] =
  927. {"*fdivrp %GF,st"};
  928. static char *fop_55[] =
  929. {"*fdivp %GF,st"};
  930. static char *fop_60[] =
  931. {"fstsw ax", 0, 0, 0, 0, 0, 0, 0};
  932.  
  933. static char **fspecial[] =
  934. {                                /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  935.     0, 0, 0, 0, 0, 0, 0, 0,
  936.     0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  937.     f0, f0, f0, f0, f0, fop_21, f0, f0,
  938.     f0, f0, f0, f0, fop_28, f0, f0, f0,
  939.     fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  940.     fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  941.     fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  942.     f0, f0, f0, f0, fop_60, f0, f0, f0,
  943. };
  944.  
  945. static char *floatops[] =
  946. {                                /* assumed " %EF" at end of each.  mod != 3 only */
  947. /*00 */ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
  948. /*08 */ "fld", 0, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
  949. /*16 */ "fiadd", "fimul", "ficomw", "ficompw", "fisub", "fisubr", "fidiv", "fidivr",
  950. /*24 */ "fild", 0, "fist", "fistp", "frstor", "fldt", 0, "fstpt",
  951. /*32 */ "faddq", "fmulq", "fcomq", "fcompq", "fsubq", "fsubrq", "fdivq", "fdivrq",
  952. /*40 */ "fldq", 0, "fstq", "fstpq", 0, 0, "fsave", "fstsww",
  953. /*48 */ "fiaddw", "fimulw", "ficomw", "ficompw", "fisubw", "fisubrw", "fidivw", "fidivr",
  954. /*56 */ "fildw", 0, "fistw", "fistpw", "fbldt", "fildq", "fbstpt", "fistpq"
  955. };
  956.  
  957. static word8 getbyte(void)
  958. {
  959.     int s;
  960.     if (bufp >= bufe) {
  961.         s = 20;
  962.         if ((vaddr & 0xfff) + s > 0x1000)
  963.             s = 0x1000 - (int)(vaddr & 0xfff);
  964.         memget(vaddr + ARENA, buf, s);
  965.         bufe = s;
  966.         bufp = 0;
  967.     }
  968.     vaddr++;
  969.     printf("%02x", buf[bufp]);
  970.     col += 2;
  971.     return buf[bufp++];
  972. }
  973.  
  974. static int prefix;
  975. static int modrmv;
  976. static int sibv;
  977. static int opsize;
  978. static int addrsize;
  979.  
  980. static int modrm(void)
  981. {
  982.     if (modrmv == -1)
  983.         modrmv = getbyte();
  984.     return modrmv;
  985. }
  986.  
  987. static int sib(void)
  988. {
  989.     if (sibv == -1)
  990.         sibv = getbyte();
  991.     return sibv;
  992. }
  993.  
  994. #define mod(a)    (((a)>>6)&7)
  995. #define reg(a)    (((a)>>3)&7)
  996. #define rm(a)    ((a)&7)
  997. #define ss(a)    (((a)>>6)&7)
  998. #define indx(a)    (((a)>>3)&7)
  999. #define base(a)    ((a)&7)
  1000.  
  1001. /*------------------------------------------------------------------------*/
  1002. static void __cdecl uprintf(char *s,...)
  1003. {
  1004.     va_list ap;
  1005.  
  1006.     va_start(ap, s);
  1007.     vsprintf(ubufp, s, ap);
  1008.     va_end(ap);
  1009.  
  1010.     while (*ubufp)
  1011.         ubufp++;
  1012. }
  1013.  
  1014. static void __pascal uputchar(char c)
  1015. {
  1016.     if (c == '\t') {
  1017.         do {
  1018.             *ubufp++ = ' ';
  1019.         } while ((ubufp - ubuf) % 8);
  1020.     } else
  1021.         *ubufp++ = c;
  1022.     *ubufp = 0;
  1023. }
  1024.  
  1025. /*------------------------------------------------------------------------*/
  1026. static int bytes(char c)
  1027. {
  1028.     switch (c) {
  1029.     case 'b':
  1030.         return 1;
  1031.     case 'w':
  1032.         return 2;
  1033.     case 'd':
  1034.         return 4;
  1035.     case 'v':
  1036.         if (opsize == 32)
  1037.             return 4;
  1038.         else
  1039.             return 2;
  1040.     }
  1041.     return 0;
  1042. }
  1043.  
  1044. /*------------------------------------------------------------------------*/
  1045. static void __pascal ohex(char c, int extend, int optional, int defsize, int sign)
  1046. {
  1047.     int n, s, i;
  1048.     int32 delta;
  1049.     unsigned char buf[6];
  1050.     char *name;
  1051.     n = s = 0;
  1052.  
  1053.     switch (c) {
  1054.     case 'a':
  1055.         break;
  1056.     case 'b':
  1057.         n = 1;
  1058.         break;
  1059.     case 'w':
  1060.         n = 2;
  1061.         break;
  1062.     case 'd':
  1063.         n = 4;
  1064.         break;
  1065.     case 's':
  1066.         n = 6;
  1067.         break;
  1068.     case 'c':
  1069.     case 'v':
  1070.         n = (defsize == 32) ? 4 : 2;
  1071.         break;
  1072.     case 'p':
  1073.         n = (defsize == 32) ? 6 : 4;
  1074.         s = 1;
  1075.         break;
  1076.     }
  1077.     for (i = 0; i < n; i++)
  1078.         buf[i] = getbyte();
  1079.     for (; i < extend; i++)
  1080.         buf[i] = (buf[i - 1] & 0x80) ? 0xff : 0;
  1081.     if (s) {
  1082.         uprintf("%#02x%02x:", buf[n - 1], buf[n - 2]);
  1083.         n -= 2;
  1084.     }
  1085.     switch (n) {
  1086.     case 1:
  1087.         delta = *(signed char *)buf;
  1088.         break;
  1089.     case 2:
  1090.         delta = *(signed int *)buf;
  1091.         break;
  1092.     case 4:
  1093.         delta = *(signed long *)buf;
  1094.         break;
  1095.     }
  1096.     if (extend > n) {
  1097.         if (delta || !optional)
  1098.             uprintf("%+ld", delta);
  1099.         return;
  1100.     }
  1101.     if ((n == 4) && !sign) {
  1102.         name = syms_val2name((word32) delta, (word32 *) & delta);
  1103.         if (name) {
  1104.             uprintf("%s", name);
  1105.             if (delta)
  1106.                 uprintf("+%lu", delta);
  1107.             return;
  1108.         }
  1109.     }
  1110.     switch (n) {
  1111.     case 1:
  1112.         if (sign)
  1113.             uprintf("%+d", (unsigned char)delta);
  1114.         else
  1115.             uprintf("%#x", (unsigned char)delta);
  1116.         break;
  1117.     case 2:
  1118.         if (sign)
  1119.             uprintf("%+d", (unsigned int)delta);
  1120.         else
  1121.             uprintf("%#x", (unsigned int)delta);
  1122.         break;
  1123.     case 4:
  1124.         if (sign)
  1125.             uprintf("%+ld", (unsigned long)delta);
  1126.         else
  1127.             uprintf("%#lx", (unsigned long)delta);
  1128.         break;
  1129.     }
  1130. }
  1131.  
  1132. /*------------------------------------------------------------------------*/
  1133.  
  1134. static char *reg_names[3][8] =
  1135. {
  1136.     {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"},
  1137.     {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"},
  1138.     {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}};
  1139.  
  1140. static void __pascal reg_name(int which, char size)
  1141. {
  1142.     if (size == 'F') {
  1143.         uprintf("st(%d)", which);
  1144.         return;
  1145.     }
  1146.     if (((size == 'v') && (opsize == 32)) || (size == 'd')) {
  1147.         uputchar('e');
  1148.     }
  1149.     if (size == 'b') {
  1150.         uputchar("acdbacdb"[which]);
  1151.         uputchar("llllhhhh"[which]);
  1152.     } else {
  1153.         uputchar("acdbsbsd"[which]);
  1154.         uputchar("xxxxppii"[which]);
  1155.     }
  1156. }
  1157.  
  1158. /*------------------------------------------------------------------------*/
  1159. static void do_sib(int m)
  1160. {
  1161.     int s, i, b;
  1162.     s = ss(sib());
  1163.     i = indx(sib());
  1164.     b = base(sib());
  1165.     switch (b) {
  1166.     case 0:
  1167.         ua_str("%p:[eax");
  1168.         break;
  1169.     case 1:
  1170.         ua_str("%p:[ecx");
  1171.         break;
  1172.     case 2:
  1173.         ua_str("%p:[edx");
  1174.         break;
  1175.     case 3:
  1176.         ua_str("%p:[ebx");
  1177.         break;
  1178.     case 4:
  1179.         ua_str("%p:[esp");
  1180.         break;
  1181.     case 5:
  1182.         if (!m) {
  1183.             ua_str("%p:[");
  1184.             ohex('d', 4, 0, addrsize, 0);
  1185.         } else
  1186.             ua_str("%p:[ebp");
  1187.         break;
  1188.     case 6:
  1189.         ua_str("%p:[esi");
  1190.         break;
  1191.     case 7:
  1192.         ua_str("%p:[edi");
  1193.         break;
  1194.     }
  1195.     switch (i) {
  1196.     case 0:
  1197.         uprintf("+eax");
  1198.         break;
  1199.     case 1:
  1200.         uprintf("+ecx");
  1201.         break;
  1202.     case 2:
  1203.         uprintf("+edx");
  1204.         break;
  1205.     case 3:
  1206.         uprintf("+ebx");
  1207.         break;
  1208.     case 4:
  1209.         break;
  1210.     case 5:
  1211.         uprintf("+ebp");
  1212.         break;
  1213.     case 6:
  1214.         uprintf("+esi");
  1215.         break;
  1216.     case 7:
  1217.         uprintf("+edi");
  1218.         break;
  1219.     }
  1220.     if (i != 4)
  1221.         switch (s) {
  1222.         case 0:
  1223.             uprintf("");
  1224.             break;
  1225.         case 1:
  1226.             uprintf("*2");
  1227.             break;
  1228.         case 2:
  1229.             uprintf("*4");
  1230.             break;
  1231.         case 3:
  1232.             uprintf("*8");
  1233.             break;
  1234.         }
  1235. }
  1236. /*------------------------------------------------------------------------*/
  1237. static void __pascal do_modrm(char t)
  1238. {
  1239.     int m = mod(modrm());
  1240.     int r = rm(modrm());
  1241.     int extend = (addrsize == 32) ? 4 : 2;
  1242.     if (m == 3) {
  1243.         reg_name(r, t);
  1244.         return;
  1245.     }
  1246.     if (!m && (r == 5) && (addrsize == 32)) {
  1247.         ua_str("%p:[");
  1248.         ohex('d', extend, 0, addrsize, 0);
  1249.         uputchar(']');
  1250.         return;
  1251.     }
  1252.     if (!m && (r == 6) && (addrsize == 16)) {
  1253.         ua_str("%p:[");
  1254.         ohex('w', extend, 0, addrsize, 0);
  1255.         uputchar(']');
  1256.         return;
  1257.     }
  1258.     if ((addrsize != 32) || (r != 4))
  1259.         ua_str("%p:[");
  1260.     if (addrsize == 16) {
  1261.         switch (r) {
  1262.         case 0:
  1263.             uprintf("bx+si");
  1264.             break;
  1265.         case 1:
  1266.             uprintf("bx+di");
  1267.             break;
  1268.         case 2:
  1269.             uprintf("bp+si");
  1270.             break;
  1271.         case 3:
  1272.             uprintf("bp+di");
  1273.             break;
  1274.         case 4:
  1275.             uprintf("si");
  1276.             break;
  1277.         case 5:
  1278.             uprintf("di");
  1279.             break;
  1280.         case 6:
  1281.             uprintf("bp");
  1282.             break;
  1283.         case 7:
  1284.             uprintf("bx");
  1285.             break;
  1286.         }
  1287.     } else {
  1288.         switch (r) {
  1289.         case 0:
  1290.             uprintf("eax");
  1291.             break;
  1292.         case 1:
  1293.             uprintf("ecx");
  1294.             break;
  1295.         case 2:
  1296.             uprintf("edx");
  1297.             break;
  1298.         case 3:
  1299.             uprintf("ebx");
  1300.             break;
  1301.         case 4:
  1302.             do_sib(m);
  1303.             break;
  1304.         case 5:
  1305.             uprintf("ebp");
  1306.             break;
  1307.         case 6:
  1308.             uprintf("esi");
  1309.             break;
  1310.         case 7:
  1311.             uprintf("edi");
  1312.             break;
  1313.         }
  1314.     }
  1315.     switch (m) {
  1316.     case 1:
  1317.         ohex('b', extend, 1, addrsize, 0);
  1318.         break;
  1319.     case 2:
  1320.         ohex('v', extend, 1, addrsize, 1);
  1321.         break;
  1322.     }
  1323.     uputchar(']');
  1324. }
  1325.  
  1326. /*------------------------------------------------------------------------*/
  1327. static void floating_point(int e1)
  1328. {
  1329.     int esc = e1 * 8 + reg(modrm());
  1330.     if (mod(modrm()) == 3) {
  1331.         if (fspecial[esc]) {
  1332.             if (fspecial[esc][0][0] == '*') {
  1333.                 ua_str(fspecial[esc][0] + 1);
  1334.             } else {
  1335.                 ua_str(fspecial[esc][rm(modrm())]);
  1336.             }
  1337.         } else {
  1338.             ua_str(floatops[esc]);
  1339.             ua_str(" %EF");
  1340.         }
  1341.     } else {
  1342.         ua_str(floatops[esc]);
  1343.         ua_str(" %EF");
  1344.     }
  1345. }
  1346.  
  1347. /*------------------------------------------------------------------------*/
  1348. static void percent(char c, char t)
  1349. {
  1350.     word32 vofs, delta;
  1351.     char *name;
  1352.     int extend = (addrsize == 32) ? 4 : 2;
  1353.     switch (c) {
  1354.     case 'A':
  1355.         ohex(t, extend, 0, addrsize, 0);
  1356.         break;
  1357.     case 'C':
  1358.         uprintf("cr%d", reg(modrm()));
  1359.         break;
  1360.     case 'D':
  1361.         uprintf("dr%d", reg(modrm()));
  1362.         break;
  1363.     case 'E':
  1364.         do_modrm(t);
  1365.         break;
  1366.     case 'G':
  1367.         if (t == 'F')
  1368.             reg_name(rm(modrm()), t);
  1369.         else
  1370.             reg_name(reg(modrm()), t);
  1371.         break;
  1372.     case 'I':
  1373.         ohex(t, 0, 0, opsize, 0);
  1374.         break;
  1375.     case 'J':
  1376.         switch (bytes(t)) {
  1377.         case 1:
  1378.             vofs = (int8) getbyte();
  1379.             break;
  1380.         case 2:
  1381.             vofs = getbyte();
  1382.             vofs += getbyte() << 8;
  1383.             vofs = (int16) vofs;
  1384.             break;
  1385.         case 4:
  1386.             vofs = (word32) getbyte();
  1387.             vofs |= (word32) getbyte() << 8;
  1388.             vofs |= (word32) getbyte() << 16;
  1389.             vofs |= (word32) getbyte() << 24;
  1390.             break;
  1391.         }
  1392.         name = syms_val2name(vofs + vaddr, &delta);
  1393.         uprintf("%s", name);
  1394.         if (delta)
  1395.             uprintf("+%lu (%#lx %c)", delta, vofs + vaddr, (vofs & 0x80000000L) ? 0x1e : 0x1f);
  1396.         break;
  1397.     case 'M':
  1398.         do_modrm(t);
  1399.         break;
  1400.     case 'O':
  1401.         ua_str("%p:[");
  1402.         ohex(t, extend, 0, addrsize, 0);
  1403.         uputchar(']');
  1404.         break;
  1405.     case 'R':
  1406.         do_modrm(t);
  1407.         break;
  1408.     case 'S':
  1409.         uputchar("ecsdfg"[reg(modrm())]);
  1410.         uputchar('s');
  1411.         break;
  1412.     case 'T':
  1413.         uprintf("tr%d", reg(modrm()));
  1414.         break;
  1415.     case 'X':
  1416.         uprintf("ds:[");
  1417.         if (addrsize == 32)
  1418.             uputchar('e');
  1419.         uprintf("si]");
  1420.         break;
  1421.     case 'Y':
  1422.         uprintf("es:[");
  1423.         if (addrsize == 32)
  1424.             uputchar('e');
  1425.         uprintf("di]");
  1426.         break;
  1427.     case '2':
  1428.         ua_str(second[getbyte()]);
  1429.         break;
  1430.     case 'e':
  1431.         if (opsize == 32) {
  1432.             if (t == 'w')
  1433.                 uputchar('d');
  1434.             else {
  1435.                 uputchar('e');
  1436.                 uputchar(t);
  1437.             }
  1438.         } else
  1439.             uputchar(t);
  1440.         break;
  1441.     case 'f':
  1442.         floating_point(t - '0');
  1443.         break;
  1444.     case 'g':
  1445.         ua_str(groups[t - '0'][reg(modrm())]);
  1446.         break;
  1447.     case 'p':
  1448.         switch (t) {
  1449.         case 'c':
  1450.         case 'd':
  1451.         case 'e':
  1452.         case 'f':
  1453.         case 'g':
  1454.         case 's':
  1455.             prefix = t;
  1456.             ua_str(opmap1[getbyte()]);
  1457.             break;
  1458.         case ':':
  1459.             if (prefix)
  1460.                 uprintf("%cs:", prefix);
  1461.             break;
  1462.         case ' ':
  1463.             ua_str(opmap1[getbyte()]);
  1464.             break;
  1465.         }
  1466.         break;
  1467.     case 's':
  1468.         switch (t) {
  1469.         case 'a':
  1470.             addrsize = 48 - addrsize;
  1471.             ua_str(opmap1[getbyte()]);
  1472.             break;
  1473.         case 'o':
  1474.             opsize = 48 - opsize;
  1475.             ua_str(opmap1[getbyte()]);
  1476.             break;
  1477.         }
  1478.         break;
  1479.     }
  1480. }
  1481.  
  1482. static void __pascal ua_str(char *s)
  1483. {
  1484.     int c;
  1485.     if (!s) {
  1486.         uprintf("<invalid>");
  1487.         return;
  1488.     }
  1489.     while ((c = *s++) != 0) {
  1490.         if (c == '%') {
  1491.             c = *s++;
  1492.             percent(c, *s++);
  1493.         } else if (c == ' ')
  1494.             uputchar('\t');
  1495.         else
  1496.             uputchar(c);
  1497.     }
  1498. }
  1499.  
  1500. #ifdef SOURCE_LIST
  1501. /*
  1502.    ** A little brute force hacking and hey presto! A source debugger!
  1503.    ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  1504.    **
  1505.    ** KNOWN BUGS:
  1506.    ** The program will summarily terminate if you run out
  1507.    ** of memory while you're looking for all the line offsets.  Since
  1508.    ** a two thousand line source file only creats an 8K array, and the
  1509.    ** symbol table goes into virtual memory, this shouldn't happen too
  1510.    ** often.
  1511.    **
  1512.    ** One file is left open for reading indefinitely.
  1513.    ** keep the source line offsets in virtual memory, so you can
  1514.    ** debug big programs
  1515.    ** for each file encountered, keep an array of line start offsets
  1516.    ** so you can seek into the file to display the current line.
  1517.  */
  1518. typedef struct {
  1519.     char *filename;
  1520.     word32 offsets;
  1521. } line_info;
  1522.  
  1523. static line_info files[32];
  1524. static last_file = 0;
  1525.  
  1526. /*
  1527.    ** these don't seem to be defined anywhere else ...
  1528.  */
  1529. static void *__pascal xmalloc(unsigned size)
  1530. {
  1531.     void *rval = malloc(size);
  1532.     if (!rval) {
  1533.         fprintf(stderr, "Out of memory\n");
  1534.         exit(1);
  1535.     }
  1536.     return rval;
  1537. }
  1538.  
  1539. static void *xrealloc(void *rval, unsigned size)
  1540. {
  1541.     rval = realloc(rval, size);
  1542.     if (!rval) {
  1543.         fprintf(stderr, "Out of memory\n");
  1544.         exit(1);
  1545.     }
  1546.     return rval;
  1547. }
  1548.  
  1549. static char *xstrdup(char *s)
  1550. {
  1551.     char *rval = xmalloc(strlen(s) + 1);
  1552.     strcpy(rval, s);
  1553.     return rval;
  1554. }
  1555.  
  1556. /*
  1557.    ** add_file -- add a file to the source line database
  1558.  */
  1559. static int add_file(char *name)
  1560. {
  1561.     FILE *f = fopen(name, "r");
  1562.     char c;
  1563.     long *lines, curpos;
  1564.     unsigned curline = 0;
  1565.  
  1566.     if (!f)
  1567.         return -1;
  1568.  
  1569.     files[last_file].filename = xstrdup(name);
  1570.     /*
  1571.        ** build an array of line offsets in real memory.
  1572.      */
  1573.     lines = xmalloc(sizeof(long));
  1574.     lines[curline++] = curpos = 0L;
  1575.  
  1576.     while ((c = fgetc(f)) != EOF) {
  1577.         curpos++;
  1578.         if (c == '\n') {
  1579.             lines = xrealloc(lines, sizeof(long) * (curline + 1));
  1580.             lines[curline++] = curpos;
  1581.         }
  1582.     }
  1583.     /*
  1584.        ** now move the whole array into virtual memory
  1585.      */
  1586.     files[last_file].offsets = salloc(curline * sizeof(long));
  1587.     symsput(files[last_file].offsets, lines, (curline * sizeof(long)));
  1588.     /*
  1589.        ** don't need the real memory version any more
  1590.      */
  1591.     free(lines);
  1592.  
  1593.     fclose(f);
  1594.  
  1595.     last_file++;
  1596.     return 0;
  1597. }
  1598.  
  1599. static line_info *__pascal find_file(char *name)
  1600. {
  1601.     int i;
  1602.     for (i = 0; i < last_file; i++)
  1603.         if (!strcmp(name, files[i].filename))
  1604.             return &files[i];
  1605.     if (add_file(name) == -1)
  1606.         return NULL;
  1607.     return find_file(name);
  1608. }
  1609.  
  1610. /*
  1611.    ** myfopen -- cache the most recently accessed source file
  1612.    ** so you aren't constantly reopening a new file
  1613.  */
  1614. static FILE *myfopen(char *name)
  1615. {
  1616.     static char fname[80] = "";
  1617.     static FILE *current = NULL;
  1618.     if (current != NULL && !strcmp(fname, name))
  1619.         return current;
  1620.     if (current != NULL)
  1621.         fclose(current);
  1622.     strcpy(fname, name);
  1623.     return (current = fopen(name, "r"));
  1624. }
  1625.  
  1626. /*
  1627.    ** put_source_line -- print the current source line, along with
  1628.    ** the line # and file name, if necessary.
  1629.  */
  1630. static void __pascal put_source_line(int fmt, char *name, int line)
  1631. {
  1632.     line_info *current = find_file(name);
  1633.     FILE *cur;
  1634.     if (current == NULL) {
  1635.       regular:
  1636.         if (!fmt)
  1637.             printf(" (%s#%d):\n", name, line);
  1638.         else
  1639.             printf("#%d:\n", line);
  1640.     } else {
  1641.         char buf[70];
  1642.         long offset;
  1643.         if ((cur = myfopen(name)) == NULL)
  1644.             goto regular;
  1645.         /*
  1646.            ** get the symbol out of virtual memory
  1647.          */
  1648.         symsget(current->offsets + ((line - 1) * sizeof(long)),
  1649.                 &offset, sizeof(long));
  1650.         fseek(cur, offset, SEEK_SET);
  1651.         /*
  1652.            ** truncate line so it fits on screen.
  1653.          */
  1654.         fgets(buf, sizeof(buf) - 2, cur);
  1655.         if (strchr(buf, '\n') == NULL)
  1656.             strcat(buf, "\n");
  1657.         if (!fmt)
  1658.             printf(" (%s#%d): %s", name, line, buf);
  1659.         else
  1660.             printf("#%d: %s", line, buf);
  1661.     }
  1662. }
  1663.  
  1664. #endif
  1665.  
  1666. static word32 __pascal unassemble(word32 v, int showregs)
  1667. {
  1668.     int a, b, n, wi, linenum;
  1669.     char *cmp, *brp;
  1670.     word8 *wp;
  1671.     word32 delta;
  1672.     char *name, *lname;
  1673.  
  1674.     last_unassemble_unconditional = last_unassemble_jump = last_unassemble_extra_lines = 0;
  1675.     name = syms_val2name(v, &delta);
  1676.     if (use_ansi)
  1677.         printf("\033[1;36m");
  1678.     mono_attr = MONO_BOLD;
  1679.     if (!delta && (name[0] != '0')) {
  1680.         printf("%s()", name);
  1681.         lname = syms_val2line(v, &linenum, 1);
  1682.         if (lname)
  1683. #ifndef SOURCE_LIST
  1684.             printf(" (%s#%d):\n", lname, linenum);
  1685. #else
  1686.             put_source_line(0, lname, linenum);
  1687. #endif
  1688.         else
  1689.             printf(":\n");
  1690.         last_unassemble_extra_lines++;
  1691.     } else {
  1692.         lname = syms_val2line(v, &linenum, 1);
  1693.         if (lname) {
  1694. #ifndef SOURCE_LIST
  1695.             printf("#%d:\n", linenum);
  1696. #else
  1697.             put_source_line(1, lname, linenum);
  1698. #endif
  1699.             last_unassemble_extra_lines++;
  1700.         }
  1701.     }
  1702.  
  1703.     if (use_ansi)
  1704.         printf("\033[0m");
  1705.     mono_attr = MONO_NORMAL;
  1706.     printf("%08lx: ", v);
  1707.     if (!page_is_valid(v + ARENA) || !page_is_valid(v + 5 + ARENA)) {
  1708.         printf("<bad address>\n");
  1709.         return v;
  1710.     }
  1711.     prefix = bufp = bufe = col = 0;
  1712.     modrmv = sibv = -1;
  1713.     opsize = addrsize = seg_size;
  1714.     vaddr = v;
  1715.     ubufp = ubuf;
  1716.     ua_str(opmap1[getbyte()]);
  1717.     do {
  1718.         mputchar(' ');
  1719.         col++;
  1720.     } while (col < 15);
  1721.     col += strlen(ubuf);
  1722.     do {
  1723.         uputchar(' ');
  1724.         col++;
  1725.     } while (col < 43);
  1726.     if (use_ansi)
  1727.         printf("\033[1m");
  1728.     mono_attr = MONO_BOLD;
  1729.     printf("%s", ubuf);
  1730.     if (use_ansi)
  1731.         printf("\033[0m");
  1732.     mono_attr = MONO_NORMAL;
  1733.  
  1734.     if (!strncmp(ubuf, "jmp ", 4) || !strncmp(ubuf, "ret", 3))
  1735.         last_unassemble_unconditional = 1;
  1736.     if (ubuf[0] == 'j')
  1737.         last_unassemble_jump = 1;
  1738.  
  1739.     if (!showregs) {
  1740.         mputchar('\n');
  1741.         return vaddr;
  1742.     }
  1743.     col -= 43;                    /* total 25 columns left */
  1744.     wp = (word8 *) & (tss_ptr->tss_eax);
  1745.     cmp = strchr(ubuf + 8, ',');
  1746.     brp = strchr(ubuf + 8, '[');
  1747.     if (!cmp)
  1748.         cmp = ubuf + 8;
  1749.     if (!brp)
  1750.         brp = ubufp;
  1751.     if (brp < cmp)
  1752.         cmp = brp;
  1753.     if (strncmp(ubuf, "mov ", 4))
  1754.         cmp = ubuf + 8;
  1755.     for (b = 0; b < 8; b++) {
  1756.         for (a = 2; a >= 0; a--) {
  1757.             n = (!a) ? 1 : ((a == 1) ? 2 : 4);
  1758.             if (strstr(cmp, reg_names[a][b])) {
  1759.                 col += strlen(reg_names[a][b]) + n * 2 + 2;
  1760.                 if (col > 29) {
  1761.                     printf("\n%53s", "");
  1762.                     col = 0;
  1763.                 }
  1764.                 printf("%s=", reg_names[a][b]);
  1765.                 wi = (!a) ? ((b & 3) * 4 + (b >> 2)) : (b * 4);
  1766.                 while (n) {
  1767.                     n--;
  1768.                     printf("%02x", wp[wi + n]);
  1769.                 }
  1770.                 mputchar(' ');
  1771.                 break;
  1772.             }
  1773.         }
  1774.     }
  1775.     mputchar('\n');
  1776.     return vaddr;
  1777. }
  1778.  
  1779. #endif /* DEBUGGER */
  1780.