summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/miscregfile.cc43
-rw-r--r--src/arch/x86/miscregfile.hh2
-rw-r--r--src/arch/x86/miscregs.hh5
-rw-r--r--src/arch/x86/predecoder.cc78
-rw-r--r--src/arch/x86/predecoder.hh5
5 files changed, 69 insertions, 64 deletions
diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc
index f7c804fd0..317cdadc5 100644
--- a/src/arch/x86/miscregfile.cc
+++ b/src/arch/x86/miscregfile.cc
@@ -97,7 +97,7 @@ using namespace std;
class Checkpoint;
void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0,
- SegAttr csAttr, RFLAGS rflags)
+ SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags)
{
HandyM5Reg m5reg;
if (efer.lma) {
@@ -120,6 +120,37 @@ void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0,
m5reg.cpl = csAttr.dpl;
m5reg.paging = cr0.pg;
m5reg.prot = cr0.pe;
+
+ // Compute the default and alternate operand size.
+ if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) {
+ m5reg.defOp = 2;
+ m5reg.altOp = 1;
+ } else {
+ m5reg.defOp = 1;
+ m5reg.altOp = 2;
+ }
+
+ // Compute the default and alternate address size.
+ if (m5reg.submode == SixtyFourBitMode) {
+ m5reg.defAddr = 3;
+ m5reg.altAddr = 2;
+ } else if (csAttr.defaultSize) {
+ m5reg.defAddr = 2;
+ m5reg.altAddr = 1;
+ } else {
+ m5reg.defAddr = 1;
+ m5reg.altAddr = 2;
+ }
+
+ // Compute the stack size
+ if (m5reg.submode == SixtyFourBitMode) {
+ m5reg.stack = 3;
+ } else if (ssAttr.defaultSize) {
+ m5reg.stack = 2;
+ } else {
+ m5reg.stack = 1;
+ }
+
regVal[MISCREG_M5_REG] = m5reg;
}
@@ -199,6 +230,7 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
updateHandyM5Reg(regVal[MISCREG_EFER],
newCR0,
regVal[MISCREG_CS_ATTR],
+ regVal[MISCREG_SS_ATTR],
regVal[MISCREG_RFLAGS]);
}
break;
@@ -239,9 +271,17 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
updateHandyM5Reg(regVal[MISCREG_EFER],
regVal[MISCREG_CR0],
newCSAttr,
+ regVal[MISCREG_SS_ATTR],
regVal[MISCREG_RFLAGS]);
}
break;
+ case MISCREG_SS_ATTR:
+ updateHandyM5Reg(regVal[MISCREG_EFER],
+ regVal[MISCREG_CR0],
+ regVal[MISCREG_CS_ATTR],
+ val,
+ regVal[MISCREG_RFLAGS]);
+ break;
// These segments always actually use their bases, or in other words
// their effective bases must stay equal to their actual bases.
case MISCREG_FS_BASE:
@@ -346,6 +386,7 @@ void MiscRegFile::setReg(MiscRegIndex miscReg,
updateHandyM5Reg(regVal[MISCREG_EFER],
regVal[MISCREG_CR0],
regVal[MISCREG_CS_ATTR],
+ regVal[MISCREG_SS_ATTR],
regVal[MISCREG_RFLAGS]);
return;
default:
diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh
index 0488dbba7..babc65b44 100644
--- a/src/arch/x86/miscregfile.hh
+++ b/src/arch/x86/miscregfile.hh
@@ -108,7 +108,7 @@ namespace X86ISA
protected:
MiscReg regVal[NumMiscRegs];
void updateHandyM5Reg(Efer efer, CR0 cr0,
- SegAttr csAttr, RFLAGS rflags);
+ SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags);
public:
void clear();
diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh
index 7d46a87b9..088dbeace 100644
--- a/src/arch/x86/miscregs.hh
+++ b/src/arch/x86/miscregs.hh
@@ -520,6 +520,11 @@ namespace X86ISA
Bitfield<5, 4> cpl;
Bitfield<6> paging;
Bitfield<7> prot;
+ Bitfield<9, 8> defOp;
+ Bitfield<11, 10> altOp;
+ Bitfield<13, 12> defAddr;
+ Bitfield<15, 14> altAddr;
+ Bitfield<17, 16> stack;
EndBitUnion(HandyM5Reg)
/**
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index 620ab89ea..5bac8e711 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -80,9 +80,9 @@ namespace X86ISA
emi.modRM = 0;
emi.sib = 0;
- HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
- emi.mode.mode = m5reg.mode;
- emi.mode.submode = m5reg.submode;
+ m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ emi.mode.mode = m5Reg.mode;
+ emi.mode.submode = m5Reg.submode;
}
void Predecoder::process()
@@ -216,34 +216,15 @@ namespace X86ISA
DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
emi.opcode.op = nextByte;
- SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
-
//Figure out the effective operand size. This can be overriden to
//a fixed value at the decoder level.
int logOpSize;
- if (emi.mode.submode == SixtyFourBitMode)
- {
- if(emi.rex.w)
- logOpSize = 3; // 64 bit operand size
- else if(emi.legacy.op)
- logOpSize = 1; // 16 bit operand size
- else
- logOpSize = 2; // 32 bit operand size
- }
- else if(csAttr.defaultSize)
- {
- if(emi.legacy.op)
- logOpSize = 1; // 16 bit operand size
- else
- logOpSize = 2; // 32 bit operand size
- }
- else // 16 bit default operand size
- {
- if(emi.legacy.op)
- logOpSize = 2; // 32 bit operand size
- else
- logOpSize = 1; // 16 bit operand size
- }
+ if (emi.rex.w)
+ logOpSize = 3; // 64 bit operand size
+ else if (emi.legacy.op)
+ logOpSize = m5Reg.altOp;
+ else
+ logOpSize = m5Reg.defOp;
//Set the actual op size
emi.opSize = 1 << logOpSize;
@@ -251,41 +232,18 @@ namespace X86ISA
//Figure out the effective address size. This can be overriden to
//a fixed value at the decoder level.
int logAddrSize;
- if(emi.mode.submode == SixtyFourBitMode)
- {
- if(emi.legacy.addr)
- logAddrSize = 2; // 32 bit address size
- else
- logAddrSize = 3; // 64 bit address size
- }
- else if(csAttr.defaultSize)
- {
- if(emi.legacy.addr)
- logAddrSize = 1; // 16 bit address size
- else
- logAddrSize = 2; // 32 bit address size
- }
- else // 16 bit default operand size
- {
- if(emi.legacy.addr)
- logAddrSize = 2; // 32 bit address size
- else
- logAddrSize = 1; // 16 bit address size
- }
-
- SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR);
- //Figure out the effective stack width. This can be overriden to
- //a fixed value at the decoder level.
- if(emi.mode.submode == SixtyFourBitMode)
- emi.stackSize = 8; // 64 bit stack width
- else if(ssAttr.defaultSize)
- emi.stackSize = 4; // 32 bit stack width
+ if(emi.legacy.addr)
+ logAddrSize = m5Reg.altAddr;
else
- emi.stackSize = 2; // 16 bit stack width
+ logAddrSize = m5Reg.defAddr;
//Set the actual address size
emi.addrSize = 1 << logAddrSize;
+ //Figure out the effective stack width. This can be overriden to
+ //a fixed value at the decoder level.
+ emi.stackSize = 1 << m5Reg.stack;
+
//Figure out how big of an immediate we'll retreive based
//on the opcode.
int immType = ImmediateType[emi.opcode.num - 1][nextByte];
@@ -318,9 +276,7 @@ namespace X86ISA
ModRM modRM;
modRM = nextByte;
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
- SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
- if (emi.mode.submode != SixtyFourBitMode &&
- !csAttr.defaultSize) {
+ if (m5Reg.defOp == 1) {
//figure out 16 bit displacement size
if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
displacementSize = 2;
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index a16ce6fb8..4893f1de9 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -61,6 +61,7 @@
#include <cassert>
#include "arch/x86/types.hh"
+#include "arch/x86/miscregs.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"
#include "base/trace.hh"
@@ -91,10 +92,11 @@ namespace X86ISA
int offset;
//The extended machine instruction being generated
ExtMachInst emi;
+ HandyM5Reg m5Reg;
inline uint8_t getNextByte()
{
- return (fetchChunk >> (offset * 8)) & 0xff;
+ return ((uint8_t *)&fetchChunk)[offset];
}
void getImmediate(int &collected, uint64_t &current, int size)
@@ -182,6 +184,7 @@ namespace X86ISA
{
emi.mode.mode = LongMode;
emi.mode.submode = SixtyFourBitMode;
+ m5Reg = 0;
}
void reset()