Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/core/m68k/s68kcpu.c
2 views
1
/* ======================================================================== */
2
/* SUB 68K CORE */
3
/* ======================================================================== */
4
5
extern int scd_68k_irq_ack(int level);
6
7
#define m68ki_cpu s68k
8
#define MUL (4)
9
10
/* ======================================================================== */
11
/* ================================ INCLUDES ============================== */
12
/* ======================================================================== */
13
14
#ifndef BUILD_TABLES
15
#include "s68ki_cycles.h"
16
#endif
17
18
#include "s68kconf.h"
19
#include "m68kcpu.h"
20
#include "m68kops.h"
21
22
/* ======================================================================== */
23
/* ================================= DATA ================================= */
24
/* ======================================================================== */
25
26
#ifdef BUILD_TABLES
27
static unsigned char s68ki_cycles[0x10000];
28
#endif
29
static int irq_latency;
30
31
/* IRQ priority */
32
static const uint8 irq_level[0x40] =
33
{
34
0, 1, 2, 2, 3, 3, 3, 3,
35
4, 4, 4, 4, 4, 4, 4, 4,
36
5, 5, 5, 5, 5, 5, 5, 5,
37
5, 5, 5, 5, 5, 5, 5, 5,
38
6, 6, 6, 6, 6, 6, 6, 6,
39
6, 6, 6, 6, 6, 6, 6, 6,
40
6, 6, 6, 6, 6, 6, 6, 6,
41
6, 6, 6, 6, 6, 6, 6, 6
42
};
43
44
m68ki_cpu_core s68k;
45
46
47
/* ======================================================================== */
48
/* =============================== CALLBACKS ============================== */
49
/* ======================================================================== */
50
51
/* Default callbacks used if the callback hasn't been set yet, or if the
52
* callback is set to NULL
53
*/
54
55
#if M68K_EMULATE_INT_ACK == OPT_ON
56
/* Interrupt acknowledge */
57
static int default_int_ack_callback(int int_level)
58
{
59
CPU_INT_LEVEL = 0;
60
return M68K_INT_ACK_AUTOVECTOR;
61
}
62
#endif
63
64
#if M68K_EMULATE_RESET == OPT_ON
65
/* Called when a reset instruction is executed */
66
static void default_reset_instr_callback(void)
67
{
68
}
69
#endif
70
71
#if M68K_TAS_HAS_CALLBACK == OPT_ON
72
/* Called when a tas instruction is executed */
73
static int default_tas_instr_callback(void)
74
{
75
return 1; // allow writeback
76
}
77
#endif
78
79
#if M68K_EMULATE_FC == OPT_ON
80
/* Called every time there's bus activity (read/write to/from memory */
81
static void default_set_fc_callback(unsigned int new_fc)
82
{
83
}
84
#endif
85
86
87
/* ======================================================================== */
88
/* ================================= API ================================== */
89
/* ======================================================================== */
90
91
/* Access the internals of the CPU */
92
unsigned int s68k_get_reg(m68k_register_t regnum)
93
{
94
switch(regnum)
95
{
96
case M68K_REG_D0: return m68ki_cpu.dar[0];
97
case M68K_REG_D1: return m68ki_cpu.dar[1];
98
case M68K_REG_D2: return m68ki_cpu.dar[2];
99
case M68K_REG_D3: return m68ki_cpu.dar[3];
100
case M68K_REG_D4: return m68ki_cpu.dar[4];
101
case M68K_REG_D5: return m68ki_cpu.dar[5];
102
case M68K_REG_D6: return m68ki_cpu.dar[6];
103
case M68K_REG_D7: return m68ki_cpu.dar[7];
104
case M68K_REG_A0: return m68ki_cpu.dar[8];
105
case M68K_REG_A1: return m68ki_cpu.dar[9];
106
case M68K_REG_A2: return m68ki_cpu.dar[10];
107
case M68K_REG_A3: return m68ki_cpu.dar[11];
108
case M68K_REG_A4: return m68ki_cpu.dar[12];
109
case M68K_REG_A5: return m68ki_cpu.dar[13];
110
case M68K_REG_A6: return m68ki_cpu.dar[14];
111
case M68K_REG_A7: return m68ki_cpu.dar[15];
112
case M68K_REG_PC: return MASK_OUT_ABOVE_32(m68ki_cpu.pc);
113
case M68K_REG_SR: return m68ki_cpu.t1_flag |
114
(m68ki_cpu.s_flag << 11) |
115
m68ki_cpu.int_mask |
116
((m68ki_cpu.x_flag & XFLAG_SET) >> 4) |
117
((m68ki_cpu.n_flag & NFLAG_SET) >> 4) |
118
((!m68ki_cpu.not_z_flag) << 2) |
119
((m68ki_cpu.v_flag & VFLAG_SET) >> 6) |
120
((m68ki_cpu.c_flag & CFLAG_SET) >> 8);
121
case M68K_REG_SP: return m68ki_cpu.dar[15];
122
case M68K_REG_USP: return m68ki_cpu.s_flag ? m68ki_cpu.sp[0] : m68ki_cpu.dar[15];
123
case M68K_REG_ISP: return m68ki_cpu.s_flag ? m68ki_cpu.dar[15] : m68ki_cpu.sp[4];
124
#if M68K_EMULATE_PREFETCH
125
case M68K_REG_PREF_ADDR: return m68ki_cpu.pref_addr;
126
case M68K_REG_PREF_DATA: return m68ki_cpu.pref_data;
127
#endif
128
case M68K_REG_IR: return m68ki_cpu.ir;
129
default: return 0;
130
}
131
}
132
133
void s68k_set_reg(m68k_register_t regnum, unsigned int value)
134
{
135
switch(regnum)
136
{
137
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
138
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
139
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
140
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
141
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
142
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
143
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
144
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
145
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
146
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
147
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
148
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
149
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
150
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
151
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
152
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
153
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
154
case M68K_REG_SR: m68ki_set_sr(value); return;
155
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
156
case M68K_REG_USP: if(FLAG_S)
157
REG_USP = MASK_OUT_ABOVE_32(value);
158
else
159
REG_SP = MASK_OUT_ABOVE_32(value);
160
return;
161
case M68K_REG_ISP: if(FLAG_S)
162
REG_SP = MASK_OUT_ABOVE_32(value);
163
else
164
REG_ISP = MASK_OUT_ABOVE_32(value);
165
return;
166
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
167
#if M68K_EMULATE_PREFETCH
168
case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return;
169
#endif
170
default: return;
171
}
172
}
173
174
/* Set the callbacks */
175
#if M68K_EMULATE_INT_ACK == OPT_ON
176
void s68k_set_int_ack_callback(int (*callback)(int int_level))
177
{
178
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
179
}
180
#endif
181
182
#if M68K_EMULATE_RESET == OPT_ON
183
void s68k_set_reset_instr_callback(void (*callback)(void))
184
{
185
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
186
}
187
#endif
188
189
#if M68K_TAS_HAS_CALLBACK == OPT_ON
190
void s68k_set_tas_instr_callback(int (*callback)(void))
191
{
192
CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
193
}
194
#endif
195
196
#if M68K_EMULATE_FC == OPT_ON
197
void s68k_set_fc_callback(void (*callback)(unsigned int new_fc))
198
{
199
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
200
}
201
#endif
202
203
extern void error(char *format, ...);
204
extern uint16 v_counter;
205
206
/* update IRQ level according to triggered interrupts */
207
void s68k_update_irq(unsigned int mask)
208
{
209
/* Get IRQ level (6 interrupt lines) */
210
mask = irq_level[mask];
211
212
/* Set IRQ level */
213
CPU_INT_LEVEL = mask << 8;
214
215
#ifdef LOG_SCD
216
error("[%d][%d] IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc);
217
#endif
218
}
219
220
void s68k_run(unsigned int cycles)
221
{
222
/* Make sure CPU is not already ahead */
223
if (s68k.cycles >= cycles)
224
{
225
return;
226
}
227
228
/* Check interrupt mask to process IRQ if needed */
229
m68ki_check_interrupts();
230
231
/* Make sure we're not stopped */
232
if (CPU_STOPPED)
233
{
234
s68k.cycles = cycles;
235
return;
236
}
237
238
/* Save end cycles count for when CPU is stopped */
239
s68k.cycle_end = cycles;
240
241
/* Return point for when we have an address error (TODO: use goto) */
242
m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */
243
244
#ifdef LOG_SCD
245
error("[%d][%d] s68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, s68k.cycles, cycles, s68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL);
246
#endif
247
248
while (s68k.cycles < cycles)
249
{
250
/* Set tracing accodring to T1. */
251
m68ki_trace_t1() /* auto-disable (see m68kcpu.h) */
252
253
/* Set the address space for reads */
254
m68ki_use_data_space() /* auto-disable (see m68kcpu.h) */
255
256
/* Decode next instruction */
257
REG_IR = m68ki_read_imm_16();
258
259
/* Execute instruction */
260
m68ki_instruction_jump_table[REG_IR]();
261
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
262
263
/* Trace m68k_exception, if necessary */
264
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
265
}
266
}
267
268
void s68k_init(void)
269
{
270
#ifdef BUILD_TABLES
271
static uint emulation_initialized = 0;
272
273
/* The first call to this function initializes the opcode handler jump table */
274
if(!emulation_initialized)
275
{
276
m68ki_build_opcode_table();
277
emulation_initialized = 1;
278
}
279
#endif
280
281
#if M68K_EMULATE_INT_ACK == OPT_ON
282
s68k_set_int_ack_callback(NULL);
283
#endif
284
#if M68K_EMULATE_RESET == OPT_ON
285
s68k_set_reset_instr_callback(NULL);
286
#endif
287
#if M68K_TAS_HAS_CALLBACK == OPT_ON
288
s68k_set_tas_instr_callback(NULL);
289
#endif
290
#if M68K_EMULATE_FC == OPT_ON
291
s68k_set_fc_callback(NULL);
292
#endif
293
}
294
295
/* Pulse the RESET line on the CPU */
296
void s68k_pulse_reset(void)
297
{
298
/* Clear all stop levels */
299
CPU_STOPPED = 0;
300
#if M68K_EMULATE_ADDRESS_ERROR
301
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
302
#endif
303
304
/* Turn off tracing */
305
FLAG_T1 = 0;
306
m68ki_clear_trace()
307
308
/* Interrupt mask to level 7 */
309
FLAG_INT_MASK = 0x0700;
310
CPU_INT_LEVEL = 0;
311
irq_latency = 0;
312
313
/* Go to supervisor mode */
314
m68ki_set_s_flag(SFLAG_SET);
315
316
/* Invalidate the prefetch queue */
317
#if M68K_EMULATE_PREFETCH
318
/* Set to arbitrary number since our first fetch is from 0 */
319
CPU_PREF_ADDR = 0x1000;
320
#endif /* M68K_EMULATE_PREFETCH */
321
322
/* Read the initial stack pointer and program counter */
323
m68ki_jump(0);
324
REG_SP = m68ki_read_imm_32();
325
REG_PC = m68ki_read_imm_32();
326
m68ki_jump(REG_PC);
327
328
#if M68K_EMULATE_ADDRESS_ERROR
329
CPU_RUN_MODE = RUN_MODE_NORMAL;
330
#endif
331
332
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]);
333
}
334
335
void s68k_pulse_halt(void)
336
{
337
/* Pulse the HALT line on the CPU */
338
CPU_STOPPED |= STOP_LEVEL_HALT;
339
}
340
341
void s68k_clear_halt()
342
{
343
/* Clear the HALT line on the CPU */
344
CPU_STOPPED &= ~STOP_LEVEL_HALT;
345
}
346
347
/* ======================================================================== */
348
/* ============================== END OF FILE ============================= */
349
/* ======================================================================== */
350
351