From 7146eb79f179510c980fd7681d1e45adf212c2b0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 26 Apr 2009 16:49:24 -0700 Subject: [PATCH] X86: Precompute the default and alternate address and operand size and the stack size. --- src/arch/x86/miscregfile.cc | 43 +++++++++++++++++++- src/arch/x86/miscregfile.hh | 2 +- src/arch/x86/miscregs.hh | 5 +++ src/arch/x86/predecoder.cc | 78 ++++++++----------------------------- src/arch/x86/predecoder.hh | 5 ++- 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 #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 ¤t, int size) @@ -182,6 +184,7 @@ namespace X86ISA { emi.mode.mode = LongMode; emi.mode.submode = SixtyFourBitMode; + m5Reg = 0; } void reset()