comparison m68k_core_x86.c @ 987:1f09994e92c5

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.
author Michael Pavone <pavone@retrodev.com>
date Tue, 26 Apr 2016 23:13:37 -0700
parents f680fe746a7d
children d70000fdff0b
comparison
equal deleted inserted replaced
986:f680fe746a7d 987:1f09994e92c5
2126 ldi_native(opts, inst->address+2, opts->gen.scratch1); 2126 ldi_native(opts, inst->address+2, opts->gen.scratch1);
2127 jmp(code, opts->trap); 2127 jmp(code, opts->trap);
2128 *no_trap = code->cur - (no_trap + 1); 2128 *no_trap = code->cur - (no_trap + 1);
2129 } 2129 }
2130 2130
2131 void translate_m68k_odd(m68k_options *opts, m68kinst *inst)
2132 {
2133 code_info *code = &opts->gen.code;
2134 //swap USP and SSP if not already in supervisor mode
2135 check_user_mode_swap_ssp_usp(opts);
2136 //save PC
2137 subi_areg(opts, 4, 7);
2138 areg_to_native(opts, 7, opts->gen.scratch2);
2139 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2140 call(code, opts->write_32_lowfirst);
2141 //save status register
2142 subi_areg(opts, 2, 7);
2143 call(code, opts->get_sr);
2144 areg_to_native(opts, 7, opts->gen.scratch2);
2145 call(code, opts->write_16);
2146 //save instruction register
2147 subi_areg(opts, 2, 7);
2148 //TODO: Use actual value
2149 mov_ir(code, 0, opts->gen.scratch1, SZ_W);
2150 areg_to_native(opts, 7, opts->gen.scratch2);
2151 call(code, opts->write_16);
2152 //save access address
2153 subi_areg(opts, 4, 7);
2154 mov_ir(code, inst->address, opts->gen.scratch1, SZ_D);
2155 areg_to_native(opts, 7, opts->gen.scratch2);
2156 call(code, opts->write_32_lowfirst);
2157 //save FC, I/N and R/W word'
2158 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2159 //FC3 is basically the same as the supervisor bit
2160 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2161 shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2162 and_ir(code, 4, opts->gen.scratch1, SZ_B);
2163 //set FC1 to one to indicate instruction fetch, and R/W to indicate read
2164 or_ir(code, 0x12, opts->gen.scratch1, SZ_B);
2165 //TODO: Figure out what undefined bits get set to, looks like it might be value of IR
2166 subi_areg(opts, 2, 7);
2167 areg_to_native(opts, 7, opts->gen.scratch2);
2168 call(code, opts->write_16);
2169 //set supervisor bit
2170 or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2171 //load vector address
2172 mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2173 call(code, opts->read_32);
2174 call(code, opts->native_addr_and_sync);
2175 cycles(&opts->gen, 18);
2176 jmp_r(code, opts->gen.scratch1);
2177 }
2178
2131 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) 2179 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2132 { 2180 {
2133 code_info *code = &opts->gen.code; 2181 code_info *code = &opts->gen.code;
2134 //TODO: Trap if not in system mode 2182 //TODO: Trap if not in system mode
2135 call(code, opts->get_sr); 2183 call(code, opts->get_sr);
2283 #endif 2331 #endif
2284 opts->gen.context_reg = RSI; 2332 opts->gen.context_reg = RSI;
2285 opts->gen.cycles = RAX; 2333 opts->gen.cycles = RAX;
2286 opts->gen.limit = RBP; 2334 opts->gen.limit = RBP;
2287 opts->gen.scratch1 = RCX; 2335 opts->gen.scratch1 = RCX;
2336 opts->gen.align_error_mask = 1;
2288 2337
2289 2338
2290 opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); 2339 opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2291 memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS); 2340 memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2292 opts->gen.deferred = NULL; 2341 opts->gen.deferred = NULL;
2390 pop_r(code, opts->gen.scratch1); 2439 pop_r(code, opts->gen.scratch1);
2391 *skip_sync = code->cur - (skip_sync+1); 2440 *skip_sync = code->cur - (skip_sync+1);
2392 retn(code); 2441 retn(code);
2393 2442
2394 opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write; 2443 opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write;
2395 2444
2445 check_alloc_code(code, 256);
2446 opts->gen.handle_align_error_write = code->cur;
2447 code->cur += 256;
2448 check_alloc_code(code, 256);
2449 opts->gen.handle_align_error_read = code->cur;
2450 code->cur += 256;
2451
2396 opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL); 2452 opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL);
2397 opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL); 2453 opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL);
2398 opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL); 2454 opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL);
2399 opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8, NULL); 2455 opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8, NULL);
2400 2456
2491 setcc_rind(code, CC_C, opts->gen.context_reg); 2547 setcc_rind(code, CC_C, opts->gen.context_reg);
2492 } 2548 }
2493 } 2549 }
2494 } 2550 }
2495 retn(code); 2551 retn(code);
2552
2553 code_info tmp_code = *code;
2554 code->cur = opts->gen.handle_align_error_write;
2555 code->last = code->cur + 256;
2556 //unwind the stack one functinon call
2557 add_ir(code, 16, RSP, SZ_PTR);
2558 //save address that triggered error so we can write it to the 68K stack at the appropriate place
2559 push_r(code, opts->gen.scratch2);
2560 //swap USP and SSP if not already in supervisor mode
2561 check_user_mode_swap_ssp_usp(opts);
2562 //save PC
2563 subi_areg(opts, 4, 7);
2564 areg_to_native(opts, 7, opts->gen.scratch2);
2565 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2566 call(code, opts->write_32_lowfirst);
2567 //save status register
2568 subi_areg(opts, 2, 7);
2569 call(code, opts->get_sr);
2570 areg_to_native(opts, 7, opts->gen.scratch2);
2571 call(code, opts->write_16);
2572 //save instruction register
2573 subi_areg(opts, 2, 7);
2574 //TODO: Use actual value
2575 mov_ir(code, 0, opts->gen.scratch1, SZ_W);
2576 areg_to_native(opts, 7, opts->gen.scratch2);
2577 call(code, opts->write_16);
2578 //save access address
2579 subi_areg(opts, 4, 7);
2580 pop_r(code, opts->gen.scratch1);
2581 areg_to_native(opts, 7, opts->gen.scratch2);
2582 call(code, opts->write_32_lowfirst);
2583 //save FC, I/N and R/W word'
2584 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2585 //FC3 is basically the same as the supervisor bit
2586 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2587 shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2588 and_ir(code, 4, opts->gen.scratch1, SZ_B);
2589 //set FC0 to one to indicate data access
2590 or_ir(code, 1, opts->gen.scratch1, SZ_B);
2591 //TODO: Figure out what undefined bits get set to, looks like it might be value of IR
2592 subi_areg(opts, 2, 7);
2593 areg_to_native(opts, 7, opts->gen.scratch2);
2594 call(code, opts->write_16);
2595 //set supervisor bit
2596 or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2597 //load vector address
2598 mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2599 call(code, opts->read_32);
2600 call(code, opts->native_addr_and_sync);
2601 cycles(&opts->gen, 18);
2602 jmp_r(code, opts->gen.scratch1);
2603
2604 code->cur = opts->gen.handle_align_error_read;
2605 code->last = code->cur + 256;
2606 //unwind the stack one functinon call
2607 add_ir(code, 16, RSP, SZ_PTR);
2608 //save address that triggered error so we can write it to the 68K stack at the appropriate place
2609 push_r(code, opts->gen.scratch1);
2610 //swap USP and SSP if not already in supervisor mode
2611 check_user_mode_swap_ssp_usp(opts);
2612 //save PC
2613 subi_areg(opts, 4, 7);
2614 areg_to_native(opts, 7, opts->gen.scratch2);
2615 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2616 call(code, opts->write_32_lowfirst);
2617 //save status register
2618 subi_areg(opts, 2, 7);
2619 call(code, opts->get_sr);
2620 areg_to_native(opts, 7, opts->gen.scratch2);
2621 call(code, opts->write_16);
2622 //save instruction register
2623 subi_areg(opts, 2, 7);
2624 //TODO: Use actual value
2625 mov_ir(code, 0, opts->gen.scratch1, SZ_W);
2626 areg_to_native(opts, 7, opts->gen.scratch2);
2627 call(code, opts->write_16);
2628 //save access address
2629 subi_areg(opts, 4, 7);
2630 pop_r(code, opts->gen.scratch1);
2631 areg_to_native(opts, 7, opts->gen.scratch2);
2632 call(code, opts->write_32_lowfirst);
2633 //save FC, I/N and R/W word'
2634 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2635 //FC3 is basically the same as the supervisor bit
2636 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2637 shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2638 and_ir(code, 4, opts->gen.scratch1, SZ_B);
2639 //set FC0 to one to indicate data access, and R/W to indicate read
2640 or_ir(code, 0x11, opts->gen.scratch1, SZ_B);
2641 //TODO: Figure out what undefined bits get set to, looks like it might be value of IR
2642 subi_areg(opts, 2, 7);
2643 areg_to_native(opts, 7, opts->gen.scratch2);
2644 call(code, opts->write_16);
2645 //set supervisor bit
2646 or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2647 //load vector address
2648 mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2649 call(code, opts->read_32);
2650 call(code, opts->native_addr_and_sync);
2651 cycles(&opts->gen, 18);
2652 jmp_r(code, opts->gen.scratch1);
2653
2654 *code = tmp_code;
2496 2655
2497 opts->gen.handle_cycle_limit_int = code->cur; 2656 opts->gen.handle_cycle_limit_int = code->cur;
2498 //calculate stack adjust size 2657 //calculate stack adjust size
2499 add_ir(code, 16-sizeof(void*), RSP, SZ_PTR); 2658 add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
2500 uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int; 2659 uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int;
2628 shl_ir(code, 2, opts->gen.scratch1, SZ_D); 2787 shl_ir(code, 2, opts->gen.scratch1, SZ_D);
2629 call(code, opts->read_32); 2788 call(code, opts->read_32);
2630 call(code, opts->native_addr_and_sync); 2789 call(code, opts->native_addr_and_sync);
2631 cycles(&opts->gen, 18); 2790 cycles(&opts->gen, 18);
2632 jmp_r(code, opts->gen.scratch1); 2791 jmp_r(code, opts->gen.scratch1);
2633 2792 }
2634 opts->odd_address = code->cur;
2635 mov_ir(code, (int64_t)stderr, RDI, SZ_PTR);
2636 mov_ir(code, (int64_t)"Attempt to execute code at odd address\n", RSI, SZ_PTR);
2637 call_args_abi(code, (code_ptr)fprintf, 2, RDI, RSI, RDX);
2638 xor_rr(code, RDI, RDI, SZ_D);
2639 call_args(code, (code_ptr)exit, 1, RDI);
2640 }