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

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

unix.superglobalmegacorp.com

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