# HG changeset patch # User Michael Pavone # Date 1475771671 25200 # Node ID 2ec5e6eaf81d77e375296eaa101095489be2449f # Parent 89cc20cf1ad374f72e9a002480b52ad015083ef3 Add support for specifying a reset handler in the M68K core. Adjust memory map initialization to handle extra field. Improved handling of out of bounds execution. diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d blastem.c --- a/blastem.c Thu Oct 06 09:25:43 2016 -0700 +++ b/blastem.c Thu Oct 06 09:34:31 2016 -0700 @@ -875,11 +875,11 @@ #ifndef NO_Z80 const memmap_chunk z80_map[] = { - { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, - { 0x8000, 0x10000, 0x7FFF, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, - { 0x4000, 0x6000, 0x0003, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, - { 0x6000, 0x6100, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, - { 0x7F00, 0x8000, 0x00FF, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} + { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0x7FFF, 0, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, + { 0x7F00, 0x8000, 0x00FF, 0, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} }; #endif @@ -939,7 +939,7 @@ init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K); //TODO: make this configurable opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; - gen->m68k = init_68k_context(opts); + gen->m68k = init_68k_context(opts, NULL); gen->m68k->system = gen; for (int i = 0; i < rom->map_chunks; i++) @@ -1213,12 +1213,12 @@ } ram = malloc(RAM_WORDS * sizeof(uint16_t)); memmap_chunk base_map[] = { - {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, + {0xE00000, 0x1000000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL}, - {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL, + {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, - {0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL, + {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, (read_16_fun)io_read_w, (write_16_fun)io_write_w, (read_8_fun)io_read, (write_8_fun)io_write} }; diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d gen.h --- a/gen.h Thu Oct 06 09:25:43 2016 -0700 +++ b/gen.h Thu Oct 06 09:34:31 2016 -0700 @@ -26,6 +26,8 @@ void jmp_r(code_info *code, uint8_t dst); //call a function and put the arguments in the appropriate place according to the host ABI void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...); +//like the above, but call a function pointer stored in a register +void call_args_r(code_info *code, uint8_t fun_reg, uint32_t num_args, ...); //like the above, but follows other aspects of the ABI like stack alignment //void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...); #define call_args_abi call_args diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d gen_x86.c --- a/gen_x86.c Thu Oct 06 09:25:43 2016 -0700 +++ b/gen_x86.c Thu Oct 06 09:34:31 2016 -0700 @@ -2138,6 +2138,19 @@ code->stack_off -= adjust; } } + +void call_args_r(code_info *code, uint8_t fun_reg, uint32_t num_args, ...) +{ + va_list args; + va_start(args, num_args); + uint32_t adjust = prep_args(code, num_args, args); + va_end(args); + call_r(code, fun_reg); + if (adjust) { + add_ir(code, adjust, RSP, SZ_PTR); + code->stack_off -= adjust; + } +} /* void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...) { diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d m68k_core.c --- a/m68k_core.c Thu Oct 06 09:25:43 2016 -0700 +++ b/m68k_core.c Thu Oct 06 09:34:31 2016 -0700 @@ -43,7 +43,7 @@ return op->addr_mode == MODE_REG ? dreg_offset(op->params.regs.pri) : areg_offset(op->params.regs.pri); } -void print_regs_exit(m68k_context * context) +void m68k_print_regs(m68k_context * context) { printf("XNZVC\n%d%d%d%d%d\n", context->flags[0], context->flags[1], context->flags[2], context->flags[3], context->flags[4]); for (int i = 0; i < 8; i++) { @@ -52,7 +52,6 @@ for (int i = 0; i < 8; i++) { printf("a%d: %X\n", i, context->aregs[i]); } - exit(0); } void m68k_read_size(m68k_options *opts, uint8_t size) @@ -538,13 +537,6 @@ native_to_areg(opts, opts->gen.scratch2, 8); } -void translate_m68k_reset(m68k_options *opts, m68kinst *inst) -{ - code_info *code = &opts->gen.code; - call(code, opts->gen.save_context); - call_args(code, (code_ptr)print_regs_exit, 1, opts->gen.context_reg); -} - void translate_m68k_rte(m68k_options *opts, m68kinst *inst) { m68k_trap_if_not_supervisor(opts, inst); @@ -907,7 +899,7 @@ encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); if (!encoded) { map_native_address(context, address, code->cur, 2, 1); - translate_out_of_bounds(code); + translate_out_of_bounds(opts, address); break; } code_ptr existing = get_native_address(opts, address); @@ -1068,7 +1060,7 @@ } -m68k_context * init_68k_context(m68k_options * opts) +m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler) { size_t ctx_size = sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8; m68k_context * context = malloc(ctx_size); @@ -1077,5 +1069,6 @@ context->options = opts; context->int_cycle = CYCLE_NEVER; context->status = 0x27; + context->reset_handler = (code_ptr)reset_handler; return context; } diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d m68k_core.h --- a/m68k_core.h Thu Oct 06 09:25:43 2016 -0700 +++ b/m68k_core.h Thu Oct 06 09:34:31 2016 -0700 @@ -61,6 +61,7 @@ uint32_t last_prefetch_address; uint16_t *mem_pointers[NUM_MEM_AREAS]; code_ptr resume_pc; + code_ptr reset_handler; native_map_slot *native_code_map; m68k_options *options; void *system; @@ -69,12 +70,14 @@ uint8_t ram_code_flags[]; } m68k_context; +typedef m68k_context *(*m68k_reset_handler)(m68k_context *context); + void translate_m68k(m68k_options * opts, struct m68kinst * inst); void translate_m68k_stream(uint32_t address, m68k_context * context); void start_68k_context(m68k_context * context, uint32_t address); void resume_68k(m68k_context *context); void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider); -m68k_context * init_68k_context(m68k_options * opts); +m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler); void m68k_reset(m68k_context * context); void m68k_options_free(m68k_options *opts); void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler); @@ -82,6 +85,7 @@ m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context); uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code_map, uint32_t address); uint16_t m68k_get_ir(m68k_context *context); +void m68k_print_regs(m68k_context * context); #endif //M68K_CORE_H_ diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d m68k_core_x86.c --- a/m68k_core_x86.c Thu Oct 06 09:25:43 2016 -0700 +++ b/m68k_core_x86.c Thu Oct 06 09:34:31 2016 -0700 @@ -1156,6 +1156,21 @@ } } +void translate_m68k_reset(m68k_options *opts, m68kinst *inst) +{ + code_info *code = &opts->gen.code; + cycles(&opts->gen, BUS); + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR); + cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR); + code_ptr no_reset_handler = code->cur + 1; + jcc(code, CC_Z, code->cur+2); + call(code, opts->gen.save_context); + call_args_r(code, opts->gen.scratch1, 1, opts->gen.context_reg); + mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); + call(code, opts->gen.load_context); + *no_reset_handler = code->cur - (no_reset_handler + 1); +} + void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size) { switch (inst->op) @@ -2220,10 +2235,16 @@ m68k_save_result(inst, opts); } -void translate_out_of_bounds(code_info *code) +void m68k_out_of_bounds_execution(uint32_t address) { - xor_rr(code, RDI, RDI, SZ_D); - call_args(code, (code_ptr)exit, 1, RDI); + fatal_error("M68K attempted to execute code at unmapped or I/O address %X\n", address); +} + +void translate_out_of_bounds(m68k_options *opts, uint32_t address) +{ + code_info *code = &opts->gen.code; + mov_ir(code, address, opts->gen.scratch1, SZ_D); + call_args(code, (code_ptr)m68k_out_of_bounds_execution, 1, opts->gen.scratch1); } void m68k_set_last_prefetch(m68k_options *opts, uint32_t address) diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d m68k_internal.h --- a/m68k_internal.h Thu Oct 06 09:25:43 2016 -0700 +++ b/m68k_internal.h Thu Oct 06 09:34:31 2016 -0700 @@ -9,7 +9,7 @@ #include "68kinst.h" //functions implemented in host CPU specfic file -void translate_out_of_bounds(code_info *code); +void translate_out_of_bounds(m68k_options *opts, uint32_t address); void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg); void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg); @@ -42,7 +42,6 @@ size_t areg_offset(uint8_t reg); size_t reg_offset(m68k_op_info *op); void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst); -void print_regs_exit(m68k_context * context); void m68k_read_size(m68k_options *opts, uint8_t size); void m68k_write_size(m68k_options *opts, uint8_t size, uint8_t lowfirst); void m68k_save_result(m68kinst * inst, m68k_options * opts); @@ -88,6 +87,7 @@ void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op); void translate_m68k_stop(m68k_options *opts, m68kinst *inst); void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op); +void translate_m68k_reset(m68k_options *opts, m68kinst *inst); //flag update bits #define X0 0x0001 diff -r 89cc20cf1ad3 -r 2ec5e6eaf81d trans.c --- a/trans.c Thu Oct 06 09:25:43 2016 -0700 +++ b/trans.c Thu Oct 06 09:34:31 2016 -0700 @@ -27,6 +27,14 @@ return context; } +m68k_context *reset_handler(m68k_context *context) +{ + m68k_print_regs(context); + exit(0); + //unreachable + return context; +} + int main(int argc, char ** argv) { long filesize; @@ -60,7 +68,7 @@ memmap[1].buffer = malloc(64 * 1024); memset(memmap[1].buffer, 0, 64 * 1024); init_m68k_opts(&opts, memmap, 2, 1); - m68k_context * context = init_68k_context(&opts); + m68k_context * context = init_68k_context(&opts, reset_handler); context->mem_pointers[0] = memmap[0].buffer; context->mem_pointers[1] = memmap[1].buffer; context->target_cycle = context->sync_cycle = 0x80000000;