src/musashi/readme.txt

Tue, 15 Nov 2011 10:12:37 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 15 Nov 2011 10:12:37 +0000
changeset 109
2f8afb9e5baa
parent 0
8bf1bf91a36d
permissions
-rw-r--r--

[musashi] Fix handling of bus errors

Patch-Author: Andrew Warkentin <andreww591!gmail>
Patch-MessageID: <4EC200CE.2020304@gmail.com>

I have fixed the first page fault test failure in FreeBee (the page fault test now hangs rather than errors out, because it is trying to read from the hard drive to test DMA page faults).

There were actually two bugs (the first bug was masking the second one).

First, the ancient version of Musashi that you used is unable to properly resume from bus errors that happen in the middle of certain instructions (some instructions are fetched in stages, with the PC being advanced to each part of the instruction, so basically what happens is the CPU core attempts to read the memory location referenced by the first operand, the bus error occurs, causing the PC to jump to the exception vector, but the faulting instruction is still in the middle of being fetched, so the PC is then advanced past the beginning of the exception handler). I fixed this by delaying the jump to the bus error vector until after the faulting instruction finishes.

The second bug is simpler - you had the UDS and LDS bits in BSR0 inverted (they are supposed to be active low).

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