From a7f3bbcfab9d54387517c2a52e56bfefee092901 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:21:47 +0000 Subject: [PATCH 01/10] Make microOp vs microop and macroOp vs macroop capitilization consistent. src/arch/x86/isa/macroop.isa: Make microOp vs microop and macroOp vs macroop capitilization consistent. Also fill out the emulation environment handling a little more, and use an object to pass around output code. src/arch/x86/isa/microops/base.isa: Make microOp vs microop and macroOp vs macroop capitilization consistent. Also adjust python to C++ bool translation. --HG-- extra : convert_revision : 6f4bacfa334c42732c845f9a7f211cbefc73f96f --- src/arch/sparc/isa/formats/mem/blockmem.isa | 20 ++--- src/arch/sparc/isa/formats/micro.isa | 24 +++--- src/arch/x86/isa/macroop.isa | 86 +++++++++++++-------- src/arch/x86/isa/microops/base.isa | 24 +++--- src/arch/x86/isa/microops/limmop.isa | 4 +- src/arch/x86/isa/microops/regop.isa | 18 +++-- src/arch/x86/isa/microops/specop.isa | 4 +- src/cpu/exetrace.cc | 12 +-- src/cpu/simple/atomic.cc | 4 +- src/cpu/simple/base.cc | 8 +- src/cpu/static_inst.cc | 4 +- src/cpu/static_inst.hh | 18 ++--- 12 files changed, 126 insertions(+), 100 deletions(-) diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index e19016bd0..caf5bb8ce 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -248,14 +248,14 @@ def template BlockMemConstructor {{ : %(base_class)s("%(mnemonic)s", machInst) { %(constructor)s; - microOps[0] = new %(class_name)s_0(machInst); - microOps[1] = new %(class_name)s_1(machInst); - microOps[2] = new %(class_name)s_2(machInst); - microOps[3] = new %(class_name)s_3(machInst); - microOps[4] = new %(class_name)s_4(machInst); - microOps[5] = new %(class_name)s_5(machInst); - microOps[6] = new %(class_name)s_6(machInst); - microOps[7] = new %(class_name)s_7(machInst); + microops[0] = new %(class_name)s_0(machInst); + microops[1] = new %(class_name)s_1(machInst); + microops[2] = new %(class_name)s_2(machInst); + microops[3] = new %(class_name)s_3(machInst); + microops[4] = new %(class_name)s_4(machInst); + microops[5] = new %(class_name)s_5(machInst); + microops[6] = new %(class_name)s_6(machInst); + microops[7] = new %(class_name)s_7(machInst); } }}; @@ -289,9 +289,9 @@ let {{ for microPc in range(8): flag_code = '' if (microPc == 7): - flag_code = "flags[IsLastMicroOp] = true;" + flag_code = "flags[IsLastMicroop] = true;" elif (microPc == 0): - flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;" + flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroop] = true;" else: flag_code = "flags[IsDelayedCommit] = true;" pcedCode = matcher.sub("Frd_%d" % microPc, code) diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa index da0f97d1b..c1d0c4f36 100644 --- a/src/arch/sparc/isa/formats/micro.isa +++ b/src/arch/sparc/isa/formats/micro.isa @@ -58,33 +58,33 @@ output header {{ class SparcMacroInst : public SparcStaticInst { protected: - const uint32_t numMicroOps; + const uint32_t numMicroops; //Constructor. SparcMacroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint32_t _numMicroOps) + OpClass __opClass, uint32_t _numMicroops) : SparcStaticInst(mnem, _machInst, __opClass), - numMicroOps(_numMicroOps) + numMicroops(_numMicroops) { - assert(numMicroOps); - microOps = new StaticInstPtr[numMicroOps]; - flags[IsMacroOp] = true; + assert(numMicroops); + microops = new StaticInstPtr[numMicroops]; + flags[IsMacroop] = true; } ~SparcMacroInst() { - delete [] microOps; + delete [] microops; } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - StaticInstPtr * microOps; + StaticInstPtr * microops; - StaticInstPtr fetchMicroOp(MicroPC microPC) + StaticInstPtr fetchMicroop(MicroPC microPC) { - assert(microPC < numMicroOps); - return microOps[microPC]; + assert(microPC < numMicroops); + return microops[microPC]; } %(MacroExecute)s @@ -100,7 +100,7 @@ output header {{ ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { - flags[IsMicroOp] = true; + flags[IsMicroop] = true; } }; diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index a7477c5a6..bc7fc8015 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -72,33 +72,33 @@ def template MacroExecPanic {{ output header {{ // Base class for combinationally generated macroops - class MacroOp : public StaticInst + class Macroop : public StaticInst { protected: - const uint32_t numMicroOps; + const uint32_t numMicroops; //Constructor. - MacroOp(const char *mnem, ExtMachInst _machInst, - uint32_t _numMicroOps) + Macroop(const char *mnem, ExtMachInst _machInst, + uint32_t _numMicroops) : StaticInst(mnem, _machInst, No_OpClass), - numMicroOps(_numMicroOps) + numMicroops(_numMicroops) { - assert(numMicroOps); - microOps = new StaticInstPtr[numMicroOps]; - flags[IsMacroOp] = true; + assert(numMicroops); + microops = new StaticInstPtr[numMicroops]; + flags[IsMacroop] = true; } - ~MacroOp() + ~Macroop() { - delete [] microOps; + delete [] microops; } - StaticInstPtr * microOps; + StaticInstPtr * microops; - StaticInstPtr fetchMicroOp(MicroPC microPC) + StaticInstPtr fetchMicroop(MicroPC microPC) { - assert(microPC < numMicroOps); - return microOps[microPC]; + assert(microPC < numMicroops); + return microops[microPC]; } std::string generateDisassembly(Addr pc, @@ -113,7 +113,7 @@ output header {{ // Basic instruction class declaration template. def template MacroDeclare {{ - namespace X86Microop + namespace X86Macroop { /** * Static instruction class for "%(mnemonic)s". @@ -122,20 +122,20 @@ def template MacroDeclare {{ { public: // Constructor. - %(class_name)s(ExtMachInst machInst); + %(class_name)s(ExtMachInst machInst, EmulEnv env); }; }; }}; // Basic instruction class constructor template. def template MacroConstructor {{ - inline %(class_name)s::%(class_name)s(ExtMachInst machInst) - : %(base_class)s("%(mnemonic)s", machInst, %(num_micro_ops)s) + inline X86Macroop::%(class_name)s::%(class_name)s(ExtMachInst machInst, EmulEnv env) + : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s) { %(constructor)s; - //alloc_micro_ops is the code that sets up the microOps + //alloc_microops is the code that sets up the microops //array in the parent class. - %(alloc_micro_ops)s; + %(alloc_microops)s; } }}; @@ -153,7 +153,7 @@ let {{ } self.declared = False def getAllocator(self, env): - return "new X86Macroop::%s(machInst)" % self.name + return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator()) def getDeclaration(self): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out @@ -167,14 +167,14 @@ let {{ micropc = 0 for op in self.microops: allocMicroops += \ - "microOps[%d] = %s;\n" % \ + "microops[%d] = %s;\n" % \ (micropc, op.getAllocator(True, False, micropc == 0, micropc == numMicroops - 1)) micropc += 1 iop = InstObjParams(self.name, self.name, "Macroop", - {"code" : "", "num_micro_ops" : numMicroops, - "alloc_micro_ops" : allocMicroops}) + {"code" : "", "num_microops" : numMicroops, + "alloc_microops" : allocMicroops}) return MacroConstructor.subst(iop); }}; @@ -201,26 +201,46 @@ output header {{ let {{ class EmulEnv(object): def __init__(self): - self.reg = "Not specified" - self.regm = "Not specified" + self.reg = "0" + self.regUsed = False + self.regm = "0" + self.regmUsed = False self.immediate = "IMMEDIATE" self.displacement = "DISPLACEMENT" self.addressSize = "ADDRSIZE" self.dataSize = "OPSIZE" def getAllocator(self): - return "EmulEmv(%(reg)s, %(regm)s, %(immediate)s, %(displacement)s, %(addressSize)s, %(dataSize)s)" % \ - self.__dict__() + return '''EmulEnv(%(reg)s, + %(regm)s, + %(immediate)s, + %(displacement)s, + %(addressSize)s, + %(dataSize)s)''' % \ + self.__dict__ + def addReg(self, reg): + print "Adding reg \"%s\"" % reg + if not self.regUsed: + print "Added as reg" + self.reg = reg + self.regUsed = True + elif not self.regmUsed: + print "Added as regm" + self.regm = reg + self.regmUsed = True + else: + raise Exception, "EmulEnv is out of register specialization spots." }}; let {{ 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: - global header_output - global decoder_output - header_output = macroop.getDeclaration() - decoder_output = macroop.getDefinition() - return "return %s;\n" % macroop.getAllocator(env) + blocks.header_output = macroop.getDeclaration() + blocks.decoder_output = macroop.getDefinition() + macroop.declared = True + blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) + return blocks }}; diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 7fa4f0457..a066d4802 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -64,14 +64,14 @@ let {{ //A class which is the base of all x86 micro ops. It provides a function to //set necessary flags appropriately. output header {{ - class X86MicroOpBase : public X86StaticInst + class X86MicroopBase : public X86StaticInst { protected: const char * instMnem; uint8_t opSize; uint8_t addrSize; - X86MicroOpBase(ExtMachInst _machInst, + X86MicroopBase(ExtMachInst _machInst, const char *mnem, const char *_instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, @@ -79,10 +79,10 @@ output header {{ X86StaticInst(mnem, _machInst, __opClass), instMnem(_instMnem) { - flags[IsMicroOp] = isMicro; + flags[IsMicroop] = isMicro; flags[IsDelayedCommit] = isDelayed; - flags[IsFirstMicroOp] = isFirst; - flags[IsLastMicroOp] = isLast; + flags[IsFirstMicroop] = isFirst; + flags[IsLastMicroop] = isLast; } std::string generateDisassembly(Addr pc, @@ -108,15 +108,19 @@ let {{ def __init__(self, name): self.name = name + # This converts a python bool into a C++ bool + def cppBool(self, val): + if val: + return "true" + else: + return "false" + # This converts a list of python bools into # a comma seperated list of C++ bools. def microFlagsText(self, vals): text = "" for val in vals: - if val: - text += ", true" - else: - text += ", false" + text += ", %s" % self.cppBool(val) return text def getAllocator(self, mnemonic, *microFlags): @@ -130,7 +134,7 @@ let {{ ////////////////////////////////////////////////////////////////////////// def template MicroLdStOpDeclare {{ - class %(class_name)s : public X86MicroOpBase + class %(class_name)s : public X86MicroopBase { protected: const uint8_t scale; diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index 5fce37126..a25d2b712 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -72,7 +72,7 @@ def template MicroLimmOpExecute {{ }}; def template MicroLimmOpDeclare {{ - class %(class_name)s : public X86MicroOpBase + class %(class_name)s : public X86MicroopBase { protected: const RegIndex dest; @@ -141,7 +141,7 @@ let {{ let {{ # Build up the all register version of this micro op - iop = InstObjParams("limm", "Limm", 'X86MicroOpBase', + iop = InstObjParams("limm", "Limm", 'X86MicroopBase', {"code" : "DestReg = imm;"}) header_output += MicroLimmOpDeclare.subst(iop) decoder_output += MicroLimmOpConstructor.subst(iop) diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 52c13231c..c2aa27b67 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -231,17 +231,18 @@ let {{ self.ext = 0 def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, %(mnemonic)s, - %(flags)s %(src1)s, %(src2)s, %(dest)s, + allocator = '''new %(class_name)s(machInst, "%(mnemonic)s" + %(flags)s, %(src1)s, %(src2)s, %(dest)s, %(setStatus)s, %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "src2" : self.src2, "dest" : self.dest, - "setStatus" : self.setStatus, + "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} + return allocator class RegOpImm(X86Microop): def __init__(self, dest, src1, imm): @@ -253,17 +254,18 @@ let {{ self.ext = 0 def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, %(mnemonic)s, - %(flags)s %(src1)s, %(imm8)s, %(dest)s, + allocator = '''new %(class_name)s(machInst, "%(mnemonic)s" + %(flags)s, %(src1)s, %(imm8)s, %(dest)s, %(setStatus)s, %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "imm8" : self.imm8, "dest" : self.dest, - "setStatus" : self.setStatus, + "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} + return allocator }}; let {{ @@ -290,7 +292,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, 'X86MicroopBase', {"code" : regCode}) header_output += MicroRegOpDeclare.subst(iop) decoder_output += MicroRegOpConstructor.subst(iop) exec_output += MicroRegOpExecute.subst(iop) @@ -305,7 +307,7 @@ let {{ # Build up the immediate version of this micro op iop = InstObjParams(name + "i", Name, - 'X86MicroOpBase', {"code" : immCode}) + 'X86MicroopBase', {"code" : immCode}) header_output += MicroRegOpImmDeclare.subst(iop) decoder_output += MicroRegOpImmConstructor.subst(iop) exec_output += MicroRegOpImmExecute.subst(iop) diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index a3ca7d91c..96fdf1c5e 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -69,7 +69,7 @@ def template MicroFaultExecute {{ }}; def template MicroFaultDeclare {{ - class %(class_name)s : public X86MicroOpBase + class %(class_name)s : public X86MicroopBase { protected: Fault fault; @@ -118,7 +118,7 @@ def template MicroFaultConstructor {{ let {{ # This microop takes in a single parameter, a fault to return. - iop = InstObjParams("fault", "GenFault", 'X86MicroOpBase', {"code" : ""}) + iop = InstObjParams("fault", "GenFault", 'X86MicroopBase', {"code" : ""}) header_output += MicroFaultDeclare.subst(iop) decoder_output += MicroFaultConstructor.subst(iop) exec_output += MicroFaultExecute.subst(iop) diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 3e2b0f03e..75792fa8c 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -162,7 +162,7 @@ Trace::InstRecord::dump() static int fd = 0; //Don't print what happens for each micro-op, just print out //once at the last op, and for regular instructions. - if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) + if(!staticInst->isMicroop() || staticInst->isLastMicroop()) { if(!cosim_listener) { @@ -245,7 +245,7 @@ Trace::InstRecord::dump() #if 0 //THE_ISA == SPARC_ISA //Don't print what happens for each micro-op, just print out //once at the last op, and for regular instructions. - if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) + if(!staticInst->isMicroop() || staticInst->isLastMicroop()) { static uint64_t regs[32] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -432,7 +432,7 @@ Trace::InstRecord::dump() setupSharedData(); // We took a trap on a micro-op... - if (wasMicro && !staticInst->isMicroOp()) + if (wasMicro && !staticInst->isMicroop()) { // let's skip comparing this tick while (!compared) @@ -444,13 +444,13 @@ Trace::InstRecord::dump() wasMicro = false; } - if (staticInst->isLastMicroOp()) + if (staticInst->isLastMicroop()) wasMicro = false; - else if (staticInst->isMicroOp()) + else if (staticInst->isMicroop()) wasMicro = true; - if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { + if(!staticInst->isMicroop() || staticInst->isLastMicroop()) { while (!compared) { if (shared_data->flags == OWN_M5) { m5Pc = PC & TheISA::PAddrImplMask; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index fab537748..ea1c7d87f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -540,8 +540,8 @@ AtomicSimpleCPU::tick() } // @todo remove me after debugging with legion done - if (curStaticInst && (!curStaticInst->isMicroOp() || - curStaticInst->isFirstMicroOp())) + if (curStaticInst && (!curStaticInst->isMicroop() || + curStaticInst->isFirstMicroop())) instCnt++; if (simulate_stalls) { diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 33c5877a5..b4371b2c4 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -400,17 +400,17 @@ BaseSimpleCPU::preExecute() //If we decoded an instruction and it's microcoded, start pulling //out micro ops - if (instPtr && instPtr->isMacroOp()) { + if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> - fetchMicroOp(thread->readMicroPC()); + fetchMicroop(thread->readMicroPC()); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op curStaticInst = curMacroStaticInst-> - fetchMicroOp(thread->readMicroPC()); + fetchMicroop(thread->readMicroPC()); } //If we decoded an instruction this "tick", record information about it. @@ -475,7 +475,7 @@ BaseSimpleCPU::advancePC(Fault fault) thread->setNextMicroPC(1); } else { //If we're at the last micro op for this instruction - if (curStaticInst && curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroop()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index 64fcc0580..a5580d707 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -76,9 +76,9 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const } StaticInstPtr -StaticInst::fetchMicroOp(MicroPC micropc) +StaticInst::fetchMicroop(MicroPC micropc) { - panic("StaticInst::fetchMicroOp() called on instruction " + panic("StaticInst::fetchMicroop() called on instruction " "that is not microcoded."); } diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index a58ac85d6..b11e74c6e 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -143,11 +143,11 @@ class StaticInstBase : public RefCounted IsUnverifiable, ///< Can't be verified by a checker //Flags for microcode - IsMacroOp, ///< Is a macroop containing microops - IsMicroOp, ///< Is a microop + IsMacroop, ///< Is a macroop containing microops + IsMicroop, ///< Is a microop IsDelayedCommit, ///< This microop doesn't commit right away - IsLastMicroOp, ///< This microop ends a microop sequence - IsFirstMicroOp, ///< This microop begins a microop sequence + IsLastMicroop, ///< This microop ends a microop sequence + IsFirstMicroop, ///< This microop begins a microop sequence //This flag doesn't do anything yet IsMicroBranch, ///< This microop branches within the microcode for a macroop @@ -242,11 +242,11 @@ class StaticInstBase : public RefCounted bool isQuiesce() const { return flags[IsQuiesce]; } bool isIprAccess() const { return flags[IsIprAccess]; } bool isUnverifiable() const { return flags[IsUnverifiable]; } - bool isMacroOp() const { return flags[IsMacroOp]; } - bool isMicroOp() const { return flags[IsMicroOp]; } + bool isMacroop() const { return flags[IsMacroop]; } + bool isMicroop() const { return flags[IsMicroop]; } bool isDelayedCommit() const { return flags[IsDelayedCommit]; } - bool isLastMicroOp() const { return flags[IsLastMicroOp]; } - bool isFirstMicroOp() const { return flags[IsFirstMicroOp]; } + bool isLastMicroop() const { return flags[IsLastMicroop]; } + bool isFirstMicroop() const { return flags[IsFirstMicroop]; } //This flag doesn't do anything yet bool isMicroBranch() const { return flags[IsMicroBranch]; } //@} @@ -369,7 +369,7 @@ class StaticInst : public StaticInstBase * Return the microop that goes with a particular micropc. This should * only be defined/used in macroops which will contain microops */ - virtual StaticInstPtr fetchMicroOp(MicroPC micropc); + virtual StaticInstPtr fetchMicroop(MicroPC micropc); /** * Return the target address for a PC-relative branch. From 4ad73abcfb663050d02b10b0595b4bc80a8a186f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:22:35 +0000 Subject: [PATCH 02/10] Add some dprintfs --HG-- extra : convert_revision : 7e9a1feb808604364584893eed1735a8da1556fb --- src/arch/x86/intregfile.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/arch/x86/intregfile.cc b/src/arch/x86/intregfile.cc index 15e86d88b..9c9ea134e 100644 --- a/src/arch/x86/intregfile.cc +++ b/src/arch/x86/intregfile.cc @@ -87,6 +87,7 @@ #include "arch/x86/intregfile.hh" #include "base/misc.hh" +#include "base/trace.hh" #include "sim/serialize.hh" #include @@ -119,11 +120,13 @@ void IntRegFile::clear() IntReg IntRegFile::readReg(int intReg) { + DPRINTF(X86, "Read int reg %d and got value %#x\n", intReg, regs[intReg]); return regs[intReg]; } void IntRegFile::setReg(int intReg, const IntReg &val) { + DPRINTF(X86, "Setting int reg %d to value %#x\n", intReg, val); regs[intReg] = val; } From d0c5da2cd4227f6dfd12546a0ffcc9e50ffe77cb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:23:42 +0000 Subject: [PATCH 03/10] Add an address size bitfield to the isa description and the ExtMachInst --HG-- extra : convert_revision : f8907ef5ef77e050eeb00d895263b49da4a9b6e9 --- src/arch/x86/isa/bitfields.isa | 1 + src/arch/x86/types.hh | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index e4a5e310c..c7ed02f2c 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -87,3 +87,4 @@ def bitfield SIB_INDEX sib.index; def bitfield SIB_BASE sib.base; def bitfield OPSIZE opSize; +def bitfield ADDRSIZE addrSize; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 022f20ee5..225258358 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -149,7 +149,8 @@ namespace X86ISA //The effective operand size. uint8_t opSize; - //The + //The effective address size. + uint8_t addrSize; }; inline static std::ostream & From 7a52faa39bf1bc9a961c98a382afa520eb2d0c87 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:25:47 +0000 Subject: [PATCH 04/10] Use objects to pass around output code, and fix/implement a few things. src/arch/x86/isa/formats/multi.isa: Make the formats use objects to pass around output code. --HG-- extra : convert_revision : 428915bda22e848befac15097f56375c1818426e --- src/arch/x86/isa/formats/multi.isa | 8 ++++-- src/arch/x86/isa/specialize.isa | 43 ++++++++++++++++-------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa index 8648800b4..f951dc28a 100644 --- a/src/arch/x86/isa/formats/multi.isa +++ b/src/arch/x86/isa/formats/multi.isa @@ -62,12 +62,16 @@ ////////////////////////////////////////////////////////////////////////// def format Inst(*opTypeSet) {{ - decode_block = specializeInst(Name, list(opTypeSet), EmulEnv()) + blocks = specializeInst(Name, list(opTypeSet), EmulEnv()) + (header_output, decoder_output, + decode_block, exec_output) = blocks.makeList() }}; def format MultiInst(switchVal, *opTypeSets) {{ switcher = {} for (count, opTypeSet) in zip(xrange(len(opTypeSets)), opTypeSets): switcher[count] = (opTypeSet, EmulEnv()) - decode_block = doSplitDecode(Name, specializeInst, switchVal, switcher) + blocks = doSplitDecode(Name, specializeInst, switchVal, switcher) + (header_output, decoder_output, + decode_block, exec_output) = blocks.makeList() }}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 79b785ecf..3b4e09daa 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -67,17 +67,20 @@ let {{ # builder is called on the exploded contents of "vals" values to generate # whatever code should be used. def doSplitDecode(Name, builder, switchVal, vals, default = None): - decode_block = 'switch(%s) {\n' % switchVal + blocks = OutputBlocks() + blocks.decode_block = 'switch(%s) {\n' % switchVal for (val, todo) in vals.items(): - new_block = builder(Name, *todo) - new_block = '\tcase %s: %s\n' % (val, new_block) - decode_block += new_block + new_blocks = builder(Name, *todo) + new_blocks.decode_block = \ + '\tcase %s: %s\n' % (val, new_blocks.decode_block) + blocks.append(new_blocks) if default: - new_block = builder(Name, *default) - new_block = '\tdefault: %s\n' % new_block - decode_block += new_block - decode_block += '}\n' - return decode_block + new_blocks = builder(Name, *default) + new_blocks.decode_block = \ + '\tdefault: %s\n' % new_blocks.decode_block + blocks.append(new_blocks) + blocks.decode_block += '}\n' + return blocks }}; let {{ @@ -95,18 +98,18 @@ let {{ # This function specializes the given piece of code to use a particular # set of argument types described by "opTypes". def specializeInst(Name, opTypes, env): + print "Specializing %s with opTypes %s" % (Name, opTypes) while len(opTypes): - # print "Building a composite op with tags", opTypes - # print "And code", code - opNum = len(opTypes) - 1 - # Parse the operand type string we're working with - opType = OpType(opTypes[opNum]) + opType = OpType(opTypes[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. - print "INTREG_R%s" % (opType.reg + opType.size.upper()) + if opType.reg in ("A", "B", "C", "D"): + env.addReg("INTREG_R%sX" % opType.reg) + else: + env.addReg("INTREG_R%s" % opType.reg) if opType.size: if opType.rsize in ("l", "h", "b"): print "byte" @@ -118,23 +121,23 @@ let {{ raise Exception, "Problem parsing operand tag: %s" % opType.tag elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"): # Use the "reg" field of the ModRM byte to select the register - print "(uint8_t)MODRM_REG" + env.addReg("(uint8_t)MODRM_REG") elif opType.tag in ("E", "Q", "W"): # This might refer to memory or to a register. We need to # divide it up farther. - print "(uint8_t)MODRM_RM" regTypes = copy.copy(opTypes) regTypes.pop(0) regEnv = copy.copy(env) + regEnv.addReg("(uint8_t)MODRM_RM") # 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" memTypes = copy.copy(opTypes) memTypes.pop(0) memEnv = copy.copy(env) + print "%0" return doSplitDecode(Name, specializeInst, "MODRM_MOD", - {"3" : (regTypes, memEnv)}, (memTypes, memEnv)) + {"3" : (regTypes, regEnv)}, (memTypes, memEnv)) elif opType.tag in ("I", "J"): # Immediates print "IMMEDIATE" @@ -146,7 +149,7 @@ let {{ elif opType.tag in ("PR", "R", "VR"): # There should probably be a check here to verify that mod # is equal to 11b - print "(uint8_t)MODRM_RM" + env.addReg("(uint8_t)MODRM_RM") else: raise Exception, "Unrecognized tag %s." % opType.tag opTypes.pop(0) From 2e9fa55f516d7236d1d303da230c81af596b3658 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:29:49 +0000 Subject: [PATCH 05/10] Get rid of unnecessary namespace prototype. --HG-- extra : convert_revision : 388c0d6f2af96c4d33c1fe5d42a21866a4d71556 --- src/arch/x86/isa/includes.isa | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 269233c07..8bb282150 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -108,8 +108,6 @@ output header {{ output decoder {{ -namespace X86Macroop { -}; #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() From eb68c9986ed72b7292673e7b2b06b02bf43dcc56 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:30:48 +0000 Subject: [PATCH 06/10] Fix up a comment that wasn't changed over to x86. --HG-- extra : convert_revision : 58448b984447babba708b9dcb1b4939ed35308a6 --- src/arch/x86/isa/main.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa index d78887c43..fed8903c0 100644 --- a/src/arch/x86/isa/main.isa +++ b/src/arch/x86/isa/main.isa @@ -67,7 +67,7 @@ //////////////////////////////////////////////////////////////////// // // Namespace statement. Everything below this line will be in the -// SparcISAInst namespace. +// X86ISAInst namespace. // namespace X86ISA; From ea3f7c9531f7dc3272733fe722df0b28e73183f9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:31:42 +0000 Subject: [PATCH 07/10] Add in MOV instructions. --HG-- extra : convert_revision : 54a6b36dff3c15699faf2c767fc594359422c0ee --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 8 ++++---- src/arch/x86/isa/insts/data_transfer/move.py | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 8219d0ba8..c29133a5c 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -237,10 +237,10 @@ 0x7: xchg_Ev_Gv(); } 0x11: decode OPCODE_OP_BOTTOM3 { - 0x0: MOV(); - 0x1: MOV(); - 0x2: MOV(); - 0x3: MOV(); + 0x0: Inst::MOV(Eb,Gb); + 0x1: Inst::MOV(Ev,Gv); + 0x2: Inst::MOV(Gb,Eb); + 0x3: Inst::MOV(Gv,Eb); 0x4: mov_MwRv_Sw(); //What to do with this one? 0x5: lea_Gv_M(); 0x6: mov_Sw_MwRv(); diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index d1d1c1f01..acfe2f516 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -53,7 +53,11 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop MOV{ + mov "env.reg", "env.reg", "env.regm" +}; +''' #let {{ # class MOV(Inst): # "Mov ^0 ^0 ^1" From 548b121c1c33a870beb7379de29c14e9c2e8cf82 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:45:06 +0000 Subject: [PATCH 08/10] Flesh out the bitfields for prefixes. --HG-- extra : convert_revision : 0956b3d3532cba3856deda914d7cc708377b701b --- src/arch/x86/isa/bitfields.isa | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index c7ed02f2c..82fa4f25b 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -58,9 +58,21 @@ // Bitfield definitions. // -//Prefixes +//REX prefix def bitfield REX rex; +def bitfield REX_W rex.w; +def bitfield REX_R rex.r; +def bitfield REX_X rex.x; +def bitfield REX_B rex.b; + +//Legacy prefixes def bitfield LEGACY legacy; +def bitfield LEGACY_REPNE legacy.repne; +def bitfield LEGACY_REP legacy.rep; +def bitfield LEGACY_LOCK legacy.lock; +def bitfield LEGACY_ADDR legacy.addr; +def bitfield LEGACY_OP legacy.op; +def bitfield LEGACY_SEG legacy.seg; // Pieces of the opcode def bitfield OPCODE_NUM opcode.num; From baf145e0f537cafeaa756d1128e3507dfce4bd01 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:46:04 +0000 Subject: [PATCH 09/10] Reset the rex and legacy prefix components of the ExtMachInst as well. --HG-- extra : convert_revision : 832a324fec2d2b59f1c101d7fa72d7f670f0495d --- src/arch/x86/predecoder.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 65f951f44..c99b0cfb0 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -66,6 +66,8 @@ namespace X86ISA { origPC = basePC + offset; DPRINTF(Predecoder, "Setting origPC to %#x\n", origPC); + emi.rex = 0; + emi.legacy = 0; emi.opcode.num = 0; immediateCollected = 0; From 0d8d3f988f835e58e5e53b6ee2be871e7bff9132 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 12 Jun 2007 16:47:10 +0000 Subject: [PATCH 10/10] Make use of some of the REX prefix. --HG-- extra : convert_revision : 948eceb59a1cd9b02ad9355dd5894af0bbec4e83 --- src/arch/x86/isa/specialize.isa | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 3b4e09daa..fe3730b77 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -95,6 +95,9 @@ let {{ self.size = match.group("size") self.rsize = match.group("rsize") + ModRMRegIndex = "(MODRM_REG | (REX_R << 3))" + ModRMRMIndex = "(MODRM_RM | (REX_B << 3))" + # This function specializes the given piece of code to use a particular # set of argument types described by "opTypes". def specializeInst(Name, opTypes, env): @@ -121,14 +124,14 @@ let {{ raise Exception, "Problem parsing operand tag: %s" % opType.tag elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"): # Use the "reg" field of the ModRM byte to select the register - env.addReg("(uint8_t)MODRM_REG") + env.addReg(ModRMRegIndex) 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("(uint8_t)MODRM_RM") + regEnv.addReg(ModRMRMIndex) # This needs to refer to memory, but we'll fill in the details # later. It needs to take into account unaligned memory # addresses. @@ -149,7 +152,7 @@ let {{ elif opType.tag in ("PR", "R", "VR"): # There should probably be a check here to verify that mod # is equal to 11b - env.addReg("(uint8_t)MODRM_RM") + env.addReg(ModRMRMIndex) else: raise Exception, "Unrecognized tag %s." % opType.tag opTypes.pop(0)