diff --git a/Musashi/m68k_in.c b/Musashi/m68k_in.c index cfbacf4..5c5a7a1 100644 --- a/Musashi/m68k_in.c +++ b/Musashi/m68k_in.c @@ -9298,7 +9298,7 @@ M68KMAKE_OP(rte, 32, ., .) new_sr = m68ki_pull_16(); new_pc = m68ki_pull_32(); m68ki_fake_pull_16(); /* format word */ - m68ki_fake_pull_16(); /* special status word */ + uint ssw=m68ki_pull_16(); /* special status word */ m68ki_fake_pull_32(); /* fault address */ m68ki_fake_pull_16(); /* unused/reserved */ m68ki_fake_pull_16(); /* data output buffer */ @@ -9314,7 +9314,11 @@ M68KMAKE_OP(rte, 32, ., .) m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); - m68ki_jump(new_pc); + if (ssw&0x8000) { //ReRun flag set - jump over erroneous instruction + m68ki_jump(m68ki_cpu.mmu_tmp_buserror_newpc); + } else { + m68ki_jump(new_pc); + } m68ki_set_sr(new_sr); CPU_INSTR_MODE = INSTRUCTION_YES; CPU_RUN_MODE = RUN_MODE_NORMAL; diff --git a/Musashi/m68kcpu.h b/Musashi/m68kcpu.h index be88bf8..11935ad 100644 --- a/Musashi/m68kcpu.h +++ b/Musashi/m68kcpu.h @@ -1001,6 +1001,15 @@ typedef struct void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */ + //bus error special register support, backported from Mame + uint16 mmu_tmp_fc; /* temporary hack: function code for the mmu (moves) */ + uint16 mmu_tmp_rw; /* temporary hack: read/write (1/0) for the mmu */ + uint8 mmu_tmp_sz; /* temporary hack: size for mmu */ + uint32 mmu_tmp_buserror_newpc; /* pc after the erroneous instruction, for rr */ + + uint16 mmu_tmp_buserror_fc; /* temporary hack: (first) bus error fc */ + uint16 mmu_tmp_buserror_rw; /* temporary hack: (first) bus error rw */ + uint16 mmu_tmp_buserror_sz; /* temporary hack: (first) bus error size` */ } m68ki_cpu_core; @@ -1042,6 +1051,10 @@ extern uint pmmu_translate_addr(uint addr_in); */ static inline uint m68ki_read_imm_16(void) { + m68ki_cpu.mmu_tmp_fc = m68ki_cpu.s_flag | FUNCTION_CODE_USER_PROGRAM; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = 2; + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ @@ -1087,6 +1100,10 @@ static inline uint m68ki_read_imm_32(void) #endif #endif + m68ki_cpu.mmu_tmp_fc = m68ki_cpu.s_flag | FUNCTION_CODE_USER_PROGRAM; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = 4; + #if M68K_EMULATE_PREFETCH uint temp_val; @@ -1127,7 +1144,9 @@ static inline uint m68ki_read_imm_32(void) */ static inline uint m68ki_read_8_fc(uint address, uint fc) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = 1; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU @@ -1139,7 +1158,9 @@ static inline uint m68ki_read_8_fc(uint address, uint fc) } static inline uint m68ki_read_16_fc(uint address, uint fc) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = 2; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ @@ -1152,7 +1173,9 @@ static inline uint m68ki_read_16_fc(uint address, uint fc) } static inline uint m68ki_read_32_fc(uint address, uint fc) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = 4; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ @@ -1166,7 +1189,9 @@ static inline uint m68ki_read_32_fc(uint address, uint fc) static inline void m68ki_write_8_fc(uint address, uint fc, uint value) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 0; + m68ki_cpu.mmu_tmp_sz = 1; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU @@ -1178,7 +1203,9 @@ static inline void m68ki_write_8_fc(uint address, uint fc, uint value) } static inline void m68ki_write_16_fc(uint address, uint fc, uint value) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 0; + m68ki_cpu.mmu_tmp_sz = 2; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ @@ -1191,7 +1218,9 @@ static inline void m68ki_write_16_fc(uint address, uint fc, uint value) } static inline void m68ki_write_32_fc(uint address, uint fc, uint value) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 0; + m68ki_cpu.mmu_tmp_sz = 4; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ @@ -1206,7 +1235,9 @@ static inline void m68ki_write_32_fc(uint address, uint fc, uint value) #if M68K_SIMULATE_PD_WRITES static inline void m68ki_write_32_pd_fc(uint address, uint fc, uint value) { - (void)fc; + m68ki_cpu.mmu_tmp_fc = fc; + m68ki_cpu.mmu_tmp_rw = 0; + m68ki_cpu.mmu_tmp_sz = 4; m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ @@ -1469,6 +1500,7 @@ static inline void m68ki_jump(uint new_pc) static inline void m68ki_jump_vector(uint vector) { + m68ki_set_fc(0x7); //int ack REG_PC = (vector<<2) + REG_VBR; REG_PC = m68ki_read_data_32(REG_PC); m68ki_pc_changed(REG_PC); @@ -1665,6 +1697,9 @@ static inline void m68ki_stack_frame_buserr(uint sr) */ static inline void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) { + int orig_rw = m68ki_cpu.mmu_tmp_buserror_rw; // this gets splatted by the following pushes, so save it now + int orig_fc = m68ki_cpu.mmu_tmp_buserror_fc; + /* VERSION * NUMBER * INTERNAL INFORMATION, 16 WORDS @@ -1700,7 +1735,10 @@ static inline void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) m68ki_push_32(0); /* SPECIAL STATUS WORD */ - m68ki_push_16(0); + m68ki_push_16(orig_fc | + (((orig_fc&3)==1)?(1<<12):0) | + (((orig_fc&3)==2)?(1<<13):0) | + (orig_rw<<8)); /* 1000, VECTOR OFFSET */ m68ki_push_16(0x8000 | (vector<<2)); @@ -1915,6 +1953,9 @@ extern jmp_buf m68ki_bus_error_jmp_buf; static inline void m68ki_exception_bus_error(void) { int i; + m68ki_cpu.mmu_tmp_buserror_fc = m68ki_cpu.mmu_tmp_fc; + m68ki_cpu.mmu_tmp_buserror_rw = m68ki_cpu.mmu_tmp_rw; + m68ki_cpu.mmu_tmp_buserror_sz = m68ki_cpu.mmu_tmp_sz; /* If we were processing a bus error, address error, or reset, * while writing the stack frame, this is a catastrophic failure. @@ -1938,6 +1979,7 @@ static inline void m68ki_exception_bus_error(void) uint sr = m68ki_init_exception(); /* Note: This is implemented for 68010 only! */ + m68ki_cpu.mmu_tmp_buserror_newpc=REG_PC; m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR); m68ki_jump_vector(EXCEPTION_BUS_ERROR);