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

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

unix.superglobalmegacorp.com

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