X86: Autogenerate macroop generateDisassemble function.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 7 Jan 2009 06:55:27 +0000 (22:55 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 7 Jan 2009 06:55:27 +0000 (22:55 -0800)
src/arch/x86/insts/macroop.hh
src/arch/x86/isa/macroop.isa
src/arch/x86/isa/microops/base.isa
src/arch/x86/isa/microops/debug.isa
src/arch/x86/isa/microops/fpop.isa
src/arch/x86/isa/microops/ldstop.isa
src/arch/x86/isa/microops/limmop.isa
src/arch/x86/isa/microops/regop.isa
src/arch/x86/isa/microops/seqop.isa
src/arch/x86/isa/microops/specop.isa
src/arch/x86/isa/specialize.isa

index d89a693baac6b0ce61a03ee01a7709b8c64d7f08..d6925a1a5fb5f752ffbcf200a21de0b8d690a799 100644 (file)
 namespace X86ISA
 {
 // Base class for combinationally generated macroops
-class MacroopBase : public StaticInst
+class MacroopBase : public X86StaticInst
 {
   protected:
+    const char *macrocodeBlock;
+
     const uint32_t numMicroops;
-    X86ISA::EmulEnv emulEnv;
+    X86ISA::EmulEnv env;
 
     //Constructor.
     MacroopBase(const char *mnem, ExtMachInst _machInst,
-            uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv)
-                StaticInst(mnem, _machInst, No_OpClass),
-                numMicroops(_numMicroops), emulEnv(_emulEnv)
+            uint32_t _numMicroops, X86ISA::EmulEnv _env) :
+                X86StaticInst(mnem, _machInst, No_OpClass),
+                numMicroops(_numMicroops), env(_env)
     {
         assert(numMicroops);
         microops = new StaticInstPtr[numMicroops];
@@ -95,8 +97,8 @@ class MacroopBase : public StaticInst
         return microops[microPC];
     }
 
-    std::string generateDisassembly(Addr pc,
-            const SymbolTable *symtab) const
+    std::string
+    generateDisassembly(Addr pc, const SymbolTable *symtab) const
     {
         return mnemonic;
     }
@@ -111,7 +113,7 @@ class MacroopBase : public StaticInst
     X86ISA::EmulEnv
     getEmulEnv()
     {
-        return emulEnv;
+        return env;
     }
 };
 }
index c5134f336fc5cb2ba71fa9feffc3f36ab9102fdc..8eaf5f7867c8bbbf7fb5f6a2dcf182e1f17f9bcd 100644 (file)
@@ -76,8 +76,8 @@ output header {{
         {
           public:
             Macroop(const char *mnem, ExtMachInst _machInst,
-                    uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv)
-                        : MacroopBase(mnem, _machInst, _numMicroops, _emulEnv)
+                    uint32_t _numMicroops, X86ISA::EmulEnv _env)
+                        : MacroopBase(mnem, _machInst, _numMicroops, _env)
             {}
             %(MacroExecPanic)s
         };
@@ -102,22 +102,42 @@ def template MacroDeclare {{
                 %(declareLabels)s
               public:
                 // Constructor.
-                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
+                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
+
+                std::string
+                generateDisassembly(Addr pc, const SymbolTable *symtab) const;
             };
         };
 }};
 
+def template MacroDisassembly {{
+    std::string
+    X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
+            const SymbolTable *symtab) const
+    {
+        std::stringstream out;
+        out << mnemonic << "\t";
+
+        int regSize = %(regSize)s;
+        %(disassembly)s
+        // Shut up gcc.
+        regSize = regSize;
+        return out.str();
+    }
+}};
+
 // Basic instruction class constructor template.
 def template MacroConstructor {{
         inline X86Macroop::%(class_name)s::%(class_name)s(
-                ExtMachInst machInst, EmulEnv env)
-            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, env)
+                ExtMachInst machInst, EmulEnv _env)
+            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
         {
             %(adjust_env)s;
             %(adjust_imm)s;
             %(adjust_disp)s;
             %(do_modrm)s;
             %(constructor)s;
+            const char *macrocodeBlock = "%(class_name)s";
             //alloc_microops is the code that sets up the microops
             //array in the parent class.
             %(alloc_microops)s;
@@ -158,7 +178,12 @@ let {{
                 adjustedDisp = adjustedDisp;
             '''
         def getAllocator(self, env):
-            return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
+            return "new X86Macroop::%s(machInst, %s)" % \
+                    (self.name, env.getAllocator())
+        def getMnemonic(self):
+            mnemonic = self.name.lower()
+            mnemonic = re.match(r'[^_]*', mnemonic).group(0)
+            return mnemonic
         def getDeclaration(self):
             #FIXME This first parameter should be the mnemonic. I need to
             #write some code which pulls that out
@@ -166,12 +191,12 @@ let {{
             for (label, microop) in self.labels.items():
                 declareLabels += "const static uint64_t label_%s = %d;\n" \
                                   % (label, microop.micropc)
-            iop = InstObjParams(self.name, self.name, "Macroop",
+            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
                     {"code" : "",
                      "declareLabels" : declareLabels
                     })
             return MacroDeclare.subst(iop);
-        def getDefinition(self):
+        def getDefinition(self, env):
             #FIXME This first parameter should be the mnemonic. I need to
             #write some code which pulls that out
             numMicroops = len(self.microops)
@@ -184,14 +209,28 @@ let {{
                     (micropc, op.getAllocator(True, not isLast,
                                               micropc == 0, isLast))
                 micropc += 1
-            iop = InstObjParams(self.name, self.name, "Macroop",
+            if env.useStackSize:
+                useStackSize = "true"
+            else:
+                useStackSize = "false"
+            if env.memoryInst:
+                memoryInst = "true"
+            else:
+                memoryInst = "false"
+            regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
+                         env.stackSize :
+                         env.dataSize)''' % (useStackSize, memoryInst)
+            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
                                 {"code" : "", "num_microops" : numMicroops,
                                  "alloc_microops" : allocMicroops,
                                  "adjust_env" : self.adjust_env,
                                  "adjust_imm" : self.adjust_imm,
                                  "adjust_disp" : self.adjust_disp,
+                                 "disassembly" : env.disassembly,
+                                 "regSize" : regSize,
                                  "do_modrm" : self.doModRM})
-            return MacroConstructor.subst(iop);
+            return MacroConstructor.subst(iop) + \
+                   MacroDisassembly.subst(iop);
 }};
 
 let {{
@@ -207,6 +246,16 @@ let {{
             self.dataSize = "OPSIZE"
             self.stackSize = "STACKSIZE"
             self.doModRM = False
+            self.disassembly = ""
+            self.firstArgument = True
+            self.useStackSize = False
+            self.memoryInst = False
+
+        def addToDisassembly(self, code):
+            if not self.firstArgument:
+                self.disassembly += "out << \", \";\n"
+            self.firstArgument = False
+            self.disassembly += code
 
         def getAllocator(self):
             if self.size == 'b':
@@ -264,7 +313,7 @@ let {{
             if env.doModRM:
                 macroop.doModRM = doModRMString
             blocks.header_output = macroop.getDeclaration()
-            blocks.decoder_output = macroop.getDefinition()
+            blocks.decoder_output = macroop.getDefinition(env)
             macroop.declared = True
         blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
         return blocks
index 2b73cf563233220e0d0e7751d2079f3b403d1efe..f1007bf7123143c3ecbc102fdc940ae651a749ad 100644 (file)
@@ -76,7 +76,7 @@ let {{
             StaticInstPtr
             ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop)
             {
-                static const char * mnemonic = romMnemonic;
+                static const char *macrocodeBlock = romMnemonic;
                 static const ExtMachInst dummyExtMachInst;
                 static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1);
 
index 895e971998a0e5daaeed14e551dd89aa87de6fd1..38fee59bbab1a0891011823d512ec848231946f6 100644 (file)
@@ -183,7 +183,7 @@ let {{
                 self.cond = "0"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, "%(message)s", %(cc)s)''' % {
                 "class_name" : self.className,
                 "flags" : self.microFlagsText(microFlags),
index 2919aa277f99301eb02f93117a8e4bdfb5de2266..d4acfdbf41827c47d29c693bd4922d0ed6d508c2 100644 (file)
@@ -245,7 +245,7 @@ let {{
                 self.className += "Top"
 
         def getAllocator(self, *microFlags):
-            return '''new %(class_name)s(machInst, mnemonic
+            return '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(src1)s, %(src2)s, %(dest)s,
                     %(dataSize)s, %(spm)d)''' % {
                 "class_name" : self.className,
index 30a7c8801098d8a33f0cfd93c3686db8aef1f1f2..8a0af14bec123952e18d4de75258bc4deb6951a4 100644 (file)
@@ -362,7 +362,7 @@ let {{
             self.addressSize = addressSize
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(scale)s, %(index)s, %(base)s,
                     %(disp)s, %(segment)s, %(data)s,
                     %(dataSize)s, %(addressSize)s)''' % {
index 6686444fd1711933775f3095df5a3b4c2b7eb5d0..4e75ab8b01bbb88012fa5810f255a5359149e82b 100644 (file)
@@ -154,7 +154,7 @@ let {{
             self.dataSize = dataSize
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % {
                 "class_name" : self.className,
                 "mnemonic" : self.mnemonic,
index 944d5e9ec61f2a4c17f4d67fde0287fd6b78d03d..492452a51220779b544e312cb0a8ade722354122 100644 (file)
@@ -438,7 +438,7 @@ let {{
             className = self.className
             if self.mnemonic == self.base_mnemonic + 'i':
                 className += "Imm"
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(src1)s, %(op2)s, %(dest)s,
                     %(dataSize)s, %(ext)s)''' % {
                 "class_name" : className,
index f03094f668cd736510711d71ae51ae3f28a96b03..332519b87359d1a720f2c0035109066ebdea57d8 100644 (file)
@@ -181,7 +181,7 @@ let {{
                 self.cond = "0"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(target)s, %(cc)s)''' % {
                 "class_name" : self.className,
                 "flags" : self.microFlagsText(microFlags),
index ad14b54a323524d51a1823e933116d53dab21b5d..c6e172ef10d532a0dec293ed00db2222bf6428ec 100644 (file)
@@ -230,7 +230,7 @@ let {{
                 self.cond = "0"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(fault)s, %(cc)s)''' % {
                 "class_name" : self.className,
                 "flags" : self.microFlagsText(microFlags),
@@ -257,7 +257,7 @@ let {{
             pass
 
         def getAllocator(self, *microFlags):
-            return "new MicroHalt(machInst, mnemonic %s)" % \
+            return "new MicroHalt(machInst, macrocodeBlock %s)" % \
                     self.microFlagsText(microFlags)
 
     microopClasses["halt"] = Halt
index abf734307fd2b034d7e0d5c4f1758ed0de669943..b7436347071da4f13897b80231eec7c2e6cba0fa 100644 (file)
@@ -86,8 +86,17 @@ let {{
 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))
+        env.memoryInst = True
+        normEnv = copy.copy(env)
+        normEnv.addToDisassembly(
+                '''printMem(out, env.seg, env.scale, env.index, env.base,
+                    machInst.displacement, env.addressSize, false);''')
+        normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), normEnv)
+        ripEnv = copy.copy(env)
+        ripEnv.addToDisassembly(
+                '''printMem(out, env.seg, 1, 0, 0,
+                    machInst.displacement, env.addressSize, true);''')
+        ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), ripEnv)
 
         blocks = OutputBlocks()
         blocks.append(normBlocks)
@@ -138,12 +147,17 @@ let {{
                 #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)
+                    regString = "INTREG_R%sX" % opType.reg
                 else:
-                    env.addReg("INTREG_R%s" % opType.reg)
+                    regString = "INTREG_R%s" % opType.reg
+                env.addReg(regString)
+                env.addToDisassembly(
+                        "printReg(out, %s, regSize);\n" % regString)
                 Name += "_R"
             elif opType.tag == "B":
                 # This refers to registers whose index is encoded as part of the opcode
+                env.addToDisassembly(
+                        "printReg(out, %s, regSize);\n" % InstRegIndex)
                 Name += "_R"
                 env.addReg(InstRegIndex)
             elif opType.tag == "M":
@@ -156,24 +170,34 @@ let {{
             elif opType.tag == "C":
                 # A control register indexed by the "reg" field
                 env.addReg(ModRMRegIndex)
+                env.addToDisassembly(
+                        "ccprintf(out, \"CR%%d\", %s);\n" % ModRMRegIndex)
                 Name += "_C"
             elif opType.tag == "D":
                 # A debug register indexed by the "reg" field
                 env.addReg(ModRMRegIndex)
+                env.addToDisassembly(
+                        "ccprintf(out, \"DR%%d\", %s);\n" % ModRMRegIndex)
                 Name += "_D"
             elif opType.tag == "S":
                 # A segment selector register indexed by the "reg" field
                 env.addReg(ModRMRegIndex)
+                env.addToDisassembly(
+                        "printSegment(out, %s);\n" % ModRMRegIndex)
                 Name += "_S"
             elif opType.tag in ("G", "P", "T", "V"):
                 # Use the "reg" field of the ModRM byte to select the register
                 env.addReg(ModRMRegIndex)
+                env.addToDisassembly(
+                        "printReg(out, %s, regSize);\n" % ModRMRegIndex)
                 Name += "_R"
             elif opType.tag in ("E", "Q", "W"):
                 # This might refer to memory or to a register. We need to
                 # divide it up farther.
                 regEnv = copy.copy(env)
                 regEnv.addReg(ModRMRMIndex)
+                regEnv.addToDisassembly(
+                        "printReg(out, %s, regSize);\n" % ModRMRMIndex)
                 # This refers to memory. The macroop constructor should set up
                 # modrm addressing.
                 memEnv = copy.copy(env)
@@ -183,6 +207,8 @@ let {{
                            (doRipRelativeDecode, Name, copy.copy(opTypes), memEnv))
             elif opType.tag in ("I", "J"):
                 # Immediates
+                env.addToDisassembly(
+                        "ccprintf(out, \"%#x\", machInst.immediate);\n")
                 Name += "_I"
             elif opType.tag == "O":
                 # Immediate containing a memory offset
@@ -190,10 +216,22 @@ let {{
             elif opType.tag in ("PR", "R", "VR"):
                 # Non register modrm settings should cause an error
                 env.addReg(ModRMRMIndex)
+                env.addToDisassembly(
+                        "printReg(out, %s, regSize);\n" % ModRMRMIndex)
                 Name += "_R"
             elif opType.tag in ("X", "Y"):
                 # This type of memory addressing is for string instructions.
                 # They'll use the right index and segment internally.
+                if opType.tag == "X":
+                    env.addToDisassembly(
+                            '''printMem(out, env.seg,
+                                1, X86ISA::ZeroReg, X86ISA::INTREG_RSI, 0,
+                                env.addressSize, false);''')
+                else:
+                    env.addToDisassembly(
+                            '''printMem(out, SEGMENT_REG_ES,
+                                1, X86ISA::ZeroReg, X86ISA::INTREG_RDI, 0,
+                                env.addressSize, false);''')
                 Name += "_M"
             else:
                 raise Exception, "Unrecognized tag %s." % opType.tag