X86: Make X86's microcode ROM actually do something.
authorGabe Black <gblack@eecs.umich.edu>
Mon, 13 Oct 2008 00:48:44 +0000 (17:48 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 13 Oct 2008 00:48:44 +0000 (17:48 -0700)
src/arch/x86/isa/includes.isa
src/arch/x86/isa/macroop.isa
src/arch/x86/isa/microasm.isa
src/arch/x86/isa/microops/base.isa
src/arch/x86/isa/rom.isa [new file with mode: 0644]
src/arch/x86/microcode_rom.hh

index 926e9185aac53d4f100c56be241bf1be54d0505a..e523b7e32c68a8df542e23d38e88fb1464378cc8 100644 (file)
@@ -113,6 +113,7 @@ output header {{
 output decoder {{
 #include "arch/x86/faults.hh"
 #include "arch/x86/floatregs.hh"
+#include "arch/x86/microcode_rom.hh"
 #include "arch/x86/miscregs.hh"
 #include "arch/x86/segmentregs.hh"
 #include "base/cprintf.hh"
index 4818b926cb65b224c245067f41ed1238b8d8a647..b851a92c752739233b5d5a4d429e2a32d80ebefa 100644 (file)
@@ -76,12 +76,13 @@ output header {{
         {
           protected:
             const uint32_t numMicroops;
+            X86ISA::EmulEnv emulEnv;
 
             //Constructor.
             Macroop(const char *mnem, ExtMachInst _machInst,
-                    uint32_t _numMicroops)
+                    uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv)
                         : StaticInst(mnem, _machInst, No_OpClass),
-                        numMicroops(_numMicroops)
+                        numMicroops(_numMicroops), emulEnv(_emulEnv)
             {
                 assert(numMicroops);
                 microops = new StaticInstPtr[numMicroops];
@@ -107,7 +108,20 @@ output header {{
                 return mnemonic;
             }
 
+          public:
             %(MacroExecPanic)s
+
+            ExtMachInst
+            getExtMachInst()
+            {
+                return machInst;
+            }
+
+            X86ISA::EmulEnv
+            getEmulEnv()
+            {
+                return emulEnv;
+            }
         };
 }};
 
@@ -139,7 +153,7 @@ def template MacroDeclare {{
 def template MacroConstructor {{
         inline X86Macroop::%(class_name)s::%(class_name)s(
                 ExtMachInst machInst, EmulEnv env)
-            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s)
+            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, env)
         {
             %(adjust_env)s;
             %(adjust_imm)s;
index 735a7722cbc84d9caa431e7f9c204c3a32b932c9..9a5019f10abc172a0b52011265b799372f7493b0 100644 (file)
 //Include code to build macroops in both C++ and python.
 ##include "macroop.isa"
 
+//Include code to fill out the microcode ROM in both C++ and python.
+##include "rom.isa"
+
 let {{
     import sys
     sys.path[0:0] = ["src/arch/x86/isa/"]
     from insts import microcode
     # print microcode
-    from micro_asm import MicroAssembler, Rom_Macroop, Rom
-    mainRom = Rom('main ROM')
+    from micro_asm import MicroAssembler, Rom_Macroop
+    mainRom = X86MicrocodeRom('main ROM')
     assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop)
     # Add in symbols for the microcode registers
     for num in range(15):
@@ -186,4 +189,7 @@ let {{
     assembler.symbols["st"] = stack_index
 
     macroopDict = assembler.assemble(microcode)
+
+    decoder_output += mainRom.getDefinition()
+    header_output += mainRom.getDeclaration()
 }};
index 75658a26c52e68f823136012efeee7bb638bf660..994e997d875502142e2cc8d315d72fad7b0a5b65 100644 (file)
@@ -69,6 +69,28 @@ let {{
 
 let {{
     class X86Microop(object):
+        generatorNameTemplate = "generate_%s_%d"
+
+        generatorTemplate = '''
+            StaticInstPtr
+            ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop)
+            {
+                static const char * mnemonic = romMnemonic;
+                static const ExtMachInst dummyExtMachInst;
+                static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1);
+
+                Macroop * macroop = dynamic_cast<Macroop *>(curMacroop.get());
+                const ExtMachInst &machInst =
+                    macroop ? macroop->getExtMachInst() : dummyExtMachInst;
+                const EmulEnv &env =
+                    macroop ? macroop->getEmulEnv() : dummyEmulEnv;
+                // env may not be used in the microop's constructor.
+                RegIndex reg = env.reg;
+                reg = reg;
+                return %s;
+            }
+        '''
 
         def __init__(self, name):
             self.name = name
@@ -91,4 +113,12 @@ let {{
         def getAllocator(self, mnemonic, *microFlags):
             return 'new %s(machInst, %s)' % \
                 (self.className, mnemonic, self.microFlagsText(microFlags))
+
+        def getGeneratorDef(self, micropc):
+            return self.generatorTemplate % \
+                (self.className, micropc, \
+                 self.getAllocator(True, False, False, False))
+
+        def getGenerator(self, micropc):
+            return self.generatorNameTemplate % (self.className, micropc)
 }};
diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa
new file mode 100644 (file)
index 0000000..7d3eb86
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (c) 2008 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: 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 holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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
+
+def template MicroRomConstructor {{
+
+    %(define_generators)s
+    const MicroPC X86ISA::MicrocodeRom::numMicroops = %(num_microops)s;
+
+    X86ISA::MicrocodeRom::MicrocodeRom()
+    {
+        using namespace RomLabels;
+        genFuncs = new GenFunc[numMicroops];
+        %(alloc_generators)s;
+    }
+}};
+
+let {{
+    from micro_asm import Rom
+
+    class X86MicrocodeRom(Rom):
+        def __init__(self, name):
+            super(X86MicrocodeRom, self).__init__(name)
+            self.directives = {}
+
+        def add_microop(self, mnemonic, microop):
+            microop.mnemonic = mnemonic
+            microop.micropc = len(self.microops)
+            self.microops.append(microop)
+
+
+        def getDeclaration(self):
+            declareLabels = "namespace RomLabels {\n"
+            for (label, microop) in self.labels.items():
+                declareLabels += "const static uint64_t label_%s = %d;\n" \
+                                  % (label, microop.micropc)
+            for (label, microop) in self.externs.items():
+                declareLabels += \
+                    "const static MicroPC extern_label_%s = %d;\n" \
+                        % (label, microop.micropc)
+            declareLabels += "}\n"
+            return declareLabels;
+
+        def getDefinition(self):
+            numMicroops = len(self.microops)
+            allocGenerators = ''
+            micropc = 0
+            define_generators = '''
+                namespace
+                {
+                    static const char romMnemonic[] = "Microcode_ROM";
+            '''
+            for op in self.microops:
+                define_generators += op.getGeneratorDef(micropc)
+                allocGenerators += "genFuncs[%d] = %s;\n" % \
+                        (micropc, op.getGenerator(micropc))
+                micropc += 1
+            define_generators += "}\n"
+            iop = InstObjParams(self.name, self.name, "MicrocodeRom",
+                                {"code" : "",
+                                 "define_generators" : define_generators,
+                                 "num_microops" : numMicroops,
+                                 "alloc_generators" : allocGenerators
+                                })
+            return MicroRomConstructor.subst(iop);
+}};
index 1495ff699e7670556ce7d728b964870f24809f28..f8ad410ce4d3f9465373194fe5ac515f962f3898 100644 (file)
 #ifndef __ARCH_X86_MICROCODE_ROM_HH__
 #define __ARCH_X86_MICROCODE_ROM_HH__
 
-#include "sim/microcode_rom.hh"
+#include "arch/x86/emulenv.hh"
+#include "cpu/static_inst.hh"
+
+namespace X86ISAInst
+{
+    class MicrocodeRom
+    {
+      protected:
+
+        typedef StaticInstPtr (*GenFunc)(StaticInstPtr);
+
+        static const MicroPC numMicroops;
+
+        GenFunc * genFuncs;
+
+      public:
+        //Constructor.
+        MicrocodeRom();
+
+        //Destructor.
+        ~MicrocodeRom()
+        {
+            delete [] genFuncs;
+        }
+
+        StaticInstPtr
+        fetchMicroop(MicroPC microPC, StaticInstPtr curMacroop)
+        {
+            microPC = normalMicroPC(microPC);
+            assert(microPC < numMicroops);
+            return genFuncs[microPC](curMacroop);
+        }
+    };
+}
 
 namespace X86ISA
 {
-    using ::MicrocodeRom;
+    using X86ISAInst::MicrocodeRom;
 }
 
 #endif // __ARCH_X86_MICROCODE_ROM_HH__