| 1 | MUSASHI\r |
| 2 | =======\r |
| 3 | \r |
| 4 | Version 3.3\r |
| 5 | \r |
| 6 | A portable Motorola M680x0 processor emulation engine.\r |
| 7 | Copyright 1998-2001 Karl Stenerud. All rights reserved.\r |
| 8 | \r |
| 9 | \r |
| 10 | \r |
| 11 | INTRODUCTION:\r |
| 12 | ------------\r |
| 13 | \r |
| 14 | Musashi is a Motorola 68000, 68010, 68EC020, and 68020 emulator written in C.\r |
| 15 | This emulator was written with two goals in mind: portability and speed.\r |
| 16 | \r |
| 17 | The emulator is written to ANSI C specifications with the exception that I use\r |
| 18 | inline functions. This is not compliant to the ANSI spec, but will be\r |
| 19 | compliant to the ANSI C9X spec.\r |
| 20 | \r |
| 21 | It has been successfully running in the MAME project (www.mame.net) for over 2\r |
| 22 | years and so has had time to mature.\r |
| 23 | \r |
| 24 | \r |
| 25 | \r |
| 26 | LICENSE AND COPYRIGHT:\r |
| 27 | ---------------------\r |
| 28 | \r |
| 29 | The Musashi M680x0 emulator is copyright 1998-2001 Karl Stenerud.\r |
| 30 | \r |
| 31 | The source code included in this archive is provided AS-IS, free for any\r |
| 32 | non-commercial purpose.\r |
| 33 | \r |
| 34 | If you build a program using this core, please give credit to the author.\r |
| 35 | \r |
| 36 | If you wish to use this core in a commercial environment, please contact\r |
| 37 | the author to discuss commercial licensing.\r |
| 38 | \r |
| 39 | \r |
| 40 | \r |
| 41 | AVAILABILITY:\r |
| 42 | ------------\r |
| 43 | The latest version of this code can be obtained at:\r |
| 44 | http://kstenerud.cjb.net\r |
| 45 | \r |
| 46 | \r |
| 47 | \r |
| 48 | CONTACTING THE AUTHOR:\r |
| 49 | ---------------------\r |
| 50 | I can be reached at kstenerud@mame.net\r |
| 51 | \r |
| 52 | \r |
| 53 | \r |
| 54 | BASIC CONFIGURATION:\r |
| 55 | -------------------\r |
| 56 | The basic configuration will give you a standard 68000 that has sufficient\r |
| 57 | functionality to work in a primitive environment.\r |
| 58 | \r |
| 59 | This setup assumes that you only have 1 device interrupting it, that the\r |
| 60 | device will always request an autovectored interrupt, and it will always clear\r |
| 61 | the interrupt before the interrupt service routine finishes (but could\r |
| 62 | possibly re-assert the interrupt).\r |
| 63 | You will have only one address space, no tracing, and no instruction prefetch.\r |
| 64 | \r |
| 65 | To implement the basic configuration:\r |
| 66 | \r |
| 67 | - Open m68kconf.h and verify that the settings for INLINE and DECL_SPEC will\r |
| 68 | work with your compiler. (They are set for gcc)\r |
| 69 | \r |
| 70 | - In your host program, implement the following functions:\r |
| 71 | unsigned int m68k_read_memory_8(unsigned int address);\r |
| 72 | unsigned int m68k_read_memory_16(unsigned int address);\r |
| 73 | unsigned int m68k_read_memory_32(unsigned int address);\r |
| 74 | void m68k_write_memory_8(unsigned int address, unsigned int value);\r |
| 75 | void m68k_write_memory_16(unsigned int address, unsigned int value);\r |
| 76 | void m68k_write_memory_32(unsigned int address, unsigned int value);\r |
| 77 | \r |
| 78 | - In your host program, be sure to call m68k_pulse_reset() once before calling\r |
| 79 | any of the other functions as this initializes the core.\r |
| 80 | \r |
| 81 | - Use m68k_execute() to execute instructions and m68k_set_irq() to cause an\r |
| 82 | interrupt.\r |
| 83 | \r |
| 84 | \r |
| 85 | \r |
| 86 | ADDING PROPER INTERRUPT HANDLING:\r |
| 87 | --------------------------------\r |
| 88 | The interrupt handling in the basic configuration doesn't emulate the\r |
| 89 | interrupt acknowledge phase of the CPU and automatically clears an interrupt\r |
| 90 | request during interrupt processing.\r |
| 91 | While this works for most systems, you may need more accurate interrupt\r |
| 92 | handling.\r |
| 93 | \r |
| 94 | To add proper interrupt handling:\r |
| 95 | \r |
| 96 | - In m68kconf.h, set M68K_EMULATE_INT_ACK to OPT_SPECIFY_HANDLER\r |
| 97 | \r |
| 98 | - In m68kconf.h, set M68K_INT_ACK_CALLBACK(A) to your interrupt acknowledge\r |
| 99 | routine\r |
| 100 | \r |
| 101 | - Your interrupt acknowledge routine must return an interrupt vector,\r |
| 102 | M68K_INT_ACK_AUTOVECTOR, or M68K_INT_ACK_SPURIOUS. most m68k\r |
| 103 | implementations just use autovectored interrupts.\r |
| 104 | \r |
| 105 | - When the interrupting device is satisfied, you must call m68k_set_irq(0) to\r |
| 106 | remove the interrupt request.\r |
| 107 | \r |
| 108 | \r |
| 109 | \r |
| 110 | MULTIPLE INTERRUPTS:\r |
| 111 | -------------------\r |
| 112 | The above system will work if you have only one device interrupting the CPU,\r |
| 113 | but if you have more than one device, you must do a bit more.\r |
| 114 | \r |
| 115 | To add multiple interrupts:\r |
| 116 | \r |
| 117 | - You must make an interrupt arbitration device that will take the highest\r |
| 118 | priority interrupt and encode it onto the IRQ pins on the CPU.\r |
| 119 | \r |
| 120 | - The interrupt arbitration device should use m68k_set_irq() to set the\r |
| 121 | highest pending interrupt, or 0 for no interrupts pending.\r |
| 122 | \r |
| 123 | \r |
| 124 | \r |
| 125 | SEPARATE IMMEDIATE AND PC-RELATIVE READS:\r |
| 126 | ----------------------------------------\r |
| 127 | You can write faster memory access functions if you know whether you are\r |
| 128 | fetching from ROM or RAM. Immediate reads are always from the program space\r |
| 129 | (Always in ROM unless it is running self-modifying code).\r |
| 130 | This will also separate the pc-relative reads, since some systems treat\r |
| 131 | PROGRAM mode reads and DATA mode reads differently (for program encryption,\r |
| 132 | for instance). See the section below (ADDRESS SPACE) for an explanation of\r |
| 133 | PROGRAM and DATA mode.\r |
| 134 | \r |
| 135 | To enable separate reads:\r |
| 136 | \r |
| 137 | - In m68kconf.h, turn on M68K_SEPARATE_READS.\r |
| 138 | \r |
| 139 | - In your host program, implement the following functions:\r |
| 140 | unsigned int m68k_read_immediate_16(unsigned int address);\r |
| 141 | unsigned int m68k_read_immediate_32(unsigned int address);\r |
| 142 | \r |
| 143 | unsigned int m68k_read_pcrelative_8(unsigned int address);\r |
| 144 | unsigned int m68k_read_pcrelative_16(unsigned int address);\r |
| 145 | unsigned int m68k_read_pcrelative_32(unsigned int address);\r |
| 146 | \r |
| 147 | - If you need to know the current PC (for banking and such), set\r |
| 148 | M68K_MONITOR_PC to OPT_SPECIFY_HANDLER, and set M68K_SET_PC_CALLBACK(A) to\r |
| 149 | your routine.\r |
| 150 | \r |
| 151 | \r |
| 152 | \r |
| 153 | ADDRESS SPACES:\r |
| 154 | --------------\r |
| 155 | Most systems will only implement one address space, placing ROM at the lower\r |
| 156 | addresses and RAM at the higher. However, there is the possibility that a\r |
| 157 | system will implement ROM and RAM in the same address range, but in different\r |
| 158 | address spaces, or will have different mamory types that require different\r |
| 159 | handling for the program and the data.\r |
| 160 | \r |
| 161 | The 68k accomodates this by allowing different program spaces, the most\r |
| 162 | important to us being PROGRAM and DATA space. Here is a breakdown of\r |
| 163 | how information is fetched:\r |
| 164 | \r |
| 165 | - All immediate reads are fetched from PROGRAM space.\r |
| 166 | \r |
| 167 | - All PC-relative reads are fetched from PROGRAM space.\r |
| 168 | \r |
| 169 | - The initial stack pointer and program counter are fetched from PROGRAM space.\r |
| 170 | \r |
| 171 | - All other reads (except for those from the moves instruction for 68020)\r |
| 172 | are fetched from DATA space.\r |
| 173 | \r |
| 174 | The m68k deals with this by encoding the requested address space on the\r |
| 175 | function code pins:\r |
| 176 | \r |
| 177 | FC\r |
| 178 | Address Space 210\r |
| 179 | ------------------ ---\r |
| 180 | USER DATA 001\r |
| 181 | USER PROGRAM 010\r |
| 182 | SUPERVISOR DATA 101\r |
| 183 | SUPERVISOR PROGRAM 110\r |
| 184 | CPU SPACE 111 <-- not emulated in this core since we emulate\r |
| 185 | interrupt acknowledge in another way.\r |
| 186 | \r |
| 187 | Problems arise here if you need to emulate this distinction (if, for example,\r |
| 188 | your ROM and RAM are at the same address range, with RAM and ROM enable\r |
| 189 | wired to the function code pins).\r |
| 190 | \r |
| 191 | There are 2 ways to deal with this situation using Musashi:\r |
| 192 | \r |
| 193 | 1. If you only need the distinction between PROGRAM and DATA (the most common),\r |
| 194 | you can just separate the reads (see the preceeding section). This is the\r |
| 195 | faster solution.\r |
| 196 | \r |
| 197 | 2. You can emulate the function code pins entirely.\r |
| 198 | \r |
| 199 | To emulate the function code pins:\r |
| 200 | \r |
| 201 | - In m68kconf.h, set M68K_EMULATE_FC to OPT_SPECIFY_HANDLER and set\r |
| 202 | M68K_SET_FC_CALLBACK(A) to your function code handler function.\r |
| 203 | \r |
| 204 | - Your function code handler should select the proper address space for\r |
| 205 | subsequent calls to m68k_read_xx (and m68k_write_xx for 68010+).\r |
| 206 | \r |
| 207 | Note: immediate reads are always done from program space, so technically you\r |
| 208 | don't need to implement the separate immediate reads, although you could\r |
| 209 | gain more speed improvements leaving them in and doing some clever\r |
| 210 | programming.\r |
| 211 | \r |
| 212 | \r |
| 213 | \r |
| 214 | USING DIFFERENT CPU TYPES:\r |
| 215 | -------------------------\r |
| 216 | The default is to enable only the 68000 cpu type. To change this, change the\r |
| 217 | settings for M68K_EMULATE_010 etc in m68kconf.h.\r |
| 218 | \r |
| 219 | To set the CPU type you want to use:\r |
| 220 | \r |
| 221 | - Make sure it is enabled in m68kconf.h. Current switches are:\r |
| 222 | M68K_EMULATE_010\r |
| 223 | M68K_EMULATE_EC020\r |
| 224 | M68K_EMULATE_020\r |
| 225 | \r |
| 226 | - In your host program, call m68k_set_cpu_type() and then call\r |
| 227 | m68k_pulse_reset(). Valid CPU types are:\r |
| 228 | M68K_CPU_TYPE_68000,\r |
| 229 | M68K_CPU_TYPE_68010,\r |
| 230 | M68K_CPU_TYPE_68EC020,\r |
| 231 | M68K_CPU_TYPE_68020\r |
| 232 | \r |
| 233 | \r |
| 234 | \r |
| 235 | CLOCK FREQUENCY:\r |
| 236 | ---------------\r |
| 237 | In order to emulate the correct clock frequency, you will have to calculate\r |
| 238 | how long it takes the emulation to execute a certain number of "cycles" and\r |
| 239 | vary your calls to m68k_execute() accordingly.\r |
| 240 | As well, it is a good idea to take away the CPU's timeslice when it writes to\r |
| 241 | a memory-mapped port in order to give the device it wrote to a chance to\r |
| 242 | react.\r |
| 243 | \r |
| 244 | You can use the functions m68k_cycles_run(), m68k_cycles_remaining(),\r |
| 245 | m68k_modify_timeslice(), and m68k_end_timeslice() to do this.\r |
| 246 | Try to use large cycle values in your calls to m68k_execute() since it will\r |
| 247 | increase throughput. You can always take away the timeslice later.\r |
| 248 | \r |
| 249 | \r |
| 250 | \r |
| 251 | MORE CORRECT EMULATION:\r |
| 252 | ----------------------\r |
| 253 | You may need to enable these in order to properly emulate some of the more\r |
| 254 | obscure functions of the m68k:\r |
| 255 | \r |
| 256 | - M68K_EMULATE_BKPT_ACK causes the CPU to call a breakpoint handler on a BKPT\r |
| 257 | instruction\r |
| 258 | \r |
| 259 | - M68K_EMULATE_TRACE causes the CPU to generate trace exceptions when the\r |
| 260 | trace bits are set\r |
| 261 | \r |
| 262 | - M68K_EMULATE_RESET causes the CPU to call a reset handler on a RESET\r |
| 263 | instruction.\r |
| 264 | \r |
| 265 | - M68K_EMULATE_PREFETCH emulates the 4-word instruction prefetch that is part\r |
| 266 | of the 68000/68010 (needed for Amiga emulation).\r |
| 267 | \r |
| 268 | - call m68k_pulse_halt() to emulate the HALT pin.\r |
| 269 | \r |
| 270 | \r |
| 271 | \r |
| 272 | CONVENIENCE FUNCTIONS:\r |
| 273 | ---------------------\r |
| 274 | These are in here for programmer convenience:\r |
| 275 | \r |
| 276 | - M68K_INSTRUCTION_HOOK lets you call a handler before each instruction.\r |
| 277 | \r |
| 278 | - M68K_LOG_ENABLE and M68K_LOG_1010_1111 lets you log illegal and A/F-line\r |
| 279 | instructions.\r |
| 280 | \r |
| 281 | \r |
| 282 | \r |
| 283 | MULTIPLE CPU EMULATION:\r |
| 284 | ----------------------\r |
| 285 | The default is to use only one CPU. To use more than one CPU in this core,\r |
| 286 | there are some things to keep in mind:\r |
| 287 | \r |
| 288 | - To have different cpus call different functions, use OPT_ON instead of\r |
| 289 | OPT_SPECIFY_HANDLER, and use the m68k_set_xxx_callback() functions to set\r |
| 290 | your callback handlers on a per-cpu basis.\r |
| 291 | \r |
| 292 | - Be sure to call set_cpu_type() for each CPU you use.\r |
| 293 | \r |
| 294 | - Use m68k_set_context() and m68k_get_context() to switch to another CPU.\r |
| 295 | \r |
| 296 | \r |
| 297 | \r |
| 298 | LOAD AND SAVE CPU CONTEXTS FROM DISK:\r |
| 299 | ------------------------------------\r |
| 300 | You can use them68k_load_context() and m68k_save_context() functions to load\r |
| 301 | and save the CPU state to disk.\r |
| 302 | \r |
| 303 | \r |
| 304 | \r |
| 305 | GET/SET INFORMATION FROM THE CPU:\r |
| 306 | --------------------------------\r |
| 307 | You can use m68k_get_reg() and m68k_set_reg() to gain access to the internals\r |
| 308 | of the CPU.\r |
| 309 | \r |
| 310 | \r |
| 311 | \r |
| 312 | EXAMPLE:\r |
| 313 | -------\r |
| 314 | \r |
| 315 | I have included a file example.zip that contains a full example.\r |