From 079bec06eb3b4df9e53f952a2e8f1f7f67c61ce9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Oct 2022 03:07:48 +0200 Subject: [PATCH] Added segment limti checks to CPU instruction FFh, fixes #2583. --- src/cpu/x86_ops_call.h | 192 +++++++++++++++++++++++++++++------------ 1 file changed, 136 insertions(+), 56 deletions(-) diff --git a/src/cpu/x86_ops_call.h b/src/cpu/x86_ops_call.h index 1c928a70b..ecd50f107 100644 --- a/src/cpu/x86_ops_call.h +++ b/src/cpu/x86_ops_call.h @@ -162,26 +162,38 @@ static int opFF_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x08: /*DEC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); break; case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } new_pc = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(cpu_state.pc); cpu_state.pc = new_pc; @@ -192,8 +204,10 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; @@ -203,8 +217,10 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } new_pc = geteaw(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -214,8 +230,10 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } #ifdef USE_NEW_DYNAREC old_pc = cpu_state.pc; #else @@ -234,8 +252,10 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -261,26 +281,38 @@ static int opFF_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } seteaw(temp + 1); if (cpu_state.abrt) return 1; setadd16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x08: /*DEC w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } seteaw(temp - 1); if (cpu_state.abrt) return 1; setsub16nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); break; case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } new_pc = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(cpu_state.pc); cpu_state.pc = new_pc; @@ -291,8 +323,10 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = readmemw(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1; @@ -302,8 +336,10 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } new_pc = geteaw(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -313,8 +349,10 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } #ifdef USE_NEW_DYNAREC old_pc = cpu_state.pc; #else @@ -333,8 +371,10 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH w*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1UL); + } temp = geteaw(); if (cpu_state.abrt) return 1; PUSH_W(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -361,26 +401,38 @@ static int opFF_l_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x08: /*DEC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); break; case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = geteal(); if (cpu_state.abrt) return 1; PUSH_L(cpu_state.pc); cpu_state.pc = new_pc; @@ -391,8 +443,10 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; @@ -402,8 +456,10 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = geteal(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -413,8 +469,10 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } #ifdef USE_NEW_DYNAREC old_pc = cpu_state.pc; #else @@ -433,8 +491,10 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); @@ -460,26 +520,38 @@ static int opFF_l_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*INC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } seteal(temp + 1); if (cpu_state.abrt) return 1; setadd32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x08: /*DEC l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; + if (cpu_mod != 3) { + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } seteal(temp - 1); if (cpu_state.abrt) return 1; setsub32nc(temp, 1); CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); break; case 0x10: /*CALL*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = geteal(); if (cpu_state.abrt) return 1; PUSH_L(cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; @@ -490,8 +562,10 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x18: /*CALL far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } new_pc = readmeml(easeg, cpu_state.eaaddr); new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1; @@ -501,8 +575,10 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x20: /*JMP*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } new_pc = geteal(); if (cpu_state.abrt) return 1; cpu_state.pc = new_pc; CPU_BLOCK_END(); @@ -512,8 +588,10 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5UL); + } #ifdef USE_NEW_DYNAREC old_pc = cpu_state.pc; #else @@ -532,8 +610,10 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x30: /*PUSH l*/ - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); + if (cpu_mod != 3) { + SEG_CHECK_READ(cpu_state.ea_seg); if (cpu_state.abrt) return 1; + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3UL); + } temp = geteal(); if (cpu_state.abrt) return 1; PUSH_L(temp); PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1);