cc68a136 |
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 |