From 6c125779372ecc7c9482f6e79bd4c5c0c99ad7ec Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 18 Jun 2007 14:15:00 +0000 Subject: Add in incomplete pick and merge functions which read and write pieces of registers, and fill out microcode disassembly. --HG-- extra : convert_revision : 56332b3999a9079b1bd305ee2826abdf593367e1 --- src/arch/x86/isa/base.isa | 58 ++++++++++++++- src/arch/x86/isa/microops/limmop.isa | 18 +++++ src/arch/x86/isa/microops/regop.isa | 138 ++++++++++++++++++++++++++++------- src/arch/x86/isa_traits.hh | 4 +- 4 files changed, 187 insertions(+), 31 deletions(-) diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa index eba24f709..d9bd87f2d 100644 --- a/src/arch/x86/isa/base.isa +++ b/src/arch/x86/isa/base.isa @@ -95,6 +95,14 @@ output header {{ /** * Base class for all X86 static instructions. */ + BitUnion64(X86IntReg) + Bitfield<63,0> R; + Bitfield<31,0> E; + Bitfield<15,0> X; + Bitfield<15,8> H; + Bitfield<7, 0> L; + EndBitUnion(X86IntReg) + class X86StaticInst : public StaticInst { protected: @@ -114,10 +122,50 @@ output header {{ inline uint64_t merge(uint64_t into, uint64_t val, int size) const { - //FIXME This needs to be significantly more sophisticated + X86IntReg reg; + reg = into; + //FIXME This needs to be handle high bytes as well + switch(size) + { + case 1: + reg.L = val; + break; + case 2: + reg.X = val; + break; + case 4: + //XXX Check if this should be zeroed or sign extended + reg = 0; + reg.E = val; + break; + case 8: + reg.R = val; + break; + default: + panic("Tried to merge with unrecognized size %d.\n", size); + } return val; } + inline uint64_t pick(uint64_t from, int size) + { + X86IntReg reg; + reg = from; + switch(size) + { + case 1: + return reg.L; + case 2: + return reg.E; + case 4: + return reg.X; + case 8: + return reg.R; + default: + panic("Tried to pick with unrecognized size %d.\n", size); + } + } + }; }}; @@ -128,6 +176,12 @@ output decoder {{ ccprintf(os, "\t%s ", mnemonic); } + inline void printMnemonic(std::ostream &os, + const char * instMnemonic, const char * mnemonic) + { + ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); + } + void X86StaticInst::printSrcReg(std::ostream &os, int reg) const { @@ -197,6 +251,8 @@ output decoder {{ case INTREG_R15W: ccprintf(os, "r15"); break; + default: + ccprintf(os, "t%d", reg - NUM_INTREGS); } } else if (reg < Ctrl_Base_DepTag) { ccprintf(os, "%%f%d", reg - FP_Base_DepTag); diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index c76c074b1..141d7523f 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -79,6 +79,9 @@ def template MicroLimmOpDeclare {{ const uint64_t imm; void buildMe(); + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + public: %(class_name)s(ExtMachInst _machInst, const char * instMnem, @@ -93,6 +96,20 @@ def template MicroLimmOpDeclare {{ }; }}; +def template MicroLimmOpDisassembly {{ + std::string %(class_name)s::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, dest); + response << ", "; + ccprintf(response, "%#x", imm); + return response.str(); + } +}}; + def template MicroLimmOpConstructor {{ inline void %(class_name)s::buildMe() @@ -148,5 +165,6 @@ let {{ {"code" : "DestReg = imm;"}) header_output += MicroLimmOpDeclare.subst(iop) decoder_output += MicroLimmOpConstructor.subst(iop) + decoder_output += MicroLimmOpDisassembly.subst(iop) exec_output += MicroLimmOpExecute.subst(iop) }}; diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index a99194c5e..d5fb25cb5 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -59,6 +59,100 @@ // ////////////////////////////////////////////////////////////////////////// +output header {{ + /** + * Base classes for RegOps which provides a generateDisassembly method. + */ + class RegOp : public X86MicroopBase + { + protected: + const RegIndex src1; + const RegIndex src2; + const RegIndex dest; + const bool setStatus; + const uint8_t dataSize; + const uint8_t ext; + + // Constructor + RegOp(ExtMachInst _machInst, + const char *mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + RegIndex _src1, RegIndex _src2, RegIndex _dest, + bool _setStatus, uint8_t _dataSize, uint8_t _ext, + OpClass __opClass) : + X86MicroopBase(_machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, + __opClass), + src1(_src1), src2(_src2), dest(_dest), + setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + class RegOpImm : public X86MicroopBase + { + protected: + const RegIndex src1; + const uint8_t imm8; + const RegIndex dest; + const bool setStatus; + const uint8_t dataSize; + const uint8_t ext; + + // Constructor + RegOpImm(ExtMachInst _machInst, + const char * mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + RegIndex _src1, uint8_t _imm8, RegIndex _dest, + bool _setStatus, uint8_t _dataSize, uint8_t _ext, + OpClass __opClass) : + X86MicroopBase(_machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, + __opClass), + src1(_src1), imm8(_imm8), dest(_dest), + setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string RegOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, dest); + response << ", "; + printReg(response, src1); + response << ", "; + printReg(response, src2); + return response.str(); + } + + std::string RegOpImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, dest); + response << ", "; + printReg(response, src1); + ccprintf(response, ", %#x", imm8); + return response.str(); + } +}}; + def template MicroRegOpExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -101,12 +195,6 @@ def template MicroRegOpDeclare {{ class %(class_name)s : public %(base_class)s { protected: - const RegIndex src1; - const RegIndex src2; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; void buildMe(); public: @@ -130,12 +218,6 @@ def template MicroRegOpImmDeclare {{ class %(class_name)sImm : public %(base_class)s { protected: - const RegIndex src1; - const uint8_t imm8; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; void buildMe(); public: @@ -166,9 +248,9 @@ def template MicroRegOpConstructor {{ RegIndex _src1, RegIndex _src2, RegIndex _dest, bool _setStatus, uint8_t _dataSize, uint8_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - false, false, false, false, %(op_class)s), - src1(_src1), src2(_src2), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + false, false, false, false, + _src1, _src2, _dest, _setStatus, _dataSize, _ext, + %(op_class)s) { buildMe(); } @@ -179,9 +261,9 @@ def template MicroRegOpConstructor {{ RegIndex _src1, RegIndex _src2, RegIndex _dest, bool _setStatus, uint8_t _dataSize, uint8_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - isMicro, isDelayed, isFirst, isLast, %(op_class)s), - src1(_src1), src2(_src2), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + isMicro, isDelayed, isFirst, isLast, + _src1, _src2, _dest, _setStatus, _dataSize, _ext, + %(op_class)s) { buildMe(); } @@ -199,9 +281,9 @@ def template MicroRegOpImmConstructor {{ RegIndex _src1, uint8_t _imm8, RegIndex _dest, bool _setStatus, uint8_t _dataSize, uint8_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - false, false, false, false, %(op_class)s), - src1(_src1), imm8(_imm8), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + false, false, false, false, + _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + %(op_class)s) { buildMe(); } @@ -212,9 +294,9 @@ def template MicroRegOpImmConstructor {{ RegIndex _src1, uint8_t _imm8, RegIndex _dest, bool _setStatus, uint8_t _dataSize, uint8_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - isMicro, isDelayed, isFirst, isLast, %(op_class)s), - src1(_src1), imm8(_imm8), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) + isMicro, isDelayed, isFirst, isLast, + _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + %(op_class)s) { buildMe(); } @@ -227,7 +309,7 @@ let {{ self.src1 = src1 self.src2 = src2 self.setStatus = False - self.dataSize = 1 + self.dataSize = "env.dataSize" self.ext = 0 def getAllocator(self, *microFlags): @@ -249,7 +331,7 @@ let {{ self.src1 = src1 self.imm8 = imm8 self.setStatus = False - self.dataSize = 1 + self.dataSize = "env.dataSize" self.ext = 0 def getAllocator(self, *microFlags): @@ -290,7 +372,7 @@ let {{ immCode = matcher.sub("imm8", code) # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'X86MicroopBase', {"code" : regCode}) + iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) header_output += MicroRegOpDeclare.subst(iop) decoder_output += MicroRegOpConstructor.subst(iop) exec_output += MicroRegOpExecute.subst(iop) @@ -305,7 +387,7 @@ let {{ # Build up the immediate version of this micro op iop = InstObjParams(name + "i", Name, - 'X86MicroopBase', {"code" : immCode}) + 'RegOpImm', {"code" : immCode}) header_output += MicroRegOpImmDeclare.subst(iop) decoder_output += MicroRegOpImmConstructor.subst(iop) exec_output += MicroRegOpImmExecute.subst(iop) diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh index 5a625f741..7aba6248a 100644 --- a/src/arch/x86/isa_traits.hh +++ b/src/arch/x86/isa_traits.hh @@ -81,8 +81,8 @@ namespace X86ISA // These enumerate all the registers for dependence tracking. enum DependenceTags { - //The number of microcode registers needs to be added to this - FP_Base_DepTag = 16, + //There are 16 microcode registers at the moment + FP_Base_DepTag = 32, Ctrl_Base_DepTag = FP_Base_DepTag + //mmx/x87 registers -- cgit v1.2.3 From 4ae284282ef87140ed6aad7bffb42420b10a2073 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 18 Jun 2007 14:15:47 +0000 Subject: Get rid of unnecessary output. --HG-- extra : convert_revision : 0df9a12788b8ce3225c113c095d5f13e49a7c544 --- src/arch/x86/isa/specialize.isa | 1 - 1 file changed, 1 deletion(-) diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index faf863351..bb2be47d9 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -148,7 +148,6 @@ let {{ (memName, memTypes, memEnv)) elif opType.tag in ("I", "J"): # Immediates - print "IMMEDIATE" Name += "_I" elif opType.tag == "M": # This needs to refer to memory, but we'll fill in the details -- cgit v1.2.3 From 2d08ab0cc26fc2b03a575f054508abc035786a08 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 18 Jun 2007 18:11:07 -0400 Subject: fix bug in timing cpu. getTime() is the time the requset was created, not the time it was repsonded to. In timing mode the time it was responded to is curTick. Doesn't change the results, but it does make implementation of nextCycle() more difficult --HG-- extra : convert_revision : 67ed6261a5451d17d96d5df45992590acc353afc --- src/cpu/simple/timing.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 1c79fcf6b..7698a588d 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -560,8 +560,7 @@ TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt) { if (pkt->isResponse()) { // delay processing of returned data until next CPU clock edge - Tick mem_time = pkt->req->getTime(); - Tick next_tick = cpu->nextCycle(mem_time); + Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeIfetch(pkt); @@ -655,8 +654,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { if (pkt->isResponse()) { // delay processing of returned data until next CPU clock edge - Tick mem_time = pkt->req->getTime(); - Tick next_tick = cpu->nextCycle(mem_time); + Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeDataAccess(pkt); -- cgit v1.2.3 From 1012fd442708f30b7db64d9ec3914a0b09a970b0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 14:14:17 +0000 Subject: Add a function to print out segment names. --HG-- extra : convert_revision : 8cbe3ca0d05165f7da5d6fa38c899ecc9e782511 --- src/arch/x86/isa/base.isa | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa index d9bd87f2d..eed969b47 100644 --- a/src/arch/x86/isa/base.isa +++ b/src/arch/x86/isa/base.isa @@ -182,6 +182,33 @@ output decoder {{ ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); } + void printSegment(std::ostream &os, int segment) + { + switch (segment) + { + case 0: + ccprintf(os, "ES"); + break; + case 1: + ccprintf(os, "CS"); + break; + case 2: + ccprintf(os, "SS"); + break; + case 3: + ccprintf(os, "DS"); + break; + case 4: + ccprintf(os, "FS"); + break; + case 5: + ccprintf(os, "GS"); + break; + default: + panic("Unrecognized segment %d\n", segment); + } + } + void X86StaticInst::printSrcReg(std::ostream &os, int reg) const { -- cgit v1.2.3 From 8caef7d25a6a150fa6369234bbdc8c14ef637df8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 14:15:21 +0000 Subject: Add a stack size bitfield and expose the mode component of the ExtMachInst. --HG-- extra : convert_revision : aad0ec51745fb94335898b0565bb11c1b399bbee --- src/arch/x86/isa/bitfields.isa | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index 82fa4f25b..8707bbb4c 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -100,3 +100,8 @@ def bitfield SIB_BASE sib.base; def bitfield OPSIZE opSize; def bitfield ADDRSIZE addrSize; +def bitfield STACKSIZE stackSize; + +def bitfield MODE mode; +def bitfield MODE_MODE mode.mode; +def bitfield MODE_SUBMODE mode.submode; -- cgit v1.2.3 From 6e286cddfaf6286f96e06c26266070f6fbbd7749 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 14:18:25 +0000 Subject: Get rid of the immediate and displacement components of the EmulEnv struct and use them directly out of the instruction. The extra copies are conceptually realistic but are just innefficient as implemented. Also don't use the zeroeth microcode register for general storage since it's now the zero register, and implement a load and a store microops. --HG-- extra : convert_revision : 0686296ca8b72940d961ecc6051063bfda1e932d --- src/arch/x86/isa/insts/data_transfer/move.py | 4 +- .../isa/insts/data_transfer/stack_operations.py | 10 +- src/arch/x86/isa/insts/logical.py | 16 +- src/arch/x86/isa/macroop.isa | 23 +- src/arch/x86/isa/microops/ldstop.isa | 317 ++++++++++++++++++++- src/arch/x86/isa/operands.isa | 8 +- src/arch/x86/isa_traits.hh | 2 +- src/arch/x86/types.hh | 12 +- src/arch/x86/utility.hh | 3 +- 9 files changed, 349 insertions(+), 46 deletions(-) diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index 9d23b24e8..ff4af0af4 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -67,11 +67,11 @@ def macroop MOV_R_M { }; def macroop MOV_R_I { - limm "env.reg", "env.immediate" + limm "env.reg", "IMMEDIATE" }; def macroop MOV_M_I { - limm "env.reg", "env.immediate" + limm "env.reg", "IMMEDIATE" #Do a store to put the register operand into memory }; ''' diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py index b7ec0ec66..50b690354 100644 --- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py @@ -55,15 +55,21 @@ microcode = ''' def macroop POP_R { + + # Make the default data size of pops 64 bits in 64 bit mode .adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;" - # There needs to be a load here to actually "pop" the data + + ld "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"] addi "INTREG_RSP", "INTREG_RSP", "env.dataSize" }; def macroop PUSH_R { + + # Make the default data size of pops 64 bits in 64 bit mode .adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;" + subi "INTREG_RSP", "INTREG_RSP", "env.dataSize" - # There needs to be a store here to actually "push" the data + st "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"] }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py index ec0ed97b2..824c75053 100644 --- a/src/arch/x86/isa/insts/logical.py +++ b/src/arch/x86/isa/insts/logical.py @@ -61,34 +61,34 @@ def macroop XOR_R_R def macroop XOR_R_I { - limm "NUM_INTREGS", "env.immediate" - xor "env.reg", "env.reg", "NUM_INTREGS" + limm "NUM_INTREGS+1", "IMMEDIATE" + xor "env.reg", "env.reg", "NUM_INTREGS+1" }; def macroop XOR_M_R { #Do a load to get one of the sources - xor "NUM_INTREGS", "NUM_INTREGS", "env.reg" + xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg" #Do a store to write the destination }; def macroop XOR_R_M { #Do a load to get one of the sources - xor "env.reg", "env.reg", "NUM_INTREGS" + xor "env.reg", "env.reg", "NUM_INTREGS+1" }; def macroop AND_R_I { - limm "NUM_INTREGS", "env.immediate" - and "env.reg", "env.reg", "NUM_INTREGS" + limm "NUM_INTREGS+1", "IMMEDIATE" + and "env.reg", "env.reg", "NUM_INTREGS+1" }; def macroop AND_M_I { #Do a load to get one of the sources - limm "NUM_INTREGS", "env.immediate" - and "NUM_INTREGS", "NUM_INTREGS", "NUM_INTREGS+1" + limm "NUM_INTREGS+1", "IMMEDIATE" + and "NUM_INTREGS+1", "NUM_INTREGS+1", "NUM_INTREGS+2" #Do a store to write the destination }; ''' diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 2d928d7c9..0cc818409 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -189,17 +189,18 @@ output header {{ { X86ISA::RegIndex reg; X86ISA::RegIndex regm; - uint64_t immediate; - uint64_t displacement; - int addressSize; + uint8_t scale; + X86ISA::RegIndex index; + X86ISA::RegIndex base; int dataSize; + int addressSize; + int stackSize; EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm, - uint64_t _immediate, uint64_t _displacement, - int _addressSize, int _dataSize) : + int _dataSize, int _addressSize, int _stackSize) : reg(_reg), regm(_regm), - immediate(_immediate), displacement(_displacement), - addressSize(_addressSize), dataSize(_dataSize) + dataSize(_dataSize), addressSize(_addressSize), + stackSize(_stackSize) {;} }; }}; @@ -211,17 +212,15 @@ let {{ self.regUsed = False self.regm = "0" self.regmUsed = False - self.immediate = "IMMEDIATE" - self.displacement = "DISPLACEMENT" self.addressSize = "ADDRSIZE" self.dataSize = "OPSIZE" + self.stackSize = "STACKSIZE" def getAllocator(self): return '''EmulEnv(%(reg)s, %(regm)s, - %(immediate)s, - %(displacement)s, + %(dataSize)s, %(addressSize)s, - %(dataSize)s)''' % \ + %(stackSize)s)''' % \ self.__dict__ def addReg(self, reg): if not self.regUsed: diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 7e164fa82..38b690e6a 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -59,8 +59,14 @@ // ////////////////////////////////////////////////////////////////////////// -def template MicroLdStOpDeclare {{ - class %(class_name)s : public X86MicroopBase + +// Load templates + +output header {{ + /** + * Base class for load and store ops + */ + class LdStOp : public X86MicroopBase { protected: const uint8_t scale; @@ -71,6 +77,195 @@ def template MicroLdStOpDeclare {{ const RegIndex data; const uint8_t dataSize; const uint8_t addressSize; + + //Constructor + LdStOp(ExtMachInst _machInst, + const char * mnem, const char * _instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint8_t _scale, RegIndex _index, RegIndex _base, + uint64_t _disp, uint8_t _segment, + RegIndex _data, + uint8_t _dataSize, uint8_t _addressSize, + OpClass __opClass) : + X86MicroopBase(machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, __opClass), + scale(_scale), index(_index), base(_base), + disp(_disp), segment(_segment), + data(_data), + dataSize(_dataSize), addressSize(_addressSize) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string LdStOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, data); + response << ", "; + printSegment(response, segment); + ccprintf(response, ":[%d*", scale); + printReg(response, index); + response << " + "; + printReg(response, base); + ccprintf(response, " + %#x]", disp); + return response.str(); + } +}}; + +def template MicroLoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); + + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template MicroLoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); + + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + + return fault; + } +}}; + +def template MicroLoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + + %(op_decl)s; + %(op_rd)s; + + Mem = pkt->get(); + %(code)s; + + if(fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +// Store templates + +def template MicroStoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s * xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); + + %(code)s; + + if(fault == NoFault) + { + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, + EA, 0, 0); + } + if(fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template MicroStoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); + + %(code)s; + + if(fault == NoFault) + { + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, + EA, 0, 0); + } + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +def template MicroStoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + return NoFault; + } +}}; + +// Common templates + +//This delcares the initiateAcc function in memory operations +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +//This declares the completeAcc function in memory operations +def template CompleteAccDeclare {{ + Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +def template MicroLdStOpDeclare {{ + class %(class_name)s : public %(base_class)s + { + protected: void buildMe(); public: @@ -90,6 +285,10 @@ def template MicroLdStOpDeclare {{ uint8_t _dataSize, uint8_t _addressSize); %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s }; }}; @@ -107,11 +306,10 @@ def template MicroLdStOpConstructor {{ RegIndex _data, uint8_t _dataSize, uint8_t _addressSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - false, false, false, false, %(op_class)s), - scale(_scale), index(_index), base(_base), - disp(_disp), segment(_segment), - data(_data), - dataSize(_dataSize), addressSize(_addressSize) + false, false, false, false, + _scale, _index, _base, + _disp, _segment, _data, + _dataSize, _addressSize, %(op_class)s) { buildMe(); } @@ -120,17 +318,106 @@ def template MicroLdStOpConstructor {{ ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, uint8_t _scale, RegIndex _index, RegIndex _base, - uint64_t _disp, uint8_t segment, - RegIndex data, - uint8_t dataSize, uint8_t addressSize) : + uint64_t _disp, uint8_t _segment, + RegIndex _data, + uint8_t _dataSize, uint8_t _addressSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, - isMicro, isDelayed, isFirst, isLast, %(op_class)s), - scale(_scale), index(_index), base(_base), - disp(_disp), segment(_segment), - data(_data), - dataSize(_dataSize), addressSize(_addressSize) + isMicro, isDelayed, isFirst, isLast, + _scale, _index, _base, + _disp, _segment, _data, + _dataSize, _addressSize, %(op_class)s) { buildMe(); } }}; +let {{ + class LdStOp(X86Microop): + def __init__(self, data, segment, addr, disp): + self.data = data + [self.scale, self.index, self.base] = addr + self.disp = disp + self.segment = segment + self.dataSize = "env.dataSize" + self.addressSize = "env.addressSize" + + def getAllocator(self, *microFlags): + allocator = '''new %(class_name)s(machInst, mnemonic + %(flags)s, %(scale)s, %(index)s, %(base)s, + %(disp)s, %(segment)s, %(data)s, + %(dataSize)s, %(addressSize)s)''' % { + "class_name" : self.className, + "flags" : self.microFlagsText(microFlags), + "scale" : self.scale, "index" : self.index, + "base" : self.base, + "disp" : self.disp, + "segment" : self.segment, "data" : self.data, + "dataSize" : self.dataSize, "addressSize" : self.addressSize} + return allocator +}}; + +let {{ + + # Make these empty strings so that concatenating onto + # them will always work. + header_output = "" + decoder_output = "" + exec_output = "" + + calculateEA = "EA = scale * Index + Base + disp;" + + def defineMicroLoadOp(mnemonic, code): + global header_output + global decoder_output + global exec_output + global microopClasses + Name = mnemonic + name = mnemonic.lower() + + # Build up the all register version of this micro op + iop = InstObjParams(name, Name, 'LdStOp', + {"code": code, "ea_code": calculateEA}) + header_output += MicroLdStOpDeclare.subst(iop) + decoder_output += MicroLdStOpConstructor.subst(iop) + exec_output += MicroLoadExecute.subst(iop) + exec_output += MicroLoadInitiateAcc.subst(iop) + exec_output += MicroLoadCompleteAcc.subst(iop) + + class LoadOp(LdStOp): + def __init__(self, data, segment, addr, disp = 0): + super(LoadOp, self).__init__(data, segment, addr, disp) + self.className = Name + self.mnemonic = name + + microopClasses[name] = LoadOp + + defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);') + + def defineMicroStoreOp(mnemonic, code): + global header_output + global decoder_output + global exec_output + global microopClasses + Name = mnemonic + name = mnemonic.lower() + + # Build up the all register version of this micro op + iop = InstObjParams(name, Name, 'LdStOp', + {"code": code, "ea_code": calculateEA}) + header_output += MicroLdStOpDeclare.subst(iop) + decoder_output += MicroLdStOpConstructor.subst(iop) + exec_output += MicroStoreExecute.subst(iop) + exec_output += MicroStoreInitiateAcc.subst(iop) + exec_output += MicroStoreCompleteAcc.subst(iop) + + class StoreOp(LdStOp): + def __init__(self, data, addr, segment): + super(LoadOp, self).__init__(data, addr, segment) + self.className = Name + self.mnemonic = name + + microopClasses[name] = StoreOp + + defineMicroLoadOp('St', 'Mem = Data;') +}}; + diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 1564c23e9..b2ac17d66 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -99,7 +99,9 @@ def operands {{ 'DestReg': ('IntReg', 'uqw', 'dest', 'IsInteger', 1), 'SrcReg1': ('IntReg', 'uqw', 'src1', 'IsInteger', 2), 'SrcReg2': ('IntReg', 'uqw', 'src2', 'IsInteger', 3), - 'IntRegOp0': ('IntReg', 'udw', 'param0', 'IsInteger', 1), - 'IntRegOp1': ('IntReg', 'udw', 'param1', 'IsInteger', 2), - 'IntRegOp2': ('IntReg', 'udw', 'param2', 'IsInteger', 2), + 'Base': ('IntReg', 'uqw', 'base', 'IsInteger', 4), + 'Index': ('IntReg', 'uqw', 'index', 'IsInteger', 5), + 'Data': ('IntReg', 'uqw', 'data', 'IsInteger', 6), + 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10), + 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) }}; diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh index 7aba6248a..4c02ee35e 100644 --- a/src/arch/x86/isa_traits.hh +++ b/src/arch/x86/isa_traits.hh @@ -93,7 +93,7 @@ namespace X86ISA // semantically meaningful register indices //There is no such register in X86 - const int ZeroReg = 0; + const int ZeroReg = NUM_INTREGS; const int StackPointerReg = INTREG_RSP; //X86 doesn't seem to have a link register const int ReturnAddressReg = 0; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index fc9f1d82b..298dff80b 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -169,6 +169,8 @@ namespace X86ISA uint8_t opSize; //The effective address size. uint8_t addrSize; + //The effective stack size. + uint8_t stackSize; //Mode information OperatingMode mode; @@ -193,8 +195,6 @@ namespace X86ISA inline static bool operator == (const ExtMachInst &emi1, const ExtMachInst &emi2) { - if(emi1.mode != emi2.mode) - return false; if(emi1.legacy != emi2.legacy) return false; if(emi1.rex != emi2.rex) @@ -215,6 +215,14 @@ namespace X86ISA return false; if(emi1.displacement != emi2.displacement) return false; + if(emi1.mode != emi2.mode) + return false; + if(emi1.opSize != emi2.opSize) + return false; + if(emi1.addrSize != emi2.addrSize) + return false; + if(emi1.stackSize != emi2.stackSize) + return false; return true; } diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index ed401a519..3f3f1cca3 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -79,7 +79,8 @@ namespace __hash_namespace { ((uint64_t)emi.opcode.prefixB << 8) | ((uint64_t)emi.opcode.op)) ^ emi.immediate ^ emi.displacement ^ - emi.mode ^ emi.opSize; + emi.mode ^ + emi.opSize ^ emi.addrSize ^ emi.stackSize; }; }; } -- cgit v1.2.3 From 056cfc345bffd0fa5450ed5ef886415a596cf9f9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 14:26:42 +0000 Subject: Get rid of the commented out versions of macroops which have been reimplemented. The comments are basically functioning like a todo list. --HG-- extra : convert_revision : cb07e3813f6cf882b4a5c77c498ffbca26adf586 --- src/arch/x86/isa/insts/data_transfer/stack_operations.py | 6 ------ src/arch/x86/isa/insts/logical.py | 8 -------- 2 files changed, 14 deletions(-) diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py index 50b690354..ad95fd468 100644 --- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py @@ -73,16 +73,10 @@ def macroop PUSH_R { }; ''' #let {{ -# class POP(Inst): -# "GenFault ${new UnimpInstFault}" -# class POPA(Inst): -# "GenFault ${new UnimpInstFault}" # class POPA(Inst): # "GenFault ${new UnimpInstFault}" # class POPAD(Inst): # "GenFault ${new UnimpInstFault}" -# class PUSH(Inst): -# "GenFault ${new UnimpInstFault}" # class PUSHA(Inst): # "GenFault ${new UnimpInstFault}" # class PUSHAD(Inst): diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py index 824c75053..0b7c41208 100644 --- a/src/arch/x86/isa/insts/logical.py +++ b/src/arch/x86/isa/insts/logical.py @@ -94,18 +94,10 @@ def macroop AND_M_I ''' #let {{ #microcodeString = ''' -# def macroop AND -# { -# And reg reg regm -# }; # def macroop OR # { # Or reg reg regm # }; -# def macroop XOR -# { -# Xor reg reg regm -# }; # def macroop NOT # { # Xor reg reg "0xFFFFFFFFFFFFFFFFULL" -- cgit v1.2.3 From ebe4d05f70e2cac823bdbbc1e2060ab507e3e80f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 14:50:35 +0000 Subject: Renovate the "fault" microop implementation. --HG-- extra : convert_revision : dc9d67dd5413f00f16d37cb2d0f8b0d10971e14a --- src/arch/x86/isa/microops/specop.isa | 64 +++++++++++++++++------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index 96fdf1c5e..b56223390 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -59,67 +59,63 @@ // ////////////////////////////////////////////////////////////////////////// -def template MicroFaultExecute {{ - Fault %(class_name)s ::execute(%(CPU_exec_context)s *xc, - Trace::InstRecord *traceData) const - { - //Return the fault we were constructed with - return fault; - } -}}; - -def template MicroFaultDeclare {{ - class %(class_name)s : public X86MicroopBase +output header {{ + class MicroFault : public X86MicroopBase { protected: Fault fault; void buildMe(); public: - %(class_name)s(ExtMachInst _machInst, - const char * instMnem, + MicroFault(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, Fault _fault); - %(class_name)s(ExtMachInst _machInst, - const char * instMnem, + MicroFault(ExtMachInst _machInst, const char * instMnem, Fault _fault); %(BasicExecDeclare)s }; }}; -def template MicroFaultConstructor {{ - - inline void %(class_name)s::buildMe() - { - %(constructor)s; - } +output decoder {{ + Fault MicroFault::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + //Return the fault we were constructed with + return fault; + } +}}; - inline %(class_name)s::%(class_name)s( +output decoder {{ + inline MicroFault::MicroFault( ExtMachInst machInst, const char * instMnem, Fault _fault) : - %(base_class)s(machInst, "%(mnemonic)s", instMnem, - false, false, false, false, %(op_class)s), fault(_fault) + X86MicroopBase(machInst, "fault", instMnem, + false, false, false, false, No_OpClass), fault(_fault) { - buildMe(); } - inline %(class_name)s::%(class_name)s( + inline MicroFault::MicroFault( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, Fault _fault) : - %(base_class)s(machInst, "%(mnemonic)s", instMnem, - isMicro, isDelayed, isFirst, isLast, %(op_class)s), + X86MicroopBase(machInst, "fault", instMnem, + isMicro, isDelayed, isFirst, isLast, No_OpClass), fault(_fault) { - buildMe(); } }}; let {{ - # This microop takes in a single parameter, a fault to return. - iop = InstObjParams("fault", "GenFault", 'X86MicroopBase', {"code" : ""}) - header_output += MicroFaultDeclare.subst(iop) - decoder_output += MicroFaultConstructor.subst(iop) - exec_output += MicroFaultExecute.subst(iop) + class Fault(X86Microop): + def __init__(self, fault): + self.fault = fault + + def getAllocator(self, *microFlags): + allocator = '''new MicroFault(machInst, mnemonic + %(flags)s, %(fault)s)''' % { + "flags" : self.microFlagsText(microFlags), + "fault" : self.fault} + return allocator + microopClasses["fault"] = Fault }}; -- cgit v1.2.3 From 4486762a8519783aaec7ebe6a391355cd30792e0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 17:53:10 +0000 Subject: Make an error message a little more descriptive. --HG-- extra : convert_revision : dbde025b1dcec0083e7276a9938bd21e7ab2887f --- src/arch/micro_asm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index a8a63e1f8..145029477 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -131,7 +131,8 @@ def handle_statement(parser, container, statement): microop = eval('parser.microops[statement.mnemonic](%s)' % statement.params) except: - print_error("Error creating microop object.") + print_error("Error creating microop object with mnemonic %s." % \ + statement.mnemonic) raise try: for label in statement.labels: -- cgit v1.2.3 From d49649279312fe8d05c27a91f94992d8d584c35b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 17:56:06 +0000 Subject: Make instructions that are illegal in 64 bit mode not do the wrong thing in 64 bit mode. Also add in more versions of PUSH and POP, and a version of near CALL. --HG-- extra : convert_revision : 7d8266cdfa54ac25610466b3533d3e9e5433297b --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 164 +++++++++++++++++------- src/arch/x86/isa/insts/control_transfer/call.py | 13 +- src/arch/x86/isa/microops/regop.isa | 70 ++++++++++ 3 files changed, 202 insertions(+), 45 deletions(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index b72b2b16a..78270e782 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -63,8 +63,14 @@ 0x00: decode OPCODE_OP_BOTTOM3 { 0x4: ADD(); 0x5: ADD(); - 0x6: push_ES(); - 0x7: pop_ES(); + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: push_ES(); + } + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: pop_ES(); + } default: ADD(); } 0x01: decode OPCODE_OP_BOTTOM3 { @@ -74,7 +80,10 @@ 0x3: or_Gv_Ev(); 0x4: or_Al_Ib(); 0x5: or_rAX_Iz(); - 0x6: push_CS(); + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: push_CS(); + } //Any time this is seen, it should generate a two byte opcode 0x7: M5InternalError::error( {{"Saw a one byte opcode whose value was 0x0F!"}}); @@ -86,8 +95,14 @@ 0x3: adc_Gv_Ev(); 0x4: adc_Al_Ib(); 0x5: adc_rAX_Iz(); - 0x6: push_SS(); - 0x7: pop_SS(); + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: push_SS(); + } + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: pop_SS(); + } } 0x03: decode OPCODE_OP_BOTTOM3 { 0x0: sbb_Eb_Gb(); @@ -96,8 +111,14 @@ 0x3: sbb_Gv_Ev(); 0x4: sbb_Al_Ib(); 0x5: sbb_rAX_Iz(); - 0x6: push_DS(); - 0x7: pop_DS(); + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: push_DS(); + } + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: pop_DS(); + } } 0x04: decode OPCODE_OP_BOTTOM3 { 0x0: and_Eb_Gb(); @@ -108,7 +129,10 @@ 0x5: and_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the ES segment override prefix!"}}); - 0x7: daa(); + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: daa(); + } } 0x05: decode OPCODE_OP_BOTTOM3 { 0x0: sub_Eb_Gb(); @@ -126,7 +150,10 @@ 0x5: Inst::XOR(rAx,Iz); 0x6: M5InternalError::error( {{"Tried to execute the SS segment override prefix!"}}); - 0x7: aaa(); + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: aaa(); + } default: MultiInst::XOR(OPCODE_OP_BOTTOM3, [Eb,Gb], [Ev,Gv], [Gb,Eb], [Gv,Ev]); @@ -140,7 +167,10 @@ 0x5: cmp_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the DS segment override prefix!"}}); - 0x7: aas(); + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: aas(); + } } 0x08: decode OPCODE_OP_BOTTOM3 { 0x0: inc_eAX(); @@ -162,30 +192,41 @@ 0x6: dec_eSI(); 0x7: dec_eDI(); } - 0x0A: decode OPCODE_OP_BOTTOM3 { - 0x0: Inst::PUSH(rAx); - 0x1: push_rCX(); - 0x2: push_rDX(); - 0x3: push_rBX(); - 0x4: Inst::PUSH(rSP); - 0x5: push_rBP(); - 0x6: push_rSI(); - 0x7: push_rDI(); - } - 0x0B: decode OPCODE_OP_BOTTOM3 { - 0x0: pop_rAX(); - 0x1: pop_rCX(); - 0x2: pop_rDX(); - 0x3: pop_rBX(); - 0x4: pop_rSP(); - 0x5: pop_rBP(); - 0x6: Inst::POP(rSI); - 0x7: pop_rDI(); + format Inst { + 0x0A: decode OPCODE_OP_BOTTOM3 { + 0x0: PUSH(rAx); + 0x1: PUSH(rCx); + 0x2: PUSH(rDx); + 0x3: PUSH(rBx); + 0x4: PUSH(rSP); + 0x5: PUSH(rBP); + 0x6: PUSH(rSI); + 0x7: PUSH(rDI); + } + 0x0B: decode OPCODE_OP_BOTTOM3 { + 0x0: POP(rAx); + 0x1: POP(rCx); + 0x2: POP(rDx); + 0x3: POP(rBx); + 0x4: POP(rSP); + 0x5: POP(rBP); + 0x6: POP(rSI); + 0x7: POP(rDI); + } } 0x0C: decode OPCODE_OP_BOTTOM3 { - 0x0: pusha(); - 0x1: popa(); - 0x2: bound_Gv_Ma(); + 0x0: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: pusha(); + } + 0x1: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: popa(); + } + 0x2: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: bound_Gv_Ma(); + } 0x3: arpl_Ew_Gw(); 0x4: M5InternalError::error( {{"Tried to execute the FS segment override prefix!"}}); @@ -229,7 +270,10 @@ 0x10: decode OPCODE_OP_BOTTOM3 { 0x0: group1_Eb_Ib(); 0x1: group1_Ev_Iz(); - 0x2: group1_Eb_Ib(); + 0x2: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: group1_Eb_Ib(); + } //0x3: group1_Ev_Ib(); 0x3: decode MODRM_REG { 0x0: add_Eb_Ib(); @@ -269,12 +313,23 @@ 0x13: decode OPCODE_OP_BOTTOM3 { 0x0: cbw_or_cwde_or_cdqe_rAX(); 0x1: cwd_or_cdq_or_cqo_rAX_rDX(); - 0x2: call_Ap(); + 0x2: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: call_Ap(); + } 0x3: fwait(); //aka wait 0x4: pushf_Fv(); 0x5: popf_Fv(); - 0x6: sahf(); - 0x7: lahf(); + //Both of these should be illegal only if CPUID.AHF64=0, + //according to sandpile.org + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: sahf(); + } + 0x7: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: lahf(); + } } 0x14: decode OPCODE_OP_BOTTOM3 { 0x0: mov_Al_Ob(); @@ -321,8 +376,14 @@ 0x1: group2_Ev_Ib(); 0x2: ret_near_Iw(); 0x3: ret_near(); - 0x4: les_Gz_Mp(); - 0x5: lds_Gz_Mp(); + 0x4: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: les_Gz_Mp(); + } + 0x5: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: lds_Gz_Mp(); + } //0x6: group12_Eb_Ib(); 0x6: decode MODRM_REG { 0x0: Inst::MOV(Eb,Ib); @@ -339,7 +400,10 @@ 0x3: ret_far(); 0x4: int3(); 0x5: int_Ib(); - 0x6: into(); + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: into(); + } 0x7: iret(); } 0x1A: decode OPCODE_OP_BOTTOM3 { @@ -347,9 +411,18 @@ 0x1: group2_Ev_1(); 0x2: group2_Eb_Cl(); 0x3: group2_Ev_Cl(); - 0x4: aam_Ib(); - 0x5: aad_Ib(); - 0x6: salc(); + 0x4: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: aam_Ib(); + } + 0x5: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: aad_Ib(); + } + 0x6: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: salc(); + } 0x7: xlat(); } 0x1B: decode OPCODE_OP_BOTTOM3 { @@ -373,9 +446,12 @@ 0x7: out_Ib_eAX(); } 0x1D: decode OPCODE_OP_BOTTOM3 { - 0x0: call_Jz(); + 0x0: Inst::CALL(Jz); 0x1: jmp_Jz(); - 0x2: jmp_Ap(); + 0x2: decode MODE_SUBMODE { + 0x0: This_should_be_an_illegal_instruction(); + default: jmp_Ap(); + } 0x3: jmp_Jb(); 0x4: in_Al_Dx(); 0x5: in_eAX_Dx(); diff --git a/src/arch/x86/isa/insts/control_transfer/call.py b/src/arch/x86/isa/insts/control_transfer/call.py index 231db6e40..5cd8a6359 100644 --- a/src/arch/x86/isa/insts/control_transfer/call.py +++ b/src/arch/x86/isa/insts/control_transfer/call.py @@ -53,7 +53,18 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop CALL_I +{ + .adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;" + + limm "NUM_INTREGS+2", "IMMEDIATE" + rdip "NUM_INTREGS+1" + subi "INTREG_RSP", "INTREG_RSP", "env.dataSize" + st "NUM_INTREGS+1", 2, [0, "NUM_INTREGS", "INTREG_RSP"] + wrip "NUM_INTREGS+1", "NUM_INTREGS+2" +}; +''' #let {{ # class CALL(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index d5fb25cb5..6f86892c3 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -410,4 +410,74 @@ let {{ defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)') + # This has it's own function because Wr ops have implicit destinations + def defineMicroRegOpWr(mnemonic, code): + global header_output + global decoder_output + global exec_output + global microopClasses + Name = mnemonic + name = mnemonic.lower() + + # Find op2 in each of the instruction definitions. Create two versions + # of the code, one with an integer operand, and one with an immediate + # operand. + matcher = re.compile("op2(?P\\.\\w+)?") + regCode = matcher.sub("SrcReg2", code) + immCode = matcher.sub("imm8", code) + + # Build up the all register version of this micro op + iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) + header_output += MicroRegOpDeclare.subst(iop) + decoder_output += MicroRegOpConstructor.subst(iop) + exec_output += MicroRegOpExecute.subst(iop) + + class RegOpChild(RegOp): + def __init__(self, src1, src2): + super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2) + self.className = Name + self.mnemonic = name + + microopClasses[name] = RegOpChild + + # Build up the immediate version of this micro op + iop = InstObjParams(name + "i", Name, + 'RegOpImm', {"code" : immCode}) + header_output += MicroRegOpImmDeclare.subst(iop) + decoder_output += MicroRegOpImmConstructor.subst(iop) + exec_output += MicroRegOpImmExecute.subst(iop) + + class RegOpImmChild(RegOpImm): + def __init__(self, src1, imm): + super(RegOpImmChild, self).__init__("NUM_INTREGS", src1, imm) + self.className = Name + "Imm" + self.mnemonic = name + "i" + + microopClasses[name + "i"] = RegOpImmChild + + defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') + + # This has it's own function because Rd ops don't always have two parameters + def defineMicroRegOpRd(mnemonic, code): + global header_output + global decoder_output + global exec_output + global microopClasses + Name = mnemonic + name = mnemonic.lower() + + iop = InstObjParams(name, Name, 'RegOp', {"code" : code}) + header_output += MicroRegOpDeclare.subst(iop) + decoder_output += MicroRegOpConstructor.subst(iop) + exec_output += MicroRegOpExecute.subst(iop) + + class RegOpChild(RegOp): + def __init__(self, dest, src1 = "NUM_INTREGS"): + super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS") + self.className = Name + self.mnemonic = name + + microopClasses[name] = RegOpChild + + defineMicroRegOpRd('Rdip', 'DestReg = RIP') }}; -- cgit v1.2.3 From ea70e6d6daee29e7a4780d4b48f8140220ee2576 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 18:17:34 +0000 Subject: Make branches work by repopulating the predecoder every time through. This is probably fine as far as the predecoder goes, but the simple cpu might want to not refetch something it already has. That reintroduces the self modifying code problem though. --HG-- extra : convert_revision : 802197e65f8dc1ad657c6b346091e03cb563b0c0 --- src/arch/alpha/predecoder.hh | 6 +----- src/arch/mips/predecoder.hh | 3 +-- src/arch/sparc/predecoder.hh | 4 +--- src/arch/x86/predecoder.hh | 6 +++--- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/simple/atomic.cc | 6 +++--- src/cpu/simple/base.cc | 10 +++++----- 7 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh index 0407ce99b..4887de856 100644 --- a/src/arch/alpha/predecoder.hh +++ b/src/arch/alpha/predecoder.hh @@ -44,8 +44,6 @@ namespace AlphaISA { protected: ThreadContext * tc; - //The pc of the current instruction - Addr fetchPC; //The extended machine instruction being generated ExtMachInst ext_inst; @@ -69,10 +67,8 @@ namespace AlphaISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr _fetchPC, Addr off, MachInst inst) + void moreBytes(Addr pc, Addr fetchPC, MachInst inst) { - fetchPC = _fetchPC; - assert(off == 0); ext_inst = inst; #if FULL_SYSTEM if (pc && 0x1) diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh index 90f768d73..e310dded4 100644 --- a/src/arch/mips/predecoder.hh +++ b/src/arch/mips/predecoder.hh @@ -66,9 +66,8 @@ namespace MipsISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst inst) + void moreBytes(Addr pc, Addr fetchPC, MachInst inst) { - assert(off == 0); emi = inst; } diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh index 38d8fd1a2..d990c3256 100644 --- a/src/arch/sparc/predecoder.hh +++ b/src/arch/sparc/predecoder.hh @@ -67,10 +67,8 @@ namespace SparcISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst inst) + void moreBytes(Addr pc, Addr fetchPC, MachInst inst) { - assert(off == 0); - emi = inst; //The I bit, bit 13, is used to figure out where the ASI //should come from. Use that in the ExtMachInst. This is diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index 3c858f061..f34b66364 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -195,12 +195,12 @@ namespace X86ISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, Addr off, MachInst data) + void moreBytes(Addr pc, Addr fetchPC, MachInst data) { + DPRINTF(Predecoder, "Getting more bytes.\n"); basePC = fetchPC; - offset = off; + offset = (fetchPC >= pc) ? 0 : pc - fetchPC; fetchChunk = data; - assert(off < sizeof(MachInst)); outOfBytes = false; process(); } diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index ab55ec744..1ce5bd20f 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1128,7 +1128,7 @@ DefaultFetch::fetch(bool &status_change) (&cacheData[tid][offset])); predecoder.setTC(cpu->thread[tid]->getTC()); - predecoder.moreBytes(fetch_PC, fetch_PC, 0, inst); + predecoder.moreBytes(fetch_PC, fetch_PC, inst); ext_inst = predecoder.getExtMachInst(); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index ea1c7d87f..03ff1282b 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -521,15 +521,15 @@ AtomicSimpleCPU::tick() dcache_access = false; // assume no dcache access //Fetch more instruction memory if necessary - if(predecoder.needMoreBytes()) - { + //if(predecoder.needMoreBytes()) + //{ icache_access = true; ifetch_pkt->reinitFromRequest(); icache_latency = icachePort.sendAtomic(ifetch_pkt); // ifetch_req is initialized to read the instruction directly // into the CPU object's inst field. - } + //} preExecute(); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b7f60522f..9285aa7b5 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -379,11 +379,11 @@ BaseSimpleCPU::preExecute() //This should go away once the constructor can be set up properly predecoder.setTC(thread->getTC()); //If more fetch data is needed, pass it in. - if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), - (thread->readPC() & PCMask) + fetchOffset, 0, inst); - else - predecoder.process(); + Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; + //if(predecoder.needMoreBytes()) + predecoder.moreBytes(thread->readPC(), fetchPC, inst); + //else + // predecoder.process(); //If an instruction is ready, decode it. Otherwise, we'll have to //fetch beyond the MachInst at the current pc. -- cgit v1.2.3 From cc796de96201754b3e3a38996090ed633307aa8c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 19:01:02 +0000 Subject: Missed an "offset" to get rid of. --HG-- extra : convert_revision : 7542f130b269a6a09e6ed51ae4689d1faa45a155 --- src/cpu/exetrace.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 9b87f2e8a..85df19348 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -650,7 +650,7 @@ Trace::InstRecord::dump() << endl; predecoder.setTC(thread); - predecoder.moreBytes(m5Pc, m5Pc, 0, + predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction); assert(predecoder.extMachInstReady()); -- cgit v1.2.3 From d2ccf5e50917701a4eab9f1848c8d524ccf0c7cc Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Jun 2007 22:40:10 +0000 Subject: More faithfulness to what instructions should work in what modes, and added the MOVSXD instruction. --HG-- extra : convert_revision : 38b9bf6cd4bdec6355b1158967c7d3562715cacd --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 51 +++++++++------ src/arch/x86/isa/insts/data_transfer/move.py | 9 +++ src/arch/x86/isa/microops/regop.isa | 94 ++++++++++++--------------- 3 files changed, 83 insertions(+), 71 deletions(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 78270e782..c3f95137a 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -172,25 +172,33 @@ default: aas(); } } - 0x08: decode OPCODE_OP_BOTTOM3 { - 0x0: inc_eAX(); - 0x1: inc_eCX(); - 0x2: inc_eDX(); - 0x3: inc_eBX(); - 0x4: inc_eSP(); - 0x5: inc_eBP(); - 0x6: inc_eSI(); - 0x7: inc_eDI(); + 0x08: decode MODE_SUBMODE { + 0x0: M5InternalError::error ( + {{"Tried to execute an REX prefix!"}}); + default: decode OPCODE_OP_BOTTOM3 { + 0x0: inc_eAX(); + 0x1: inc_eCX(); + 0x2: inc_eDX(); + 0x3: inc_eBX(); + 0x4: inc_eSP(); + 0x5: inc_eBP(); + 0x6: inc_eSI(); + 0x7: inc_eDI(); + } } - 0x09: decode OPCODE_OP_BOTTOM3 { - 0x0: dec_eAX(); - 0x1: dec_eCX(); - 0x2: dec_eDX(); - 0x3: dec_eBX(); - 0x4: dec_eSP(); - 0x5: dec_eBP(); - 0x6: dec_eSI(); - 0x7: dec_eDI(); + 0x09: decode MODE_SUBMODE { + 0x0: M5InternalError::error ( + {{"Tried to execute an REX prefix!"}}); + default: decode OPCODE_OP_BOTTOM3 { + 0x0: dec_eAX(); + 0x1: dec_eCX(); + 0x2: dec_eDX(); + 0x3: dec_eBX(); + 0x4: dec_eSP(); + 0x5: dec_eBP(); + 0x6: dec_eSI(); + 0x7: dec_eDI(); + } } format Inst { 0x0A: decode OPCODE_OP_BOTTOM3 { @@ -227,7 +235,10 @@ 0x0: This_should_be_an_illegal_instruction(); default: bound_Gv_Ma(); } - 0x3: arpl_Ew_Gw(); + 0x3: decode MODE_SUBMODE { + 0x0: Inst::MOVSXD(Gv,Ed); + default: arpl_Ew_Gw(); + } 0x4: M5InternalError::error( {{"Tried to execute the FS segment override prefix!"}}); 0x5: M5InternalError::error( @@ -301,7 +312,7 @@ 0x7: group10_Ev(); //Make sure this is Ev } 0x12: decode OPCODE_OP_BOTTOM3 { - 0x0: nop_or_pause(); //Check for repe prefix + default: nop_or_pause(); //Check for repe prefix 0x1: xchg_rCX_rAX(); 0x2: xchg_rDX_rAX(); 0x3: xchg_rVX_rAX(); diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index ff4af0af4..1464e6379 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -74,6 +74,15 @@ def macroop MOV_M_I { limm "env.reg", "IMMEDIATE" #Do a store to put the register operand into memory }; + +def macroop MOVSXD_R_R { + sext "env.reg", "env.regm", "env.dataSize" +}; + +def macroop MOVSXD_R_M { + #Do a load to fill the register operand from memory + sext "env.reg", "env.regm", "env.dataSize" +}; ''' #let {{ # class MOV(Inst): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 6f86892c3..7c5b6df01 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -356,11 +356,20 @@ let {{ decoder_output = "" exec_output = "" - def defineMicroRegOp(mnemonic, code): + def setUpMicroRegOp(name, Name, base, code, child): global header_output global decoder_output global exec_output global microopClasses + + iop = InstObjParams(name, Name, base, {"code" : code}) + header_output += MicroRegOpDeclare.subst(iop) + decoder_output += MicroRegOpConstructor.subst(iop) + exec_output += MicroRegOpExecute.subst(iop) + + microopClasses[name] = child + + def defineMicroRegOp(mnemonic, code): Name = mnemonic name = mnemonic.lower() @@ -371,34 +380,23 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) - header_output += MicroRegOpDeclare.subst(iop) - decoder_output += MicroRegOpConstructor.subst(iop) - exec_output += MicroRegOpExecute.subst(iop) - + # Build the all register version of this micro op class RegOpChild(RegOp): def __init__(self, dest, src1, src2): super(RegOpChild, self).__init__(dest, src1, src2) self.className = Name self.mnemonic = name - microopClasses[name] = RegOpChild - - # Build up the immediate version of this micro op - iop = InstObjParams(name + "i", Name, - 'RegOpImm', {"code" : immCode}) - header_output += MicroRegOpImmDeclare.subst(iop) - decoder_output += MicroRegOpImmConstructor.subst(iop) - exec_output += MicroRegOpImmExecute.subst(iop) + setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild); - class RegOpImmChild(RegOpImm): - def __init__(self, dest, src1, imm): - super(RegOpImmChild, self).__init__(dest, src1, imm) + # Build the immediate version of this micro op + class RegOpChildImm(RegOpImm): + def __init__(self, dest, src1, src2): + super(RegOpChildImm, self).__init__(dest, src1, src2) self.className = Name + "Imm" self.mnemonic = name + "i" - microopClasses[name + "i"] = RegOpImmChild + setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm); defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') @@ -412,10 +410,6 @@ let {{ # This has it's own function because Wr ops have implicit destinations def defineMicroRegOpWr(mnemonic, code): - global header_output - global decoder_output - global exec_output - global microopClasses Name = mnemonic name = mnemonic.lower() @@ -426,58 +420,56 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) - header_output += MicroRegOpDeclare.subst(iop) - decoder_output += MicroRegOpConstructor.subst(iop) - exec_output += MicroRegOpExecute.subst(iop) - + # Build the all register version of this micro op class RegOpChild(RegOp): def __init__(self, src1, src2): super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2) self.className = Name self.mnemonic = name - microopClasses[name] = RegOpChild - - # Build up the immediate version of this micro op - iop = InstObjParams(name + "i", Name, - 'RegOpImm', {"code" : immCode}) - header_output += MicroRegOpImmDeclare.subst(iop) - decoder_output += MicroRegOpImmConstructor.subst(iop) - exec_output += MicroRegOpImmExecute.subst(iop) + setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild); - class RegOpImmChild(RegOpImm): - def __init__(self, src1, imm): - super(RegOpImmChild, self).__init__("NUM_INTREGS", src1, imm) + # Build the immediate version of this micro op + class RegOpChildImm(RegOpImm): + def __init__(self, src1, src2): + super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2) self.className = Name + "Imm" self.mnemonic = name + "i" - microopClasses[name + "i"] = RegOpImmChild + setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm); defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') # This has it's own function because Rd ops don't always have two parameters def defineMicroRegOpRd(mnemonic, code): - global header_output - global decoder_output - global exec_output - global microopClasses Name = mnemonic name = mnemonic.lower() - iop = InstObjParams(name, Name, 'RegOp', {"code" : code}) - header_output += MicroRegOpDeclare.subst(iop) - decoder_output += MicroRegOpConstructor.subst(iop) - exec_output += MicroRegOpExecute.subst(iop) - class RegOpChild(RegOp): def __init__(self, dest, src1 = "NUM_INTREGS"): super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS") self.className = Name self.mnemonic = name - microopClasses[name] = RegOpChild + setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild); defineMicroRegOpRd('Rdip', 'DestReg = RIP') + + def defineMicroRegOpImm(mnemonic, code): + Name = mnemonic + name = mnemonic.lower() + + class RegOpChild(RegOpImm): + def __init__(self, dest, src1, src2): + super(RegOpChild, self).__init__(dest, src1, src2) + self.className = Name + self.mnemonic = name + + setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild); + + defineMicroRegOpImm('Sext', ''' + IntReg val = SrcReg1; + int sign_bit = bits(val, imm8-1, imm8-1); + val = sign_bit ? (val | ~mask(imm8)) : val; + DestReg = merge(DestReg, val, dataSize);''') }}; -- cgit v1.2.3 From a68ddf685c739220d09fdc44000dd217d0707f8e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 15:02:50 +0000 Subject: Make memory instructions work better, add more macroop implementations, add an lea microop, move EmulEnv into it's own .cc and .hh. --HG-- extra : convert_revision : 1212b8463eab1c1dcba7182c487d1e9184cf9bea --- src/arch/x86/SConscript | 1 + src/arch/x86/isa/decoder/one_byte_opcodes.isa | 42 ++++++++----- src/arch/x86/isa/includes.isa | 1 + .../x86/isa/insts/arithmetic/add_and_subtract.py | 14 ++++- src/arch/x86/isa/insts/compare_and_test/test.py | 32 ++++++++-- src/arch/x86/isa/insts/data_transfer/move.py | 4 +- src/arch/x86/isa/insts/load_effective_address.py | 10 +-- src/arch/x86/isa/macroop.isa | 47 ++++++-------- src/arch/x86/isa/microops/ldstop.isa | 73 ++++++++++++++++++++-- src/arch/x86/isa/specialize.isa | 39 +++++------- src/arch/x86/predecoder.cc | 17 +++-- src/arch/x86/types.hh | 2 +- 12 files changed, 186 insertions(+), 96 deletions(-) diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 2e2c5b006..6de243c9c 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -85,6 +85,7 @@ Import('*') if env['TARGET_ISA'] == 'x86': + Source('emulenv.cc') Source('floatregfile.cc') Source('intregfile.cc') Source('miscregfile.cc') diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index c3f95137a..3b4e72347 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -280,7 +280,17 @@ } 0x10: decode OPCODE_OP_BOTTOM3 { 0x0: group1_Eb_Ib(); - 0x1: group1_Ev_Iz(); + //0x1: group1_Ev_Iz(); + 0x1: decode MODRM_REG { + 0x0: add_Ev_Iz(); + 0x1: or_Ev_Ibz(); + 0x2: adc_Ev_Iz(); + 0x3: sbb_Ev_Iz(); + 0x4: Inst::AND(Ev,Iz); + 0x5: Inst::SUB(Ev,Iz); + 0x6: xor_Ev_Iz(); + 0x7: cmp_Ev_Iz(); + } 0x2: decode MODE_SUBMODE { 0x0: This_should_be_an_illegal_instruction(); default: group1_Eb_Ib(); @@ -296,8 +306,8 @@ 0x6: xor_Eb_Ib(); 0x7: cmp_Eb_Ib(); } - 0x4: test_Eb_Gb(); - 0x5: test_Ev_Gv(); + 0x4: Inst::TEST(Eb,Gb); + 0x5: Inst::TEST(Ev,Gv); 0x6: xchg_Eb_Gb(); 0x7: xchg_Ev_Gv(); } @@ -307,7 +317,7 @@ 0x2: Inst::MOV(Gb,Eb); 0x3: Inst::MOV(Gv,Eb); 0x4: mov_MwRv_Sw(); //What to do with this one? - 0x5: lea_Gv_M(); + 0x5: Inst::LEA(Gv,M); 0x6: mov_Sw_MwRv(); 0x7: group10_Ev(); //Make sure this is Ev } @@ -353,8 +363,8 @@ 0x7: cmps_Yv_Xv(); } 0x15: decode OPCODE_OP_BOTTOM3 { - 0x0: test_Al_Ib(); - 0x1: test_rAX_Iz(); + 0x0: Inst::TEST(rAl,Ib); + 0x1: Inst::TEST(rAX,Iz); 0x2: stos_Yb_Al(); 0x3: stos_Yv_rAX(); 0x4: lods_Al_Xb(); @@ -372,15 +382,17 @@ 0x6: mov_Dh_Ib(); 0x7: mov_Bh_Ib(); } - 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: mov_rAX_Iv(); - 0x1: mov_rCX_Iv(); - 0x2: mov_rDX_Iv(); - 0x3: mov_rBX_Iv(); - 0x4: mov_rSP_Iv(); - 0x5: mov_rBP_Iv(); - 0x6: mov_rSI_Iv(); - 0x7: mov_rDI_Iv(); + format Inst { + 0x17: decode OPCODE_OP_BOTTOM3 { + 0x0: MOV(rAX,Iv); + 0x1: MOV(rCX,Iv); + 0x2: MOV(rDX,Iv); + 0x3: MOV(rBX,Iv); + 0x4: MOV(rSP,Iv); + 0x5: MOV(rBP,Iv); + 0x6: MOV(rSI,Iv); + 0x7: MOV(rDI,Iv); + } } 0x18: decode OPCODE_OP_BOTTOM3 { 0x0: group2_Eb_Ib(); diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 8bb282150..14406931b 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -96,6 +96,7 @@ output header {{ #include #include +#include "arch/x86/emulenv.hh" #include "arch/x86/faults.hh" #include "arch/x86/isa_traits.hh" #include "arch/x86/regfile.hh" diff --git a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py index 283152f30..349c2bb46 100644 --- a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py +++ b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py @@ -53,7 +53,19 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop SUB_R_I +{ + subi "env.reg", "env.reg", "IMMEDIATE" +}; + +def macroop SUB_M_I +{ + #Load into t1 + subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE" + #save from t1 +}; +''' #let {{ # class ADC(Inst): # "Adc ^0 ^0 ^1" diff --git a/src/arch/x86/isa/insts/compare_and_test/test.py b/src/arch/x86/isa/insts/compare_and_test/test.py index b4d1cf9b8..36abab5d1 100644 --- a/src/arch/x86/isa/insts/compare_and_test/test.py +++ b/src/arch/x86/isa/insts/compare_and_test/test.py @@ -53,8 +53,30 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class TEST(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop TEST_M_R +{ + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg" +}; + +def macroop TEST_R_R +{ + and "NUM_INTREGS", "env.reg", "env.regm" +}; + +def macroop TEST_M_I +{ + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + limm "NUM_INTREGS+2", "IMMEDIATE" + and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2" +}; + +def macroop TEST_R_I +{ + limm "NUM_INTREGS+1", "IMMEDIATE" + and "NUM_INTREGS", "env.reg", "NUM_INTREGS+1" +}; +''' diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index 1464e6379..c674329ea 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -59,11 +59,11 @@ def macroop MOV_R_R { }; def macroop MOV_M_R { - #Do a store to put the register operand into memory + st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" }; def macroop MOV_R_M { - #Do a load to fill the register operand from memory + ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" }; def macroop MOV_R_I { diff --git a/src/arch/x86/isa/insts/load_effective_address.py b/src/arch/x86/isa/insts/load_effective_address.py index dab6960b1..ac32638a0 100644 --- a/src/arch/x86/isa/insts/load_effective_address.py +++ b/src/arch/x86/isa/insts/load_effective_address.py @@ -53,8 +53,8 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class LEA(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop LEA_R_M { + lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" +}; +''' diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 0cc818409..8453a4fe9 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -111,6 +111,12 @@ output header {{ }; }}; +////////////////////////////////////////////////////////////////////////////// +// +// X86 specific +// +////////////////////////////////////////////////////////////////////////////// + // Basic instruction class declaration template. def template MacroDeclare {{ namespace X86Macroop @@ -122,17 +128,19 @@ def template MacroDeclare {{ { public: // Constructor. - %(class_name)s(ExtMachInst machInst, EmulEnv env); + %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env); }; }; }}; // Basic instruction class constructor template. def template MacroConstructor {{ - inline X86Macroop::%(class_name)s::%(class_name)s(ExtMachInst machInst, EmulEnv env) + inline X86Macroop::%(class_name)s::%(class_name)s( + ExtMachInst machInst, EmulEnv env) : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s) { %(adjust_env)s; + %(do_modrm)s; %(constructor)s; //alloc_microops is the code that sets up the microops //array in the parent class. @@ -140,11 +148,6 @@ def template MacroConstructor {{ } }}; -////////////////////////////////////////////////////////////////////////////// -// -// X86 specific -// - let {{ from micro_asm import Combinational_Macroop, Rom_Macroop class X86Macroop(Combinational_Macroop): @@ -157,6 +160,7 @@ let {{ } self.declared = False self.adjust_env = "" + self.doModRM = "" def getAllocator(self, env): return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator()) def getDeclaration(self): @@ -180,31 +184,11 @@ let {{ iop = InstObjParams(self.name, self.name, "Macroop", {"code" : "", "num_microops" : numMicroops, "alloc_microops" : allocMicroops, - "adjust_env" : self.adjust_env}) + "adjust_env" : self.adjust_env, + "do_modrm" : self.doModRM}) return MacroConstructor.subst(iop); }}; -output header {{ - struct EmulEnv - { - X86ISA::RegIndex reg; - X86ISA::RegIndex regm; - uint8_t scale; - X86ISA::RegIndex index; - X86ISA::RegIndex base; - int dataSize; - int addressSize; - int stackSize; - - EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm, - int _dataSize, int _addressSize, int _stackSize) : - reg(_reg), regm(_regm), - dataSize(_dataSize), addressSize(_addressSize), - stackSize(_stackSize) - {;} - }; -}}; - let {{ class EmulEnv(object): def __init__(self): @@ -215,6 +199,8 @@ let {{ self.addressSize = "ADDRSIZE" self.dataSize = "OPSIZE" self.stackSize = "STACKSIZE" + self.doModRM = False + def getAllocator(self): return '''EmulEnv(%(reg)s, %(regm)s, @@ -234,12 +220,15 @@ let {{ }}; let {{ + doModRMString = "env.doModRM(machInst);\n" def genMacroop(Name, env): blocks = OutputBlocks() if not macroopDict.has_key(Name): raise Exception, "Unrecognized instruction: %s" % Name macroop = macroopDict[Name] if not macroop.declared: + if env.doModRM: + macroop.doModRM = doModRMString blocks.header_output = macroop.getDeclaration() blocks.decoder_output = macroop.getDefinition() macroop.declared = True diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 38b690e6a..fbff899a0 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -59,9 +59,6 @@ // ////////////////////////////////////////////////////////////////////////// - -// Load templates - output header {{ /** * Base class for load and store ops @@ -119,6 +116,58 @@ output decoder {{ } }}; +// LEA template + +def template MicroLeaExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); + + %(code)s; + if(fault == NoFault) + { + %(op_wb)s; + } + + return fault; + } +}}; + +def template MicroLeaDeclare {{ + class %(class_name)s : public %(base_class)s + { + protected: + void buildMe(); + + public: + %(class_name)s(ExtMachInst _machInst, + const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint8_t _scale, RegIndex _index, RegIndex _base, + uint64_t _disp, uint8_t _segment, + RegIndex _data, + uint8_t _dataSize, uint8_t _addressSize); + + %(class_name)s(ExtMachInst _machInst, + const char * instMnem, + uint8_t _scale, RegIndex _index, RegIndex _base, + uint64_t _disp, uint8_t _segment, + RegIndex _data, + uint8_t _dataSize, uint8_t _addressSize); + + %(BasicExecDeclare)s + }; +}}; + +// Load templates + def template MicroLoadExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -411,13 +460,27 @@ let {{ exec_output += MicroStoreCompleteAcc.subst(iop) class StoreOp(LdStOp): - def __init__(self, data, addr, segment): - super(LoadOp, self).__init__(data, addr, segment) + def __init__(self, data, segment, addr, disp = 0): + super(LoadOp, self).__init__(data, segment, addr, disp) self.className = Name self.mnemonic = name microopClasses[name] = StoreOp defineMicroLoadOp('St', 'Mem = Data;') + + iop = InstObjParams("lea", "Lea", 'LdStOp', + {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA}) + header_output += MicroLeaDeclare.subst(iop) + decoder_output += MicroLdStOpConstructor.subst(iop) + exec_output += MicroLeaExecute.subst(iop) + + class LeaOp(LdStOp): + def __init__(self, data, segment, addr, disp = 0): + super(LeaOp, self).__init__(data, segment, addr, disp) + self.className = "Lea" + self.mnemonic = "lea" + + microopClasses["lea"] = LeaOp }}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index bb2be47d9..10e57ba18 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -85,7 +85,7 @@ let {{ let {{ class OpType(object): - parser = re.compile(r"(?P[A-Z][A-Z]*)(?P[a-z][a-z]*)|(r(?P[A-Z0-9]*)(?P[a-z]*))") + parser = re.compile(r"(?P[A-Z]+)(?P[a-z]*)|(r(?P[A-Z0-9]+)(?P[a-z]*))") def __init__(self, opTypeString): match = OpType.parser.search(opTypeString) if match == None: @@ -105,14 +105,15 @@ let {{ while len(opTypes): # Parse the operand type string we're working with opType = OpType(opTypes[0]) + opTypes.pop(0) if opType.reg: #Figure out what to do with fixed register operands #This is the index to use, so we should stick it some place. if opType.reg in ("A", "B", "C", "D"): - env.addReg("INTREG_R%sX" % opType.reg) + env.addReg("INTREG_R%sX | (REX_B << 3)" % opType.reg) else: - env.addReg("INTREG_R%s" % opType.reg) + env.addReg("INTREG_R%s | (REX_B << 3)" % opType.reg) if opType.size: if opType.rsize in ("l", "h", "b"): print "byte" @@ -121,6 +122,11 @@ let {{ else: print "Didn't recognize fixed register size %s!" % opType.rsize Name += "_R" + elif opType.tag == "M": + # This refers to memory. The macroop constructor sets up modrm + # addressing. Non memory modrm settings should cause an error. + Name += "_M" + env.doModRM = True elif opType.tag == None or opType.size == None: raise Exception, "Problem parsing operand tag: %s" % opType.tag elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"): @@ -130,39 +136,24 @@ let {{ elif opType.tag in ("E", "Q", "W"): # This might refer to memory or to a register. We need to # divide it up farther. - regTypes = copy.copy(opTypes) - regTypes.pop(0) regEnv = copy.copy(env) regEnv.addReg(ModRMRMIndex) - regName = Name + "_R" - # This needs to refer to memory, but we'll fill in the details - # later. It needs to take into account unaligned memory - # addresses. - memTypes = copy.copy(opTypes) - memTypes.pop(0) + # This refers to memory. The macroop constructor should set up + # modrm addressing. memEnv = copy.copy(env) - memName = Name + "_M" - print "%0" + memEnv.doModRM = True return doSplitDecode(specializeInst, "MODRM_MOD", - {"3" : (regName, regTypes, regEnv)}, - (memName, memTypes, memEnv)) + {"3" : (Name + "_R", copy.copy(opTypes), regEnv)}, + (Name + "_M", copy.copy(opTypes), memEnv)) elif opType.tag in ("I", "J"): # Immediates Name += "_I" - elif opType.tag == "M": - # This needs to refer to memory, but we'll fill in the details - # later. It needs to take into account unaligned memory - # addresses. - print "%0" - Name += "_M" elif opType.tag in ("PR", "R", "VR"): - # There should probably be a check here to verify that mod - # is equal to 11b + # Non register modrm settings should cause an error env.addReg(ModRMRMIndex) Name += "_R" else: raise Exception, "Unrecognized tag %s." % opType.tag - opTypes.pop(0) # Generate code to return a macroop of the given name which will # operate in the "emulation environment" env diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 3ed18aeb2..bbbad7dd0 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -264,31 +264,29 @@ namespace X86ISA Predecoder::State Predecoder::doModRMState(uint8_t nextByte) { State nextState = ErrorState; - emi.modRM = nextByte; + ModRM modRM; + modRM = nextByte; DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); if (0) {//FIXME in 16 bit mode //figure out 16 bit displacement size - if(nextByte & 0xC7 == 0x06 || - nextByte & 0xC0 == 0x80) + if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2) displacementSize = 2; - else if(nextByte & 0xC0 == 0x40) + else if(modRM.mod == 1) displacementSize = 1; else displacementSize = 0; } else { //figure out 32/64 bit displacement size - if(nextByte & 0xC6 == 0x04 || - nextByte & 0xC0 == 0x80) + if(modRM.mod == 0 && modRM.rm == 4 || modRM.mod == 2) displacementSize = 4; - else if(nextByte & 0xC0 == 0x40) + else if(modRM.mod == 1) displacementSize = 1; else displacementSize = 0; } //If there's an SIB, get that next. //There is no SIB in 16 bit mode. - if(nextByte & 0x7 == 4 && - nextByte & 0xC0 != 0xC0) { + if(modRM.rm == 4 && modRM.mod != 3) { // && in 32/64 bit mode) nextState = SIBState; } else if(displacementSize) { @@ -301,6 +299,7 @@ namespace X86ISA } //The ModRM byte is consumed no matter what consumeByte(); + emi.modRM = modRM; return nextState; } diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 298dff80b..61ab2bac9 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -160,7 +160,7 @@ namespace X86ISA } opcode; //Modifier bytes ModRM modRM; - uint8_t sib; + Sib sib; //Immediate fields uint64_t immediate; uint64_t displacement; -- cgit v1.2.3 From 438ec924d65f0ff36a88965b6db0b3d0c4c115b3 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 20 Jun 2007 08:12:10 -0700 Subject: Don't go over 80 chars per line --HG-- extra : convert_revision : ec73c3c8788757990a6fab8c600f3b353d0d4206 --- src/SConscript | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SConscript b/src/SConscript index 34c5453b7..7a3b25c92 100644 --- a/src/SConscript +++ b/src/SConscript @@ -277,9 +277,10 @@ def makeEnv(label, objsfx, strip = False, **kwargs): if strip: stripped_bin = bin + '.stripped' if sys.platform == 'sunos5': - newEnv.Command(stripped_bin, bin, 'cp $SOURCE $TARGET; strip $TARGET') + cmd = 'cp $SOURCE $TARGET; strip $TARGET' else: - newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET') + cmd = 'strip $SOURCE -o $TARGET' + newEnv.Command(stripped_bin, bin, cmd) bin = stripped_bin targets = newEnv.Concat(exe, [bin, 'm5py.zip']) newEnv.M5Binary = targets[0] -- cgit v1.2.3 From b47737dde7e9138a7e7511380d785f11417552d0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 20 Jun 2007 08:14:11 -0700 Subject: Make sure all parameters have default values if they're supposed to and make sure parameters have the right type. Also make sure that any object that should be an intermediate type has the right options set. --HG-- extra : convert_revision : d56910628d9a067699827adbc0a26ab629d11e93 --- src/cpu/o3/O3CPU.py | 20 ++++++++++---------- src/dev/Ethernet.py | 7 ++++--- src/mem/cache/BaseCache.py | 1 + src/sim/Process.py | 2 +- src/sim/System.py | 1 + 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index e031faefa..e691cfe5d 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -55,7 +55,7 @@ class DerivO3CPU(BaseCPU): checker.itb = Parent.itb checker.dtb = Parent.dtb - cachePorts = Param.Unsigned("Cache Ports") + cachePorts = Param.Unsigned(200, "Cache Ports") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") _mem_ports = ['icache_port', 'dcache_port'] @@ -137,15 +137,15 @@ class DerivO3CPU(BaseCPU): function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - smtNumFetchingThreads = Param.Unsigned("SMT Number of Fetching Threads") - smtFetchPolicy = Param.String("SMT Fetch policy") - smtLSQPolicy = Param.String("SMT LSQ Sharing Policy") - smtLSQThreshold = Param.String("SMT LSQ Threshold Sharing Parameter") - smtIQPolicy = Param.String("SMT IQ Sharing Policy") - smtIQThreshold = Param.String("SMT IQ Threshold Sharing Parameter") - smtROBPolicy = Param.String("SMT ROB Sharing Policy") - smtROBThreshold = Param.String("SMT ROB Threshold Sharing Parameter") - smtCommitPolicy = Param.String("SMT Commit Policy") + smtNumFetchingThreads = Param.Unsigned(1, "SMT Number of Fetching Threads") + smtFetchPolicy = Param.String('SingleThread', "SMT Fetch policy") + smtLSQPolicy = Param.String('Partitioned', "SMT LSQ Sharing Policy") + smtLSQThreshold = Param.Int(100, "SMT LSQ Threshold Sharing Parameter") + smtIQPolicy = Param.String('Partitioned', "SMT IQ Sharing Policy") + smtIQThreshold = Param.Int(100, "SMT IQ Threshold Sharing Parameter") + smtROBPolicy = Param.String('Partitioned', "SMT ROB Sharing Policy") + smtROBThreshold = Param.Int(100, "SMT ROB Threshold Sharing Parameter") + smtCommitPolicy = Param.String('RoundRobin', "SMT Commit Policy") def addPrivateSplitL1Caches(self, ic, dc): BaseCPU.addPrivateSplitL1Caches(self, ic, dc) diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index e81862a96..587087640 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -64,7 +64,8 @@ class EtherDump(SimObject): class IGbE(PciDevice): type = 'IGbE' - hardware_address = Param.String("Ethernet Hardware Address") + hardware_address = Param.EthernetAddr(NextEthernetAddr, + "Ethernet Hardware Address") use_flow_control = Param.Bool(False, "Should we use xon/xoff flow contorl (UNIMPLEMENTD)") rx_fifo_size = Param.MemorySize('384kB', "Size of the rx FIFO") @@ -100,9 +101,9 @@ class IGbEInt(EtherInt): type = 'IGbEInt' device = Param.IGbE("Ethernet device of this interface") - - class EtherDevBase(PciDevice): + type = 'EtherDevBase' + abstract = True hardware_address = Param.EthernetAddr(NextEthernetAddr, "Ethernet Hardware Address") diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index 32f3f0174..55b68f81f 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -90,3 +90,4 @@ class BaseCache(MemObject): "Only prefetch on data not on instruction accesses") cpu_side = Port("Port on side closer to CPU") mem_side = Port("Port on side closer to MEM") + addr_range = VectorParam.AddrRange(AllMemory, "The address range in bytes") diff --git a/src/sim/Process.py b/src/sim/Process.py index 16be65fd4..34ff6c394 100644 --- a/src/sim/Process.py +++ b/src/sim/Process.py @@ -40,7 +40,7 @@ class LiveProcess(Process): type = 'LiveProcess' executable = Param.String('', "executable (overrides cmd[0] if set)") cmd = VectorParam.String("command line (executable plus arguments)") - env = VectorParam.String('', "environment settings") + env = VectorParam.String([], "environment settings") cwd = Param.String('', "current working directory") input = Param.String('cin', "filename for stdin") uid = Param.Int(100, 'user id') diff --git a/src/sim/System.py b/src/sim/System.py index b37e385c1..3f4c57f0c 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -39,6 +39,7 @@ class System(SimObject): physmem = Param.PhysicalMemory(Parent.any, "phsyical memory") mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in") if build_env['FULL_SYSTEM']: + abstract = True boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, "boot processor frequency") init_param = Param.UInt64(0, "numerical value to pass into simulator") -- cgit v1.2.3 From f65e2710ecb725f9f44e0e9edd8389f39720cd64 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 20 Jun 2007 08:15:06 -0700 Subject: Don't do checker stuff if the checker is not defined --HG-- extra : convert_revision : 1c920b050c21e592a386410e4e9f45354f8e4441 --- src/cpu/o3/cpu.cc | 10 ++++------ src/cpu/o3/cpu.hh | 3 +++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index a775b66d5..9e1b5d132 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -204,19 +204,17 @@ FullO3CPU::FullO3CPU(O3CPU *o3_cpu, Params *params) _status = Idle; } - checker = NULL; - - if (params->checker) { #if USE_CHECKER + if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast *>(temp_checker); #if FULL_SYSTEM checker->setSystem(params->system); #endif -#else - panic("Checker enabled but not compiled in!"); -#endif // USE_CHECKER + } else { + checker = NULL; } +#endif // USE_CHECKER #if !FULL_SYSTEM thread.resize(number_of_threads); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index e71d05c8e..b7533e311 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -42,6 +42,7 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "config/full_system.hh" +#include "config/use_checker.hh" #include "cpu/activity.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" @@ -617,11 +618,13 @@ class FullO3CPU : public BaseO3CPU /** The global sequence number counter. */ InstSeqNum globalSeqNum;//[Impl::MaxThreads]; +#if USE_CHECKER /** Pointer to the checker, which can dynamically verify * instruction results at run time. This can be set to NULL if it * is not being used. */ Checker *checker; +#endif #if FULL_SYSTEM /** Pointer to the system. */ -- cgit v1.2.3 From d540dde5b4ed38c5aec846282082dd04fce24b78 Mon Sep 17 00:00:00 2001 From: Vincentius Robby Date: Wed, 20 Jun 2007 14:54:17 -0400 Subject: Removed "adding instead of dividing" trick. Caused slowdown in performance instead of speeding up. src/cpu/base.cc: Removed "adding instead of dividing" trick. src/mem/bus.cc: Fixed spelling in comments. Removed "adding instead of dividing" trick. --HG-- extra : convert_revision : 65a736f4f09a64e737dc7aeee53b117976330488 --- src/cpu/base.cc | 6 ++---- src/mem/bus.cc | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 078ae1283..f86313da0 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -269,12 +269,10 @@ Tick BaseCPU::nextCycle(Tick begin_tick) { Tick next_tick = begin_tick; - next_tick -= (next_tick % clock); + if (next_tick % clock != 0) + next_tick = next_tick - (next_tick % clock) + clock; next_tick += phase; - while (next_tick < curTick) - next_tick += clock; - assert(next_tick >= curTick); return next_tick; } diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 13e545064..806c7ed85 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -115,11 +115,14 @@ void Bus::occupyBus(PacketPtr pkt) //Bring tickNextIdle up to the present tick //There is some potential ambiguity where a cycle starts, which might make //a difference when devices are acting right around a cycle boundary. Using - //a < allows things which happen exactly on a cycle boundary to take up only - //the following cycle. Anthing that happens later will have to "wait" for - //the end of that cycle, and then start using the bus after that. - while (tickNextIdle < curTick) - tickNextIdle += clock; + //a < allows things which happen exactly on a cycle boundary to take up + //only the following cycle. Anything that happens later will have to "wait" + //for the end of that cycle, and then start using the bus after that. + if (tickNextIdle < curTick) { + tickNextIdle = curTick; + if (tickNextIdle % clock != 0) + tickNextIdle -= (curTick % clock) + clock; + } // The packet will be sent. Figure out how long it occupies the bus, and // how much of that time is for the first "word", aka bus width. @@ -132,10 +135,9 @@ void Bus::occupyBus(PacketPtr pkt) // We're using the "adding instead of dividing" trick again here if (pkt->hasData()) { int dataSize = pkt->getSize(); - for (int transmitted = 0; transmitted < dataSize; - transmitted += width) { + numCycles += dataSize/width; + if (dataSize % width) numCycles++; - } } else { // If the packet didn't have data, it must have been a response. // Those use the bus for one cycle to send their data. -- cgit v1.2.3 From 4a7bc06553577f25e8dc895fa20506c62455a4b6 Mon Sep 17 00:00:00 2001 From: Vincentius Robby Date: Wed, 20 Jun 2007 15:04:36 -0400 Subject: Minor error. --HG-- extra : convert_revision : 514032e21c8861f20fcbcae7204e132088cc7dbc --- src/mem/bus.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 806c7ed85..d818a25ea 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -121,7 +121,7 @@ void Bus::occupyBus(PacketPtr pkt) if (tickNextIdle < curTick) { tickNextIdle = curTick; if (tickNextIdle % clock != 0) - tickNextIdle -= (curTick % clock) + clock; + tickNextIdle = curTick - (curTick % clock) + clock; } // The packet will be sent. Figure out how long it occupies the bus, and -- cgit v1.2.3 From 27da9f99b1a294411629e89ab1abf04f91c3fd64 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:04:38 +0000 Subject: Comment out some unnecessary debug statements. --HG-- extra : convert_revision : aabaaf099f070832bf42cedf2472170e0738ee1c --- src/arch/micro_asm.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 145029477..5aa910cc3 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -238,9 +238,7 @@ def t_params_PARAMS(t): unescapeParamsRE = re.compile(r'(\\[\n;\\])') def unescapeParams(mo): val = mo.group(0) - print "About to sub %s for %s" % (val[1], val) return val[1] - print "Looking for matches in %s" % t.value t.value = unescapeParamsRE.sub(unescapeParams, t.value) t.lexer.begin('asm') return t @@ -483,9 +481,9 @@ class MicroAssembler(object): def assemble(self, asm): self.parser.parse(asm, lexer=self.lexer) # Begin debug printing - for macroop in self.parser.macroops.values(): - print macroop - print self.parser.rom + #for macroop in self.parser.macroops.values(): + # print macroop + #print self.parser.rom # End debug printing macroops = self.parser.macroops self.parser.macroops = {} -- cgit v1.2.3 From a735b7e282b3773c44265489e7d7afe0ddd6e4e0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:04:39 +0000 Subject: Forgot to check these in... --HG-- extra : convert_revision : f489fda15740bae0a73bfb012f3bab5790b5c2b5 --- src/arch/x86/emulenv.cc | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/emulenv.hh | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 src/arch/x86/emulenv.cc create mode 100644 src/arch/x86/emulenv.hh diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc new file mode 100644 index 000000000..e3f703cff --- /dev/null +++ b/src/arch/x86/emulenv.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/emulenv.hh" +#include "base/misc.hh" + +using namespace X86ISA; + +void EmulEnv::doModRM(const ExtMachInst & machInst) +{ + assert(machInst.modRM.mod != 3); + //Use the SIB byte for addressing if the modrm byte calls for it. + if (machInst.modRM.rm == 4 && machInst.addrSize != 2) { + scale = 1 << machInst.sib.scale; + index = machInst.sib.index; + base = machInst.sib.base; + //In this special case, we don't use a base. The displacement also + //changes, but that's managed by the predecoder. + if (machInst.sib.base == INTREG_RBP && machInst.modRM.mod == 0) + base = NUM_INTREGS; + //In -this- special case, we don't use an index. + if (machInst.sib.index == INTREG_RSP) + index = NUM_INTREGS; + } else { + if (machInst.addrSize == 2) { + warn("I'm not really using 16 bit MODRM like I'm supposed to!\n"); + } else { + scale = 0; + base = machInst.modRM.rm; + if (machInst.modRM.mod == 0 && machInst.modRM.rm == 5) { + base = NUM_INTREGS; + if (machInst.mode.submode == SixtyFourBitMode) + base = NUM_INTREGS+7; + } + } + } +} + diff --git a/src/arch/x86/emulenv.hh b/src/arch/x86/emulenv.hh new file mode 100644 index 000000000..66c56fb79 --- /dev/null +++ b/src/arch/x86/emulenv.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_EMULENV_HH__ +#define __ARCH_X86_EMULENV_HH__ + +#include "arch/x86/types.hh" +#include "arch/x86/intregs.hh" + +namespace X86ISA +{ + struct EmulEnv + { + RegIndex reg; + RegIndex regm; + uint8_t scale; + RegIndex index; + RegIndex base; + int dataSize; + int addressSize; + int stackSize; + + EmulEnv(RegIndex _reg, RegIndex _regm, + int _dataSize, int _addressSize, int _stackSize) : + reg(_reg), regm(_regm), + scale(0), index(NUM_INTREGS), + base(NUM_INTREGS), + dataSize(_dataSize), addressSize(_addressSize), + stackSize(_stackSize) + {;} + + void doModRM(const ExtMachInst & machInst); + }; +}; + +#endif // __ARCH_X86_TYPES_HH__ -- cgit v1.2.3 From e6328170e17fd98cce34d5d5675097aec7f73b88 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:04:40 +0000 Subject: Comment out some unnecessary debug output. --HG-- extra : convert_revision : 9df17841d970a7995d8ed1d51ee66e2c5457e5e3 --- src/arch/x86/isa/microasm.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index fde430691..50addb33f 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -68,7 +68,7 @@ let {{ import sys sys.path[0:0] = ["src/arch/x86/isa/"] from insts import microcode - print microcode + # print microcode from micro_asm import MicroAssembler, Rom_Macroop, Rom mainRom = Rom('main ROM') assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop) -- cgit v1.2.3 From 6c4b3db04ce0999601bf834ea3227b8fd07d7bdd Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:04:41 +0000 Subject: Fix a typo in one of the operand type tags. --HG-- extra : convert_revision : bea87214ba4b40d75a350b803154836ec6d0ae9e --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 3b4e72347..484f8160d 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -315,7 +315,7 @@ 0x0: Inst::MOV(Eb,Gb); 0x1: Inst::MOV(Ev,Gv); 0x2: Inst::MOV(Gb,Eb); - 0x3: Inst::MOV(Gv,Eb); + 0x3: Inst::MOV(Gv,Ev); 0x4: mov_MwRv_Sw(); //What to do with this one? 0x5: Inst::LEA(Gv,M); 0x6: mov_Sw_MwRv(); -- cgit v1.2.3 From a19f1c40145ebc8dec66f888c82ac92bfd05d28e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:05:06 +0000 Subject: X86 probably doesn't need a window save area. --HG-- extra : convert_revision : c4a76262d4396f5f5b96b1c9e751014c2abbd78a --- src/arch/x86/process.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index af7494598..7deb54945 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -268,7 +268,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize) int argv_array_size = intSize * (argv.size() + 1); int argc_size = intSize; - int window_save_size = intSize * 16; int space_needed = mysterious_size + @@ -276,8 +275,7 @@ X86LiveProcess::argsInit(int intSize, int pageSize) aux_array_size + envp_array_size + argv_array_size + - argc_size + - window_save_size; + argc_size; stack_min = stack_base - space_needed; stack_min &= alignmentMask; @@ -296,10 +294,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize) Addr envp_array_base = auxv_array_base - envp_array_size; Addr argv_array_base = envp_array_base - argv_array_size; Addr argc_base = argv_array_base - argc_size; -#ifndef NDEBUG - // only used in DPRINTF - Addr window_save_base = argc_base - window_save_size; -#endif DPRINTF(X86, "The addresses of items on the initial stack:\n"); DPRINTF(X86, "0x%x - file name\n", file_name_base); @@ -309,7 +303,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize) DPRINTF(X86, "0x%x - envp array\n", envp_array_base); DPRINTF(X86, "0x%x - argv array\n", argv_array_base); DPRINTF(X86, "0x%x - argc \n", argc_base); - DPRINTF(X86, "0x%x - window save\n", window_save_base); DPRINTF(X86, "0x%x - stack min\n", stack_min); // write contents to stack -- cgit v1.2.3 From c4ebfa850e141ae7b33184f061874f9576bf5a54 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:06:08 +0000 Subject: Fix a newly introduced bug where the predecoder wasn't picking up all the displacement. --HG-- extra : convert_revision : 9202c11ee187458adcd85ba616b7f7f4bdd4eec1 --- src/arch/x86/predecoder.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index bbbad7dd0..49f76699b 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -277,7 +277,8 @@ namespace X86ISA displacementSize = 0; } else { //figure out 32/64 bit displacement size - if(modRM.mod == 0 && modRM.rm == 4 || modRM.mod == 2) + if(modRM.mod == 0 && (modRM.rm == 4 || modRM.rm == 5) + || modRM.mod == 2) displacementSize = 4; else if(modRM.mod == 1) displacementSize = 1; -- cgit v1.2.3 From 77aa98d0f84343445588b3c137463e4eba4c2909 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 20 Jun 2007 19:08:04 +0000 Subject: Implement rip relative addressing and put in some missing loads and stores. --HG-- extra : convert_revision : 99053414cef40f13c5226871a72909b2622d8c26 --- src/arch/x86/isa/formats/multi.isa | 4 +- .../x86/isa/insts/arithmetic/add_and_subtract.py | 16 +++++++- src/arch/x86/isa/insts/compare_and_test/test.py | 17 ++++++++ src/arch/x86/isa/insts/data_transfer/move.py | 34 ++++++++++++++-- src/arch/x86/isa/insts/load_effective_address.py | 5 +++ src/arch/x86/isa/insts/logical.py | 46 +++++++++++++++++++--- src/arch/x86/isa/specialize.isa | 37 +++++++++++++---- 7 files changed, 137 insertions(+), 22 deletions(-) diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa index 37b28fe64..97777f727 100644 --- a/src/arch/x86/isa/formats/multi.isa +++ b/src/arch/x86/isa/formats/multi.isa @@ -70,8 +70,8 @@ def format Inst(*opTypeSet) {{ def format MultiInst(switchVal, *opTypeSets) {{ switcher = {} for (count, opTypeSet) in zip(xrange(len(opTypeSets)), opTypeSets): - switcher[count] = (Name, opTypeSet, EmulEnv()) - blocks = doSplitDecode(specializeInst, switchVal, switcher) + switcher[count] = (specializeInst, Name, opTypeSet, EmulEnv()) + blocks = doSplitDecode(switchVal, switcher) (header_output, decoder_output, decode_block, exec_output) = blocks.makeList() }}; diff --git a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py index 349c2bb46..de66f70f3 100644 --- a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py +++ b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py @@ -61,9 +61,21 @@ def macroop SUB_R_I def macroop SUB_M_I { - #Load into t1 + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE" - #save from t1 + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" +}; + +def macroop SUB_P_I +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE" + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/compare_and_test/test.py b/src/arch/x86/isa/insts/compare_and_test/test.py index 36abab5d1..7b4ab0781 100644 --- a/src/arch/x86/isa/insts/compare_and_test/test.py +++ b/src/arch/x86/isa/insts/compare_and_test/test.py @@ -61,6 +61,14 @@ def macroop TEST_M_R and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg" }; +def macroop TEST_P_R +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg" +}; + def macroop TEST_R_R { and "NUM_INTREGS", "env.reg", "env.regm" @@ -74,6 +82,15 @@ def macroop TEST_M_I and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2" }; +def macroop TEST_P_I +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + limm "NUM_INTREGS+2", "IMMEDIATE" + and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2" +}; + def macroop TEST_R_I { limm "NUM_INTREGS+1", "IMMEDIATE" diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index c674329ea..662b2c373 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -62,17 +62,35 @@ def macroop MOV_M_R { st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" }; +def macroop MOV_P_R { + rdip "NUM_INTREGS+7" + st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" +}; + def macroop MOV_R_M { ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" }; +def macroop MOV_R_P { + rdip "NUM_INTREGS+7" + ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" +}; + def macroop MOV_R_I { limm "env.reg", "IMMEDIATE" }; def macroop MOV_M_I { - limm "env.reg", "IMMEDIATE" - #Do a store to put the register operand into memory + limm "NUM_INTREGS+1", "IMMEDIATE" + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" +}; + +def macroop MOV_P_I { + rdip "NUM_INTREGS+7" + limm "NUM_INTREGS+1", "IMMEDIATE" + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" }; def macroop MOVSXD_R_R { @@ -80,8 +98,16 @@ def macroop MOVSXD_R_R { }; def macroop MOVSXD_R_M { - #Do a load to fill the register operand from memory - sext "env.reg", "env.regm", "env.dataSize" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + sext "env.reg", "NUM_INTREGS+1", "env.dataSize" +}; + +def macroop MOVSXD_R_P { + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + sext "env.reg", "NUM_INTREGS+1", "env.dataSize" }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/load_effective_address.py b/src/arch/x86/isa/insts/load_effective_address.py index ac32638a0..f5f92ddbf 100644 --- a/src/arch/x86/isa/insts/load_effective_address.py +++ b/src/arch/x86/isa/insts/load_effective_address.py @@ -57,4 +57,9 @@ microcode = ''' def macroop LEA_R_M { lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" }; + +def macroop LEA_R_P { + rdip "NUM_INTREGS+7" + lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT" +}; ''' diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py index 0b7c41208..d02bfd586 100644 --- a/src/arch/x86/isa/insts/logical.py +++ b/src/arch/x86/isa/insts/logical.py @@ -67,14 +67,35 @@ def macroop XOR_R_I def macroop XOR_M_R { - #Do a load to get one of the sources + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg" - #Do a store to write the destination + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" +}; + +def macroop XOR_P_R +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg" + st "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" }; def macroop XOR_R_M { - #Do a load to get one of the sources + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + xor "env.reg", "env.reg", "NUM_INTREGS+1" +}; + +def macroop XOR_R_P +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" xor "env.reg", "env.reg", "NUM_INTREGS+1" }; @@ -86,10 +107,23 @@ def macroop AND_R_I def macroop AND_M_I { - #Do a load to get one of the sources + ld "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" + limm "NUM_INTREGS+1", "IMMEDIATE" + and "NUM_INTREGS+2", "NUM_INTREGS+2", "NUM_INTREGS+1" + st "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" +}; + +def macroop AND_P_I +{ + rdip "NUM_INTREGS+7" + ld "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" limm "NUM_INTREGS+1", "IMMEDIATE" - and "NUM_INTREGS+1", "NUM_INTREGS+1", "NUM_INTREGS+2" - #Do a store to write the destination + and "NUM_INTREGS+2", "NUM_INTREGS+2", "NUM_INTREGS+1" + st "NUM_INTREGS+2", 3, ["env.scale", "env.index", "env.base"], \ + "DISPLACEMENT" }; ''' #let {{ diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 10e57ba18..3183f32ba 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -64,18 +64,18 @@ let {{ # This code builds up a decode block which decodes based on switchval. # vals is a dict which matches case values with what should be decoded to. - # builder is called on the exploded contents of "vals" values to generate - # whatever code should be used. - def doSplitDecode(builder, switchVal, vals, default = None): + # Each element of the dict is a list containing a function and then the + # arguments to pass to it. + def doSplitDecode(switchVal, vals, default = None): blocks = OutputBlocks() blocks.decode_block = 'switch(%s) {\n' % switchVal for (val, todo) in vals.items(): - new_blocks = builder(*todo) + new_blocks = todo[0](*todo[1:]) new_blocks.decode_block = \ '\tcase %s: %s\n' % (val, new_blocks.decode_block) blocks.append(new_blocks) if default: - new_blocks = builder(*default) + new_blocks = default[0](*default[1:]) new_blocks.decode_block = \ '\tdefault: %s\n' % new_blocks.decode_block blocks.append(new_blocks) @@ -83,6 +83,27 @@ let {{ return blocks }}; +let {{ + def doRipRelativeDecode(Name, opTypes, env): + # print "RIPing %s with opTypes %s" % (Name, opTypes) + normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), copy.copy(env)) + ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), copy.copy(env)) + + blocks = OutputBlocks() + blocks.append(normBlocks) + blocks.append(ripBlocks) + + blocks.decode_block = ''' + if(machInst.modRM.mod == 0 && + machInst.modRM.rm == 5 && + machInst.mode.submode == SixtyFourBitMode) + { %s } + else + { %s }''' % \ + (ripBlocks.decode_block, normBlocks.decode_block) + return blocks +}}; + let {{ class OpType(object): parser = re.compile(r"(?P[A-Z]+)(?P[a-z]*)|(r(?P[A-Z0-9]+)(?P[a-z]*))") @@ -142,9 +163,9 @@ let {{ # modrm addressing. memEnv = copy.copy(env) memEnv.doModRM = True - return doSplitDecode(specializeInst, "MODRM_MOD", - {"3" : (Name + "_R", copy.copy(opTypes), regEnv)}, - (Name + "_M", copy.copy(opTypes), memEnv)) + return doSplitDecode("MODRM_MOD", + {"3" : (specializeInst, Name + "_R", copy.copy(opTypes), regEnv)}, + (doRipRelativeDecode, Name, copy.copy(opTypes), memEnv)) elif opType.tag in ("I", "J"): # Immediates Name += "_I" -- cgit v1.2.3 From 5195500cdf7dc99b5367f91387eef4e9f5b65bfe Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 21 Jun 2007 13:50:35 -0400 Subject: Use FastAlloc for Packet, Request, CoherenceState, and SenderState so we don't spend so much time calling malloc() --HG-- extra : convert_revision : a946564eee46ed7d2aed41c32d488ca7f036c32f --- src/mem/packet.hh | 7 ++++--- src/mem/request.hh | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index c1e6a1e7f..fb077901e 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -43,6 +43,7 @@ #include #include "base/compiler.hh" +#include "base/fast_alloc.hh" #include "base/misc.hh" #include "mem/request.hh" #include "sim/host.hh" @@ -182,7 +183,7 @@ class MemCmd * ultimate destination and back, possibly being conveyed by several * different Packets along the way.) */ -class Packet +class Packet : public FastAlloc { public: @@ -257,7 +258,7 @@ class Packet /** A virtual base opaque structure used to hold coherence-related * state. A specific subclass would be derived from this to * carry state specific to a particular coherence protocol. */ - class CoherenceState { + class CoherenceState : public FastAlloc { public: virtual ~CoherenceState() {} }; @@ -274,7 +275,7 @@ class Packet * needed to process it. A specific subclass would be derived * from this to carry state specific to a particular sending * device. */ - class SenderState { + class SenderState : public FastAlloc { public: virtual ~SenderState() {} }; diff --git a/src/mem/request.hh b/src/mem/request.hh index d2ebc91d3..e08593f0d 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -39,6 +39,7 @@ #ifndef __MEM_REQUEST_HH__ #define __MEM_REQUEST_HH__ +#include "base/fast_alloc.hh" #include "sim/host.hh" #include "sim/core.hh" @@ -76,7 +77,7 @@ const uint32_t MEM_SWAP = 0x100000; const uint32_t MEM_SWAP_COND = 0x200000; -class Request +class Request : public FastAlloc { private: /** @@ -153,6 +154,8 @@ class Request setVirt(_asid, _vaddr, _size, _flags, _pc); } + ~Request() {} // for FastAlloc + /** * Set up CPU and thread numbers. */ void setThreadContext(int _cpuNum, int _threadNum) -- cgit v1.2.3