Mercurial > repos > blastem
comparison m68k_core_x86.c @ 846:98d7b6073163
Implement interrupt latency. Fixes Sesame Street: Counting Cafe and gives accurate results in my test ROM
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 31 Oct 2015 22:17:50 -0700 |
parents | 4556818b6847 |
children | 7decd421cdc8 |
comparison
equal
deleted
inserted
replaced
845:3a18b5f63afc | 846:98d7b6073163 |
---|---|
2008 //leave supervisor mode | 2008 //leave supervisor mode |
2009 swap_ssp_usp(opts); | 2009 swap_ssp_usp(opts); |
2010 } | 2010 } |
2011 if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700) | 2011 if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700) |
2012 || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) { | 2012 || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) { |
2013 if (inst->op == M68K_ANDI_SR) { | |
2014 //set int pending flag in case we trigger an interrupt as a result of the mask change | |
2015 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2016 } | |
2013 call(code, opts->do_sync); | 2017 call(code, opts->do_sync); |
2014 } | 2018 } |
2015 } | 2019 } |
2016 } | 2020 } |
2017 | 2021 |
2033 xor_flag(opts, 1, FLAG_N); | 2037 xor_flag(opts, 1, FLAG_N); |
2034 } | 2038 } |
2035 if (inst->src.params.immed & 0x10) { | 2039 if (inst->src.params.immed & 0x10) { |
2036 xor_flag(opts, 1, FLAG_X); | 2040 xor_flag(opts, 1, FLAG_X); |
2037 } | 2041 } |
2038 if (inst->op == M68K_ORI_SR) { | 2042 if (inst->op == M68K_EORI_SR) { |
2039 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2043 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2040 if (inst->src.params.immed & 0x700) { | 2044 if (inst->src.params.immed & 0x700) { |
2045 //set int pending flag in case we trigger an interrupt as a result of the mask change | |
2046 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2041 call(code, opts->do_sync); | 2047 call(code, opts->do_sync); |
2042 } | 2048 } |
2043 } | 2049 } |
2044 } | 2050 } |
2045 | 2051 |
2062 if (inst->op == M68K_MOVE_SR) { | 2068 if (inst->op == M68K_MOVE_SR) { |
2063 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2069 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2064 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2070 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2065 //leave supervisor mode | 2071 //leave supervisor mode |
2066 swap_ssp_usp(opts); | 2072 swap_ssp_usp(opts); |
2073 } | |
2074 if (((src_op->disp >> 8) & 7) < 7) { | |
2075 //set int pending flag in case we trigger an interrupt as a result of the mask change | |
2076 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2067 } | 2077 } |
2068 call(code, opts->do_sync); | 2078 call(code, opts->do_sync); |
2069 } | 2079 } |
2070 cycles(&opts->gen, 12); | 2080 cycles(&opts->gen, 12); |
2071 } else { | 2081 } else { |
2464 } | 2474 } |
2465 } | 2475 } |
2466 } | 2476 } |
2467 shr_ir(code, 8, opts->gen.scratch1, SZ_W); | 2477 shr_ir(code, 8, opts->gen.scratch1, SZ_W); |
2468 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2478 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2479 //set int pending flag in case we trigger an interrupt as a result of the mask change | |
2480 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2469 retn(code); | 2481 retn(code); |
2470 | 2482 |
2471 opts->set_ccr = code->cur; | 2483 opts->set_ccr = code->cur; |
2472 for (int flag = FLAG_C; flag >= FLAG_X; flag--) | 2484 for (int flag = FLAG_C; flag >= FLAG_X; flag--) |
2473 { | 2485 { |
2497 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); | 2509 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
2498 jmp(code, opts->gen.load_context); | 2510 jmp(code, opts->gen.load_context); |
2499 *skip_sync = code->cur - (skip_sync+1); | 2511 *skip_sync = code->cur - (skip_sync+1); |
2500 retn(code); | 2512 retn(code); |
2501 *do_int = code->cur - (do_int+1); | 2513 *do_int = code->cur - (do_int+1); |
2514 //implement 1 instruction latency | |
2515 cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2516 do_int = code->cur + 1; | |
2517 jcc(code, CC_NZ, do_int); | |
2518 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); | |
2519 retn(code); | |
2520 *do_int = code->cur - (do_int + 1); | |
2502 //set target cycle to sync cycle | 2521 //set target cycle to sync cycle |
2503 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D); | 2522 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D); |
2504 //swap USP and SSP if not already in supervisor mode | 2523 //swap USP and SSP if not already in supervisor mode |
2505 check_user_mode_swap_ssp_usp(opts); | 2524 check_user_mode_swap_ssp_usp(opts); |
2506 //save PC | 2525 //save PC |