summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--genesis.c5
-rw-r--r--m68k_core.h3
-rw-r--r--m68k_core_x86.c52
-rw-r--r--trans.c3
5 files changed, 59 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index ee55219..3bd1152 100644
--- a/Makefile
+++ b/Makefile
@@ -111,7 +111,7 @@ CPU:=i686
endif
endif
-TRANSOBJS=gen.o backend.o $(MEM) arena.o
+TRANSOBJS=gen.o backend.o $(MEM) arena.o tern.o
M68KOBJS=68kinst.o m68k_core.o
ifeq ($(CPU),x86_64)
M68KOBJS+= m68k_core_x86.o
diff --git a/genesis.c b/genesis.c
index da95c8f..896e76b 100644
--- a/genesis.c
+++ b/genesis.c
@@ -82,6 +82,11 @@ static void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter);
old_int_cycle = context->int_cycle;
}*/
+
+ if (context->status & M68K_STATUS_TRACE) {
+ context->target_cycle = context->current_cycle;
+ return;
+ }
context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle;
if (context->should_return) {
diff --git a/m68k_core.h b/m68k_core.h
index 786447f..48a2a90 100644
--- a/m68k_core.h
+++ b/m68k_core.h
@@ -21,6 +21,8 @@ struct m68kinst;
#define INT_PENDING_SR_CHANGE 254
#define INT_PENDING_NONE 255
+#define M68K_STATUS_TRACE 0x80
+
typedef void (*start_fun)(uint8_t * addr, void * context);
typedef struct {
@@ -78,6 +80,7 @@ typedef struct m68k_context {
m68k_options *options;
void *system;
uint8_t int_pending;
+ uint8_t trace_pending;
uint8_t should_return;
uint8_t ram_code_flags[];
} m68k_context;
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index ac26072..9bcfd4d 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -2197,7 +2197,7 @@ void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst)
swap_ssp_usp(opts);
}
if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700)
- || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) {
+ || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x8700)) {
if (inst->op == M68K_ANDI_SR) {
//set int pending flag in case we trigger an interrupt as a result of the mask change
mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
@@ -2929,10 +2929,17 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int;
code->cur = opts->gen.handle_cycle_limit_int;
-
+ bt_irdisp(code, 7, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+ code_ptr no_trace = code->cur + 1;
+ jcc(code, CC_NC, no_trace);
+ cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+ code_ptr do_trace = code->cur + 1;
+ jcc(code, CC_NZ, do_trace);
+ mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+ *no_trace = code->cur - (no_trace + 1);
cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
- code_ptr do_int = code->cur + 1;
- jcc(code, CC_NC, code->cur + 2);
+ code_ptr do_int = code->cur + 2;
+ jcc(code, CC_NC, do_int+512);//force 32-bit displacement
cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
skip_sync = code->cur + 1;
jcc(code, CC_C, code->cur + 2);
@@ -2955,7 +2962,42 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
retn(code);
code->stack_off = tmp_stack_off;
- *do_int = code->cur - (do_int+1);
+ *do_trace = code->cur - (do_trace + 1);
+ //clear out trace pending flag
+ mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+ //save PC as stored in scratch1 for later
+ push_r(code, opts->gen.scratch1);
+ //swap USP and SSP if not already in supervisor mode
+ check_user_mode_swap_ssp_usp(opts);
+ //save status register
+ subi_areg(opts, 6, 7);
+ call(code, opts->get_sr);
+ cycles(&opts->gen, 6);
+ //save SR to stack
+ areg_to_native(opts, 7, opts->gen.scratch2);
+ call(code, opts->write_16);
+ //update the status register
+ and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+ or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+ //save PC
+ areg_to_native(opts, 7, opts->gen.scratch2);
+ add_ir(code, 2, opts->gen.scratch2, SZ_D);
+ pop_r(code, opts->gen.scratch1);
+ call(code, opts->write_32_lowfirst);
+ //read vector
+ mov_ir(code, 0x24, opts->gen.scratch1, SZ_D);
+ call(code, opts->read_32);
+ call(code, opts->native_addr_and_sync);
+ //2 prefetch bus operations + 2 idle bus cycles
+ cycles(&opts->gen, 10);
+ //discard function return address
+ pop_r(code, opts->gen.scratch2);
+ add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
+ jmp_r(code, opts->gen.scratch1);
+
+ code->stack_off = tmp_stack_off;
+
+ *((uint32_t *)do_int) = code->cur - (do_int+4);
//implement 1 instruction latency
cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
do_int = code->cur + 1;
diff --git a/trans.c b/trans.c
index bdde49c..9399a96 100644
--- a/trans.c
+++ b/trans.c
@@ -24,6 +24,9 @@ m68k_context * sync_components(m68k_context * context, uint32_t address)
if (context->current_cycle > 0x80000000) {
context->current_cycle -= 0x80000000;
}
+ if (context->status & 0x80) {
+ context->target_cycle = context->current_cycle;
+ }
return context;
}