From b2121be23f388a760c0ff1985b5aa904906a702c Mon Sep 17 00:00:00 2001 From: shanshe Date: Tue, 13 Apr 2021 10:53:17 +0200 Subject: [PATCH] Bus Error and 68k OPs update (to latest MAME) --- m68k_in.c | 643 ++++++++++++++++++++++++++++++++++++------------------ m68kcpu.c | 6 +- m68kcpu.h | 33 ++- 3 files changed, 455 insertions(+), 227 deletions(-) diff --git a/m68k_in.c b/m68k_in.c index 9283892..ec2614f 100644 --- a/m68k_in.c +++ b/m68k_in.c @@ -947,13 +947,14 @@ M68KMAKE_OP(abcd, 8, rr, .) uint src = DY; uint dst = *r_dst; uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -973,13 +974,14 @@ M68KMAKE_OP(abcd, 8, mm, ax7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -999,13 +1001,14 @@ M68KMAKE_OP(abcd, 8, mm, ay7) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -1025,13 +1028,14 @@ M68KMAKE_OP(abcd, 8, mm, axy7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -1051,13 +1055,14 @@ M68KMAKE_OP(abcd, 8, mm, .) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ + uint corf = 0; if(res > 9) - res += 6; + corf = 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; + FLAG_V = ~res; /* Undefined V behavior */ + res += corf; + FLAG_X = FLAG_C = (res > 0x9f) << 8; if(FLAG_C) res -= 0xa0; @@ -2508,7 +2513,7 @@ M68KMAKE_OP(bfchg, 32, ., .) if((width + offset) > 32) { - mask_byte = MASK_OUT_ABOVE_8(mask_base); + mask_byte = MASK_OUT_ABOVE_8(mask_base) << (8-offset); data_byte = m68ki_read_8(ea+4); FLAG_Z |= (data_byte & mask_byte); m68ki_write_8(ea+4, data_byte ^ mask_byte); @@ -2599,7 +2604,7 @@ M68KMAKE_OP(bfclr, 32, ., .) if((width + offset) > 32) { - mask_byte = MASK_OUT_ABOVE_8(mask_base); + mask_byte = MASK_OUT_ABOVE_8(mask_base) << (8-offset); data_byte = m68ki_read_8(ea+4); FLAG_Z |= (data_byte & mask_byte); m68ki_write_8(ea+4, data_byte & ~mask_byte); @@ -2660,17 +2665,20 @@ M68KMAKE_OP(bfexts, 32, ., .) if(BIT_5(word2)) width = REG_D[width&7]; - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; + if(BIT_B(word2)) { + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } } width = ((width-1) & 31) + 1; - data = m68ki_read_32(ea); + data = (offset+width) < 8 ? (m68ki_read_8(ea) << 24) : + (offset+width) < 16 ? (m68ki_read_16(ea) << 16) : m68ki_read_32(ea); data = MASK_OUT_ABOVE_32(data< 32) @@ -2839,7 +2850,7 @@ M68KMAKE_OP(bfffo, 32, ., .) } width = ((width-1) & 31) + 1; - data = m68ki_read_32(ea); + data = (offset+width) < 16 ? (m68ki_read_16(ea) << 16) : m68ki_read_32(ea); data = MASK_OUT_ABOVE_32(data< 32) @@ -2928,13 +2939,15 @@ M68KMAKE_OP(bfins, 32, ., .) if(BIT_5(word2)) width = REG_D[width&7]; - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; + if(BIT_B(word2)) { + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } } width = ((width-1) & 31) + 1; @@ -2946,11 +2959,18 @@ M68KMAKE_OP(bfins, 32, ., .) FLAG_Z = insert_base; insert_long = insert_base >> offset; - data_long = m68ki_read_32(ea); + data_long = (offset+width) < 8 ? (m68ki_read_8(ea) << 24) : + (offset+width) < 16 ? (m68ki_read_16(ea) << 16) : m68ki_read_32(ea); FLAG_V = VFLAG_CLEAR; FLAG_C = CFLAG_CLEAR; - m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + if((width + offset) < 8) { + m68ki_write_8(ea, ((data_long & ~mask_long) | insert_long) >> 24); + } else if((width + offset) < 16) { + m68ki_write_16(ea, ((data_long & ~mask_long) | insert_long) >> 16); + } else { + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + } if((width + offset) > 32) { @@ -3146,6 +3166,7 @@ M68KMAKE_OP(bftst, 32, ., .) M68KMAKE_OP(bkpt, 0, ., .) { +// TODO: review this... if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) { m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ @@ -3158,8 +3179,9 @@ M68KMAKE_OP(bra, 8, ., .) { m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); +// TODO: review this... +// if(REG_PC == REG_PPC) +// USE_ALL_CYCLES(); } @@ -3169,8 +3191,9 @@ M68KMAKE_OP(bra, 16, ., .) REG_PC -= 2; m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_16(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); +// TODO: review this... +// if(REG_PC == REG_PPC) +// USE_ALL_CYCLES(); } @@ -3182,16 +3205,19 @@ M68KMAKE_OP(bra, 32, ., .) REG_PC -= 4; m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_32(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); +// TODO: review this... +// if(REG_PC == REG_PPC) +// USE_ALL_CYCLES(); return; } else { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); +// TODO: review this... + m68ki_exception_illegal(); +// m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +// m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); +// if(REG_PC == REG_PPC) +// USE_ALL_CYCLES(); } } @@ -3269,9 +3295,11 @@ M68KMAKE_OP(bsr, 32, ., .) } else { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); +// TODO: review this... + m68ki_exception_illegal(); +// m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +// m68ki_push_32(REG_PC); +// m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); } } @@ -3314,7 +3342,7 @@ M68KMAKE_OP(callm, 32, ., .) (void)ea; /* just to avoid an 'unused variable' warning */ M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_illegal(); @@ -3585,17 +3613,25 @@ M68KMAKE_OP(chk2cmp2, 8, ., pcdi) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xff; + uint ea = EA_PCDI_8(); sint lower_bound = m68ki_read_pcrel_8(ea); sint upper_bound = m68ki_read_pcrel_8(ea + 1); - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x80) { + lower_bound = (int32)(int8)lower_bound; + upper_bound = (int32)(int8)upper_bound; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + } + + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3612,16 +3648,24 @@ M68KMAKE_OP(chk2cmp2, 8, ., pcix) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xff; + uint ea = EA_PCIX_8(); sint lower_bound = m68ki_read_pcrel_8(ea); sint upper_bound = m68ki_read_pcrel_8(ea + 1); - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => ||, faster operation short circuits + if (lower_bound & 0x80) { + lower_bound = (int32)(int8)lower_bound; + upper_bound = (int32)(int8)upper_bound; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + } + + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3637,17 +3681,25 @@ M68KMAKE_OP(chk2cmp2, 8, ., .) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xff; + uint ea = M68KMAKE_GET_EA_AY_8; sint lower_bound = (int8)m68ki_read_8(ea); sint upper_bound = (int8)m68ki_read_8(ea + 1); - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x80) { + lower_bound = (int32)(int8)lower_bound; + upper_bound = (int32)(int8)upper_bound; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + } + + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3662,16 +3714,25 @@ M68KMAKE_OP(chk2cmp2, 16, ., pcdi) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xffff; + uint ea = EA_PCDI_16(); sint lower_bound = (int16)m68ki_read_pcrel_16(ea); sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x8000) { + lower_bound = (int32)(int16)lower_bound; + upper_bound = (int32)(int16)upper_bound; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + } + + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3686,16 +3747,25 @@ M68KMAKE_OP(chk2cmp2, 16, ., pcix) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xffff; + uint ea = EA_PCIX_16(); sint lower_bound = (int16)m68ki_read_pcrel_16(ea); sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x8000) { + lower_bound = (int32)(int16)lower_bound; + upper_bound = (int32)(int16)upper_bound; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + } + + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3710,16 +3780,25 @@ M68KMAKE_OP(chk2cmp2, 16, ., .) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + sint compare = REG_DA[(word2 >> 12) & 15]; + if(!BIT_F(word2)) + compare &= 0xffff; + uint ea = M68KMAKE_GET_EA_AY_16; sint lower_bound = (int16)m68ki_read_16(ea); sint upper_bound = (int16)m68ki_read_16(ea + 2); - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x8000) { + lower_bound = (int32)(int16)lower_bound; + upper_bound = (int32)(int16)upper_bound; + + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + } - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); @@ -3733,16 +3812,22 @@ M68KMAKE_OP(chk2cmp2, 32, ., pcdi) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCDI_32(); - sint lower_bound = m68ki_read_pcrel_32(ea); - sint upper_bound = m68ki_read_pcrel_32(ea + 4); + uint32 word2 = OPER_I_16(); + sint64 compare = REG_DA[(word2 >> 12) & 15]; + uint32 ea = EA_PCDI_32(); + sint64 lower_bound = m68ki_read_pcrel_32(ea); + sint64 upper_bound = m68ki_read_pcrel_32(ea + 4); + + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x80000000) { + lower_bound = (int64)(int32)lower_bound; + upper_bound = (int64)(int32)upper_bound; + compare = (int64)(int32)compare; + } - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); return; @@ -3755,16 +3840,22 @@ M68KMAKE_OP(chk2cmp2, 32, ., pcix) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCIX_32(); - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); + uint32 word2 = OPER_I_16(); + sint64 compare = REG_DA[(word2 >> 12) & 15]; + uint32 ea = EA_PCIX_32(); + sint64 lower_bound = m68ki_read_32(ea); + sint64 upper_bound = m68ki_read_32(ea + 4); + + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x80000000) { + lower_bound = (int64)(int32)lower_bound; + upper_bound = (int64)(int32)upper_bound; + compare = (int64)(int32)compare; + } - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); return; @@ -3777,17 +3868,22 @@ M68KMAKE_OP(chk2cmp2, 32, ., .) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { - uint word2 = OPER_I_16(); - // JFF changed the logic. chk2/cmp2 uses signed values, not unsigned - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = M68KMAKE_GET_EA_AY_32; - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); + uint32 word2 = OPER_I_16(); + sint64 compare = REG_DA[(word2 >> 12) & 15]; + uint32 ea = M68KMAKE_GET_EA_AY_32; + sint64 lower_bound = m68ki_read_32(ea); + sint64 upper_bound = m68ki_read_32(ea + 4); + + // for signed compare, the arithmetically smaller value is the lower bound + if (lower_bound & 0x80000000) { + lower_bound = (int64)(int32)lower_bound; + upper_bound = (int64)(int32)upper_bound; + compare = (int64)(int32)compare; + } - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + FLAG_C = (compare >= lower_bound && compare <= upper_bound) ? CFLAG_CLEAR : CFLAG_SET; + FLAG_Z = ((upper_bound == compare) || (lower_bound == compare)) ? 0 : 1; - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - if(COND_CS() && BIT_B(word2)) m68ki_exception_trap(EXCEPTION_CHK); return; @@ -3809,7 +3905,11 @@ M68KMAKE_OP(clr, 8, ., d) M68KMAKE_OP(clr, 8, ., .) { - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); + uint32 ea = M68KMAKE_GET_EA_AY_8; + + if(CPU_TYPE_IS_000(CPU_TYPE)) + m68ki_read_8(ea); /* the 68000 does a dummy read, the value is discarded */ + m68ki_write_8(ea, 0); FLAG_N = NFLAG_CLEAR; FLAG_V = VFLAG_CLEAR; @@ -3831,7 +3931,11 @@ M68KMAKE_OP(clr, 16, ., d) M68KMAKE_OP(clr, 16, ., .) { - m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); + uint32 ea = M68KMAKE_GET_EA_AY_16; + + if(CPU_TYPE_IS_000(CPU_TYPE)) + m68ki_read_16(ea); /* the 68000 does a dummy read, the value is discarded */ + m68ki_write_16(ea, 0); FLAG_N = NFLAG_CLEAR; FLAG_V = VFLAG_CLEAR; @@ -3853,7 +3957,11 @@ M68KMAKE_OP(clr, 32, ., d) M68KMAKE_OP(clr, 32, ., .) { - m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); + uint32 ea = M68KMAKE_GET_EA_AY_32; + + if(CPU_TYPE_IS_000(CPU_TYPE)) + m68ki_read_32(ea); /* the 68000 does a dummy read, the value is discarded */ + m68ki_write_32(ea, 0); FLAG_N = NFLAG_CLEAR; FLAG_V = VFLAG_CLEAR; @@ -4315,7 +4423,7 @@ M68KMAKE_OP(cpbcc, 32, ., .) { M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_1111(); @@ -4328,7 +4436,7 @@ M68KMAKE_OP(cpdbcc, 32, ., .) { M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_1111(); @@ -4337,11 +4445,13 @@ M68KMAKE_OP(cpdbcc, 32, ., .) M68KMAKE_OP(cpgen, 32, ., .) { +// TODO: what's the condition? +// if(HAS_FPU || HAS_PMMU) if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_1111(); @@ -4354,7 +4464,7 @@ M68KMAKE_OP(cpscc, 32, ., .) { M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_1111(); @@ -4367,7 +4477,7 @@ M68KMAKE_OP(cptrapcc, 32, ., .) { M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); // JFF: unsupported, but at least if the trap doesn't occur, app should still work, so at least PC increase is correct REG_PC += 4; return; @@ -4445,12 +4555,12 @@ M68KMAKE_OP(divs, 16, ., d) if(src != 0) { + FLAG_C = CFLAG_CLEAR; if((uint32)*r_dst == 0x80000000 && src == -1) { FLAG_Z = 0; FLAG_N = NFLAG_CLEAR; FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = 0; return; } @@ -4463,7 +4573,6 @@ M68KMAKE_OP(divs, 16, ., d) FLAG_Z = quotient; FLAG_N = NFLAG_16(quotient); FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); return; } @@ -4483,12 +4592,12 @@ M68KMAKE_OP(divs, 16, ., .) if(src != 0) { + FLAG_C = CFLAG_CLEAR; if((uint32)*r_dst == 0x80000000 && src == -1) { FLAG_Z = 0; FLAG_N = NFLAG_CLEAR; FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = 0; return; } @@ -4501,7 +4610,6 @@ M68KMAKE_OP(divs, 16, ., .) FLAG_Z = quotient; FLAG_N = NFLAG_16(quotient); FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); return; } @@ -4519,6 +4627,7 @@ M68KMAKE_OP(divu, 16, ., d) if(src != 0) { + FLAG_C = CFLAG_CLEAR; uint quotient = *r_dst / src; uint remainder = *r_dst % src; @@ -4527,7 +4636,6 @@ M68KMAKE_OP(divu, 16, ., d) FLAG_Z = quotient; FLAG_N = NFLAG_16(quotient); FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); return; } @@ -4545,6 +4653,7 @@ M68KMAKE_OP(divu, 16, ., .) if(src != 0) { + FLAG_C = CFLAG_CLEAR; uint quotient = *r_dst / src; uint remainder = *r_dst % src; @@ -4553,7 +4662,6 @@ M68KMAKE_OP(divu, 16, ., .) FLAG_Z = quotient; FLAG_N = NFLAG_16(quotient); FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); return; } @@ -5241,8 +5349,6 @@ M68KMAKE_OP(jmp, 32, ., .) { m68ki_jump(M68KMAKE_GET_EA_AY_32); m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); } @@ -6920,7 +7026,7 @@ M68KMAKE_OP(movec, 32, rc, .) /* 68030 can write all bits except 5-7, 040 can write all */ if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) { - REG_CACR = REG_DA[(word2 >> 12) & 15]; + REG_CACR = REG_DA[(word2 >> 12) & 15] & 0xfffffffe; // Old I cache bit not working on 040 } else if (CPU_TYPE_IS_030_PLUS(CPU_TYPE)) { @@ -6930,6 +7036,10 @@ M68KMAKE_OP(movec, 32, rc, .) { REG_CACR = REG_DA[(word2 >> 12) & 15] & 0x0f; } + + if (REG_CACR & (M68K_CACR_CI | M68K_CACR_CEI)) { + m68ki_ic_clear(); + } return; } m68ki_exception_illegal(); @@ -7767,19 +7877,19 @@ M68KMAKE_OP(mull, 32, ., .) M68KMAKE_OP(nbcd, 8, ., d) { uint* r_dst = &DY; - uint dst = *r_dst; - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = - dst - XFLAG_AS_1(); - if(res != 0x9a) + if(res != 0) { - FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = res; /* Undefined V behavior */ - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; + if(((res|dst) & 0x0f) == 0) + res = (res & 0xf0) + 6; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res + 0x9a); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; @@ -7801,18 +7911,18 @@ M68KMAKE_OP(nbcd, 8, ., .) { uint ea = M68KMAKE_GET_EA_AY_8; uint dst = m68ki_read_8(ea); - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + uint res = - dst - XFLAG_AS_1(); - if(res != 0x9a) + if(res != 0) { - FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = res; /* Undefined V behavior */ - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; + if(((res|dst) & 0x0f) == 0) + res = (res & 0xf0) + 6; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res + 0x9a); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); @@ -8334,7 +8444,7 @@ M68KMAKE_OP(pack, 16, mm, ax7) ea_src = EA_AY_PD_8(); src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + m68ki_write_8(EA_A7_PD_8(), ((src >> 8) & 0x000f) | ((src<<4) & 0x00f0)); return; } m68ki_exception_illegal(); @@ -8349,7 +8459,7 @@ M68KMAKE_OP(pack, 16, mm, ay7) uint ea_src = EA_A7_PD_8(); uint src = m68ki_read_8(ea_src); ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + src = (src | (m68ki_read_8(ea_src) << 8)) + OPER_I_16(); m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); return; @@ -8365,7 +8475,7 @@ M68KMAKE_OP(pack, 16, mm, axy7) uint ea_src = EA_A7_PD_8(); uint src = m68ki_read_8(ea_src); ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + src = (src | (m68ki_read_8(ea_src) << 8)) + OPER_I_16(); m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); return; @@ -8382,7 +8492,7 @@ M68KMAKE_OP(pack, 16, mm, .) uint ea_src = EA_AY_PD_8(); uint src = m68ki_read_8(ea_src); ea_src = EA_AY_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + src = (src | (m68ki_read_8(ea_src) << 8)) + OPER_I_16(); m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); return; @@ -9273,26 +9383,23 @@ 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 */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + m68ki_fake_pull_16(); /* special status */ m68ki_fake_pull_32(); /* fault address */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data output buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data input buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* instruction input buffer */ - m68ki_fake_pull_32(); /* internal information, 16 words */ - m68ki_fake_pull_32(); /* (actually, we use 8 DWORDs) */ + m68ki_fake_pull_32(); /* reserved and data output buffer */ + m68ki_fake_pull_32(); /* reserved and data input buffer */ + m68ki_fake_pull_32(); /* reserved and instruction input buffer */ + m68ki_fake_pull_32(); /* 8 dwords of CPU specific undocumented data */ + m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); m68ki_fake_pull_32(); - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; return; } CPU_INSTR_MODE = INSTRUCTION_YES; @@ -9327,6 +9434,84 @@ rte_loop: new_pc = m68ki_pull_32(); m68ki_fake_pull_16(); /* format word */ m68ki_fake_pull_32(); /* address */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + case 7: /* 68040 access error */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* $06: format word */ + m68ki_fake_pull_32(); /* $08: effective address */ + m68ki_fake_pull_16(); /* $0c: special status word */ + m68ki_fake_pull_16(); /* $0e: wb3s */ + m68ki_fake_pull_16(); /* $10: wb2s */ + m68ki_fake_pull_16(); /* $12: wb1s */ + m68ki_fake_pull_32(); /* $14: data fault address */ + m68ki_fake_pull_32(); /* $18: wb3a */ + m68ki_fake_pull_32(); /* $1c: wb3d */ + m68ki_fake_pull_32(); /* $20: wb2a */ + m68ki_fake_pull_32(); /* $24: wb2d */ + m68ki_fake_pull_32(); /* $28: wb1a */ + m68ki_fake_pull_32(); /* $2c: wb1d/pd0 */ + m68ki_fake_pull_32(); /* $30: pd1 */ + m68ki_fake_pull_32(); /* $34: pd2 */ + m68ki_fake_pull_32(); /* $38: pd3 */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + + case 0x0a: /* Bus Error at instruction boundary */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* $06: format word */ + m68ki_fake_pull_16(); /* $08: internal register */ + m68ki_fake_pull_16(); /* $0a: special status word */ + m68ki_fake_pull_16(); /* $0c: instruction pipe stage c */ + m68ki_fake_pull_16(); /* $0e: instruction pipe stage b */ + m68ki_fake_pull_32(); /* $10: data fault address */ + m68ki_fake_pull_32(); /* $14: internal registers */ + m68ki_fake_pull_32(); /* $18: data output buffer */ + m68ki_fake_pull_32(); /* $1c: internal registers */ + + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + + case 0x0b: /* Bus Error - Instruction Execution in Progress */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* $06: format word */ + m68ki_fake_pull_16(); /* $08: internal register */ + m68ki_fake_pull_16(); /* $0a: special status word */ + m68ki_fake_pull_16(); /* $0c: instruction pipe stage c */ + m68ki_fake_pull_16(); /* $0e: instruction pipe stage b */ + m68ki_fake_pull_32(); /* $10: data fault address */ + m68ki_fake_pull_32(); /* $14: internal registers */ + m68ki_fake_pull_32(); /* $18: data output buffer */ + m68ki_fake_pull_32(); /* $1c: internal registers */ + m68ki_fake_pull_32(); /* $20: */ + m68ki_fake_pull_32(); /* $24: stage B address */ + m68ki_fake_pull_32(); /* $28: */ + m68ki_fake_pull_32(); /* $2c: data input buffer */ + m68ki_fake_pull_32(); /* $30: */ + m68ki_fake_pull_16(); /* $34: */ + m68ki_fake_pull_16(); /* $36: version #, internal information */ + m68ki_fake_pull_32(); /* $38: */ + m68ki_fake_pull_32(); /* $3c: */ + m68ki_fake_pull_32(); /* $40: */ + m68ki_fake_pull_32(); /* $44: */ + m68ki_fake_pull_32(); /* $48: */ + m68ki_fake_pull_32(); /* $4c: */ + m68ki_fake_pull_32(); /* $50: */ + m68ki_fake_pull_32(); /* $54: */ + m68ki_fake_pull_32(); /* $58: */ + m68ki_jump(new_pc); m68ki_set_sr(new_sr); CPU_INSTR_MODE = INSTRUCTION_YES; @@ -9350,7 +9535,7 @@ M68KMAKE_OP(rtm, 32, ., .) m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + m68ki_disassemble_quick(ADDRESS_68K(REG_PC - 2),CPU_TYPE))); return; } m68ki_exception_illegal(); @@ -9378,19 +9563,23 @@ M68KMAKE_OP(sbcd, 8, rr, .) uint src = DY; uint dst = *r_dst; uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + } else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; + else + FLAG_N = FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; @@ -9404,19 +9593,23 @@ M68KMAKE_OP(sbcd, 8, mm, ax7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + } else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; + else + FLAG_N = FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; @@ -9430,19 +9623,23 @@ M68KMAKE_OP(sbcd, 8, mm, ay7) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + } else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; + else + FLAG_N = FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; @@ -9456,19 +9653,23 @@ M68KMAKE_OP(sbcd, 8, mm, axy7) uint ea = EA_A7_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + } else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; + else + FLAG_N = FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; @@ -9482,19 +9683,23 @@ M68KMAKE_OP(sbcd, 8, mm, .) uint ea = EA_AX_PD_8(); uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + uint corf = 0; - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; + if(res > 0xf) + corf = 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) + FLAG_V = res; /* Undefined V behavior */ + if(res > 0xff) { res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + } else if(res < corf) + FLAG_X = FLAG_C = CFLAG_SET; + else + FLAG_N = FLAG_X = FLAG_C = 0; - res = MASK_OUT_ABOVE_8(res); + res = MASK_OUT_ABOVE_8(res - corf); - FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_V &= ~res; /* Undefined V behavior part II */ FLAG_N = NFLAG_8(res); /* Undefined N behavior */ FLAG_Z |= res; @@ -10227,6 +10432,7 @@ M68KMAKE_OP(trapt, 16, ., .) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { + // TODO: review this... as mame is not using it... REG_PC += 2; // JFF else stackframe & return addresses are incorrect m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ return; @@ -10239,6 +10445,7 @@ M68KMAKE_OP(trapt, 32, ., .) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { + // TODO: review this... as mame is not using it... REG_PC += 4; // JFF else stackframe & return addresses are incorrect m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ return; @@ -10295,6 +10502,7 @@ M68KMAKE_OP(trapcc, 16, ., .) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { + // TODO: review this... as mame is not using it... REG_PC += 2; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ if(M68KMAKE_CC) { @@ -10312,6 +10520,7 @@ M68KMAKE_OP(trapcc, 32, ., .) { if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) { + // TODO: review this... as mame is not using it... REG_PC += 4; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ if(M68KMAKE_CC) { @@ -10616,9 +10825,9 @@ M68KMAKE_OP(unpk, 16, mm, ax7) src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); m68ki_write_8(ea_dst, src & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); return; } m68ki_exception_illegal(); @@ -10635,9 +10844,9 @@ M68KMAKE_OP(unpk, 16, mm, ay7) src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); m68ki_write_8(ea_dst, src & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); return; } m68ki_exception_illegal(); @@ -10653,9 +10862,9 @@ M68KMAKE_OP(unpk, 16, mm, axy7) src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); m68ki_write_8(ea_dst, src & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); return; } m68ki_exception_illegal(); @@ -10672,9 +10881,9 @@ M68KMAKE_OP(unpk, 16, mm, .) src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); m68ki_write_8(ea_dst, src & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); return; } m68ki_exception_illegal(); diff --git a/m68kcpu.c b/m68kcpu.c index 4cc48c5..74f83c8 100644 --- a/m68kcpu.c +++ b/m68kcpu.c @@ -990,9 +990,6 @@ int m68k_execute(int num_cycles) /* Main loop. Keep going until we run out of clock cycles */ do { -#ifdef M68K_BUSERR_THING - int i; -#endif /* Set tracing accodring to T1. (T0 is done inside instruction) */ m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ @@ -1006,8 +1003,9 @@ int m68k_execute(int num_cycles) REG_PPC = REG_PC; /* Record previous D/A register state (in case of bus error) */ +//#define M68K_BUSERR_THING #ifdef M68K_BUSERR_THING - for (i = 15; i >= 0; i--){ + for (int i = 15; i >= 0; i--){ REG_DA_SAVE[i] = REG_DA[i]; } #endif diff --git a/m68kcpu.h b/m68kcpu.h index 923f143..680aa71 100644 --- a/m68kcpu.h +++ b/m68kcpu.h @@ -43,6 +43,7 @@ extern "C" { #include #include +#include /* ======================================================================== */ /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ @@ -667,6 +668,7 @@ extern jmp_buf m68ki_aerr_trap; longjmp(m68ki_aerr_trap, 1); \ } #endif + #define m68ki_bus_error(ADDR,WRITE_MODE) m68ki_aerr_address=ADDR;m68ki_aerr_write_mode=WRITE_MODE;m68ki_exception_bus_error() #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \ if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \ @@ -682,12 +684,12 @@ extern jmp_buf m68ki_aerr_trap; /* Logging */ #if M68K_LOG_ENABLE #include - extern FILE* M68K_LOG_FILEHANDLE +// extern FILE* M68K_LOG_FILEHANDLE; extern const char *const m68ki_cpu_names[]; - #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A + #define M68K_DO_LOG(A) do{printf("*************");printf A;}while(0) //if(M68K_LOG_FILEHANDLE) fprintf A #if M68K_LOG_1010_1111 - #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A + #define M68K_DO_LOG_EMU(A) printf A //if(M68K_LOG_FILEHANDLE) fprintf A #else #define M68K_DO_LOG_EMU(A) #endif @@ -2279,13 +2281,32 @@ static inline void m68ki_exception_address_error(void) CPU_STOPPED = STOP_LEVEL_HALT; return; } - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - /* Note: This is implemented for 68000 only! */ - m68ki_stack_frame_buserr(sr); + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; + + if (CPU_TYPE_IS_000(CPU_TYPE)) + { + /* Note: This is implemented for 68000 only! */ + m68ki_stack_frame_buserr(sr); + } + else if (CPU_TYPE_IS_010(CPU_TYPE)) + { + /* only the 68010 throws this unique type-1000 frame */ + m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR); + } + else if (m68ki_cpu.mmu_tmp_buserror_address == REG_PPC) + { + m68ki_stack_frame_1010(sr, EXCEPTION_BUS_ERROR, REG_PPC, m68ki_cpu.mmu_tmp_buserror_address); + } + else + { + m68ki_stack_frame_1011(sr, EXCEPTION_BUS_ERROR, REG_PPC, m68ki_cpu.mmu_tmp_buserror_address); + } m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR); + m68ki_cpu.run_mode = RUN_MODE_BERR_AERR_RESET; + /* Use up some clock cycles. Note that we don't need to undo the instruction's cycles here as we've longjmp:ed directly from the instruction handler without passing the part of the excecute loop -- 2.39.2