home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / emul_op.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  15KB  |  509 lines

  1. /*
  2.  *  emul_op.cpp - 68k opcodes for ROM patches
  3.  *
  4.  *  Basilisk II (C) 1997-1999 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <string.h>
  22. #include <stdio.h>
  23.  
  24. #include "sysdeps.h"
  25. #include "cpu_emulation.h"
  26. #include "main.h"
  27. #include "macos_util.h"
  28. #include "rom_patches.h"
  29. #include "rsrc_patches.h"
  30. #include "xpram.h"
  31. #include "adb.h"
  32. #include "timer.h"
  33. #include "clip.h"
  34. #include "serial.h"
  35. #include "sony.h"
  36. #include "disk.h"
  37. #include "cdrom.h"
  38. #include "scsi.h"
  39. #include "video.h"
  40. #include "audio.h"
  41. #include "ether.h"
  42. #include "extfs.h"
  43. #include "emul_op.h"
  44.  
  45. #if ENABLE_MON
  46. #include "mon.h"
  47. #endif
  48.  
  49. #define DEBUG 0
  50. #include "debug.h"
  51.  
  52.  
  53. /*
  54.  *  Execute EMUL_OP opcode (called by 68k emulator or Illegal Instruction trap handler)
  55.  */
  56.  
  57. void EmulOp(uint16 opcode, M68kRegisters *r)
  58. {
  59.     D(bug("EmulOp %04x\n", opcode));
  60.     switch (opcode) {
  61.         case M68K_EMUL_BREAK: {                // Breakpoint
  62.             printf("*** Breakpoint\n");
  63.             printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
  64.                    "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
  65.                    "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
  66.                    "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
  67.                    "sr %04x\n",
  68.                    r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
  69.                    r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
  70.                    r->sr);
  71. #if ENABLE_MON
  72.             char *arg[2] = {"rmon", NULL};
  73.             mon(1, arg);
  74. #endif
  75.             QuitEmulator();
  76.             break;
  77.         }
  78.  
  79.         case M68K_EMUL_OP_SHUTDOWN:            // Quit emulator
  80.             QuitEmulator();
  81.             break;
  82.  
  83.         case M68K_EMUL_OP_RESET: {            // MacOS reset
  84.             D(bug("*** RESET ***\n"));
  85.             TimerReset();
  86.             EtherReset();
  87.  
  88.             // Create BootGlobs at top of memory
  89.             Mac_memset(RAMBaseMac + RAMSize - 4096, 0, 4096);
  90.             uint32 boot_globs = RAMBaseMac + RAMSize - 0x1c;
  91.             WriteMacInt32(boot_globs + 0x00, RAMBaseMac);    // First RAM bank
  92.             WriteMacInt32(boot_globs + 0x04, RAMSize);
  93.             WriteMacInt32(boot_globs + 0x08, 0xffffffff);    // End of bank table
  94.             WriteMacInt32(boot_globs + 0x0c, 0);
  95.  
  96.             // Setup registers for boot routine
  97.             r->d[0] = ReadMacInt32(ROMBaseMac + UniversalInfo + 0x18);    // AddrMapFlags
  98.             r->d[1] = ReadMacInt32(ROMBaseMac + UniversalInfo + 0x1c);    // UnivROMFlags
  99.             r->d[2] = ReadMacInt32(ROMBaseMac + UniversalInfo + 0x10);    // HWCfgFlags/IDs
  100.             if (FPUType)
  101.                 r->d[2] |= 0x10000000;                                    // Set FPU flag if FPU present
  102.             else
  103.                 r->d[2] &= 0xefffffff;                                    // Clear FPU flag if no FPU present
  104.             r->a[0] = ROMBaseMac + UniversalInfo + ReadMacInt32(ROMBaseMac + UniversalInfo);// AddrMap
  105.             r->a[1] = ROMBaseMac + UniversalInfo;                        // UniversalInfo
  106.             r->a[6] = boot_globs;                                        // BootGlobs
  107.             r->a[7] = RAMBaseMac + 0x10000;                                // Boot stack
  108.             break;
  109.         }
  110.  
  111.         case M68K_EMUL_OP_CLKNOMEM: {        // Clock/PRAM operations
  112.             bool is_read = r->d[1] & 0x80;
  113.             if ((r->d[1] & 0x78) == 0x38) {
  114.                 // XPRAM
  115.                 uint8 reg = (r->d[1] << 5) & 0xe0 | (r->d[1] >> 10) & 0x1f;
  116.                 if (is_read) {
  117.                     r->d[2] = XPRAM[reg];
  118.                     bool localtalk = !(XPRAM[0xe0] || XPRAM[0xe1]);    // LocalTalk enabled?
  119.                     switch (reg) {
  120.                         case 0x08:
  121.                             if (ROMVersion != ROM_VERSION_32)
  122.                                 r->d[2] &= 0xf8;
  123.                             break;
  124.                         case 0x8a:
  125.                             r->d[2] |= 0x05;    // 32bit mode is always enabled
  126.                             break;
  127.                         case 0xe0:                // Disable LocalTalk (use EtherTalk instead)
  128.                             if (localtalk)
  129.                                 r->d[2] = 0x00;
  130.                             break;
  131.                         case 0xe1:
  132.                             if (localtalk)
  133.                                 r->d[2] = 0xf1;
  134.                             break;
  135.                         case 0xe2:
  136.                             if (localtalk)
  137.                                 r->d[2] = 0x00;
  138.                             break;
  139.                         case 0xe3:
  140.                             if (localtalk)
  141.                                 r->d[2] = 0x0a;
  142.                             break;
  143.                     }
  144.                     D(bug("Read XPRAM %02x->%02lx\n", reg, r->d[2]));
  145.                 } else {
  146.                     D(bug("Write XPRAM %02x<-%02lx\n", reg, r->d[2] & 0xff));
  147.                     if (reg == 0x8a && !TwentyFourBitAddressing)
  148.                         r->d[2] |= 0x05;    // 32bit mode is always enabled if possible
  149.                     XPRAM[reg] = r->d[2];
  150.                 }
  151.             } else {
  152.                 // PRAM, RTC and other clock registers
  153.                 uint8 reg = (r->d[1] >> 2) & 0x1f;
  154.                 if (reg >= 0x10 || (reg >= 0x08 && reg < 0x0c)) {
  155.                     if (is_read) {
  156.                         r->d[2] = XPRAM[reg];
  157.                         D(bug("Read XPRAM %02x->%02x\n", reg, XPRAM[reg]));
  158.                     } else {
  159.                         D(bug("Write PRAM %02x<-%02lx\n", reg, r->d[2]));
  160.                         XPRAM[reg] = r->d[2];
  161.                     }
  162.                 } else if (reg < 0x08 && is_read) {
  163.                     uint32 t = TimerDateTime();
  164.                     uint8 b = t;
  165.                     switch (reg & 3) {
  166.                         case 1: b = t >> 8; break;
  167.                         case 2: b = t >> 16; break;
  168.                         case 3: b = t >> 24; break;
  169.                     }
  170.                     r->d[2] = b;
  171.                 } else
  172.                     D(bug("RTC %s op %d, d1 %08lx d2 %08lx\n", is_read ? "read" : "write", reg, r->d[1], r->d[2]));
  173.             }
  174.             r->d[0] = 0;
  175.             r->d[1] = r->d[2];
  176.             break;
  177.         }
  178.  
  179.         case M68K_EMUL_OP_READ_XPRAM:        // Read from XPRAM (ROM10/11)
  180.             D(bug("Read XPRAM %02lx\n", r->d[1]));
  181.             r->d[1] = XPRAM[r->d[1] & 0xff];
  182.             break;
  183.  
  184.         case M68K_EMUL_OP_READ_XPRAM2:        // Read from XPRAM (ROM15)
  185.             D(bug("Read XPRAM %02lx\n", r->d[0]));
  186.             r->d[0] = XPRAM[r->d[0] & 0xff];
  187.             break;
  188.  
  189.         case M68K_EMUL_OP_PATCH_BOOT_GLOBS:    // Patch BootGlobs at startup
  190.             D(bug("Patch BootGlobs\n"));
  191.             WriteMacInt32(r->a[4] - 20, RAMBaseMac + RAMSize);            // MemTop
  192.             WriteMacInt8(r->a[4] - 26, 0);                                // No MMU
  193.             WriteMacInt8(r->a[4] - 25, ReadMacInt8(r->a[4] - 25) | 1);    // No MMU
  194.             r->a[6] = RAMBaseMac + RAMSize;
  195.             break;
  196.  
  197.         case M68K_EMUL_OP_FIX_BOOTSTACK:    // Set boot stack to 3/4 of RAM (7.5)
  198.             D(bug("Fix boot stack\n"));
  199.             r->a[1] = RAMBaseMac + RAMSize * 3 / 4;
  200.             break;
  201.  
  202.         case M68K_EMUL_OP_FIX_MEMSIZE: {    // Set correct logical and physical memory size
  203.             D(bug("Fix MemSize\n"));
  204.             uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4);    // Difference between logical and physical size
  205.             WriteMacInt32(0x1ef8, RAMSize);            // Physical RAM size
  206.             WriteMacInt32(0x1ef4, RAMSize - diff);    // Logical RAM size
  207.             break;
  208.         }
  209.  
  210.         case M68K_EMUL_OP_ADBOP:            // ADBOp() replacement
  211.             ADBOp(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0])));
  212.             break;
  213.  
  214.         case M68K_EMUL_OP_INSTIME:            // InsTime() replacement
  215.             r->d[0] = InsTime(r->a[0], r->d[1]);
  216.             break;
  217.  
  218.         case M68K_EMUL_OP_RMVTIME:            // RmvTime() replacement
  219.             r->d[0] = RmvTime(r->a[0]);
  220.             break;
  221.  
  222.         case M68K_EMUL_OP_PRIMETIME:        // PrimeTime() replacement
  223.             r->d[0] = PrimeTime(r->a[0], r->d[0]);
  224.             break;
  225.  
  226.         case M68K_EMUL_OP_MICROSECONDS:     // Microseconds() replacement
  227.             Microseconds(r->a[0], r->d[0]);
  228.             break;
  229.  
  230.         case M68K_EMUL_OP_INSTALL_DRIVERS: {// Patch to install our own drivers during startup
  231.             // Install drivers
  232.             D(bug("InstallDrivers\n"));
  233.             InstallDrivers(r->a[0]);
  234.  
  235.             // Install PutScrap() patch
  236.             M68kRegisters r;
  237.             r.d[0] = 0xa9fe;
  238.             r.a[0] = PutScrapPatch;
  239.             Execute68kTrap(0xa647, &r);        // SetToolTrap()
  240.  
  241.             // Setup fake ASC registers
  242.             if (ROMVersion == ROM_VERSION_32) {
  243.                 r.d[0] = 0x1000;
  244.                 Execute68kTrap(0xa71e, &r);        // NewPtrSysClear()
  245.                 uint32 asc_regs = r.a[0];
  246.                 D(bug("ASC registers at %08lx\n", asc_regs));
  247.                 WriteMacInt8(asc_regs + 0x800, 0x0f);    // Set ASC version number
  248.                 WriteMacInt32(0xcc0, asc_regs);            // Set ASCBase
  249.             }
  250.             break;
  251.         }
  252.  
  253.         case M68K_EMUL_OP_SERD:                // Install serial drivers
  254.             D(bug("InstallSERD\n"));
  255.             InstallSERD();
  256.             break;
  257.  
  258.         case M68K_EMUL_OP_SONY_OPEN:        // Floppy driver functions
  259.             r->d[0] = SonyOpen(r->a[0], r->a[1]);
  260.             break;
  261.  
  262.         case M68K_EMUL_OP_SONY_PRIME:
  263.             r->d[0] = SonyPrime(r->a[0], r->a[1]);
  264.             break;
  265.  
  266.         case M68K_EMUL_OP_SONY_CONTROL:
  267.             r->d[0] = SonyControl(r->a[0], r->a[1]);
  268.             break;
  269.  
  270.         case M68K_EMUL_OP_SONY_STATUS:
  271.             r->d[0] = SonyStatus(r->a[0], r->a[1]);
  272.             break;
  273.  
  274.         case M68K_EMUL_OP_DISK_OPEN:        // Disk driver functions
  275.             r->d[0] = DiskOpen(r->a[0], r->a[1]);
  276.             break;
  277.  
  278.         case M68K_EMUL_OP_DISK_PRIME:
  279.             r->d[0] = DiskPrime(r->a[0], r->a[1]);
  280.             break;
  281.  
  282.         case M68K_EMUL_OP_DISK_CONTROL:
  283.             r->d[0] = DiskControl(r->a[0], r->a[1]);
  284.             break;
  285.  
  286.         case M68K_EMUL_OP_DISK_STATUS:
  287.             r->d[0] = DiskStatus(r->a[0], r->a[1]);
  288.             break;
  289.  
  290.         case M68K_EMUL_OP_CDROM_OPEN:        // CD-ROM driver functions
  291.             r->d[0] = CDROMOpen(r->a[0], r->a[1]);
  292.             break;
  293.  
  294.         case M68K_EMUL_OP_CDROM_PRIME:
  295.             r->d[0] = CDROMPrime(r->a[0], r->a[1]);
  296.             break;
  297.  
  298.         case M68K_EMUL_OP_CDROM_CONTROL:
  299.             r->d[0] = CDROMControl(r->a[0], r->a[1]);
  300.             break;
  301.  
  302.         case M68K_EMUL_OP_CDROM_STATUS:
  303.             r->d[0] = CDROMStatus(r->a[0], r->a[1]);
  304.             break;
  305.  
  306.         case M68K_EMUL_OP_VIDEO_OPEN:        // Video driver functions
  307.             r->d[0] = VideoDriverOpen(r->a[0], r->a[1]);
  308.             break;
  309.  
  310.         case M68K_EMUL_OP_VIDEO_CONTROL:
  311.             r->d[0] = VideoDriverControl(r->a[0], r->a[1]);
  312.             break;
  313.  
  314.         case M68K_EMUL_OP_VIDEO_STATUS:
  315.             r->d[0] = VideoDriverStatus(r->a[0], r->a[1]);
  316.             break;
  317.  
  318.         case M68K_EMUL_OP_SERIAL_OPEN:        // Serial driver functions
  319.             r->d[0] = SerialOpen(r->a[0], r->a[1], r->d[0]);
  320.             break;
  321.  
  322.         case M68K_EMUL_OP_SERIAL_PRIME:
  323.             r->d[0] = SerialPrime(r->a[0], r->a[1], r->d[0]);
  324.             break;
  325.  
  326.         case M68K_EMUL_OP_SERIAL_CONTROL:
  327.             r->d[0] = SerialControl(r->a[0], r->a[1], r->d[0]);
  328.             break;
  329.  
  330.         case M68K_EMUL_OP_SERIAL_STATUS:
  331.             r->d[0] = SerialStatus(r->a[0], r->a[1], r->d[0]);
  332.             break;
  333.  
  334.         case M68K_EMUL_OP_SERIAL_CLOSE:
  335.             r->d[0] = SerialClose(r->a[0], r->a[1], r->d[0]);
  336.             break;
  337.  
  338.         case M68K_EMUL_OP_ETHER_OPEN:        // Ethernet driver functions
  339.             r->d[0] = EtherOpen(r->a[0], r->a[1]);
  340.             break;
  341.  
  342.         case M68K_EMUL_OP_ETHER_CONTROL:
  343.             r->d[0] = EtherControl(r->a[0], r->a[1]);
  344.             break;
  345.  
  346.         case M68K_EMUL_OP_ETHER_READ_PACKET:
  347.             EtherReadPacket((uint8 **)&r->a[0], r->a[3], r->d[3], r->d[1]);
  348.             break;
  349.  
  350.         case M68K_EMUL_OP_SCSI_DISPATCH: {    // SCSIDispatch() replacement
  351.             uint32 ret = ReadMacInt32(r->a[7]);        // Get return address
  352.             uint16 sel = ReadMacInt16(r->a[7] + 4);    // Get selector
  353.             r->a[7] += 6;
  354.             int stack = 0;
  355.             switch (sel) {
  356.                 case 0:        // SCSIReset
  357.                     WriteMacInt16(r->a[7], SCSIReset());
  358.                     stack = 0;
  359.                     break;
  360.                 case 1:        // SCSIGet
  361.                     WriteMacInt16(r->a[7], SCSIGet());
  362.                     stack = 0;
  363.                     break;
  364.                 case 2:        // SCSISelect
  365.                 case 11:    // SCSISelAtn
  366.                     WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt16(r->a[7]) & 0xff));
  367.                     stack = 2;
  368.                     break;
  369.                 case 3:        // SCSICmd
  370.                     WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2))));
  371.                     stack = 6;
  372.                     break;
  373.                 case 4:        // SCSIComplete
  374.                     WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8)));
  375.                     stack = 12;
  376.                     break;
  377.                 case 5:        // SCSIRead
  378.                 case 8:        // SCSIRBlind
  379.                     WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7])));
  380.                     stack = 4;
  381.                     break;
  382.                 case 6:        // SCSIWrite
  383.                 case 9:        // SCSIWBlind
  384.                     WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7])));
  385.                     stack = 4;
  386.                     break;
  387.                 case 10:    // SCSIStat
  388.                     WriteMacInt16(r->a[7], SCSIStat());
  389.                     stack = 0;
  390.                     break;
  391.                 case 12:    // SCSIMsgIn
  392.                     WriteMacInt16(r->a[7] + 4, 0);
  393.                     stack = 4;
  394.                     break;
  395.                 case 13:    // SCSIMsgOut
  396.                     WriteMacInt16(r->a[7] + 2, 0);
  397.                     stack = 2;
  398.                     break;
  399.                 case 14:    // SCSIMgrBusy
  400.                     WriteMacInt16(r->a[7], SCSIMgrBusy());
  401.                     stack = 0;
  402.                     break;
  403.                 default:
  404.                     printf("FATAL: SCSIDispatch(%d): illegal selector\n", sel);
  405.                     QuitEmulator();
  406.                     break;
  407.             }
  408.             r->a[0] = ret;            // "rtd" emulation, a0 = return address, a1 = new stack pointer
  409.             r->a[1] = r->a[7] + stack;
  410.             break;
  411.         }
  412.  
  413.         case M68K_EMUL_OP_IRQ:            // Level 1 interrupt
  414.             r->d[0] = 0;
  415.             if (InterruptFlags & INTFLAG_60HZ) {
  416.                 ClearInterruptFlag(INTFLAG_60HZ);
  417.                 if (HasMacStarted()) {
  418.  
  419.                     // Mac has started, execute all 60Hz interrupt functions
  420.                     ADBInterrupt();
  421.                     TimerInterrupt();
  422.                     VideoInterrupt();
  423.                     SonyInterrupt();
  424.                     DiskInterrupt();
  425.                     CDROMInterrupt();
  426.  
  427.                     // Call DoVBLTask(0)
  428.                     if (ROMVersion == ROM_VERSION_32) {
  429.                         M68kRegisters r2;
  430.                         r2.d[0] = 0;
  431.                         Execute68kTrap(0xa072, &r2);
  432.                     }
  433.  
  434.                     r->d[0] = 1;            // Flag: 68k interrupt routine executes VBLTasks etc.
  435.                 }
  436.             }
  437.             if (InterruptFlags & INTFLAG_SERIAL) {
  438.                 ClearInterruptFlag(INTFLAG_SERIAL);
  439.                 SerialInterrupt();
  440.             }
  441.             if (InterruptFlags & INTFLAG_ETHER) {
  442.                 ClearInterruptFlag(INTFLAG_ETHER);
  443.                 EtherInterrupt();
  444.             }
  445.             if (InterruptFlags & INTFLAG_AUDIO) {
  446.                 ClearInterruptFlag(INTFLAG_AUDIO);
  447.                 AudioInterrupt();
  448.             }
  449.             break;
  450.  
  451.         case M68K_EMUL_OP_PUT_SCRAP: {        // PutScrap() patch
  452.             void *scrap = Mac2HostAddr(ReadMacInt32(r->a[7] + 4));
  453.             uint32 type = ReadMacInt32(r->a[7] + 8);
  454.             int32 length = ReadMacInt32(r->a[7] + 12);
  455.             PutScrap(type, scrap, length);
  456.             break;
  457.         }
  458.  
  459.         case M68K_EMUL_OP_CHECKLOAD: {        // vCheckLoad() patch (resource loader)
  460.             uint32 type = r->d[1];
  461.             int16 id = ReadMacInt16(r->a[2]);
  462.             if (r->a[0] == 0)
  463.                 break;
  464.             uint32 adr = ReadMacInt32(r->a[0]);
  465.             if (adr == 0)
  466.                 break;
  467.             uint8 *p = Mac2HostAddr(adr);
  468.             uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
  469.             CheckLoad(type, id, p, size);
  470.             break;
  471.         }
  472.  
  473.         case M68K_EMUL_OP_AUDIO:            // Audio component dispatch function
  474.             r->d[0] = AudioDispatch(r->a[3], r->a[4]);
  475.             break;
  476.  
  477. #if SUPPORTS_EXTFS
  478.         case M68K_EMUL_OP_EXTFS_COMM:        // External file system routines
  479.             WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
  480.             break;
  481.  
  482.         case M68K_EMUL_OP_EXTFS_HFS:
  483.             WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4)));
  484.             break;
  485. #endif
  486.  
  487.         case M68K_EMUL_OP_BLOCK_MOVE:        // BlockMove() replacement
  488.             memmove(Mac2HostAddr(r->a[1]), Mac2HostAddr(r->a[0]), r->d[0]);
  489.             break;
  490.  
  491.         default:
  492.             printf("FATAL: EMUL_OP called with bogus opcode %08x\n", opcode);
  493.             printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
  494.                    "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
  495.                    "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
  496.                    "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
  497.                    "sr %04x\n",
  498.                    r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
  499.                    r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
  500.                    r->sr);
  501. #if ENABLE_MON
  502.             char *arg[2] = {"rmon", NULL};
  503.             mon(1, arg);
  504. #endif
  505.             QuitEmulator();
  506.             break;
  507.     }
  508. }
  509.