|
|
1.1 ! root 1: /*************************************************************************** ! 2: ! 3: i860dbg.cpp ! 4: ! 5: Debugger for the Intel i860 emulator. ! 6: ! 7: Copyright (C) 1995-present Jason Eckhardt ([email protected]) ! 8: Released for general non-commercial use under the MAME license ! 9: with the additional requirement that you are free to use and ! 10: redistribute this code in modified or unmodified form, provided ! 11: you list me in the credits. ! 12: Visit http://mamedev.org for licensing and usage restrictions. ! 13: ! 14: Changes for previous/NeXTdimension by Simon Schubiger (SC) ! 15: ! 16: ***************************************************************************/ ! 17: ! 18: int i860_disassembler(UINT32 pc, UINT32 insn, char* buffer); ! 19: ! 20: /* A simple internal debugger. */ ! 21: void i860_cpu_device::debugger() { ! 22: debugger(0, ""); ! 23: } ! 24: ! 25: extern volatile int mainPauseEmulation; ! 26: ! 27: void i860_cpu_device::debugger(char cmd, const char* format, ...) { ! 28: if(!(isatty(fileno(stdin)))) return; ! 29: ! 30: char buf[256]; ! 31: UINT32 curr_disasm = m_pc; ! 32: UINT32 curr_dumpdb = 0; ! 33: int c = 0; ! 34: ! 35: if(format) ! 36: m_single_stepping = 0; ! 37: ! 38: if (m_single_stepping > 1 && m_single_stepping != m_pc) ! 39: return; ! 40: ! 41: mainPauseEmulation = 1; ! 42: ! 43: if(format) { ! 44: va_list ap; ! 45: va_start (ap, format); ! 46: fprintf(stderr, "\n[i860]"); ! 47: if(format[0]) { ! 48: fprintf(stderr, " ("); ! 49: vfprintf (stderr, format, ap); ! 50: } ! 51: va_end (ap); ! 52: if(format[0]) ! 53: fprintf(stderr, ")"); ! 54: fprintf(stderr, " debugger started (? for help).\n"); ! 55: } ! 56: ! 57: if(!(cmd)) ! 58: disasm (m_pc, (m_dim ? 2 : 1) + delay_slots(ifetch_notrap(m_pc))); ! 59: ! 60: buf[0] = 0; ! 61: fflush (stdin); ! 62: ! 63: m_single_stepping = 0; ! 64: ! 65: while(!m_single_stepping) { ! 66: if(cmd) { ! 67: m_lastcmd = cmd; ! 68: buf[0] = cmd; ! 69: buf[1] = 0; ! 70: cmd = 0; ! 71: } else { ! 72: fprintf (stderr, ">"); ! 73: for(;;) { ! 74: char it = 0; ! 75: if (read(STDIN_FILENO, &it, 1) == 1) { ! 76: if (it == '\n') { ! 77: buf[c] = 0; ! 78: c = 0; ! 79: break; ! 80: } ! 81: buf[c++] = it; ! 82: } ! 83: } ! 84: if(buf[0] == 0) { ! 85: buf[0] = m_lastcmd; ! 86: buf[1] = 0; ! 87: } else { ! 88: m_lastcmd = buf[0]; ! 89: } ! 90: } ! 91: switch(buf[0]) { ! 92: case 'g': ! 93: if (buf[1] == '0') ! 94: sscanf (buf + 1, "%x", &m_single_stepping); ! 95: else { ! 96: m_single_stepping = 2; ! 97: break; ! 98: } ! 99: buf[1] = 0; ! 100: fprintf (stderr, "go until pc = 0x%08x.\n", m_single_stepping); ! 101: break; ! 102: case 'h': ! 103: halt(true); ! 104: m_single_stepping = 2; ! 105: break; ! 106: case 'c': ! 107: halt(false); ! 108: m_single_stepping = 2; ! 109: break; ! 110: case 'r': ! 111: dump_state(); ! 112: break; ! 113: case 'd': ! 114: if (buf[1] == '0') ! 115: sscanf (buf + 1, "%x", &curr_disasm); ! 116: curr_disasm = disasm (curr_disasm, 10); ! 117: buf[1] = 0; ! 118: break; ! 119: case 'p': ! 120: if (buf[1] >= '0' && buf[1] <= '4') ! 121: dump_pipe (buf[1] - 0x30); ! 122: buf[1] = 0; ! 123: break; ! 124: case 's': ! 125: m_single_stepping = 1; ! 126: break; ! 127: case 'w': ! 128: nd->dbg_cmd(buf); ! 129: break; ! 130: case 'k': ! 131: m_console[m_console_idx] = 0; ! 132: fputs(m_console, stderr); ! 133: fflush(stderr); ! 134: break; ! 135: case 'b': ! 136: SET_PSR_IT (1); ! 137: m_flow |= TRAP_NORMAL; ! 138: m_single_stepping = 2; ! 139: break; ! 140: case 'm': ! 141: if (buf[1] == '0') ! 142: sscanf (buf + 1, "%x", &curr_dumpdb); ! 143: dbg_memdump (curr_dumpdb, 32); ! 144: curr_dumpdb += 32; ! 145: break; ! 146: case 't': { ! 147: int bufsz = sizeof(m_traceback) / sizeof(m_traceback[0]); ! 148: int count = bufsz; ! 149: if(buf[1]) ! 150: sscanf(buf + 1, "%d", &count); ! 151: if(count >= bufsz) count = bufsz; ! 152: fprintf (stderr, "Traceback of last %d instructions:\n", count); ! 153: int before = m_traceback_idx; ! 154: m_traceback_idx += bufsz; ! 155: m_traceback_idx -= count; ! 156: while(count--) ! 157: disasm(m_traceback[m_traceback_idx++ % bufsz], 1); ! 158: m_traceback_idx = before; ! 159: break;} ! 160: case 'x': ! 161: if(buf[1] == '0') { ! 162: UINT32 v; ! 163: sscanf (buf + 1, "%x", &v); ! 164: if (GET_DIRBASE_ATE ()) ! 165: fprintf (stderr, "vma 0x%08x ==> phys 0x%08x\n", v, get_address_translation (v, 1, 0)); ! 166: else ! 167: fprintf (stderr, "not in virtual address mode.\n"); ! 168: break; ! 169: } ! 170: case '?': ! 171: fprintf (stderr, ! 172: " m: dump bytes (m[0xaddress])\n" ! 173: " r: dump registers\n" ! 174: " s: single-step\n" ! 175: " h: halt i860\n" ! 176: " c: continue i860\n" ! 177: " g: go back to emulator (g[0xaddress])\n" ! 178: " k: print console buffer\n" ! 179: " d: disassemble (u[0xaddress])\n" ! 180: " p: dump pipelines (p{0-4} for all, add, mul, load, graphics)\n" ! 181: " b: break - set trap on next instruction\n" ! 182: " t: dump traceback buffer (t[count])\n" ! 183: " x: give virt->phys translation (x{0xaddress})\n"); ! 184: nd->dbg_cmd(0); ! 185: break; ! 186: default: ! 187: if(!(nd->dbg_cmd(buf))) ! 188: fprintf (stderr, "Bad command '%s'. Type '?' for help.\n", buf); ! 189: break; ! 190: } ! 191: } ! 192: ! 193: /* Less noise when single-stepping. */ ! 194: if(m_single_stepping != 1) { ! 195: fprintf (stderr, "Debugger done, continuing emulation.\n"); ! 196: if(m_single_stepping == 2) m_single_stepping = 0; ! 197: } ! 198: ! 199: mainPauseEmulation = 2; ! 200: } ! 201: ! 202: /* Disassemble `len' instructions starting at `addr'. */ ! 203: UINT32 i860_cpu_device::disasm (UINT32 addr, int len) ! 204: { ! 205: UINT32 insn; ! 206: int j; ! 207: for (j = 0; j < len; j++) { ! 208: char buf[256]; ! 209: /* Note that we print the incoming (possibly virtual) address as the ! 210: PC rather than the translated address. */ ! 211: fprintf (stderr, " [i860] %08X: ", addr); ! 212: insn = ifetch_notrap(addr); ! 213: i860_disassembler(addr, insn, buf); ! 214: fprintf (stderr, "%s\n", buf); ! 215: addr += 4; ! 216: } ! 217: return addr; ! 218: } ! 219: ! 220: ! 221: /* Dump `len' bytes starting at `addr'. */ ! 222: void i860_cpu_device::dbg_memdump (UINT32 addr, int len) { ! 223: UINT8 b[16]; ! 224: int i; ! 225: /* This will always dump a multiple of 16 bytes, even if 'len' isn't. */ ! 226: while (len > 0) { ! 227: /* Note that we print the incoming (possibly virtual) address ! 228: rather than the translated address. */ ! 229: fprintf (stderr, "0x%08x: ", addr); ! 230: for (i = 0; i < 16; i++) { ! 231: UINT32 phys_addr = addr; ! 232: if (GET_DIRBASE_ATE ()) ! 233: phys_addr = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); ! 234: ! 235: rdmem[1](nd, phys_addr, (UINT32*)&b[i]); ! 236: fprintf (stderr, "%02x ", b[i]); ! 237: addr++; ! 238: } ! 239: fprintf (stderr, "| "); ! 240: for (i = 0; i < 16; i++) { ! 241: if (isprint (b[i])) ! 242: fprintf (stderr, "%c", b[i]); ! 243: else ! 244: fprintf (stderr, "."); ! 245: } ! 246: fprintf (stderr, "\n"); ! 247: len -= 16; ! 248: } ! 249: } ! 250: ! 251: /* Do a pipeline dump. ! 252: type: 0 (all), 1 (add), 2 (mul), 3 (load), 4 (graphics). */ ! 253: void i860_cpu_device::dump_pipe (int type) ! 254: { ! 255: int i = 0; ! 256: ! 257: fprintf (stderr, "pipeline state:\n"); ! 258: /* Dump the adder pipeline, if requested. */ ! 259: if (type == 0 || type == 1) ! 260: { ! 261: fprintf (stderr, " A: "); ! 262: for (i = 0; i < 3; i++) ! 263: { ! 264: if (m_A[i].stat.arp) ! 265: fprintf (stderr, "[%dd] 0x%016llx ", i + 1, ! 266: *(UINT64 *)(&m_A[i].val.d)); ! 267: else ! 268: fprintf (stderr, "[%ds] 0x%08x ", i + 1, ! 269: *(UINT32 *)(&m_A[i].val.s)); ! 270: } ! 271: fprintf (stderr, "\n"); ! 272: } ! 273: ! 274: ! 275: /* Dump the multiplier pipeline, if requested. */ ! 276: if (type == 0 || type == 2) ! 277: { ! 278: fprintf (stderr, " M: "); ! 279: for (i = 0; i < 3; i++) ! 280: { ! 281: if (m_M[i].stat.mrp) ! 282: fprintf (stderr, "[%dd] 0x%016llx ", i + 1, ! 283: *(UINT64 *)(&m_M[i].val.d)); ! 284: else ! 285: fprintf (stderr, "[%ds] 0x%08x ", i + 1, ! 286: *(UINT32 *)(&m_M[i].val.s)); ! 287: } ! 288: fprintf (stderr, "\n"); ! 289: } ! 290: ! 291: /* Dump the load pipeline, if requested. */ ! 292: if (type == 0 || type == 3) ! 293: { ! 294: fprintf (stderr, " L: "); ! 295: for (i = 0; i < 3; i++) ! 296: { ! 297: if (m_L[i].stat.lrp) ! 298: fprintf (stderr, "[%dd] 0x%016llx ", i + 1, ! 299: *(UINT64 *)(&m_L[i].val.d)); ! 300: else ! 301: fprintf (stderr, "[%ds] 0x%08x ", i + 1, ! 302: *(UINT32 *)(&m_L[i].val.s)); ! 303: } ! 304: fprintf (stderr, "\n"); ! 305: } ! 306: ! 307: /* Dump the graphics pipeline, if requested. */ ! 308: if (type == 0 || type == 4) ! 309: { ! 310: fprintf (stderr, " I: "); ! 311: if (m_G.stat.irp) ! 312: fprintf (stderr, "[1d] 0x%016llx\n", ! 313: *(UINT64 *)(&m_G.val.d)); ! 314: else ! 315: fprintf (stderr, "[1s] 0x%08x\n", ! 316: *(UINT32 *)(&m_G.val.s)); ! 317: } ! 318: } ! 319: ! 320: ! 321: /* Do a register/state dump. */ ! 322: void i860_cpu_device::dump_state() ! 323: { ! 324: int rn; ! 325: ! 326: /* GR's first, 4 per line. */ ! 327: for (rn = 0; rn < 32; rn++) ! 328: { ! 329: if ((rn % 4) == 0) ! 330: fprintf (stderr, "\n"); ! 331: fprintf (stderr, "%%r%-3d: 0x%08x ", rn, get_iregval (rn)); ! 332: } ! 333: fprintf (stderr, "\n"); ! 334: ! 335: /* FR's (as 32-bits), 4 per line. */ ! 336: for (rn = 0; rn < 32; rn++) ! 337: { ! 338: FLOAT32 ff = get_fregval_s (rn); ! 339: if ((rn % 4) == 0) ! 340: fprintf (stderr, "\n"); ! 341: fprintf (stderr, "%%f%-3d: 0x%08x ", rn, *(UINT32 *)&ff); ! 342: } ! 343: fprintf (stderr, "\n"); ! 344: fprintf(stderr, " psr: CC=%d LCC=%d SC=%d IM=%d U=%d IT=%d FT=%d IAT=%d DAT=%d IN=%d PS=%d PM=%08X\n", ! 345: GET_PSR_CC (), GET_PSR_LCC (), GET_PSR_SC (), GET_PSR_IM (), GET_PSR_U (), ! 346: GET_PSR_IT (), GET_PSR_FT (), GET_PSR_IAT (), GET_PSR_DAT (), GET_PSR_IN (), GET_PSR_PS(), GET_PSR_PM()); ! 347: fprintf(stderr, " epsr: INT=%d, OF=%d BE=%d WP=%d\n", GET_EPSR_INT (), GET_EPSR_OF (), GET_EPSR_BE (), GET_EPSR_WP()); ! 348: fprintf(stderr, "dirbase: CS8=%d ATE=%d 0x%08x", GET_DIRBASE_CS8(), GET_DIRBASE_ATE(), m_cregs[CR_DIRBASE]); ! 349: fprintf(stderr, " fir: 0x%08x fsr: 0x%08x pc:0x%08x\n", m_cregs[CR_FIR], m_cregs[CR_FSR], m_pc); ! 350: fprintf(stderr, " merge: 0x%016llx\n", m_merge); ! 351: } ! 352: ! 353: void i860_cpu_device::halt(bool state) { ! 354: if(state) { ! 355: m_halt = true; ! 356: Log_Printf(LOG_WARN, "[i860] **** HALTED ****"); ! 357: Statusbar_SetNdLed(0); ! 358: } else { ! 359: Log_Printf(LOG_WARN, "[i860] **** RESTARTED ****"); ! 360: m_halt = false; ! 361: Statusbar_SetNdLed(1); ! 362: } ! 363: } ! 364: ! 365: void i860_cpu_device::pause(bool state) { ! 366: if(state) { ! 367: m_halt = true; ! 368: Log_Printf(LOG_WARN, "[i860] **** PAUSED ****"); ! 369: } else { ! 370: Log_Printf(LOG_WARN, "[i860] **** RESUMED ****"); ! 371: m_halt = false; ! 372: } ! 373: } ! 374: ! 375: void i860_cpu_device::dbg_check_wr(UINT32 addr, int size, UINT8* data) { ! 376: if(addr == 0xF83FE800 || addr == 0xF80FF800) { ! 377: switch(*((UINT32*)data)) { ! 378: case 0: ! 379: case 4: { ! 380: // catch ND console writes ! 381: UINT32 ptr = addr + 4; ! 382: int count; readmem_emu(ptr, 4, (UINT8*)&count); ! 383: int col = 0; ! 384: ptr += 4; ! 385: if(count < 1024) { // sanity check ! 386: for(int i = 0; i < count; i++) { ! 387: char ch; readmem_emu(ptr++, 1, (UINT8*)&ch); ! 388: switch(ch) { // msg cleanup & tab expand for debugger console ! 389: case '\r': continue; ! 390: case '\t': while(col++ % 16) m_console[m_console_idx++] = ' '; continue; ! 391: case '\n': ! 392: col = -1; ! 393: // fall-through ! 394: default: ! 395: m_console[m_console_idx++] = ch; ! 396: col++; ! 397: break; ! 398: } ! 399: } ! 400: m_console[m_console_idx] = 0; ! 401: if(strstr(m_console, "NeXTdimension Trap:")) ! 402: m_break_on_next_msg = true; ! 403: if(*((UINT32*)data) == 4) { ! 404: char exit_code; readmem_emu(addr + 8, 1, (UINT8*)&exit_code); ! 405: debugger('k', "NeXTdimension exit(%d)", exit_code); ! 406: } ! 407: } ! 408: break; ! 409: } ! 410: case 5: ! 411: if(m_break_on_next_msg) { ! 412: m_break_on_next_msg = false; ! 413: debugger('k', "NeXTdimension Trap"); ! 414: } ! 415: break; ! 416: } ! 417: } ! 418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.