comparison m68k_core_x86.c @ 847:7decd421cdc8

Update timing and order of steps in interrupt processing to match latest measurements
author Michael Pavone <pavone@retrodev.com>
date Sun, 01 Nov 2015 00:12:52 -0700
parents 98d7b6073163
children 7022ba865cfd
comparison
equal deleted inserted replaced
846:98d7b6073163 847:7decd421cdc8
2516 do_int = code->cur + 1; 2516 do_int = code->cur + 1;
2517 jcc(code, CC_NZ, do_int); 2517 jcc(code, CC_NZ, do_int);
2518 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); 2518 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2519 retn(code); 2519 retn(code);
2520 *do_int = code->cur - (do_int + 1); 2520 *do_int = code->cur - (do_int + 1);
2521 //save PC as stored in scratch1 for later
2522 push_r(code, opts->gen.scratch1);
2521 //set target cycle to sync cycle 2523 //set target cycle to sync cycle
2522 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D); 2524 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D);
2523 //swap USP and SSP if not already in supervisor mode 2525 //swap USP and SSP if not already in supervisor mode
2524 check_user_mode_swap_ssp_usp(opts); 2526 check_user_mode_swap_ssp_usp(opts);
2525 //save PC
2526 subi_areg(opts, 4, 7);
2527 areg_to_native(opts, 7, opts->gen.scratch2);
2528 call(code, opts->write_32_lowfirst);
2529 //save status register 2527 //save status register
2530 subi_areg(opts, 2, 7); 2528 subi_areg(opts, 6, 7);
2531 call(code, opts->get_sr); 2529 call(code, opts->get_sr);
2530 //6 cycles before SR gets saved
2531 cycles(&opts->gen, 6);
2532 //save SR to stack
2532 areg_to_native(opts, 7, opts->gen.scratch2); 2533 areg_to_native(opts, 7, opts->gen.scratch2);
2533 call(code, opts->write_16); 2534 call(code, opts->write_16);
2535 //interrupt ack cycle
2536 //the Genesis responds to these exclusively with !VPA which means its a slow
2537 //6800 operation. documentation says these can take between 10 and 19 cycles.
2538 //actual results measurements seem to suggest it's actually between 9 and 18
2539 //WARNING: this code might break with register assignment changes
2540 //save RDX
2541 push_r(code, RDX);
2542 //save cycle count
2543 mov_rr(code, RAX, opts->gen.scratch1, SZ_D);
2544 //clear top doubleword of dividend
2545 xor_rr(code, RDX, RDX, SZ_D);
2546 //set divisor to clock divider
2547 mov_ir(code, opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
2548 div_r(code, opts->gen.scratch2, SZ_D);
2549 //discard remainder
2550 xor_rr(code, RDX, RDX, SZ_D);
2551 //set divisor to 10, the period of E
2552 mov_ir(code, 10, opts->gen.scratch2, SZ_D);
2553 div_r(code, opts->gen.scratch2, SZ_D);
2554 //delay will be (9 + 4 + the remainder) * clock_divider
2555 //the extra 4 is to cover the idle bus period after the ack
2556 add_ir(code, 9 + 4, RDX, SZ_D);
2557 mov_ir(code, opts->gen.clock_divider, RAX, SZ_D);
2558 mul_r(code, RDX, SZ_D);
2559 pop_r(code, RDX);
2560 //add saved cycle count to result
2561 add_rr(code, opts->gen.scratch1, RAX, SZ_D);
2562
2534 //update status register 2563 //update status register
2535 and_irdisp(code, 0xF8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); 2564 and_irdisp(code, 0xF8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2536 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B); 2565 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
2537 or_ir(code, 0x20, opts->gen.scratch1, SZ_B); 2566 or_ir(code, 0x20, opts->gen.scratch1, SZ_B);
2538 or_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); 2567 or_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2568
2569 pop_r(code, opts->gen.scratch1);
2570
2571 //save PC
2572 areg_to_native(opts, 7, opts->gen.scratch2);
2573 add_ir(code, 2, opts->gen.scratch2, SZ_D);
2574 call(code, opts->write_32_lowfirst);
2575
2539 //calculate interrupt vector address 2576 //calculate interrupt vector address
2540 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_D); 2577 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_D);
2541 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_ack), SZ_W); 2578 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_ack), SZ_W);
2542 shl_ir(code, 2, opts->gen.scratch1, SZ_D); 2579 shl_ir(code, 2, opts->gen.scratch1, SZ_D);
2543 add_ir(code, 0x60, opts->gen.scratch1, SZ_D); 2580 add_ir(code, 0x60, opts->gen.scratch1, SZ_D);
2544 call(code, opts->read_32); 2581 call(code, opts->read_32);
2545 call(code, opts->native_addr_and_sync); 2582 call(code, opts->native_addr_and_sync);
2546 cycles(&opts->gen, 24); 2583 //2 prefetch bus operations + 2 idle bus cycles
2584 cycles(&opts->gen, 10);
2547 //discard function return address 2585 //discard function return address
2548 pop_r(code, opts->gen.scratch2); 2586 pop_r(code, opts->gen.scratch2);
2549 jmp_r(code, opts->gen.scratch1); 2587 jmp_r(code, opts->gen.scratch1);
2550 2588
2551 opts->trap = code->cur; 2589 opts->trap = code->cur;