From d23c2a613df47d68d9ec3988f4eaf4c804501b6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 24 May 2024 00:10:04 +0200 Subject: [PATCH 1/4] 286/386 interpreter: reinstall VM_FLAG check on accessin the debug registers. --- src/cpu/x86_ops_mov_ctrl_2386.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h index cae6c9957b9..6bb00d8dad6 100644 --- a/src/cpu/x86_ops_mov_ctrl_2386.h +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -82,7 +82,7 @@ opMOV_r_CRx_a32(uint32_t fetchdat) static int opMOV_r_DRx_a16(uint32_t fetchdat) { - if ((CPL > 0) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } @@ -124,7 +124,7 @@ opMOV_r_DRx_a16(uint32_t fetchdat) static int opMOV_r_DRx_a32(uint32_t fetchdat) { - if ((CPL > 0) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } @@ -282,7 +282,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) static int opMOV_DRx_r_a16(uint32_t fetchdat) { - if ((CPL > 0) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } @@ -325,7 +325,7 @@ opMOV_DRx_r_a16(uint32_t fetchdat) static int opMOV_DRx_r_a32(uint32_t fetchdat) { - if ((CPL > 0) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } From a07ffdecab9ecc742d508b76548dc5c43c218ee0 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Mon, 15 Jan 2024 06:22:38 +0500 Subject: [PATCH 2/4] Restore the debug register operation on 486+ But put it behind a compile-time option due to performance hits Also add the DE flag to CPUID on supported CPUs --- CMakeLists.txt | 1 + src/CMakeLists.txt | 4 + src/cpu/386_common.h | 109 +++++++++++++++++++++++++++ src/cpu/386_dynarec.c | 68 ++++++++++++++++- src/cpu/386_dynarec_ops.c | 1 + src/cpu/cpu.c | 52 +++++++------ src/cpu/x86.c | 4 + src/cpu/x86_ops_flag.h | 12 +++ src/cpu/x86_ops_mov_ctrl.h | 147 +++++++++++++++++++++++++++++++++++-- src/cpu/x86_ops_ret.h | 12 +++ src/io.c | 76 +++++++++++++++++++ src/mem/mem.c | 82 +++++++++++++++++++-- 12 files changed, 531 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0066e04a75..fa1d02a1519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ option(MINITRACE "Enable Chrome tracing using the modified minitrace library" option(GDBSTUB "Enable GDB stub server for debugging" OFF) option(DEV_BRANCH "Development branch" OFF) option(DISCORD "Discord Rich Presence support" ON) +option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF) if(WIN32) set(QT ON) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6cfaef89cb9..66fe7082170 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -57,6 +57,10 @@ if(DISCORD) target_sources(86Box PRIVATE discord.c) endif() +if(DEBUGREGS486) + add_compile_definitions(USE_DEBUG_REGS_486) +endif() + if(VNC) find_package(LibVNCServer) if(LibVNCServer_FOUND) diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index a98a3e93051..6ef65771d4e 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -49,6 +49,82 @@ # define do_mmut_wb(s, a, b) do_mmutranslate_2386((s) + (a), b, 1, 1) # define do_mmut_ww(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 1) # define do_mmut_wl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 1) +#elif defined(USE_DEBUG_REGS_486) +# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) +# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) +# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) + +# define writememb_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + writemembl_no_mmut((s) + (a), b, v); \ + else \ + *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememw_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + writememwl_no_mmut((s) + (a), b, v); \ + else \ + *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememl_n(s, a, b, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + writememll_no_mmut((s) + (a), b, v); \ + else \ + *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememb(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + writemembl((s) + (a), v); \ + else \ + *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememw(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + writememwl((s) + (a), v); \ + else \ + *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememl(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + writememll((s) + (a), v); \ + else \ + *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v +# define writememq(s, a, v) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7) || (dr[7] & 0xFF)) \ + writememql((s) + (a), v); \ + else \ + *(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v + +# define do_mmut_rb(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 1, 0) +# define do_mmut_rw(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 2, 0) +# define do_mmut_rl(s, a, b) \ + if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 4, 0) +# define do_mmut_rb2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 1, 0) +# define do_mmut_rw2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 2, 0) +# define do_mmut_rl2(s, a, b) \ + old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \ + if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 4, 0) + +# define do_mmut_wb(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 1, 1) +# define do_mmut_ww(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 2, 1) +# define do_mmut_wl(s, a, b) \ + if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \ + do_mmutranslate((s) + (a), b, 4, 1) #else # define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a)))) # define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a)))) @@ -263,6 +339,11 @@ fastreadb(uint32_t a) { uint8_t *t; +# ifdef USE_DEBUG_REGS_486 + read_type = 1; + mem_debug_check_addr(a, read_type); + read_type = 4; +# endif if ((a >> 12) == pccache) # if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) return *((uint8_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL))); @@ -286,6 +367,12 @@ fastreadw(uint32_t a) { uint8_t *t; uint16_t val; +# ifdef USE_DEBUG_REGS_486 + read_type = 1; + mem_debug_check_addr(a, read_type); + mem_debug_check_addr(a + 1, read_type); + read_type = 4; +# endif if ((a & 0xFFF) > 0xFFE) { val = fastreadb(a); val |= (fastreadb(a + 1) << 8); @@ -315,6 +402,14 @@ fastreadl(uint32_t a) { uint8_t *t; uint32_t val; +# ifdef USE_DEBUG_REGS_486 + int i; + read_type = 1; + for (i = 0; i < 4; i++) { + mem_debug_check_addr(a + i, read_type); + } + read_type = 4; +# endif if ((a & 0xFFF) < 0xFFD) { if ((a >> 12) != pccache) { t = getpccache(a); @@ -402,6 +497,12 @@ fastreadw_fetch(uint32_t a) { uint8_t *t; uint16_t val; +# ifdef USE_DEBUG_REGS_486 + read_type = 1; + mem_debug_check_addr(a, read_type); + mem_debug_check_addr(a + 1, read_type); + read_type = 4; +# endif if ((a & 0xFFF) > 0xFFE) { val = fastreadb(a); if (opcode_length[val & 0xff] > 1) @@ -432,6 +533,14 @@ fastreadl_fetch(uint32_t a) { uint8_t *t; uint32_t val; +# ifdef USE_DEBUG_REGS_486 + int i; + read_type = 1; + for (i = 0; i < 4; i++) { + mem_debug_check_addr(a + i, read_type); + } + read_type = 4; +# endif if ((a & 0xFFF) < 0xFFD) { if ((a >> 12) != pccache) { t = getpccache(a); diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index c96e3420d4e..77914a2a533 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -28,6 +28,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> +#include <86box/plat_fallthrough.h> #include <86box/gdbstub.h> #ifdef USE_DYNAREC # include "codegen.h" @@ -224,7 +225,11 @@ fetch_ea_16_long(uint32_t rmdat) #include "386_ops.h" -#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) +#ifdef USE_DEBUG_REGS_486 +# define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG) && !(dr[7] & 0xFF)) +#else +# define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) +#endif #ifdef USE_DYNAREC int32_t cycles_main = 0; @@ -269,7 +274,11 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; +# ifdef USE_DEBUG_REGS_486 + if (trap & 2) { +# else if (trap == 2) { +# endif /* Handle the T bit in the new TSS first. */ CPU_BLOCK_END(); goto block_ended; @@ -286,6 +295,13 @@ exec386_dynarec_int(void) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; +# ifdef USE_DEBUG_REGS_486 + if (UNLIKELY(cpu_386_check_instruction_fault())) { + x86gen(); + goto block_ended; + } +# endif + fetchdat = fastreadl_fetch(cs + cpu_state.pc); # ifdef ENABLE_386_DYNAREC_LOG if (in_smm) @@ -296,9 +312,16 @@ exec386_dynarec_int(void) opcode = fetchdat & 0xFF; fetchdat >>= 8; +# ifdef USE_DEBUG_REGS_486 + trap |= !!(cpu_state.flags & T_FLAG); +# else trap = cpu_state.flags & T_FLAG; +# endif cpu_state.pc++; +# ifdef USE_DEBUG_REGS_486 + cpu_state.eflags &= ~(RF_FLAG); +# endif x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); } @@ -307,6 +330,16 @@ exec386_dynarec_int(void) cpu_state.pc &= 0xffff; # endif +# ifdef USE_DEBUG_REGS_486 + if (!cpu_state.abrt) { + if (!rf_flag_no_clear) { + cpu_state.eflags &= ~RF_FLAG; + } + + rf_flag_no_clear = 0; + } +# endif + if (((cs + cpu_state.pc) >> 12) != pccache) CPU_BLOCK_END(); @@ -330,7 +363,14 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && trap) { +# ifdef USE_DEBUG_REGS_486 + //pclog("Debug trap 0x%X\n", trap); + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; +# else dr[6] |= (trap == 2) ? 0x8000 : 0x4000; +# endif + trap = 0; # ifndef USE_NEW_DYNAREC oldcs = CS; @@ -842,6 +882,13 @@ exec386(int32_t cycs) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; +#ifdef USE_DEBUG_REGS_486 + if (UNLIKELY(cpu_386_check_instruction_fault())) { + x86gen(); + goto block_ended; + } +#endif + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (!cpu_state.abrt) { @@ -851,9 +898,16 @@ exec386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; +#ifdef USE_DEBUG_REGS_486 + trap |= !!(cpu_state.flags & T_FLAG); +#else trap = cpu_state.flags & T_FLAG; +#endif cpu_state.pc++; +#ifdef USE_DEBUG_REGS_486 + cpu_state.eflags &= ~(RF_FLAG); +#endif x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); if (x86_was_reset) break; @@ -871,6 +925,9 @@ exec386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; +#ifdef USE_DEBUG_REGS_486 +block_ended: +#endif if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; @@ -895,12 +952,21 @@ exec386(int32_t cycs) } } else if (trap) { flags_rebuild(); +#ifdef USE_DEBUG_REGS_486 + if (trap & 1) + dr[6] |= 0x4000; + if (trap & 2) + dr[6] |= 0x8000; +#endif + trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; +#ifndef USE_DEBUG_REGS_486 dr[6] |= 0x4000; +#endif x86_int(1); } diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index 77b72ef5990..066b00dd691 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -24,6 +24,7 @@ #include <86box/gdbstub.h> #include "codegen.h" #include <86box/plat_unused.h> +#include <86box/plat_fallthrough.h> #define CPU_BLOCK_END() cpu_block_end = 1 diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 0f83a5e4b3e..b812a24f949 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -81,6 +81,12 @@ enum { #define CPUID_3DNOWE (1UL << 30UL) /* Extended 3DNow! instructions */ #define CPUID_3DNOW (1UL << 31UL) /* 3DNow! instructions */ +/* Remove the Debugging Extensions CPUID flag if not compiled + with debug register support for 486 and later CPUs. */ +#ifndef USE_DEBUG_REGS_486 +# define CPUID_DE 0 +#endif + /* Make sure this is as low as possible. */ cpu_state_t cpu_state; fpu_state_t fpu_state; @@ -1973,7 +1979,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) @@ -1999,7 +2005,7 @@ cpu_CPUID(void) case 1: EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) @@ -2010,7 +2016,7 @@ cpu_CPUID(void) break; case 0x80000001: EAX = CPUID; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 9)) @@ -2048,7 +2054,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; if (cpu_s->cpu_type != CPU_P24T) EDX |= CPUID_MCE; } else @@ -2065,7 +2071,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE; } else EAX = EBX = ECX = EDX = 0; break; @@ -2081,7 +2087,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; break; case 0x80000000: EAX = 0x80000005; @@ -2090,7 +2096,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; break; case 0x80000002: /* Processor name string */ EAX = 0x2D444D41; /* AMD-K5(tm) Proce */ @@ -2126,7 +2132,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; break; case 0x80000000: EAX = 0x80000005; @@ -2135,7 +2141,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; break; case 0x80000002: /* Processor name string */ EAX = 0x2D444D41; /* AMD-K6tm w/ mult */ @@ -2183,7 +2189,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; if (cpu_s->cpu_type == CPU_K6_2C) EDX |= CPUID_PGE; break; @@ -2194,7 +2200,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_3DNOW; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_3DNOW; if (cpu_s->cpu_type == CPU_K6_2C) EDX |= CPUID_PGE; break; @@ -2233,7 +2239,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000006; @@ -2242,7 +2248,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */ @@ -2284,7 +2290,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000007; @@ -2293,7 +2299,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm)-III P */ @@ -2339,7 +2345,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; } else EAX = EBX = ECX = EDX = 0; break; @@ -2382,7 +2388,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else EAX = EBX = ECX = EDX = 0; break; @@ -2396,7 +2402,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; } else EAX = EBX = ECX = EDX = 0; break; @@ -2411,7 +2417,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries @@ -2434,7 +2440,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV; } else if (EAX == 2) { EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries @@ -2457,7 +2463,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; } else if (EAX == 2) { EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries @@ -2496,7 +2502,7 @@ cpu_CPUID(void) case 1: EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 7)) @@ -2507,7 +2513,7 @@ cpu_CPUID(void) break; case 0x80000001: EAX = CPUID; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; + EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; if (msr.fcr & (1 << 7)) diff --git a/src/cpu/x86.c b/src/cpu/x86.c index cf2867182a7..32b274f0631 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -279,7 +279,11 @@ reset_common(int hard) cr4 = 0; cpu_state.eflags = 0; cgate32 = 0; +#ifdef USE_DEBUG_REGS_486 + if (is386) { +#else if (is386 && !is486) { +#endif for (uint8_t i = 0; i < 4; i++) dr[i] = 0x00000000; dr[6] = 0xffff1ff0; diff --git a/src/cpu/x86_ops_flag.h b/src/cpu/x86_ops_flag.h index f08b30fceab..019472aa039 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu/x86_ops_flag.h @@ -178,6 +178,9 @@ opPOPF_186(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -211,6 +214,9 @@ opPOPF_286(uint32_t fetchdat) else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; flags_extract(); +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -264,6 +270,9 @@ opPOPF(uint32_t fetchdat) cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; } flags_extract(); +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); @@ -307,6 +316,9 @@ opPOPFD(uint32_t fetchdat) cpu_state.eflags = (templ >> 16) & 3; flags_extract(); +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index b0c841f83f4..5d6e44e34bd 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -82,12 +82,43 @@ opMOV_r_CRx_a32(uint32_t fetchdat) static int opMOV_r_DRx_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } +#ifdef USE_DEBUG_REGS_486 + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } +#endif fetch_ea_16(fetchdat); - cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); return 0; @@ -95,12 +126,43 @@ opMOV_r_DRx_a16(uint32_t fetchdat) static int opMOV_r_DRx_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } +#ifdef USE_DEBUG_REGS_486 + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } +#endif fetch_ea_32(fetchdat); - cpu_state.regs[cpu_rm].l = dr[cpu_reg] | (cpu_reg == 6 ? 0xffff0ff0u : 0); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); return 0; @@ -224,27 +286,96 @@ opMOV_CRx_r_a32(uint32_t fetchdat) static int opMOV_DRx_r_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } +#ifdef USE_DEBUG_REGS_486 + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + x86gen(); + return 1; + } +#endif fetch_ea_16(fetchdat); - dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); +#ifdef USE_DEBUG_REGS_486 + CPU_BLOCK_END(); +#endif return 0; } static int opMOV_DRx_r_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + if (((CPL > 0) || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { x86gpf(NULL, 0); return 1; } +#ifdef USE_DEBUG_REGS_486 + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } +#endif fetch_ea_16(fetchdat); - dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } CLOCK_CYCLES(6); PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); +#ifdef USE_DEBUG_REGS_486 + CPU_BLOCK_END(); +#endif return 0; } diff --git a/src/cpu/x86_ops_ret.h b/src/cpu/x86_ops_ret.h index 0d9a6370bf3..d30d4eb8ffa 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu/x86_ops_ret.h @@ -135,6 +135,9 @@ opIRET_186(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -175,6 +178,9 @@ opIRET_286(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -243,6 +249,9 @@ opIRET(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); @@ -285,6 +294,9 @@ opIRETD(uint32_t fetchdat) } flags_extract(); nmi_enable = 1; +#ifdef USE_DEBUG_REGS_486 + rf_flag_no_clear = 1; +#endif CPU_BLOCK_END(); PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); diff --git a/src/io.c b/src/io.c index 0e68049c36f..fd87089d0a8 100644 --- a/src/io.c +++ b/src/io.c @@ -279,6 +279,58 @@ io_handler_interleaved(int set, uint16_t base, int size, io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 2); } +#ifdef USE_DEBUG_REGS_486 +extern int trap; +/* Set trap for I/O address breakpoints. */ +void +io_debug_check_addr(uint16_t addr) +{ + int i = 0; + int set_trap = 0; + + if (!(dr[7] & 0xFF)) + return; + + if (!(cr4 & 0x8)) + return; /* No I/O debug trap. */ + + for (i = 0; i < 4; i++) { + uint16_t dr_addr = dr[i] & 0xFFFF; + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))); + int len_type_pair = ((dr[7] >> 16) & (0xF << (4 * i))) >> (4 * i); + if (!breakpoint_enabled) + continue; + if ((len_type_pair & 3) != 2) + continue; + + switch ((len_type_pair >> 2) & 3) + { + case 0x00: + if (dr_addr == addr) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x01: + if ((dr_addr & ~1) == addr || ((dr_addr & ~1) + 1) == (addr + 1)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + case 0x03: + dr_addr &= ~3; + if (addr >= dr_addr && addr < (dr_addr + 4)) { + set_trap = 1; + dr[6] |= (1 << i); + } + break; + } + } + if (set_trap) + trap |= 4; +} +#endif + uint8_t inb(uint16_t port) { @@ -290,6 +342,10 @@ inb(uint16_t port) int qfound = 0; #endif +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_read(port, NULL); found = 1; @@ -350,6 +406,10 @@ outb(uint16_t port, uint8_t val) int qfound = 0; #endif +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_write(port, val, NULL); found = 1; @@ -402,6 +462,10 @@ inw(uint16_t port) #endif uint8_t ret8[2]; +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readw(port, NULL); found = 2; @@ -474,6 +538,10 @@ outw(uint16_t port, uint16_t val) int qfound = 0; #endif +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writew(port, val, NULL); found = 2; @@ -542,6 +610,10 @@ inl(uint16_t port) int qfound = 0; #endif +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { ret = pci_readl(port, NULL); found = 4; @@ -646,6 +718,10 @@ outl(uint16_t port, uint32_t val) #endif int i = 0; +#ifdef USE_DEBUG_REGS_486 + io_debug_check_addr(port); +#endif + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { pci_writel(port, val, NULL); found = 4; diff --git a/src/mem/mem.c b/src/mem/mem.c index 1d373dafbef..be097b5f3d0 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -164,6 +164,46 @@ mem_log(const char *fmt, ...) # define mem_log(fmt, ...) #endif +#ifdef USE_DEBUG_REGS_486 +/* As below, 1 = exec, 4 = read. */ +int read_type = 4; + +/* Set trap for data address breakpoints - 1 = exec, 2 = write, 4 = read. */ +void +mem_debug_check_addr(uint32_t addr, int flags) +{ + uint32_t bp_addr; + uint32_t bp_mask; + uint32_t len_type_pair; + int bp_enabled; + uint8_t match_flags[4] = { 0, 2, 0, 6 }; + + if (cpu_state.abrt || ((flags == 1) && (cpu_state.eflags & RF_FLAG))) + return; + + if (dr[7] & 0x000000ff) for (uint8_t i = 0; i < 4; i++) { + bp_addr = dr[i]; + bp_enabled = (dr[7] >> (i << 1)) & 0x03; + len_type_pair = (dr[7] >> (16 + (i << 2))) & 0x0f; + bp_mask = ~((len_type_pair >> 2) & 0x03); + + if ((flags & match_flags[len_type_pair & 0x03]) && ((bp_addr & bp_mask) == (addr & bp_mask))) { + /* + From the Intel i386 documemntation: + + (Note that the processor sets Bn regardless of whether Gn or + Ln is set. If more than one breakpoint condition occurs at one time and if + the breakpoint trap occurs due to an enabled condition other than n, Bn may + be set, even though neither Gn nor Ln is set.) + */ + dr[6] |= (1 << i); + if (bp_enabled) + trap |= (read_type == 1) ? 8 : 4; + } + } +} +#endif + int mem_addr_is_ram(uint32_t addr) { @@ -793,6 +833,9 @@ readmembl(uint32_t addr) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr, read_type); +#endif addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -822,6 +865,9 @@ writemembl(uint32_t addr, uint8_t val) uint64_t a; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr, 2); +#endif addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -908,6 +954,10 @@ readmemwl(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr, read_type); + mem_debug_check_addr(addr + 1, read_type); +#endif GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -966,6 +1016,10 @@ writememwl(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr, 2); + mem_debug_check_addr(addr + 1, 2); +#endif GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -1142,8 +1196,12 @@ readmemll(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr + i, read_type); +#endif + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; @@ -1216,8 +1274,12 @@ writememll(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr + i, 2); +#endif + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; @@ -1420,8 +1482,12 @@ readmemql(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr + i, read_type); +#endif + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -1486,8 +1552,12 @@ writememql(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr + i, 2); +#endif + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -1584,7 +1654,9 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) int cond = 1; uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; - +#ifdef USE_DEBUG_REGS_486 + mem_debug_check_addr(addr, write ? 2 : read_type); +#endif for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; From 0a9d71a42b48997ff9b63f847bcff3d2ce1ba1ca Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 24 May 2024 03:58:37 +0200 Subject: [PATCH 3/4] Correct the NVR mask of the two Compaq Presario's, fixes crashes with the 2240. --- src/machine/machine_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 18bcc5a8289..4cc5c5736af 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11576,7 +11576,7 @@ const machine_t machines[] = { .max = 131072, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -11616,7 +11616,7 @@ const machine_t machines[] = { .max = 131072, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 511, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, From 5ff67132a6530bfed1086bfa8b5c280dea9af1b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 24 May 2024 10:14:41 +0200 Subject: [PATCH 4/4] PCI: Add mechanism for internally wired IRQ routings. --- src/include/86box/pci.h | 9 +++++++++ src/pci.c | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 8483eb417f9..d2348ba0229 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -115,6 +115,11 @@ /* PCI MIRQ lines (currently 8, this many are needed by the ALi M1543(C). */ #define PCI_MIRQS_NUM 8 #define PCI_MIRQ_MAX (PCI_MIRQS_NUM - 1) +/* The base for internal IRQ lines accepted by pci_irq(). */ +#define PCI_IIRQ_BASE 0x80 +/* PCI direct IRQ lines - always at 4 per the PCI specification. */ +#define PCI_IIRQS_NUM 4 +#define PCI_IIRQ_MAX (PCI_IIRQS_NUM - 1) /* The base for direct IRQ lines accepted by pci_irq(). */ #define PCI_DIRQ_BASE 0xf0 /* PCI direct IRQ lines (currently 16 because we only emulate the legacy PIC). */ @@ -148,12 +153,16 @@ #define pci_set_mirq(mirq, level, irq_state) \ pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 1, irq_state) +#define pci_set_iirq(pci_int, irq_state) \ + pci_irq(PCI_IIRQ_BASE | 0, pci_int, 0, 1, irq_state) #define pci_set_dirq(irq, irq_state) \ pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 1, irq_state) #define pci_set_irq(slot, pci_int, irq_state) \ pci_irq(slot, pci_int, 0, 1, irq_state) #define pci_clear_mirq(mirq, level, irq_state) \ pci_irq(PCI_MIRQ_BASE | (mirq), 0, level, 0, irq_state) +#define pci_clear_iirq(pci_int, irq_state) \ + pci_irq(PCI_IIRQ_BASE | 0, pci_int, 0, 0, irq_state) #define pci_clear_dirq(dirq, irq_state) \ pci_irq(PCI_DIRQ_BASE | (irq), 0, 1, 0, irq_state) #define pci_clear_irq(slot, pci_int, irq_state) \ diff --git a/src/pci.c b/src/pci.c index 13b780050c0..266be4396de 100644 --- a/src/pci.c +++ b/src/pci.c @@ -204,6 +204,19 @@ pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state) } } break; + case (PCI_IIRQ_BASE | 0x00) ... (PCI_IIRQ_BASE | PCI_IIRQ_MAX): + /* PCI internal routing. */ + if (!last_pci_card || (pci_flags & FLAG_NO_IRQ_STEERING)) + return; + + irq_routing = (pci_int_index - PCI_INTA) & PCI_IRQ_MAX; + + irq_line = pci_irqs[irq_routing]; + + /* Ignore what was provided to us as a parameter and override it with whatever + the chipset is set to. */ + level = !!pci_irq_level[irq_routing]; + break; case (PCI_MIRQ_BASE | 0x00) ... (PCI_MIRQ_BASE | PCI_MIRQ_MAX): /* MIRQ */ slot &= PCI_MIRQ_MAX;