(header_output,
      decoder_output,
      decode_block,
-     exec_output) = doInst(name, Name, list(opTypeSet))
+     exce_output) = doInst(name, Name, list(opTypeSet)).makeList()
 }};
 
 def format MultiInst(switchVal, *opTypeSets) {{
     (header_output,
      decoder_output,
      decode_block,
-     exec_output) = doSplitDecode(name, Name, doInst, switchVal, switcher)
+     exec_output) = doSplitDecode(name, Name, doInst, switchVal, switcher).makeList()
 }};
 
 //
 // Authors: Gabe Black
 
+//////////////////////////////////////////////////////////////////////////////
+//
+//  Architecture independent
+//
+
 // Execute method for macroops.
 def template MacroExecPanic {{
         Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
         {
             panic("Tried to execute macroop directly!");
-            M5_DUMMY_RETURN
+            return NoFault;
         }
 }};
 
 output header {{
 
-        // Base class for most macroops, except ones that need to commit as
-        // they go.
-        class X86MacroInst : public StaticInst
+        // Base class for macroops
+        class MacroOp : public StaticInst
         {
           protected:
             const uint32_t numMicroOps;
 
             //Constructor.
-            X86MacroInst(const char *mnem, ExtMachInst _machInst,
+            MacroOp(const char *mnem, ExtMachInst _machInst,
                     uint32_t _numMicroOps)
                         : StaticInst(mnem, _machInst, No_OpClass),
                         numMicroOps(_numMicroOps)
                 flags[IsMacroOp] = true;
             }
 
-            ~X86MacroInst()
+            ~MacroOp()
             {
                 delete [] microOps;
             }
                 return microOps[microPC];
             }
 
+            std::string generateDisassembly(Addr pc,
+                    const SymbolTable *symtab) const
+            {
+                return mnemonic;
+            }
+
             %(MacroExecPanic)s
         };
 }};
 
+// Basic instruction class declaration template.
+def template MacroDeclare {{
+        /**
+         * Static instruction class for "%(mnemonic)s".
+         */
+        class %(class_name)s : public %(base_class)s
+        {
+          public:
+            // Constructor.
+            %(class_name)s(ExtMachInst machInst);
+        };
+}};
+
 // Basic instruction class constructor template.
 def template MacroConstructor {{
         inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
         }
 }};
 
+//////////////////////////////////////////////////////////////////////////////
+//
+//  X86 specific
+//
+
 let {{
     def genMacroOp(name, Name, opSeq):
-        baseClass = 'X86MacroInst'
-        numMicroOps = len(opSeq.ops)
+        numMicroOps = len(opSeq)
         allocMicroOps = ''
         micropc = 0
-        for op in opSeq.ops:
+        for op in opSeq:
             allocMicroOps += \
                 "microOps[%d] = %s;\n" % \
-                (micropc, op.getAllocator(True, op.delayed,
+                (micropc, op.getAllocator('"' + name + '"', True, False, #op.delayed,
                                           micropc == 0,
                                           micropc == numMicroOps - 1))
             micropc += 1
-        iop = InstObjParams(name, Name, baseClass,
+        iop = InstObjParams(name, Name, 'MacroOp',
                 {'code' : '', 'num_micro_ops' : numMicroOps,
                 'alloc_micro_ops' : allocMicroOps})
-        header_output = BasicDeclare.subst(iop)
+        header_output = MacroDeclare.subst(iop)
         decoder_output = MacroConstructor.subst(iop)
         decode_block = BasicDecode.subst(iop)
         exec_output = ''
 
                     text += ", false"
             return text
 
-        def getAllocator(self, *microFlags):
+        def getAllocator(self, mnemonic, *microFlags):
             args = ''
             signature = "<"
             emptySig = True
                 else:
                     raise Exception, "Unrecognized operand type."
             signature += ">"
-            return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
+            return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
 }};
 
 let{{
         # the beginning of the line, so the previous component is stripped
         # before continuing.
         labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
-        lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$')
+        lineRe = re.compile(r'^(?P<line>..*)(\n|$)')
         classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
         # This recognizes three different flavors of operands:
         # 1. Raw decimal numbers composed of digits between 0 and 9
             # Get a line and seperate it from the rest of the code
             line = lineMatch.group("line")
             orig_line = line
-            # print "Parsing line %s" % line
+            #print "Parsing line %s" % line
             code = lineRe.sub('', code, 1)
 
             # Find the label, if any
             labelMatch = labelRe.search(line)
             if labelMatch != None:
                 statement.label = labelMatch.group("label")
-                # print "Found label %s." % statement.label
+                #print "Found label %s." % statement.label
             # Clear the label from the statement
             line = labelRe.sub('', line, 1)
 
                         % orig_line
             else:
                 statement.className = classMatch.group("className")
-                # print "Found class name %s." % statement.className
+                #print "Found class name %s." % statement.className
 
             # Clear the class name from the statement
             line = classRe.sub('', line, 1)
                     print "Problem parsing operand in statement: %s" \
                             % orig_line
                 line = opRe.sub('', line, 1)
-                # print "Found operand %s." % statement.args[-1]
+                #print "Found operand %s." % statement.args[-1]
                 opMatch = opRe.search(line)
-            # print "Found operands", statement.args
+            #print "Found operands", statement.args
 
             # Add this statement to our collection
             statements.append(statement)
                     arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
             micropc += 1
 
+        if len(statements) == 0:
+            raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code
+
         # If we can implement this instruction with exactly one microop, just
         # use that directly.
         if len(statements) == 1:
             decode_block = "return %s;" % \
-                            statements[0].getAllocator()
+                            statements[0].getAllocator('"' + name + '"')
             return ('', '', decode_block, '')
         else:
             # Build a macroop to contain the sequence of microops we've
 
     class X86MicroOpBase : public X86StaticInst
     {
       protected:
+        const char * instMnem;
         uint8_t opSize;
         uint8_t addrSize;
 
-        X86MicroOpBase(bool isMicro, bool isDelayed,
+        X86MicroOpBase(ExtMachInst _machInst,
+                const char *mnem, const char *_instMnem,
+                bool isMicro, bool isDelayed,
                 bool isFirst, bool isLast,
-                const char *mnem, ExtMachInst _machInst,
                 OpClass __opClass) :
-            X86StaticInst(mnem, _machInst, __opClass)
+            X86StaticInst(mnem, _machInst, __opClass),
+            instMnem(_instMnem)
         {
             flags[IsMicroOp] = isMicro;
             flags[IsDelayedCommit] = isDelayed;
             flags[IsFirstMicroOp] = isFirst;
             flags[IsLastMicroOp] = isLast;
         }
+
+        std::string generateDisassembly(Addr pc,
+                const SymbolTable *symtab) const
+        {
+            std::stringstream ss;
+
+            ccprintf(ss, "\t%s.%s", instMnem, mnemonic);
+
+            return ss.str();
+        }
     };
 }};
 
 }};
 
 // A tmeplate for building a specialized version of the microcode
-// instruction which knows specifies which arguments it wants
+// instruction which specifies which arguments it wants
 def template MicroOpDeclare {{
     template<>
     class %(class_name)s%(signature)s : public X86MicroOpBase
         void buildMe();
 
       public:
-        %(class_name)s(bool isMicro, bool isDelayed,
-                bool isFirst, bool isLast,
-                ExtMachInst _machInst %(param_arg_dec)s);
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem,
+                bool isMicro, bool isDelayed,
+                bool isFirst, bool isLast
+                %(param_arg_dec)s);
 
-        %(class_name)s(ExtMachInst _machInst %(param_arg_dec)s);
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem
+                %(param_arg_dec)s);
 
         %(BasicExecDeclare)s
     };
     }
 
     inline %(class_name)s%(signature)s::%(class_name)s(
-            ExtMachInst machInst %(param_arg_dec)s) :
-        %(base_class)s(false, false, false, false,
-                "%(mnemonic)s", machInst, %(op_class)s)
+            ExtMachInst machInst, const char * instMnem
+            %(param_arg_dec)s) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                false, false, false, false, %(op_class)s)
                 %(param_init)s
     {
         buildMe();
     }
 
     inline %(class_name)s%(signature)s::%(class_name)s(
-            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
-            ExtMachInst machInst %(param_arg_dec)s)
-        : %(base_class)s(isMicro, isDelayed, isFirst, isLast,
-                "%(mnemonic)s", machInst, %(op_class)s)
+            ExtMachInst machInst, const char * instMnem,
+            bool isMicro, bool isDelayed, bool isFirst, bool isLast
+            %(param_arg_dec)s)
+        : %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                isMicro, isDelayed, isFirst, isLast, %(op_class)s)
                 %(param_init)s
     {
         buildMe();
 
     # builder is called on the exploded contents of "vals" values to generate
     # whatever code should be used.
     def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
-        header_output = ''
-        decoder_output = ''
-        decode_block = 'switch(%s) {\n' % switchVal
-        exec_output = ''
+        blocks = OutputBlocks()
+        blocks.decode_block += 'switch(%s) {\n' % switchVal
         for (val, todo) in vals.items():
-            (new_header_output,
-             new_decoder_output,
-             new_decode_block,
-             new_exec_output) = builder(name, Name, *todo)
-            header_output += new_header_output
-            decoder_output += new_decoder_output
-            decode_block += '\tcase %s: %s\n' % (val, new_decode_block)
-            exec_output += new_exec_output
+            built = builder(name, Name, *todo)
+            built.decode_block = '\tcase %s: %s\n' % (val, built.decode_block)
+            blocks.append(built)
         if default:
-            (new_header_output,
-             new_decoder_output,
-             new_decode_block,
-             new_exec_output) = builder(name, Name, *default)
-            header_output += new_header_output
-            decoder_output += new_decoder_output
-            decode_block += '\tdefault: %s\n' % new_decode_block
-            exec_output += new_exec_output
-        decode_block += '}\n'
-        return (header_output, decoder_output, decode_block, exec_output)
+            built = builder(name, Name, *default)
+            built.decode_block = '\tdefault: %s\n' % built.decode_block
+            blocks.append(built)
+        blocks.decode_block += '}\n'
+        return blocks
 }};
 
 let {{
                 # This needs to refer to memory, but we'll fill in the details
                 # later. It needs to take into account unaligned memory
                 # addresses.
+                code = "GenFault ${new UnimpInstFault}\n" + code
                 memCode = opRe.sub("%0", code)
                 memTypes = copy.copy(opTypes)
                 memTypes.pop(-1)
                 # This needs to refer to memory, but we'll fill in the details
                 # later. It needs to take into account unaligned memory
                 # addresses.
+                code = "GenFault ${new UnimpInstFault}\n" + code
                 code = opRe.sub("%0", code)
             elif opType.tag in ("PR", "R", "VR"):
                 # There should probably be a check here to verify that mod
         # At this point, we've built up "code" to have all the necessary extra
         # instructions needed to implement whatever types of operands were
         # specified. Now we'll assemble it it into a StaticInst.
-        return assembleMicro(name, Name, code)
+        blocks = OutputBlocks()
+        blocks.append(assembleMicro(name, Name, code))
+        return blocks
 }};