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

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

unix.superglobalmegacorp.com

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