diff options
author | Michael Pavone <pavone@retrodev.com> | 2016-04-26 23:13:37 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2016-04-26 23:13:37 -0700 |
commit | 8b7027061d5d79712f2bdd859f55923d571efb4f (patch) | |
tree | b7d0e553d1fa1f450e21f64e561a2b74bc849530 /m68k_core_x86.c | |
parent | 042768acd31ac2a59049db55e31b647c2eb51818 (diff) |
Initial stab at implementing address error exceptions. Need to fill in the value of IR, undefined bits of last stack frame word and properly deal with address errors that occur during exception processing.
Diffstat (limited to 'm68k_core_x86.c')
-rw-r--r-- | m68k_core_x86.c | 168 |
1 files changed, 160 insertions, 8 deletions
diff --git a/m68k_core_x86.c b/m68k_core_x86.c index 48d245b..2533452 100644 --- a/m68k_core_x86.c +++ b/m68k_core_x86.c @@ -2128,6 +2128,54 @@ void translate_m68k_trapv(m68k_options *opts, m68kinst *inst) *no_trap = code->cur - (no_trap + 1); } +void translate_m68k_odd(m68k_options *opts, m68kinst *inst) +{ + code_info *code = &opts->gen.code; + //swap USP and SSP if not already in supervisor mode + check_user_mode_swap_ssp_usp(opts); + //save PC + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D); + call(code, opts->write_32_lowfirst); + //save status register + subi_areg(opts, 2, 7); + call(code, opts->get_sr); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save instruction register + subi_areg(opts, 2, 7); + //TODO: Use actual value + mov_ir(code, 0, opts->gen.scratch1, SZ_W); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save access address + subi_areg(opts, 4, 7); + mov_ir(code, inst->address, opts->gen.scratch1, SZ_D); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_32_lowfirst); + //save FC, I/N and R/W word' + xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W); + //FC3 is basically the same as the supervisor bit + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B); + shr_ir(code, 3, opts->gen.scratch1, SZ_B); + and_ir(code, 4, opts->gen.scratch1, SZ_B); + //set FC1 to one to indicate instruction fetch, and R/W to indicate read + or_ir(code, 0x12, opts->gen.scratch1, SZ_B); + //TODO: Figure out what undefined bits get set to, looks like it might be value of IR + subi_areg(opts, 2, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //set supervisor bit + or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); + //load vector address + mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D); + call(code, opts->read_32); + call(code, opts->native_addr_and_sync); + cycles(&opts->gen, 18); + jmp_r(code, opts->gen.scratch1); +} + void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) { code_info *code = &opts->gen.code; @@ -2285,6 +2333,7 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu opts->gen.cycles = RAX; opts->gen.limit = RBP; opts->gen.scratch1 = RCX; + opts->gen.align_error_mask = 1; opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); @@ -2392,7 +2441,14 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu retn(code); opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write; - + + check_alloc_code(code, 256); + opts->gen.handle_align_error_write = code->cur; + code->cur += 256; + check_alloc_code(code, 256); + opts->gen.handle_align_error_read = code->cur; + code->cur += 256; + opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL); opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL); opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL); @@ -2493,6 +2549,109 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu } } retn(code); + + code_info tmp_code = *code; + code->cur = opts->gen.handle_align_error_write; + code->last = code->cur + 256; + //unwind the stack one functinon call + add_ir(code, 16, RSP, SZ_PTR); + //save address that triggered error so we can write it to the 68K stack at the appropriate place + push_r(code, opts->gen.scratch2); + //swap USP and SSP if not already in supervisor mode + check_user_mode_swap_ssp_usp(opts); + //save PC + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D); + call(code, opts->write_32_lowfirst); + //save status register + subi_areg(opts, 2, 7); + call(code, opts->get_sr); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save instruction register + subi_areg(opts, 2, 7); + //TODO: Use actual value + mov_ir(code, 0, opts->gen.scratch1, SZ_W); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save access address + subi_areg(opts, 4, 7); + pop_r(code, opts->gen.scratch1); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_32_lowfirst); + //save FC, I/N and R/W word' + xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W); + //FC3 is basically the same as the supervisor bit + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B); + shr_ir(code, 3, opts->gen.scratch1, SZ_B); + and_ir(code, 4, opts->gen.scratch1, SZ_B); + //set FC0 to one to indicate data access + or_ir(code, 1, opts->gen.scratch1, SZ_B); + //TODO: Figure out what undefined bits get set to, looks like it might be value of IR + subi_areg(opts, 2, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //set supervisor bit + or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); + //load vector address + mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D); + call(code, opts->read_32); + call(code, opts->native_addr_and_sync); + cycles(&opts->gen, 18); + jmp_r(code, opts->gen.scratch1); + + code->cur = opts->gen.handle_align_error_read; + code->last = code->cur + 256; + //unwind the stack one functinon call + add_ir(code, 16, RSP, SZ_PTR); + //save address that triggered error so we can write it to the 68K stack at the appropriate place + push_r(code, opts->gen.scratch1); + //swap USP and SSP if not already in supervisor mode + check_user_mode_swap_ssp_usp(opts); + //save PC + subi_areg(opts, 4, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D); + call(code, opts->write_32_lowfirst); + //save status register + subi_areg(opts, 2, 7); + call(code, opts->get_sr); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save instruction register + subi_areg(opts, 2, 7); + //TODO: Use actual value + mov_ir(code, 0, opts->gen.scratch1, SZ_W); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //save access address + subi_areg(opts, 4, 7); + pop_r(code, opts->gen.scratch1); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_32_lowfirst); + //save FC, I/N and R/W word' + xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W); + //FC3 is basically the same as the supervisor bit + mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B); + shr_ir(code, 3, opts->gen.scratch1, SZ_B); + and_ir(code, 4, opts->gen.scratch1, SZ_B); + //set FC0 to one to indicate data access, and R/W to indicate read + or_ir(code, 0x11, opts->gen.scratch1, SZ_B); + //TODO: Figure out what undefined bits get set to, looks like it might be value of IR + subi_areg(opts, 2, 7); + areg_to_native(opts, 7, opts->gen.scratch2); + call(code, opts->write_16); + //set supervisor bit + or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); + //load vector address + mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D); + call(code, opts->read_32); + call(code, opts->native_addr_and_sync); + cycles(&opts->gen, 18); + jmp_r(code, opts->gen.scratch1); + + *code = tmp_code; opts->gen.handle_cycle_limit_int = code->cur; //calculate stack adjust size @@ -2630,11 +2789,4 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu call(code, opts->native_addr_and_sync); cycles(&opts->gen, 18); jmp_r(code, opts->gen.scratch1); - - opts->odd_address = code->cur; - mov_ir(code, (int64_t)stderr, RDI, SZ_PTR); - mov_ir(code, (int64_t)"Attempt to execute code at odd address\n", RSI, SZ_PTR); - call_args_abi(code, (code_ptr)fprintf, 2, RDI, RSI, RDX); - xor_rr(code, RDI, RDI, SZ_D); - call_args(code, (code_ptr)exit, 1, RDI); } |