Merged proc_ctrl.cc. Also fixed a bug in CR4 reloading; we were
printing a message when a reserved bit was set, but not causing a #GP(0). As well, I force a new PAE support option to 1 when Hammer support is enabled.
This commit is contained in:
parent
93d05990cc
commit
278e27d5fe
@ -558,6 +558,7 @@ typedef unsigned int Boolean;
|
||||
#define BX_SupportGuest2HostTLB 0
|
||||
#define BX_SupportRepeatSpeedups 0
|
||||
#define BX_SupportGlobalPages 0
|
||||
#define BX_SupportPAE 0
|
||||
|
||||
#define BX_HAVE_GETENV 0
|
||||
#define BX_HAVE_SELECT 0
|
||||
|
21
bochs/configure
vendored
21
bochs/configure
vendored
@ -623,7 +623,7 @@ else
|
||||
fi
|
||||
|
||||
|
||||
# From configure.in Id: configure.in,v 1.100 2002/09/13 23:59:23 kevinlawton Exp
|
||||
# From configure.in Id: configure.in,v 1.101 2002/09/14 05:46:57 kevinlawton Exp
|
||||
|
||||
|
||||
VERSION="1.4.cvs"
|
||||
@ -6059,6 +6059,20 @@ if test ! -d instrument; then mkdir instrument; fi
|
||||
if test ! -d build; then mkdir build; fi
|
||||
if test ! -d build/linux; then mkdir build/linux; fi
|
||||
|
||||
if test "$use_x86_64" = 1; then
|
||||
# For x86-64, force support of the Physical Address Extension (PAE).
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define BX_SupportPAE 1
|
||||
EOF
|
||||
|
||||
else
|
||||
# Not an option yet for x86-32.
|
||||
cat >> confdefs.h <<\EOF
|
||||
#define BX_SupportPAE 0
|
||||
EOF
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
@ -6088,7 +6102,7 @@ if test ! -d build/linux; then mkdir build/linux; fi
|
||||
# Extract the first word of "gzip", so it can be a program name with args.
|
||||
set dummy gzip; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6092: checking for $ac_word" >&5
|
||||
echo "configure:6106: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GZIP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6123,7 +6137,7 @@ fi
|
||||
# Extract the first word of "tar", so it can be a program name with args.
|
||||
set dummy tar; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6127: checking for $ac_word" >&5
|
||||
echo "configure:6141: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_TAR'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6361,6 +6375,7 @@ s%@WX_CXXFLAGS@%$WX_CXXFLAGS%g
|
||||
s%@PTHREAD_CC@%$PTHREAD_CC%g
|
||||
s%@PTHREAD_LIBS@%$PTHREAD_LIBS%g
|
||||
s%@PTHREAD_CFLAGS@%$PTHREAD_CFLAGS%g
|
||||
s%@BX_SupportPAE@%$BX_SupportPAE%g
|
||||
s%@INSTALL_TARGET@%$INSTALL_TARGET%g
|
||||
s%@INSTALL_LIST_FOR_PLATFORM@%$INSTALL_LIST_FOR_PLATFORM%g
|
||||
s%@RFB_LIBS@%$RFB_LIBS%g
|
||||
|
@ -2,7 +2,7 @@ dnl // Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.4)
|
||||
AC_INIT(bochs.h)
|
||||
AC_REVISION([[$Id: configure.in,v 1.101 2002-09-14 05:46:57 kevinlawton Exp $]])
|
||||
AC_REVISION([[$Id: configure.in,v 1.102 2002-09-14 23:17:55 kevinlawton Exp $]])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl // Put Bochs version information right here so that it gets substituted
|
||||
@ -1660,6 +1660,14 @@ if test ! -d instrument; then mkdir instrument; fi
|
||||
if test ! -d build; then mkdir build; fi
|
||||
if test ! -d build/linux; then mkdir build/linux; fi
|
||||
|
||||
if test "$use_x86_64" = 1; then
|
||||
# For x86-64, force support of the Physical Address Extension (PAE).
|
||||
AC_DEFINE(BX_SupportPAE, 1)
|
||||
else
|
||||
# Not an option yet for x86-32.
|
||||
AC_DEFINE(BX_SupportPAE, 0)
|
||||
fi
|
||||
AC_SUBST(BX_SupportPAE)
|
||||
|
||||
AC_SUBST(INSTALL_TARGET)
|
||||
AC_SUBST(INSTALL_LIST_FOR_PLATFORM)
|
||||
|
@ -63,7 +63,6 @@ OBJS32 = \
|
||||
bit.o \
|
||||
flag_ctrl.o \
|
||||
io.o \
|
||||
proc_ctrl.o \
|
||||
string.o \
|
||||
$(EXT_DEBUG_OBJS) \
|
||||
|
||||
@ -104,6 +103,7 @@ OBJSXX = \
|
||||
data_xfer16.o \
|
||||
data_xfer32.o \
|
||||
exception.o \
|
||||
proc_ctrl.o \
|
||||
|
||||
|
||||
# Objects which are only used for x86-64 code, but which have been
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.53 2002-09-14 19:21:40 kevinlawton Exp $
|
||||
// $Id: cpu.h,v 1.54 2002-09-14 23:17:55 kevinlawton Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -1917,9 +1917,7 @@ union {
|
||||
BX_SMF void RDTSC(BxInstruction_t *);
|
||||
BX_SMF void RDMSR(BxInstruction_t *);
|
||||
BX_SMF void SetCR0(Bit32u val_32);
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_SMF void SetCR4(Bit32u val_32);
|
||||
#endif
|
||||
BX_SMF void dynamic_translate(void);
|
||||
BX_SMF void dynamic_init(void);
|
||||
BX_SMF unsigned FetchDecode(Bit8u *, BxInstruction_t *, unsigned, Boolean);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.36 2002-09-14 19:21:40 kevinlawton Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.37 2002-09-14 23:17:55 kevinlawton Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -33,6 +33,17 @@
|
||||
#define this (BX_CPU(0))
|
||||
#endif
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64==0
|
||||
// Make life easier for merging code.
|
||||
#define RAX EAX
|
||||
#define RBX EBX
|
||||
#define RCX ECX
|
||||
#define RDX EDX
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void
|
||||
BX_CPU_C::UndefinedOpcode(BxInstruction_t *i)
|
||||
{
|
||||
@ -352,10 +363,215 @@ BX_CPU_C::MOV_RdDd(BxInstruction_t *i)
|
||||
BX_PANIC(("MOV_RdDd: control register index out of range"));
|
||||
val_32 = 0;
|
||||
}
|
||||
BX_WRITE_32BIT_REG(i->rm, val_32);
|
||||
BX_WRITE_32BIT_REGZ(i->rm, val_32);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
void
|
||||
BX_CPU_C::MOV_DqRq(BxInstruction_t *i)
|
||||
{
|
||||
Bit64u val_64;
|
||||
|
||||
if (v8086_mode()) BX_PANIC(("MOV_DqRq: v8086 mode unsupported"));
|
||||
|
||||
/* NOTES:
|
||||
* 64bit operands always used
|
||||
* r/m field specifies general register
|
||||
* mod field should always be 11 binary
|
||||
* reg field specifies which special register
|
||||
*/
|
||||
|
||||
if (i->mod != 0xc0) {
|
||||
BX_PANIC(("MOV_DqRq(): rm field not a register!"));
|
||||
}
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
if (protected_mode() && CPL!=0) {
|
||||
BX_PANIC(("MOV_DqRq: CPL!=0"));
|
||||
/* #GP(0) if CPL is not 0 */
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
val_64 = BX_READ_64BIT_REG(i->rm);
|
||||
if (bx_dbg.dreg)
|
||||
BX_INFO(("MOV_DqRq: DR[%u]=%08xh unhandled",
|
||||
(unsigned) i->nnn, (unsigned) val_64));
|
||||
|
||||
switch (i->nnn) {
|
||||
case 0: // DR0
|
||||
BX_CPU_THIS_PTR dr0 = val_64;
|
||||
break;
|
||||
case 1: // DR1
|
||||
BX_CPU_THIS_PTR dr1 = val_64;
|
||||
break;
|
||||
case 2: // DR2
|
||||
BX_CPU_THIS_PTR dr2 = val_64;
|
||||
break;
|
||||
case 3: // DR3
|
||||
BX_CPU_THIS_PTR dr3 = val_64;
|
||||
break;
|
||||
|
||||
case 4: // DR4
|
||||
case 6: // DR6
|
||||
// DR4 aliased to DR6 by default. With Debug Extensions on,
|
||||
// access to DR4 causes #UD
|
||||
#if BX_CPU_LEVEL >= 4
|
||||
if ( (i->nnn == 4) && (BX_CPU_THIS_PTR cr4.get_DE()) ) {
|
||||
// Debug extensions on
|
||||
BX_INFO(("MOV_DqRq: access to DR4 causes #UD"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
#endif
|
||||
#if BX_CPU_LEVEL <= 4
|
||||
// On 386/486 bit12 is settable
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(val_64 & 0x0000f00f);
|
||||
#else
|
||||
// On Pentium+, bit12 is always zero
|
||||
BX_CPU_THIS_PTR dr6 = (BX_CPU_THIS_PTR dr6 & 0xffff0ff0) |
|
||||
(val_64 & 0x0000e00f);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 5: // DR5
|
||||
case 7: // DR7
|
||||
// Note: 486+ ignore GE and LE flags. On the 386, exact
|
||||
// data breakpoint matching does not occur unless it is enabled
|
||||
// by setting the LE and/or GE flags.
|
||||
|
||||
// DR5 aliased to DR7 by default. With Debug Extensions on,
|
||||
// access to DR5 causes #UD
|
||||
#if BX_CPU_LEVEL >= 4
|
||||
if ( (i->nnn == 5) && (BX_CPU_THIS_PTR cr4.get_DE()) ) {
|
||||
// Debug extensions (CR4.DE) on
|
||||
BX_INFO(("MOV_DqRq: access to DR5 causes #UD"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
#endif
|
||||
// Some sanity checks...
|
||||
if ( val_64 & 0x00002000 ) {
|
||||
BX_PANIC(("MOV_DqRq: GD bit not supported yet"));
|
||||
// Note: processor clears GD upon entering debug exception
|
||||
// handler, to allow access to the debug registers
|
||||
}
|
||||
if ( (((val_64>>16) & 3)==2) ||
|
||||
(((val_64>>20) & 3)==2) ||
|
||||
(((val_64>>24) & 3)==2) ||
|
||||
(((val_64>>28) & 3)==2) ) {
|
||||
// IO breakpoints (10b) are not yet supported.
|
||||
BX_PANIC(("MOV_DqRq: write of %08x contains IO breakpoint",
|
||||
val_64));
|
||||
}
|
||||
if ( (((val_64>>18) & 3)==2) ||
|
||||
(((val_64>>22) & 3)==2) ||
|
||||
(((val_64>>26) & 3)==2) ||
|
||||
(((val_64>>30) & 3)==2) ) {
|
||||
// LEN0..3 contains undefined length specifier (10b)
|
||||
BX_PANIC(("MOV_DqRq: write of %08x contains undefined LENx",
|
||||
val_64));
|
||||
}
|
||||
if ( ((((val_64>>16) & 3)==0) && (((val_64>>18) & 3)!=0)) ||
|
||||
((((val_64>>20) & 3)==0) && (((val_64>>22) & 3)!=0)) ||
|
||||
((((val_64>>24) & 3)==0) && (((val_64>>26) & 3)!=0)) ||
|
||||
((((val_64>>28) & 3)==0) && (((val_64>>30) & 3)!=0)) ) {
|
||||
// Instruction breakpoint with LENx not 00b (1-byte length)
|
||||
BX_PANIC(("MOV_DqRq: write of %08x, R/W=00b LEN!=00b",
|
||||
val_64));
|
||||
}
|
||||
#if BX_CPU_LEVEL <= 4
|
||||
// 386/486: you can play with all the bits except b10 is always 1
|
||||
BX_CPU_THIS_PTR dr7 = val_64 | 0x00000400;
|
||||
#else
|
||||
// Pentium+: bits15,14,12 are hardwired to 0, rest are settable.
|
||||
// Even bits 11,10 are changeable though reserved.
|
||||
BX_CPU_THIS_PTR dr7 = (val_64 & 0xffff2fff) | 0x00000400;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("MOV_DqRq: control register index out of range"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
void
|
||||
BX_CPU_C::MOV_RqDq(BxInstruction_t *i)
|
||||
{
|
||||
Bit64u val_64;
|
||||
|
||||
if (v8086_mode()) {
|
||||
BX_INFO(("MOV_RqDq: v8086 mode causes #GP"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
if (i->mod != 0xc0) {
|
||||
BX_PANIC(("MOV_RqDq(): rm field not a register!"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
|
||||
if (protected_mode() && (CPL!=0)) {
|
||||
BX_INFO(("MOV_RqDq: CPL!=0 causes #GP"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bx_dbg.dreg)
|
||||
BX_INFO(("MOV_RqDq: DR%u not implemented yet", i->nnn));
|
||||
|
||||
switch (i->nnn) {
|
||||
case 0: // DR0
|
||||
val_64 = BX_CPU_THIS_PTR dr0;
|
||||
break;
|
||||
case 1: // DR1
|
||||
val_64 = BX_CPU_THIS_PTR dr1;
|
||||
break;
|
||||
case 2: // DR2
|
||||
val_64 = BX_CPU_THIS_PTR dr2;
|
||||
break;
|
||||
case 3: // DR3
|
||||
val_64 = BX_CPU_THIS_PTR dr3;
|
||||
break;
|
||||
|
||||
case 4: // DR4
|
||||
case 6: // DR6
|
||||
// DR4 aliased to DR6 by default. With Debug Extensions on,
|
||||
// access to DR4 causes #UD
|
||||
#if BX_CPU_LEVEL >= 4
|
||||
if ( (i->nnn == 4) && (BX_CPU_THIS_PTR cr4.get_DE()) ) {
|
||||
// Debug extensions on
|
||||
BX_INFO(("MOV_RqDq: access to DR4 causes #UD"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
#endif
|
||||
val_64 = BX_CPU_THIS_PTR dr6;
|
||||
break;
|
||||
|
||||
case 5: // DR5
|
||||
case 7: // DR7
|
||||
// DR5 aliased to DR7 by default. With Debug Extensions on,
|
||||
// access to DR5 causes #UD
|
||||
#if BX_CPU_LEVEL >= 4
|
||||
if ( (i->nnn == 5) && (BX_CPU_THIS_PTR cr4.get_DE()) ) {
|
||||
// Debug extensions on
|
||||
BX_INFO(("MOV_RqDq: access to DR5 causes #UD"));
|
||||
UndefinedOpcode(i);
|
||||
}
|
||||
#endif
|
||||
val_64 = BX_CPU_THIS_PTR dr7;
|
||||
break;
|
||||
|
||||
default:
|
||||
BX_PANIC(("MOV_RqDq: control register index out of range"));
|
||||
val_64 = 0;
|
||||
}
|
||||
BX_WRITE_64BIT_REG(i->rm, val_64);
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
|
||||
|
||||
void
|
||||
BX_CPU_C::LMSW_Ew(BxInstruction_t *i)
|
||||
@ -426,7 +642,7 @@ BX_CPU_C::SMSW_Ew(BxInstruction_t *i)
|
||||
|
||||
if (i->mod == 0xc0) {
|
||||
if (i->os_32) {
|
||||
BX_WRITE_32BIT_REG(i->rm, msw); // zeros out high 16bits
|
||||
BX_WRITE_32BIT_REGZ(i->rm, msw); // zeros out high 16bits
|
||||
}
|
||||
else {
|
||||
BX_WRITE_16BIT_REG(i->rm, msw);
|
||||
@ -476,7 +692,7 @@ BX_CPU_C::MOV_CdRd(BxInstruction_t *i)
|
||||
|
||||
switch (i->nnn) {
|
||||
case 0: // CR0 (MSW)
|
||||
// BX_INFO(("MOV_CdRd:CR0: R32 = %08x\n @CS:EIP %04x:%04x ",
|
||||
// BX_INFO(("MOV_CdRd:CR0: R32 = %08x @CS:EIP %04x:%04x ",
|
||||
// (unsigned) val_32,
|
||||
// (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
|
||||
// (unsigned) EIP));
|
||||
@ -507,27 +723,10 @@ BX_CPU_C::MOV_CdRd(BxInstruction_t *i)
|
||||
val_32));
|
||||
UndefinedOpcode(i);
|
||||
#else
|
||||
Bit32u allowMask = 0;
|
||||
Bit32u oldCR4 = BX_CPU_THIS_PTR cr4.getRegister();
|
||||
// Protected mode: #GP(0) if attempt to write a 1 to
|
||||
// any reserved bit of CR4
|
||||
|
||||
#if BX_SUPPORT_4MEG_PAGES
|
||||
allowMask |= (1<<4);
|
||||
#endif
|
||||
|
||||
#if BX_SupportGlobalPages
|
||||
allowMask |= (1<<7);
|
||||
#endif
|
||||
|
||||
if (val_32 & ~allowMask) {
|
||||
BX_INFO(("MOV_CdRd: (CR4) write of 0x%08x not supported!",
|
||||
val_32));
|
||||
}
|
||||
|
||||
val_32 = val_32 & allowMask; // Screen out unsupported bits.
|
||||
BX_CPU_THIS_PTR cr4.setRegister(val_32);
|
||||
pagingCR4Changed(oldCR4, BX_CPU_THIS_PTR cr4.getRegister());
|
||||
SetCR4(val_32);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@ -570,7 +769,7 @@ BX_CPU_C::MOV_RdCd(BxInstruction_t *i)
|
||||
case 0: // CR0 (MSW)
|
||||
val_32 = BX_CPU_THIS_PTR cr0.val32;
|
||||
#if 0
|
||||
BX_INFO(("MOV_RdCd:CR0: R32 = %08x\n @CS:EIP %04x:%04x",
|
||||
BX_INFO(("MOV_RdCd:CR0: R32 = %08x @CS:EIP %04x:%04x",
|
||||
(unsigned) val_32,
|
||||
(unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
|
||||
(unsigned) EIP));
|
||||
@ -604,10 +803,173 @@ BX_CPU_C::MOV_RdCd(BxInstruction_t *i)
|
||||
BX_PANIC(("MOV_RdCd: control register index out of range"));
|
||||
val_32 = 0;
|
||||
}
|
||||
BX_WRITE_32BIT_REG(i->rm, val_32);
|
||||
BX_WRITE_32BIT_REGZ(i->rm, val_32);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
void
|
||||
BX_CPU_C::MOV_CqRq(BxInstruction_t *i)
|
||||
{
|
||||
// mov general register data to control register
|
||||
#if BX_CPU_LEVEL < 3
|
||||
BX_PANIC(("MOV_CqRq: not supported on < 386"));
|
||||
#else
|
||||
Bit64u val_64;
|
||||
|
||||
|
||||
if (v8086_mode()) BX_PANIC(("proc_ctrl: v8086 mode unsupported"));
|
||||
|
||||
/* NOTES:
|
||||
* 64bit operands always used
|
||||
* r/m field specifies general register
|
||||
* mod field should always be 11 binary
|
||||
* reg field specifies which special register
|
||||
*/
|
||||
|
||||
if (i->mod != 0xc0) {
|
||||
BX_PANIC(("MOV_CqRq(): rm field not a register!"));
|
||||
}
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
if (protected_mode() && CPL!=0) {
|
||||
BX_PANIC(("MOV_CqRq: CPL!=0"));
|
||||
/* #GP(0) if CPL is not 0 */
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
val_64 = BX_READ_64BIT_REG(i->rm);
|
||||
|
||||
switch (i->nnn) {
|
||||
case 0: // CR0 (MSW)
|
||||
// BX_INFO(("MOV_CqRq:CR0: R64 = %08x @CS:EIP %04x:%04x ",
|
||||
// (unsigned) val_64,
|
||||
// (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
|
||||
// (unsigned) EIP));
|
||||
SetCR0(val_64);
|
||||
break;
|
||||
|
||||
case 1: /* CR1 */
|
||||
BX_PANIC(("MOV_CqRq: CR1 not implemented yet"));
|
||||
break;
|
||||
case 2: /* CR2 */
|
||||
BX_DEBUG(("MOV_CqRq: CR2 not implemented yet"));
|
||||
BX_DEBUG(("MOV_CqRq: CR2 = reg"));
|
||||
BX_CPU_THIS_PTR cr2 = val_64;
|
||||
break;
|
||||
case 3: // CR3
|
||||
if (bx_dbg.creg)
|
||||
BX_INFO(("MOV_CqRq:CR3 = %08x", (unsigned) val_64));
|
||||
// Reserved bits take on value of MOV instruction
|
||||
CR3_change(val_64);
|
||||
BX_INSTR_TLB_CNTRL(BX_INSTR_MOV_CR3, val_64);
|
||||
break;
|
||||
case 4: // CR4
|
||||
#if BX_CPU_LEVEL == 3
|
||||
BX_PANIC(("MOV_CqRq: write to CR4 of 0x%08x on 386",
|
||||
val_64));
|
||||
UndefinedOpcode(i);
|
||||
#else
|
||||
// Protected mode: #GP(0) if attempt to write a 1 to
|
||||
// any reserved bit of CR4
|
||||
|
||||
BX_INFO(("MOV_CqRq: ignoring write to CR4 of 0x%08x",
|
||||
val_64));
|
||||
if (val_64) {
|
||||
BX_INFO(("MOV_CqRq: (CR4) write of 0x%08x not supported!",
|
||||
val_64));
|
||||
}
|
||||
// Only allow writes of 0 to CR4 for now.
|
||||
// Writes to bits in CR4 should not be 1s as CPUID
|
||||
// returns not-supported for all of these features.
|
||||
SetCR4(val_64);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("MOV_CqRq: control register index out of range"));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
void
|
||||
BX_CPU_C::MOV_RqCq(BxInstruction_t *i)
|
||||
{
|
||||
// mov control register data to register
|
||||
#if BX_CPU_LEVEL < 3
|
||||
BX_PANIC(("MOV_RqCq: not supported on < 386"));
|
||||
#else
|
||||
Bit64u val_64;
|
||||
|
||||
if (v8086_mode()) BX_PANIC(("proc_ctrl: v8086 mode unsupported"));
|
||||
|
||||
/* NOTES:
|
||||
* 64bit operands always used
|
||||
* r/m field specifies general register
|
||||
* mod field should always be 11 binary
|
||||
* reg field specifies which special register
|
||||
*/
|
||||
|
||||
if (i->mod != 0xc0) {
|
||||
BX_PANIC(("MOV_RqC(): rm field not a register!"));
|
||||
}
|
||||
|
||||
if (protected_mode() && CPL!=0) {
|
||||
BX_PANIC(("MOV_RqCq: CPL!=0"));
|
||||
/* #GP(0) if CPL is not 0 */
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (i->nnn) {
|
||||
case 0: // CR0 (MSW)
|
||||
val_64 = BX_CPU_THIS_PTR cr0.val32;
|
||||
#if 0
|
||||
BX_INFO(("MOV_RqCq:CR0: R64 = %08x @CS:EIP %04x:%04x",
|
||||
(unsigned) val_64,
|
||||
(unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
|
||||
(unsigned) EIP));
|
||||
#endif
|
||||
break;
|
||||
case 1: /* CR1 */
|
||||
BX_PANIC(("MOV_RqCq: CR1 not implemented yet"));
|
||||
val_64 = 0;
|
||||
break;
|
||||
case 2: /* CR2 */
|
||||
if (bx_dbg.creg)
|
||||
BX_INFO(("MOV_RqCq: CR2"));
|
||||
val_64 = BX_CPU_THIS_PTR cr2;
|
||||
break;
|
||||
case 3: // CR3
|
||||
if (bx_dbg.creg)
|
||||
BX_INFO(("MOV_RqCq: reading CR3"));
|
||||
val_64 = BX_CPU_THIS_PTR cr3;
|
||||
break;
|
||||
case 4: // CR4
|
||||
#if BX_CPU_LEVEL == 3
|
||||
val_64 = 0;
|
||||
BX_INFO(("MOV_RqCq: read of CR4 causes #UD"));
|
||||
UndefinedOpcode(i);
|
||||
#else
|
||||
BX_INFO(("MOV_RqCq: read of CR4"));
|
||||
val_64 = BX_CPU_THIS_PTR cr4.getRegister();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("MOV_RqCq: control register index out of range"));
|
||||
val_64 = 0;
|
||||
}
|
||||
BX_WRITE_64BIT_REG(i->rm, val_64);
|
||||
#endif
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
void
|
||||
BX_CPU_C::MOV_TdRd(BxInstruction_t *i)
|
||||
{
|
||||
@ -981,10 +1343,10 @@ BX_CPU_C::CPUID(BxInstruction_t *i)
|
||||
// EBX: vendor ID string
|
||||
// EDX: vendor ID string
|
||||
// ECX: vendor ID string
|
||||
EAX = 1; // 486 or pentium
|
||||
EBX = 0x756e6547; // "Genu"
|
||||
EDX = 0x49656e69; // "ineI"
|
||||
ECX = 0x6c65746e; // "ntel"
|
||||
RAX = 1; // 486 or pentium
|
||||
RBX = 0x756e6547; // "Genu"
|
||||
RDX = 0x49656e69; // "ineI"
|
||||
RCX = 0x6c65746e; // "ntel"
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@ -1058,25 +1420,54 @@ BX_CPU_C::CPUID(BxInstruction_t *i)
|
||||
# if BX_SUPPORT_MMX
|
||||
features |= (1<<23); // support MMX
|
||||
# endif
|
||||
|
||||
#else
|
||||
BX_PANIC(("CPUID: not implemented for > 6"));
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_4MEG_PAGES
|
||||
features |= 8; // support page-size extension (4m pages)
|
||||
features |= (1<<3); // Support Page-Size Extension (4M pages)
|
||||
#endif
|
||||
|
||||
#if BX_SupportGlobalPages
|
||||
features |= (1<<13); // Support Global pages.
|
||||
#endif
|
||||
|
||||
EAX = (family <<8) | (model<<4) | stepping;
|
||||
EBX = ECX = 0; // reserved
|
||||
EDX = features;
|
||||
#if BX_SupportPAE
|
||||
features |= (1<<6); // Support PAE.
|
||||
#endif
|
||||
|
||||
RAX = (family <<8) | (model<<4) | stepping;
|
||||
RBX = RCX = 0; // reserved
|
||||
RDX = features;
|
||||
break;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
// x86-64 functions
|
||||
case 0x80000000:
|
||||
// max function supported.
|
||||
RAX = 0x80000008;
|
||||
RBX = 0x68747541; // "Auth"
|
||||
RDX = 0x69746e65; // "enti"
|
||||
RCX = 0x444d4163; // "cAMD"
|
||||
break;
|
||||
|
||||
case 0x80000001:
|
||||
// long mode supported.
|
||||
// bug in manual - should be EDX not EAX
|
||||
RDX = (1 << 29);
|
||||
RAX = RBX = RCX = 0;
|
||||
break;
|
||||
|
||||
case 0x80000008:
|
||||
// virtual & phys address size in low 2 bytes.
|
||||
RAX = 0x00003028;
|
||||
RBX = RCX = RDX = 0;
|
||||
break;
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
default:
|
||||
EAX = EBX = ECX = EDX = 0; // Reserved, undefined
|
||||
RAX = RBX = RCX = RDX = 0; // Reserved, undefined
|
||||
break;
|
||||
}
|
||||
#else
|
||||
@ -1137,11 +1528,80 @@ BX_CPU_C::SetCR0(Bit32u val_32)
|
||||
enter_real_mode();
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (prev_pg==0 && BX_CPU_THIS_PTR cr0.pg) {
|
||||
if (BX_CPU_THIS_PTR msr.lme) {
|
||||
if (!BX_CPU_THIS_PTR cr4.get_PAE()) {
|
||||
BX_PANIC(("SetCR0: attempt to enter x86-64 LONG mode without enabling CR4.PAE !!!"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.lma = 1;
|
||||
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
|
||||
#if BX_EXTERNAL_DEBUGGER
|
||||
trap_debugger(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (prev_pg==1 && BX_CPU_THIS_PTR cr0.pg==0) {
|
||||
if (BX_CPU_THIS_PTR msr.lma) {
|
||||
if (BX_CPU_THIS_PTR dword.rip_upper != 0) {
|
||||
BX_PANIC(("SetCR0: attempt to leave x86-64 LONG mode with RIP upper != 0 !!!"));
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.lma = 0;
|
||||
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32;
|
||||
#if BX_EXTERNAL_DEBUGGER
|
||||
trap_debugger(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
// Give the paging unit a chance to look for changes in bits
|
||||
// it cares about, like {PG,PE}, so it can flush cache entries etc.
|
||||
pagingCR0Changed(oldCR0, newCR0);
|
||||
}
|
||||
|
||||
void
|
||||
BX_CPU_C::SetCR4(Bit32u val_32)
|
||||
{
|
||||
Bit32u allowMask = 0;
|
||||
Bit32u oldCR4 = BX_CPU_THIS_PTR cr4.getRegister();
|
||||
|
||||
#if BX_SUPPORT_4MEG_PAGES
|
||||
allowMask |= (1<<4);
|
||||
#endif
|
||||
|
||||
#if BX_SupportGlobalPages
|
||||
allowMask |= (1<<7);
|
||||
#endif
|
||||
|
||||
#if BX_SupportPAE
|
||||
allowMask |= (1<<5);
|
||||
#endif
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
#warning "KPL: SetCR4: should config with x86-64 force PSE support?"
|
||||
// need to GPF #0 if LME=1 and PAE=0
|
||||
if ( (BX_CPU_THIS_PTR msr.lme)
|
||||
&& (!(val_32 >> 5) & 1)
|
||||
&& (BX_CPU_THIS_PTR cr4.get_PAE())
|
||||
) {
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Need to GPF if trying to set undefined bits.
|
||||
if (val_32 & ~allowMask) {
|
||||
BX_INFO(("#GP(0): SetCR4: Write of 0x%08x not supported (allowMask=0x%x).",
|
||||
val_32, allowMask));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
val_32 &= allowMask; // Screen out unsupported bits. (not needed, for good measure)
|
||||
BX_CPU_THIS_PTR cr4.setRegister(val_32);
|
||||
pagingCR4Changed(oldCR4, BX_CPU_THIS_PTR cr4.getRegister());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BX_CPU_C::RSM(BxInstruction_t *i)
|
||||
@ -1164,8 +1624,8 @@ BX_CPU_C::RDTSC(BxInstruction_t *i)
|
||||
if ((tsd==0) || (tsd==1 && cpl==0)) {
|
||||
// return ticks
|
||||
Bit64u ticks = bx_pc_system.time_ticks ();
|
||||
EAX = (Bit32u) (ticks & 0xffffffff);
|
||||
EDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
|
||||
RAX = (Bit32u) (ticks & 0xffffffff);
|
||||
RDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
|
||||
//BX_INFO(("RDTSC: returning EDX:EAX = %08x:%08x", EDX, EAX));
|
||||
} else {
|
||||
// not allowed to use RDTSC!
|
||||
@ -1181,7 +1641,7 @@ BX_CPU_C::RDMSR(BxInstruction_t *i)
|
||||
{
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
invalidate_prefetch_q();
|
||||
|
||||
|
||||
if (v8086_mode()) {
|
||||
BX_INFO(("RDMSR: Invalid whilst in virtual 8086 mode"));
|
||||
goto do_exception;
|
||||
@ -1236,15 +1696,59 @@ BX_CPU_C::RDMSR(BxInstruction_t *i)
|
||||
*/
|
||||
case BX_MSR_APICBASE:
|
||||
/* we return low 32 bits in EAX, and high in EDX */
|
||||
EAX = Bit32u(BX_CPU_THIS_PTR msr.apicbase & 0xffffffff);
|
||||
EDX = Bit32u(BX_CPU_THIS_PTR msr.apicbase >> 32);
|
||||
RAX = Bit32u(BX_CPU_THIS_PTR msr.apicbase & 0xffffffff);
|
||||
RDX = Bit32u(BX_CPU_THIS_PTR msr.apicbase >> 32);
|
||||
BX_INFO(("RDMSR: Read %08x:%08x from MSR_APICBASE", EDX, EAX));
|
||||
return;
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
case BX_MSR_EFER:
|
||||
RAX = (BX_CPU_THIS_PTR msr.sce << 0)
|
||||
| (BX_CPU_THIS_PTR msr.lme << 8)
|
||||
| (BX_CPU_THIS_PTR msr.lma << 10);
|
||||
RDX = 0;
|
||||
return;
|
||||
|
||||
case BX_MSR_STAR:
|
||||
RAX = BX_CPU_THIS_PTR msr.star;
|
||||
RDX = BX_CPU_THIS_PTR msr.star >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_LSTAR:
|
||||
RAX = BX_CPU_THIS_PTR msr.lstar;
|
||||
RDX = BX_CPU_THIS_PTR msr.lstar >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_CSTAR:
|
||||
RAX = BX_CPU_THIS_PTR msr.cstar;
|
||||
RDX = BX_CPU_THIS_PTR msr.cstar >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_FMASK:
|
||||
RAX = BX_CPU_THIS_PTR msr.fmask;
|
||||
RDX = BX_CPU_THIS_PTR msr.fmask >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_FSBASE:
|
||||
RAX = BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base;
|
||||
RDX = BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_GSBASE:
|
||||
RAX = BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base;
|
||||
RDX = BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base >> 32;
|
||||
return;
|
||||
|
||||
case BX_MSR_KERNELGSBASE:
|
||||
RAX = BX_CPU_THIS_PTR msr.kernelgsbase;
|
||||
RDX = BX_CPU_THIS_PTR msr.kernelgsbase >> 32;
|
||||
return;
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
default:
|
||||
BX_PANIC(("RDMSR: Unknown register %#x", ECX));
|
||||
goto do_exception;
|
||||
|
||||
|
||||
}
|
||||
#endif /* BX_CPU_LEVEL >= 5 */
|
||||
|
||||
@ -1303,14 +1807,48 @@ BX_CPU_C::WRMSR(BxInstruction_t *i)
|
||||
*/
|
||||
|
||||
case BX_MSR_APICBASE:
|
||||
BX_CPU_THIS_PTR msr.apicbase = ((Bit64u)EDX << 32) + EAX;
|
||||
BX_CPU_THIS_PTR msr.apicbase = ((Bit64u) EDX << 32) + EAX;
|
||||
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", EDX, EAX));
|
||||
return;
|
||||
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
case BX_MSR_EFER:
|
||||
// GPF #0 if lme 0->1 and cr0.pg = 1
|
||||
// GPF #0 if lme 1->0 and cr0.pg = 1
|
||||
if ( (BX_CPU_THIS_PTR msr.lme != (EAX >> 8) & 1)
|
||||
&& (BX_CPU_THIS_PTR cr0.pg == 1)) {
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1;
|
||||
BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1;
|
||||
return;
|
||||
case BX_MSR_STAR:
|
||||
BX_CPU_THIS_PTR msr.star = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_LSTAR:
|
||||
BX_CPU_THIS_PTR msr.lstar = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_CSTAR:
|
||||
BX_CPU_THIS_PTR msr.cstar = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_FMASK:
|
||||
BX_CPU_THIS_PTR msr.fmask = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_FSBASE:
|
||||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_GSBASE:
|
||||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
case BX_MSR_KERNELGSBASE:
|
||||
BX_CPU_THIS_PTR msr.kernelgsbase = ((Bit64u) EDX << 32) + EAX;
|
||||
return;
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
default:
|
||||
BX_PANIC(("WRMSR: Unknown register %#x", ECX));
|
||||
goto do_exception;
|
||||
|
||||
|
||||
}
|
||||
#endif /* BX_CPU_LEVEL >= 5 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user