Mon, 06 Dec 2010 01:43:04 +0000
fix side-select bug in WDC FDC driver, was causing all reads to occur on side0... now the Loader boots!
Loader will boot, but immediately gives up on the floppy drive... Not sure why.
1 #ifndef M68K__HEADER
2 #define M68K__HEADER
4 /* ======================================================================== */
5 /* ========================= LICENSING & COPYRIGHT ======================== */
6 /* ======================================================================== */
7 /*
8 * MUSASHI
9 * Version 3.3
10 *
11 * A portable Motorola M680x0 processor emulation engine.
12 * Copyright 1998-2001 Karl Stenerud. All rights reserved.
13 *
14 * This code may be freely used for non-commercial purposes as long as this
15 * copyright notice remains unaltered in the source code and any binary files
16 * containing this code in compiled form.
17 *
18 * All other lisencing terms must be negotiated with the author
19 * (Karl Stenerud).
20 *
21 * The latest version of this code can be obtained at:
22 * http://kstenerud.cjb.net
23 */
27 /* ======================================================================== */
28 /* ============================ GENERAL DEFINES =========================== */
30 /* ======================================================================== */
32 /* There are 7 levels of interrupt to the 68K.
33 * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
34 */
35 #define M68K_IRQ_NONE 0
36 #define M68K_IRQ_1 1
37 #define M68K_IRQ_2 2
38 #define M68K_IRQ_3 3
39 #define M68K_IRQ_4 4
40 #define M68K_IRQ_5 5
41 #define M68K_IRQ_6 6
42 #define M68K_IRQ_7 7
45 /* Special interrupt acknowledge values.
46 * Use these as special returns from the interrupt acknowledge callback
47 * (specified later in this header).
48 */
50 /* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
51 * This happens in a real 68K if VPA or AVEC is asserted during an interrupt
52 * acknowledge cycle instead of DTACK.
53 */
54 #define M68K_INT_ACK_AUTOVECTOR 0xffffffff
56 /* Causes the spurious interrupt vector (0x18) to be taken
57 * This happens in a real 68K if BERR is asserted during the interrupt
58 * acknowledge cycle (i.e. no devices responded to the acknowledge).
59 */
60 #define M68K_INT_ACK_SPURIOUS 0xfffffffe
63 /* CPU types for use in m68k_set_cpu_type() */
64 enum
65 {
66 M68K_CPU_TYPE_INVALID,
67 M68K_CPU_TYPE_68000,
68 M68K_CPU_TYPE_68010,
69 M68K_CPU_TYPE_68EC020,
70 M68K_CPU_TYPE_68020,
71 M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
72 M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
73 };
75 /* Registers used by m68k_get_reg() and m68k_set_reg() */
76 typedef enum
77 {
78 /* Real registers */
79 M68K_REG_D0, /* Data registers */
80 M68K_REG_D1,
81 M68K_REG_D2,
82 M68K_REG_D3,
83 M68K_REG_D4,
84 M68K_REG_D5,
85 M68K_REG_D6,
86 M68K_REG_D7,
87 M68K_REG_A0, /* Address registers */
88 M68K_REG_A1,
89 M68K_REG_A2,
90 M68K_REG_A3,
91 M68K_REG_A4,
92 M68K_REG_A5,
93 M68K_REG_A6,
94 M68K_REG_A7,
95 M68K_REG_PC, /* Program Counter */
96 M68K_REG_SR, /* Status Register */
97 M68K_REG_SP, /* The current Stack Pointer (located in A7) */
98 M68K_REG_USP, /* User Stack Pointer */
99 M68K_REG_ISP, /* Interrupt Stack Pointer */
100 M68K_REG_MSP, /* Master Stack Pointer */
101 M68K_REG_SFC, /* Source Function Code */
102 M68K_REG_DFC, /* Destination Function Code */
103 M68K_REG_VBR, /* Vector Base Register */
104 M68K_REG_CACR, /* Cache Control Register */
105 M68K_REG_CAAR, /* Cache Address Register */
107 /* Assumed registers */
108 /* These are cheat registers which emulate the 1-longword prefetch
109 * present in the 68000 and 68010.
110 */
111 M68K_REG_PREF_ADDR, /* Last prefetch address */
112 M68K_REG_PREF_DATA, /* Last prefetch data */
114 /* Convenience registers */
115 M68K_REG_PPC, /* Previous value in the program counter */
116 M68K_REG_IR, /* Instruction register */
117 M68K_REG_CPU_TYPE /* Type of CPU being run */
118 } m68k_register_t;
120 /* ======================================================================== */
121 /* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
122 /* ======================================================================== */
124 /* You will have to implement these functions */
126 /* read/write functions called by the CPU to access memory.
127 * while values used are 32 bits, only the appropriate number
128 * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
129 * of value should be written to memory).
130 *
131 * NOTE: I have separated the immediate and PC-relative memory fetches
132 * from the other memory fetches because some systems require
133 * differentiation between PROGRAM and DATA fetches (usually
134 * for security setups such as encryption).
135 * This separation can either be achieved by setting
136 * M68K_SEPARATE_READS in m68kconf.h and defining
137 * the read functions, or by setting M68K_EMULATE_FC and
138 * making a function code callback function.
139 * Using the callback offers better emulation coverage
140 * because you can also monitor whether the CPU is in SYSTEM or
141 * USER mode, but it is also slower.
142 */
144 /* Read from anywhere */
145 unsigned int m68k_read_memory_8(unsigned int address);
146 unsigned int m68k_read_memory_16(unsigned int address);
147 unsigned int m68k_read_memory_32(unsigned int address);
149 /* Read data immediately following the PC */
150 unsigned int m68k_read_immediate_16(unsigned int address);
151 unsigned int m68k_read_immediate_32(unsigned int address);
153 /* Read data relative to the PC */
154 unsigned int m68k_read_pcrelative_8(unsigned int address);
155 unsigned int m68k_read_pcrelative_16(unsigned int address);
156 unsigned int m68k_read_pcrelative_32(unsigned int address);
158 /* Memory access for the disassembler */
159 unsigned int m68k_read_disassembler_8 (unsigned int address);
160 unsigned int m68k_read_disassembler_16 (unsigned int address);
161 unsigned int m68k_read_disassembler_32 (unsigned int address);
163 /* Write to anywhere */
164 void m68k_write_memory_8(unsigned int address, unsigned int value);
165 void m68k_write_memory_16(unsigned int address, unsigned int value);
166 void m68k_write_memory_32(unsigned int address, unsigned int value);
170 /* ======================================================================== */
171 /* ============================== CALLBACKS =============================== */
172 /* ======================================================================== */
174 /* These functions allow you to set callbacks to the host when specific events
175 * occur. Note that you must enable the corresponding value in m68kconf.h
176 * in order for these to do anything useful.
177 * Note: I have defined default callbacks which are used if you have enabled
178 * the corresponding #define in m68kconf.h but either haven't assigned a
179 * callback or have assigned a callback of NULL.
180 */
182 /* Set the callback for an interrupt acknowledge.
183 * You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
184 * The CPU will call the callback with the interrupt level being acknowledged.
185 * The host program must return either a vector from 0x02-0xff, or one of the
186 * special interrupt acknowledge values specified earlier in this header.
187 * If this is not implemented, the CPU will always assume an autovectored
188 * interrupt, and will automatically clear the interrupt request when it
189 * services the interrupt.
190 * Default behavior: return M68K_INT_ACK_AUTOVECTOR.
191 */
192 void m68k_set_int_ack_callback(int (*callback)(int int_level));
195 /* Set the callback for a breakpoint acknowledge (68010+).
196 * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
197 * The CPU will call the callback with whatever was in the data field of the
198 * BKPT instruction for 68020+, or 0 for 68010.
199 * Default behavior: do nothing.
200 */
201 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
204 /* Set the callback for the RESET instruction.
205 * You must enable M68K_EMULATE_RESET in m68kconf.h.
206 * The CPU calls this callback every time it encounters a RESET instruction.
207 * Default behavior: do nothing.
208 */
209 void m68k_set_reset_instr_callback(void (*callback)(void));
212 /* Set the callback for informing of a large PC change.
213 * You must enable M68K_MONITOR_PC in m68kconf.h.
214 * The CPU calls this callback with the new PC value every time the PC changes
215 * by a large value (currently set for changes by longwords).
216 * Default behavior: do nothing.
217 */
218 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
221 /* Set the callback for CPU function code changes.
222 * You must enable M68K_EMULATE_FC in m68kconf.h.
223 * The CPU calls this callback with the function code before every memory
224 * access to set the CPU's function code according to what kind of memory
225 * access it is (supervisor/user, program/data and such).
226 * Default behavior: do nothing.
227 */
228 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
231 /* Set a callback for the instruction cycle of the CPU.
232 * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
233 * The CPU calls this callback just before fetching the opcode in the
234 * instruction cycle.
235 * Default behavior: do nothing.
236 */
237 void m68k_set_instr_hook_callback(void (*callback)(void));
241 /* ======================================================================== */
242 /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
243 /* ======================================================================== */
245 /* Use this function to set the CPU type you want to emulate.
246 * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
247 * M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
248 */
249 void m68k_set_cpu_type(unsigned int cpu_type);
251 /* Pulse the RESET pin on the CPU.
252 * You *MUST* reset the CPU at least once to initialize the emulation
253 * Note: If you didn't call m68k_set_cpu_type() before resetting
254 * the CPU for the first time, the CPU will be set to
255 * M68K_CPU_TYPE_68000.
256 */
257 void m68k_pulse_reset(void);
259 /* execute num_cycles worth of instructions. returns number of cycles used */
260 int m68k_execute(int num_cycles);
262 /* These functions let you read/write/modify the number of cycles left to run
263 * while m68k_execute() is running.
264 * These are useful if the 68k accesses a memory-mapped port on another device
265 * that requires immediate processing by another CPU.
266 */
267 int m68k_cycles_run(void); /* Number of cycles run so far */
268 int m68k_cycles_remaining(void); /* Number of cycles left */
269 void m68k_modify_timeslice(int cycles); /* Modify cycles left */
270 void m68k_end_timeslice(void); /* End timeslice now */
272 /* Set the IPL0-IPL2 pins on the CPU (IRQ).
273 * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
274 * Setting IRQ to 0 will clear an interrupt request.
275 */
276 void m68k_set_irq(unsigned int int_level);
279 /* Halt the CPU as if you pulsed the HALT pin. */
280 void m68k_pulse_halt(void);
283 /* Trigger a bus error exception */
284 void m68k_pulse_bus_error(void);
287 /* Context switching to allow multiple CPUs */
289 /* Get the size of the cpu context in bytes */
290 unsigned int m68k_context_size(void);
292 /* Get a cpu context */
293 unsigned int m68k_get_context(void* dst);
295 /* set the current cpu context */
296 void m68k_set_context(void* dst);
298 /* Save the current cpu context to disk.
299 * You must provide a function pointer of the form:
300 * void save_value(char* identifier, unsigned int value)
301 */
302 void m68k_save_context( void (*save_value)(char* identifier, unsigned int value));
304 /* Load a cpu context from disk.
305 * You must provide a function pointer of the form:
306 * unsigned int load_value(char* identifier)
307 */
308 void m68k_load_context(unsigned int (*load_value)(char* identifier));
312 /* Peek at the internals of a CPU context. This can either be a context
313 * retrieved using m68k_get_context() or the currently running context.
314 * If context is NULL, the currently running CPU context will be used.
315 */
316 unsigned int m68k_get_reg(void* context, m68k_register_t reg);
318 /* Poke values into the internals of the currently running CPU context */
319 void m68k_set_reg(m68k_register_t reg, unsigned int value);
321 /* Check if an instruction is valid for the specified CPU type */
322 unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
324 /* Disassemble 1 instruction using the epecified CPU type at pc. Stores
325 * disassembly in str_buff and returns the size of the instruction in bytes.
326 */
327 unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
330 /* ======================================================================== */
331 /* ============================= CONFIGURATION ============================ */
332 /* ======================================================================== */
334 /* Import the configuration for this build */
335 #include "m68kconf.h"
339 /* ======================================================================== */
340 /* ============================== END OF FILE ============================= */
341 /* ======================================================================== */
343 #endif /* M68K__HEADER */