home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / cl5sr386.zip / GO32 / DEBUG.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  20KB  |  745 lines

  1. /* This is file DEBUG.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:175,26 */
  16. #include <stdio.h>
  17. #include <setjmp.h>
  18. #include <math.h>
  19. #include <dos.h>
  20.  
  21. #include "build.h"
  22. #include "types.h"
  23. #include "gdt.h"
  24. #include "tss.h"
  25. #include "utils.h"
  26. #include "unassmbl.h"
  27. #include "syms.h"
  28. #include "paging.h"
  29. #include "npx.h"
  30. #include "mono.h"
  31.  
  32. extern int was_exception, have_80387;
  33. jmp_buf back_to_debugger;
  34. int can_longjmp=0;
  35.  
  36. #if DEBUGGER
  37.  
  38. #ifndef  NOEVENTS
  39. #include "eventque.h"
  40. extern   EventQueue *event_queue;
  41. #endif
  42.  
  43. extern word32 dr[8];
  44. extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
  45.  
  46. typedef struct {
  47.     char *cp;
  48.     int t;
  49.     } item;
  50.  
  51. my_getline(char *buf, char *lasttoken)
  52. {
  53.   int idx, i, ch;
  54. #ifndef NOEVENTS
  55.   unsigned char old_enable;
  56.  
  57.   if(event_queue != NULL) {
  58.     old_enable = event_queue->evq_enable;
  59.     event_queue->evq_enable = 0;
  60.   }
  61. #endif
  62.   if (use_ansi)
  63.     printf("\033[0;32m");
  64.   mono_attr = MONO_NORMAL;
  65.   printf(">> %s", lasttoken);
  66.   for (i=0; lasttoken[i]; i++)
  67.     mputchar(8);
  68.   while (!bioskey(1));
  69.   for (i=0; lasttoken[i]; i++)
  70.     mputchar(' ');
  71.   for (i=0; lasttoken[i]; i++)
  72.     mputchar(8);
  73.   idx = 0;
  74.   if (use_ansi)
  75.     printf("\033[1;33m");
  76.   mono_attr = MONO_BOLD;
  77.   while (1)
  78.   {
  79.     ch = bioskey(0) & 0xff;
  80.     switch (ch)
  81.     {
  82.       case 10:
  83.       case 13:
  84.         buf[idx] = 0;
  85.         if (!idx && lasttoken[0])
  86.           printf("\r  \r");
  87.         else
  88.           mputchar('\n');
  89.         if (use_ansi)
  90.           printf("\033[0m");
  91.         mono_attr = MONO_NORMAL;
  92. #ifndef NOEVENTS
  93.         if(event_queue != NULL)
  94.           event_queue->evq_enable = old_enable;
  95. #endif
  96.         return;
  97.       case 27:
  98.         while (idx)
  99.         {
  100.           printf("\b \b");
  101.           idx--;
  102.         }
  103.         break;
  104.       case 8:
  105.         if (idx)
  106.         {
  107.           printf("\b \b");
  108.           idx--;
  109.         }
  110.         break;
  111.       default:
  112.         mputchar(ch);
  113.         buf[idx++] = ch;
  114.         break;
  115.     }
  116.   }
  117. }
  118.  
  119. typedef enum { Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
  120. DUMP, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
  121. CLS };
  122.  
  123. extern struct {
  124.   char *name;
  125.   int size;
  126.   int ofs;
  127.   } regs[];
  128.  
  129. item cmds[] = {
  130.     "g", CONT,
  131.     "go", CONT,
  132.     "cont", CONT,
  133.     "c", CONT,
  134.     "step", STEP,
  135.     "s", STEP,
  136.     "next", NEXT,
  137.     "n", NEXT,
  138.     "regs", REGS,
  139.     "r", REGS,
  140.     "set", SET,
  141.     "help", HELP,
  142.     "h", HELP,
  143.     "?", HELP,
  144.     "list", LIST,
  145.     "l", LIST,
  146.     "u", LIST,
  147.     "dump", DUMP,
  148.     "d", DUMP,
  149.     "da", DUMP_A,
  150.     "db", DUMP_B,
  151.     "dw", DUMP_W,
  152.     "dd", DUMP,
  153.     "quit", QUIT,
  154.     "q", QUIT,
  155.     "break", BREAK,
  156.     "b", BREAK,
  157.     "status", STATUS,
  158.     "where", WHERE,
  159.     "whereis", WHEREIS,
  160.     "npx", XNPX,
  161.     "cls", CLS,
  162.     0, 0
  163.     };
  164.  
  165. extern int debug_mode;
  166.  
  167. debugger()
  168. {
  169.   char buf[140], token[10];
  170.   char buf2[140], *name, lasttoken[140];
  171.   int i, n, s, len, rem_cmd, cmd, vstep, found;
  172.   word32 vaddr, v, rem_v, olddr7;
  173.   int32 delta;
  174.  
  175.   dr0 = dr1 = dr2 = ARENA;
  176.   dr3 = syms_name2val("_main") + ARENA;
  177.   if (undefined_symbol)
  178.     dr3 = tss_ptr->tss_eip + ARENA;
  179.   rem_cmd = Zero;
  180.   lasttoken[0] = 0;
  181.   setjmp(back_to_debugger);
  182.   can_longjmp = 1;
  183.   while (1)
  184.   {
  185.     if (debug_mode)
  186.     {
  187.       int found;
  188.       my_getline(buf, lasttoken);
  189.       token[0] = 0;
  190.       if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
  191.         buf[0] = 0;
  192.       if (token[0])
  193.         strcpy(lasttoken, token);
  194.       cmd = rem_cmd;
  195.       found = 0;
  196.       for (i=0; cmds[i].cp; i++)
  197.         if (strcmp(cmds[i].cp, token) == 0)
  198.         {
  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.     }
  207.     else
  208.     {
  209.       cmd = CONT;
  210.       debug_mode = 1;
  211.     }
  212.     switch (cmd)
  213.     {
  214.       case HELP:
  215.         printf("Commands:\n");
  216.         printf("go <v>\tg\tgo, stop at <v>\n");
  217.         printf("cont\tc\tcontinue execution\n");
  218.         printf("step\ts\tstep through current instruction\n");
  219.         printf("next\tn\tstep to next instruction\n");
  220.         printf("list\tl u\tlist instructions (takes addr, count)\n");
  221.         printf("dump\td\tdump memory (takes addr, count)\n");
  222.         printf("break\tb\tset breakpoint (takes which, addr)\n");
  223.         printf("status\t\tbreakpoint status\n");
  224.         printf("regs\tr\tprint registers\n");
  225.         printf("set\t\tset register/memory\n");
  226.         printf("npx\t\tdisplay 80387 contents\n");
  227.         printf("where\t\tdisplay list of active functions\n");
  228.         printf("whereis\t\tfind a symbol/location (takes wildcard or value)\n");
  229.         printf("cls\t\tclear screen\n");
  230.         printf("help\th,?\tprint help\n");
  231.         printf("quit\tq\tquit\n");
  232.         break;
  233.       case CONT:
  234.         sscanf(buf, "%s", buf);
  235.         if (buf[0])
  236.         {
  237.           v = syms_name2val(buf);
  238.           if (undefined_symbol)
  239.             break;
  240.           dr3 = v+ARENA;
  241.           dr7 |= 0xc0;
  242.         }
  243.         else
  244.           dr7 &= ~0xc0;
  245.         olddr7 = dr7;
  246.         dr7 = 0;
  247.         tss_ptr->tss_eflags |= 0x0100;
  248.         go_til_stop();
  249.         dr7 = olddr7;
  250.         if (tss_ptr->tss_irqn == 1)
  251.         {
  252.           tss_ptr->tss_eflags &= ~0x0100;
  253.           tss_ptr->tss_eflags |= 0x10000;
  254.           go_til_stop();
  255.           if (tss_ptr->tss_irqn == 1)
  256.             tssprint(tss_ptr);
  257.         }
  258.         print_reason();
  259.         dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  260.         break;
  261.       case STEP:
  262.         if (rem_cmd != cmd)
  263.           n = 1;
  264.         sscanf(buf, "%d", &n);
  265.         tss_ptr->tss_eflags |= 0x0100;
  266.         for (i=0; i<n; i++)
  267.         {
  268.           olddr7 = dr7;
  269.           dr7 = 0;
  270.           go_til_stop();
  271.           dr7 = olddr7;
  272.           print_reason();
  273.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  274.           if (tss_ptr->tss_irqn != 1)
  275.             break;
  276.         }
  277.         tss_ptr->tss_eflags &= ~0x0100;
  278.         break;
  279.       case NEXT:
  280.         if (rem_cmd != cmd)
  281.           n = 1;
  282.         sscanf(buf, "%d", &n);
  283.         for (i=0; i<n; i++)
  284.         {
  285.           olddr7 = dr7;
  286.           dr7 &= ~0xc0;
  287.           dr7 |= 0xc0;
  288.           if (last_unassemble_unconditional ||
  289.               last_unassemble_jump)
  290.             tss_ptr->tss_eflags |= 0x0100; /* step */
  291.           else
  292.             tss_ptr->tss_eflags &= ~0x0100;
  293.           go_til_stop();
  294.           dr7 = olddr7;
  295.           print_reason();
  296.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  297.           if (tss_ptr->tss_irqn != 1)
  298.             break;
  299.         }
  300.         tss_ptr->tss_eflags &= ~0x0100;
  301.         break;
  302.       case WHERE:
  303.         v = tss_ptr->tss_ebp;
  304.         vaddr = tss_ptr->tss_eip;
  305.         printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  306.         name = syms_val2line(vaddr, &i, 0);
  307.         if (name)
  308.           printf(", line %d in file %s", i, name);
  309.         else if (delta)
  310.           printf("%+ld", delta);
  311.         mputchar('\n');
  312.         do {
  313.           if (v == 0)
  314.             break;
  315.           rem_v = peek32(v+ARENA);
  316.           if (rem_v == 0)
  317.             break;
  318.           vaddr = peek32(v+ARENA+4);
  319.           printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  320.           name = syms_val2line(vaddr, &i, 0);
  321.           if (name)
  322.             printf(", line %d in file %s", i, name);
  323.           else if (delta)
  324.             printf("%+ld", delta);
  325.           mputchar('\n');
  326.           v = rem_v;
  327.         } while ((v>=tss_ptr->tss_esp) && (v<0x90000000L));
  328.         break;
  329.       case WHEREIS:
  330.         sscanf(buf, "%s", buf2);
  331.         if (strpbrk(buf2, "*?"))
  332.         {
  333.           syms_listwild(buf2);
  334.           break;
  335.         }
  336.         if (buf2[0])
  337.           vaddr = syms_name2val(buf2);
  338.         if (undefined_symbol)
  339.           break;
  340.         name = syms_val2name(vaddr, &delta);
  341.         printf("0x%08lx %s", vaddr, name);
  342.         if (delta)
  343.           printf("+%lx", delta);
  344.         name = syms_val2line(vaddr, &i, 0);
  345.         if (name)
  346.           printf(", line %d in file %s", i, name);
  347.         mputchar('\n');
  348.         break;
  349.       case LIST:
  350.         if (rem_cmd != cmd)
  351.           n = 10;
  352.         buf2[0] = 0;
  353.         sscanf(buf, "%s %d", buf2, &n);
  354.         if (buf2[0] && strcmp(buf2, "."))
  355.           vaddr = syms_name2val(buf2);
  356.         if (undefined_symbol)
  357.           break;
  358.         for (i=0; i<n; i++)
  359.         {
  360.           vaddr = unassemble(vaddr, 0);
  361.           i += last_unassemble_extra_lines;
  362. /*          if (last_unassemble_unconditional)
  363.             break; */
  364.         }
  365.         break;
  366.       case DUMP_A:
  367.         buf2[0] = 0;
  368.         sscanf(buf, "%s %d", buf2, &n);
  369.         if (buf2[0])
  370.           vaddr = syms_name2val(buf2);
  371.         if (undefined_symbol)
  372.           break;
  373.         while (1)
  374.         {
  375.           word8 ch;
  376.           if (!page_is_valid(vaddr+ARENA))
  377.           {
  378.             printf("<bad address>\n");
  379.             break;
  380.           }
  381.           ch = peek8(vaddr+ARENA);
  382.           if (ch == 0)
  383.           {
  384.             mputchar('\n');
  385.             break;
  386.           }
  387.           if (ch < ' ')
  388.             printf("^%c", ch+'@');
  389.           else if ((ch >= ' ') && (ch < 0x7f))
  390.             mputchar(ch);
  391.           else if (ch == 0x7f)
  392.             printf("^?");
  393.           else if ((ch >= 0x80) && (ch < 0xa0))
  394.             printf("M-^%c", ch-0x80+'@');
  395.           else if (ch >= 0xa0)
  396.             printf("M-%c", ch-0x80);
  397.           vaddr++;
  398.         }
  399.         break;
  400.       case DUMP:
  401.       case DUMP_B:
  402.       case DUMP_W:
  403.         if (rem_cmd != cmd)
  404.           n = 4;
  405.         buf2[0] = 0;
  406.         sscanf(buf, "%s %d", buf2, &n);
  407.         if (buf2[0])
  408.           vaddr = syms_name2val(buf2);
  409.         if (undefined_symbol)
  410.           break;
  411.         s = 0;
  412.         len = n + (~((vaddr&15)/4-1) & 3);
  413.         for (i=-(vaddr&15)/4; i<len; i++)
  414.         {
  415.           if ((s&3) == 0)
  416.             printf("0x%08lx:", vaddr+i*4);
  417.           if ((i>=0) && (i<n))
  418.             printf(" 0x%08lx", peek32(vaddr+i*4+ARENA));
  419.           else
  420.             printf("           ");
  421.           if ((s & 3) == 3)
  422.           {
  423.             int j, c;
  424.             printf("  ");
  425.             for (j=0; j<16; j++)
  426.               if ((j+i*4-12>=0) && (j+i*4-12 < n*4))
  427.               {
  428.                 c = peek8(vaddr+j+i*4-12+ARENA);
  429.                 if (c<' ')
  430.                   mputchar('.');
  431.                 else
  432.                   mputchar(c);
  433.               }
  434.               else
  435.                 mputchar(' ');
  436.             printf("\n");
  437.           }
  438.           s++;
  439.         }
  440.         if (s & 3)
  441.           printf("\n");
  442.         vaddr += n*4;
  443.         break;
  444.       case BREAK:
  445.         vaddr = n = 0;
  446.         buf2[0] = 0;
  447.         sscanf(buf, "%d %s", &n, buf2);
  448.         if (buf2[0])
  449.           vaddr = syms_name2val(buf2);
  450.         if (undefined_symbol)
  451.           break;
  452.         dr[n] = vaddr + ARENA;
  453.         if (vaddr == 0)
  454.           dr7 &= ~(2 << (n*2));
  455.         else
  456.           dr7 |= 2 << (n*2);
  457.       case STATUS:
  458.         s = 0;
  459.         for (n=0; n<4; n++)
  460.         {
  461.           s = 1;
  462.           name = syms_val2name(dr[n]-ARENA, &delta);
  463.           printf("  dr%d  %s", n, name);
  464.           if (delta)
  465.             printf("+%#lx", delta);
  466.           if (name[0] != '0')
  467.             printf(" (0x%lx)", dr[n] - ARENA);
  468.           if (!(dr7 & (3 << (n*2))))
  469.             printf(" (disabled)");
  470.           mputchar('\n');
  471.         }
  472.         if (s == 0)
  473.           printf("  No breakpoints set\n");
  474.         break;
  475.       case REGS:
  476.         tssprint(tss_ptr);
  477.         unassemble(tss_ptr->tss_eip, 0);
  478.         break;
  479.       case SET:
  480.         cmd = Zero;
  481.         lasttoken[0] = 0;
  482.         buf2[0] = 0;
  483.         len = sscanf(buf, "%s %s", buf2, buf);
  484.         if (buf2[0] == 0)
  485.         {
  486.           break;
  487.         }
  488.         if (len > 1)
  489.         {
  490.           v = syms_name2val(buf);
  491.           if (undefined_symbol)
  492.             break;
  493.         }
  494.         found = 0;
  495.         for (i=0; regs[i].name; i++)
  496.           if (strcmp(regs[i].name, buf2) == 0)
  497.           {
  498.             found = 1;
  499.             if (len > 1)
  500.             {
  501.               switch (regs[i].size)
  502.               {
  503.                 case 1:
  504.                   *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  505.                   break;
  506.                 case 2:
  507.                   *(word16 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  508.                   break;
  509.                 case 4:
  510.                   *(word32 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  511.                   break;
  512.               }
  513.             }
  514.             else
  515.             {
  516.               switch (regs[i].size)
  517.               {
  518.                 case 1:
  519.                   printf("%02x ", *(word8 *)((word8 *)tss_ptr + regs[i].ofs));
  520.                   my_getline(buf, "");
  521.                   if (buf[0])
  522.                   {
  523.                     v = syms_name2val(buf);
  524.                     if (undefined_symbol)
  525.                       break;
  526.                     *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  527.                   }
  528.                   break;
  529.                 case 2:
  530.                   printf("%04x ", *(word16 *)((word16 *)tss_ptr + regs[i].ofs));
  531.                   my_getline(buf, "");
  532.                   if (buf[0])
  533.                   {
  534.                     v = syms_name2val(buf);
  535.                     if (undefined_symbol)
  536.                       break;
  537.                     *(word16 *)((word16 *)tss_ptr + regs[i].ofs) = v;
  538.                   }
  539.                   break;
  540.                 case 4:
  541.                   printf("%08lx ", *(word32 *)((word32 *)tss_ptr + regs[i].ofs));
  542.                   my_getline(buf, "");
  543.                   if (buf[0])
  544.                   {
  545.                     v = syms_name2val(buf);
  546.                     if (undefined_symbol)
  547.                       break;
  548.                     *(word32 *)((word32 *)tss_ptr + regs[i].ofs) = v;
  549.                   }
  550.                   break;
  551.               }
  552.             }
  553.             break;
  554.           }
  555.         if (found)
  556.           break;
  557.         vaddr = syms_name2val(buf2);
  558.         if (undefined_symbol)
  559.           break;
  560.         if (len < 2)
  561.         {
  562.           v = syms_name2val(buf);
  563.           if (undefined_symbol)
  564.             break;
  565.           poke32(vaddr, v);
  566.         }
  567.         while (1)
  568.         {
  569.           printf("0x%08lx 0x%08lx", vaddr, peek32(vaddr+ARENA));
  570.           my_getline(buf, "");
  571.           if (buf[0])
  572.           {
  573.             if (strcmp(buf, ".") == 0)
  574.               break;
  575.             poke32(vaddr+ARENA, syms_name2val(buf));
  576.           }
  577.           vaddr += 4;
  578.         }
  579.         break;
  580.       case XNPX:
  581.         if (!have_80387)
  582.         {
  583.           printf("No 80387 present\n");
  584.           break;
  585.         }
  586.         save_npx();
  587.         printf("Control: 0x%04lx  Status: 0x%04lx  Tag: 0x%04lx\n",
  588.                npx.control, npx.status, npx.tag);
  589.         for (i=0; i<8; i++)
  590.         {
  591.           double d;
  592.           int tag;
  593.           int tos = (npx.status >> 11) & 7;
  594.           printf("st(%d)  ", i);
  595.           if (npx.reg[i].sign)
  596.             mputchar('-');
  597.           else
  598.             mputchar('+');
  599.           printf(" %04x %04x %04x %04x e %04x    ",
  600.                  npx.reg[i].sig3,
  601.                  npx.reg[i].sig2,
  602.                  npx.reg[i].sig1,
  603.                  npx.reg[i].sig0,
  604.                  npx.reg[i].exponent);
  605.           tag = (npx.tag >> (((i+tos)%8)*2)) & 3;
  606.           switch (tag)
  607.           {
  608.             case 0:
  609.               printf("Valid");
  610.               if (((int)npx.reg[i].exponent-16382 < 1000) &&
  611.                   ((int)npx.reg[i].exponent-16382 > -1000))
  612.               {
  613.                 d = npx.reg[i].sig3/65536.0 + npx.reg[i].sig2/65536.0/65536.0
  614.                   + npx.reg[i].sig1/65536.0/65536.0/65536.0;
  615.                 d = ldexp(d,(int)npx.reg[i].exponent-16382);
  616.                 if (npx.reg[i].sign)
  617.                   d = -d;
  618.                 printf("  %.16lg", d);
  619.               }
  620.               else
  621.                 printf("  (too big to display)");
  622.               mputchar('\n');
  623.               break;
  624.             case 1:
  625.               printf("Zero\n");
  626.               break;
  627.             case 2:
  628.               printf("Special\n");
  629.               break;
  630.             case 3:
  631.               printf("Empty\n");
  632.               break;
  633.           }
  634.         }
  635.         break;
  636.       case CLS:
  637.         if (use_mono)
  638.           mputchar(12);
  639.         else
  640.         {
  641.           _AH=15;
  642.           geninterrupt(0x10);
  643.           _AH = 0;
  644.           geninterrupt(0x10);
  645.           mputchar('\n');
  646.         }
  647.         break;
  648.       case QUIT:
  649.         return;
  650.       case Zero:
  651.         break;
  652.       default:
  653.         printf("Unknown command\n");
  654.         lasttoken[0] = 0;
  655.         cmd = Zero;
  656.         break;
  657.     }
  658.     if (undefined_symbol)
  659.     {
  660.       lasttoken[0] = 0;
  661.       cmd = Zero;
  662.       undefined_symbol = 0;
  663.     }
  664.     rem_cmd = cmd;
  665.     debug_mode = 1;
  666.   }
  667. }
  668. #endif /* DEBUGGER */
  669.  
  670. go_til_stop()
  671. {
  672.   tss_ptr = &a_tss;
  673.   while (1)
  674.   {
  675.     go32();
  676.     if (!was_exception)
  677.       return;
  678.     if (exception_handler())
  679.       return;
  680.   }
  681. }
  682.  
  683. #if DEBUGGER
  684. print_reason()
  685. {
  686.   int n, i;
  687.   i = tss_ptr->tss_irqn;
  688.   if ((i == 0x21) && ((tss_ptr->tss_eax & 0xff00) == 0x4c00))
  689.   {
  690.     tss_ptr->tss_eip -= 2; /* point to int 21h */
  691.     return;
  692.   }
  693.   if (use_ansi)
  694.     printf("\033[1;34m");
  695.   mono_attr = MONO_BOLD;
  696.   if (i != 1)
  697.   {
  698.     tssprint(tss_ptr);
  699.     if (tss_ptr != &a_tss)
  700.     {
  701.       printf("internal error: tss_ptr NOT a_tss\n");
  702.     }
  703.     if (i == 0x79)
  704.       printf("Keyboard interrupt\n");
  705.     else if (i == 0x75)
  706.     {
  707.       save_npx();
  708.       printf("Numeric Exception (");
  709.       if ((npx.status & 0x0241) == 0x0241)
  710.         printf("stack overflow");
  711.       else if ((npx.status & 0x0241) == 0x0041)
  712.         printf("stack underflow");
  713.       else if (npx.status & 1)
  714.         printf("invalid operation");
  715.       else if (npx.status & 2)
  716.         printf("denormal operand");
  717.       else if (npx.status & 4)
  718.         printf("divide by zero");
  719.       else if (npx.status & 8)
  720.         printf("overflow");
  721.       else if (npx.status & 16)
  722.         printf("underflow");
  723.       else if (npx.status & 32)
  724.         printf("loss of precision");
  725.       printf(") at eip=0x%08lx\n", npx.eip);
  726.       unassemble(npx.eip, 0);
  727.     }
  728.     else
  729.     {
  730.       printf("exception %d (%#02x) occurred", i, i);
  731.       if ((i == 8) || ((i>=10) && (i<=14)))
  732.         printf(", error code=%#lx", tss_ptr->tss_error);
  733.       mputchar('\n');
  734.     }
  735.   }
  736.   for (n=0; n<3; n++)
  737.     if ((dr6 & (1<<n)) && (dr7 & (3<<(n*2))))
  738.       printf("breakpoint %d hit\n", n);
  739.   if (use_ansi)
  740.     printf("\033[0m");
  741.   mono_attr = MONO_NORMAL;
  742. }
  743.  
  744. #endif /* DEBUGGER */
  745.