diff options
author | Michael Pavone <pavone@retrodev.com> | 2017-03-28 00:13:35 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2017-03-28 00:13:35 -0700 |
commit | 15be1a3421956600cf3a773b96bf7aaf8f092d04 (patch) | |
tree | 377049a149b3cae59df5a804e393847823525ad8 | |
parent | 246813eedfa1274917f3a88755afd3a316ee8aae (diff) |
Implemented M68K trace mode. Some edge cases/SR update paths still need work
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | genesis.c | 5 | ||||
-rw-r--r-- | m68k_core.h | 3 | ||||
-rw-r--r-- | m68k_core_x86.c | 52 | ||||
-rw-r--r-- | trans.c | 3 |
5 files changed, 59 insertions, 6 deletions
@@ -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 @@ -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; @@ -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; } |