Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/gpgx/core/m68k/m68k.h
2 views
1
#ifndef M68K__HEADER
2
#define M68K__HEADER
3
4
/* ======================================================================== */
5
/* ========================= LICENSING & COPYRIGHT ======================== */
6
/* ======================================================================== */
7
/*
8
* MUSASHI
9
* Version 3.32
10
*
11
* A portable Motorola M680x0 processor emulation engine.
12
* Copyright 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 licensing 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
*/
24
25
/* Modified by Eke-Eke for Genesis Plus GX:
26
27
- removed unused stuff to reduce memory usage / optimize execution (multiple CPU types support, NMI support, ...)
28
- moved stuff to compile statically in a single object file
29
- implemented support for global cycle count (shared by 68k & Z80 CPU)
30
- added support for interrupt latency (Sesame's Street Counting Cafe, Fatal Rewind)
31
- added proper cycle use on reset
32
- added cycle accurate timings for MUL/DIV instructions (thanks to Jorge Cwik !)
33
- fixed undocumented flags for DIV instructions (Blood Shot)
34
- added MAIN-CPU & SUB-CPU support for Mega CD emulation
35
36
*/
37
38
/* ======================================================================== */
39
/* ================================ INCLUDES ============================== */
40
/* ======================================================================== */
41
42
#include <setjmp.h>
43
#include "macros.h"
44
45
/* ======================================================================== */
46
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
47
/* ======================================================================== */
48
49
/* Check for > 32bit sizes */
50
#if UINT_MAX > 0xffffffff
51
#define M68K_INT_GT_32_BIT 1
52
#else
53
#define M68K_INT_GT_32_BIT 0
54
#endif
55
56
/* Data types used in this emulation core */
57
#undef sint8
58
#undef sint16
59
#undef sint32
60
#undef sint64
61
#undef uint8
62
#undef uint16
63
#undef uint32
64
#undef uint64
65
#undef sint
66
#undef uint
67
68
#define sint8 signed char /* ASG: changed from char to signed char */
69
#define sint16 signed short
70
#define sint32 signed int /* AWJ: changed from long to int */
71
#define uint8 unsigned char
72
#define uint16 unsigned short
73
#define uint32 unsigned int /* AWJ: changed from long to int */
74
75
/* signed and unsigned int must be at least 32 bits wide */
76
#define sint signed int
77
#define uint unsigned int
78
79
80
#if M68K_USE_64_BIT
81
#define sint64 signed long long
82
#define uint64 unsigned long long
83
#else
84
#define sint64 sint32
85
#define uint64 uint32
86
#endif /* M68K_USE_64_BIT */
87
88
89
90
/* Allow for architectures that don't have 8-bit sizes */
91
/*#if UCHAR_MAX == 0xff*/
92
#define MAKE_INT_8(A) (sint8)(A)
93
/*#else
94
#undef sint8
95
#define sint8 signed int
96
#undef uint8
97
#define uint8 unsigned int
98
INLINE sint MAKE_INT_8(uint value)
99
{
100
return (value & 0x80) ? value | ~0xff : value & 0xff;
101
}*/
102
/*#endif *//* UCHAR_MAX == 0xff */
103
104
105
/* Allow for architectures that don't have 16-bit sizes */
106
/*#if USHRT_MAX == 0xffff*/
107
#define MAKE_INT_16(A) (sint16)(A)
108
/*#else
109
#undef sint16
110
#define sint16 signed int
111
#undef uint16
112
#define uint16 unsigned int
113
INLINE sint MAKE_INT_16(uint value)
114
{
115
return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
116
}*/
117
/*#endif *//* USHRT_MAX == 0xffff */
118
119
120
/* Allow for architectures that don't have 32-bit sizes */
121
/*#if UINT_MAX == 0xffffffff*/
122
#define MAKE_INT_32(A) (sint32)(A)
123
/*#else
124
#undef sint32
125
#define sint32 signed int
126
#undef uint32
127
#define uint32 unsigned int
128
INLINE sint MAKE_INT_32(uint value)
129
{
130
return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
131
}*/
132
/*#endif *//* UINT_MAX == 0xffffffff */
133
134
135
136
/* ======================================================================== */
137
/* ============================ GENERAL DEFINES =========================== */
138
139
/* ======================================================================== */
140
141
/* There are 7 levels of interrupt to the 68K.
142
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
143
*/
144
#define M68K_IRQ_NONE 0
145
#define M68K_IRQ_1 1
146
#define M68K_IRQ_2 2
147
#define M68K_IRQ_3 3
148
#define M68K_IRQ_4 4
149
#define M68K_IRQ_5 5
150
#define M68K_IRQ_6 6
151
#define M68K_IRQ_7 7
152
153
154
/* Special interrupt acknowledge values.
155
* Use these as special returns from the interrupt acknowledge callback
156
* (specified later in this header).
157
*/
158
159
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
160
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
161
* acknowledge cycle instead of DTACK.
162
*/
163
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
164
165
/* Causes the spurious interrupt vector (0x18) to be taken
166
* This happens in a real 68K if BERR is asserted during the interrupt
167
* acknowledge cycle (i.e. no devices responded to the acknowledge).
168
*/
169
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
170
171
172
/* Registers used by m68k_get_reg() and m68k_set_reg() */
173
typedef enum
174
{
175
/* Real registers */
176
M68K_REG_D0, /* Data registers */
177
M68K_REG_D1,
178
M68K_REG_D2,
179
M68K_REG_D3,
180
M68K_REG_D4,
181
M68K_REG_D5,
182
M68K_REG_D6,
183
M68K_REG_D7,
184
M68K_REG_A0, /* Address registers */
185
M68K_REG_A1,
186
M68K_REG_A2,
187
M68K_REG_A3,
188
M68K_REG_A4,
189
M68K_REG_A5,
190
M68K_REG_A6,
191
M68K_REG_A7,
192
M68K_REG_PC, /* Program Counter */
193
M68K_REG_SR, /* Status Register */
194
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
195
M68K_REG_USP, /* User Stack Pointer */
196
M68K_REG_ISP, /* Interrupt Stack Pointer */
197
198
#if M68K_EMULATE_PREFETCH
199
/* Assumed registers */
200
/* These are cheat registers which emulate the 1-longword prefetch
201
* present in the 68000 and 68010.
202
*/
203
M68K_REG_PREF_ADDR, /* Last prefetch address */
204
M68K_REG_PREF_DATA, /* Last prefetch data */
205
#endif
206
207
/* Convenience registers */
208
M68K_REG_IR /* Instruction register */
209
} m68k_register_t;
210
211
212
/* 68k memory map structure */
213
typedef struct
214
{
215
unsigned char *base; /* memory-based access (ROM, RAM) */
216
unsigned int (*read8)(unsigned int address); /* I/O byte read access */
217
unsigned int (*read16)(unsigned int address); /* I/O word read access */
218
void (*write8)(unsigned int address, unsigned int data); /* I/O byte write access */
219
void (*write16)(unsigned int address, unsigned int data); /* I/O word write access */
220
} cpu_memory_map;
221
222
/* 68k idle loop detection */
223
typedef struct
224
{
225
uint pc;
226
uint cycle;
227
uint detected;
228
} cpu_idle_t;
229
230
typedef struct
231
{
232
cpu_memory_map memory_map[256]; /* memory mapping */
233
234
cpu_idle_t poll; /* polling detection */ // 0x1400
235
236
uint cycles; /* current master cycle count */
237
uint cycle_end; /* aimed master cycle count for current execution frame */
238
239
uint dar[16]; /* Data and Address Registers */
240
uint pc; /* Program Counter */
241
uint sp[5]; /* User and Interrupt Stack Pointers */
242
uint ir; /* Instruction Register */
243
uint t1_flag; /* Trace 1 */
244
uint s_flag; /* Supervisor */
245
uint x_flag; /* Extend */
246
uint n_flag; /* Negative */
247
uint not_z_flag; /* Zero, inverted for speedups */
248
uint v_flag; /* Overflow */
249
uint c_flag; /* Carry */
250
uint int_mask; /* I0-I2 */
251
uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
252
uint stopped; /* Stopped state */
253
254
uint pref_addr; /* Last prefetch address */
255
uint pref_data; /* Data in the prefetch queue */
256
257
uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
258
uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
259
uint aerr_enabled; /* Enables/deisables address error checks at runtime */
260
jmp_buf aerr_trap; /* Address error jump */
261
uint aerr_address; /* Address error location */
262
uint aerr_write_mode; /* Address error write mode */
263
uint aerr_fc; /* Address error FC code */
264
265
uint tracing; /* Tracing enable flag */
266
267
uint address_space; /* Current FC code */
268
269
/* Callbacks to host */
270
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
271
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
272
int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */
273
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
274
} m68ki_cpu_core;
275
276
/* CPU cores */
277
extern m68ki_cpu_core m68k;
278
extern m68ki_cpu_core s68k;
279
280
281
/* ======================================================================== */
282
/* ============================== CALLBACKS =============================== */
283
/* ======================================================================== */
284
285
/* These functions allow you to set callbacks to the host when specific events
286
* occur. Note that you must enable the corresponding value in m68kconf.h
287
* in order for these to do anything useful.
288
* Note: I have defined default callbacks which are used if you have enabled
289
* the corresponding #define in m68kconf.h but either haven't assigned a
290
* callback or have assigned a callback of NULL.
291
*/
292
293
#if M68K_EMULATE_INT_ACK == OPT_ON
294
/* Set the callback for an interrupt acknowledge.
295
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
296
* The CPU will call the callback with the interrupt level being acknowledged.
297
* The host program must return either a vector from 0x02-0xff, or one of the
298
* special interrupt acknowledge values specified earlier in this header.
299
* If this is not implemented, the CPU will always assume an autovectored
300
* interrupt, and will automatically clear the interrupt request when it
301
* services the interrupt.
302
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
303
*/
304
void m68k_set_int_ack_callback(int (*callback)(int int_level));
305
#endif
306
307
#if M68K_EMULATE_RESET == OPT_ON
308
/* Set the callback for the RESET instruction.
309
* You must enable M68K_EMULATE_RESET in m68kconf.h.
310
* The CPU calls this callback every time it encounters a RESET instruction.
311
* Default behavior: do nothing.
312
*/
313
void m68k_set_reset_instr_callback(void (*callback)(void));
314
#endif
315
316
#if M68K_TAS_HAS_CALLBACK == OPT_ON
317
/* Set the callback for the TAS instruction.
318
* You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h.
319
* The CPU calls this callback every time it encounters a TAS instruction.
320
* Default behavior: return 1, allow writeback.
321
*/
322
void m68k_set_tas_instr_callback(int (*callback)(void));
323
#endif
324
325
#if M68K_EMULATE_FC == OPT_ON
326
/* Set the callback for CPU function code changes.
327
* You must enable M68K_EMULATE_FC in m68kconf.h.
328
* The CPU calls this callback with the function code before every memory
329
* access to set the CPU's function code according to what kind of memory
330
* access it is (supervisor/user, program/data and such).
331
* Default behavior: do nothing.
332
*/
333
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
334
#endif
335
336
337
/* ======================================================================== */
338
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
339
/* ======================================================================== */
340
341
/* Do whatever initialisations the core requires. Should be called
342
* at least once at init time.
343
*/
344
extern void m68k_init(void);
345
extern void s68k_init(void);
346
347
/* Pulse the RESET pin on the CPU.
348
* You *MUST* reset the CPU at least once to initialize the emulation
349
*/
350
extern void m68k_pulse_reset(void);
351
extern void s68k_pulse_reset(void);
352
353
/* Run until given cycle count is reached */
354
extern void m68k_run(unsigned int cycles);
355
extern void s68k_run(unsigned int cycles);
356
357
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
358
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
359
* Setting IRQ to 0 will clear an interrupt request.
360
*/
361
extern void m68k_set_irq(unsigned int int_level);
362
extern void m68k_set_irq_delay(unsigned int int_level);
363
extern void m68k_update_irq(unsigned int mask);
364
extern void s68k_update_irq(unsigned int mask);
365
366
/* Halt the CPU as if you pulsed the HALT pin. */
367
extern void m68k_pulse_halt(void);
368
extern void m68k_clear_halt(void);
369
extern void s68k_pulse_halt(void);
370
extern void s68k_clear_halt(void);
371
372
373
/* Peek at the internals of a CPU context. This can either be a context
374
* retrieved using m68k_get_context() or the currently running context.
375
* If context is NULL, the currently running CPU context will be used.
376
*/
377
extern unsigned int m68k_get_reg(m68k_register_t reg);
378
extern unsigned int s68k_get_reg(m68k_register_t reg);
379
380
/* Poke values into the internals of the currently running CPU context */
381
extern void m68k_set_reg(m68k_register_t reg, unsigned int value);
382
extern void s68k_set_reg(m68k_register_t reg, unsigned int value);
383
384
385
/* ======================================================================== */
386
/* ============================== END OF FILE ============================= */
387
/* ======================================================================== */
388
389
#endif /* M68K__HEADER */
390
391