38 |
|
#include "name_registry.h" |
39 |
|
#include "serial.h" |
40 |
|
#include "ether.h" |
41 |
+ |
#include "timer.h" |
42 |
|
|
43 |
|
#include <stdio.h> |
44 |
|
#include <stdlib.h> |
102 |
|
// Interrupts in native mode? |
103 |
|
#define INTERRUPTS_IN_NATIVE_MODE 1 |
104 |
|
|
105 |
+ |
// Enable native EMUL_OPs to be run without a mode switch |
106 |
+ |
#define ENABLE_NATIVE_EMUL_OP 1 |
107 |
+ |
|
108 |
|
// Pointer to Kernel Data |
109 |
|
static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE; |
110 |
|
|
133 |
|
void init_decoder(); |
134 |
|
void execute_sheep(uint32 opcode); |
135 |
|
|
136 |
+ |
// Filter out EMUL_OP routines that only call native code |
137 |
+ |
bool filter_execute_emul_op(uint32 emul_op); |
138 |
+ |
|
139 |
+ |
// "Native" EMUL_OP routines |
140 |
+ |
void execute_emul_op_microseconds(); |
141 |
+ |
void execute_emul_op_idle_time_1(); |
142 |
+ |
void execute_emul_op_idle_time_2(); |
143 |
+ |
|
144 |
|
public: |
145 |
|
|
146 |
|
// Constructor |
250 |
|
typedef bit_field< 20, 25 > NATIVE_OP_field; |
251 |
|
typedef bit_field< 26, 31 > EMUL_OP_field; |
252 |
|
|
253 |
+ |
// "Native" EMUL_OP routines |
254 |
+ |
#define GPR_A(REG) gpr(16 + (REG)) |
255 |
+ |
#define GPR_D(REG) gpr( 8 + (REG)) |
256 |
+ |
|
257 |
+ |
void sheepshaver_cpu::execute_emul_op_microseconds() |
258 |
+ |
{ |
259 |
+ |
Microseconds(GPR_A(0), GPR_D(0)); |
260 |
+ |
} |
261 |
+ |
|
262 |
+ |
void sheepshaver_cpu::execute_emul_op_idle_time_1() |
263 |
+ |
{ |
264 |
+ |
// Sleep if no events pending |
265 |
+ |
if (ReadMacInt32(0x14c) == 0) |
266 |
+ |
Delay_usec(16667); |
267 |
+ |
GPR_A(0) = ReadMacInt32(0x2b6); |
268 |
+ |
} |
269 |
+ |
|
270 |
+ |
void sheepshaver_cpu::execute_emul_op_idle_time_2() |
271 |
+ |
{ |
272 |
+ |
// Sleep if no events pending |
273 |
+ |
if (ReadMacInt32(0x14c) == 0) |
274 |
+ |
Delay_usec(16667); |
275 |
+ |
GPR_D(0) = (uint32)-2; |
276 |
+ |
} |
277 |
+ |
|
278 |
+ |
// Filter out EMUL_OP routines that only call native code |
279 |
+ |
bool sheepshaver_cpu::filter_execute_emul_op(uint32 emul_op) |
280 |
+ |
{ |
281 |
+ |
switch (emul_op) { |
282 |
+ |
case OP_MICROSECONDS: |
283 |
+ |
execute_emul_op_microseconds(); |
284 |
+ |
return true; |
285 |
+ |
case OP_IDLE_TIME: |
286 |
+ |
execute_emul_op_idle_time_1(); |
287 |
+ |
return true; |
288 |
+ |
case OP_IDLE_TIME_2: |
289 |
+ |
execute_emul_op_idle_time_2(); |
290 |
+ |
return true; |
291 |
+ |
} |
292 |
+ |
return false; |
293 |
+ |
} |
294 |
+ |
|
295 |
|
// Execute EMUL_OP routine |
296 |
|
void sheepshaver_cpu::execute_emul_op(uint32 emul_op) |
297 |
|
{ |
298 |
+ |
#if ENABLE_NATIVE_EMUL_OP |
299 |
+ |
// First, filter out EMUL_OPs that can be executed without a mode switch |
300 |
+ |
if (filter_execute_emul_op(emul_op)) |
301 |
+ |
return; |
302 |
+ |
#endif |
303 |
+ |
|
304 |
|
M68kRegisters r68; |
305 |
|
WriteMacInt32(XLM_68K_R25, gpr(25)); |
306 |
|
WriteMacInt32(XLM_RUN_MODE, MODE_EMUL_OP); |
454 |
|
} |
455 |
|
|
456 |
|
default: { // EMUL_OP |
457 |
+ |
uint32 emul_op = EMUL_OP_field::extract(opcode) - 3; |
458 |
+ |
#if ENABLE_NATIVE_EMUL_OP |
459 |
+ |
typedef void (*emul_op_func_t)(dyngen_cpu_base); |
460 |
+ |
emul_op_func_t emul_op_func = 0; |
461 |
+ |
switch (emul_op) { |
462 |
+ |
case OP_MICROSECONDS: |
463 |
+ |
emul_op_func = (emul_op_func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op_microseconds).ptr(); |
464 |
+ |
break; |
465 |
+ |
case OP_IDLE_TIME: |
466 |
+ |
emul_op_func = (emul_op_func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op_idle_time_1).ptr(); |
467 |
+ |
break; |
468 |
+ |
case OP_IDLE_TIME_2: |
469 |
+ |
emul_op_func = (emul_op_func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op_idle_time_2).ptr(); |
470 |
+ |
break; |
471 |
+ |
} |
472 |
+ |
if (emul_op_func) { |
473 |
+ |
dg.gen_invoke_CPU(emul_op_func); |
474 |
+ |
cg_context.done_compile = false; |
475 |
+ |
compiled = true; |
476 |
+ |
break; |
477 |
+ |
} |
478 |
+ |
#endif |
479 |
|
typedef void (*func_t)(dyngen_cpu_base, uint32); |
480 |
|
func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op).ptr(); |
481 |
< |
dg.gen_invoke_CPU_im(func, EMUL_OP_field::extract(opcode) - 3); |
481 |
> |
dg.gen_invoke_CPU_im(func, emul_op); |
482 |
|
cg_context.done_compile = false; |
483 |
|
compiled = true; |
484 |
|
break; |