# HG changeset patch # User Michael Pavone # Date 1490685215 25200 # Node ID 208803173ebcd490d410a53dfc48c8f8e86e1d5b # Parent d2cb97ab3cffbb4495c982f9f51879b4b5be9873 Implemented M68K trace mode. Some edge cases/SR update paths still need work diff -r d2cb97ab3cff -r 208803173ebc Makefile --- a/Makefile Mon Mar 27 09:45:40 2017 -0700 +++ b/Makefile Tue Mar 28 00:13:35 2017 -0700 @@ -111,7 +111,7 @@ 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 -r d2cb97ab3cff -r 208803173ebc genesis.c --- a/genesis.c Mon Mar 27 09:45:40 2017 -0700 +++ b/genesis.c Tue Mar 28 00:13:35 2017 -0700 @@ -82,6 +82,11 @@ 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 -r d2cb97ab3cff -r 208803173ebc m68k_core.h --- a/m68k_core.h Mon Mar 27 09:45:40 2017 -0700 +++ b/m68k_core.h Tue Mar 28 00:13:35 2017 -0700 @@ -21,6 +21,8 @@ #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 @@ 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 -r d2cb97ab3cff -r 208803173ebc m68k_core_x86.c --- a/m68k_core_x86.c Mon Mar 27 09:45:40 2017 -0700 +++ b/m68k_core_x86.c Tue Mar 28 00:13:35 2017 -0700 @@ -2197,7 +2197,7 @@ 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 @@ 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 @@ 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 -r d2cb97ab3cff -r 208803173ebc trans.c --- a/trans.c Mon Mar 27 09:45:40 2017 -0700 +++ b/trans.c Tue Mar 28 00:13:35 2017 -0700 @@ -24,6 +24,9 @@ if (context->current_cycle > 0x80000000) { context->current_cycle -= 0x80000000; } + if (context->status & 0x80) { + context->target_cycle = context->current_cycle; + } return context; }