/***************************************************************************** * pce * *****************************************************************************/ /***************************************************************************** * File name: src/arch/macplus/cmd_68k.c * * Created: 2007-04-15 by Hampa Hug * * Copyright: (C) 2007-2023 Hampa Hug * *****************************************************************************/ /***************************************************************************** * This program is free software. You can redistribute it and / or modify it * * under the terms of the GNU General Public License version 2 as published * * by the Free Software Foundation. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY, without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * * Public License for more details. * *****************************************************************************/ #include "main.h" #include "cmd_68k.h" #include "macplus.h" #include "traps.h" #include #include #include #include #include #include #include #include #include mon_cmd_t par_cmd[] = { { "c", "[cnt]", "clock" }, { "gb", "[addr..]", "run with breakpoints at addr" }, { "ge", "[exception]", "run until exception" }, { "g", "", "run" }, { "halt", "[val]", "set halt state [2]" }, { "p", "[cnt]", "execute cnt instructions, skip calls [1]" }, { "reset", "", "reset" }, { "rte", "", "execute to next rte" }, { "r", "reg [val]", "get or set a register" }, { "s", "[what]", "print status (cpu|disks|iwm|mem|scc|via)" }, { "t", "[cnt]", "execute cnt instructions [1]" }, { "u", "[gas] [[-]addr [cnt]]", "disassemble" } }; unsigned par_cmd_cnt = sizeof (par_cmd) / sizeof (par_cmd[0]); static void mac_dasm_str (char *dst, e68_dasm_t *op) { unsigned i, n; char tmp[512]; const char *ins; strcpy (dst, ""); for (i = 0; i < op->irn; i++) { sprintf (tmp, "%04X ", (unsigned) op->ir[i]); strcat (dst, tmp); } for (i = op->irn; i < 4; i++) { strcat (dst, " "); } if (op->flags & E68_DFLAG_PRIV) { strcat (dst, "*"); } else if (op->flags & E68_DFLAG_CALL) { strcat (dst, ">"); } else if (op->flags & E68_DFLAG_RTS) { strcat (dst, "<"); } else { strcat (dst, " "); } ins = mac_get_trap_name (op->ir[0]); if (ins == NULL) { ins = op->op; } switch (op->argn) { case 0: sprintf (tmp, "%s", ins); break; case 1: sprintf (tmp, "%-8s %s", ins, op->arg1); break; case 2: sprintf (tmp, "%-8s %s, %s", ins, op->arg1, op->arg2); break; case 3: sprintf (tmp, "%-8s %s, %s, %s", ins, op->arg1, op->arg2, op->arg3 ); break; default: strcpy (tmp, "---"); break; } strcat (dst, tmp); if (op->comm[0] != 0) { n = strlen (dst); dst += n; while (n < 50) { *(dst++) = ' '; n += 1; } strcpy (dst, "; "); strcat (dst, op->comm); } } static void mac_prt_state_cpu (e68000_t *c) { unsigned long opcnt, clkcnt; unsigned long delay; e68_dasm_t op; char str[256]; pce_prt_sep ("68000"); opcnt = e68_get_opcnt (c); clkcnt = e68_get_clkcnt (c); delay = e68_get_delay (c); pce_printf ("CLK=%lx OP=%lx DLY=%lu CPI=%.4f\n", clkcnt, opcnt, delay, (opcnt > 0) ? ((double) (clkcnt + delay) / (double) opcnt) : 1.0 ); pce_printf (" SR=%04X[%c%c] CC=%02X[%c%c%c%c%c] EX=%02X(%-4s) TRP=%04X IML=%X IPL=%X\n", (unsigned) e68_get_sr (c), (e68_get_sr_t (c)) ? 'T' : '-', (e68_get_sr_s (c)) ? 'S' : '-', (unsigned) e68_get_ccr (c), (e68_get_sr_c (c)) ? 'C' : '-', (e68_get_sr_v (c)) ? 'V' : '-', (e68_get_sr_z (c)) ? 'Z' : '-', (e68_get_sr_n (c)) ? 'N' : '-', (e68_get_sr_x (c)) ? 'X' : '-', e68_get_exception (c), e68_get_exception_name (c), e68_get_last_trap_a (c), e68_get_iml (c), e68_get_ipl (c) ); pce_printf (" D0=%08lX D4=%08lX A0=%08lX A4=%08lX PC=%08lX\n", (unsigned long) e68_get_dreg32 (c, 0), (unsigned long) e68_get_dreg32 (c, 4), (unsigned long) e68_get_areg32 (c, 0), (unsigned long) e68_get_areg32 (c, 4), (unsigned long) e68_get_pc (c) ); pce_printf (" D1=%08lX D5=%08lX A1=%08lX A5=%08lX LPC=%08lX\n", (unsigned long) e68_get_dreg32 (c, 1), (unsigned long) e68_get_dreg32 (c, 5), (unsigned long) e68_get_areg32 (c, 1), (unsigned long) e68_get_areg32 (c, 5), e68_get_last_pc (c, 0) ); pce_printf (" D2=%08lX D6=%08lX A2=%08lX A6=%08lX USP=%08lX\n", (unsigned long) e68_get_dreg32 (c, 2), (unsigned long) e68_get_dreg32 (c, 6), (unsigned long) e68_get_areg32 (c, 2), (unsigned long) e68_get_areg32 (c, 6), (unsigned long) e68_get_usp (c) ); pce_printf (" D3=%08lX D7=%08lX A3=%08lX A7=%08lX SSP=%08lX\n", (unsigned long) e68_get_dreg32 (c, 3), (unsigned long) e68_get_dreg32 (c, 7), (unsigned long) e68_get_areg32 (c, 3), (unsigned long) e68_get_areg32 (c, 7), (unsigned long) e68_get_ssp (c) ); e68_dasm_mem (c, &op, e68_get_pc (c)); mac_dasm_str (str, &op); pce_printf ("%08lX %s\n", (unsigned long) e68_get_pc (c), str); } static void mac_prt_state_scc (macplus_t *sim) { unsigned i; e8530_t *scc; e8530_chn_t *chn; static const char p[4] = { 'N', 'O', 'E', ' ' }; static const char *s[5] = { "0", "", "1", "1.5", "2" }; scc = &sim->scc; pce_prt_sep ("8530-SCC"); pce_printf ("IRQ=%u\n", scc->irq_val); for (i = 0; i < 2; i++) { chn = scc->chn + i; pce_printf ("CHN%u=%u%c%u%s\n", i, chn->bps, p[chn->parity & 3], chn->bpc, s[chn->stop] ); } for (i = 0; i < 16; i++) { pce_printf ( "WR%02uA=%02X RR%02uA=%02X WR%02uB=%02X RR%02uB=%02X\n", i, scc->chn[0].wr[i], i, scc->chn[0].rr[i], i, scc->chn[1].wr[i], i, scc->chn[1].rr[i] ); } } static void mac_prt_state_via (macplus_t *sim) { e6522_t *via; via = &sim->via; pce_prt_sep ("6522-VIA"); pce_printf (" PCR=%02X ACR=%02X IFR=%02X IER=%02X IRQ=%u\n", via->pcr, via->acr, via->ifr, via->ier, via->irq_val ); pce_printf ("DDRA=%02X DDRB=%02X CA1=%X T1L=%04X SHFT=%02X/%u\n", via->ddra, via->ddrb, via->ca1_inp, via->t1_latch, via->shift_val, via->shift_cnt ); pce_printf (" IRA=%02X IRB=%02X CA2=%X %cT1V=%04X\n", via->ira, via->irb, via->ca2_inp, via->t1_hot ? '*' : ' ', via->t1_val ); pce_printf (" ORA=%02X ORB=%02X CB1=%X T2L=%04X\n", via->ora, via->orb, 0, via->t2_latch ); pce_printf (" PA=%02X PB=%02X CB2=%X %cT2V=%04X\n", sim->via_port_a, sim->via_port_b, 0, via->t2_hot ? '*' : ' ', via->t2_val ); } static void mac_print_state_iwm (macplus_t *sim) { unsigned i; mac_iwm_drive_t *drv; mac_iwm_t *iwm; pce_prt_sep ("IWM"); iwm = &sim->iwm; pce_printf ("DSEL=%02X HSEL=%02X LINE=%02X WR=%d\n", iwm->drive_sel, iwm->head_sel, iwm->lines, iwm->writing ); pce_printf ("STAT=%02X MODE=%02X HDSK=%02X\n", iwm->status, iwm->mode, iwm->handshake ); pce_printf ("SCNT=%u SHFT=%02X RBUF=%02X\n", iwm->shift_cnt, iwm->shift, iwm->read_buf ); for (i = 0; i < 2; i++) { drv = &sim->iwm.drv[i]; pce_printf ("D%u: DSK=%d MOT=%d MOD=%c%c TRK=%2u/%u POS=%lu/%lu\n", i + 1, drv->disk_inserted, drv->motor_on, drv->dirty ? 'D' : '-', drv->track_dirty ? 'T' : '-', drv->cur_cyl, drv->cur_head, drv->cur_track_pos, drv->cur_track_len ); } } static void mac_prt_state_mem (macplus_t *sim) { pce_prt_sep ("MEM"); mem_prt_state (sim->mem, stdout); } void mac_prt_state (macplus_t *sim, const char *str) { cmd_t cmd; cmd_set_str (&cmd, str); if (cmd_match_eol (&cmd)) { return; } while (!cmd_match_eol (&cmd)) { if (cmd_match (&cmd, "cpu")) { mac_prt_state_cpu (sim->cpu); } else if (cmd_match (&cmd, "disks")) { dsks_print_info (sim->dsks); } else if (cmd_match (&cmd, "iwm")) { mac_print_state_iwm (sim); } else if (cmd_match (&cmd, "mem")) { mac_prt_state_mem (sim); } else if (cmd_match (&cmd, "scc")) { mac_prt_state_scc (sim); } else if (cmd_match (&cmd, "via")) { mac_prt_state_via (sim); } else { pce_printf ("unknown component (%s)\n", cmd_get_str (&cmd)); return; } } } /* * Check if a breakpoint has triggered */ static int mac_check_break (macplus_t *sim) { unsigned long pc; pc = e68_get_pc (sim->cpu) & 0x00ffffff; if (bps_check (&sim->bps, 0, pc, stdout)) { return (1); } if (sim->brk) { return (1); } return (0); } /* * Execute one instruction */ static int mac_exec (macplus_t *sim) { unsigned long old; old = e68_get_opcnt (sim->cpu); while (e68_get_opcnt (sim->cpu) == old) { mac_clock (sim, 0); if (mac_check_break (sim)) { return (1); } } return (0); } /* * Execute until a specific PC is reached */ static int mac_exec_to (macplus_t *sim, unsigned long addr) { while (e68_get_pc (sim->cpu) != addr) { mac_clock (sim, 0); if (mac_check_break (sim)) { return (1); } } return (0); } /* * Run the simulation */ void mac_run (macplus_t *sim) { pce_start (&sim->brk); mac_clock_discontinuity (sim); while (1) { mac_clock (par_sim, 0); mac_clock (par_sim, 0); if (sim->brk) { break; } while (sim->pause) { pce_usleep (50UL * 1000UL); trm_check (sim->trm); } } pce_stop(); } #if 0 static void mac_log_opcode (void *ext, unsigned long ir) { macplus_t *sim = ext; } #endif static void mac_log_undef (void *ext, unsigned long ir) { unsigned long pc; macplus_t *sim = ext; pc = e68_get_last_pc (sim->cpu, 0); pce_log (MSG_DEB, "%08lX: undefined operation: %04lX [%04X %04X %04X %04X %04X]\n", pc, ir, (unsigned) e68_get_mem16 (sim->cpu, pc), (unsigned) e68_get_mem16 (sim->cpu, pc + 2), (unsigned) e68_get_mem16 (sim->cpu, pc + 4), (unsigned) e68_get_mem16 (sim->cpu, pc + 6), (unsigned) e68_get_mem16 (sim->cpu, pc + 8) ); /* mac_set_msg (sim, "emu.stop", NULL); */ } static void mac_log_exception (void *ext, unsigned tn) { unsigned iw; macplus_t *sim = ext; iw = e68_get_mem16 (sim->cpu, e68_get_last_pc (sim->cpu, 0)); switch (tn) { case 0x00: mac_reset (sim); return; case 0x0a: mac_sony_patch (&sim->sony); return; case 0x19: case 0x1a: return; case 0x20: /* trap */ return; case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2e: return; } pce_log (MSG_DEB, "%08lX: exception %02X (%s) IW=%04X\n", (unsigned long) e68_get_last_pc (sim->cpu, 0), tn, e68_get_exception_name (sim->cpu), iw ); } void mac_log_mem (void *ext, unsigned long addr, unsigned type) { #if 0 macplus_t *sim = ext; addr &= 0x00ffffff; #endif } /* * c - clock */ static void mac_cmd_c (cmd_t *cmd, macplus_t *sim) { unsigned long cnt; cnt = 1; cmd_match_uint32 (cmd, &cnt); if (!cmd_match_end (cmd)) { return; } while (cnt > 0) { mac_clock (sim, 1); cnt -= 1; } mac_prt_state_cpu (sim->cpu); } /* * gb - run with breakpoints */ static void mac_cmd_g_b (cmd_t *cmd, macplus_t *sim) { unsigned long addr; breakpoint_t *bp; while (cmd_match_uint32 (cmd, &addr)) { bp = bp_addr_new (addr); bps_bp_add (&sim->bps, bp); } if (!cmd_match_end (cmd)) { return; } pce_start (&sim->brk); mac_clock_discontinuity (sim); while (1) { if (mac_exec (sim)) { break; } } pce_stop(); } /* * ge - run until an exception is raised */ static void mac_cmd_g_e (cmd_t *cmd, macplus_t *sim) { unsigned cnt; unsigned short tn; if (!cmd_match_uint16 (cmd, &tn)) { tn = 0xffff; } if (!cmd_match_end (cmd)) { return; } cnt = e68_get_exception_cnt (sim->cpu); pce_start (&sim->brk); mac_clock_discontinuity (sim); while (1) { mac_exec (sim); if (mac_check_break (sim)) { break; } if (e68_get_exception_cnt (sim->cpu) == cnt) { continue; } if (tn == 0xffff) { pce_printf ("exception %02X (%s)\n", e68_get_exception (sim->cpu), e68_get_exception_name (sim->cpu) ); break; } else { if (e68_get_exception (sim->cpu) == tn) { pce_printf ("exception %02X (%s)\n", e68_get_exception (sim->cpu), e68_get_exception_name (sim->cpu) ); break; } } } pce_stop(); } /* * g - run */ static void mac_cmd_g (cmd_t *cmd, macplus_t *sim) { if (cmd_match (cmd, "b")) { mac_cmd_g_b (cmd, sim); return; } else if (cmd_match (cmd, "e")) { mac_cmd_g_e (cmd, sim); return; } if (!cmd_match_end (cmd)) { return; } mac_run (sim); } /* * halt - halt the cpu */ static void mac_cmd_halt (cmd_t *cmd, macplus_t *sim) { unsigned short val; if (cmd_match_uint16 (cmd, &val) == 0) { val = 2; } if (!cmd_match_end (cmd)) { return; } e68_set_halt (sim->cpu, val); mac_prt_state_cpu (sim->cpu); } static void mac_cmd_hm (cmd_t *cmd) { pce_puts ( "emu.exit\n" "emu.pause \"0\" | \"1\"\n" "emu.pause.toggle\n" "emu.realtime \"0\" | \"1\"\n" "emu.realtime.toggle\n" "emu.reset\n" "emu.stop\n" "\n" "emu.cpu.model \"68000\" | \"68010\" | \"68020\"\n" "emu.cpu.speed \n" "emu.cpu.speed.step \n" "\n" "emu.mac.insert \n" "\n" "emu.ser1.driver \n" "emu.ser1.file \n" "emu.ser1.multi \n" "emu.ser2.driver \n" "emu.ser2.file \n" "emu.ser2.multi \n" "\n" "emu.term.fullscreen \"0\" | \"1\"\n" "emu.term.fullscreen.toggle\n" "emu.term.grab\n" "emu.term.release\n" "emu.term.screenshot []\n" "emu.term.title \n" "\n" "emu.video.brightness <val>\n" "\n" ); msg_dsk_print_help(); } /* * p - step */ static void mac_cmd_p (cmd_t *cmd, macplus_t *sim) { unsigned ecnt; unsigned long cnt; e68_dasm_t da; cnt = 1; while (cmd_match (cmd, "p")) { cnt += 1; } cmd_match_uint32 (cmd, &cnt); if (!cmd_match_end (cmd)) { return; } ecnt = e68_get_exception_cnt (sim->cpu); pce_start (&sim->brk); mac_clock_discontinuity (sim); while (cnt > 0) { e68_dasm_mem (sim->cpu, &da, e68_get_pc (sim->cpu)); if (da.flags & E68_DFLAG_CALL) { if (mac_exec_to (sim, e68_get_pc (sim->cpu) + 2 * da.irn)) { break; } } else { if (mac_exec (sim)) { break; } if (e68_get_exception_cnt (sim->cpu) != ecnt) { if (mac_exec_to (sim, sim->cpu->except_addr)) { break; } } } cnt -= 1; } pce_stop(); mac_prt_state_cpu (sim->cpu); } /* * reset - reset the simulation */ static void mac_cmd_reset (cmd_t *cmd, macplus_t *sim) { if (!cmd_match_end (cmd)) { return; } mac_reset (sim); mac_prt_state_cpu (sim->cpu); } /* * rte - execute until rte */ static void mac_cmd_rte (cmd_t *cmd, macplus_t *sim) { e68_dasm_t dis; if (!cmd_match_end (cmd)) { return; } pce_start (&sim->brk); mac_clock_discontinuity (sim); while (1) { mac_exec (sim); if (mac_check_break (sim)) { break; } e68_dasm_mem (sim->cpu, &dis, e68_get_pc (sim->cpu)); if (dis.flags & E68_DFLAG_RTE) { mac_prt_state_cpu (sim->cpu); break; } } pce_stop(); } /* * r - display or set register contents */ static void mac_cmd_r (cmd_t *cmd, macplus_t *sim) { unsigned long val; char sym[256]; if (cmd_match_eol (cmd)) { mac_prt_state_cpu (sim->cpu); return; } if (!cmd_match_ident (cmd, sym, 256)) { cmd_error (cmd, "missing register\n"); return; } if (e68_get_reg (sim->cpu, sym, &val)) { pce_printf ("bad register (%s)\n", sym); return; } if (cmd_match_eol (cmd)) { pce_printf ("%08lX\n", val); return; } if (!cmd_match_uint32 (cmd, &val)) { cmd_error (cmd, "missing value\n"); return; } if (!cmd_match_end (cmd)) { return; } e68_set_reg (sim->cpu, sym, val); mac_prt_state_cpu (sim->cpu); } /* * s - print state */ static void mac_cmd_s (cmd_t *cmd, macplus_t *sim) { if (cmd_match_eol (cmd)) { mac_prt_state_cpu (sim->cpu); return; } mac_prt_state (sim, cmd_get_str (cmd)); } /* * t - execute one instruction */ static void mac_cmd_t (cmd_t *cmd, macplus_t *sim) { unsigned long i, n; n = 1; while (cmd_match (cmd, "t")) { n += 1; } cmd_match_uint32 (cmd, &n); if (!cmd_match_end (cmd)) { return; } pce_start (&sim->brk); mac_clock_discontinuity (sim); for (i = 0; i < n; i++) { mac_exec (sim); } pce_stop(); mac_prt_state_cpu (sim->cpu); } /* * u- - disassemble to address */ static void mac_cmd_u_to (cmd_t *cmd, macplus_t *sim, unsigned long addr) { unsigned long cnt; unsigned ins_i, ins_j, ins_n; unsigned sync; unsigned long pc; unsigned long insn[256]; e68_dasm_t op; char str[256]; cnt = 16; if (cmd_match_uint32 (cmd, &addr)) { cmd_match_uint32 (cmd, &cnt); } if (!cmd_match_end (cmd)) { return; } if (cnt > 256) { cnt = 256; } ins_i = 0; ins_j = 0; ins_n = 0; sync = 5; pc = (addr - 12 * cnt) & ~1UL; while (pc <= addr) { if (sync == 0) { insn[ins_j] = pc; ins_j = (ins_j + 1) % 256; if (ins_j == ins_i) { ins_i = (ins_i + 1) % 256; } else { ins_n += 1; } } else { sync -= 1; } e68_dasm_mem (sim->cpu, &op, pc); pc += 2 * op.irn; } if (ins_n > cnt) { ins_i = (ins_i + (ins_n - cnt)) % 256; } while (ins_i != ins_j) { pc = insn[ins_i]; e68_dasm_mem (sim->cpu, &op, pc); mac_dasm_str (str, &op); pce_printf ("%08lX %s\n", pc, str); ins_i = (ins_i + 1) % 256; } } /* * u gas - disassemble for gas */ static void mac_cmd_u_gas (cmd_t *cmd, macplus_t *sim) { unsigned i; unsigned long addr1, addr2; const char *ins; e68_dasm_t op; addr1 = 0; addr2 = 0; if (cmd_match_uint32 (cmd, &addr1)) { addr2 = addr1; cmd_match_uint32 (cmd, &addr2); } if (!cmd_match_end (cmd)) { return; } pce_printf ("\t.text\n"); while (addr1 < addr2) { e68_dasm_mem (sim->cpu, &op, addr1); pce_printf ("\tdc.w\t0x%04x", (unsigned) op.ir[0]); for (i = 1; i < op.irn; i++) { pce_printf (", 0x%04x", (unsigned) op.ir[i]); } for (i = op.irn; i < 4; i++) { pce_printf ("\t"); } pce_printf ("\t| %06lX ", op.pc); ins = mac_get_trap_name (op.ir[0]); if (ins == NULL) { ins = op.op; } pce_printf ((op.argn > 0) ? "%-8s" : "%s", ins); if (op.argn >= 1) { pce_printf ("%s", op.arg1); } if (op.argn >= 2) { pce_printf (", %s", op.arg2); } if (op.argn >= 3) { pce_printf (", %s", op.arg3); } pce_printf ("\n"); if (op.flags & E68_DFLAG_RTS) { pce_printf ("\n"); } addr1 += 2 * op.irn; } } /* * u - disassemble */ static void mac_cmd_u (cmd_t *cmd, macplus_t *sim) { unsigned i; unsigned long addr, cnt; static unsigned int first = 1; static unsigned long saddr = 0; e68_dasm_t op; char str[256]; if (cmd_match (cmd, "gas")) { mac_cmd_u_gas (cmd, sim); return; } if (first) { first = 0; saddr = e68_get_pc (sim->cpu); } addr = saddr; cnt = 16; if (cmd_match (cmd, "-")) { mac_cmd_u_to (cmd, sim, addr); return; } if (cmd_match_uint32 (cmd, &addr)) { cmd_match_uint32 (cmd, &cnt); } if (!cmd_match_end (cmd)) { return; } for (i = 0; i < cnt; i++) { e68_dasm_mem (sim->cpu, &op, addr); mac_dasm_str (str, &op); pce_printf ("%08lX %s\n", addr, str); addr += 2 * op.irn; } saddr = addr; } int mac_cmd (macplus_t *sim, cmd_t *cmd) { if (sim->trm != NULL) { trm_check (sim->trm); } if (cmd_match (cmd, "b")) { cmd_do_b (cmd, &sim->bps); } else if (cmd_match (cmd, "c")) { mac_cmd_c (cmd, sim); } else if (cmd_match (cmd, "g")) { mac_cmd_g (cmd, sim); } else if (cmd_match (cmd, "halt")) { mac_cmd_halt (cmd, sim); } else if (cmd_match (cmd, "hm")) { mac_cmd_hm (cmd); } else if (cmd_match (cmd, "p")) { mac_cmd_p (cmd, sim); } else if (cmd_match (cmd, "reset")) { mac_cmd_reset (cmd, sim); } else if (cmd_match (cmd, "rte")) { mac_cmd_rte (cmd, sim); } else if (cmd_match (cmd, "r")) { mac_cmd_r (cmd, sim); } else if (cmd_match (cmd, "s")) { mac_cmd_s (cmd, sim); } else if (cmd_match (cmd, "t")) { mac_cmd_t (cmd, sim); } else if (cmd_match (cmd, "u")) { mac_cmd_u (cmd, sim); } else { return (1); } if (sim->trm != NULL) { trm_set_msg_trm (sim->trm, "term.release", "1"); } return (0); } void mac_cmd_init (macplus_t *sim, monitor_t *mon) { mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0])); mon_cmd_add_bp (mon); sim->cpu->log_ext = sim; sim->cpu->log_opcode = NULL; sim->cpu->log_undef = mac_log_undef; sim->cpu->log_exception = mac_log_exception; sim->cpu->log_mem = mac_log_mem; }