Annotation of previous_trunk/src/dimension/i860dbg.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

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