VME support - beta #1

This commit is contained in:
Stanislav Shwartsman 2005-10-17 13:06:09 +00:00
parent e83c77db49
commit 670395f1be
12 changed files with 314 additions and 211 deletions

View File

@ -2,7 +2,7 @@ dnl // Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_INIT(bochs.h)
AC_REVISION([[$Id: configure.in,v 1.298 2005-10-16 23:13:18 sshwarts Exp $]])
AC_REVISION([[$Id: configure.in,v 1.299 2005-10-17 13:06:08 sshwarts Exp $]])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(ltdlconf.h)
@ -1543,12 +1543,6 @@ AC_ARG_ENABLE(vme,
AC_DEFINE(BX_SUPPORT_VME, 0)
fi
],
[
if test "$bx_cpu_level" -ge 5; then
AC_MSG_RESULT(no)
AC_DEFINE(BX_SUPPORT_VME, 0)
fi
]
)
AC_MSG_CHECKING(for MMX support)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.245 2005-10-16 23:13:19 sshwarts Exp $
// $Id: cpu.h,v 1.246 2005-10-17 13:06:08 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -398,13 +398,13 @@ BOCHSAPI extern BX_CPU_C *bx_cpu_array[BX_SMP_PROCESSORS];
#endif
typedef struct {
/* 31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16
* ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==
* 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|ID|VP|VF|AC|VM|RF
/* 31|30|29|28| 27|26|25|24| 23|22|21|20| 19|18|17|16
* ==|==|=====| ==|==|==|==| ==|==|==|==| ==|==|==|==
* 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|ID|VP| VF|AC|VM|RF
*
* 15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0
* ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==
* 0|NT| IOPL|OF|DF|IF|TF|SF|ZF| 0|AF| 0|PF| 1|CF
* 15|14|13|12| 11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0
* ==|==|=====| ==|==|==|==| ==|==|==|==| ==|==|==|==
* 0|NT| IOPL| OF|DF|IF|TF| SF|ZF| 0|AF| 0|PF| 1|CF
*/
Bit32u val32; // Raw 32-bit value in x86 bit position. Used to store
// some eflags which are not cached in separate fields.
@ -512,6 +512,8 @@ typedef struct {
#define EFlagsVIFMask EFlagsVFMask
#define EFlagsVIPMask EFlagsVPMask
#define EFlagsValidMask 0x003f7fd5 // only supported bits for EFLAGS
} bx_flags_reg_t;
@ -610,12 +612,14 @@ typedef struct {
#define IMPLEMENT_CR4_ACCESSORS(name,bitnum) \
BX_CPP_INLINE bx_bool get_##name () { \
return 1 & (registerValue >> bitnum); \
} \
} \
BX_CPP_INLINE void set_##name (Bit8u val) { \
registerValue = (registerValue&~(1<<bitnum)) | (val ? (1<<bitnum) : 0); \
}
#if BX_SUPPORT_VME
IMPLEMENT_CR4_ACCESSORS(VME, 0);
IMPLEMENT_CR4_ACCESSORS(PVI, 1);
#endif
IMPLEMENT_CR4_ACCESSORS(TSD, 2);
IMPLEMENT_CR4_ACCESSORS(DE, 3);
IMPLEMENT_CR4_ACCESSORS(PSE, 4);
@ -1196,8 +1200,8 @@ public: // for now...
bx_segment_reg_t save_cs;
bx_segment_reg_t save_ss;
Bit32u save_eip;
Bit32u save_esp;
bx_address save_eip;
bx_address save_esp;
// This help for OS/2
bx_bool except_chk;
Bit16u except_cs;
@ -2799,9 +2803,9 @@ public: // for now...
BX_SMF void long_iret(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#endif
BX_SMF void validate_seg_regs(void);
BX_SMF void stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector,
Bit32u flags32);
BX_SMF void stack_return_from_v86(bxInstruction_c *);
BX_SMF void stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector, Bit32u flags32);
BX_SMF void iret16_stack_return_from_v86(bxInstruction_c *);
BX_SMF void iret32_stack_return_from_v86(bxInstruction_c *);
#if BX_SUPPORT_VME
BX_SMF void v86_redirect_interrupt(Bit32u vector);
#endif
@ -2815,8 +2819,6 @@ public: // for now...
BX_SMF void get_RSP_from_TSS(unsigned pl, Bit64u *rsp);
#endif
BX_SMF void write_flags(Bit16u flags, bx_bool change_IOPL, bx_bool change_IF) BX_CPP_AttrRegparmN(3);
BX_SMF void write_eflags(Bit32u eflags, bx_bool change_IOPL, bx_bool change_IF,
bx_bool change_VM, bx_bool change_RF);
BX_SMF void writeEFlags(Bit32u eflags, Bit32u changeMask) BX_CPP_AttrRegparmN(2); // Newer variant.
#if BX_SUPPORT_FPU || BX_SUPPORT_SSE >= 1
BX_SMF void write_eflags_fpu_compare(int float_relation);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer16.cc,v 1.30 2005-07-20 01:26:44 sshwarts Exp $
// $Id: ctrl_xfer16.cc,v 1.31 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -404,7 +404,7 @@ void BX_CPU_C::IRET16(bxInstruction_c *i)
if (v8086_mode()) {
// IOPL check in stack_return_from_v86()
stack_return_from_v86(i);
iret16_stack_return_from_v86(i);
goto done;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer32.cc,v 1.43 2005-10-16 23:13:19 sshwarts Exp $
// $Id: ctrl_xfer32.cc,v 1.44 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -398,7 +398,7 @@ void BX_CPU_C::IRET32(bxInstruction_c *i)
if (v8086_mode()) {
// IOPL check in stack_return_from_v86()
stack_return_from_v86(i);
iret32_stack_return_from_v86(i);
goto done;
}
@ -414,24 +414,21 @@ void BX_CPU_C::IRET32(bxInstruction_c *i)
exception(BX_SS_EXCEPTION, 0, 0);
}
access_linear(BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_SS) + ESP,
4, CPL == 3, BX_READ, &eip);
pop_32(&eip);
// still need to be validated !
if (eip > 0xffff) {
// CS.LIMIT in real mode is 0xffff
if (eip > 0xffff) {
BX_PANIC(("IRETD: instruction pointer not within code segment limits"));
exception(BX_GP_EXCEPTION, 0, 0);
}
pop_32(&eip);
pop_32(&ecs);
pop_32(&eflags);
ecs &= 0xffff;
eflags = (eflags & 0x257fd5) | (read_eflags() & 0x1a0000);
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u)ecs);
EIP = eip;
writeEFlags(eflags, 0xffffffff);
writeEFlags(eflags, 0x00257fd5); // VIF, VIP, VM unchanged
done:
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.64 2005-10-13 16:22:21 sshwarts Exp $
// $Id: exception.cc,v 1.65 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -783,10 +783,15 @@ void BX_CPU_C::interrupt(Bit8u vector, bx_bool is_INT, bx_bool is_error_code, Bi
BX_CPU_THIS_PTR debug_trap = 0;
BX_CPU_THIS_PTR inhibit_mask = 0;
BX_CPU_THIS_PTR save_cs = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS];
BX_CPU_THIS_PTR save_ss = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS];
BX_CPU_THIS_PTR save_cs = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS];
BX_CPU_THIS_PTR save_ss = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS];
#if BX_SUPPORT_X86_64
BX_CPU_THIS_PTR save_eip = RIP;
BX_CPU_THIS_PTR save_esp = RSP;
#else
BX_CPU_THIS_PTR save_eip = EIP;
BX_CPU_THIS_PTR save_esp = ESP;
#endif
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lma) {
@ -832,10 +837,15 @@ void BX_CPU_C::exception(unsigned vector, Bit16u error_code, bx_bool is_INT)
// if not initial error, restore previous register values from
// previous attempt to handle exception
if (BX_CPU_THIS_PTR errorno) {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS] = BX_CPU_THIS_PTR save_cs;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS] = BX_CPU_THIS_PTR save_ss;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS] = BX_CPU_THIS_PTR save_cs;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS] = BX_CPU_THIS_PTR save_ss;
#if BX_SUPPORT_X86_64
RIP = BX_CPU_THIS_PTR save_eip;
RSP = BX_CPU_THIS_PTR save_esp;
#else
EIP = BX_CPU_THIS_PTR save_eip;
ESP = BX_CPU_THIS_PTR save_esp;
#endif
}
BX_CPU_THIS_PTR errorno++;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: flag_ctrl.cc,v 1.23 2005-10-16 23:13:19 sshwarts Exp $
// $Id: flag_ctrl.cc,v 1.24 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -114,7 +114,7 @@ void BX_CPU_C::STI(bxInstruction_c *i)
if (BX_CPU_THIS_PTR cr4.get_PVI())
{
if (cpl == 3 && IOPL < 3) {
if (! BX_CPU_THIS_PTR get_VIP ())
if (! BX_CPU_THIS_PTR get_VIP())
{
BX_CPU_THIS_PTR assert_VIF();
return;
@ -168,14 +168,76 @@ void BX_CPU_C::CMC(bxInstruction_c *i)
void BX_CPU_C::PUSHF_Fw(bxInstruction_c *i)
{
Bit16u flags = read_flags();
if (v8086_mode()) {
if ((BX_CPU_THIS_PTR get_IOPL () < 3) && (CR4_VME_ENABLED == 0)) {
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
#if BX_SUPPORT_VME
if (CR4_VME_ENABLED && BX_CPU_THIS_PTR get_IOPL() < 3) {
flags |= EFlagsIOPLMask;
if (BX_CPU_THIS_PTR get_VIF())
flags |= EFlagsIFMask;
else
flags &= ~EFlagsIFMask;
}
#endif
}
push_16(read_flags());
push_16(flags);
}
void BX_CPU_C::POPF_Fw(bxInstruction_c *i)
{
// Build a mask of the following bits:
// x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask;
#if BX_CPU_LEVEL >= 3
changeMask |= EFlagsNTMask; // NT could be modified
#endif
Bit16u flags16;
if (protected_mode()) {
pop_16(&flags16);
if (CPL==0)
changeMask |= EFlagsIOPLMask;
if (CPL <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
}
else if (v8086_mode()) {
if ((BX_CPU_THIS_PTR get_IOPL () < 3) && (CR4_VME_ENABLED == 0)) {
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
pop_16(&flags16);
#if BX_SUPPORT_VME
if (CR4_VME_ENABLED && BX_CPU_THIS_PTR get_IOPL() < 3) {
if (((flags16 & EFlagsIFMask) && BX_CPU_THIS_PTR get_VIP()) ||
(flags16 & EFlagsTFMask))
{
BX_DEBUG(("POPFW: #GP(0) in VME mode"));
exception(BX_GP_EXCEPTION, 0, 0);
}
// IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF
changeMask |= EFlagsVIFMask;
Bit32u flags32 = (Bit32u) flags16;
if (BX_CPU_THIS_PTR get_IF()) flags32 |= EFlagsVIFMask;
writeEFlags(flags32, changeMask);
return;
}
#endif
changeMask |= EFlagsIFMask;
}
else {
pop_16(&flags16);
// All non-reserved flags can be modified
changeMask |= (EFlagsIOPLMask | EFlagsIFMask);
}
writeEFlags((Bit32u) flags16, changeMask);
}
#if BX_CPU_LEVEL >= 3
@ -191,58 +253,10 @@ void BX_CPU_C::PUSHF_Fd(bxInstruction_c *i)
push_32(read_eflags() & 0x00fcffff);
}
#if BX_SUPPORT_X86_64
void BX_CPU_C::PUSHF_Fq(bxInstruction_c *i)
{
// VM & RF flags cleared in image stored on the stack
push_64(read_eflags() & 0x00fcffff);
}
#endif
#endif // BX_CPU_LEVEL >= 3
void BX_CPU_C::POPF_Fw(bxInstruction_c *i)
{
// Build a mask of the following bits:
// x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask;
0x0dd5;
#if BX_CPU_LEVEL >= 3
changeMask |= EFlagsNTMask; // NT could be modified
#endif
Bit16u flags16;
if (protected_mode()) {
pop_16(&flags16);
if (CPL==0)
changeMask |= EFlagsIOPLMask;
if (CPL <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
}
else if (v8086_mode()) {
if (BX_CPU_THIS_PTR get_IOPL() < 3) {
exception(BX_GP_EXCEPTION, 0, 0);
return;
}
pop_16(&flags16);
// All non-reserved flags except IOPL can be modified
changeMask |= EFlagsIFMask;
}
else {
pop_16(&flags16);
// All non-reserved flags can be modified
changeMask |= (EFlagsIOPLMask | EFlagsIFMask);
}
writeEFlags((Bit32u) flags16, changeMask);
}
#if BX_CPU_LEVEL >= 3
void BX_CPU_C::POPF_Fd(bxInstruction_c *i)
{
// Build a mask of the following bits:
// ID,VP,VF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
#if BX_CPU_LEVEL >= 4
@ -266,7 +280,7 @@ void BX_CPU_C::POPF_Fd(bxInstruction_c *i)
return;
}
pop_32(&flags32);
// v8086-mode: VM,IOPL,VIP,VIF are unaffected
// v8086-mode: VM, IOPL, VIP, VIF are unaffected
changeMask |= EFlagsIFMask;
}
else { // Real-mode
@ -279,21 +293,25 @@ void BX_CPU_C::POPF_Fd(bxInstruction_c *i)
}
#if BX_SUPPORT_X86_64
void BX_CPU_C::PUSHF_Fq(bxInstruction_c *i)
{
// VM & RF flags cleared in image stored on the stack
push_64(read_eflags() & 0x00fcffff);
}
void BX_CPU_C::POPF_Fq(bxInstruction_c *i)
{
// Build a mask of the following bits:
// ID,VP,VF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
#if BX_CPU_LEVEL >= 4
changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC
#endif
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask
| EFlagsNTMask | EFlagsRFMask | EFlagsACMask
| EFlagsIDMask;
Bit64u flags64;
BX_ASSERT (protected_mode());
pop_64(&flags64);
Bit32u flags32 = flags64 & 0xffffffff;
Bit32u flags32 = (Bit32u) flags64;
if (CPL==0)
changeMask |= EFlagsIOPLMask;
if (CPL <= BX_CPU_THIS_PTR get_IOPL())

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: flag_ctrl_pro.cc,v 1.20 2005-10-16 23:13:19 sshwarts Exp $
// $Id: flag_ctrl_pro.cc,v 1.21 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -88,31 +88,6 @@ BX_CPU_C::write_flags(Bit16u flags, bx_bool change_IOPL, bx_bool change_IF)
writeEFlags(Bit32u(flags), changeMask);
}
#if BX_CPU_LEVEL >= 3
void BX_CPU_C::write_eflags(Bit32u eflags_raw, bx_bool change_IOPL,
bx_bool change_IF, bx_bool change_VM, bx_bool change_RF)
{
// Build a mask of the following bits:
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask;
#if BX_CPU_LEVEL >= 4
changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC
#endif
if (change_IOPL)
changeMask |= EFlagsIOPLMask;
if (change_IF)
changeMask |= EFlagsIFMask;
if (change_VM)
changeMask |= EFlagsVMMask;
if (change_RF)
changeMask |= EFlagsRFMask;
writeEFlags(eflags_raw, changeMask);
}
#endif /* BX_CPU_LEVEL >= 3 */
// Cause arithmetic flags to be in known state and cached in val32.
Bit32u BX_CPU_C::force_flags(void)
{

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: iret.cc,v 1.8 2005-10-16 23:13:19 sshwarts Exp $
// $Id: iret.cc,v 1.9 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -215,8 +215,21 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
/* load CS-cache with new code segment descriptor */
branch_far32(&cs_selector, &cs_descriptor, new_eip, cs_selector.rpl);
/* load EFLAGS with 3rd doubleword from stack */
write_eflags(new_eflags, CPL==0, CPL<=BX_CPU_THIS_PTR get_IOPL (), 0, 1);
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
#if BX_CPU_LEVEL >= 4
changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC
#endif
if (CPL <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
if (CPL == 0)
changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask;
// IF only changed if (CPL <= EFLAGS.IOPL)
// VIF, VIP, IOPL only changed if CPL == 0
// VM unaffected
writeEFlags(new_eflags, changeMask);
}
else {
/* load CS-cache with new code segment descriptor */
@ -326,13 +339,24 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
/* set CPL to the RPL of the return CS selector */
branch_far32(&cs_selector, &cs_descriptor, new_eip, cs_selector.rpl);
/* load flags from stack */
// perhaps I should always write_eflags(), thus zeroing
// out the upper 16bits of eflags for CS.D_B==0 ???
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
#if BX_CPU_LEVEL >= 4
changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC
#endif
if (prev_cpl <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
if (prev_cpl == 0)
changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask;
if (cs_descriptor.u.segment.d_b)
write_eflags(new_eflags, prev_cpl==0, prev_cpl<=BX_CPU_THIS_PTR get_IOPL(), 0, 1);
else
write_flags((Bit16u) new_eflags, prev_cpl==0, prev_cpl<=BX_CPU_THIS_PTR get_IOPL());
changeMask &= 0xffff;
// IF only changed if (prev_CPL <= EFLAGS.IOPL)
// VIF, VIP, IOPL only changed if prev_CPL == 0
// VM unaffected
writeEFlags(new_eflags, changeMask);
// load SS:eSP from stack
// load the SS-cache with SS descriptor
@ -473,8 +497,18 @@ BX_CPU_C::long_iret(bxInstruction_c *i)
/* load CS-cache with new code segment descriptor */
branch_far32(&cs_selector, &cs_descriptor, new_rip, CPL);
/* load EFLAGS with 3rd doubleword from stack */
write_eflags(new_eflags, CPL==0, CPL<=BX_CPU_THIS_PTR get_IOPL(), 0, 1);
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask |
EFlagsNTMask | EFlagsRFMask | EFlagsIDMask | EFlagsACMask;
if (CPL <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
if (CPL == 0)
changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask;
// IF only changed if (CPL <= EFLAGS.IOPL)
// VIF, VIP, IOPL only changed if CPL == 0
// VM unaffected
writeEFlags(new_eflags, changeMask);
/* we are NOT in 64-bit mode */
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
@ -570,13 +604,21 @@ BX_CPU_C::long_iret(bxInstruction_c *i)
/* set CPL to the RPL of the return CS selector */
branch_far64(&cs_selector, &cs_descriptor, new_rip, cs_selector.rpl);
/* load flags from stack */
// perhaps I should always write_eflags(), thus zeroing
// out the upper 16bits of eflags for CS.D_B==0 ???
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask |
EFlagsNTMask | EFlagsRFMask | EFlagsIDMask | EFlagsACMask;
if (prev_cpl <= BX_CPU_THIS_PTR get_IOPL())
changeMask |= EFlagsIFMask;
if (prev_cpl == 0)
changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask;
if (cs_descriptor.u.segment.d_b)
write_eflags(new_eflags, prev_cpl==0, prev_cpl<=BX_CPU_THIS_PTR get_IOPL(), 0, 1);
else
write_flags((Bit16u) new_eflags, prev_cpl==0, prev_cpl<=BX_CPU_THIS_PTR get_IOPL());
changeMask &= 0xffff;
// IF only changed if (prev_CPL <= EFLAGS.IOPL)
// VIF, VIP, IOPL only changed if prev_CPL == 0
// VM unaffected
writeEFlags(new_eflags, changeMask);
if ( (raw_ss_selector & 0xfffc) != 0 ) {
// load SS:RSP from stack

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.118 2005-10-16 23:13:19 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.119 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2012,7 +2012,7 @@ SYSCALL_LEGACY_MODE:
Bit32u dword1, dword2;
if (!BX_CPU_THIS_PTR msr.sce) {
exception(BX_GP_EXCEPTION, 0, 0);
exception(BX_UD_EXCEPTION, 0, 0);
}
invalidate_prefetch_q();
@ -2020,10 +2020,7 @@ SYSCALL_LEGACY_MODE:
if (BX_CPU_THIS_PTR msr.lma)
{
RCX = RIP;
#ifdef __GNUC__
#warning - PRT: SYSCALL -- do we reset RF/VM before saving to R11?
#endif
R11 = read_eflags();
R11 = read_eflags() & ~(EFlagsRFMask);
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
temp_RIP = MSR_LSTAR;
@ -2042,8 +2039,8 @@ SYSCALL_LEGACY_MODE:
parse_descriptor(dword1, dword2, &ss_descriptor);
load_ss(&ss_selector, &ss_descriptor, 0);
write_eflags(read_eflags() & (~MSR_FMASK),1,1,1,0);
BX_CPU_THIS_PTR clear_RF ();
writeEFlags(read_eflags() & (~MSR_FMASK), EFlagsValidMask);
BX_CPU_THIS_PTR clear_RF();
RIP = temp_RIP;
}
else {
@ -2132,7 +2129,7 @@ SYSRET_NON_64BIT_MODE:
Bit32u dword1, dword2;
if (!BX_CPU_THIS_PTR msr.sce) {
exception(BX_GP_EXCEPTION, 0, 0);
exception(BX_UD_EXCEPTION, 0, 0);
}
if(real_mode() || CPL != 0) {
@ -2168,7 +2165,7 @@ SYSRET_NON_64BIT_MODE:
load_ss(&ss_selector, &ss_descriptor, 0);
// SS base, limit, attributes unchanged.
write_eflags(R11,1,1,1,1);
writeEFlags(R11, EFlagsValidMask);
RIP = temp_RIP;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: stack_pro.cc,v 1.25 2005-08-28 17:37:37 sshwarts Exp $
// $Id: stack_pro.cc,v 1.26 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -55,7 +55,7 @@ BX_CPU_C::push_16(Bit16u value16)
}
}
/* push 32 bit operand size */
/* push 32 bit operand */
void BX_CPU_C::push_32(Bit32u value32)
{
/* must use StackAddrSize, and either RSP, ESP or SP accordingly */
@ -80,6 +80,7 @@ void BX_CPU_C::push_32(Bit32u value32)
}
}
/* push 64 bit operand */
void BX_CPU_C::push_64(Bit64u value64)
{
/* must use StackAddrSize, and either RSP, ESP or SP accordingly */
@ -104,6 +105,7 @@ void BX_CPU_C::push_64(Bit64u value64)
}
}
/* pop 16 bit operand from the stack */
void BX_CPU_C::pop_16(Bit16u *value16_ptr)
{
bx_address temp_RSP;
@ -120,7 +122,6 @@ void BX_CPU_C::pop_16(Bit16u *value16_ptr)
#endif
temp_RSP = SP;
/* access within limits */
read_virtual_word(BX_SEG_REG_SS, temp_RSP, value16_ptr);
#if BX_CPU_LEVEL >= 3
@ -136,6 +137,7 @@ void BX_CPU_C::pop_16(Bit16u *value16_ptr)
SP += 2;
}
/* pop 32 bit operand from the stack */
void BX_CPU_C::pop_32(Bit32u *value32_ptr)
{
bx_address temp_RSP;
@ -152,7 +154,6 @@ void BX_CPU_C::pop_32(Bit32u *value32_ptr)
#endif
temp_RSP = SP;
/* access within limits */
read_virtual_dword(BX_SEG_REG_SS, temp_RSP, value32_ptr);
#if BX_CPU_LEVEL >= 3
@ -168,6 +169,7 @@ void BX_CPU_C::pop_32(Bit32u *value32_ptr)
SP += 4;
}
/* pop 64 bit operand from the stack */
void BX_CPU_C::pop_64(Bit64u *value64_ptr)
{
bx_address temp_RSP;
@ -184,7 +186,6 @@ void BX_CPU_C::pop_64(Bit64u *value64_ptr)
#endif
temp_RSP = SP;
/* access within limits */
read_virtual_qword(BX_SEG_REG_SS, temp_RSP, value64_ptr);
#if BX_CPU_LEVEL >= 3

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.25 2005-09-03 11:39:26 sshwarts Exp $
// $Id: tasking.cc,v 1.26 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -460,7 +460,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
}
BX_CPU_THIS_PTR prev_eip = EIP = newEIP;
write_eflags(newEFLAGS, 1,1,1,1);
writeEFlags(newEFLAGS, EFlagsValidMask);
EAX = newEAX;
ECX = newECX;
EDX = newEDX;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vm8086.cc,v 1.21 2005-10-16 23:13:19 sshwarts Exp $
// $Id: vm8086.cc,v 1.22 2005-10-17 13:06:09 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -30,6 +30,12 @@
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_X86_64==0
// Make life easier for merging 64&32-bit code.
#define RIP EIP
#define RSP ESP
#endif
// Notes:
//
@ -55,9 +61,8 @@ void BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector,
Bit16u raw_es_selector, raw_ds_selector, raw_fs_selector,
raw_gs_selector, raw_ss_selector;
// Must be 32bit effective opsize, VM is in upper 16bits of eFLAGS
// CPL = 0 to get here
// Must be 32bit effective opsize, VM is set in upper 16bits of eFLAGS
// and CPL = 0 to get here
// ----------------
// | | OLD GS | eSP+32
@ -82,8 +87,7 @@ void BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector,
exception(BX_SS_EXCEPTION, 0, 0);
}
esp_laddr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base +
temp_ESP;
esp_laddr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base + temp_ESP;
// load SS:ESP from stack
access_linear(esp_laddr + 12, 4, 0, BX_READ, &new_esp);
@ -95,8 +99,7 @@ void BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector,
access_linear(esp_laddr + 28, 2, 0, BX_READ, &raw_fs_selector);
access_linear(esp_laddr + 32, 2, 0, BX_READ, &raw_gs_selector);
write_eflags(flags32, /*change IOPL*/ 1, /*change IF*/ 1,
/*change VM*/ 1, /*change RF*/ 1);
writeEFlags(flags32, EFlagsValidMask);
// load CS:IP from stack; already read and passed as args
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = raw_cs_selector;
@ -107,16 +110,61 @@ void BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value = raw_fs_selector;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = raw_gs_selector;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = raw_ss_selector;
#if BX_SUPPORT_X86_64
RSP = new_esp;
#else
ESP = new_esp; // Full 32bits are loaded.
#endif
RSP = new_esp; // full 32 bit are loaded
init_v8086_mode();
}
void BX_CPU_C::stack_return_from_v86(bxInstruction_c *i)
void BX_CPU_C::iret16_stack_return_from_v86(bxInstruction_c *i)
{
if ((BX_CPU_THIS_PTR get_IOPL() < 3) && (CR4_VME_ENABLED == 0)) {
// trap to virtual 8086 monitor
BX_DEBUG(("IRET in vm86 with IOPL != 3, VME = 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
Bit16u ip, cs_raw, flags16;
if( !can_pop(6) )
{
exception(BX_SS_EXCEPTION, 0, 0);
return;
}
pop_16(&ip);
pop_16(&cs_raw);
pop_16(&flags16);
#if BX_SUPPORT_VME
if (CR4_VME_ENABLED && BX_CPU_THIS_PTR get_IOPL() < 3)
{
if (((flags16 & EFlagsIFMask) && BX_CPU_THIS_PTR get_VIP()) ||
(flags16 & EFlagsTFMask))
{
BX_DEBUG(("iret16_stack_return_from_v86: #GP(0) in VME mode"));
exception(BX_GP_EXCEPTION, 0, 0);
}
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
RIP = (Bit32u) ip;
// IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF
Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
EFlagsDFMask | EFlagsNTMask | EFlagsVIFMask;
Bit32u flags32 = (Bit32u) flags16;
if (BX_CPU_THIS_PTR get_IF()) flags32 |= EFlagsVIFMask;
writeEFlags(flags32, changeMask);
return;
}
#endif
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
RIP = (Bit32u) ip;
write_flags(flags16, /*IOPL*/ 0, /*IF*/ 1);
}
void BX_CPU_C::iret32_stack_return_from_v86(bxInstruction_c *i)
{
if (BX_CPU_THIS_PTR get_IOPL() < 3) {
// trap to virtual 8086 monitor
@ -124,42 +172,68 @@ void BX_CPU_C::stack_return_from_v86(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0, 0);
}
if (i->os32L()) {
Bit32u eip, cs_raw, eflags_tmp;
Bit32u eip, cs_raw, flags32;
// Build a mask of the following bits:
// ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
Bit32u change_mask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsIFMask
| EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
if( !can_pop(12) )
{
exception(BX_SS_EXCEPTION, 0, 0);
return;
}
#if BX_CPU_LEVEL >= 4
change_mask |= (EFlagsIDMask | EFlagsACMask); // ID/AC
#endif
if( !can_pop(12) )
{
exception(BX_SS_EXCEPTION, 0, 0);
return;
}
pop_32(&eip);
pop_32(&cs_raw);
pop_32(&eflags_tmp);
pop_32(&eip);
pop_32(&cs_raw);
pop_32(&flags32);
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs_raw);
EIP = eip;
write_eflags(eflags_tmp, /*IOPL*/ 0, /*IF*/ 1, /*VM*/ 0, /*RF*/ 1);
}
else {
Bit16u ip, cs_raw, flags;
if( !can_pop(6) )
{
exception(BX_SS_EXCEPTION, 0, 0);
return;
}
pop_16(&ip);
pop_16(&cs_raw);
pop_16(&flags);
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
EIP = (Bit32u) ip;
write_flags(flags, /*IOPL*/ 0, /*IF*/ 1);
}
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs_raw);
RIP = eip;
// VIF, VIP, VM, IOPL unchanged
writeEFlags(flags32, change_mask);
}
#if BX_SUPPORT_VME
void BX_CPU_C::v86_redirect_interrupt(Bit32u vector)
{
Bit16u temp_IP, temp_CS, temp_flags = read_flags();
access_linear(vector*4, 2, 0, BX_READ, &temp_IP);
access_linear(vector*4 + 2, 2, 0, BX_READ, &temp_CS);
if (BX_CPU_THIS_PTR get_IOPL() < 3) {
temp_flags |= EFlagsIOPLMask;
if (BX_CPU_THIS_PTR get_VIF())
temp_flags |= EFlagsIFMask;
else
temp_flags &= ~EFlagsIFMask;
}
Bit16u old_IP = IP;
Bit16u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
push_16(temp_flags);
// push return address onto new stack
push_16(old_CS);
push_16(old_IP);
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) temp_CS);
RIP = temp_IP;
BX_CPU_THIS_PTR clear_TF ();
BX_CPU_THIS_PTR clear_RF ();
if (BX_CPU_THIS_PTR get_IOPL() == 3)
BX_CPU_THIS_PTR clear_IF ();
else
BX_CPU_THIS_PTR clear_VIF();
}
#endif
void BX_CPU_C::init_v8086_mode(void)
{
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
@ -265,13 +339,6 @@ void BX_CPU_C::init_v8086_mode(void)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.rpl = 3;
}
#if BX_SUPPORT_VME
void BX_CPU_C::v86_redirect_interrupt(Bit32u vector)
{
BX_PANIC(("Redirection of interrupts through virtual-mode idt still not implemented"));
}
#endif
#endif /* BX_CPU_LEVEL >= 3 */
#else // BX_SUPPORT_V8086_MODE