Unpack more fields in bxInstruction_c -> this increase bxInstruction size by 4 bytes but I have no way but do it if want to support SSE5 dest override later

This commit is contained in:
Stanislav Shwartsman 2008-02-04 21:28:53 +00:00
parent 25a9b9fef1
commit fb0ce45d28
4 changed files with 94 additions and 73 deletions

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer_pro.cc,v 1.66 2008-02-02 21:46:50 sshwarts Exp $
// $Id: ctrl_xfer_pro.cc,v 1.67 2008-02-04 21:28:53 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -103,18 +103,20 @@ BX_CPU_C::load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cp
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR efer.lma) {
unsigned mode = BX_CPU_THIS_PTR cpu_mode;
if (descriptor->u.segment.l) {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_64;
BX_DEBUG(("Long Mode Activated"));
loadSRegLMNominal(BX_SEG_REG_CS, selector->value, cpl);
}
else {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
BX_DEBUG(("Compatibility Mode Activated"));
if (BX_CPU_THIS_PTR eip_reg.dword.rip_upper != 0) {
BX_PANIC(("handleCpuModeChange: leaving long mode with RIP upper != 0 !"));
}
}
if (mode != BX_CPU_THIS_PTR cpu_mode) {
BX_DEBUG(("%s activated", cpu_mode_string(BX_CPU_THIS_PTR cpu_mode)));
}
}
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.cc,v 1.163 2008-02-02 21:46:50 sshwarts Exp $
// $Id: fetchdecode.cc,v 1.164 2008-02-04 21:28:53 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2470,8 +2470,8 @@ BX_CPU_C::fetchDecode32(Bit8u *iptr, bxInstruction_c *i, unsigned remainingInPag
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
i->ResolveModrm = 0;
i->initMetaInfo(/*os32*/ is_32, /*as32*/ is_32,
/*os64*/ 0, /*as64*/ 0);
i->init(/*os32*/ is_32, /*as32*/ is_32,
/*os64*/ 0, /*as64*/ 0);
offset = os_32 << 9; // * 512
@ -2607,10 +2607,10 @@ fetch_b1:
if ((b1 & ~3) == 0x120)
mod = 0xc0;
i->metaData.modRMData1 = rm;
i->metaData.modRMData2 = mod;
i->setModRM(b2);
i->metaData.metaData1 = rm;
i->setSibBase(rm); // initialize with rm to use BxResolve32Base
i->metaData.modRMData4 = nnn;
i->metaData.metaData5 = nnn;
// initialize displ32 with zero to include cases with no diplacement
i->modRMForm.displ32u = 0;
@ -2668,9 +2668,9 @@ get_8bit_displ:
base = sib & 0x7; sib >>= 3;
index = sib & 0x7; sib >>= 3;
scale = sib;
i->setSibIndex(index);
i->setSibScale(scale);
i->setSibBase(base);
i->metaData.modRMData2 |= (index);
i->metaData.modRMData2 |= (scale<<4);
if (index == 4)
i->ResolveModrm = &BX_CPU_C::BxResolve32Base;
else
@ -2794,7 +2794,7 @@ modrm_done:
// the if() above after fetching the 2nd byte, so this path is
// taken in all cases if a modrm byte is NOT required.
i->execute = BxOpcodeInfo32R[b1+offset].ExecutePtr;
i->metaData.modRMData1 = b1 & 7;
i->setOpcodeReg(b1 & 7);
}
if (lock) { // lock prefix invalid opcode
@ -2974,7 +2974,7 @@ modrm_done:
void BX_CPU_C::BxError(bxInstruction_c *i)
{
BX_DEBUG(("BxError: i with opcode=0x%x", i->b1()));
BX_DEBUG(("mod was %x, nnn was %u, rm was %u", i->mod(), i->nnn(), i->rm()));
BX_DEBUG(("modrm was 0x%02x, nnn was %u, rm was %u", i->modrm(), i->nnn(), i->rm()));
BX_DEBUG(("WARNING: Encountered an unknown i (signalling illegal i)"));
BX_CPU_THIS_PTR UndefinedOpcode(i);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode64.cc,v 1.170 2008-02-02 21:46:51 sshwarts Exp $
// $Id: fetchdecode64.cc,v 1.171 2008-02-04 21:28:53 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -3372,10 +3372,10 @@ BX_CPU_C::fetchDecode64(Bit8u *iptr, bxInstruction_c *i, unsigned remainingInPag
unsigned rex_prefix = 0;
i->ResolveModrm = 0;
i->initMetaInfo(/*os32*/ 1, // operand size 32 override defaults to 1
/*as32*/ 1, // address size 32 override defaults to 1
/*os64*/ 0, // operand size 64 override defaults to 0
/*as64*/ 1); // address size 64 override defaults to 1
i->init(/*os32*/ 1, // operand size 32 override defaults to 1
/*as32*/ 1, // address size 32 override defaults to 1
/*os64*/ 0, // operand size 64 override defaults to 0
/*as64*/ 1); // address size 64 override defaults to 1
fetch_b1:
b1 = *iptr++;
@ -3534,10 +3534,10 @@ fetch_b1:
if ((b1 & ~3) == 0x120)
mod = 0xc0;
i->metaData.modRMData1 = rm;
i->metaData.modRMData2 = mod;
i->setModRM(b2);
i->metaData.metaData1 = rm;
i->setSibBase(rm); // initialize with rm to use BxResolve32Base
i->metaData.modRMData4 = nnn;
i->metaData.metaData5 = nnn;
// initialize displ32 with zero to include cases with no diplacement
i->modRMForm.displ32u = 0;
@ -3595,9 +3595,9 @@ get_8bit_displ:
base = (sib & 0x7) | rex_b; sib >>= 3;
index = (sib & 0x7) | rex_x; sib >>= 3;
scale = sib;
i->setSibIndex(index);
i->setSibScale(scale);
i->setSibBase(base);
i->metaData.modRMData2 |= (index);
i->metaData.modRMData2 |= (scale<<4);
if (index == 4)
i->ResolveModrm = &BX_CPU_C::BxResolve64Base;
else
@ -3657,8 +3657,8 @@ get_8bit_displ:
index = (sib & 0x7) | rex_x; sib >>= 3;
scale = sib;
i->setSibBase(base);
i->metaData.modRMData2 |= (index);
i->metaData.modRMData2 |= (scale<<4);
i->metaData.metaData2 |= (index);
i->metaData.metaData2 |= (scale<<4);
if (index == 4)
i->ResolveModrm = &BX_CPU_C::BxResolve32Base;
else
@ -3748,7 +3748,7 @@ modrm_done:
// the if() above after fetching the 2nd byte, so this path is
// taken in all cases if a modrm byte is NOT required.
i->execute = BxOpcodeInfo64R[b1+offset].ExecutePtr;
i->metaData.modRMData1 = (b1 & 7) | rex_b;
i->setOpcodeReg((b1 & 7) | rex_b);
}
if (lock) { // lock prefix invalid opcode

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: instr.h,v 1.3 2008-02-02 21:46:51 sshwarts Exp $
// $Id: instr.h,v 1.4 2008-02-04 21:28:53 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2008 Stanislav Shwartsman
@ -40,16 +40,14 @@ public:
#endif
struct {
// 31..29 (unused)
// 28..20 b1 (9bits of opcode; 1byte-op=0..255, 2byte-op=256..511
// 15...7 b1 (9bits of opcode; 1byte-op=0..255, 2byte-op=256..511
// (leave this one on top so no mask is needed)
// 19..19 stop trace (used with trace cache)
// 18..18 mod==c0 (modrm)
// 17..16 repUsed (0=none, 2=0xF2, 3=0xF3)
// 6...1 (unused - 6 bits)
// 0...0 stop trace (used with trace cache)
Bit16u metaInfo3;
// 15..12 (unused)
// 11...8 ilen (0..15)
// 7...4 (unused)
// 3...0 ilen (0..15)
Bit8u metaInfo2;
// 7...7 extend8bit
@ -57,27 +55,42 @@ public:
// 5...5 os64
// 4...4 as32
// 3...3 os32
// 2...0 seg
// 2...2 mod==c0 (modrm)
// 1...0 repUsed (0=none, 2=0xF2, 3=0xF3)
Bit8u metaInfo1;
} metaInfo;
struct {
// 31..28 (unused)
// 27..24 nnn (modrm)
Bit8u modRMData4;
// (unused, keep for alignment)
// (will be used for SSE5 destination override later)
Bit8u metaData8;
// 23..20 (unused)
// 19..16 base (sib)
Bit8u modRMData3;
// 7...0 modrm
Bit8u metaData7;
// 15..14 mod (modrm)
// 13..12 scale (sib)
// 11...8 index (sib)
Bit8u modRMData2;
// 7...3 (unused)
// 2...0 seg
Bit8u metaData6;
// 7...4 (unused)
// 3...0 nnn (modrm)
Bit8u metaData5;
// 7...4 (unused)
// 3...0 base (sib)
Bit8u metaData4;
// 7...4 (unused)
// 3...0 index (sib)
Bit8u metaData3;
// 7...2 (unused)
// 1...0 scale (sib)
Bit8u metaData2;
// 7...4 (unused)
// 3...0 rm (modrm) // also used for opcodeReg()
Bit8u modRMData1;
Bit8u metaData1;
} metaData;
union {
@ -114,48 +127,54 @@ public:
#endif
};
BX_CPP_INLINE unsigned opcodeReg() {
BX_CPP_INLINE void setOpcodeReg(unsigned opreg) {
// The opcodeReg form (low 3 bits of the opcode byte (extended
// by REX.B on x86-64) to be used with IxIxForm or IqForm.
return metaData.modRMData1;
metaData.metaData1 = opreg;
}
BX_CPP_INLINE unsigned opcodeReg() {
return metaData.metaData1;
}
BX_CPP_INLINE void setModRM(unsigned modrm) {
metaData.metaData7 = modrm;
}
// used in FPU only
BX_CPP_INLINE unsigned modrm() {
#if BX_SUPPORT_X86_64
return mod() | (rm() & 7) | ((nnn() & 7) << 3);
#else
return mod() | rm() | (nnn() << 3);
#endif
return metaData.metaData7;
}
BX_CPP_INLINE unsigned mod() { return metaData.modRMData2 & 0xc0; }
BX_CPP_INLINE unsigned modC0()
{
// This is a cheaper way to test for modRM instructions where
// the mod field is 0xc0. FetchDecode flags this condition since
// it is quite common to be tested for.
return metaInfo.metaInfo3 & (1<<2);
return metaInfo.metaInfo1 & (1<<2);
}
BX_CPP_INLINE unsigned assertModC0()
{
return metaInfo.metaInfo3 |= (1<<2);
return metaInfo.metaInfo1 |= (1<<2);
}
BX_CPP_INLINE unsigned nnn() {
return metaData.modRMData4;
return metaData.metaData5;
}
BX_CPP_INLINE unsigned rm() {
return metaData.modRMData1;
return metaData.metaData1;
}
BX_CPP_INLINE void setSibScale(unsigned scale) {
metaData.metaData2 = scale;
}
BX_CPP_INLINE unsigned sibScale() {
return (metaData.modRMData2 >> 4) & 0x3;
return metaData.metaData2;
}
BX_CPP_INLINE void setSibIndex(unsigned index) {
metaData.metaData3 = index;
}
BX_CPP_INLINE unsigned sibIndex() {
return (metaData.modRMData2) & 0xf;
return metaData.metaData3;
}
BX_CPP_INLINE void setSibBase(unsigned base) {
metaData.modRMData3 = base;
metaData.metaData4 = base;
}
BX_CPP_INLINE unsigned sibBase() {
return metaData.modRMData3;
return metaData.metaData4;
}
BX_CPP_INLINE Bit32u displ32u() { return modRMForm.displ32u; }
BX_CPP_INLINE Bit16u displ16u() { return modRMForm.displ16u; }
@ -173,18 +192,18 @@ public:
// is for Logical comparisons, eg if (i->os32L() && i->as32L()). If you
// want a bx_bool value, use os32B() etc. This makes for smaller
// code, when a strict 0 or 1 is not necessary.
BX_CPP_INLINE void initMetaInfo(unsigned os32, unsigned as32,
unsigned os64, unsigned as64)
BX_CPP_INLINE void init(unsigned os32, unsigned as32, unsigned os64, unsigned as64)
{
metaInfo.metaInfo1 = BX_SEG_REG_NULL | (os32<<3) | (as32<<4) | (os64<<5) | (as64<<6);
metaInfo.metaInfo1 = (os32<<3) | (as32<<4) | (os64<<5) | (as64<<6);
metaInfo.metaInfo2 = 0;
metaInfo.metaInfo3 = 0;
metaData.metaData6 = BX_SEG_REG_NULL;
}
BX_CPP_INLINE unsigned seg(void) {
return metaInfo.metaInfo1 & 7;
return metaData.metaData6;
}
BX_CPP_INLINE void setSeg(unsigned val) {
metaInfo.metaInfo1 = (metaInfo.metaInfo1 & ~7) | val;
metaData.metaData6 = val;
}
BX_CPP_INLINE unsigned os32L(void) {
@ -249,13 +268,13 @@ public:
}
BX_CPP_INLINE unsigned repUsedL(void) {
return metaInfo.metaInfo3 & 3;
return metaInfo.metaInfo1 & 3;
}
BX_CPP_INLINE unsigned repUsedValue(void) {
return metaInfo.metaInfo3 & 3;
return metaInfo.metaInfo1 & 3;
}
BX_CPP_INLINE void setRepUsed(unsigned value) {
metaInfo.metaInfo3 = (metaInfo.metaInfo3 & ~3) | (value);
metaInfo.metaInfo1 = (metaInfo.metaInfo1 & ~3) | (value);
}
#if BX_SUPPORT_TRACE_CACHE
@ -270,10 +289,10 @@ public:
// Note this is the highest field, and thus needs no masking.
// DON'T PUT ANY FIELDS HIGHER THAN THIS ONE WITHOUT ADDING A MASK.
BX_CPP_INLINE unsigned b1(void) {
return metaInfo.metaInfo3 >> 4;
return metaInfo.metaInfo3 >> 7;
}
BX_CPP_INLINE void setB1(unsigned b1) {
metaInfo.metaInfo3 = (metaInfo.metaInfo3 & ~(0x1ff << 4)) | ((b1 & 0x1ff) << 4);
metaInfo.metaInfo3 = (metaInfo.metaInfo3 & ~(0x1ff << 7)) | ((b1 & 0x1ff) << 7);
}
};
// <TAG-CLASS-INSTRUCTION-END>