Changes list made after CVS service crash:

- Fixed critical bug in CPU code added with one of the prev commits
  - Disasm support for SSE4
  - Rename PNI->SSE3 everywhere in the code
  - Correctly decode, disassemble and execute 'XCHG R8, rAX' x86-64 instruction
  - Correctly decode, disassemble and execute multi-byte NOP 0F F1 opcode
  - Fixed ENTER and LEAVE instructions in x86-64 mode
  - Added ability to turn ON instruction trace, only GUI support is missed.
    Instruction trace could be enabled if Bochs was compiled with disasm
  - More changes Bit32u -> bx_phy_address
  - Complete preliminary implementation of SMM in Bochs, SMI is still PANICs but if you press 'continue' everything should work OK
  - Small code cleanup
  - Update CHANGES and user docs
This commit is contained in:
Stanislav Shwartsman 2006-04-05 17:31:35 +00:00
parent c2455e7c1e
commit f8c3968d42
29 changed files with 1208 additions and 491 deletions

View File

@ -1,22 +1,30 @@
Changes after 2.2.6 release:
- Fixed bug in FSTENV instruction (Stanislav Shwartsman)
- Recognize #XF exception (19) when SSE is enabled
- Fixed bug in SYSRET instruction legacy mode
- Fixed bug in PSRAW/PSRAD MMX and SSE instructions
- Fixed bug in CALL/JMP far through call gate 64 in x86-64 mode
- Fixed bug in ENTER instruction in x86-64 mode (Stanislav Shwartsman)
- Fixes in Bochs debugger and disassembler
- Save and restore RIP/RSP only for FAULT-type exceptions, not for traps
- Moved configure time --enable-reset-on-triple-fault option to runtime,
the 'cpu' option in .bochsrc is extended and the old configure option
is deprecated (Stanislav Shwartsman)
- Support for Dual Core and Intel(R) HyperThreading Technology. Now you
could choose amount of cores per processor and amount of HT threads per
core from .bochsrc for SMP simulation (Stanislav Shwartsman)
- Removed --enable-pni configure option, to compile with PNI use
--enable-sse=3 instead (Stanislav Shwartsman)
- Raise A20 line after system reset (Stanislav Shwartsman)
- CPU and internal debugger fixes
- Fixed bug in FSTENV instruction (Stanislav Shwartsman)
- Recognize #XF exception (19) when SSE is enabled
- Fixed bug in SYSRET instruction legacy mode
- Fixed bug in PSRAW/PSRAD MMX and SSE instructions
- Fixed bug in CALL/JMP far through call gate 64 in x86-64 mode
- Correctly decode, disassemble and execute 'XCHG R8, rAX' x86-64 instruction
- Correctly decode, disassemble and execute multi-byte NOP 0F F1 opcode
- Fixed ENTER and LEAVE instructions in x86-64 mode (Stanislav)
- Save and restore RIP/RSP only for FAULT-type exceptions, not for traps
- Raise A20 line after system reset (Stanislav Shwartsman)
- Implemented NMI delivery (Stanislav)
- Many fixes in Bochs debugger and disassembler
- SMP
- Support for Dual Core and Intel(R) HyperThreading Technology. Now you
could choose amount of cores per processor and amount of HT threads per
core from .bochsrc for SMP simulation (Stanislav Shwartsman)
- Configure and compile
- Moved configure time --enable-reset-on-triple-fault option to runtime,
the 'cpu' option in .bochsrc is extended and the old configure option
is deprecated (Stanislav Shwartsman)
- Removed --enable-pni configure option, to compile with PNI use
--enable-sse=3 instead (Stanislav Shwartsman)
-------------------------------------------------------------------------
Changes in 2.2.6 (January 29, 2006):

View File

@ -512,7 +512,7 @@ smm.o: smm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../cpu/cpu.h ../cpu/descriptor.h \
../cpu/lazy_flags.h ../cpu/hostasm.h ../cpu/icache.h ../cpu/apic.h \
../cpu/i387.h ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h \
../fpu/control_w.h ../cpu/xmm.h ../memory/memory.h ../pc_system.h \
../fpu/control_w.h ../cpu/xmm.h ../cpu/smm.h ../memory/memory.h ../pc_system.h \
../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
../gui/keymap.h ../instrument/stubs/instrument.h
protect_ctrl.o: protect_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.80 2006-03-06 22:02:51 sshwarts Exp $
// $Id: apic.cc,v 1.81 2006-04-05 17:31:29 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -175,8 +175,8 @@ void bx_generic_apic_c::set_id(Bit8u newid)
bx_bool bx_generic_apic_c::is_selected(bx_phy_address addr, unsigned len)
{
if((addr & ~0xfff) == get_base()) {
if(((addr & 0xf) != 0) || (len != 4))
BX_INFO(("warning: misaligned or wrong-size APIC access. len=%d, addr=%08x", len, addr));
if((addr & 0xf) != 0)
BX_INFO(("warning: misaligned APIC access. addr=%08x, len=%d", addr, len));
return 1;
}
return 0;
@ -665,6 +665,8 @@ bx_bool bx_local_apic_c::deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_m
return 0;
case APIC_DM_NMI:
BX_PANIC(("Delivery of NMI still not implemented !"));
cpu->async_event = 1;
cpu->nmi_pending = 1;
return 0;
case APIC_DM_INIT:
BX_DEBUG(("Deliver INIT IPI"));

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.141 2006-03-26 19:39:37 sshwarts Exp $
// $Id: cpu.cc,v 1.142 2006-04-05 17:31:29 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -228,10 +228,10 @@ void BX_CPU_C::cpu_loop(Bit32s max_instr_count)
// or the boundary fetch (across pages), by this point.
BX_INSTR_FETCH_DECODE_COMPLETED(BX_CPU_ID, i);
#if BX_DEBUGGER
#if BX_DISASM
if (BX_CPU_THIS_PTR trace) {
// print the instruction that is about to be executed.
bx_dbg_disassemble_current(BX_CPU_ID, 1); // only one cpu, print time stamp
// print the instruction that is about to be executed
debug_disasm_instruction(BX_CPU_THIS_PTR prev_eip);
}
#endif
@ -573,10 +573,10 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
// (bochs doesn't support these)
if (BX_CPU_THIS_PTR smi_pending && ! BX_CPU_THIS_PTR smm_mode())
{
BX_PANIC(("SMI: system management mode still not implemented !"));
// clear SMI pending flag and NMI disable flag when SMM was accepted
// clear SMI pending flag and disable NMI when SMM was accepted
BX_CPU_THIS_PTR smi_pending = 0;
BX_CPU_THIS_PTR nmi_disable = 1;
enter_system_management_mode();
}
// Priority 4: Traps on Previous Instruction
@ -687,9 +687,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
else {
// only bother comparing if any breakpoints enabled
if (BX_CPU_THIS_PTR dr7 & 0x000000ff) {
Bit32u iaddr =
BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS) +
BX_CPU_THIS_PTR prev_eip;
Bit32u iaddr = BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS) + BX_CPU_THIS_PTR prev_eip;
Bit32u dr6_bits;
if ( (dr6_bits = hwdebug_compare(iaddr, 1, BX_HWDebugInstruction,
BX_HWDebugInstruction)) )

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.275 2006-03-29 18:08:13 sshwarts Exp $
// $Id: cpu.h,v 1.276 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -903,9 +903,9 @@ typedef void (BX_CPU_C::*BxExecutePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN
typedef bx_ptr_equiv_t bx_hostpageaddr_t;
typedef struct {
bx_address lpf; // linear page frame
Bit32u ppf; // physical page frame
Bit32u accessBits; // Page Table Address for updating A & D bits
bx_address lpf; // linear page frame
bx_phy_address ppf; // physical page frame
Bit32u accessBits; // Page Table Address for updating A & D bits
bx_hostpageaddr_t hostPageAddr;
} bx_TLB_entry;
#endif // #if BX_USE_TLB
@ -1102,11 +1102,11 @@ public: // for now...
/* Control registers */
#if BX_CPU_LEVEL >= 2
bx_cr0_t cr0;
Bit32u cr1;
bx_address cr2;
bx_address cr3;
bx_address cr3_masked;
bx_cr0_t cr0;
Bit32u cr1;
bx_address cr2;
bx_phy_address cr3;
bx_phy_address cr3_masked;
#endif
#if BX_CPU_LEVEL >= 4
@ -1232,7 +1232,7 @@ public: // for now...
#if BX_SUPPORT_ICACHE
bxICache_c iCache BX_CPP_AlignN(32);
Bit32u fetchModeMask;
Bit32u updateFetchModeMask(void);
void updateFetchModeMask(void);
#endif
struct {
@ -1255,7 +1255,7 @@ public: // for now...
virtual void ask (int level, const char *prefix, const char *fmt, va_list ap);
#endif
void setEFlags(Bit32u val) BX_CPP_AttrRegparmN(1);
BX_SMF void setEFlags(Bit32u val) BX_CPP_AttrRegparmN(1);
#define lfMaskCF 0x0000000f
#define lfMaskPF 0x000000f0
@ -2622,7 +2622,6 @@ public: // for now...
BX_SMF unsigned dbg_query_pending(void);
BX_SMF Bit32u dbg_get_descriptor_l(bx_descriptor_t *);
BX_SMF Bit32u dbg_get_descriptor_h(bx_descriptor_t *);
BX_SMF Bit32u dbg_get_eflags(void);
BX_SMF bx_bool dbg_is_begin_instr_bpoint(Bit16u cs, bx_address eip, bx_address laddr, bx_bool is_32, bx_bool is_64);
BX_SMF bx_bool dbg_is_end_instr_bpoint(Bit16u cs, bx_address eip, bx_address laddr, bx_bool is_32, bx_bool is_64);
#endif
@ -2743,12 +2742,18 @@ public: // for now...
BX_SMF void smram_save_state(Bit32u *smm_saved_state);
BX_SMF bx_bool smram_restore_state(const Bit32u *smm_saved_state);
BX_SMF int int_number(bx_segment_reg_t *seg);
BX_SMF void CR3_change(bx_address value) BX_CPP_AttrRegparmN(1);
BX_SMF void SetCR0(Bit32u val_32);
BX_SMF void CR3_change(bx_phy_address value) BX_CPP_AttrRegparmN(1);
#if BX_CPU_LEVEL >= 4
BX_SMF bx_bool SetCR4(Bit32u val_32);
#endif
BX_SMF void pagingCR0Changed(Bit32u oldCR0, Bit32u newCR0) BX_CPP_AttrRegparmN(2);
BX_SMF void pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4) BX_CPP_AttrRegparmN(2);
BX_SMF void pagingA20Changed(void);
BX_SMF void reset(unsigned source);
BX_SMF void shutdown(void);
BX_SMF void handleCpuModeChange(void);
BX_SMF void jump_protected(bxInstruction_c *, Bit16u cs, bx_address disp) BX_CPP_AttrRegparmN(3);
BX_SMF void jmp_task_gate(bx_descriptor_t *gate_descriptor) BX_CPP_AttrRegparmN(1);
@ -2802,6 +2807,8 @@ public: // for now...
BX_SMF void parse_selector(Bit16u raw_selector, bx_selector_t *selector) BX_CPP_AttrRegparmN(2);
BX_SMF void parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp) BX_CPP_AttrRegparmN(3);
BX_SMF Bit16u get_segment_ar_data(bx_descriptor_t *d) BX_CPP_AttrRegparmN(1);
BX_SMF bx_bool set_segment_ar_data(bx_segment_reg_t *seg, Bit16u raw_selector,
bx_address base, Bit32u limit, Bit16u ar_data);
BX_SMF void load_ldtr(bx_selector_t *selector, bx_descriptor_t *descriptor);
BX_SMF void check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_rpl, Bit8u check_cpl);
BX_SMF void load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) BX_CPP_AttrRegparmN(3);
@ -2922,18 +2929,13 @@ public: // for now...
BX_SMF void check_exceptionsSSE(int);
BX_SMF void print_state_SSE(void);
#endif
BX_SMF void SetCR0(Bit32u val_32);
#if BX_CPU_LEVEL >= 4
BX_SMF bx_bool SetCR4(Bit32u val_32);
#endif
};
#if BX_SUPPORT_ICACHE
BX_CPP_INLINE Bit32u BX_CPU_C::updateFetchModeMask(void)
BX_CPP_INLINE void BX_CPU_C::updateFetchModeMask(void)
{
return (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b << 31)
fetchModeMask = (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b << 31)
#if BX_SUPPORT_X86_64
| ((BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)<<30)
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpuid.cc,v 1.34 2006-03-06 22:02:52 sshwarts Exp $
// $Id: cpuid.cc,v 1.35 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -246,7 +246,7 @@ void BX_CPU_C::CPUID(bxInstruction_c *i)
// [23:16] Number of logical processors in one physical processor
// [31:24] Local Apic ID
// ECX: Feature Flags::Extended
// [0:0] PNI
// [0:0] SSE3
// [2:1] Reserved
// [3:3] MONITOR/MWAIT
// [4:4] CPL qualified debug store available

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: data_xfer32.cc,v 1.37 2006-03-26 18:58:01 sshwarts Exp $
// $Id: data_xfer32.cc,v 1.38 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -34,13 +34,12 @@
void BX_CPU_C::XCHG_ERXEAX(bxInstruction_c *i)
{
Bit32u temp32 = EAX;
#if BX_SUPPORT_X86_64
RAX = BX_CPU_THIS_PTR gen_reg[i->opcodeReg()].dword.erx;
BX_CPU_THIS_PTR gen_reg[i->opcodeReg()].dword.erx = temp32;
RAX = BX_READ_32BIT_REG(i->opcodeReg());
BX_WRITE_32BIT_REGZ(i->opcodeReg(), temp32);
#else
EAX = BX_CPU_THIS_PTR gen_reg[i->opcodeReg()].dword.erx;
BX_CPU_THIS_PTR gen_reg[i->opcodeReg()].dword.erx = temp32;
EAX = BX_READ_32BIT_REG(i->opcodeReg());
BX_WRITE_32BIT_REG(i->opcodeReg(), temp32);
#endif
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: debugstuff.cc,v 1.62 2006-03-29 18:08:13 sshwarts Exp $
// $Id: debugstuff.cc,v 1.63 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -37,23 +37,34 @@ void BX_CPU_C::debug_disasm_instruction(bx_address offset)
bx_bool valid;
Bit32u phy_addr;
Bit8u instr_buf[16];
char char_buf[256];
unsigned isize;
char char_buf[512];
unsigned isize, i=0;
static char letters[20] = "0123456789ABCDEF";
static disassembler bx_disassemble;
dbg_xlate_linear2phy(BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS) + offset,
&phy_addr, &valid);
if (valid && BX_CPU_THIS_PTR mem!=NULL) {
BX_CPU_THIS_PTR mem->dbg_fetch_mem(phy_addr, 16, instr_buf);
char_buf[i++] = '>';
char_buf[i++] = '>';
char_buf[i++] = ' ';
isize = bx_disassemble.disasm(
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b,
BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64,
BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS), offset,
instr_buf, char_buf);
for (unsigned j=0; j<isize; j++)
BX_INFO((">> %02x", (unsigned) instr_buf[j]));
BX_INFO((">> : %s", char_buf));
instr_buf, char_buf+i);
i=strlen(char_buf);
char_buf[i++] = ' ';
char_buf[i++] = ':';
char_buf[i++] = ' ';
for (unsigned j=0; j<isize; j++) {
char_buf[i++] = letters[(instr_buf[j] >> 4) & 0xf];
char_buf[i++] = letters[(instr_buf[j] >> 0) & 0xf];
}
char_buf[i] = 0;
BX_INFO(("%s", char_buf));
}
else {
BX_INFO(("(instruction unavailable) page not present"));
@ -206,10 +217,8 @@ void BX_CPU_C::debug(bx_address offset)
(unsigned) (BX_CPU_THIS_PTR cr0.val32), 0,
(unsigned) (BX_CPU_THIS_PTR cr2 >> 32),
(unsigned) (BX_CPU_THIS_PTR cr2 & 0xffffffff)));
BX_INFO(("| CR3=0x%08x%08x CR4=0x%08x",
(unsigned) (BX_CPU_THIS_PTR cr3 >> 32),
(unsigned) (BX_CPU_THIS_PTR cr3 & 0xffffffff),
BX_CPU_THIS_PTR cr4.getRegister()));
BX_INFO(("| CR3=0x%08x CR4=0x%08x",
(unsigned) BX_CPU_THIS_PTR cr3, BX_CPU_THIS_PTR cr4.getRegister()));
#else
BX_INFO(("| EIP=%08x (%08x)", (unsigned) EIP,
(unsigned) BX_CPU_THIS_PTR prev_eip));
@ -245,7 +254,7 @@ Bit32u BX_CPU_C::dbg_get_reg(unsigned reg)
switch (reg) {
case BX_DBG_REG_EIP: return(EIP);
case BX_DBG_REG_EFLAGS:
return_val32 = dbg_get_eflags();
return_val32 = BX_CPU_THIS_PTR read_eflags();
return(return_val32);
case BX_DBG_REG_CS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
case BX_DBG_REG_SS: return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value);
@ -269,7 +278,7 @@ bx_bool BX_CPU_C::dbg_set_reg(unsigned reg, Bit32u val)
case BX_DBG_REG_EIP: EIP = val; return(1);
case BX_DBG_REG_EFLAGS:
BX_INFO(("dbg_set_reg: can not handle eflags yet."));
if ( val & 0xffff0000 ) {
if (val & 0xffff0000) {
BX_INFO(("dbg_set_reg: can not set upper 16 bits of eflags."));
return(0);
}
@ -357,11 +366,6 @@ unsigned BX_CPU_C::dbg_query_pending(void)
return(ret);
}
Bit32u BX_CPU_C::dbg_get_eflags(void)
{
return (BX_CPU_THIS_PTR read_eflags());
}
Bit32u BX_CPU_C::dbg_get_descriptor_l(bx_descriptor_t *d)
{
Bit32u val;
@ -489,14 +493,13 @@ bx_bool BX_CPU_C::dbg_get_cpu(bx_dbg_cpu_t *cpu)
cpu->ebx = EBX;
cpu->ecx = ECX;
cpu->edx = EDX;
cpu->ebp = EBP;
cpu->esi = ESI;
cpu->edi = EDI;
cpu->esp = ESP;
cpu->eip = EIP;
cpu->eflags = dbg_get_eflags();
cpu->eip = EIP;
cpu->eflags = BX_CPU_THIS_PTR read_eflags();
cpu->cs.sel = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
cpu->cs.des_l = dbg_get_descriptor_l(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache);
@ -552,7 +555,6 @@ bx_bool BX_CPU_C::dbg_get_cpu(bx_dbg_cpu_t *cpu)
cpu->dr7 = BX_CPU_THIS_PTR dr7;
#if BX_CPU_LEVEL >= 2
// cr0:32=pg,cd,nw,am,wp,ne,ts,em,mp,pe
cpu->cr0 = BX_CPU_THIS_PTR cr0.val32;
cpu->cr1 = 0;
cpu->cr2 = BX_CPU_THIS_PTR cr2;
@ -579,75 +581,75 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
// CS, SS, DS, ES, FS, GS descriptor checks
if (!cpu->cs.valid) {
BX_ERROR(( "Error: CS not valid" ));
BX_ERROR(("Error: CS not valid"));
return(0); // error
}
if ( (cpu->cs.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: CS not application type" ));
if ((cpu->cs.des_h & 0x1000) == 0) {
BX_ERROR(("Error: CS not application type"));
return(0); // error
}
if ( (cpu->cs.des_h & 0x0800) == 0 ) {
BX_ERROR(( "Error: CS not executable" ));
if ((cpu->cs.des_h & 0x0800) == 0) {
BX_ERROR(("Error: CS not executable"));
return(0); // error
}
if (!cpu->ss.valid) {
BX_ERROR(( "Error: SS not valid" ));
BX_ERROR(("Error: SS not valid"));
return(0); // error
}
if ( (cpu->ss.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: SS not application type" ));
if ((cpu->ss.des_h & 0x1000) == 0) {
BX_ERROR(("Error: SS not application type"));
return(0); // error
}
if (cpu->ds.valid) {
if ( (cpu->ds.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: DS not application type" ));
if ((cpu->ds.des_h & 0x1000) == 0) {
BX_ERROR(("Error: DS not application type"));
return(0); // error
}
}
if (cpu->es.valid) {
if ( (cpu->es.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: ES not application type" ));
if ((cpu->es.des_h & 0x1000) == 0) {
BX_ERROR(("Error: ES not application type"));
return(0); // error
}
}
if (cpu->fs.valid) {
if ( (cpu->fs.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: FS not application type" ));
if ((cpu->fs.des_h & 0x1000) == 0) {
BX_ERROR(("Error: FS not application type"));
return(0); // error
}
}
if (cpu->gs.valid) {
if ( (cpu->gs.des_h & 0x1000) == 0 ) {
BX_ERROR(( "Error: GS not application type" ));
if ((cpu->gs.des_h & 0x1000) == 0) {
BX_ERROR(("Error: GS not application type"));
return(0); // error
}
}
if (cpu->ldtr.valid) {
if ( cpu->ldtr.des_h & 0x1000 ) {
BX_ERROR(( "Error: LDTR not system type" ));
if (cpu->ldtr.des_h & 0x1000) {
BX_ERROR(("Error: LDTR not system type"));
return(0); // error
}
if ( ((cpu->ldtr.des_h >> 8) & 0x0f) != 2 ) {
BX_ERROR(( "Error: LDTR descriptor type not LDT" ));
if (((cpu->ldtr.des_h >> 8) & 0x0f) != BX_SYS_SEGMENT_LDT) {
BX_ERROR(("Error: LDTR descriptor type not LDT"));
return(0); // error
}
}
if (cpu->tr.valid) {
if ( cpu->tr.des_h & 0x1000 ) {
BX_ERROR(( "Error: TR not system type"));
if (cpu->tr.des_h & 0x1000) {
BX_ERROR(("Error: TR not system type"));
return(0); // error
}
type = (cpu->tr.des_h >> 8) & 0x0f;
if ( (type != 1) && (type != 9) ) {
BX_ERROR(( "Error: TR descriptor type not TSS" ));
if ((type != 1) && (type != 9)) {
BX_ERROR(("Error: TR descriptor type not TSS"));
return(0); // error
}
}
@ -664,33 +666,10 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
ESI = cpu->esi;
EDI = cpu->edi;
ESP = cpu->esp;
// eflags
val = cpu->eflags;
BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2;
BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2;
BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2;
BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_TF (val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_IF (val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_DF (val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_OF(val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_IOPL (val & 0x03); val >>= 2;
BX_CPU_THIS_PTR set_NT (val & 0x01); val >>= 2;
BX_CPU_THIS_PTR set_RF (val & 0x01); val >>= 1;
BX_CPU_THIS_PTR set_VM (val & 0x01); val >>= 1;
#if BX_CPU_LEVEL >= 4
BX_CPU_THIS_PTR set_AC (val & 0x01); val >>= 1;
//BX_CPU_THIS_PTR eflags.set_VIF (val & 0x01);
val >>= 1;
//BX_CPU_THIS_PTR eflags.set_VIP (val & 0x01);
val >>= 1;
BX_CPU_THIS_PTR set_ID (val & 0x01);
#endif
EIP = cpu->eip;
setEFlags(cpu->eflags);
// CS:
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = cpu->cs.sel;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = cpu->cs.sel >> 3;
@ -755,7 +734,6 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit;
// DS:
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = cpu->ds.sel;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index = cpu->ds.sel >> 3;
@ -786,7 +764,6 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit;
// ES:
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = cpu->es.sel;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.index = cpu->es.sel >> 3;
@ -817,7 +794,6 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit_scaled =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit;
// FS:
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value = cpu->fs.sel;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.index = cpu->fs.sel >> 3;
@ -848,7 +824,6 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit_scaled =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit;
// GS:
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = cpu->gs.sel;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.index = cpu->gs.sel >> 3;
@ -879,21 +854,21 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit_scaled =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit;
// LDTR:
// LDTR
BX_CPU_THIS_PTR ldtr.selector.value = cpu->ldtr.sel;
BX_CPU_THIS_PTR ldtr.selector.index = cpu->ldtr.sel >> 3;
BX_CPU_THIS_PTR ldtr.selector.ti = (cpu->ldtr.sel >> 2) & 0x01;
BX_CPU_THIS_PTR ldtr.selector.rpl = cpu->ldtr.sel & 0x03;
BX_CPU_THIS_PTR ldtr.cache.valid = cpu->ldtr.valid;
BX_CPU_THIS_PTR ldtr.cache.p = (cpu->ldtr.des_h >> 15) & 0x01;
BX_CPU_THIS_PTR ldtr.cache.dpl = (cpu->ldtr.des_h >> 13) & 0x03;
BX_CPU_THIS_PTR ldtr.cache.segment = (cpu->ldtr.des_h >> 12) & 0x01;
BX_CPU_THIS_PTR ldtr.cache.type = (cpu->ldtr.des_h >> 8) & 0x0f;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base = (cpu->ldtr.des_l >> 16);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff) << 16;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff000000);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = (cpu->ldtr.des_l & 0xffff);
BX_CPU_THIS_PTR ldtr.cache.valid = cpu->ldtr.valid;
BX_CPU_THIS_PTR ldtr.cache.p = (cpu->ldtr.des_h >> 15) & 0x01;
BX_CPU_THIS_PTR ldtr.cache.dpl = (cpu->ldtr.des_h >> 13) & 0x03;
BX_CPU_THIS_PTR ldtr.cache.segment = (cpu->ldtr.des_h >> 12) & 0x01;
BX_CPU_THIS_PTR ldtr.cache.type = (cpu->ldtr.des_h >> 8) & 0x0f;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base = (cpu->ldtr.des_l >> 16);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff) << 16;
BX_CPU_THIS_PTR ldtr.cache.u.ldt.base |= (cpu->ldtr.des_h & 0xff000000);
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit = (cpu->ldtr.des_l & 0xffff);
// TR
type = (cpu->tr.des_h >> 8) & 0x0f;
@ -903,16 +878,16 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR tr.selector.ti = (cpu->tr.sel >> 2) & 0x01;
BX_CPU_THIS_PTR tr.selector.rpl = cpu->tr.sel & 0x03;
BX_CPU_THIS_PTR tr.cache.valid = cpu->tr.valid;
BX_CPU_THIS_PTR tr.cache.p = (cpu->tr.des_h >> 15) & 0x01;
BX_CPU_THIS_PTR tr.cache.dpl = (cpu->tr.des_h >> 13) & 0x03;
BX_CPU_THIS_PTR tr.cache.segment = (cpu->tr.des_h >> 12) & 0x01;
BX_CPU_THIS_PTR tr.cache.type = type;
BX_CPU_THIS_PTR tr.cache.valid = cpu->tr.valid;
BX_CPU_THIS_PTR tr.cache.p = (cpu->tr.des_h >> 15) & 0x01;
BX_CPU_THIS_PTR tr.cache.dpl = (cpu->tr.des_h >> 13) & 0x03;
BX_CPU_THIS_PTR tr.cache.segment = (cpu->tr.des_h >> 12) & 0x01;
BX_CPU_THIS_PTR tr.cache.type = type;
if (type == 1) { // 286 TSS
BX_CPU_THIS_PTR tr.cache.u.tss286.base = (cpu->tr.des_l >> 16);
BX_CPU_THIS_PTR tr.cache.u.tss286.base |= (cpu->tr.des_h & 0xff) << 16;
BX_CPU_THIS_PTR tr.cache.u.tss286.limit = (cpu->tr.des_l & 0xffff);
}
}
else { // type == 9, 386 TSS
BX_CPU_THIS_PTR tr.cache.u.tss386.base = (cpu->tr.des_l >> 16);
BX_CPU_THIS_PTR tr.cache.u.tss386.base |= (cpu->tr.des_h & 0xff) << 16;
@ -921,14 +896,13 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
BX_CPU_THIS_PTR tr.cache.u.tss386.limit |= (cpu->tr.des_h & 0x000f0000);
BX_CPU_THIS_PTR tr.cache.u.tss386.g = (cpu->tr.des_h >> 23) & 0x01;
BX_CPU_THIS_PTR tr.cache.u.tss386.avl = (cpu->tr.des_h >> 20) & 0x01;
}
}
// gdtr
// GDTR
BX_CPU_THIS_PTR gdtr.base = cpu->gdtr.base;
BX_CPU_THIS_PTR gdtr.limit = cpu->gdtr.limit;
// idtr
// IDTR
BX_CPU_THIS_PTR idtr.base = cpu->idtr.base;
BX_CPU_THIS_PTR idtr.limit = cpu->idtr.limit;
@ -945,7 +919,7 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
SetCR0(cpu->cr0);
BX_CPU_THIS_PTR cr1 = cpu->cr1;
BX_CPU_THIS_PTR cr2 = cpu->cr2;
BX_CPU_THIS_PTR cr3 = cpu->cr3;
CR3_change(cpu->cr3);
#endif
#if BX_CPU_LEVEL >= 4
BX_CPU_THIS_PTR cr4.setRegister(cpu->cr4);
@ -956,7 +930,6 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu_t *cpu)
//
// flush cached items, prefetch, paging, etc
//
BX_CPU_THIS_PTR CR3_change(cpu->cr3);
BX_CPU_THIS_PTR invalidate_prefetch_q();
BX_CPU_THIS_PTR async_event = 1;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.76 2006-03-06 22:02:53 sshwarts Exp $
// $Id: exception.cc,v 1.77 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -858,6 +858,7 @@ void BX_CPU_C::exception(unsigned vector, Bit16u error_code, bx_bool is_INT)
else {
BX_PANIC(("exception(): 3rd (%d) exception with no resolution", vector));
BX_ERROR(("WARNING: Any simulation after this point is completely bogus !"));
shutdown();
}
#if BX_DEBUGGER
bx_guard.special_unwind_stack = true;

View File

@ -95,14 +95,13 @@ void bx_external_debugger(BX_CPU_C *cpu)
regs.fsbase = cpu->sregs[BX_SEG_REG_FS].cache.u.segment.base;
regs.gsbase = cpu->sregs[BX_SEG_REG_GS].cache.u.segment.base;
#if BX_SUPPORT_X86_64
regs.efer = cpu->get_EFER();
regs.efer = cpu->get_EFER();
#else
regs.efer = 0;
regs.efer = 0;
#endif
if (debug_loaded == 0) {
HINSTANCE hdbg;
debug_loaded = 1;
hdbg = LoadLibrary("debug.dll");
call_debugger = (void (*)(TRegs *,Bit8u *, Bit32u)) GetProcAddress(hdbg,"call_debugger");

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.cc,v 1.89 2006-03-22 20:47:11 sshwarts Exp $
// $Id: fetchdecode.cc,v 1.90 2006-04-05 17:31:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -721,7 +721,11 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F 1C */ { 0, &BX_CPU_C::BxError },
/* 0F 1D */ { 0, &BX_CPU_C::BxError },
/* 0F 1E */ { 0, &BX_CPU_C::BxError },
#if BX_CPU_LEVEL < 6
/* 0F 1F */ { 0, &BX_CPU_C::BxError },
#else
/* 0F 1F */ { BxAnother, &BX_CPU_C::NOP }, // multi-byte NOP
#endif
/* 0F 20 */ { BxAnother, &BX_CPU_C::MOV_RdCd },
/* 0F 21 */ { BxAnother, &BX_CPU_C::MOV_RdDd },
/* 0F 22 */ { BxAnother, &BX_CPU_C::MOV_CdRd },
@ -1267,7 +1271,11 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F 1C */ { 0, &BX_CPU_C::BxError },
/* 0F 1D */ { 0, &BX_CPU_C::BxError },
/* 0F 1E */ { 0, &BX_CPU_C::BxError },
#if BX_CPU_LEVEL < 6
/* 0F 1F */ { 0, &BX_CPU_C::BxError },
#else
/* 0F 1F */ { BxAnother, &BX_CPU_C::NOP }, // multi-byte NOP
#endif
/* 0F 20 */ { BxAnother, &BX_CPU_C::MOV_RdCd },
/* 0F 21 */ { BxAnother, &BX_CPU_C::MOV_RdDd },
/* 0F 22 */ { BxAnother, &BX_CPU_C::MOV_CdRd },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.h,v 1.21 2006-03-22 20:47:11 sshwarts Exp $
// $Id: fetchdecode.h,v 1.22 2006-04-05 17:31:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Stanislav Shwartsman
@ -123,7 +123,7 @@ static BxOpcodeInfo_t BxOpcodeInfo_FPGroupD8[8] = {
/* 0 */ { 0, &BX_CPU_C::FADD_SINGLE_REAL },
/* 1 */ { 0, &BX_CPU_C::FMUL_SINGLE_REAL },
/* 2 */ { 0, &BX_CPU_C::FCOM_SINGLE_REAL },
/* 3 */ { 0, &BX_CPU_C::FCOM_SINGLE_REAL }, // FCOMP_SINGLE_REAL
/* 3 */ { 0, &BX_CPU_C::FCOM_SINGLE_REAL }, // FCOMP_SINGLE_REAL
/* 4 */ { 0, &BX_CPU_C::FSUB_SINGLE_REAL },
/* 5 */ { 0, &BX_CPU_C::FSUBR_SINGLE_REAL },
/* 6 */ { 0, &BX_CPU_C::FDIV_SINGLE_REAL },
@ -171,7 +171,7 @@ static BxOpcodeInfo_t BxOpcodeInfo_FPGroupDC[8] = {
/* 0 */ { 0, &BX_CPU_C::FADD_DOUBLE_REAL },
/* 1 */ { 0, &BX_CPU_C::FMUL_DOUBLE_REAL },
/* 2 */ { 0, &BX_CPU_C::FCOM_DOUBLE_REAL },
/* 3 */ { 0, &BX_CPU_C::FCOM_DOUBLE_REAL }, // FCOMP_DOUBLE_REAL
/* 3 */ { 0, &BX_CPU_C::FCOM_DOUBLE_REAL }, // FCOMP_DOUBLE_REAL
/* 4 */ { 0, &BX_CPU_C::FSUB_DOUBLE_REAL },
/* 5 */ { 0, &BX_CPU_C::FSUBR_DOUBLE_REAL },
/* 6 */ { 0, &BX_CPU_C::FDIV_DOUBLE_REAL },
@ -1037,8 +1037,8 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f11[4] = {
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f12[4] = {
/* -- */ { 0, &BX_CPU_C::MOVLPS_VpsMq },
/* 66 */ { 0, &BX_CPU_C::MOVLPD_VsdMq },
/* F2 */ { 0, &BX_CPU_C::MOVDDUP_VpdWq }, // PNI
/* F3 */ { 0, &BX_CPU_C::MOVSLDUP_VpsWps } // PNI
/* F2 */ { 0, &BX_CPU_C::MOVDDUP_VpdWq }, // SSE3
/* F3 */ { 0, &BX_CPU_C::MOVSLDUP_VpsWps } // SSE3
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f13[4] = {
@ -1066,7 +1066,7 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f16[4] = {
/* -- */ { 0, &BX_CPU_C::MOVHPS_VpsMq },
/* 66 */ { 0, &BX_CPU_C::MOVHPD_VsdMq },
/* F2 */ { 0, &BX_CPU_C::BxError },
/* F3 */ { 0, &BX_CPU_C::MOVSHDUP_VpsWps } // PNI
/* F3 */ { 0, &BX_CPU_C::MOVSHDUP_VpsWps } // SSE3
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f17[4] = {
@ -1386,15 +1386,15 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0f76[4] = {
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7c[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::HADDPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::HADDPS_VpsWps }, // PNI
/* 66 */ { 0, &BX_CPU_C::HADDPD_VpdWpd }, // SSE3
/* F2 */ { 0, &BX_CPU_C::HADDPS_VpsWps }, // SSE3
/* F3 */ { 0, &BX_CPU_C::BxError }
};
static BxOpcodeInfo_t BxOpcodeGroupSSE_0f7d[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::HSUBPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::HSUBPS_VpsWps }, // PNI
/* 66 */ { 0, &BX_CPU_C::HSUBPD_VpdWpd }, // SSE3
/* F2 */ { 0, &BX_CPU_C::HSUBPS_VpsWps }, // SSE3
/* F3 */ { 0, &BX_CPU_C::BxError }
};
@ -1449,8 +1449,8 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0fc6[4] = {
static BxOpcodeInfo_t BxOpcodeGroupSSE_0fd0[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::ADDSUBPD_VpdWpd }, // PNI
/* F2 */ { 0, &BX_CPU_C::ADDSUBPS_VpsWps }, // PNI
/* 66 */ { 0, &BX_CPU_C::ADDSUBPD_VpdWpd }, // SSE3
/* F2 */ { 0, &BX_CPU_C::ADDSUBPS_VpsWps }, // SSE3
/* F3 */ { 0, &BX_CPU_C::BxError }
};
@ -1674,7 +1674,7 @@ static BxOpcodeInfo_t BxOpcodeGroupSSE_0fef[4] = {
static BxOpcodeInfo_t BxOpcodeGroupSSE_0ff0[4] = {
/* -- */ { 0, &BX_CPU_C::BxError },
/* 66 */ { 0, &BX_CPU_C::BxError },
/* F2 */ { 0, &BX_CPU_C::LDDQU_VdqMdq }, // PNI
/* F2 */ { 0, &BX_CPU_C::LDDQU_VdqMdq }, // SSE3
/* F3 */ { 0, &BX_CPU_C::BxError }
};

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode64.cc,v 1.89 2006-03-22 20:47:11 sshwarts Exp $
// $Id: fetchdecode64.cc,v 1.90 2006-04-05 17:31:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -698,7 +698,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 8D */ { BxAnother, &BX_CPU_C::LEA_GwM },
/* 8E */ { BxAnother, &BX_CPU_C::MOV_SwEw },
/* 8F */ { BxAnother, &BX_CPU_C::POP_Ew },
/* 90 */ { 0, &BX_CPU_C::NOP },
/* 90 */ { 0, &BX_CPU_C::XCHG_RXAX }, // handles XCHG R8w, AX
/* 91 */ { 0, &BX_CPU_C::XCHG_RXAX },
/* 92 */ { 0, &BX_CPU_C::XCHG_RXAX },
/* 93 */ { 0, &BX_CPU_C::XCHG_RXAX },
@ -754,8 +754,8 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* C5 */ { 0, &BX_CPU_C::BxError },
/* C6 */ { BxAnother | BxImmediate_Ib, &BX_CPU_C::MOV_EbIb },
/* C7 */ { BxAnother | BxImmediate_Iv, &BX_CPU_C::MOV_EwIw },
/* C8 */ { BxImmediate_IwIb, &BX_CPU_C::ENTER64_IwIb },
/* C9 */ { 0, &BX_CPU_C::LEAVE64 },
/* C8 */ { BxImmediate_IwIb, &BX_CPU_C::ENTER_IwIb },
/* C9 */ { 0, &BX_CPU_C::LEAVE },
/* CA */ { BxImmediate_Iw, &BX_CPU_C::RETfar16_Iw },
/* CB */ { 0, &BX_CPU_C::RETfar16 },
/* CC */ { 0, &BX_CPU_C::INT3 },
@ -848,7 +848,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 1C */ { 0, &BX_CPU_C::BxError },
/* 0F 1D */ { 0, &BX_CPU_C::BxError },
/* 0F 1E */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { BxAnother, &BX_CPU_C::NOP }, // multi-byte NOP
/* 0F 20 */ { BxAnother, &BX_CPU_C::MOV_RqCq },
/* 0F 21 */ { BxAnother, &BX_CPU_C::MOV_RdDd },
/* 0F 22 */ { BxAnother, &BX_CPU_C::MOV_CqRq },
@ -1219,7 +1219,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 8D */ { BxAnother, &BX_CPU_C::LEA_GdM },
/* 8E */ { BxAnother, &BX_CPU_C::MOV_SwEw },
/* 8F */ { BxAnother, &BX_CPU_C::POP_Eq },
/* 90 */ { 0, &BX_CPU_C::NOP },
/* 90 */ { 0, &BX_CPU_C::XCHG_ERXEAX }, // handles XCHG R8d, EAX
/* 91 */ { 0, &BX_CPU_C::XCHG_ERXEAX },
/* 92 */ { 0, &BX_CPU_C::XCHG_ERXEAX },
/* 93 */ { 0, &BX_CPU_C::XCHG_ERXEAX },
@ -1369,7 +1369,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 1C */ { 0, &BX_CPU_C::BxError },
/* 0F 1D */ { 0, &BX_CPU_C::BxError },
/* 0F 1E */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { BxAnother, &BX_CPU_C::NOP }, // multi-byte NOP
/* 0F 20 */ { BxAnother, &BX_CPU_C::MOV_RqCq },
/* 0F 21 */ { BxAnother, &BX_CPU_C::MOV_RdDd },
/* 0F 22 */ { BxAnother, &BX_CPU_C::MOV_CqRq },
@ -1740,7 +1740,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 8D */ { BxAnother, &BX_CPU_C::LEA_GqM },
/* 8E */ { BxAnother, &BX_CPU_C::MOV_SwEw },
/* 8F */ { BxAnother, &BX_CPU_C::POP_Eq },
/* 90 */ { 0, &BX_CPU_C::NOP },
/* 90 */ { 0, &BX_CPU_C::XCHG_RRXRAX }, // handles XCHG R8, RAX
/* 91 */ { 0, &BX_CPU_C::XCHG_RRXRAX },
/* 92 */ { 0, &BX_CPU_C::XCHG_RRXRAX },
/* 93 */ { 0, &BX_CPU_C::XCHG_RRXRAX },
@ -1890,7 +1890,7 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
/* 0F 1C */ { 0, &BX_CPU_C::BxError },
/* 0F 1D */ { 0, &BX_CPU_C::BxError },
/* 0F 1E */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { 0, &BX_CPU_C::BxError },
/* 0F 1F */ { BxAnother, &BX_CPU_C::NOP }, // multi-byte NOP
/* 0F 20 */ { BxAnother, &BX_CPU_C::MOV_RqCq },
/* 0F 21 */ { BxAnother, &BX_CPU_C::MOV_RqDq },
/* 0F 22 */ { BxAnother, &BX_CPU_C::MOV_CqRq },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: flag_ctrl_pro.cc,v 1.23 2006-03-06 22:02:59 sshwarts Exp $
// $Id: flag_ctrl_pro.cc,v 1.24 2006-04-05 17:31:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -36,14 +36,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::setEFlags(Bit32u val)
// VM flag could not be set from long mode
#if BX_SUPPORT_X86_64
if (IsLongMode()) {
if (get_VM()) BX_PANIC(("VM is set in long mode !"));
if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("VM is set in long mode !"));
val &= ~EFlagsVMMask;
}
#endif
BX_CPU_THIS_PTR eflags.val32 = val;
BX_CPU_THIS_PTR lf_flags_status = 0; // OSZAPC flags are known.
set_VM(val & EFlagsVMMask);
BX_CPU_THIS_PTR set_VM(val & EFlagsVMMask);
}
void BX_CPP_AttrRegparmN(2)
@ -66,7 +66,7 @@ BX_CPU_C::writeEFlags(Bit32u flags, Bit32u changeMask)
newEFlags = (BX_CPU_THIS_PTR eflags.val32 & ~changeMask) |
(flags & changeMask);
BX_CPU_THIS_PTR setEFlags(newEFlags);
setEFlags(newEFlags);
// OSZAPC flags are known - done in setEFlags(newEFlags)
if (newEFlags & EFlagsTFMask) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.95 2006-03-27 18:02:07 sshwarts Exp $
// $Id: init.cc,v 1.96 2006-04-05 17:31:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -619,6 +619,8 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR in_smm = 0;
BX_CPU_THIS_PTR nmi_disable = 0;
BX_CPU_THIS_PTR smbase = 0x30000;
#if BX_CPU_LEVEL >= 2
// MSW (Machine Status Word), so called on 286
// CR0 (Control Register 0), so called on 386+

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.70 2006-03-28 16:53:02 sshwarts Exp $
// $Id: paging.cc,v 1.71 2006-04-05 17:31:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -439,14 +439,14 @@ BX_CPU_C::pagingCR0Changed(Bit32u oldCR0, Bit32u newCR0)
BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4)
{
// Modification of PGE,PAE,PSE flushes TLB cache according to docs.
if ( (oldCR4 & 0x000000b0) != (newCR4 & 0x000000b0) )
if ((oldCR4 & 0x000000b0) != (newCR4 & 0x000000b0))
TLB_flush(1); // 1 = Flush Global entries also.
if (bx_dbg.paging)
BX_INFO(("pagingCR4Changed: (0x%x -> 0x%x)", oldCR4, newCR4));
#if BX_SUPPORT_PAE
if ( (oldCR4 & 0x00000020) != (newCR4 & 0x00000020) ) {
if ((oldCR4 & 0x00000020) != (newCR4 & 0x00000020)) {
if (BX_CPU_THIS_PTR cr4.get_PAE())
BX_CPU_THIS_PTR cr3_masked = BX_CPU_THIS_PTR cr3 & 0xffffffe0;
else
@ -456,7 +456,7 @@ BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4)
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::CR3_change(bx_address value)
BX_CPU_C::CR3_change(bx_phy_address value)
{
if (bx_dbg.paging) {
BX_INFO(("CR3_change(): flush TLB cache"));
@ -621,7 +621,8 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
// note - we assume physical memory < 4gig so for brevity & speed, we'll use
// 32 bit entries although cr3 is expanded to 64 bits.
Bit32u ppf, poffset, paddress;
Bit32u ppf, poffset;
bx_phy_address paddress;
bx_bool isWrite = (rw >= BX_WRITE); // write or r-m-w
@ -629,8 +630,8 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
if (BX_CPU_THIS_PTR cr4.get_PAE())
{
bx_address pde, pdp;
Bit32u pde_addr;
Bit32u pdp_addr;
bx_phy_address pde_addr;
bx_phy_address pdp_addr;
lpf = laddr & BX_CONST64(0xfffffffffffff000); // linear page frame
poffset = laddr & 0x00000fff; // physical offset
@ -659,10 +660,10 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lma)
{
bx_address pml4;
Bit64u pml4;
// Get PML4 entry
Bit32u pml4_addr = BX_CPU_THIS_PTR cr3_masked |
bx_phy_address pml4_addr = BX_CPU_THIS_PTR cr3_masked |
((laddr & BX_CONST64(0x0000ff8000000000)) >> 36);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pml4_addr, 8, &pml4);
@ -770,7 +771,7 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
bx_address pte;
// Get page table entry
Bit32u pte_addr = (pde & 0xfffff000) | ((laddr & 0x001ff000) >> 9);
bx_phy_address pte_addr = (pde & 0xfffff000) | ((laddr & 0x001ff000) >> 9);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, sizeof(bx_address), &pte);
@ -851,7 +852,8 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
InstrTLB_Increment(tlbMisses);
Bit32u pde, pde_addr;
Bit32u pde;
bx_phy_address pde_addr;
// Get page dir entry
pde_addr = BX_CPU_THIS_PTR cr3_masked | ((laddr & 0xffc00000) >> 20);
@ -902,7 +904,7 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
else // Else normal 4Kbyte page...
#endif
{
Bit32u pte, pte_addr;
Bit32u pte;
#if (BX_CPU_LEVEL < 6)
// update PDE if A bit was not set before
@ -913,7 +915,7 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
#endif
// Get page table entry
pte_addr = (pde & 0xfffff000) | ((laddr & 0x003ff000) >> 10);
bx_phy_address pte_addr = (pde & 0xfffff000) | ((laddr & 0x003ff000) >> 10);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, 4, &pte);
@ -1431,7 +1433,7 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
// stub functions for non-support of paging
void BX_CPU_C::CR3_change(bx_address value32)
void BX_CPU_C::CR3_change(bx_phy_address value32)
{
BX_INFO(("CR3_change(): flush TLB cache"));
BX_INFO(("Page Directory Base %08x", (unsigned) value32));

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.143 2006-03-27 18:02:07 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.144 2006-04-05 17:31:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -59,6 +59,11 @@ void BX_CPU_C::PREFETCH(bxInstruction_c *i)
#endif
}
void BX_CPU_C::shutdown(void)
{
BX_PANIC(("Entering to shutdown state still not implemented"));
}
void BX_CPU_C::HLT(bxInstruction_c *i)
{
// hack to panic if HLT comes from BIOS
@ -1240,6 +1245,42 @@ void BX_CPU_C::LOADALL(bxInstruction_c *i)
}
#endif
void BX_CPU_C::handleCpuModeChange(void)
{
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lma) {
if (! BX_CPU_THIS_PTR cr0.pe) {
BX_PANIC(("change_cpu_mode: EFER.LMA is set when CR0.PE=0 !"));
}
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l) {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_64;
BX_DEBUG(("Long Mode Activated"));
}
else {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
BX_DEBUG(("Compatibility Mode Activated"));
}
}
else
#endif
{
if (BX_CPU_THIS_PTR cr0.pe) {
if (BX_CPU_THIS_PTR get_VM()) {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_V8086;
BX_DEBUG(("VM8086 Mode Activated"));
}
else {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_PROTECTED;
BX_DEBUG(("Protected Mode Activated"));
}
}
else {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_REAL;
BX_DEBUG(("Real Mode Activated"));
}
}
}
void BX_CPU_C::SetCR0(Bit32u val_32)
{
bx_bool pe = val_32 & 0x01;
@ -1319,8 +1360,6 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
exception(BX_GP_EXCEPTION, 0, 0);
}
BX_CPU_THIS_PTR msr.lma = 1;
BX_DEBUG(("Enter Compatibility Mode"));
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
}
}
else if (prev_pg==1 && BX_CPU_THIS_PTR cr0.pg==0) {
@ -1329,18 +1368,12 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
BX_PANIC(("SetCR0: attempt to leave x86-64 LONG mode with RIP upper != 0 !!!"));
}
BX_CPU_THIS_PTR msr.lma = 0;
if (BX_CPU_THIS_PTR cr0.pe) {
BX_DEBUG(("Enter Protected Mode"));
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_PROTECTED;
}
else {
BX_DEBUG(("Enter Real Mode"));
BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_REAL;
}
}
}
#endif // #if BX_SUPPORT_X86_64
handleCpuModeChange();
// 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);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: segment_ctrl_pro.cc,v 1.57 2006-03-29 18:08:13 sshwarts Exp $
// $Id: segment_ctrl_pro.cc,v 1.58 2006-04-05 17:31:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -317,7 +317,7 @@ BX_CPU_C::parse_selector(Bit16u raw_selector, bx_selector_t *selector)
#if BX_CPU_LEVEL >= 3
Bit16u BX_CPP_AttrRegparmN(1)
BX_CPU_C::get_segment_ar_data(bx_descriptor_t *d)
BX_CPU_C::get_segment_ar_data(bx_descriptor_t *d) // used for SMM
{
Bit16u val = 0;
@ -360,6 +360,85 @@ BX_CPU_C::get_segment_ar_data(bx_descriptor_t *d)
return val;
}
bx_bool BX_CPU_C::set_segment_ar_data(bx_segment_reg_t *seg,
Bit16u raw_selector, bx_address base, Bit32u limit, Bit16u ar_data)
{
parse_selector(raw_selector, &seg->selector);
bx_descriptor_t *d = &seg->cache;
d->p = (ar_data >> 7) & 0x01;
d->dpl = (ar_data >> 5) & 0x03;
d->segment = (ar_data >> 4) & 0x01;
d->type = (ar_data & 0x0f);
if (d->segment) { /* data/code segment descriptors */
d->u.segment.executable = (ar_data >> 3) & 0x01;
d->u.segment.c_ed = (ar_data >> 2) & 0x01;
d->u.segment.r_w = (ar_data >> 1) & 0x01;
d->u.segment.a = (ar_data >> 0) & 0x01;
d->u.segment.g = (ar_data >> 15) & 0x01;
d->u.segment.d_b = (ar_data >> 14) & 0x01;
#if BX_SUPPORT_X86_64
d->u.segment.l = (ar_data >> 13) & 0x01;
#endif
d->u.segment.avl = (ar_data >> 12) & 0x01;
d->u.segment.base = base;
d->u.segment.limit = limit;
if (d->u.segment.g) {
if ((d->u.segment.executable==0) && (d->u.segment.c_ed))
d->u.segment.limit_scaled = (d->u.segment.limit << 12);
else
d->u.segment.limit_scaled = (d->u.segment.limit << 12) | 0x0fff;
}
else
d->u.segment.limit_scaled = d->u.segment.limit;
d->valid = 1;
}
else {
switch(d->type) {
case BX_SYS_SEGMENT_LDT:
d->valid = 1;
d->u.ldt.base = base;
d->u.ldt.limit = limit;
break;
case BX_SYS_SEGMENT_AVAIL_286_TSS:
case BX_SYS_SEGMENT_BUSY_286_TSS:
d->valid = 1;
d->u.tss286.base = base;
d->u.tss286.limit = limit;
break;
case BX_SYS_SEGMENT_AVAIL_386_TSS:
case BX_SYS_SEGMENT_BUSY_386_TSS:
d->valid = 1;
d->u.tss386.avl = (ar_data >> 12) & 0x01;
d->u.tss386.g = (ar_data >> 15) & 0x01;
d->u.tss386.base = base;
d->u.tss386.limit = limit;
if (d->u.tss386.g)
d->u.tss386.limit_scaled = (d->u.tss386.limit << 12) | 0x0fff;
else
d->u.tss386.limit_scaled = (d->u.tss386.limit);
break;
default:
BX_PANIC(("set_segment_ar_data(): case %u unsupported", (unsigned) d->type));
}
}
/* invalidate if null selector */
if ((raw_selector & 0xfffc) == 0) {
seg->cache.valid = 0;
}
return seg->cache.valid;
}
#endif
void BX_CPP_AttrRegparmN(3)
@ -531,8 +610,9 @@ BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
BX_CPU_THIS_PTR gdtr.limit));
exception(exception_no, selector->value & 0xfffc, 0);
}
access_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8+4, 4, 0, BX_READ, dword2);
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
}
else { /* LDT */
if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
@ -545,8 +625,9 @@ BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
exception(exception_no, selector->value & 0xfffc, 0);
}
access_linear(BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8+4, 4, 0, BX_READ, dword2);
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
}
}
@ -556,8 +637,9 @@ BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, B
if (selector->ti == 0) { /* GDT */
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit)
return(0);
access_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8+4, 4, 0, BX_READ, dword2);
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
return(1);
}
else { /* LDT */
@ -567,8 +649,9 @@ BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, B
}
if ((selector->index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit)
return(0);
access_linear(BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8+4, 4, 0, BX_READ, dword2);
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
return(1);
}
}
@ -586,11 +669,11 @@ void BX_CPU_C::fetch_raw_descriptor64(const bx_selector_t *selector,
BX_CPU_THIS_PTR gdtr.limit));
exception(exception_no, selector->value & 0xfffc, 0);
}
bx_address base = BX_CPU_THIS_PTR gdtr.base;
access_linear(base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(base + selector->index*8 + 4, 4, 0, BX_READ, dword2);
access_linear(base + selector->index*8 + 8, 4, 0, BX_READ, dword3);
access_linear(base + selector->index*8 + 12, 4, 0, BX_READ, &dword4);
bx_address offset = BX_CPU_THIS_PTR gdtr.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
access_linear(offset + 8, 4, 0, BX_READ, dword3);
access_linear(offset + 12, 4, 0, BX_READ, &dword4);
}
else { /* LDT */
if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
@ -603,11 +686,11 @@ void BX_CPU_C::fetch_raw_descriptor64(const bx_selector_t *selector,
BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit));
exception(exception_no, selector->value & 0xfffc, 0);
}
bx_address base = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base;
access_linear(base + selector->index*8, 4, 0, BX_READ, dword1);
access_linear(base + selector->index*8 + 4, 4, 0, BX_READ, dword2);
access_linear(base + selector->index*8 + 8, 4, 0, BX_READ, dword3);
access_linear(base + selector->index*8 + 12, 4, 0, BX_READ, &dword4);
bx_address offset = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base + selector->index*8;
access_linear(offset, 4, 0, BX_READ, dword1);
access_linear(offset + 4, 4, 0, BX_READ, dword2);
access_linear(offset + 8, 4, 0, BX_READ, dword3);
access_linear(offset + 12, 4, 0, BX_READ, &dword4);
}
if (dword4 != 0) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: smm.cc,v 1.12 2006-03-29 19:16:24 sshwarts Exp $
// $Id: smm.cc,v 1.13 2006-04-05 17:31:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006 Stanislav Shwartsman
@ -24,6 +24,7 @@
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu.h"
#include "smm.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_CPU_LEVEL >= 3
@ -61,7 +62,7 @@
// 5. LDTR, TR
// fields: base, limit, something more ?
// 6. Debug Registers DR0-DR7, only DR6 and DR7 are saved
// 7. Control Regsiters: CR0, CR1 is always 0, CR2 is NOT saved, CR3, CR4
// 7. Control Regsiters: CR0, CR1 is always 0, CR2 is NOT saved, CR3, CR4, EFER
// 8. SMBASE
// 9. MSR/FPU/XMM/APIC are NOT saved accoring to Intel docs
//
@ -77,13 +78,13 @@ void BX_CPU_C::RSM(bxInstruction_c *i)
}
invalidate_prefetch_q();
BX_INFO(("RSM: System Management Mode not implemented yet"));
UndefinedOpcode(i); // remove later, when SMM become stable
BX_INFO(("RSM: Resuming from System Management Mode !"));
BX_CPU_THIS_PTR nmi_disable = 0;
BX_CPU_THIS_PTR in_smm = 0;
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
// reset reserved bits
for(n=0;n<SMM_SAVE_STATE_MAP_SIZE;n++) saved_state[n] = 0;
@ -97,21 +98,25 @@ void BX_CPU_C::RSM(bxInstruction_c *i)
// restore the CPU state from SMRAM
if (! smram_restore_state(saved_state)) {
BX_PANIC(("RSM: Incorrect state when restoring CPU state - shutdown !"));
shutdown();
}
BX_CPU_THIS_PTR nmi_disable = 0;
BX_CPU_THIS_PTR in_smm = 0;
debug(RIP);
}
void BX_CPU_C::enter_system_management_mode(void)
{
invalidate_prefetch_q();
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
debug(BX_CPU_THIS_PTR prev_eip);
BX_INFO(("Enter to System Management Mode !"));
BX_CPU_THIS_PTR in_smm = 1;
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
// reset reserved bits
for(n=0;n<SMM_SAVE_STATE_MAP_SIZE;n++) saved_state[n] = 0;
// prepare CPU state to be saved in the SMRAM
BX_CPU_THIS_PTR smram_save_state(saved_state);
@ -123,7 +128,7 @@ void BX_CPU_C::enter_system_management_mode(void)
}
BX_CPU_THIS_PTR setEFlags(0x2); // Bit1 is always set
BX_CPU_THIS_PTR prev_eip = RIP = 0x000080000;
BX_CPU_THIS_PTR prev_eip = RIP = 0x00008000;
BX_CPU_THIS_PTR dr7 = 0x00000400;
// CR0 - PE, EM, TS, and PG flags set to 0; others unmodified
@ -148,7 +153,7 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR msr.lma = 0;
#endif
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = BX_CPU_THIS_PTR smbase << 4;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = BX_CPU_THIS_PTR smbase >> 4;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 0;
@ -166,7 +171,7 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xffff;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xffffffff;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 0; /* byte granular */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* page granular */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; /* 16bit default size */
#if BX_SUPPORT_X86_64
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 16bit default size */
@ -195,7 +200,7 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xffff;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xffffffff;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.avl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g = 0; /* byte granular */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; /* byte granular */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 0; /* 16bit default size */
#if BX_SUPPORT_X86_64
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.l = 0; /* 16bit default size */
@ -208,284 +213,636 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS];
}
#define SMRAM_TRANSLATE(addr) (((0x8000 - (addr)) >> 2) - 1)
#define SMM_SAVED_STATE(state, addr) (state[SMRAM_TRANSLATE(addr)])
#define SMRAM_TRANSLATE(addr) (((0x8000 - (addr)) >> 2) - 1)
#define SMRAM_FIELD(state, addr) (state[SMRAM_TRANSLATE(addr)])
#if BX_SUPPORT_X86_64
// for x86-64 configuration using AMD Athlon 64 512-byte SMM save state map
#define SMM_REVISION_ID 0x00000000
void BX_CPU_C::smram_save_state(Bit32u *saved_state)
{
// --- General Purpose Registers --- //
SMM_SAVED_STATE(saved_state, 0x7ffc) = RAX >> 32;
SMM_SAVED_STATE(saved_state, 0x7ff8) = RAX & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7ff4) = RCX >> 32;
SMM_SAVED_STATE(saved_state, 0x7ff0) = RCX & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fec) = RDX >> 32;
SMM_SAVED_STATE(saved_state, 0x7fe8) = RDX & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fe4) = RBX >> 32;
SMM_SAVED_STATE(saved_state, 0x7fe0) = RBX & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fdc) = RSP >> 32;
SMM_SAVED_STATE(saved_state, 0x7fd8) = RSP & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fd4) = RBP >> 32;
SMM_SAVED_STATE(saved_state, 0x7fd0) = RBP & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fcc) = RSI >> 32;
SMM_SAVED_STATE(saved_state, 0x7fc8) = RSI & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fc4) = RDI >> 32;
SMM_SAVED_STATE(saved_state, 0x7fc0) = RDI & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fbc) = R8 >> 32;
SMM_SAVED_STATE(saved_state, 0x7fb8) = R8 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fb4) = R9 >> 32;
SMM_SAVED_STATE(saved_state, 0x7fb0) = R9 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fac) = R10 >> 32;
SMM_SAVED_STATE(saved_state, 0x7fa8) = R10 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7fa4) = R11 >> 32;
SMM_SAVED_STATE(saved_state, 0x7fa0) = R11 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f9c) = R12 >> 32;
SMM_SAVED_STATE(saved_state, 0x7f98) = R12 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f94) = R13 >> 32;
SMM_SAVED_STATE(saved_state, 0x7f90) = R13 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f8c) = R14 >> 32;
SMM_SAVED_STATE(saved_state, 0x7f88) = R14 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f84) = R15 >> 32;
SMM_SAVED_STATE(saved_state, 0x7f80) = R15 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f7c) = RIP >> 32;
SMM_SAVED_STATE(saved_state, 0x7f78) = RIP & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f70) = read_eflags();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RAX_HI32) = RAX >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RAX_LO32) = RAX & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RCX_HI32) = RCX >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RCX_LO32) = RCX & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RDX_HI32) = RDX >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RDX_LO32) = RDX & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RBX_HI32) = RBX >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RBX_LO32) = RBX & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RSP_HI32) = RSP >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RSP_LO32) = RSP & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RBP_HI32) = RBP >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RBP_LO32) = RBP & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RSI_HI32) = RSI >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RSI_LO32) = RSI & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RDI_HI32) = RDI >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RDI_LO32) = RDI & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R8_HI32) = R8 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R8_LO32) = R8 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R9_HI32) = R9 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R9_LO32) = R9 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R10_HI32) = R10 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R10_LO32) = R10 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R11_HI32) = R11 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R11_LO32) = R11 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R12_HI32) = R12 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R12_LO32) = R12 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R13_HI32) = R13 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R13_LO32) = R13 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R14_HI32) = R14 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R14_LO32) = R14 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R15_HI32) = R15 >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_R15_LO32) = R15 & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RIP_HI32) = RIP >> 32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RIP_LO32) = RIP & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_RFLAGS32) = read_eflags();
// --- Debug and Control Registers --- //
SMM_SAVED_STATE(saved_state, 0x7f68) = BX_CPU_THIS_PTR dr6;
SMM_SAVED_STATE(saved_state, 0x7f60) = BX_CPU_THIS_PTR dr7;
SMM_SAVED_STATE(saved_state, 0x7f58) = BX_CPU_THIS_PTR cr0.val32;
SMM_SAVED_STATE(saved_state, 0x7f54) = BX_CPU_THIS_PTR cr3 >> 32;
SMM_SAVED_STATE(saved_state, 0x7f50) = BX_CPU_THIS_PTR cr3 & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7f48) = BX_CPU_THIS_PTR cr4.getRegister();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR6) = BX_CPU_THIS_PTR dr6;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR7) = BX_CPU_THIS_PTR dr7;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR0) = BX_CPU_THIS_PTR cr0.val32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR3) = BX_CPU_THIS_PTR cr3;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR4) = BX_CPU_THIS_PTR cr4.getRegister();
/* base+0x7f44 to base+0x7f04 is reserved */
SMM_SAVED_STATE(saved_state, 0x7f00) = BX_CPU_THIS_PTR smbase;
SMM_SAVED_STATE(saved_state, 0x7efc) = SMM_REVISION_ID;
SMRAM_FIELD(saved_state, SMRAM_SMBASE_OFFSET) = BX_CPU_THIS_PTR smbase;
SMRAM_FIELD(saved_state, SMRAM_SMM_REVISION_ID) = SMM_REVISION_ID;
/* base+0x7ef8 to base+0x7ed8 is reserved */
SMM_SAVED_STATE(saved_state, 0x7ed0) = BX_CPU_THIS_PTR get_EFER();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EFER) = BX_CPU_THIS_PTR get_EFER();
/* base+0x7ecc is reserved */
/* base+0x7ec8 is I/O Instruction Restart, Auto-Halt Restart and NMI Mask */
/* base+0x7ec4 is reserved */
/* base+0x7ec0 is SMM I/O Trap */
/* base+0x7ebc to base+0x7ea4 is reserved */
/* base+0x7ebc to base+0x7ea0 is reserved */
// --- Task Register --- //
if (BX_CPU_THIS_PTR tr.cache.type <= 3) {
SMM_SAVED_STATE(saved_state, 0x7e98) = BX_CPU_THIS_PTR tr.cache.u.tss286.base;
SMM_SAVED_STATE(saved_state, 0x7e94) = BX_CPU_THIS_PTR tr.cache.u.tss286.limit;
SMRAM_FIELD(saved_state, SMRAM_TR_BASE_LO32) = BX_CPU_THIS_PTR tr.cache.u.tss286.base;
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT) = BX_CPU_THIS_PTR tr.cache.u.tss286.limit;
} else {
SMM_SAVED_STATE(saved_state, 0x7e9c) = BX_CPU_THIS_PTR tr.cache.u.tss386.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e98) = BX_CPU_THIS_PTR tr.cache.u.tss386.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e94) = BX_CPU_THIS_PTR tr.cache.u.tss386.limit;
SMRAM_FIELD(saved_state, SMRAM_TR_BASE_HI32) = BX_CPU_THIS_PTR tr.cache.u.tss386.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_TR_BASE_LO32) = BX_CPU_THIS_PTR tr.cache.u.tss386.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT) = BX_CPU_THIS_PTR tr.cache.u.tss386.limit;
}
SMM_SAVED_STATE(saved_state, 0x7e90) = BX_CPU_THIS_PTR tr.selector.value |
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) = BX_CPU_THIS_PTR tr.selector.value |
(((Bit32u) get_segment_ar_data(&BX_CPU_THIS_PTR tr.cache)) << 16);
// --- IDTR --- //
SMM_SAVED_STATE(saved_state, 0x7e8c) = BX_CPU_THIS_PTR idtr.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e88) = BX_CPU_THIS_PTR idtr.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e84) = BX_CPU_THIS_PTR idtr.limit;
SMRAM_FIELD(saved_state, SMRAM_IDTR_BASE_HI32) = BX_CPU_THIS_PTR idtr.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_IDTR_BASE_LO32) = BX_CPU_THIS_PTR idtr.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_IDTR_LIMIT) = BX_CPU_THIS_PTR idtr.limit;
// --- LDTR --- //
SMM_SAVED_STATE(saved_state, 0x7e7c) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e78) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e74) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit;
SMM_SAVED_STATE(saved_state, 0x7e70) = BX_CPU_THIS_PTR ldtr.selector.value |
SMRAM_FIELD(saved_state, SMRAM_LDTR_BASE_HI32) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_LDTR_BASE_LO32) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_LDTR_LIMIT) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit;
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) = BX_CPU_THIS_PTR ldtr.selector.value |
(((Bit32u) get_segment_ar_data(&BX_CPU_THIS_PTR ldtr.cache)) << 16);
// --- GDTR --- //
SMM_SAVED_STATE(saved_state, 0x7e6c) = BX_CPU_THIS_PTR gdtr.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e68) = BX_CPU_THIS_PTR gdtr.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e64) = BX_CPU_THIS_PTR gdtr.limit;
SMRAM_FIELD(saved_state, SMRAM_GDTR_BASE_HI32) = BX_CPU_THIS_PTR gdtr.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_GDTR_BASE_LO32) = BX_CPU_THIS_PTR gdtr.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_GDTR_LIMIT) = BX_CPU_THIS_PTR gdtr.limit;
// --- GS selector --- //
bx_segment_reg_t *seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]);
SMM_SAVED_STATE(saved_state, 0x7e5c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e58) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e54) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e50) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_GS_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_GS_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_GS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- FS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]);
SMM_SAVED_STATE(saved_state, 0x7e4c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e48) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e44) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e40) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_FS_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_FS_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_FS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- DS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]);
SMM_SAVED_STATE(saved_state, 0x7e3c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e38) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e34) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e30) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_DS_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_DS_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_DS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- SS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]);
SMM_SAVED_STATE(saved_state, 0x7e2c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e28) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e24) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e20) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_SS_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_SS_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_SS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- CS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]);
SMM_SAVED_STATE(saved_state, 0x7e1c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e18) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e14) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e10) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_CS_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_CS_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_CS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- ES selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]);
SMM_SAVED_STATE(saved_state, 0x7e0c) = seg->cache.u.segment.base >> 32;
SMM_SAVED_STATE(saved_state, 0x7e08) = seg->cache.u.segment.base & 0xffffffff;
SMM_SAVED_STATE(saved_state, 0x7e04) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7e00) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_ES_BASE_HI32) = seg->cache.u.segment.base >> 32;
SMRAM_FIELD(saved_state, SMRAM_ES_BASE_LO32) = seg->cache.u.segment.base & 0xffffffff;
SMRAM_FIELD(saved_state, SMRAM_ES_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
}
#define SMRAM_FIELD64(state, addr) ((Bit64u) state[SMRAM_TRANSLATE(addr)])
bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
{
Bit32u temp_cr0 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR0);
Bit32u temp_eflags = SMRAM_FIELD(saved_state, SMRAM_OFFSET_RFLAGS32);
Bit32u temp_efer = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EFER);
bx_bool pe = (temp_cr0 & 0x01);
bx_bool nw = (temp_cr0 >> 29) & 0x01;
bx_bool cd = (temp_cr0 >> 30) & 0x01;
bx_bool pg = (temp_cr0 >> 31) & 0x01;
// check CR0 conditions for entering to shutdown state
if (pg && !pe) {
BX_PANIC(("SMM restore: attempt to set CR0.PG with CR0.PE cleared !"));
return 0;
}
if (nw && !cd) {
BX_PANIC(("SMM restore: attempt to set CR0.NW with CR0.CD cleared !"));
return 0;
}
// shutdown if write to reserved CR4 bits
if (! SetCR4(SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR4))) {
BX_PANIC(("SMM restore: incorrect CR4 state !"));
return 0;
}
BX_CPU_THIS_PTR msr.sce = (temp_efer >> 0) & 1;
BX_CPU_THIS_PTR msr.lme = (temp_efer >> 8) & 1;
BX_CPU_THIS_PTR msr.lma = (temp_efer >> 10) & 1;
BX_CPU_THIS_PTR msr.nxe = (temp_efer >> 11) & 1;
BX_CPU_THIS_PTR msr.ffxsr = (temp_efer >> 14) & 1;
if (BX_CPU_THIS_PTR msr.lma) {
if (temp_eflags & EFlagsVMMask) {
BX_PANIC(("SMM restore: If EFER.LMA = 1 => RFLAGS.VM=0 !"));
return 0;
}
if (!BX_CPU_THIS_PTR cr4.get_PAE() || !pg || !pe || !BX_CPU_THIS_PTR msr.lme) {
BX_PANIC(("SMM restore: If EFER.LMA = 1 <=> CR4.PAE, CR0.PG, CR0.PE, EFER.LME=1 !"));
return 0;
}
}
if (BX_CPU_THIS_PTR cr4.get_PAE() && pg && pe && BX_CPU_THIS_PTR msr.lme) {
if (! BX_CPU_THIS_PTR msr.lma) {
BX_PANIC(("SMM restore: If EFER.LMA = 1 <=> CR4.PAE, CR0.PG, CR0.PE, EFER.LME=1 !"));
return 0;
}
}
// hack CR0 to be able to back to long mode correctly
BX_CPU_THIS_PTR cr0.pe = 0; // real mode (bit 0)
BX_CPU_THIS_PTR cr0.pg = 0; // paging disabled (bit 31)
BX_CPU_THIS_PTR cr0.val32 &= 0x7ffffffe;
SetCR0(temp_cr0);
setEFlags(temp_eflags);
bx_address temp_cr3 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RAX_HI32) << 32;
temp_cr3 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RAX_LO32);
CR3_change(temp_cr3);
RAX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RAX_HI32) << 32;
RAX |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RAX_LO32);
RBX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RBX_HI32) << 32;
RBX |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RBX_LO32);
RCX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RCX_HI32) << 32;
RCX |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RCX_LO32);
RDX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RDX_HI32) << 32;
RDX |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RDX_LO32);
RSP = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RSP_HI32) << 32;
RSP |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RSP_LO32);
RBP = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RBP_HI32) << 32;
RBP |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RBP_LO32);
RSI = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RSI_HI32) << 32;
RSI |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RSI_LO32);
RDI = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RDI_HI32) << 32;
RDI |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RDI_LO32);
R8 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R8_HI32) << 32;
R8 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R8_LO32);
R9 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R9_HI32) << 32;
R9 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R9_LO32);
R10 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R10_HI32) << 32;
R10 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R10_LO32);
R11 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R11_HI32) << 32;
R11 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R11_LO32);
R12 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R12_HI32) << 32;
R12 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R12_LO32);
R13 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R13_HI32) << 32;
R13 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R13_LO32);
R14 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R14_HI32) << 32;
R14 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R14_LO32);
R15 = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R15_HI32) << 32;
R15 |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_R15_LO32);
RIP = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RIP_HI32) << 32;
RIP |= SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RIP_LO32);
BX_CPU_THIS_PTR dr6 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR6);
BX_CPU_THIS_PTR dr7 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR7);
BX_CPU_THIS_PTR gdtr.base = SMRAM_FIELD64(saved_state, SMRAM_GDTR_BASE_HI32) << 32;
BX_CPU_THIS_PTR gdtr.base |= SMRAM_FIELD64(saved_state, SMRAM_GDTR_BASE_LO32);
BX_CPU_THIS_PTR gdtr.limit = SMRAM_FIELD(saved_state, SMRAM_GDTR_LIMIT);
BX_CPU_THIS_PTR idtr.base = SMRAM_FIELD64(saved_state, SMRAM_IDTR_BASE_HI32) << 32;
BX_CPU_THIS_PTR idtr.base |= SMRAM_FIELD64(saved_state, SMRAM_IDTR_BASE_LO32);
BX_CPU_THIS_PTR idtr.limit = SMRAM_FIELD(saved_state, SMRAM_IDTR_LIMIT);
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS],
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_CS_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_CS_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_CS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment CS !"));
return 0;
}
}
handleCpuModeChange();
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS],
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_DS_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_DS_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_DS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment DS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS],
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_SS_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_SS_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_SS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment SS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES],
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_ES_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_ES_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_ES_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment ES !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS],
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_FS_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_FS_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_FS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment FS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS],
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_GS_BASE_LO32) |
SMRAM_FIELD64(saved_state, SMRAM_GS_BASE_HI32) << 32,
SMRAM_FIELD(saved_state, SMRAM_GS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment GS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR ldtr,
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_LDTR_BASE_HI32) |
SMRAM_FIELD64(saved_state, SMRAM_LDTR_BASE_LO32) << 32,
SMRAM_FIELD(saved_state, SMRAM_LDTR_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) >> 16))
{
if (BX_CPU_THIS_PTR ldtr.cache.type != BX_SYS_SEGMENT_LDT) {
BX_PANIC(("SMM restore: LDTR is not LDT descriptor type !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR tr,
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) & 0xffff,
SMRAM_FIELD64(saved_state, SMRAM_TR_BASE_HI32) |
SMRAM_FIELD64(saved_state, SMRAM_TR_BASE_LO32) << 32,
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) >> 16))
{
if (BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_286_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_286_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS)
{
BX_PANIC(("SMM restore: TR is not TSS descriptor type !"));
return 0;
}
}
if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION)
BX_CPU_THIS_PTR smbase = SMRAM_FIELD(saved_state, SMRAM_SMBASE_OFFSET);
return 1;
}
#else /* BX_SUPPORT_X86_64 == 0 */
// for IA32 configuration using Intel P6 512-byte SMM save state map
#define SMM_REVISION_ID 0x00000000
// source for Intel P6 SMM save state map used: www.sandpile.org
void BX_CPU_C::smram_save_state(Bit32u *saved_state)
{
SMM_SAVED_STATE(saved_state, 0x7ffc) = BX_CPU_THIS_PTR cr0.val32;
SMM_SAVED_STATE(saved_state, 0x7ff8) = BX_CPU_THIS_PTR cr3;
SMM_SAVED_STATE(saved_state, 0x7ff4) = read_eflags();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR0) = BX_CPU_THIS_PTR cr0.val32;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR3) = BX_CPU_THIS_PTR cr3;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EFLAGS) = read_eflags();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EIP) = EIP;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EDI) = EDI;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_ESI) = ESI;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EBP) = EBP;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_ESP) = ESP;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EBX) = EBX;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EDX) = EDX;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_ECX) = ECX;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_EAX) = EAX;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR6) = BX_CPU_THIS_PTR dr6;
SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR7) = BX_CPU_THIS_PTR dr7;
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR) = BX_CPU_THIS_PTR tr.selector.value;
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR) = BX_CPU_THIS_PTR ldtr.selector.value;
SMM_SAVED_STATE(saved_state, 0x7ff0) = EIP;
SMM_SAVED_STATE(saved_state, 0x7fec) = EDI;
SMM_SAVED_STATE(saved_state, 0x7fe8) = ESI;
SMM_SAVED_STATE(saved_state, 0x7fe4) = EBP;
SMM_SAVED_STATE(saved_state, 0x7fe0) = ESP;
SMM_SAVED_STATE(saved_state, 0x7fdc) = EBX;
SMM_SAVED_STATE(saved_state, 0x7fd8) = EDX;
SMM_SAVED_STATE(saved_state, 0x7fd4) = ECX;
SMM_SAVED_STATE(saved_state, 0x7fd0) = EAX;
SMM_SAVED_STATE(saved_state, 0x7fcc) = BX_CPU_THIS_PTR dr6;
SMM_SAVED_STATE(saved_state, 0x7fc8) = BX_CPU_THIS_PTR dr7;
SMM_SAVED_STATE(saved_state, 0x7fc4) = BX_CPU_THIS_PTR tr.selector.value;
SMM_SAVED_STATE(saved_state, 0x7fc0) = BX_CPU_THIS_PTR ldtr.selector.value;
SMM_SAVED_STATE(saved_state, 0x7fbc) =
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value;
SMM_SAVED_STATE(saved_state, 0x7fb8) =
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value;
SMM_SAVED_STATE(saved_state, 0x7fb4) =
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value;
SMM_SAVED_STATE(saved_state, 0x7fb0) =
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
SMM_SAVED_STATE(saved_state, 0x7fac) =
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
SMM_SAVED_STATE(saved_state, 0x7fa8) =
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR) =
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value;
// --- SS selector --- //
bx_segment_reg_t *seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]);
SMM_SAVED_STATE(saved_state, 0x7fa4) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7fa0) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f9c) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_SS_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_SS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- CS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]);
SMM_SAVED_STATE(saved_state, 0x7f98) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7f94) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f90) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_CS_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_CS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- ES selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]);
SMM_SAVED_STATE(saved_state, 0x7f8c) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7f88) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f84) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_ES_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_ES_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- LDTR --- //
SMM_SAVED_STATE(saved_state, 0x7f80) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base;
SMM_SAVED_STATE(saved_state, 0x7f7c) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit;
SMM_SAVED_STATE(saved_state, 0x7f78) = BX_CPU_THIS_PTR ldtr.selector.value |
SMRAM_FIELD(saved_state, SMRAM_LDTR_BASE) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.base;
SMRAM_FIELD(saved_state, SMRAM_LDTR_LIMIT) = BX_CPU_THIS_PTR ldtr.cache.u.ldt.limit;
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) = BX_CPU_THIS_PTR ldtr.selector.value |
(((Bit32u) get_segment_ar_data(&BX_CPU_THIS_PTR ldtr.cache)) << 16);
// --- GDTR --- //
SMM_SAVED_STATE(saved_state, 0x7f74) = BX_CPU_THIS_PTR gdtr.base;
SMM_SAVED_STATE(saved_state, 0x7f70) = BX_CPU_THIS_PTR gdtr.limit;
SMRAM_FIELD(saved_state, SMRAM_GDTR_BASE) = BX_CPU_THIS_PTR gdtr.base;
SMRAM_FIELD(saved_state, SMRAM_GDTR_LIMIT) = BX_CPU_THIS_PTR gdtr.limit;
/* base+0x7f6c is reserved */
/* base+0x7f68 is reserved */
// --- Task Register --- //
if (BX_CPU_THIS_PTR tr.cache.type <= 3) {
SMM_SAVED_STATE(saved_state, 0x7f64) = BX_CPU_THIS_PTR tr.cache.u.tss286.base;
SMM_SAVED_STATE(saved_state, 0x7f60) = BX_CPU_THIS_PTR tr.cache.u.tss286.limit;
SMRAM_FIELD(saved_state, SMRAM_TR_BASE) = BX_CPU_THIS_PTR tr.cache.u.tss286.base;
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT) = BX_CPU_THIS_PTR tr.cache.u.tss286.limit;
} else {
SMM_SAVED_STATE(saved_state, 0x7f64) = BX_CPU_THIS_PTR tr.cache.u.tss386.base;
SMM_SAVED_STATE(saved_state, 0x7f60) = BX_CPU_THIS_PTR tr.cache.u.tss386.limit;
SMRAM_FIELD(saved_state, SMRAM_TR_BASE) = BX_CPU_THIS_PTR tr.cache.u.tss386.base;
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT) = BX_CPU_THIS_PTR tr.cache.u.tss386.limit;
}
SMM_SAVED_STATE(saved_state, 0x7f5c) = BX_CPU_THIS_PTR tr.selector.value |
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) = BX_CPU_THIS_PTR tr.selector.value |
(((Bit32u) get_segment_ar_data(&BX_CPU_THIS_PTR tr.cache)) << 16);
// --- IDTR --- //
SMM_SAVED_STATE(saved_state, 0x7f58) = BX_CPU_THIS_PTR idtr.base;
SMM_SAVED_STATE(saved_state, 0x7f54) = BX_CPU_THIS_PTR idtr.limit;
SMRAM_FIELD(saved_state, SMRAM_IDTR_BASE) = BX_CPU_THIS_PTR idtr.base;
SMRAM_FIELD(saved_state, SMRAM_IDTR_LIMIT) = BX_CPU_THIS_PTR idtr.limit;
/* base+0x7f50 is reserved */
// --- GS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]);
SMM_SAVED_STATE(saved_state, 0x7f4c) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7f48) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f44) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_GS_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_GS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- FS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]);
SMM_SAVED_STATE(saved_state, 0x7f40) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7f3c) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f38) = seg->selector.value |
SMRAM_FIELD(saved_state, SMRAM_FS_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_FS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
// --- DS selector --- //
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]);
SMM_SAVED_STATE(saved_state, 0x7f34) = seg->cache.u.segment.base;
SMM_SAVED_STATE(saved_state, 0x7f30) = seg->cache.u.segment.limit;
SMM_SAVED_STATE(saved_state, 0x7f2c) = seg->selector.value |
seg = &(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]);
SMRAM_FIELD(saved_state, SMRAM_DS_BASE) = seg->cache.u.segment.base;
SMRAM_FIELD(saved_state, SMRAM_DS_LIMIT) = seg->cache.u.segment.limit;
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) = seg->selector.value |
(((Bit32u) get_segment_ar_data(&seg->cache)) << 16);
/* base+0x7f28 to base+7f18 is reserved */
#if BX_CPU_LEVEL >= 4
SMM_SAVED_STATE(saved_state, 0x7f14) = BX_CPU_THIS_PTR cr4.getRegister();
SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR4) = BX_CPU_THIS_PTR cr4.getRegister();
#endif
/* base+0x7f10 is I/O restart EIP */
/* base+0x7f0c is I/O restart ESI */
/* base+0x7f08 is I/O restart ECX */
/* base+0x7f04 is I/O restart EDI */
/* base+0x7f02 is Auto HALT restart field (2 byte) */
/* base+0x7f00 is I/O restart field (2 byte) */
SMM_SAVED_STATE(saved_state, 0x7efc) = SMM_REVISION_ID;
SMM_SAVED_STATE(saved_state, 0x7ef8) = BX_CPU_THIS_PTR smbase;
SMRAM_FIELD(saved_state, SMRAM_SMM_REVISION_ID) = SMM_REVISION_ID;
SMRAM_FIELD(saved_state, SMRAM_SMBASE_OFFSET) = BX_CPU_THIS_PTR smbase;
/* base+0x7ef4 to base+0x7e00 is reserved */
}
bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
{
SetCR0(SMM_SAVED_STATE(saved_state, 0x7ffc));
CR3_change(SMM_SAVED_STATE(saved_state, 0x7ff8));
BX_CPU_THIS_PTR setEFlags(SMM_SAVED_STATE(saved_state, 0x7ff4));
Bit32u temp_cr0 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR0);
Bit32u temp_eflags = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EFLAGS);
Bit32u temp_cr3 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR3);
EIP = SMM_SAVED_STATE(saved_state, 0x7ff0);
EIP = SMM_SAVED_STATE(saved_state, 0x7ff0);
EDI = SMM_SAVED_STATE(saved_state, 0x7fec);
ESI = SMM_SAVED_STATE(saved_state, 0x7fe8);
EBP = SMM_SAVED_STATE(saved_state, 0x7fe4);
ESP = SMM_SAVED_STATE(saved_state, 0x7fe0);
EBX = SMM_SAVED_STATE(saved_state, 0x7fdc);
EDX = SMM_SAVED_STATE(saved_state, 0x7fd8);
ECX = SMM_SAVED_STATE(saved_state, 0x7fd4);
EAX = SMM_SAVED_STATE(saved_state, 0x7fd0);
bx_bool pe = (temp_cr0 & 0x01);
bx_bool nw = (temp_cr0 >> 29) & 0x01;
bx_bool cd = (temp_cr0 >> 30) & 0x01;
bx_bool pg = (temp_cr0 >> 31) & 0x01;
BX_CPU_THIS_PTR dr6 = SMM_SAVED_STATE(saved_state, 0x7fcc);
BX_CPU_THIS_PTR dr7 = SMM_SAVED_STATE(saved_state, 0x7fc8);
// check conditions for entering to shutdown state
if (pg && !pe) {
BX_PANIC(("SMM restore: attempt to set CR0.PG with CR0.PE cleared !"));
return 0;
}
if (nw && !cd) {
BX_PANIC(("SMM restore: attempt to set CR0.NW with CR0.CD cleared !"));
return 0;
}
SetCR0(temp_cr0);
CR3_change(temp_cr3);
setEFlags(temp_eflags);
#if BX_CPU_LEVEL >= 4
if (! SetCR4(SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR4))) {
BX_PANIC(("SMM restore: incorrect CR4 state !"));
return 0;
}
#endif
EIP = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EIP);
EDI = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EDI);
ESI = SMRAM_FIELD(saved_state, SMRAM_OFFSET_ESI);
EBP = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EBP);
ESP = SMRAM_FIELD(saved_state, SMRAM_OFFSET_ESP);
EBX = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EBX);
EDX = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EDX);
ECX = SMRAM_FIELD(saved_state, SMRAM_OFFSET_ECX);
EAX = SMRAM_FIELD(saved_state, SMRAM_OFFSET_EAX);
BX_CPU_THIS_PTR dr6 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR6);
BX_CPU_THIS_PTR dr7 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_DR7);
BX_CPU_THIS_PTR gdtr.base = SMRAM_FIELD(saved_state, SMRAM_GDTR_BASE);
BX_CPU_THIS_PTR gdtr.limit = SMRAM_FIELD(saved_state, SMRAM_GDTR_LIMIT);
BX_CPU_THIS_PTR idtr.base = SMRAM_FIELD(saved_state, SMRAM_IDTR_BASE);
BX_CPU_THIS_PTR idtr.limit = SMRAM_FIELD(saved_state, SMRAM_IDTR_LIMIT);
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS],
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_CS_BASE),
SMRAM_FIELD(saved_state, SMRAM_CS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_CS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment CS !"));
return 0;
}
}
handleCpuModeChange();
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS],
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_DS_BASE),
SMRAM_FIELD(saved_state, SMRAM_DS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_DS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment DS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS],
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_SS_BASE),
SMRAM_FIELD(saved_state, SMRAM_SS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_SS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment SS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES],
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_ES_BASE),
SMRAM_FIELD(saved_state, SMRAM_ES_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_ES_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment ES !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS],
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_FS_BASE),
SMRAM_FIELD(saved_state, SMRAM_FS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_FS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment FS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS],
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_GS_BASE),
SMRAM_FIELD(saved_state, SMRAM_GS_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_GS_SELECTOR_AR) >> 16))
{
if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.segment) {
BX_PANIC(("SMM restore: restored valid non segment GS !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR ldtr,
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_LDTR_BASE),
SMRAM_FIELD(saved_state, SMRAM_LDTR_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_LDTR_SELECTOR_AR) >> 16))
{
if (BX_CPU_THIS_PTR ldtr.cache.type != BX_SYS_SEGMENT_LDT) {
BX_PANIC(("SMM restore: LDTR is not LDT descriptor type !"));
return 0;
}
}
if (set_segment_ar_data(&BX_CPU_THIS_PTR tr,
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) & 0xffff,
SMRAM_FIELD(saved_state, SMRAM_TR_BASE),
SMRAM_FIELD(saved_state, SMRAM_TR_LIMIT),
SMRAM_FIELD(saved_state, SMRAM_TR_SELECTOR_AR) >> 16))
{
if (BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_286_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_286_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS &&
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS)
{
BX_PANIC(("SMM restore: TR is not TSS descriptor type !"));
return 0;
}
}
if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) {
BX_CPU_THIS_PTR smbase = SMRAM_FIELD(saved_state, SMRAM_SMBASE_OFFSET);
#if BX_CPU_LEVEL < 6
if (BX_CPU_THIS_PTR smbase & 0x7fff) {
BX_PANIC(("SMM restore: SMBASE must be aligned to 32K !"));
return 0;
}
#endif
}
return 1;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: sse.cc,v 1.38 2006-03-06 22:03:02 sshwarts Exp $
// $Id: sse.cc,v 1.39 2006-04-05 17:31:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Stanislav Shwartsman
@ -1550,10 +1550,11 @@ void BX_CPU_C::PMADDWD_VdqWdq(bxInstruction_c *i)
if(op1.xmm32u(j) == 0x80008000 && op2.xmm32u(j) == 0x80008000) {
result.xmm32u(j) = 0x80000000;
}
else
else {
result.xmm32u(j) =
Bit32s(op1.xmm16s(2*j+0)) * Bit32s(op2.xmm16s(2*j+0)) +
Bit32s(op1.xmm16s(2*j+1)) * Bit32s(op2.xmm16s(2*j+1));
}
}
/* now write result back to destination */

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: sse_pfp.cc,v 1.26 2006-03-06 22:03:04 sshwarts Exp $
// $Id: sse_pfp.cc,v 1.27 2006-04-05 17:31:33 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Stanislav Shwartsman
@ -2483,7 +2483,7 @@ void BX_CPU_C::HADDPD_VpdWpd(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HADDPD_VpdWpd: required PNI, use --enable-pni option"));
BX_INFO(("HADDPD_VpdWpd: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -2537,7 +2537,7 @@ void BX_CPU_C::HADDPS_VpsWps(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HADDPS_VpsWps: required PNI, use --enable-pni option"));
BX_INFO(("HADDPS_VpsWps: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -2583,7 +2583,7 @@ void BX_CPU_C::HSUBPD_VpdWpd(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HSUBPD_VpdWpd: required PNI, use --enable-pni option"));
BX_INFO(("HSUBPD_VpdWpd: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -2637,7 +2637,7 @@ void BX_CPU_C::HSUBPS_VpsWps(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("HSUBPS_VpsWps: required PNI, use --enable-pni option"));
BX_INFO(("HSUBPS_VpsWps: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -2943,7 +2943,7 @@ void BX_CPU_C::ADDSUBPD_VpdWpd(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("ADDSUBPD_VpdWpd: required PNI, use --enable-pni option"));
BX_INFO(("ADDSUBPD_VpdWpd: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -2997,7 +2997,7 @@ void BX_CPU_C::ADDSUBPS_VpsWps(bxInstruction_c *i)
BX_WRITE_XMM_REG(i->nnn(), result);
#else
BX_INFO(("ADDSUBPS_VpsWps: required PNI, use --enable-pni option"));
BX_INFO(("ADDSUBPS_VpsWps: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: stack32.cc,v 1.31 2006-03-06 22:03:04 sshwarts Exp $
// $Id: stack32.cc,v 1.32 2006-04-05 17:31:34 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -30,11 +30,6 @@
#include "cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_X86_64==0
// Make life easier for merging 64&32-bit code.
#define RBP EBP
#endif
void BX_CPU_C::POP_Ed(bxInstruction_c *i)
{
Bit32u val32;
@ -315,7 +310,7 @@ void BX_CPU_C::ENTER_IwIb(bxInstruction_c *i)
} /* if (level > 0) ... */
if (ss32) {
RBP = frame_ptr32;
EBP = frame_ptr32;
ESP -= imm16;
}
else {
@ -363,7 +358,7 @@ void BX_CPU_C::LEAVE(bxInstruction_c *i)
if (i->os32L()) {
Bit32u temp32;
pop_32(&temp32);
RBP = temp32;
EBP = temp32;
}
else
#endif

View File

@ -30,9 +30,9 @@ static const unsigned char instruction_has_modrm[512] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0F 00 */
1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 0F 10 */
1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 0F 10 */
1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 0F 20 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 30 */
0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 0F 30 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */
@ -60,6 +60,7 @@ x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_
x86_insn insn(is_32, is_64);
const Bit8u *instruction_begin = instruction = instr;
resolve_modrm = NULL;
unsigned b3 = 0;
db_eip = ip;
db_base = base; // cs linear base (base for PM & cs<<4 for RM & VM)
@ -183,6 +184,9 @@ x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_
entry = opcode_table + insn.b1;
// will require 3rd byte for 3-byte opcode
if (entry->Attr & _GRP3BTAB) b3 = fetch_byte();
if (instruction_has_modrm[insn.b1])
{
decode_modrm(&insn);
@ -232,6 +236,14 @@ x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_
entry = &(BxDisasm3DNowGroup[peek_byte()]);
break;
case _GRP3BTAB:
entry = &(OPCODE_TABLE(entry)[b3 >> 4]);
break;
case _GRP3BOP:
entry = &(OPCODE_TABLE(entry)[b3 & 15]);
break;
default:
printf("Internal disassembler error - unknown attribute !\n");
return x86_insn(is_32, is_64);
@ -272,6 +284,11 @@ x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_
if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
opcode = &Ia_jecxz_Jb;
// fix nop opcode
if (insn.b1 == 0x90 && !insn.rex_b) {
opcode = &Ia_nop;
}
// print instruction disassembly
if (intel_mode)
print_disassembly_intel(&insn, opcode);

View File

@ -8,6 +8,8 @@
#define _GRP3DNOW 4
#define _GRPSSE 5
#define _GRPRM 6
#define _GRP3BOP 7
#define _GRP3BTAB 8
/* ************************************************************************ */
#define GRPSSE(n) _GRPSSE, BxDisasmGroupSSE_##n
@ -16,6 +18,8 @@
#define GRPMOD(n) _SPLIT11B, BxDisasmGroupMod##n
#define GRPFP(n) _GRPFP, BxDisasmFPGroup##n
#define GRP3DNOW _GRP3DNOW, BxDisasm3DNowGroup
#define GR3BOP(n) _GRP3BOP, BxDisasm3ByteOp##n
#define GR3BTAB(n) _GRP3BTAB, BxDisasm3ByteTable##n
/* ************************************************************************ */
#define Apw &disassembler::Apw

View File

@ -154,6 +154,118 @@ static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f2f[4] = {
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3800[4] = {
/* -- */ { 0, &Ia_pshufb_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pshufb_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3801[4] = {
/* -- */ { 0, &Ia_phaddw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phaddw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3802[4] = {
/* -- */ { 0, &Ia_phaddd_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phaddd_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3803[4] = {
/* -- */ { 0, &Ia_phaddsw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phaddsw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3804[4] = {
/* -- */ { 0, &Ia_pmaddubsw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pmaddubsw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3805[4] = {
/* -- */ { 0, &Ia_phsubw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phsubw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3806[4] = {
/* -- */ { 0, &Ia_phsubd_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phsubd_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3807[4] = {
/* -- */ { 0, &Ia_phsubsw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_phsubsw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3808[4] = {
/* -- */ { 0, &Ia_psignb_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_psignb_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3809[4] = {
/* -- */ { 0, &Ia_psignw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_psignw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f380a[4] = {
/* -- */ { 0, &Ia_psignd_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_psignd_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f380b[4] = {
/* -- */ { 0, &Ia_pmulhrsw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pmulhrsw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f381c[4] = {
/* -- */ { 0, &Ia_pabsb_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pabsb_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f381d[4] = {
/* -- */ { 0, &Ia_pabsw_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pabsw_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f381e[4] = {
/* -- */ { 0, &Ia_pabsd_Pq_Qq }, // SSE4
/* 66 */ { 0, &Ia_pabsd_Vdq_Wdq },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f3a0f[4] = {
/* -- */ { 0, &Ia_palignr_Pq_Qq_Ib }, // SSE4
/* 66 */ { 0, &Ia_palignr_Vdq_Wdq_Ib },
/* F2 */ { 0, &Ia_Invalid },
/* F3 */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasmGroupSSE_0f50[4] = {
/* -- */ { 0, &Ia_movmskps_Gd_Vps },
/* 66 */ { 0, &Ia_movmskpd_Gd_Vpd },
@ -2268,6 +2380,107 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodeInfoFP[512] = {
/* DF FF */ { 0, &Ia_Invalid },
};
/* ************************************************************************ */
/* 3-byte opcode table (Table A-4, 0F 38) */
static BxDisasmOpcodeTable_t BxDisasm3ByteOp0f380x[16] = {
/* 00 */ { GRPSSE(0f3800) },
/* 01 */ { GRPSSE(0f3801) },
/* 02 */ { GRPSSE(0f3802) },
/* 03 */ { GRPSSE(0f3803) },
/* 04 */ { GRPSSE(0f3804) },
/* 05 */ { GRPSSE(0f3805) },
/* 06 */ { GRPSSE(0f3806) },
/* 07 */ { GRPSSE(0f3807) },
/* 08 */ { GRPSSE(0f3808) },
/* 09 */ { GRPSSE(0f3809) },
/* 0A */ { GRPSSE(0f380a) },
/* 0B */ { GRPSSE(0f380b) },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasm3ByteOp0f381x[16] = {
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { GRPSSE(0f381c) },
/* 0D */ { GRPSSE(0f381d) },
/* 0E */ { GRPSSE(0f381e) },
/* 0F */ { 0, &Ia_Invalid }
};
static BxDisasmOpcodeTable_t BxDisasm3ByteTableA4[16] = {
/* 00 */ { GR3BOP(0f380x) },
/* 01 */ { GR3BOP(0f381x) },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid }
};
/* ************************************************************************ */
/* 3-byte opcode table (Table A-5, 0F 3A) */
static BxDisasmOpcodeTable_t BxDisasm3ByteOp0f3a0x[16] = {
/* 00 */ { 0, &Ia_Invalid },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { GRPSSE(0f3a0f) }
};
static BxDisasmOpcodeTable_t BxDisasm3ByteTableA5[16] = {
/* 00 */ { GR3BOP(0f3a0x) },
/* 01 */ { 0, &Ia_Invalid },
/* 02 */ { 0, &Ia_Invalid },
/* 03 */ { 0, &Ia_Invalid },
/* 04 */ { 0, &Ia_Invalid },
/* 05 */ { 0, &Ia_Invalid },
/* 06 */ { 0, &Ia_Invalid },
/* 07 */ { 0, &Ia_Invalid },
/* 08 */ { 0, &Ia_Invalid },
/* 09 */ { 0, &Ia_Invalid },
/* 0A */ { 0, &Ia_Invalid },
/* 0B */ { 0, &Ia_Invalid },
/* 0C */ { 0, &Ia_Invalid },
/* 0D */ { 0, &Ia_Invalid },
/* 0E */ { 0, &Ia_Invalid },
/* 0F */ { 0, &Ia_Invalid }
};
/* ************************************************************************ */
/* 16-bit operand size */
@ -2562,7 +2775,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes16[256*2] = {
/* 0F 1C */ { 0, &Ia_Invalid },
/* 0F 1D */ { 0, &Ia_Invalid },
/* 0F 1E */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_multibyte_nop },
/* 0F 20 */ { 0, &Ia_movl_Rd_Cd },
/* 0F 21 */ { 0, &Ia_movl_Rd_Dd },
/* 0F 22 */ { 0, &Ia_movl_Cd_Rd },
@ -2587,9 +2800,9 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes16[256*2] = {
/* 0F 35 */ { 0, &Ia_sysexit },
/* 0F 36 */ { 0, &Ia_Invalid },
/* 0F 37 */ { 0, &Ia_Invalid },
/* 0F 38 */ { 0, &Ia_Invalid },
/* 0F 38 */ { GR3BTAB(A4) },
/* 0F 39 */ { 0, &Ia_Invalid },
/* 0F 3A */ { 0, &Ia_Invalid },
/* 0F 3A */ { GR3BTAB(A5) },
/* 0F 3B */ { 0, &Ia_Invalid },
/* 0F 3C */ { 0, &Ia_Invalid },
/* 0F 3D */ { 0, &Ia_Invalid },
@ -3083,7 +3296,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes32[256*2] = {
/* 0F 1C */ { 0, &Ia_Invalid },
/* 0F 1D */ { 0, &Ia_Invalid },
/* 0F 1E */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_multibyte_nop },
/* 0F 20 */ { 0, &Ia_movl_Rd_Cd },
/* 0F 21 */ { 0, &Ia_movl_Rd_Dd },
/* 0F 22 */ { 0, &Ia_movl_Cd_Rd },
@ -3108,9 +3321,9 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes32[256*2] = {
/* 0F 35 */ { 0, &Ia_sysexit },
/* 0F 36 */ { 0, &Ia_Invalid },
/* 0F 37 */ { 0, &Ia_Invalid },
/* 0F 38 */ { 0, &Ia_Invalid },
/* 0F 38 */ { GR3BTAB(A4) },
/* 0F 39 */ { 0, &Ia_Invalid },
/* 0F 3A */ { 0, &Ia_Invalid },
/* 0F 3A */ { GR3BTAB(A5) },
/* 0F 3B */ { 0, &Ia_Invalid },
/* 0F 3C */ { 0, &Ia_Invalid },
/* 0F 3D */ { 0, &Ia_Invalid },
@ -3459,7 +3672,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64w[256*2] = {
/* 8D */ { 0, &Ia_leaw_Gw_Mw },
/* 8E */ { 0, &Ia_movw_Sw_Ew },
/* 8F */ { 0, &Ia_popw_Ew },
/* 90 */ { 0, &Ia_nop },
/* 90 */ { 0, &Ia_xchgw_RX_AX }, // handle XCHG R8w, AX
/* 91 */ { 0, &Ia_xchgw_RX_AX },
/* 92 */ { 0, &Ia_xchgw_RX_AX },
/* 93 */ { 0, &Ia_xchgw_RX_AX },
@ -3604,7 +3817,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64w[256*2] = {
/* 0F 1C */ { 0, &Ia_Invalid },
/* 0F 1D */ { 0, &Ia_Invalid },
/* 0F 1E */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_multibyte_nop },
/* 0F 20 */ { 0, &Ia_movq_Rq_Cq },
/* 0F 21 */ { 0, &Ia_movl_Rd_Dd },
/* 0F 22 */ { 0, &Ia_movq_Cq_Rq },
@ -3629,9 +3842,9 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64w[256*2] = {
/* 0F 35 */ { 0, &Ia_sysexit },
/* 0F 36 */ { 0, &Ia_Invalid },
/* 0F 37 */ { 0, &Ia_Invalid },
/* 0F 38 */ { 0, &Ia_Invalid },
/* 0F 38 */ { GR3BTAB(A4) },
/* 0F 39 */ { 0, &Ia_Invalid },
/* 0F 3A */ { 0, &Ia_Invalid },
/* 0F 3A */ { GR3BTAB(A5) },
/* 0F 3B */ { 0, &Ia_Invalid },
/* 0F 3C */ { 0, &Ia_Invalid },
/* 0F 3D */ { 0, &Ia_Invalid },
@ -3977,7 +4190,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64d[256*2] = {
/* 8D */ { 0, &Ia_leal_Gd_Md },
/* 8E */ { 0, &Ia_movw_Sw_Ew },
/* 8F */ { 0, &Ia_popq_Eq },
/* 90 */ { 0, &Ia_nop },
/* 90 */ { 0, &Ia_xchgl_ERX_EAX }, // handle XCHG R8d, EAX
/* 91 */ { 0, &Ia_xchgl_ERX_EAX },
/* 92 */ { 0, &Ia_xchgl_ERX_EAX },
/* 93 */ { 0, &Ia_xchgl_ERX_EAX },
@ -4122,7 +4335,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64d[256*2] = {
/* 0F 1C */ { 0, &Ia_Invalid },
/* 0F 1D */ { 0, &Ia_Invalid },
/* 0F 1E */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_multibyte_nop },
/* 0F 20 */ { 0, &Ia_movq_Rq_Cq },
/* 0F 21 */ { 0, &Ia_movl_Rd_Dd },
/* 0F 22 */ { 0, &Ia_movq_Cq_Rq },
@ -4147,9 +4360,9 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64d[256*2] = {
/* 0F 35 */ { 0, &Ia_sysexit },
/* 0F 36 */ { 0, &Ia_Invalid },
/* 0F 37 */ { 0, &Ia_Invalid },
/* 0F 38 */ { 0, &Ia_Invalid },
/* 0F 38 */ { GR3BTAB(A4) },
/* 0F 39 */ { 0, &Ia_Invalid },
/* 0F 3A */ { 0, &Ia_Invalid },
/* 0F 3A */ { GR3BTAB(A5) },
/* 0F 3B */ { 0, &Ia_Invalid },
/* 0F 3C */ { 0, &Ia_Invalid },
/* 0F 3D */ { 0, &Ia_Invalid },
@ -4495,7 +4708,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64q[256*2] = {
/* 8D */ { 0, &Ia_leaq_Gq_Mq },
/* 8E */ { 0, &Ia_movw_Sw_Ew },
/* 8F */ { 0, &Ia_popq_Eq },
/* 90 */ { 0, &Ia_nop },
/* 90 */ { 0, &Ia_xchgq_RRX_RAX }, // handle XCHG R8, RAX
/* 91 */ { 0, &Ia_xchgq_RRX_RAX },
/* 92 */ { 0, &Ia_xchgq_RRX_RAX },
/* 93 */ { 0, &Ia_xchgq_RRX_RAX },
@ -4640,7 +4853,7 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64q[256*2] = {
/* 0F 1C */ { 0, &Ia_Invalid },
/* 0F 1D */ { 0, &Ia_Invalid },
/* 0F 1E */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_Invalid },
/* 0F 1F */ { 0, &Ia_multibyte_nop },
/* 0F 20 */ { 0, &Ia_movq_Rq_Cq },
/* 0F 21 */ { 0, &Ia_movq_Rq_Dq },
/* 0F 22 */ { 0, &Ia_movq_Cq_Rq },
@ -4665,9 +4878,9 @@ static BxDisasmOpcodeTable_t BxDisasmOpcodes64q[256*2] = {
/* 0F 35 */ { 0, &Ia_sysexit },
/* 0F 36 */ { 0, &Ia_Invalid },
/* 0F 37 */ { 0, &Ia_Invalid },
/* 0F 38 */ { 0, &Ia_Invalid },
/* 0F 38 */ { GR3BTAB(A4) },
/* 0F 39 */ { 0, &Ia_Invalid },
/* 0F 3A */ { 0, &Ia_Invalid },
/* 0F 3A */ { GR3BTAB(A5) },
/* 0F 3B */ { 0, &Ia_Invalid },
/* 0F 3C */ { 0, &Ia_Invalid },
/* 0F 3D */ { 0, &Ia_Invalid },

View File

@ -16,30 +16,22 @@
}
// will be used in future
#define IA_8086 0x00000000 /* 8086 instruction */
#define IA_286 0x00000000 /* 286+ instruction */
#define IA_386 0x00000000 /* 386+ instruction */
#define IA_FPU 0x00000000
#define IA_486 0x00000000 /* 486+ instruction */
#define IA_PENTIUM 0x00000000 /* Pentium instruction */
#define IA_P6 0x00000000 /* P6 instruction */
#define IA_KATMAI 0x00000000 /* Katmai instruction */
#define IA_WILLAMETTE 0x00000000 /* Willamette instruction */
#define IA_PRESCOTT 0x00000000 /* Prescott instruction */
#define IA_X86_64 0x00000000 /* x86-64 specific instruction */
#define IF_ARITHMETIC 0x00000000 /* arithmetic instruction */
#define IF_LOGIC 0x00000000 /* logic instruction */
#define IF_SYSTEM 0x00000000 /* system instruction (require CPL=0) */
#define IF_BRANCH 0x00000000 /* branch instruction */
#define IF_FPU 0x00000000 /* FPU instruction */
#define IF_MMX 0x00000000 /* MMX instruction */
#define IF_3DNOW 0x00000000 /* 3DNow! instruction */
#define IF_KNI 0x00000000 /* Katmai new instruction */
#define IF_PREFETCH 0x00000000 /* Prefetch instruction */
#define IF_SSE 0x00000000 /* SSE instruction */
#define IF_SSE2 0x00000000 /* SSE2 instruction */
#define IF_PNI 0x00000000 /* Prescott new instruction */
#define IA_286 0x00000001 /* 286+ instruction */
#define IA_386 0x00000002 /* 386+ instruction */
#define IA_486 0x00000004 /* 486+ instruction */
#define IA_PENTIUM 0x00000008 /* Pentium+ instruction */
#define IA_P6 0x00000010 /* P6 new instruction */
#define IA_SYSTEM 0x00000020 /* system instruction (require CPL=0) */
#define IA_LEGACY 0x00000040 /* legacy instruction */
#define IA_X87 0x00000080 /* FPU (X87) instruction */
#define IA_MMX 0x00000100 /* MMX instruction */
#define IA_3DNOW 0x00000200 /* 3DNow! instruction */
#define IA_PREFETCH 0x00000400 /* Prefetch instruction */
#define IA_SSE 0x00000800 /* SSE instruction */
#define IA_SSE2 0x00001000 /* SSE2 instruction */
#define IA_SSE3 0x00002000 /* SSE3 instruction */
#define IA_SSE4 0x00004000 /* SSE4 instruction */
#define IA_X86_64 0x00008000 /* x86-64 instruction */
/* general purpose bit register */
enum {

View File

@ -667,6 +667,7 @@ Ia_mulps_Vps_Wps = { "mulps", "mulps", Vps, Wps, XX },
Ia_mulq_RAX_Eq = { "mul", "mulq", RAX, Eq, XX },
Ia_mulsd_Vsd_Wsd = { "mulsd", "mulsd", Vsd, Wsd, XX },
Ia_mulss_Vss_Wss = { "mulss", "mulss", Vss, Wss, XX },
Ia_multibyte_nop = { "multibyte nop", "multibyte nop", XX, XX, XX },
Ia_mulw_AX_Ew = { "mul", "mulw", AX, Ew, XX },
Ia_mwait = { "mwait", "mwait", XX, XX, XX },
Ia_negb_Eb = { "neg", "negb", Eb, XX, XX },
@ -708,6 +709,12 @@ Ia_outsl_DX_Xd = { "outsd", "outsl", DX, Xd, XX },
Ia_outsw_DX_Xw = { "outsw", "outsw", DX, Xw, XX },
Ia_outw_DX_AX = { "out", "outw", DX, AX, XX },
Ia_outw_Ib_AX = { "out", "outw", Ib, AX, XX },
Ia_pabsb_Pq_Qq = { "pabsb", "pabsb", Pq, Qq, XX },
Ia_pabsb_Vdq_Wdq = { "pabsb", "pabsb", Vdq, Wdq, XX },
Ia_pabsd_Pq_Qq = { "pabsd", "pabsd", Pq, Qq, XX },
Ia_pabsd_Vdq_Wdq = { "pabsd", "pabsd", Vdq, Wdq, XX },
Ia_pabsw_Pq_Qq = { "pabsw", "pabsw", Pq, Qq, XX },
Ia_pabsw_Vdq_Wdq = { "pabsw", "pabsw", Vdq, Wdq, XX },
Ia_packssdw_Pq_Qq = { "packssdw", "packssdw", Pq, Qq, XX },
Ia_packssdw_Vdq_Wdq = { "packssdw", "packssdw", Vdq, Wdq, XX },
Ia_packsswb_Pq_Qq = { "packsswb", "packsswb", Pq, Qq, XX },
@ -730,6 +737,8 @@ Ia_paddusw_Pq_Qq = { "paddusw", "paddusw", Pq, Qq, XX },
Ia_paddusw_Vdq_Wdq = { "paddusw", "paddusw", Vdq, Wdq, XX },
Ia_paddw_Pq_Qq = { "paddw", "paddw", Pq, Qq, XX },
Ia_paddw_Vdq_Wdq = { "paddw", "paddw", Vdq, Wdq, XX },
Ia_palignr_Pq_Qq_Ib = { "palignr", "palignr", Pq, Qq, Ib },
Ia_palignr_Vdq_Wdq_Ib = { "palignr", "palignr", Vdq, Wdq, Ib },
Ia_pand_Pq_Qq = { "pand", "pand", Pq, Qq, XX },
Ia_pand_Vdq_Wdq = { "pand", "pand", Vdq, Wdq, XX },
Ia_pandn_Pq_Qq = { "pandn", "pandn", Pq, Qq, XX },
@ -772,10 +781,24 @@ Ia_pfrsqit1_Pq_Qq = { "pfrsqit1", "pfrsqit1", Pq, Qq, XX },
Ia_pfrsqrt_Pq_Qq = { "pfrsqrt", "pfrsqrt", Pq, Qq, XX },
Ia_pfsub_Pq_Qq = { "pfsub", "pfsub", Pq, Qq, XX },
Ia_pfsubr_Pq_Qq = { "pfsubr", "pfsubr", Pq, Qq, XX },
Ia_phaddd_Pq_Qq = { "phaddd", "phaddd", Pq, Qq, XX },
Ia_phaddd_Vdq_Wdq = { "phaddd", "phaddd", Vdq, Wdq, XX },
Ia_phaddsw_Pq_Qq = { "phaddsw", "phaddsw", Pq, Qq, XX },
Ia_phaddsw_Vdq_Wdq = { "phaddsw", "phaddsw", Vdq, Wdq, XX },
Ia_phaddw_Pq_Qq = { "phaddw", "phaddw", Pq, Qq, XX },
Ia_phaddw_Vdq_Wdq = { "phaddw", "phaddw", Vdq, Wdq, XX },
Ia_phsubd_Pq_Qq = { "phsubd", "phsubd", Pq, Qq, XX },
Ia_phsubd_Vdq_Wdq = { "phsubd", "phsubd", Vdq, Wdq, XX },
Ia_phsubsw_Pq_Qq = { "phsubsw", "phsubsw", Pq, Qq, XX },
Ia_phsubsw_Vdq_Wdq = { "phsubsw", "phsubsw", Vdq, Wdq, XX },
Ia_phsubw_Pq_Qq = { "phsubw", "phsubw", Pq, Qq, XX },
Ia_phsubw_Vdq_Wdq = { "phsubw", "phsubw", Vdq, Wdq, XX },
Ia_pi2fd_Pq_Qq = { "pi2fd", "pi2fd", Pq, Qq, XX },
Ia_pi2fw_Pq_Qq = { "pi2fw", "pi2fw", Pq, Qq, XX },
Ia_pinsrw_Pq_Ed_Ib = { "pinsrw", "pinsrw", Pq, Ed, Ib },
Ia_pinsrw_Vdq_Ed_Ib = { "pinsrw", "pinsrw", Vdq, Ed, Ib },
Ia_pmaddubsw_Pq_Qq = { "pmaddubsw", "pmaddubsw", Pq, Qq, XX },
Ia_pmaddubsw_Vdq_Wdq = { "pmaddubsw", "pmaddubsw", Vdq, Wdq, XX },
Ia_pmaddwd_Pq_Qq = { "pmaddwd", "pmaddwd", Pq, Qq, XX },
Ia_pmaddwd_Vdq_Wdq = { "pmaddwd", "pmaddwd", Vdq, Wdq, XX },
Ia_pmaxub_Pq_Qq = { "pmaxub", "pmaxub", Pq, Qq, XX },
@ -788,6 +811,8 @@ Ia_pminub_Pq_Qq = { "pminub", "pminub", Pq, Qq, XX },
Ia_pminub_Vdq_Wdq = { "pminub", "pminub", Vdq, Wdq, XX },
Ia_pmovmskb_Gd_Nq = { "pmovmskb", "pmovmskb", Gd, Nq, XX },
Ia_pmovmskb_Gd_Udq = { "pmovmskb", "pmovmskb", Gd, Udq, XX },
Ia_pmulhrsw_Pq_Qq = { "pmulhrsw", "pmulhrsw", Pq, Qq, XX },
Ia_pmulhrsw_Vdq_Wdq = { "pmulhrsw", "pmulhrsw", Vdq, Wdq, XX },
Ia_pmulhrw_Pq_Qq = { "pmulhrw", "pmulhrw", Pq, Qq, XX },
Ia_pmulhuw_Pq_Qq = { "pmulhuw", "pmulhuw", Pq, Qq, XX },
Ia_pmulhuw_Vdq_Wdq = { "pmulhuw", "pmulhuw", Vdq, Wdq, XX },
@ -841,10 +866,18 @@ Ia_prefix_rex = { "rex", "rex", XX, XX, XX },
Ia_prefix_ss = { "ss", "ss", XX, XX, XX },
Ia_psadbw_Pq_Qq = { "psadbw", "psadbw", Pq, Qq, XX },
Ia_psadbw_Vdq_Wdq = { "psadbw", "psadbw", Vdq, Wdq, XX },
Ia_pshufb_Pq_Qq = { "pshufb", "pshufb", Pq, Qq, XX },
Ia_pshufb_Vdq_Wdq = { "pshufb", "pshufb", Vdq, Wdq, XX },
Ia_pshufd_Vdq_Wdq_Ib = { "pshufd", "pshufd", Vdq, Wdq, Ib },
Ia_pshufhw_Vq_Wq_Ib = { "pshufhw", "pshufhw", Vq, Wq, Ib },
Ia_pshuflw_Vq_Wq_Ib = { "pshuflw", "pshuflw", Vq, Wq, Ib },
Ia_pshufw_Pq_Qq_Ib = { "pshufw", "pshufw", Pq, Qq, Ib },
Ia_psignb_Pq_Qq = { "psignb", "psignb", Pq, Qq, XX },
Ia_psignb_Vdq_Wdq = { "psignb", "psignb", Vdq, Wdq, XX },
Ia_psignd_Pq_Qq = { "psignd", "psignd", Pq, Qq, XX },
Ia_psignd_Vdq_Wdq = { "psignd", "psignd", Vdq, Wdq, XX },
Ia_psignw_Pq_Qq = { "psignw", "psignw", Pq, Qq, XX },
Ia_psignw_Vdq_Wdq = { "psignw", "psignw", Vdq, Wdq, XX },
Ia_pslld_Nq_Ib = { "pslld", "pslld", Nq, Ib, XX },
Ia_pslld_Pq_Qq = { "pslld", "pslld", Pq, Qq, XX },
Ia_pslld_Udq_Ib = { "pslld", "pslld", Udq, Ib, XX },

View File

@ -1,7 +1,7 @@
<!--
================================================================
doc/docbook/user/user.dbk
$Id: user.dbk,v 1.208 2006-02-11 21:57:04 sshwarts Exp $
$Id: user.dbk,v 1.209 2006-04-05 17:31:35 sshwarts Exp $
This is the top level file for the Bochs Users Manual.
================================================================
@ -35,7 +35,7 @@ This is the top level file for the Bochs Users Manual.
<para>
Bochs is a program that simulates a complete Intel x86 computer. It
can be configured to act like a <!--286,--> 386, 486, Pentium, Pentium Pro, or
AMD64 CPU, including optional MMX, SSE, SSE2 and 3DNow! instructions.
AMD64 CPU, including optional MMX, SSE, SSE2, SSE3 and 3DNow! instructions.
Bochs interprets every instruction from power-up to reboot, and has
device models for all of the standard PC peripherals: keyboard, mouse,
VGA card/monitor, disks, timer chips, network card, etc. Because Bochs
@ -2210,14 +2210,9 @@ turn it off.
<entry>no</entry>
<entry>
Add support for SSE instructions, written by Stanislav Shwartsman.
For SSE only, use --enable-sse=1. For SSE and SSE2, use --enable-sse=2.
Any of SSE/SSE2/SSE3 instruction sets are supported.
</entry>
</row>
<row>
<entry>--enable-pni</entry>
<entry>no</entry>
<entry>Add support for PNI (SSE3) instructions</entry>
</row>
<row>
<entry>--enable-sep</entry>
<entry>no</entry>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fpu_load_store.cc,v 1.10 2006-03-06 22:03:04 sshwarts Exp $
// $Id: fpu_load_store.cc,v 1.11 2006-04-05 17:31:35 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003 Stanislav Shwartsman
@ -600,7 +600,7 @@ void BX_CPU_C::FISTTP16(bxInstruction_c *i)
write_virtual_word(i->seg(), RMAddr(i), (Bit16u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP16: required PNI, configure --enable-pni"));
BX_INFO(("FISTTP16: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -636,7 +636,7 @@ void BX_CPU_C::FISTTP32(bxInstruction_c *i)
write_virtual_dword(i->seg(), RMAddr(i), (Bit32u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP32: required PNI, configure --enable-pni"));
BX_INFO(("FISTTP32: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}
@ -672,7 +672,7 @@ void BX_CPU_C::FISTTP64(bxInstruction_c *i)
write_virtual_qword(i->seg(), RMAddr(i), (Bit64u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP64: required PNI, configure --enable-pni"));
BX_INFO(("FISTTP64: required SSE3, use --enable-sse option"));
UndefinedOpcode(i);
#endif
}