Annotation of uae/src/debug.c, revision 1.1.1.12

1.1.1.3   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.3   root        3:   *
1.1       root        4:   * Debugger
1.1.1.3   root        5:   *
1.1       root        6:   * (c) 1995 Bernd Schmidt
1.1.1.3   root        7:   *
1.1       root        8:   */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: 
                     13: #include <ctype.h>
                     14: #include <signal.h>
                     15: 
                     16: #include "config.h"
                     17: #include "options.h"
1.1.1.10  root       18: #include "threaddep/thread.h"
1.1.1.3   root       19: #include "uae.h"
1.1       root       20: #include "memory.h"
                     21: #include "custom.h"
                     22: #include "newcpu.h"
1.1.1.11  root       23: #include "cpu_prefetch.h"
1.1       root       24: #include "debug.h"
                     25: #include "cia.h"
                     26: #include "xwin.h"
                     27: #include "gui.h"
1.1.1.9   root       28: #include "identify.h"
1.1.1.11  root       29: #include "disk.h"
                     30: #include "autoconf.h"
1.1       root       31: 
1.1.1.11  root       32: #define console_out printf
                     33: #define console_flush() fflush (stdout)
                     34: #define console_get(BUF, COUNT) fgets (BUF, COUNT, stdin)
                     35: 
                     36: static int debugger_active;
                     37: static uaecptr skipaddr_start, skipaddr_end;
                     38: static int skipaddr_doskip;
                     39: static uae_u32 skipins;
1.1       root       40: static int do_skip;
1.1.1.11  root       41: static int debug_rewind;
                     42: static int memwatch_enabled, memwatch_triggered;
                     43: int debugging;
                     44: int exception_debugging;
1.1       root       45: 
1.1.1.7   root       46: static FILE *logfile;
                     47: 
1.1.1.4   root       48: void activate_debugger (void)
1.1       root       49: {
1.1.1.7   root       50:     if (logfile)
                     51:        fclose (logfile);
                     52:     logfile = 0;
1.1       root       53:     do_skip = 0;
                     54:     if (debugger_active)
                     55:        return;
                     56:     debugger_active = 1;
1.1.1.8   root       57:     set_special (SPCFLAG_BRK);
1.1       root       58:     debugging = 1;
                     59: }
                     60: 
                     61: int firsthist = 0;
                     62: int lasthist = 0;
                     63: #ifdef NEED_TO_DEBUG_BADLY
                     64: struct regstruct history[MAX_HIST];
                     65: union flagu historyf[MAX_HIST];
                     66: #else
1.1.1.3   root       67: uaecptr history[MAX_HIST];
1.1       root       68: #endif
                     69: 
1.1.1.11  root       70: static char help[] = {
                     71:     "          HELP for UAE Debugger\n"
                     72:     "         -----------------------\n\n"
                     73:     "  g [<address>]         Start execution at the current address or <address>\n"
                     74:     "  c                     Dump state of the CIA, disk drives and custom registers\n"
                     75:     "  r                     Dump state of the CPU\n"
                     76:     "  m <address> [<lines>] Memory dump starting at <address>\n"
                     77:     "  d <address> [<lines>] Disassembly starting at <address>\n"
                     78:     "  t [instructions]      Step one or more instructions\n"
                     79:     "  z                     Step through one instruction - useful for JSR, DBRA etc\n"
                     80:     "  f                     Step forward until PC in RAM\n"
                     81:     "  f <address>           Add/remove breakpoint\n"
                     82:     "  fi                    Step forward until PC points to RTS/RTD or RTE\n"
                     83:     "  fi <opcode>           Step forward until PC points to <opcode>\n"
                     84:     "  fl                    List breakpoints\n"
                     85:     "  fd                    Remove all breakpoints\n"
                     86:     "  f <addr1> <addr2>     Step forward until <addr1> <= PC <= <addr2>\n"
                     87:     "  e                     Dump contents of all custom registers\n"
                     88:     "  i                     Dump contents of interrupt and trap vectors\n"
                     89:     "  o <1|2|addr> [<lines>]View memory as Copper instructions\n"
                     90:     "  O                     Display bitplane offsets\n"
                     91:     "  O <plane> <offset>    Offset a bitplane\n"
                     92:     "  H <count>             Show PC history <count> instructions\n"
                     93:     "  M                     Search for *Tracker sound modules\n"
                     94:     "  C <value>             Search for values like energy or lifes in games\n"
                     95:     "  W <address> <value>   Write into Amiga memory\n"
                     96:     "  w <num> <address> <length> <R/W/RW> [<value>]\n"
                     97:     "                        Add/remove memory watchpoints\n"
                     98:     "  wd                    Enable illegal access logger\n"
                     99:     "  S <file> <addr> <n>   Save a block of Amiga memory\n"
                    100:     "  s <string>/<values> [<addr>] [<length>]\n"
                    101:     "                        Search for string/bytes\n"
                    102:     "  T                     Show exec tasks and their PCs\n"
                    103:     "  h,?                   Show this help page\n"
                    104:     "  q                     Quit the emulator. You don't want to use this command.\n\n"
                    105: };
                    106: 
                    107: static void debug_help (void)
                    108: {
                    109:     console_out (help);
                    110: }
                    111: 
                    112: 
                    113: 
1.1.1.4   root      114: static void ignore_ws (char **c)
1.1       root      115: {
                    116:     while (**c && isspace(**c)) (*c)++;
                    117: }
                    118: 
1.1.1.11  root      119: static uae_u32 readint (char **c);
1.1.1.4   root      120: static uae_u32 readhex (char **c)
1.1       root      121: {
1.1.1.3   root      122:     uae_u32 val = 0;
1.1       root      123:     char nc;
                    124: 
1.1.1.4   root      125:     ignore_ws (c);
1.1.1.11  root      126:     if (**c == '!' || **c == '_') {
                    127:        (*c)++;
                    128:        return readint (c);
                    129:     }
1.1.1.4   root      130:     while (isxdigit(nc = **c)) {
1.1       root      131:        (*c)++;
                    132:        val *= 16;
                    133:        nc = toupper(nc);
                    134:        if (isdigit(nc)) {
                    135:            val += nc - '0';
                    136:        } else {
                    137:            val += nc - 'A' + 10;
                    138:        }
                    139:     }
                    140:     return val;
                    141: }
                    142: 
1.1.1.9   root      143: static uae_u32 readint (char **c)
                    144: {
                    145:     uae_u32 val = 0;
                    146:     char nc;
                    147:     int negative = 0;
                    148: 
                    149:     ignore_ws (c);
1.1.1.11  root      150:     if (**c == '$') {
                    151:        (*c)++;
                    152:        return readhex (c);
                    153:     }
                    154:     if (**c == '0' && toupper((*c)[1]) == 'X') {
1.1.1.12! root      155:        (*c)+= 2;
1.1.1.11  root      156:        return readhex (c);
                    157:     }
1.1.1.9   root      158:     if (**c == '-')
                    159:        negative = 1, (*c)++;
                    160:     while (isdigit(nc = **c)) {
                    161:        (*c)++;
                    162:        val *= 10;
                    163:        val += nc - '0';
                    164:     }
                    165:     return val * (negative ? -1 : 1);
                    166: }
                    167: 
1.1.1.4   root      168: static char next_char( char **c)
1.1       root      169: {
1.1.1.4   root      170:     ignore_ws (c);
1.1       root      171:     return *(*c)++;
                    172: }
                    173: 
1.1.1.4   root      174: static int more_params (char **c)
1.1       root      175: {
1.1.1.4   root      176:     ignore_ws (c);
1.1       root      177:     return (**c) != 0;
                    178: }
                    179: 
1.1.1.11  root      180: static uae_u32 nextaddr (uae_u32 addr)
                    181: {
                    182:     if (addr == 0xffffffff) {
                    183:        if (currprefs.bogomem_size)
                    184:            return 0xc00000 + currprefs.bogomem_size;
                    185:        if (currprefs.fastmem_size)
                    186:            return 0x200000 + currprefs.fastmem_size;
                    187:        return currprefs.chipmem_size;
                    188:     }
                    189:     if (addr == currprefs.chipmem_size) {
                    190:        if (currprefs.fastmem_size)
                    191:            return 0x200000;
                    192:        else if (currprefs.bogomem_size)
                    193:            return 0xc00000;
                    194:        return 0xffffffff;
                    195:     }
                    196:     if (addr == 0x200000 + currprefs.fastmem_size) {
                    197:        if (currprefs.bogomem_size)
                    198:            return 0xc00000;
                    199:        return 0xffffffff;
                    200:     }
                    201:     if (addr == 0xc00000 + currprefs.bogomem_size)
                    202:        return 0xffffffff;
                    203:     return addr + 1;
                    204: }
                    205: 
1.1.1.4   root      206: static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
1.1       root      207: {
1.1.1.11  root      208:     char line[80];
                    209:     int cols = 8;
                    210:     for (;lines--;) {
1.1       root      211:        int i;
1.1.1.11  root      212:        sprintf (line, "%08lx ", addr);
                    213:        for (i = 0; i < cols; i++) {
                    214:            uae_u8 b1 = get_byte (addr + 0);
                    215:            uae_u8 b2 = get_byte (addr + 1);
                    216:            addr += 2;
                    217:            sprintf (line + 9 + i * 5, "%02x%02x ", b1, b2);
                    218:            line[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
                    219:            line[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
                    220:        }
                    221:        line[9 + cols * 5] = ' ';
                    222:        line[9 + cols * 5 + 1 + 2 * cols] = 0;
                    223:        console_out (line);
                    224:        console_out ("\n");
1.1       root      225:     }
                    226:     *nxmem = addr;
                    227: }
                    228: 
1.1.1.3   root      229: static void foundmod (uae_u32 ptr, char *type)
1.1.1.2   root      230: {
1.1.1.3   root      231:     char name[21];
                    232:     uae_u8 *ptr2 = chipmemory + ptr;
                    233:     int i,length;
                    234: 
1.1.1.11  root      235:     console_out ("Found possible %s module at 0x%lx.\n", type, ptr);
1.1.1.3   root      236:     memcpy (name, ptr2, 20);
                    237:     name[20] = '\0';
                    238: 
                    239:     /* Browse playlist */
                    240:     length = 0;
                    241:     for (i = 0x3b8; i < 0x438; i++)
                    242:        if (ptr2[i] > length)
                    243:            length = ptr2[i];
                    244: 
                    245:     length = (length+1)*1024 + 0x43c;
                    246: 
                    247:     /* Add sample lengths */
                    248:     ptr2 += 0x2A;
1.1.1.4   root      249:     for (i = 0; i < 31; i++, ptr2 += 30)
1.1.1.3   root      250:        length += 2*((ptr2[0]<<8)+ptr2[1]);
1.1.1.12! root      251: 
1.1.1.11  root      252:     console_out ("Name \"%s\", Length 0x%lx bytes.\n", name, length);
1.1.1.3   root      253: }
                    254: 
1.1.1.4   root      255: static void modulesearch (void)
1.1.1.3   root      256: {
                    257:     uae_u8 *p = get_real_address (0);
                    258:     uae_u32 ptr;
                    259: 
1.1.1.4   root      260:     for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
1.1.1.2   root      261:        /* Check for Mahoney & Kaktus */
                    262:        /* Anyone got the format of old 15 Sample (SoundTracker)modules? */
1.1.1.3   root      263:        if (ptr >= 0x438 && p[0] == 'M' && p[1] == '.' && p[2] == 'K' && p[3] == '.')
                    264:            foundmod (ptr - 0x438, "ProTracker (31 samples)");
                    265: 
                    266:        if (ptr >= 0x438 && p[0] == 'F' && p[1] == 'L' && p[2] == 'T' && p[3] == '4')
                    267:            foundmod (ptr - 0x438, "Startrekker");
                    268: 
                    269:        if (strncmp ((char *)p, "SMOD", 4) == 0) {
1.1.1.11  root      270:            console_out ("Found possible FutureComposer 1.3 module at 0x%lx, length unknown.\n", ptr);
1.1.1.3   root      271:        }
                    272:        if (strncmp ((char *)p, "FC14", 4) == 0) {
1.1.1.11  root      273:            console_out ("Found possible FutureComposer 1.4 module at 0x%lx, length unknown.\n", ptr);
1.1.1.3   root      274:        }
                    275:        if (p[0] == 0x48 && p[1] == 0xe7 && p[4] == 0x61 && p[5] == 0
                    276:            && p[8] == 0x4c && p[9] == 0xdf && p[12] == 0x4e && p[13] == 0x75
                    277:            && p[14] == 0x48 && p[15] == 0xe7 && p[18] == 0x61 && p[19] == 0
                    278:            && p[22] == 0x4c && p[23] == 0xdf && p[26] == 0x4e && p[27] == 0x75) {
1.1.1.11  root      279:            console_out ("Found possible Whittaker module at 0x%lx, length unknown.\n", ptr);
1.1.1.3   root      280:        }
                    281:        if (p[4] == 0x41 && p[5] == 0xFA) {
                    282:            int i;
                    283: 
                    284:            for (i = 0; i < 0x240; i += 2)
                    285:                if (p[i] == 0xE7 && p[i + 1] == 0x42 && p[i + 2] == 0x41 && p[i + 3] == 0xFA)
                    286:                    break;
                    287:            if (i < 0x240) {
                    288:                uae_u8 *p2 = p + i + 4;
                    289:                for (i = 0; i < 0x30; i += 2)
                    290:                    if (p2[i] == 0xD1 && p2[i + 1] == 0xFA) {
1.1.1.11  root      291:                        console_out ("Found possible MarkII module at %lx, length unknown.\n", ptr);
1.1.1.3   root      292:                    }
                    293:            }
1.1.1.2   root      294:        }
                    295:     }
                    296: }
                    297: 
1.1.1.11  root      298: static void dump_vectors (void)
1.1.1.9   root      299: {
1.1.1.11  root      300:     int i = 0, j = 0;
1.1.1.9   root      301: 
1.1.1.11  root      302:     while (int_labels[i].name || trap_labels[j].name) {
                    303:        if (int_labels[i].name) {
                    304:            console_out ("$%08X: %s  \t $%08X\t", int_labels[i].adr + regs.vbr,
                    305:                int_labels[i].name, get_long (int_labels[i].adr + (int_labels[i].adr == 4 ? 0 : regs.vbr)));
                    306:            i++;
                    307:        } else {
                    308:            console_out ("\t\t\t\t");
                    309:        }
                    310:        if (trap_labels[j].name) {
                    311:            console_out("$%08X: %s  \t $%08X", trap_labels[j].adr + regs.vbr,
                    312:               trap_labels[j].name, get_long (trap_labels[j].adr + regs.vbr));
                    313:            j++;
                    314:        }
                    315:        console_out ("\n");
1.1.1.9   root      316:     }
                    317: }
                    318: 
                    319: static void disassemble_wait (FILE *file, unsigned long insn)
                    320: {
1.1.1.11  root      321:     int vp, hp, ve, he, bfd, v_mask, h_mask;
1.1.1.9   root      322: 
                    323:     vp = (insn & 0xff000000) >> 24;
                    324:     hp = (insn & 0x00fe0000) >> 16;
                    325:     ve = (insn & 0x00007f00) >> 8;
                    326:     he = (insn & 0x000000fe);
1.1.1.11  root      327:     bfd = (insn & 0x00008000) >> 15;
1.1.1.9   root      328: 
                    329:     /* bit15 can never be masked out*/
                    330:     v_mask = vp & (ve | 0x80);
                    331:     h_mask = hp & he;
                    332:     if (v_mask > 0) {
1.1.1.11  root      333:        console_out ("vpos ");
1.1.1.9   root      334:        if (ve != 0x7f) {
1.1.1.11  root      335:            console_out ("& 0x%02x ", ve);
1.1.1.9   root      336:        }
1.1.1.11  root      337:        console_out (">= 0x%02x", v_mask);
1.1.1.9   root      338:     }
                    339:     if (he > 0) {
                    340:        if (v_mask > 0) {
1.1.1.11  root      341:            console_out (" and");
1.1.1.9   root      342:        }
1.1.1.11  root      343:        console_out (" hpos ");
1.1.1.9   root      344:        if (he != 0xfe) {
1.1.1.11  root      345:            console_out ("& 0x%02x ", he);
1.1.1.9   root      346:        }
1.1.1.11  root      347:        console_out (">= 0x%02x", h_mask);
1.1.1.9   root      348:     } else {
1.1.1.11  root      349:        console_out (", ignore horizontal");
1.1.1.9   root      350:     }
                    351: 
1.1.1.11  root      352:     console_out (".\n                        \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n",
1.1.1.9   root      353:             vp, ve, hp, he, bfd);
                    354: }
                    355: 
                    356: /* simple decode copper by Mark Cox */
                    357: static void decode_copper_insn (FILE* file, unsigned long insn, unsigned long addr)
                    358: {
                    359:     uae_u32 insn_type = insn & 0x00010001;
                    360:     int hpos, vpos;
                    361:     char record[] = "          ";
                    362:     if (find_copper_record (addr, &hpos, &vpos)) {
                    363:        sprintf (record, " [%03x %03x]", vpos, hpos);
                    364:     }
                    365: 
1.1.1.11  root      366:     console_out ("%08lx: %04lx %04lx%s\t; ", addr, insn >> 16, insn & 0xFFFF, record);
1.1.1.9   root      367: 
                    368:     switch (insn_type) {
                    369:     case 0x00010000: /* WAIT insn */
1.1.1.11  root      370:        console_out ("Wait for ");
1.1.1.9   root      371:        disassemble_wait (file, insn);
                    372: 
                    373:        if (insn == 0xfffffffe)
1.1.1.11  root      374:            console_out ("                           \t; End of Copperlist\n");
1.1.1.9   root      375: 
                    376:        break;
                    377: 
                    378:     case 0x00010001: /* SKIP insn */
1.1.1.11  root      379:        console_out ("Skip if ");
1.1.1.9   root      380:        disassemble_wait (file, insn);
                    381:        break;
                    382: 
                    383:     case 0x00000000:
                    384:     case 0x00000001: /* MOVE insn */
1.1.1.11  root      385:        {
                    386:            int addr = (insn >> 16) & 0x1fe;
                    387:            int i = 0;
                    388:            while (custd[i].name) {
                    389:                if (custd[i].adr == addr + 0xdff000)
                    390:                    break;
                    391:                i++;
                    392:            }
                    393:            if (custd[i].name)
                    394:                console_out ("%s := 0x%04lx\n", custd[i].name, insn & 0xffff);
                    395:            else
                    396:                console_out ("%04x := 0x%04lx\n", addr, insn & 0xffff);
                    397:        }
1.1.1.9   root      398:        break;
                    399: 
                    400:     default:
                    401:        abort ();
                    402:     }
                    403: 
                    404: }
                    405: 
                    406: 
                    407: static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
                    408: {
                    409:     uae_u32 insn;
                    410:     while (nolines-- > 0) {
                    411:        insn = get_long (address);
                    412:        decode_copper_insn (file, insn, address);
                    413:        address += 4;
                    414:     }
                    415:     return address;
                    416:     /* You may wonder why I don't stop this at the end of the copperlist?
1.1.1.12! root      417:      * Well, often nice things are hidden at the end and it is debatable the actual
1.1.1.9   root      418:      * values that mean the end of the copperlist */
                    419: }
                    420: 
                    421: 
1.1.1.4   root      422: /* cheat-search by Holger Jakob */
                    423: static void cheatsearch (char **c)
                    424: {
                    425:     uae_u8 *p = get_real_address (0);
                    426:     static uae_u32 *vlist = NULL;
                    427:     uae_u32 ptr;
                    428:     uae_u32 val = 0;
                    429:     uae_u32 type = 0; /* not yet */
                    430:     uae_u32 count = 0;
                    431:     uae_u32 fcount = 0;
                    432:     uae_u32 full = 0;
                    433: 
                    434:     ignore_ws (c);
1.1.1.11  root      435:     val = readhex (c);
1.1.1.4   root      436:     if (vlist == NULL) {
                    437:        vlist = malloc (256*4);
                    438:        if (vlist != 0) {
                    439:            for (count = 0; count<255; count++)
                    440:                vlist[count] = 0;
                    441:            count = 0;
                    442:            for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
                    443:                if (ptr >= 0x438 && p[3] == (val & 0xff)
                    444:                    && p[2] == (val >> 8 & 0xff)
                    445:                    && p[1] == (val >> 16 & 0xff)
                    446:                    && p[0] == (val >> 24 & 0xff))
                    447:                {
                    448:                    if (count < 255) {
                    449:                        vlist[count++]=ptr;
1.1.1.11  root      450:                        console_out ("%08x: %x%x%x%x\n",ptr,p[0],p[1],p[2],p[3]);
1.1.1.4   root      451:                    } else
                    452:                        full = 1;
                    453:                }
                    454:            }
1.1.1.11  root      455:            console_out ("Found %d possible addresses with %d\n",count,val);
                    456:            console_out ("Now continue with 'g' and use 'C' with a different value\n");
1.1.1.4   root      457:        }
                    458:     } else {
                    459:        for (count = 0; count<255; count++) {
                    460:            if (p[vlist[count]+3] == (val & 0xff)
1.1.1.12! root      461:                && p[vlist[count]+2] == (val>>8 & 0xff)
1.1.1.4   root      462:                && p[vlist[count]+1] == (val>>16 & 0xff)
                    463:                && p[vlist[count]] == (val>>24 & 0xff))
                    464:            {
                    465:                fcount++;
1.1.1.11  root      466:                console_out ("%08x: %x%x%x%x\n", vlist[count], p[vlist[count]],
1.1.1.4   root      467:                        p[vlist[count]+1], p[vlist[count]+2], p[vlist[count]+3]);
                    468:            }
                    469:        }
1.1.1.11  root      470:        console_out ("%d hits of %d found\n",fcount,val);
1.1.1.4   root      471:        free (vlist);
                    472:        vlist = NULL;
                    473:     }
                    474: }
                    475: 
1.1.1.11  root      476: #define BREAKPOINT_TOTAL 8
                    477: struct breakpoint_node {
                    478:     uaecptr addr;
                    479:     int enabled;
                    480: };
                    481: static struct breakpoint_node bpnodes[BREAKPOINT_TOTAL];
                    482: 
                    483: static addrbank **debug_mem_banks;
                    484: #define MEMWATCH_TOTAL 4
                    485: struct memwatch_node {
                    486:     uaecptr addr;
                    487:     int size;
                    488:     int rw;
                    489:     uae_u32 val;
                    490:     int val_enabled;
                    491:     uae_u32 modval;
                    492:     int modval_written;
                    493: };
                    494: static struct memwatch_node mwnodes[MEMWATCH_TOTAL];
                    495: static struct memwatch_node mwhit;
                    496: 
                    497: static uae_u8 *illgdebug;
                    498: static int illgdebug_break;
                    499: extern int cdtv_enabled, cd32_enabled;
                    500: 
                    501: static void illg_init (void)
1.1.1.4   root      502: {
1.1.1.11  root      503:     int i;
                    504: 
                    505:     free (illgdebug);
                    506:     illgdebug = xmalloc (0x1000000);
                    507:     if (!illgdebug)
                    508:        return;
                    509:     memset (illgdebug, 3, 0x1000000);
                    510:     memset (illgdebug, 0, currprefs.chipmem_size);
                    511:     memset (illgdebug + 0xc00000, 0, currprefs.bogomem_size);
                    512:     memset (illgdebug + 0x200000, 0, currprefs.fastmem_size);
                    513:     i = 0;
                    514:     while (custd[i].name) {
                    515:        int rw = custd[i].rw;
                    516:        illgdebug[custd[i].adr] = rw;
                    517:        illgdebug[custd[i].adr + 1] = rw;
                    518:        i++;
                    519:     }
                    520:     for (i = 0; i < 16; i++) { /* CIAs */
                    521:        if (i == 11)
                    522:            continue;
                    523:        illgdebug[0xbfe001 + i * 0x100] = 0;
                    524:        illgdebug[0xbfd000 + i * 0x100] = 0;
                    525:     }
                    526:     memset (illgdebug + 0xf80000, 1, 512 * 1024); /* KS ROM */
                    527:     memset (illgdebug + 0xdc0000, 0, 0x3f); /* clock */
                    528:     if (cloanto_rom)
                    529:        memset (illgdebug + 0xe00000, 1, 512 * 1024);
                    530: #ifdef FILESYS
                    531:     if (nr_units (currprefs.mountinfo) > 0) /* filesys "rom" */
                    532:        memset (illgdebug + RTAREA_BASE, 1, 0x10000);
                    533: #endif
                    534: }
                    535: 
                    536: /* add special custom register check here */
                    537: static void illg_debug_check (uaecptr addr, int rw, int size, uae_u32 val)
                    538: {
                    539:     return;
                    540: }
                    541: 
                    542: static void illg_debug_do (uaecptr addr, int rw, int size, uae_u32 val)
                    543: {
                    544:     uae_u8 mask;
                    545:     uae_u32 pc = m68k_getpc ();
                    546:     char rws = rw ? 'W' : 'R';
                    547:     int i;
                    548: 
                    549:     for (i = size - 1; i >= 0; i--) {
                    550:        uae_u8 v = val >> (i * 8);
                    551:        uae_u32 ad = addr + i;
                    552:        if (ad >= 0x1000000)
                    553:            mask = 3;
                    554:        else
                    555:            mask = illgdebug[ad];
                    556:        if (!mask)
                    557:            continue;
                    558:        if (mask & 0x80) {
                    559:            illg_debug_check (ad, rw, size, val);
                    560:        } else if ((mask & 3) == 3) {
                    561:            if (rw)
                    562:                write_log ("RW: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc);
                    563:            else
                    564:                write_log ("RW: %08.8X    %c PC=%08.8X\n", ad, rws, pc);
                    565:            if (illgdebug_break)
1.1.1.12! root      566:                activate_debugger ();
1.1.1.11  root      567:        } else if ((mask & 1) && rw) {
                    568:            write_log ("RO: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc);
                    569:            if (illgdebug_break)
1.1.1.12! root      570:                activate_debugger ();
1.1.1.11  root      571:        } else if ((mask & 2) && !rw) {
                    572:            write_log ("WO: %08.8X    %c PC=%08.8X\n", ad, rws, pc);
                    573:            if (illgdebug_break)
1.1.1.12! root      574:                activate_debugger ();
1.1.1.11  root      575:        }
                    576:     }
                    577: }
                    578: 
                    579: static int debug_mem_off (uaecptr addr)
                    580: {
                    581:     return (munge24 (addr) >> 16) & 0xff;
                    582: }
                    583: 
                    584: static void memwatch_func (uaecptr addr, int rw, int size, uae_u32 val)
                    585: {
                    586:     int i, brk;
                    587: 
                    588:     if (illgdebug)
                    589:        illg_debug_do (addr, rw, size, val);
                    590:     addr = munge24 (addr);
                    591:     for (i = 0; i < MEMWATCH_TOTAL; i++) {
                    592:        uaecptr addr2 = mwnodes[i].addr;
                    593:        uaecptr addr3 = addr2 + mwnodes[i].size;
                    594:        int rw2 = mwnodes[i].rw;
                    595: 
                    596:        brk = 0;
                    597:        if (mwnodes[i].size == 0)
                    598:            continue;
                    599:        if (mwnodes[i].val_enabled && mwnodes[i].val != val)
                    600:            continue;
                    601:        if (rw != rw2 && rw2 < 2)
                    602:            continue;
                    603:        if (addr >= addr2 && addr < addr3)
                    604:            brk = 1;
                    605:        if (!brk && size == 2 && (addr + 1 >= addr2 && addr + 1 < addr3))
                    606:            brk = 1;
                    607:        if (!brk && size == 4 && ((addr + 2 >= addr2 && addr + 2 < addr3) || (addr + 3 >= addr2 && addr + 3 < addr3)))
                    608:            brk = 1;
                    609:        if (brk && mwnodes[i].modval_written) {
                    610:            if (!rw) {
1.1.1.12! root      611:                brk = 0;
1.1.1.11  root      612:            } else if (mwnodes[i].modval_written == 1) {
                    613:                mwnodes[i].modval_written = 2;
                    614:                mwnodes[i].modval = val;
                    615:                brk = 0;
                    616:            } else if (mwnodes[i].modval == val) {
                    617:                brk = 0;
                    618:            }
                    619:        }
                    620:        if (brk) {
                    621:            mwhit.addr = addr;
                    622:            mwhit.rw = rw;
                    623:            mwhit.size = size;
                    624:            mwhit.val = 0;
                    625:            if (mwhit.rw)
                    626:                mwhit.val = val;
                    627:            memwatch_triggered = i + 1;
                    628:            debugging = 1;
                    629:            set_special (SPCFLAG_BRK);
                    630:            break;
                    631:        }
                    632:     }
                    633: }
                    634: 
                    635: static uae_u32 REGPARAM2 debug_lget (uaecptr addr)
                    636: {
                    637:     int off = debug_mem_off (addr);
                    638:     uae_u32 v;
                    639:     v = debug_mem_banks[off]->lget(addr);
                    640:     memwatch_func (addr, 0, 4, v);
                    641:     return v;
                    642: }
                    643: static uae_u32 REGPARAM2 debug_wget (uaecptr addr)
                    644: {
                    645:     int off = debug_mem_off (addr);
                    646:     uae_u32 v;
                    647:     v = debug_mem_banks[off]->wget(addr);
                    648:     memwatch_func (addr, 0, 2, v);
                    649:     return v;
                    650: }
                    651: static uae_u32 REGPARAM2 debug_bget (uaecptr addr)
                    652: {
                    653:     int off = debug_mem_off (addr);
                    654:     uae_u32 v;
                    655:     v = debug_mem_banks[off]->bget(addr);
                    656:     memwatch_func (addr, 0, 1, v);
                    657:     return v;
                    658: }
                    659: static void REGPARAM2 debug_lput (uaecptr addr, uae_u32 v)
                    660: {
                    661:     int off = debug_mem_off (addr);
                    662:     memwatch_func (addr, 1, 4, v);
                    663:     debug_mem_banks[off]->lput(addr, v);
1.1.1.12! root      664: }
1.1.1.11  root      665: static void REGPARAM2 debug_wput (uaecptr addr, uae_u32 v)
                    666: {
                    667:     int off = debug_mem_off (addr);
                    668:     memwatch_func (addr, 1, 2, v);
                    669:     debug_mem_banks[off]->wput(addr, v);
1.1.1.12! root      670: }
1.1.1.11  root      671: static void REGPARAM2 debug_bput (uaecptr addr, uae_u32 v)
                    672: {
                    673:     int off = debug_mem_off (addr);
                    674:     memwatch_func (addr, 1, 1, v);
                    675:     debug_mem_banks[off]->bput(addr, v);
1.1.1.12! root      676: }
1.1.1.11  root      677: static int REGPARAM2 debug_check (uaecptr addr, uae_u32 size)
                    678: {
                    679:     return debug_mem_banks[munge24 (addr) >> 16]->check (addr, size);
                    680: }
                    681: static uae_u8 *REGPARAM2 debug_xlate (uaecptr addr)
                    682: {
                    683:     return debug_mem_banks[munge24 (addr) >> 16]->xlateaddr (addr);
                    684: }
                    685: 
                    686: static void deinitialize_memwatch (void)
                    687: {
                    688:     int i;
                    689:     addrbank *a1, *a2;
                    690: 
                    691:     if (!memwatch_enabled)
                    692:        return;
                    693:     for (i = 0; i < 256; i++) {
                    694:        a1 = debug_mem_banks[i];
                    695:        a2 = mem_banks[i];
                    696:        memcpy (a2, a1, sizeof (addrbank));
                    697:        free (a1);
                    698:     }
                    699:     free (debug_mem_banks);
                    700:     debug_mem_banks = 0;
                    701:     memwatch_enabled = 0;
                    702:     free (illgdebug);
                    703:     illgdebug = 0;
                    704: }
                    705: 
                    706: static int initialize_memwatch (void)
                    707: {
                    708:     int i;
                    709:     addrbank *a1, *a2;
                    710: 
                    711:     if (!currprefs.address_space_24)
                    712:        return 0;
                    713:     debug_mem_banks = xmalloc (sizeof (addrbank*) * 256);
                    714:     for (i = 0; i < 256; i++) {
                    715:        a1 = debug_mem_banks[i] = xmalloc (sizeof (addrbank));
                    716:        a2 = mem_banks[i];
                    717:        memcpy (a1, a2, sizeof (addrbank));
                    718:     }
                    719:     for (i = 0; i < 256; i++) {
                    720:        a2 = mem_banks[i];
                    721:        a2->bget = debug_bget;
                    722:        a2->wget = debug_wget;
                    723:        a2->lget = debug_lget;
                    724:        a2->bput = debug_bput;
                    725:        a2->wput = debug_wput;
                    726:        a2->lput = debug_lput;
                    727:        a2->check = debug_check;
                    728:        a2->xlateaddr = debug_xlate;
                    729:     }
                    730:     memwatch_enabled = 1;
                    731:     return 1;
                    732: }
                    733: 
                    734: static void memwatch_dump (int num)
                    735: {
                    736:     int i;
                    737:     struct memwatch_node *mwn;
                    738:     for (i = 0; i < MEMWATCH_TOTAL; i++) {
                    739:        if ((num >= 0 && num == i) || (num < 0)) {
                    740:            mwn = &mwnodes[i];
                    741:            if (mwn->size == 0)
                    742:                continue;
                    743:            console_out ("%d: %08.8X - %08.8X (%d) %s",
                    744:                i, mwn->addr, mwn->addr + (mwn->size - 1), mwn->size,
                    745:                mwn->rw == 0 ? "R" : (mwn->rw == 1 ? "W" : "RW"));
                    746:            if (mwn->val_enabled)
                    747:                console_out (" =%X", mwn->val);
                    748:            if (mwn->modval_written)
                    749:                console_out (" =M");
                    750:            console_out("\n");
                    751:        }
                    752:     }
                    753: }
                    754: 
                    755: static void memwatch (char **c)
                    756: {
                    757:     int num;
                    758:     struct memwatch_node *mwn;
1.1.1.4   root      759:     char nc;
                    760: 
1.1.1.11  root      761:     if (!memwatch_enabled) {
                    762:        if (!initialize_memwatch ()) {
                    763:            console_out ("Memwatch breakpoints require 24-bit address space\n");
                    764:            return;
                    765:        }
                    766:        console_out ("Memwatch breakpoints enabled\n");
                    767:     }
                    768: 
                    769:     ignore_ws (c);
                    770:     if (!more_params (c)) {
                    771:        memwatch_dump (-1);
                    772:        return;
                    773:     }
                    774:     nc = next_char (c);
                    775:     if (nc == '-') {
                    776:        deinitialize_memwatch ();
                    777:        console_out ("Memwatch breakpoints disabled\n");
                    778:        return;
                    779:     }
                    780:     if (nc == 'd') {
                    781:        if (illgdebug) {
                    782:            ignore_ws (c);
                    783:            if (more_params (c)) {
                    784:                uae_u32 addr = readhex (c);
                    785:                uae_u32 len = 1;
                    786:                if (more_params (c))
                    787:                    len = readhex (c);
                    788:                write_log ("cleared logging addresses %08.8X - %08.8X\n", addr, addr + len);
                    789:                while (len > 0) {
                    790:                    addr &= 0xffffff;
                    791:                    illgdebug[addr] = 0;
                    792:                    addr++;
                    793:                    len--;
                    794:                }
                    795:            }
1.1.1.4   root      796:        } else {
1.1.1.11  root      797:            illg_init ();
                    798:            console_out ("Illegal memory access logging enabled\n");
                    799:            ignore_ws (c);
                    800:            illgdebug_break = 0;
                    801:            if (more_params (c))
                    802:                illgdebug_break = 1;
1.1.1.4   root      803:        }
1.1.1.11  root      804:        return;
1.1.1.4   root      805:     }
1.1.1.11  root      806:     num = nc - '0';
                    807:     if (num < 0 || num >= MEMWATCH_TOTAL)
                    808:        return;
                    809:     mwn = &mwnodes[num];
                    810:     mwn->size = 0;
                    811:     ignore_ws (c);
                    812:     if (!more_params (c)) {
                    813:        console_out ("Memwatch %d removed\n", num);
                    814:        return;
                    815:     }
                    816:     mwn->addr = readhex (c);
                    817:     mwn->size = 1;
                    818:     mwn->rw = 2;
                    819:     mwn->val_enabled = 0;
                    820:     mwn->modval_written = 0;
                    821:     ignore_ws (c);
                    822:     if (more_params (c)) {
                    823:        mwn->size = readhex (c);
                    824:        ignore_ws (c);
                    825:        if (more_params (c)) {
                    826:            char nc = toupper (next_char (c));
                    827:            if (nc == 'W')
                    828:                mwn->rw = 1;
                    829:            else if (nc == 'R' && toupper(**c) != 'W')
                    830:                mwn->rw = 0;
                    831:            else if (nc == 'R' && toupper(**c) == 'W')
                    832:                next_char (c);
                    833:            ignore_ws (c);
                    834:            if (more_params (c)) {
                    835:                if (toupper(**c) == 'M') {
                    836:                    mwn->modval_written = 1;
                    837:                } else {
                    838:                    mwn->val = readhex (c);
                    839:                    mwn->val_enabled = 1;
                    840:                }
                    841:            }
1.1.1.4   root      842:        }
                    843:     }
1.1.1.11  root      844:     memwatch_dump (num);
                    845: }
1.1.1.4   root      846: 
1.1.1.11  root      847: static void writeintomem (char **c)
                    848: {
                    849:     uae_u32 addr = 0;
                    850:     uae_u32 val = 0;
                    851:     char cc;
                    852: 
                    853:     ignore_ws(c);
                    854:     addr = readhex (c);
                    855:     ignore_ws(c);
                    856:     val = readhex (c);
                    857:     if (val > 0xffff) {
                    858:        put_long (addr, val);
                    859:        cc = 'L';
                    860:     } else if (val > 0xff) {
                    861:        put_word (addr, val);
                    862:        cc = 'W';
                    863:     } else {
                    864:        put_byte (addr, val);
                    865:        cc = 'B';
                    866:     }
                    867:     console_out ("Wrote %x (%u) at %08x.%c\n", val, val, addr, cc);
1.1.1.9   root      868: }
                    869: 
                    870: static void show_exec_tasks (void)
                    871: {
                    872:     uaecptr execbase = get_long (4);
                    873:     uaecptr taskready = get_long (execbase + 406);
                    874:     uaecptr taskwait = get_long (execbase + 420);
                    875:     uaecptr node, end;
1.1.1.11  root      876:     console_out ("execbase at 0x%08lx\n", (unsigned long) execbase);
                    877:     console_out ("Current:\n");
1.1.1.9   root      878:     node = get_long (execbase + 276);
1.1.1.11  root      879:     console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
                    880:     console_out ("Ready:\n");
1.1.1.9   root      881:     node = get_long (taskready);
                    882:     end = get_long (taskready + 4);
                    883:     while (node) {
1.1.1.11  root      884:        console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
1.1.1.9   root      885:        node = get_long (node);
                    886:     }
1.1.1.11  root      887:     console_out ("Waiting:\n");
1.1.1.9   root      888:     node = get_long (taskwait);
                    889:     end = get_long (taskwait + 4);
                    890:     while (node) {
1.1.1.11  root      891:        console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
1.1.1.9   root      892:        node = get_long (node);
                    893:     }
1.1.1.4   root      894: }
1.1.1.7   root      895: 
1.1.1.8   root      896: static int trace_same_insn_count;
                    897: static uae_u8 trace_insn_copy[10];
                    898: static struct regstruct trace_prev_regs;
1.1.1.11  root      899: static uaecptr nextpc;
1.1       root      900: 
1.1.1.11  root      901: static int instruction_breakpoint (char **c)
                    902: {
                    903:     struct breakpoint_node *bpn;
                    904:     int i;
1.1.1.3   root      905: 
1.1.1.11  root      906:     if (more_params (c)) {
                    907:        char nc = toupper((*c)[0]);
                    908:        if (nc == 'I') {
                    909:            next_char (c);
                    910:            if (more_params (c))
                    911:                skipins = readhex (c);
                    912:            else
                    913:                skipins = 0x10000;
                    914:            do_skip = 1;
                    915:            skipaddr_doskip = 1;
                    916:            return 1;
                    917:        } else if (nc == 'D' && (*c)[1] == 0) {
                    918:            for (i = 0; i < BREAKPOINT_TOTAL; i++)
                    919:                bpnodes[i].enabled = 0;
                    920:            console_out ("All breakpoints removed\n");
                    921:            return 0;
                    922:        } else if (nc == 'L') {
                    923:            int got = 0;
                    924:            for (i = 0; i < BREAKPOINT_TOTAL; i++) {
                    925:                bpn = &bpnodes[i];
                    926:                if (!bpn->enabled)
                    927:                    continue;
                    928:                console_out ("%8X ", bpn->addr);
                    929:                got = 1;
1.1.1.8   root      930:            }
1.1.1.11  root      931:            if (!got)
                    932:                console_out ("No breakpoints\n");
                    933:            else
                    934:                console_out ("\n");
1.1.1.12! root      935:            return 0;
1.1.1.8   root      936:        }
1.1.1.11  root      937:        skipaddr_doskip = 1;
                    938:        skipaddr_start = readhex (c);
                    939:        if (more_params (c)) {
                    940:            skipaddr_end = readhex (c);
                    941:        } else {
                    942:            for (i = 0; i < BREAKPOINT_TOTAL; i++) {
                    943:                bpn = &bpnodes[i];
                    944:                if (bpn->enabled && bpn->addr == skipaddr_start) {
                    945:                    bpn->enabled = 0;
                    946:                    console_out ("Breakpoint removed\n");
                    947:                    skipaddr_start = 0xffffffff;
                    948:                    skipaddr_doskip = 0;
                    949:                    return 0;
                    950:                }
                    951:            }
                    952:            for (i = 0; i < BREAKPOINT_TOTAL; i++) {
                    953:                bpn = &bpnodes[i];
                    954:                if (bpn->enabled)
                    955:                    continue;
                    956:                bpn->addr = skipaddr_start;
                    957:                bpn->enabled = 1;
                    958:                console_out ("Breakpoint added\n");
1.1.1.12! root      959:                skipaddr_start = 0xffffffff;
        !           960:                skipaddr_doskip = 0;
1.1.1.11  root      961:                break;
                    962:            }
                    963:            return 0;
                    964:        }
                    965:     }
                    966:     if (skipaddr_start == 0xC0DEDBAD) {
1.1.1.12! root      967:        trace_same_insn_count = 0;
1.1.1.11  root      968:        logfile = fopen ("uae.trace", "w");
1.1.1.8   root      969:        memcpy (trace_insn_copy, regs.pc_p, 10);
                    970:        memcpy (&trace_prev_regs, &regs, sizeof regs);
1.1.1.7   root      971:     }
1.1.1.11  root      972:     do_skip = 1;
                    973:     skipaddr_doskip = -1;
                    974:     return 1;
                    975: }
1.1.1.7   root      976: 
1.1.1.11  root      977: static void savemem (char **cc)
                    978: {
                    979:     uae_u8 b;
                    980:     uae_u32 src, src2, len, len2;
                    981:     char *name;
                    982:     FILE *fp;
                    983: 
                    984:     if (!more_params (cc))
                    985:        goto S_argh;
                    986: 
                    987:     name = *cc;
                    988:     while (**cc != '\0' && !isspace (**cc))
                    989:        (*cc)++;
                    990:     if (!isspace (**cc))
                    991:        goto S_argh;
                    992: 
                    993:     **cc = '\0';
                    994:     (*cc)++;
                    995:     if (!more_params (cc))
                    996:        goto S_argh;
                    997:     src2 = src = readhex (cc);
                    998:     if (!more_params (cc))
                    999:        goto S_argh;
                   1000:     len2 = len = readhex (cc);
                   1001:     fp = fopen (name, "wb");
                   1002:     if (fp == NULL) {
                   1003:        console_out ("Couldn't open file '%s'\n", name);
1.1       root     1004:        return;
                   1005:     }
1.1.1.11  root     1006:     while (len > 0) {
                   1007:        b = get_byte (src);
                   1008:        src++;
                   1009:        len--;
                   1010:        if (fwrite (&b, 1, 1, fp) != 1) {
                   1011:            console_out ("Error writing file\n");
                   1012:            break;
                   1013:        }
                   1014:     }
                   1015:     fclose (fp);
                   1016:     if (len == 0)
                   1017:        console_out ("Wrote %08X - %08X (%d bytes) to '%s'\n",
                   1018:            src2, src2 + len2, len2, name);
                   1019:     return;
                   1020: S_argh:
                   1021:     console_out ("S-command needs more arguments!\n");
                   1022: }
1.1       root     1023: 
1.1.1.11  root     1024: static void searchmem (char **cc)
                   1025: {
                   1026:     int i, sslen, got, val, stringmode;
                   1027:     uae_u8 ss[256];
                   1028:     uae_u32 addr, endaddr;
                   1029:     char nc;
                   1030: 
                   1031:     got = 0;
                   1032:     sslen = 0;
                   1033:     stringmode = 0;
                   1034:     ignore_ws (cc);
                   1035:     if (**cc == '"') {
                   1036:        stringmode = 1;
                   1037:        (*cc)++;
                   1038:        while (**cc != '"' && **cc != 0) {
                   1039:            ss[sslen++] = tolower (**cc);
                   1040:            (*cc)++;
                   1041:        }
                   1042:        if (**cc != 0)
                   1043:            (*cc)++;
                   1044:     } else {
                   1045:        for (;;) {
                   1046:            if (**cc == 32 || **cc == 0)
                   1047:                break;
                   1048:            nc = toupper (next_char (cc));
                   1049:            if (isspace (nc))
                   1050:                break;
                   1051:            if (isdigit(nc))
                   1052:                val = nc - '0';
                   1053:            else
                   1054:                val = nc - 'A' + 10;
                   1055:            if (val < 0 || val > 15)
                   1056:                return;
                   1057:            val *= 16;
                   1058:            if (**cc == 32 || **cc == 0)
                   1059:                break;
                   1060:            nc = toupper (next_char (cc));
                   1061:            if (isspace (nc))
                   1062:                break;
                   1063:            if (isdigit(nc))
                   1064:                val += nc - '0';
                   1065:            else
                   1066:                val += nc - 'A' + 10;
                   1067:            if (val < 0 || val > 255)
                   1068:                return;
                   1069:            ss[sslen++] = (uae_u8)val;
                   1070:        }
                   1071:     }
                   1072:     if (sslen == 0)
                   1073:        return;
                   1074:     ignore_ws (cc);
                   1075:     addr = 0;
                   1076:     endaddr = nextaddr (0xffffffff);
                   1077:     if (more_params (cc)) {
                   1078:        addr = readhex (cc);
                   1079:        if (more_params (cc))
                   1080:            endaddr = readhex (cc);
                   1081:     }
                   1082:     console_out ("Searching from %08x to %08x..\n", addr, endaddr);
                   1083:     while (addr < endaddr && addr != 0xffffffff) {
                   1084:        for (i = 0; i < sslen; i++) {
                   1085:            uae_u8 b = get_byte (addr + i);
                   1086:            if (stringmode) {
                   1087:                if (tolower (b) != ss[i])
                   1088:                    break;
                   1089:            } else {
                   1090:                if (b != ss[i])
                   1091:                    break;
                   1092:            }
                   1093:        }
                   1094:        if (i == sslen) {
                   1095:            got++;
                   1096:            console_out (" %08x", addr);
                   1097:            if (got > 100) {
                   1098:                console_out ("\nMore than 100 results, aborting..");
                   1099:                break;
                   1100:            }
                   1101:        }
                   1102:        addr = nextaddr (addr);
1.1       root     1103:     }
1.1.1.11  root     1104:     if (!got)
                   1105:        console_out ("nothing found");
                   1106:     console_out ("\n");
1.1.1.12! root     1107: }
1.1.1.11  root     1108: 
                   1109: static void m68k_modify (char **inptr)
                   1110: {
                   1111:     char c1, c2;
                   1112:     uae_u32 v;
1.1.1.12! root     1113: 
1.1.1.11  root     1114:     c1 = toupper (next_char (inptr));
                   1115:     if (!more_params (inptr))
                   1116:        return;
                   1117:     c2 = toupper (next_char (inptr));
                   1118:     if (c2 < '0' || c2 > '7')
                   1119:        return;
                   1120:     c2 -= '0';
                   1121:     v = readhex (inptr);
                   1122:     if (c1 == 'A')
                   1123:        regs.regs[8 + c2] = v;
                   1124:     else if (c1 == 'D')
                   1125:        regs.regs[c2] = v;
                   1126:     else if (c1 == 'P' && c2 == 0)
                   1127:        regs.irc = v;
                   1128:     else if (c1 == 'P' && c2 == 1)
                   1129:        regs.ir = v;
                   1130: }
                   1131: 
                   1132: static void debug_1 (void)
                   1133: {
                   1134:     char input[80];
                   1135:     uaecptr nxdis,nxmem,nxcopper;
1.1       root     1136: 
1.1.1.7   root     1137:     m68k_dumpstate (stdout, &nextpc);
1.1.1.9   root     1138:     nxdis = nextpc; nxmem = nxcopper = 0;
1.1       root     1139: 
1.1.1.4   root     1140:     for (;;) {
                   1141:        char cmd, *inptr;
1.1.1.3   root     1142: 
1.1.1.11  root     1143:        console_out (">");
                   1144:        console_flush ();
1.1.1.12! root     1145:        if (!console_get (input, 80))
1.1.1.11  root     1146:            continue;
1.1       root     1147:        inptr = input;
1.1.1.4   root     1148:        cmd = next_char (&inptr);
                   1149:        switch (cmd) {
1.1.1.9   root     1150:        case 'c': dumpcia (); dumpdisk (); dumpcustom (); break;
1.1.1.11  root     1151:        case 'i': dump_vectors (); break;
                   1152:        case 'r': if (more_params(&inptr))
                   1153:                      m68k_modify (&inptr);
                   1154:                  else
                   1155:                      m68k_dumpstate (stdout, &nextpc);
                   1156:        break;
1.1.1.9   root     1157:        case 'M': modulesearch (); break;
1.1.1.12! root     1158:        case 'C': cheatsearch (&inptr); break;
1.1.1.9   root     1159:        case 'W': writeintomem (&inptr); break;
1.1.1.11  root     1160:        case 'w': memwatch (&inptr); break;
                   1161:        case 'S': savemem (&inptr); break;
                   1162:        case 's': searchmem (&inptr); break;
1.1.1.9   root     1163:        case 'd':
                   1164:        {
                   1165:            uae_u32 daddr;
                   1166:            int count;
                   1167: 
                   1168:            if (more_params(&inptr))
                   1169:                daddr = readhex(&inptr);
                   1170:            else
                   1171:                daddr = nxdis;
                   1172:            if (more_params(&inptr))
                   1173:                count = readhex(&inptr);
                   1174:            else
                   1175:                count = 10;
                   1176:            m68k_disasm (stdout, daddr, &nxdis, count);
                   1177:        }
                   1178:        break;
                   1179:        case 'T': show_exec_tasks (); break;
1.1.1.11  root     1180:        case 't':
                   1181:            if (more_params (&inptr))
                   1182:                skipaddr_doskip = readint (&inptr);
                   1183:            if (skipaddr_doskip <= 0 || skipaddr_doskip > 10000)
                   1184:                skipaddr_doskip = 1;
                   1185:            set_special (SPCFLAG_BRK);
                   1186:            exception_debugging = 1;
                   1187:            return;
1.1.1.9   root     1188:        case 'z':
1.1.1.11  root     1189:            skipaddr_start = nextpc;
                   1190:            skipaddr_doskip = 1;
1.1       root     1191:            do_skip = 1;
1.1.1.11  root     1192:            exception_debugging = 1;
1.1       root     1193:            return;
                   1194: 
1.1.1.9   root     1195:        case 'f':
1.1.1.11  root     1196:            if (instruction_breakpoint (&inptr))
                   1197:                return;
                   1198:            break;
1.1       root     1199: 
1.1.1.9   root     1200:        case 'q': uae_quit();
1.1.1.3   root     1201:            debugger_active = 0;
                   1202:            debugging = 0;
                   1203:            return;
                   1204: 
1.1.1.9   root     1205:        case 'g':
1.1.1.11  root     1206:            if (more_params (&inptr)) {
1.1       root     1207:                m68k_setpc (readhex (&inptr));
1.1.1.11  root     1208:                fill_prefetch_slow ();
                   1209:            }
1.1       root     1210:            debugger_active = 0;
                   1211:            debugging = 0;
1.1.1.11  root     1212:            exception_debugging = 0;
1.1       root     1213:            return;
                   1214: 
1.1.1.9   root     1215:        case 'H':
                   1216:        {
                   1217:            int count;
                   1218:            int temp;
1.1       root     1219: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9   root     1220:            struct regstruct save_regs = regs;
                   1221:            union flagu save_flags = regflags;
1.1       root     1222: #endif
                   1223: 
1.1.1.9   root     1224:            if (more_params(&inptr))
                   1225:                count = readhex(&inptr);
                   1226:            else
                   1227:                count = 10;
                   1228:            if (count < 0)
                   1229:                break;
                   1230:            temp = lasthist;
                   1231:            while (count-- > 0 && temp != firsthist) {
                   1232:                if (temp == 0) temp = MAX_HIST-1; else temp--;
                   1233:            }
                   1234:            while (temp != lasthist) {
1.1       root     1235: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9   root     1236:                regs = history[temp];
                   1237:                regflags = historyf[temp];
                   1238:                m68k_dumpstate (NULL);
1.1       root     1239: #else
1.1.1.9   root     1240:                m68k_disasm (stdout, history[temp], NULL, 1);
1.1       root     1241: #endif
1.1.1.9   root     1242:                if (++temp == MAX_HIST) temp = 0;
                   1243:            }
1.1       root     1244: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9   root     1245:            regs = save_regs;
                   1246:            regflags = save_flags;
1.1       root     1247: #endif
1.1.1.9   root     1248:        }
                   1249:        break;
                   1250:        case 'm':
                   1251:        {
                   1252:            uae_u32 maddr; int lines;
                   1253:            if (more_params(&inptr))
                   1254:                maddr = readhex(&inptr);
                   1255:            else
                   1256:                maddr = nxmem;
                   1257:            if (more_params(&inptr))
                   1258:                lines = readhex(&inptr);
                   1259:            else
1.1.1.11  root     1260:                lines = 20;
1.1.1.9   root     1261:            dumpmem(maddr, &nxmem, lines);
                   1262:        }
                   1263:        break;
                   1264:        case 'o':
                   1265:        {
                   1266:            uae_u32 maddr;
                   1267:            int lines;
1.1.1.12! root     1268: 
1.1.1.9   root     1269:            if (more_params(&inptr)) {
                   1270:                maddr = readhex(&inptr);
                   1271:                if (maddr == 1 || maddr == 2)
1.1.1.12! root     1272:                    maddr = get_copper_address (maddr);
1.1       root     1273:            }
1.1.1.9   root     1274:            else
                   1275:                maddr = nxcopper;
                   1276: 
                   1277:            if (more_params (&inptr))
                   1278:                lines = readhex (&inptr);
                   1279:            else
1.1.1.11  root     1280:                lines = 20;
1.1.1.9   root     1281: 
                   1282:            nxcopper = decode_copperlist (stdout, maddr, lines);
1.1       root     1283:            break;
1.1.1.9   root     1284:        }
                   1285:        case 'O':
                   1286:            if (more_params (&inptr)) {
                   1287:                int plane = readint (&inptr);
                   1288:                int offs = readint (&inptr);
                   1289:                if (plane >= 0 && plane < 8)
1.1.1.10  root     1290:                    bpl_off[plane] = offs;
1.1.1.9   root     1291:            } else {
                   1292:                int i;
                   1293:                for (i = 0; i < 8; i++)
1.1.1.11  root     1294:                    console_out ("Plane %d offset %d\n", i, bpl_off[i]);
1.1.1.3   root     1295:            }
                   1296:            break;
1.1.1.9   root     1297:        case 'h':
                   1298:        case '?':
1.1.1.11  root     1299:            debug_help ();
1.1.1.9   root     1300:        break;
1.1       root     1301:        }
                   1302:     }
                   1303: }
1.1.1.11  root     1304: 
                   1305: void debug (void)
                   1306: {
                   1307:     int i;
                   1308: 
                   1309:     bogusframe = 1;
                   1310: 
                   1311:     if (do_skip && skipaddr_start == 0xC0DEDBAD) {
                   1312: #if 0
                   1313:        if (trace_same_insn_count > 0) {
                   1314:            if (memcmp (trace_insn_copy, regs.pc_p, 10) == 0
                   1315:                && memcmp (trace_prev_regs.regs, regs.regs, sizeof regs.regs) == 0)
                   1316:            {
                   1317:                trace_same_insn_count++;
                   1318:                return;
                   1319:            }
                   1320:        }
                   1321:        if (trace_same_insn_count > 1)
                   1322:            fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
                   1323: #endif
                   1324:        m68k_dumpstate (logfile, &nextpc);
                   1325:        trace_same_insn_count = 1;
                   1326:        memcpy (trace_insn_copy, regs.pc_p, 10);
                   1327:        memcpy (&trace_prev_regs, &regs, sizeof regs);
                   1328:     }
                   1329: 
                   1330:     if (!memwatch_triggered) {
                   1331:        if (do_skip) {
                   1332:            uae_u32 pc = munge24 (m68k_getpc());
                   1333:            uae_u16 opcode = currprefs.cpu_compatible ? regs.ir : get_word (pc);
                   1334:            int bp = 0;
                   1335: 
                   1336:            for (i = 0; i < BREAKPOINT_TOTAL; i++) {
1.1.1.12! root     1337:                if (!bpnodes[i].enabled)
1.1.1.11  root     1338:                    continue;
                   1339:                if (bpnodes[i].addr == pc) {
                   1340:                    bp = 1;
                   1341:                    console_out ("Breakpoint at %08.8X\n", pc);
                   1342:                    break;
                   1343:                }
                   1344:            }
                   1345:            if (skipaddr_doskip) {
                   1346:                if (skipaddr_start == pc)
                   1347:                    bp = 1;
                   1348:                if (skipins != 0xffffffff) {
                   1349:                    if (skipins == 0x10000) {
                   1350:                        if (opcode == 0x4e75 || opcode == 0x4e73 || opcode == 0x4e77)
                   1351:                            bp = 1;
                   1352:                    } else if (opcode == skipins)
                   1353:                        bp = 1;
                   1354:                } else if (skipaddr_start == 0xffffffff && skipaddr_doskip < 0) {
                   1355:                    if ((pc < 0xe00000 || pc >= 0x1000000) && opcode != 0x4ef9)
                   1356:                        bp = 1;
                   1357:                } else if (skipaddr_start == 0xffffffff && skipaddr_doskip > 0) {
                   1358:                        bp = 1;
                   1359:                } else if (skipaddr_end != 0xffffffff) {
                   1360:                    if (pc >= skipaddr_start && pc < skipaddr_end)
                   1361:                        bp = 1;
                   1362:                }
                   1363:            }
                   1364:            if (!bp) {
1.1.1.12! root     1365:                set_special (SPCFLAG_BRK);
1.1.1.11  root     1366:                return;
                   1367:            }
                   1368:        }
                   1369:     } else {
1.1.1.12! root     1370:        write_log ("Memwatch %d: break at %08.8X.%c %c %08.8X\n", memwatch_triggered - 1, mwhit.addr,
1.1.1.11  root     1371:            mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'), mwhit.rw ? 'W' : 'R', mwhit.val);
                   1372:        memwatch_triggered = 0;
                   1373:     }
                   1374:     if (skipaddr_doskip > 0) {
                   1375:        skipaddr_doskip--;
                   1376:        if (skipaddr_doskip > 0) {
                   1377:            set_special (SPCFLAG_BRK);
                   1378:            return;
                   1379:        }
                   1380:     }
                   1381: 
                   1382: #ifdef NEED_TO_DEBUG_BADLY
                   1383:     history[lasthist] = regs;
                   1384:     historyf[lasthist] = regflags;
                   1385: #else
                   1386:     history[lasthist] = m68k_getpc();
                   1387: #endif
                   1388:     if (++lasthist == MAX_HIST) lasthist = 0;
                   1389:     if (lasthist == firsthist) {
                   1390:        if (++firsthist == MAX_HIST) firsthist = 0;
                   1391:     }
                   1392: #if 0
                   1393:     inputdevice_unacquire ();
                   1394:     pause_sound ();
                   1395: #endif
                   1396:     do_skip = 0;
                   1397:     skipaddr_start = 0xffffffff;
                   1398:     skipaddr_end = 0xffffffff;
                   1399:     skipins = 0xffffffff;
                   1400:     skipaddr_doskip = 0;
                   1401:     exception_debugging = 0;
                   1402:     debug_1 ();
                   1403:     for (i = 0; i < BREAKPOINT_TOTAL; i++) {
                   1404:        if (bpnodes[i].enabled)
                   1405:            do_skip = 1;
                   1406:     }
                   1407:     if (do_skip) {
1.1.1.12! root     1408:        set_special (SPCFLAG_BRK);
1.1.1.11  root     1409:        debugging = 1;
                   1410:     }
                   1411: #if 0
                   1412:     resume_sound ();
                   1413:     inputdevice_acquire ();
                   1414: #endif
                   1415: }
                   1416: 
                   1417: int notinrom (void)
                   1418: {
                   1419:     if (munge24 (m68k_getpc()) < 0xe0000)
                   1420:        return 1;
                   1421:     return 0;
                   1422: }
                   1423: 
                   1424: const char *debuginfo (int mode)
                   1425: {
                   1426:     static char txt[100];
                   1427:     uae_u32 pc = m68k_getpc();
                   1428:     sprintf (txt, "PC=%08.8X INS=%04.4X %04.4X %04.4X",
                   1429:        pc, get_word(pc), get_word(pc+2), get_word(pc+4));
                   1430:     return txt;
                   1431: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.