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
This commit is contained in:
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
76
src/io.c
76
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;
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user