Significant changes to ISA description to completely factor
[gem5.git] / arch / alpha / isa_desc
index 89ec05c0e26a5c3e17e8614160128d5ffbd06903..f964101df774294099f32ebc2017782084fd1d89 100644 (file)
@@ -1,41 +1,67 @@
 // -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
 //
 // Alpha ISA description file.
 //
+////////////////////////////////////////////////////////////////////
 
-let {{
-    global rcs_id
-    rcs_id = "$Id$"
-}};
 
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
 
+output header {{
 #include <sstream>
 #include <iostream>
 #include <iomanip>
 
+#include "cpu/static_inst.hh"
+#include "mem/mem_req.hh"  // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh"  // for Jump::branchTarget()
+
 #include <math.h>
 #if defined(linux)
 #include <fenv.h>
 #endif
+}};
 
-#include "cpu/static_inst.hh"
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "cpu/full_cpu/op_class.hh"
+output exec {{
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
 
-#include "cpu/exec_context.hh"
-#include "cpu/simple_cpu/simple_cpu.hh"
-#include "cpu/full_cpu/spec_state.hh"
-#include "cpu/full_cpu/full_cpu.hh"
+#include "cpu/base_cpu.hh"
 #include "cpu/exetrace.hh"
-#include "sim/annotation.hh"
+#include "sim/sim_exit.hh"
 
 #ifdef FULL_SYSTEM
-#include "targetarch/ev5.hh"
+#include "arch/alpha/ev5.hh"
+#include "arch/alpha/pseudo_inst.hh"
 #endif
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement.  Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
 
 namespace AlphaISA;
 
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
 // Universal (format-independent) fields
 def bitfield OPCODE    <31:26>;
 def bitfield RA                <25:21>;
@@ -94,68 +120,48 @@ def bitfield HW_IPR_IDX <15:0>;     // IPR index
 // M5 instructions
 def bitfield M5FUNC <7:0>;
 
-let {{
-    global operandTypeMap
-    operandTypeMap = {
-       'sb' : ('signed int', 8),
-       'ub' : ('unsigned int', 8),
-       'sw' : ('signed int', 16),
-       'uw' : ('unsigned int', 16),
-       'sl' : ('signed int', 32),
-       'ul' : ('unsigned int', 32),
-       'sq' : ('signed int', 64),
-       'uq' : ('unsigned int', 64),
-       'sf' : ('float', 32),
-       'df' : ('float', 64)
-    }
-
-    global operandTraitsMap
-    operandTraitsMap = {
-       # Int regs default to unsigned, but code should not count on this.
-       # For clarity, descriptions that depend on unsigned behavior should
-       # explicitly specify '.uq'.
-       'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
-       'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
-       'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
-       'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
-       'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
-       'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
-       'Mem': MemOperandTraits('uq', None,
-                               ('IsMemRef', 'IsLoad', 'IsStore'), 4),
-       'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
-       'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
-       'FPCR':  ControlRegOperandTraits('uq', 'Fpcr', None, 1),
-       # The next two are hacks for non-full-system call-pal emulation
-       'R0':  IntRegOperandTraits('uq', '0', None, 1),
-       'R16': IntRegOperandTraits('uq', '16', None, 1),
-    }
+def operand_types {{
+    'sb' : ('signed int', 8),
+    'ub' : ('unsigned int', 8),
+    'sw' : ('signed int', 16),
+    'uw' : ('unsigned int', 16),
+    'sl' : ('signed int', 32),
+    'ul' : ('unsigned int', 32),
+    'sq' : ('signed int', 64),
+    'uq' : ('unsigned int', 64),
+    'sf' : ('float', 32),
+    'df' : ('float', 64)
+}};
 
-    defineDerivedOperandVars()
+def operands {{
+    # Int regs default to unsigned, but code should not count on this.
+    # For clarity, descriptions that depend on unsigned behavior should
+    # explicitly specify '.uq'.
+    'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
+    'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
+    'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
+    'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
+    'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
+    'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
+    'Mem': MemOperandTraits('uq', None,
+                            ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+    'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
+    'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
+    'FPCR':  ControlRegOperandTraits('uq', 'Fpcr', None, 1),
+    # The next two are hacks for non-full-system call-pal emulation
+    'R0':  IntRegOperandTraits('uq', '0', None, 1),
+    'R16': IntRegOperandTraits('uq', '16', None, 1)
 }};
 
-declare {{
-// just temporary, while comparing with old code for debugging
-// #define SS_COMPATIBLE_DISASSEMBLY
+////////////////////////////////////////////////////////////////////
+//
+// Basic instruction classes/templates/formats etc.
+//
 
-    /// Check "FP enabled" machine status bit.  Called when executing any FP
-    /// instruction in full-system mode.
-    /// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
-    /// if not.  Non-full-system mode: always returns No_Fault.
-#ifdef FULL_SYSTEM
-    inline Fault checkFpEnableFault(ExecContext *xc)
-    {
-       Fault fault = No_Fault; // dummy... this ipr access should not fault
-       if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
-           fault = Fen_Fault;
-       }
-       return fault;
-    }
-#else
-    inline Fault checkFpEnableFault(ExecContext *xc)
-    {
-       return No_Fault;
-    }
-#endif
+output header {{
+// uncomment the following to get SimpleScalar-compatible disassembly
+// (useful for diffing output traces).
+// #define SS_COMPATIBLE_DISASSEMBLY
 
     /**
      * Base class for all Alpha static instructions.
@@ -183,47 +189,60 @@ declare {{
 
        /// Print a register name for disassembly given the unique
        /// dependence tag number (FP or int).
-       void printReg(std::ostream &os, int reg)
-       {
-           if (reg < FP_Base_DepTag) {
-               ccprintf(os, "r%d", reg);
-           }
-           else {
-               ccprintf(os, "f%d", reg - FP_Base_DepTag);
-           }
-       }
+       void printReg(std::ostream &os, int reg);
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           std::stringstream ss;
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
 
-           ccprintf(ss, "%-10s ", mnemonic);
+output decoder {{
+    void
+    AlphaStaticInst::printReg(std::ostream &os, int reg)
+    {
+       if (reg < FP_Base_DepTag) {
+           ccprintf(os, "r%d", reg);
+       }
+       else {
+           ccprintf(os, "f%d", reg - FP_Base_DepTag);
+       }
+    }
 
-           // just print the first two source regs... if there's
-           // a third one, it's a read-modify-write dest (Rc),
-           // e.g. for CMOVxx
-           if (_numSrcRegs > 0) {
-               printReg(ss, _srcRegIdx[0]);
-           }
-           if (_numSrcRegs > 1) {
-               ss << ",";
-               printReg(ss, _srcRegIdx[1]);
-           }
+    std::string
+    AlphaStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       std::stringstream ss;
 
-           // just print the first dest... if there's a second one,
-           // it's generally implicit
-           if (_numDestRegs > 0) {
-               if (_numSrcRegs > 0)
-                   ss << ",";
-               printReg(ss, _destRegIdx[0]);
-           }
+       ccprintf(ss, "%-10s ", mnemonic);
 
-           return ss.str();
+       // just print the first two source regs... if there's
+       // a third one, it's a read-modify-write dest (Rc),
+       // e.g. for CMOVxx
+       if (_numSrcRegs > 0) {
+           printReg(ss, _srcRegIdx[0]);
        }
-    };
+       if (_numSrcRegs > 1) {
+           ss << ",";
+           printReg(ss, _srcRegIdx[1]);
+       }
+
+       // just print the first dest... if there's a second one,
+       // it's generally implicit
+       if (_numDestRegs > 0) {
+           if (_numSrcRegs > 0)
+               ss << ",";
+           printReg(ss, _destRegIdx[0]);
+       }
+
+       return ss.str();
+    }
 }};
 
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+    Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *);
+}};
 
+// Basic instruction class declaration template.
 def template BasicDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -232,54 +251,47 @@ def template BasicDeclare {{
     {
       public:
        /// Constructor.
-       %(class_name)s(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
-       {
-           %(constructor)s;
-       }
-
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_rd)s;
-           %(code)s;
+       %(class_name)s(MachInst machInst);
 
-           if (fault == No_Fault) {
-               %(simple_wb)s;
-           }
-
-           return fault;
-       }
+       %(BasicExecDeclare)s
+    };
+}};
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           DynInst *memAccessObj __attribute__((unused)) = dynInst;
-           Fault fault = No_Fault;
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+    inline %(class_name)s::%(class_name)s(MachInst machInst)
+        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+    {
+       %(constructor)s;
+    }
+}};
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_rd)s;
-           %(code)s;
+// Basic instruction class execute method template.
+def template BasicExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                                 Trace::InstRecord *traceData)
+    {
+       Fault fault = No_Fault;
 
-           if (fault == No_Fault) {
-               %(dtld_wb)s;
-           }
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_rd)s;
+       %(code)s;
 
-           return fault;
+       if (fault == No_Fault) {
+           %(op_wb)s;
        }
-    };
+
+       return fault;
+    }
 }};
 
+// Basic decode template.
 def template BasicDecode {{
     return new %(class_name)s(machInst);
 }};
 
+// Basic decode template, passing mnemonic in as string arg to constructor.
 def template BasicDecodeWithMnemonic {{
     return new %(class_name)s("%(mnemonic)s", machInst);
 }};
@@ -287,14 +299,20 @@ def template BasicDecodeWithMnemonic {{
 // The most basic instruction format... used only for a few misc. insts
 def format BasicOperate(code, *flags) {{
     iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
 
 
 ////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
 
-declare {{
+output header {{
     /**
      * Static instruction class for no-ops.  This is a leaf class.
      */
@@ -314,27 +332,21 @@ declare {{
 
        ~Nop() { }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           return No_Fault;
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           return No_Fault;
-       }
+       %(BasicExecDeclare)s
+    };
+}};
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
+output decoder {{
+    std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
 #ifdef SS_COMPATIBLE_DISASSEMBLY
-           return originalDisassembly;
+       return originalDisassembly;
 #else
-           return csprintf("%-10s (%s)", "nop", originalDisassembly);
+       return csprintf("%-10s (%s)", "nop", originalDisassembly);
 #endif
-       }
-    };
+    }
 
     /// Helper function for decoding nops.  Substitute Nop object
     /// for original inst passed in as arg (and delete latter).
@@ -348,18 +360,21 @@ declare {{
     }
 }};
 
-def format Nop() {{
-    return ('', 'return new Nop("%s", machInst);\n' % name)
+output exec {{
+    Fault
+    Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+    {
+       return No_Fault;
+    }
 }};
 
-
 // integer & FP operate instructions use Rc as dest, so check for
 // Rc == 31 to detect nops
 def template OperateNopCheckDecode {{
  {
      AlphaStaticInst *i = new %(class_name)s(machInst);
      if (RC == 31) {
-        i = makeNop(i);
+         i = makeNop(i);
      }
      return i;
  }
@@ -369,7 +384,10 @@ def template OperateNopCheckDecode {{
 def format BasicOperateWithNopCheck(code, *opt_args) {{
     iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
                        opt_args)
-    return iop.subst('BasicDeclare', 'OperateNopCheckDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = OperateNopCheckDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
 
@@ -378,7 +396,7 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
 // Integer operate instructions
 //
 
-declare {{
+output header {{
     /**
      * Base class for integer immediate instructions.
      */
@@ -394,39 +412,45 @@ declare {{
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           std::stringstream ss;
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
 
-           ccprintf(ss, "%-10s ", mnemonic);
+output decoder {{
+    std::string
+    IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       std::stringstream ss;
 
-           // just print the first source reg... if there's
-           // a second one, it's a read-modify-write dest (Rc),
-           // e.g. for CMOVxx
-           if (_numSrcRegs > 0) {
-               printReg(ss, _srcRegIdx[0]);
-               ss << ",";
-           }
+       ccprintf(ss, "%-10s ", mnemonic);
 
-           ss << (int)imm;
-           if (_numDestRegs > 0) {
-               ss << ",";
-               printReg(ss, _destRegIdx[0]);
-           }
+       // just print the first source reg... if there's
+       // a second one, it's a read-modify-write dest (Rc),
+       // e.g. for CMOVxx
+       if (_numSrcRegs > 0) {
+           printReg(ss, _srcRegIdx[0]);
+           ss << ",";
+       }
 
-           return ss.str();
+       ss << (int)imm;
+       if (_numDestRegs > 0) {
+           ss << ",";
+           printReg(ss, _destRegIdx[0]);
        }
-    };
+
+       return ss.str();
+    }
 }};
 
+
 def template RegOrImmDecode {{
  {
      AlphaStaticInst *i =
-        (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
-        : (AlphaStaticInst *)new %(class_name)s(machInst);
+         (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
+               : (AlphaStaticInst *)new %(class_name)s(machInst);
      if (RC == 31) {
-        i = makeNop(i);
+         i = makeNop(i);
      }
      return i;
  }
@@ -453,21 +477,23 @@ def format IntegerOperate(code, *opt_flags) {{
     # generate declaration for register version
     cblk = CodeBlock(code)
     iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
-    decls = iop.subst('BasicDeclare')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 
     if uses_imm:
         # append declaration for imm version
         imm_cblk = CodeBlock(imm_code)
         imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
                                opt_flags)
-        decls += imm_iop.subst('BasicDeclare')
+       header_output += BasicDeclare.subst(imm_iop)
+        decoder_output += BasicConstructor.subst(imm_iop)
+        exec_output += BasicExecute.subst(imm_iop)
         # decode checks IMM bit to pick correct version
-       decode = iop.subst('RegOrImmDecode')
+       decode_block = RegOrImmDecode.subst(iop)
     else:
         # no imm version: just check for nop
-        decode = iop.subst('OperateNopCheckDecode')
-
-    return (decls, decode)
+        decode_block = OperateNopCheckDecode.subst(iop)
 }};
 
 
@@ -480,7 +506,29 @@ def format IntegerOperate(code, *opt_flags) {{
 //     BasicOperateWithNopCheck.
 //
 
-declare {{
+output exec {{
+    /// Check "FP enabled" machine status bit.  Called when executing any FP
+    /// instruction in full-system mode.
+    /// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
+    /// if not.  Non-full-system mode: always returns No_Fault.
+#ifdef FULL_SYSTEM
+    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+    {
+       Fault fault = No_Fault; // dummy... this ipr access should not fault
+       if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
+           fault = Fen_Fault;
+       }
+       return fault;
+    }
+#else
+    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+    {
+       return No_Fault;
+    }
+#endif
+}};
+
+output header {{
     /**
      * Base class for general floating-point instructions.  Includes
      * support for various Alpha rounding and trapping modes.  Only FP
@@ -537,60 +585,93 @@ declare {{
              trappingMode((enum TrappingMode)FP_TRAPMODE)
        {
            if (trappingMode != Imprecise) {
-               warn("Warning: precise FP traps unimplemented\n");
+               warn("precise FP traps unimplemented\n");
            }
        }
 
 #if defined(linux)
-       int
-       getC99RoundingMode(ExecContext *xc)
-       {
-           if (roundingMode == Dynamic) {
-               return alphaToC99RoundingMode[bits(xc->readFpcr(), 59, 58)];
-           }
-           else {
-               return alphaToC99RoundingMode[roundingMode];
-           }
-       }
+       int getC99RoundingMode(uint64_t fpcr_val);
 #endif
 
        // This differs from the AlphaStaticInst version only in
        // printing suffixes for non-default rounding & trapping modes.
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           std::string mnem_str(mnemonic);
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
 
-           mnem_str += ((_destRegIdx[0] >= FP_Base_DepTag)
-                        ? fpTrappingModeSuffix[trappingMode]
-                        : intTrappingModeSuffix[trappingMode]);
-           mnem_str += roundingModeSuffix[roundingMode];
+}};
 
-           std::stringstream ss;
 
-           ccprintf(ss, "%-10s ", mnem_str.c_str());
+def template FloatingPointDecode {{
+ {
+     bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
+                 && FP_ROUNDMODE == AlphaFP::Normal);
+     AlphaStaticInst *i =
+        fast ? (AlphaStaticInst *)new %(class_name)sFast(machInst) :
+               (AlphaStaticInst *)new %(class_name)sGeneral(machInst);
 
-           // just print the first two source regs... if there's
-           // a third one, it's a read-modify-write dest (Rc),
-           // e.g. for CMOVxx
-           if (_numSrcRegs > 0) {
-               printReg(ss, _srcRegIdx[0]);
-           }
-           if (_numSrcRegs > 1) {
-               ss << ",";
-               printReg(ss, _srcRegIdx[1]);
-           }
+     if (FC == 31) {
+        i = makeNop(i);
+     }
 
-           // just print the first dest... if there's a second one,
-           // it's generally implicit
-           if (_numDestRegs > 0) {
-               if (_numSrcRegs > 0)
-                   ss << ",";
-               printReg(ss, _destRegIdx[0]);
-           }
+     return i;
+ }
+}};
 
-           return ss.str();
+output decoder {{
+#if defined(linux)
+    int
+    AlphaFP::getC99RoundingMode(uint64_t fpcr_val)
+    {
+       if (roundingMode == Dynamic) {
+           return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
+       }
+       else {
+           return alphaToC99RoundingMode[roundingMode];
+       }
+    }
+#endif
+
+    std::string
+    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       std::string mnem_str(mnemonic);
+
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+       std::string suffix("");
+       suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+                  ? fpTrappingModeSuffix[trappingMode]
+                  : intTrappingModeSuffix[trappingMode]);
+       suffix += roundingModeSuffix[roundingMode];
+
+       if (suffix != "") {
+           mnem_str = csprintf("%s/%s", mnemonic, suffix);
+       }
+#endif
+
+       std::stringstream ss;
+       ccprintf(ss, "%-10s ", mnem_str.c_str());
+
+       // just print the first two source regs... if there's
+       // a third one, it's a read-modify-write dest (Rc),
+       // e.g. for CMOVxx
+       if (_numSrcRegs > 0) {
+           printReg(ss, _srcRegIdx[0]);
+       }
+       if (_numSrcRegs > 1) {
+           ss << ",";
+           printReg(ss, _srcRegIdx[1]);
        }
-    };
+
+       // just print the first dest... if there's a second one,
+       // it's generally implicit
+       if (_numDestRegs > 0) {
+           if (_numSrcRegs > 0)
+               ss << ",";
+           printReg(ss, _destRegIdx[0]);
+       }
+
+       return ss.str();
+    }
 
 #if defined(linux)
     const int AlphaFP::alphaToC99RoundingMode[] = {
@@ -610,150 +691,36 @@ declare {{
        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
 }};
 
+// General format for floating-point operate instructions:
+// - Checks trapping and rounding mode flags.  Trapping modes
+//   currently unimplemented (will fail).
+// - Generates NOP if FC == 31.
+def format FloatingPointOperate(code, *opt_args) {{
+    iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+    decode_block = FloatingPointDecode.subst(iop)
 
-def template FloatingPointDeclare {{
-    /**
-     * "Fast" static instruction class for "%(mnemonic)s" (imprecise
-     * trapping mode, normal rounding mode).
-     */
-    class %(class_name)sFast : public %(base_class)s
-    {
-      public:
-       /// Constructor.
-       %(class_name)sFast(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
-       {
-           %(constructor)s;
-       }
-
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_rd)s;
-           %(code)s;
-
-           if (fault == No_Fault) {
-               %(simple_wb)s;
-           }
-
-           return fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_rd)s;
-           %(code)s;
-
-           if (fault == No_Fault) {
-               %(dtld_wb)s;
-           }
-
-           return fault;
-       }
-    };
-
-    /**
-     * General static instruction class for "%(mnemonic)s".  Supports
-     * all the various rounding and trapping modes.
-     */
-    class %(class_name)sGeneral : public %(base_class)s
-    {
-      public:
-       /// Constructor.
-       %(class_name)sGeneral(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
-       {
-           %(constructor)s;
-       }
-
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_rd)s;
-
-#if defined(linux)
-           fesetround(getC99RoundingMode(xc));
-#endif
-
-           %(code)s;
-
-#if defined(linux)
-           fesetround(FE_TONEAREST);
-#endif
-
-           if (fault == No_Fault) {
-               %(simple_wb)s;
-           }
-
-           return fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_rd)s;
+    fast_iop = InstObjParams(name, Name + 'Fast', 'AlphaFP',
+                            CodeBlock(code), opt_args)
+    header_output = BasicDeclare.subst(fast_iop)
+    decoder_output = BasicConstructor.subst(fast_iop)
+    exec_output = BasicExecute.subst(fast_iop)
 
+    gen_code_prefix = r'''
 #if defined(linux)
-           fesetround(getC99RoundingMode(xc));
+    fesetround(getC99RoundingMode(xc->readFpcr()));
 #endif
-
-           %(code)s;
-
+'''
+    gen_code_suffix = r'''
 #if defined(linux)
-           fesetround(FE_TONEAREST);
+    fesetround(FE_TONEAREST);
 #endif
+'''
 
-           if (fault == No_Fault) {
-               %(dtld_wb)s;
-           }
-
-           return fault;
-       }
-    };
-}};
-
-def template FloatingPointDecode {{
- {
-     bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
-                 && FP_ROUNDMODE == AlphaFP::Normal);
-     AlphaStaticInst *i =
-        fast ? (AlphaStaticInst *)new %(class_name)sFast(machInst) :
-               (AlphaStaticInst *)new %(class_name)sGeneral(machInst);
-
-     if (FC == 31) {
-        i = makeNop(i);
-     }
-
-     return i;
- }
-}};
-
-
-// General format for floating-point operate instructions:
-// - Checks trapping and rounding mode flags.  Trapping modes
-//   currently unimplemented (will fail).
-// - Generates NOP if FC == 31.
-def format FloatingPointOperate(code, *opt_args) {{
-    iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code),
-                       opt_args)
-    return iop.subst('FloatingPointDeclare', 'FloatingPointDecode')
+    gen_iop = InstObjParams(name, Name + 'General', 'AlphaFP',
+    CodeBlock(gen_code_prefix + code + gen_code_suffix), opt_args)
+    header_output += BasicDeclare.subst(gen_iop)
+    decoder_output += BasicConstructor.subst(gen_iop)
+    exec_output += BasicExecute.subst(gen_iop)
 }};
 
 
@@ -762,7 +729,7 @@ def format FloatingPointOperate(code, *opt_args) {{
 // Memory-format instructions: LoadAddress, Load, Store
 //
 
-declare {{
+output header {{
     /**
      * Base class for general Alpha memory-format instructions.
      */
@@ -770,49 +737,71 @@ declare {{
     {
       protected:
 
-       /// Displacement for EA calculation (signed).
-       int32_t disp;
        /// Memory request flags.  See mem_req_base.hh.
         unsigned memAccessFlags;
+       /// Pointer to EAComp object.
+       const StaticInstPtr<AlphaISA> eaCompPtr;
+       /// Pointer to MemAcc object.
+       const StaticInstPtr<AlphaISA> memAccPtr;
 
        /// Constructor
-       Memory(const char *mnem, MachInst _machInst, OpClass __opClass)
+       Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+              StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+              StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
            : AlphaStaticInst(mnem, _machInst, __opClass),
-             disp(MEMDISP), memAccessFlags(0)
+             memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+
+      public:
+
+       const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
+       const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
+    };
+
+    /**
+     * Base class for memory-format instructions using a 32-bit
+     * displacement (i.e. most of them).
+     */
+    class MemoryDisp32 : public Memory
+    {
+      protected:
+       /// Displacement for EA calculation (signed).
+       int32_t disp;
+
+       /// Constructor.
+       MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
+                    StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+                    StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
+           : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+             disp(MEMDISP)
        {
-           return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
-                           flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
        }
     };
 
+
     /**
      * Base class for a few miscellaneous memory-format insts
      * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
      * None of these instructions has a destination register either.
      */
-    class MemoryNoDisp : public AlphaStaticInst
+    class MemoryNoDisp : public Memory
     {
       protected:
-       /// Memory request flags.  See mem_req_base.hh.
-        unsigned memAccessFlags;
-
        /// Constructor
-       MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass)
-           : AlphaStaticInst(mnem, _machInst, __opClass),
-             memAccessFlags(0)
+       MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
+                    StaticInstPtr<AlphaISA> _eaCompPtr,
+                    StaticInstPtr<AlphaISA> _memAccPtr)
+           : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           return csprintf("%-10s (r%d)", mnemonic, RB);
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 
+
     /**
      * Base class for "fake" effective-address computation
      * instructions returnded by eaCompInst().
@@ -826,13 +815,7 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute eacomp"); }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute eacomp"); }
+       %(BasicExecDeclare)s
     };
 
     /**
@@ -848,21 +831,48 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute memacc"); }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute memacc"); }
+       %(BasicExecDeclare)s
     };
 
 }};
 
 
+output decoder {{
+    std::string
+    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+                       flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
+    }
+
+    std::string
+    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       return csprintf("%-10s (r%d)", mnemonic, RB);
+    }
+}};
+
+output exec {{
+    Fault
+    EACompBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+    {
+       panic("attempt to execute eacomp");
+    }
+
+    Fault
+    MemAccBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+    {
+       panic("attempt to execute memacc");
+    }
+}};
+
+
 def format LoadAddress(code) {{
-    iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
 
@@ -881,11 +891,7 @@ def template LoadStoreDeclare {{
        {
          public:
            /// Constructor
-           EAComp(MachInst machInst)
-               : EACompBase(machInst)
-           {
-               %(ea_constructor)s;
-           }
+           EAComp(MachInst machInst);
        };
 
        /**
@@ -895,150 +901,92 @@ def template LoadStoreDeclare {{
        {
          public:
            /// Constructor
-           MemAcc(MachInst machInst)
-               : MemAccBase(machInst, %(op_class)s)
-           {
-               %(memacc_constructor)s;
-           }
+           MemAcc(MachInst machInst);
        };
 
-       /// Pointer to EAComp object.
-       StaticInstPtr<AlphaISA> eaCompPtr;
-       /// Pointer to MemAcc object.
-       StaticInstPtr<AlphaISA> memAccPtr;
-
       public:
 
-       StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
-       StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
-
        /// Constructor.
-       %(class_name)s(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
-              eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
-       {
-           %(constructor)s;
-       }
-
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           SimpleCPU *memAccessObj = cpu;
-           Addr EA;
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_nonmem_rd)s;
-           %(ea_code)s;
-
-           if (fault == No_Fault) {
-               %(simple_mem_rd)s;
-               %(memacc_code)s;
-           }
-
-           if (fault == No_Fault) {
-               %(simple_mem_wb)s;
-           }
-
-           if (fault == No_Fault) {
-               %(postacc_code)s;
-           }
-
-           if (fault == No_Fault) {
-               %(simple_nonmem_wb)s;
-           }
-
-           return fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           DynInst *memAccessObj = dynInst;
-           Addr EA;
-           Fault fault = No_Fault;
-
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_nonmem_rd)s;
-           %(ea_code)s;
-
-           if (fault == No_Fault) {
-               %(dtld_mem_rd)s;
-               %(memacc_code)s;
-           }
+       %(class_name)s(MachInst machInst);
 
-           if (fault == No_Fault) {
-               %(dtld_mem_wb)s;
-           }
+       %(BasicExecDeclare)s
+    };
+}};
 
-           if (fault == No_Fault) {
-               %(postacc_code)s;
-           }
+def template LoadStoreConstructor {{
+    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
+       : EACompBase(machInst)
+    {
+       %(ea_constructor)s;
+    }
 
-           if (fault == No_Fault) {
-               %(dtld_nonmem_wb)s;
-           }
+    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
+       : MemAccBase(machInst, %(op_class)s)
+    {
+       %(memacc_constructor)s;
+    }
 
-           return fault;
-       }
-    };
+    inline %(class_name)s::%(class_name)s(MachInst machInst)
+        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                         new EAComp(machInst), new MemAcc(machInst))
+    {
+       %(constructor)s;
+    }
 }};
 
-
-def template PrefetchDeclare {{
-    /**
-     * Static instruction class for "%(mnemonic)s".
-     */
-    class %(class_name)s : public %(base_class)s
+def template LoadStoreExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                                 Trace::InstRecord *traceData)
     {
-      public:
-       /// Constructor
-       %(class_name)s(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
-       {
-           %(constructor)s;
-       }
+       Addr EA;
+       Fault fault = No_Fault;
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           Addr EA;
-           Fault fault = No_Fault;
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_nonmem_rd)s;
+       %(ea_code)s;
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_nonmem_rd)s;
-           %(ea_code)s;
+       if (fault == No_Fault) {
+           %(op_mem_rd)s;
+           %(memacc_code)s;
+       }
 
-           if (fault == No_Fault) {
-               cpu->prefetch(EA, memAccessFlags);
-           }
+       if (fault == No_Fault) {
+           %(op_mem_wb)s;
+       }
 
-           return No_Fault;
+       if (fault == No_Fault) {
+           %(postacc_code)s;
        }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           Addr EA;
-           Fault fault = No_Fault;
+       if (fault == No_Fault) {
+           %(op_nonmem_wb)s;
+       }
+
+       return fault;
+    }
+}};
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_nonmem_rd)s;
-           %(ea_code)s;
 
-           if (fault == No_Fault) {
-               dynInst->prefetch(EA, memAccessFlags);
-           }
+def template PrefetchExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                                 Trace::InstRecord *traceData)
+    {
+       Addr EA;
+       Fault fault = No_Fault;
 
-           return No_Fault;
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_nonmem_rd)s;
+       %(ea_code)s;
+
+       if (fault == No_Fault) {
+           xc->prefetch(EA, memAccessFlags);
        }
-    };
-}};
 
+       return No_Fault;
+    }
+}};
 
 // load instructions use Ra as dest, so check for
 // Ra == 31 to detect nops
@@ -1067,11 +1015,10 @@ def template LoadPrefetchCheckDecode {{
 
 
 let {{
-global LoadStoreBase
 def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
-                 base_class = 'Memory', flags = [],
-                 declare_template = 'LoadStoreDeclare',
-                 decode_template = 'BasicDecode'):
+                 base_class = 'MemoryDisp32', flags = [],
+                 decode_template = BasicDecode,
+                 exec_template = LoadStoreExecute):
     # Segregate flags into instruction flags (handled by InstObjParams)
     # and memory access flags (handled here).
 
@@ -1102,61 +1049,68 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
     if mem_flags != '':
         iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
 
-    return iop.subst(declare_template, decode_template)
+    # (header_output, decoder_output, decode_block, exec_output)
+    return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+           decode_template.subst(iop), exec_template.subst(iop))
 }};
 
 
 def format LoadOrNop(ea_code, memacc_code, *flags) {{
-    return LoadStoreBase(name, Name, ea_code, memacc_code,
-                        flags = flags,
-                        decode_template = 'LoadNopCheckDecode')
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
+                      decode_template = LoadNopCheckDecode)
 }};
 
 
 // Note that the flags passed in apply only to the prefetch version
 def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
     # declare the load instruction object and generate the decode block
-    (decls, decode) = \
+    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code,
-                     decode_template = 'LoadPrefetchCheckDecode')
+                     decode_template = LoadPrefetchCheckDecode)
 
     # Declare the prefetch instruction object.
 
     # convert flags from tuple to list to make them mutable
     pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
 
-    (pfdecls, pfdecode) = \
+    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
        LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
-                     flags = pf_flags,
-                     declare_template = 'PrefetchDeclare')
+                     flags = pf_flags, exec_template = PrefetchExecute)
 
-    return (decls + pfdecls, decode)
+    header_output += pf_header_output
+    decoder_output += pf_decoder_output
+    exec_output += pf_exec_output
 }};
 
 
 def format Store(ea_code, memacc_code, *flags) {{
-    return LoadStoreBase(name, Name, ea_code, memacc_code,
-                        flags = flags)
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags)
 }};
 
 
 def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
-    return LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
-                        flags = flags)
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
+                      flags = flags)
 }};
 
 
 // Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
 def format MiscPrefetch(ea_code, memacc_code, *flags) {{
-    return LoadStoreBase(name, Name, ea_code, memacc_code,
-                        flags = flags, base_class = 'MemoryNoDisp')
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
+                      base_class = 'MemoryNoDisp')
 }};
 
 
 ////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
 
-
-declare {{
+output header {{
 
     /**
      * Base class for instructions whose disassembly is not purely a
@@ -1183,22 +1137,7 @@ declare {{
        {
        }
 
-       const std::string &disassemble(Addr pc, const SymbolTable *symtab)
-       {
-           if (!cachedDisassembly ||
-               pc != cachedPC || symtab != cachedSymtab)
-           {
-               if (cachedDisassembly)
-                   delete cachedDisassembly;
-
-               cachedDisassembly =
-                   new std::string(generateDisassembly(pc, symtab));
-               cachedPC = pc;
-               cachedSymtab = symtab;
-           }
-
-           return *cachedDisassembly;
-       }
+       const std::string &disassemble(Addr pc, const SymbolTable *symtab);
     };
 
     /**
@@ -1218,47 +1157,9 @@ declare {{
        {
        }
 
-       Addr branchTarget(Addr branchPC)
-       {
-           return branchPC + 4 + disp;
-       }
-
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           std::stringstream ss;
-
-           ccprintf(ss, "%-10s ", mnemonic);
-
-           // There's only one register arg (RA), but it could be
-           // either a source (the condition for conditional
-           // branches) or a destination (the link reg for
-           // unconditional branches)
-           if (_numSrcRegs > 0) {
-               printReg(ss, _srcRegIdx[0]);
-               ss << ",";
-           }
-           else if (_numDestRegs > 0) {
-               printReg(ss, _destRegIdx[0]);
-               ss << ",";
-           }
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
-           if (_numSrcRegs == 0 && _numDestRegs == 0) {
-               printReg(ss, 31);
-               ss << ",";
-           }
-#endif
-
-           Addr target = pc + 4 + disp;
-
-           std::string str;
-           if (symtab && symtab->findSymbol(target, str))
-               ss << str;
-           else 
-               ccprintf(ss, "0x%x", target);
+       Addr branchTarget(Addr branchPC) const;
 
-           return ss.str();
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 
     /**
@@ -1280,29 +1181,106 @@ declare {{
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
+       Addr branchTarget(ExecContext *xc) const;
+
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
+
+output decoder {{
+    Addr
+    Branch::branchTarget(Addr branchPC) const
+    {
+       return branchPC + 4 + disp;
+    }
+
+    Addr
+    Jump::branchTarget(ExecContext *xc) const
+    {
+       Addr NPC = xc->readPC() + 4;
+       uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+       return (Rb & ~3) | (NPC & 1);
+    }
+
+    const std::string &
+    PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab)
+    {
+       if (!cachedDisassembly ||
+           pc != cachedPC || symtab != cachedSymtab)
        {
-           std::stringstream ss;
+           if (cachedDisassembly)
+               delete cachedDisassembly;
+
+           cachedDisassembly =
+               new std::string(generateDisassembly(pc, symtab));
+           cachedPC = pc;
+           cachedSymtab = symtab;
+       }
 
-           ccprintf(ss, "%-10s ", mnemonic);
+       return *cachedDisassembly;
+    }
+
+    std::string
+    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       std::stringstream ss;
+
+       ccprintf(ss, "%-10s ", mnemonic);
+
+       // There's only one register arg (RA), but it could be
+       // either a source (the condition for conditional
+       // branches) or a destination (the link reg for
+       // unconditional branches)
+       if (_numSrcRegs > 0) {
+           printReg(ss, _srcRegIdx[0]);
+           ss << ",";
+       }
+       else if (_numDestRegs > 0) {
+           printReg(ss, _destRegIdx[0]);
+           ss << ",";
+       }
 
 #ifdef SS_COMPATIBLE_DISASSEMBLY
-           if (_numDestRegs == 0) {
-               printReg(ss, 31);
-               ss << ",";
-           }
+       if (_numSrcRegs == 0 && _numDestRegs == 0) {
+           printReg(ss, 31);
+           ss << ",";
+       }
 #endif
 
-           if (_numDestRegs > 0) {
-               printReg(ss, _destRegIdx[0]);
-               ss << ",";
-           }
+       Addr target = pc + 4 + disp;
+
+       std::string str;
+       if (symtab && symtab->findSymbol(target, str))
+           ss << str;
+       else 
+           ccprintf(ss, "0x%x", target);
+
+       return ss.str();
+    }
+
+    std::string
+    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       std::stringstream ss;
 
-           ccprintf(ss, "(r%d)", RB);
+       ccprintf(ss, "%-10s ", mnemonic);
 
-           return ss.str();
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+       if (_numDestRegs == 0) {
+           printReg(ss, 31);
+           ss << ",";
        }
-    };
+#endif
+
+       if (_numDestRegs > 0) {
+           printReg(ss, _destRegIdx[0]);
+           ss << ",";
+       }
+
+       ccprintf(ss, "(r%d)", RB);
+
+       return ss.str();
+    }
 }};
 
 def template JumpOrBranchDecode {{
@@ -1315,41 +1293,56 @@ def format CondBranch(code) {{
     code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
     iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
                        ('IsDirectControl', 'IsCondControl'))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
 let {{
-global UncondCtrlBase
 def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
     # Declare basic control transfer w/o link (i.e. link reg is R31)
     nolink_code = 'NPC = %s;\n' % npc_expr
     nolink_iop = InstObjParams(name, Name, base_class,
                                CodeBlock(nolink_code), flags)
-    decls = nolink_iop.subst('BasicDeclare')
+    header_output = BasicDeclare.subst(nolink_iop)
+    decoder_output = BasicConstructor.subst(nolink_iop)
+    exec_output = BasicExecute.subst(nolink_iop)
 
     # Generate declaration of '*AndLink' version, append to decls
     link_code = 'Ra = NPC & ~3;\n' + nolink_code
     link_iop = InstObjParams(name, Name + 'AndLink', base_class,
                              CodeBlock(link_code), flags)
-    decls += link_iop.subst('BasicDeclare')
+    header_output += BasicDeclare.subst(link_iop)
+    decoder_output += BasicConstructor.subst(link_iop)
+    exec_output += BasicExecute.subst(link_iop)
 
     # need to use link_iop for the decode template since it is expecting
     # the shorter version of class_name (w/o "AndLink")
-    return (decls, nolink_iop.subst('JumpOrBranchDecode'))
+
+    return (header_output, decoder_output,
+            JumpOrBranchDecode.subst(nolink_iop), exec_output)
 }};
 
 def format UncondBranch(*flags) {{
     flags += ('IsUncondControl', 'IsDirectControl')
-    return UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) 
+    (header_output, decoder_output, decode_block, exec_output) = \
+        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
 }};
 
 def format Jump(*flags) {{
     flags += ('IsUncondControl', 'IsIndirectControl')
-    return UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) 
+    (header_output, decoder_output, decode_block, exec_output) = \
+        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
 }};
 
 
-declare {{
+////////////////////////////////////////////////////////////////////
+//
+// PAL calls
+//
+
+output header {{
     /**
      * Base class for emulated call_pal calls (used only in
      * non-full-system mode).
@@ -1365,23 +1358,31 @@ declare {{
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
+
+output decoder {{
+    std::string
+    EmulatedCallPal::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
 #ifdef SS_COMPATIBLE_DISASSEMBLY
-           return csprintf("%s %s", "call_pal", mnemonic);
+       return csprintf("%s %s", "call_pal", mnemonic);
 #else
-           return csprintf("%-10s %s", "call_pal", mnemonic);
+       return csprintf("%-10s %s", "call_pal", mnemonic);
 #endif
-       }
-    };
+    }
 }};
 
 def format EmulatedCallPal(code) {{
     iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
-declare {{
+output header {{
     /**
      * Base class for full-system-mode call_pal instructions.
      * Probably could turn this into a leaf class and get rid of the
@@ -1392,96 +1393,135 @@ declare {{
       protected:
        int palFunc;    ///< Function code part of instruction
        int palOffset;  ///< Target PC, offset from IPR_PAL_BASE
+       bool palValid;  ///< is the function code valid?
+       bool palPriv;   ///< is this call privileged?
 
        /// Constructor.
        CallPalBase(const char *mnem, MachInst _machInst,
-                   OpClass __opClass)
-           : AlphaStaticInst(mnem, _machInst, __opClass),
-             palFunc(PALFUNC)
-       {
-           int palPriv = ((machInst & 0x80) != 0);
-           int shortPalFunc = (machInst & 0x3f);
-           palOffset = 0x2001 + (palPriv << 12) + (shortPalFunc << 6);
-       }
+                   OpClass __opClass);
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           return csprintf("%-10s %#x", "call_pal", palFunc);
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 }};
 
+output decoder {{
+    inline
+    CallPalBase::CallPalBase(const char *mnem, MachInst _machInst,
+                            OpClass __opClass)
+       : AlphaStaticInst(mnem, _machInst, __opClass),
+       palFunc(PALFUNC)
+    {
+       // From the 21164 HRM (paraphrased):
+       // Bit 7 of the function code (mask 0x80) indicates
+       // whether the call is privileged (bit 7 == 0) or
+       // unprivileged (bit 7 == 1).  The privileged call table
+       // starts at 0x2000, the unprivielged call table starts at
+       // 0x3000.  Bits 5-0 (mask 0x3f) are used to calculate the
+       // offset.
+       const int palPrivMask = 0x80;
+       const int palOffsetMask = 0x3f;
+
+       // Pal call is invalid unless all other bits are 0
+       palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+       palPriv = ((machInst & palPrivMask) == 0);
+       int shortPalFunc = (machInst & palOffsetMask);
+       // Add 1 to base to set pal-mode bit
+       palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
+    }
+
+    std::string
+    CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       return csprintf("%-10s %#x", "call_pal", palFunc);
+    }
+}};
 
 def format CallPal(code) {{
     iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
+////////////////////////////////////////////////////////////////////
 //
 // hw_ld, hw_st
 //
-declare {{
+
+output header {{
     /**
      * Base class for hw_ld and hw_st.
      */
-    class HwLoadStore : public AlphaStaticInst
+    class HwLoadStore : public Memory
     {
       protected:
 
        /// Displacement for EA calculation (signed).
        int16_t disp;
-       /// Memory request flags.  See mem_req_base.hh.
-       unsigned memAccessFlags;
 
        /// Constructor
-       HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass)
-           : AlphaStaticInst(mnem, _machInst, __opClass), disp(HW_LDST_DISP)
-       {
-           memAccessFlags = 0;
-           if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
-           if (HW_LDST_ALT)  memAccessFlags |= ALTMODE;
-           if (HW_LDST_VPTE) memAccessFlags |= VPTE;
-           if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
-       }
+       HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
+                   StaticInstPtr<AlphaISA> _eaCompPtr,
+                   StaticInstPtr<AlphaISA> _memAccPtr);
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
+
+
+output decoder {{
+    inline
+    HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst,
+                            OpClass __opClass,
+                            StaticInstPtr<AlphaISA> _eaCompPtr,
+                            StaticInstPtr<AlphaISA> _memAccPtr)
+       : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+       disp(HW_LDST_DISP)
+    {
+       memAccessFlags = 0;
+       if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
+       if (HW_LDST_ALT)  memAccessFlags |= ALTMODE;
+       if (HW_LDST_VPTE) memAccessFlags |= VPTE;
+       if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
+    }
+
+    std::string
+    HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
 #ifdef SS_COMPATIBLE_DISASSEMBLY
-           return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
+       return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
 #else
-           // HW_LDST_LOCK and HW_LDST_COND are the same bit.
-           const char *lock_str =
-               (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
-
-           return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
-                           mnemonic, RA, disp, RB,
-                           HW_LDST_PHYS ? ",PHYS" : "",
-                           HW_LDST_ALT ? ",ALT" : "",
-                           HW_LDST_QUAD ? ",QUAD" : "",
-                           HW_LDST_VPTE ? ",VPTE" : "",
-                           lock_str);
+       // HW_LDST_LOCK and HW_LDST_COND are the same bit.
+       const char *lock_str =
+           (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
+
+       return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
+                       mnemonic, RA, disp, RB,
+                       HW_LDST_PHYS ? ",PHYS" : "",
+                       HW_LDST_ALT ? ",ALT" : "",
+                       HW_LDST_QUAD ? ",QUAD" : "",
+                       HW_LDST_VPTE ? ",VPTE" : "",
+                       lock_str);
 #endif
-       }
-    };
+    }
 }};
 
-
 def format HwLoadStore(ea_code, memacc_code, class_ext, *flags) {{
-    return LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
-                         flags = flags,
-                        base_class = 'HwLoadStore')
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+                     flags = flags, base_class = 'HwLoadStore')
 }};
 
 
 def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
-    return LoadStoreBase(name, Name + class_ext,
-                        ea_code, memacc_code, postacc_code,
-                         flags = flags,
-                        base_class = 'HwLoadStore')
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+                     postacc_code, flags = flags, base_class = 'HwLoadStore')
 }};
 
 
-declare {{
+output header {{
     /**
      * Base class for hw_mfpr and hw_mtpr.
      */
@@ -1498,28 +1538,42 @@ declare {{
        {
        }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           if (_numSrcRegs > 0) {
-               // must be mtpr
-               return csprintf("%-10s r%d,IPR(%#x)",
-                               mnemonic, RA, ipr_index);
-           }
-           else {
-               // must be mfpr
-               return csprintf("%-10s IPR(%#x),r%d",
-                               mnemonic, ipr_index, RA);
-           }
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 }};
 
+output decoder {{
+    std::string
+    HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       if (_numSrcRegs > 0) {
+           // must be mtpr
+           return csprintf("%-10s r%d,IPR(%#x)",
+                           mnemonic, RA, ipr_index);
+       }
+       else {
+           // must be mfpr
+           return csprintf("%-10s IPR(%#x),r%d",
+                           mnemonic, ipr_index, RA);
+       }
+    }
+}};
+
 def format HwMoveIPR(code) {{
     iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
 }};
 
-declare {{
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
     /**
      * Static instruction class for unimplemented instructions that
      * cause simulator termination.  Note that these are recognized
@@ -1536,29 +1590,9 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           panic("attempt to execute unimplemented instruction '%s' "
-                 "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
-           return Unimplemented_Opcode_Fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           // don't panic if this is a misspeculated instruction
-           if (!xc->spec_mode)
-               panic("attempt to execute unimplemented instruction '%s' "
-                     "(inst 0x%08x, opcode 0x%x)",
-                     mnemonic, machInst, OPCODE);
-           return Unimplemented_Opcode_Fault;
-       }
+       %(BasicExecDeclare)s
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           return csprintf("%-10s (unimplemented)", mnemonic);
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 
     /**
@@ -1583,39 +1617,56 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           if (!warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
-               warned = true;
-           }
-
-           return No_Fault;
-       }
+       %(BasicExecDeclare)s
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           if (!xc->spec_mode && !warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
-               warned = true;
-           }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+    };
+}};
 
-           return No_Fault;
-       }
+output decoder {{
+    std::string
+    FailUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       return csprintf("%-10s (unimplemented)", mnemonic);
+    }
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
+    std::string
+    WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
 #ifdef SS_COMPATIBLE_DISASSEMBLY
-           return csprintf("%-10s", mnemonic);
+       return csprintf("%-10s", mnemonic);
 #else
-           return csprintf("%-10s (unimplemented)", mnemonic);
+       return csprintf("%-10s (unimplemented)", mnemonic);
 #endif
-       }
-    };
+    }
+}};
+
+output exec {{
+    Fault
+    FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+                              Trace::InstRecord *traceData)
+    {
+       if (!xc->misspeculating())
+           panic("attempt to execute unimplemented instruction '%s' "
+                 "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+       return Unimplemented_Opcode_Fault;
+    }
+
+    Fault
+    WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+                              Trace::InstRecord *traceData)
+    {
+       if (!xc->misspeculating())
+           if (!warned) {
+               warn("instruction '%s' unimplemented\n", mnemonic);
+               warned = true;
+           }
+
+       return No_Fault;
+    }
 }};
 
+
 def template WarnUnimplDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -1634,15 +1685,16 @@ def template WarnUnimplDeclare {{
 
 def format FailUnimpl() {{
     iop = InstObjParams(name, 'FailUnimplemented')
-    return ('', iop.subst('BasicDecodeWithMnemonic'))
+    decode_block = BasicDecodeWithMnemonic.subst(iop)
 }};
 
 def format WarnUnimpl() {{
     iop = InstObjParams(name, Name, 'WarnUnimplemented')
-    return iop.subst('WarnUnimplDeclare', 'BasicDecode')
+    header_output = WarnUnimplDeclare.subst(iop)
+    decode_block = BasicDecode.subst(iop)
 }};
 
-declare {{
+output header {{
     /**
      * Static instruction class for unknown (illegal) instructions.
      * These cause simulator termination if they are executed in a
@@ -1657,37 +1709,47 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           panic("attempt to execute unknown instruction "
-                 "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
-           return Unimplemented_Opcode_Fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           // don't panic if this is a misspeculated instruction
-           if (!xc->spec_mode)
-               panic("attempt to execute unknown instruction "
-                     "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
-           return Unimplemented_Opcode_Fault;
-       }
+       %(BasicExecDeclare)s
 
-       std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
-       {
-           return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
-                           "unknown", machInst, OPCODE);
-       }
+       std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
     };
 }};
 
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
+
+output decoder {{
+    std::string
+    Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab)
+    {
+       return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+                       "unknown", machInst, OPCODE);
+    }
+}};
+
+output exec {{
+    Fault
+    Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData)
+    {
+       if (!xc->misspeculating())
+           panic("attempt to execute unknown instruction "
+                 "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
+       return Unimplemented_Opcode_Fault;
+    }
+}};
+
 def format Unknown() {{
-    return ('', 'return new Unknown(machInst);\n')
+    decode_block = 'return new Unknown(machInst);\n'
 }};
 
-declare {{
+////////////////////////////////////////////////////////////////////
+//
+// Utility functions for execute methods
+//
+
+output exec {{
 
     /// Return opa + opb, summing carry into third arg.
     inline uint64_t
@@ -1701,7 +1763,7 @@ declare {{
 
     /// Multiply two 64-bit values (opa * opb), returning the 128-bit
     /// product in res_hi and res_lo.
-    void
+    inline void
     mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
     {
        // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
@@ -1771,6 +1833,11 @@ declare {{
     }
 }};
 
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
 decode OPCODE default Unknown::unknown() {
 
     format LoadAddress {
@@ -1785,13 +1852,18 @@ decode OPCODE default Unknown::unknown() {
        0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
        0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
        0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
+       0x20: copy_load({{EA = Ra;}}, 
+                       {{ fault = xc->copySrcTranslate(EA);}},
+                       IsMemRef, IsLoad, IsCopy);
     }
 
     format LoadOrPrefetch {
        0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
        0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
+       // IsFloating flag on lds gets the prefetch to disassemble
+       // using f31 instead of r31... funcitonally it's unnecessary
        0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
-                 PF_EXCLUSIVE);
+                 PF_EXCLUSIVE, IsFloating);  
     }
 
     format Store {
@@ -1802,6 +1874,9 @@ decode OPCODE default Unknown::unknown() {
        0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
        0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
        0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
+       0x24: copy_store({{EA = Rb;}},
+                        {{ fault = xc->copy(EA);}},
+                        IsMemRef, IsStore, IsCopy);
     }
 
     format StoreCond {
@@ -2299,10 +2374,6 @@ decode OPCODE default Unknown::unknown() {
     // miscellaneous mem-format ops
     0x18: decode MEMFUNC {
        format WarnUnimpl {
-           0x0000: trapb();
-           0x0400: excb();
-           0x4000: mb();
-           0x4400: wmb();
            0x8000: fetch();
            0xa000: fetch_m();
            0xe800: ecb();
@@ -2310,24 +2381,55 @@ decode OPCODE default Unknown::unknown() {
 
        format MiscPrefetch {
            0xf800: wh64({{ EA = Rb; }},
-                        {{ memAccessObj->writeHint(EA, 64); }},
+                        {{ xc->writeHint(EA, 64); }},
                         IsMemRef, IsStore, WrPort);
        }
 
        format BasicOperate {
-           0xc000: rpcc({{ Ra = curTick; }});
+           0xc000: rpcc({{
+#ifdef FULL_SYSTEM
+               Ra = xc->readIpr(AlphaISA::IPR_CC, fault);
+#else
+               Ra = curTick;
+#endif
+           }});
+
+           // All of the barrier instructions below do nothing in
+           // their execute() methods (hence the empty code blocks).
+           // All of their functionality is hard-coded in the
+           // pipeline based on the flags IsSerializing,
+           // IsMemBarrier, and IsWriteBarrier.  In the current
+           // detailed CPU model, the execute() function only gets
+           // called at fetch, so there's no way to generate pipeline
+           // behavior at any other stage.  Once we go to an
+           // exec-in-exec CPU model we should be able to get rid of
+           // these flags and implement this behavior via the
+           // execute() methods.
+
+           // trapb is just a barrier on integer traps, where excb is
+           // a barrier on integer and FP traps.  "EXCB is thus a
+           // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
+           // them the same though.
+           0x0000: trapb({{ }}, IsSerializing, No_OpClass);
+           0x0400: excb({{ }}, IsSerializing, No_OpClass);
+           0x4000: mb({{ }}, IsMemBarrier, RdPort);
+           0x4400: wmb({{ }}, IsWriteBarrier, WrPort);
        }
 
 #ifdef FULL_SYSTEM
        format BasicOperate {
            0xe000: rc({{
-               Ra = xc->regs.intrflag;
-               xc->regs.intrflag = 0;
-           }}, No_OpClass);
+               Ra = xc->readIntrFlag();
+               if (!xc->misspeculating()) {
+                   xc->setIntrFlag(0);
+               }
+           }});
            0xf000: rs({{
-               Ra = xc->regs.intrflag;
-               xc->regs.intrflag = 1;
-           }}, No_OpClass);
+               Ra = xc->readIntrFlag();
+               if (!xc->misspeculating()) {
+                   xc->setIntrFlag(1);
+               }
+           }});
        }
 #else
        format FailUnimpl {
@@ -2339,24 +2441,46 @@ decode OPCODE default Unknown::unknown() {
 
 #ifdef FULL_SYSTEM
     0x00: CallPal::call_pal({{
-       // check to see if simulator wants to do something special
-       // on this PAL call (including maybe suppress it)
-       bool dopal = xc->simPalCheck(palFunc);
-
-       Annotate::Callpal(xc, palFunc);
+       if (!palValid ||
+           (palPriv
+            && xc->readIpr(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
+           // invalid pal function code, or attempt to do privileged
+           // PAL call in non-kernel mode
+           fault = Unimplemented_Opcode_Fault;
+       }
+       else {
+           bool dopal = true;
 
-       if (dopal) {
            if (!xc->misspeculating()) {
-               AlphaISA::swap_palshadow(&xc->regs, true);
+               // check to see if simulator wants to do something special
+               // on this PAL call (including maybe suppress it)
+               dopal = xc->simPalCheck(palFunc);
+
+               if (dopal) {
+                   AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
+                   xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
+               }
+           }
+
+           // if we're misspeculating, it's still safe (if
+           // unrealistic) to set NPC, as the control-flow change
+           // won't get committed.
+           if (dopal) {
+               NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
            }
-           xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
-           NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
        }
     }});
 #else
     0x00: decode PALFUNC {
        format EmulatedCallPal {
-           0x83: callsys({{ xc->syscall(); }});
+           0x00: halt ({{
+               if (!xc->misspeculating()) 
+                   SimExit(curTick, "halt instruction encountered");
+           }});
+           0x83: callsys({{ 
+               if (!xc->misspeculating()) 
+                   xc->syscall();
+           }});
            // Read uniq reg into ABI return value register (r0)
            0x9e: rduniq({{ R0 = Runiq; }});
            // Write uniq reg with value from ABI arg register (r16)
@@ -2390,36 +2514,45 @@ decode OPCODE default Unknown::unknown() {
        // M5 special opcodes use the reserved 0x01 opcode space
        0x01: decode M5FUNC {
            0x00: arm({{
-               if (!xc->misspeculating()) {
-                   Annotate::ARM(xc);
-                   xc->kernelStats.arm();
-               }
+               if (!xc->misspeculating())
+                   AlphaPseudo::arm(xc->xcBase());
            }});
            0x01: quiesce({{
-               if (!xc->misspeculating()) {
-                   Annotate::QUIESCE(xc);
-                   xc->setStatus(ExecContext::Suspended);
-                   xc->kernelStats.quiesce();
-               }
+               if (!xc->misspeculating())
+                   AlphaPseudo::quiesce(xc->xcBase());
            }});
            0x10: ivlb({{
-               if (!xc->misspeculating()) {
-                   Annotate::BeginInterval(xc);
-                   xc->kernelStats.ivlb();
-               }
+               if (!xc->misspeculating())
+                   AlphaPseudo::ivlb(xc->xcBase());
            }}, No_OpClass);
            0x11: ivle({{
                if (!xc->misspeculating())
-                   Annotate::EndInterval(xc);
+                   AlphaPseudo::ivle(xc->xcBase());
            }}, No_OpClass);
-           0x20: m5exit({{
+           0x20: m5exit_old({{
                if (!xc->misspeculating())
-                   m5_exit();
+                   AlphaPseudo::m5exit_old(xc->xcBase());
            }}, No_OpClass);
-            0x30: initparam({{ Ra = xc->cpu->system->init_param; }});
+           0x21: m5exit({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::m5exit(xc->xcBase());
+           }}, No_OpClass);
+            0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
             0x40: resetstats({{
                if (!xc->misspeculating())
-                   Statistics::reset();
+                   AlphaPseudo::resetstats(xc->xcBase());
+           }});
+            0x41: dumpstats({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::dumpstats(xc->xcBase());
+           }});
+            0x42: dumpresetstats({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::dumpresetstats(xc->xcBase());
+           }});
+            0x43: m5checkpoint({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::m5checkpoint(xc->xcBase());
            }});
        }
     }
@@ -2427,7 +2560,7 @@ decode OPCODE default Unknown::unknown() {
     format HwMoveIPR {
        0x19: hw_mfpr({{
            // this instruction is only valid in PAL mode
-           if (!PC_PAL(xc->regs.pc)) {
+           if (!xc->inPalMode()) {
                fault = Unimplemented_Opcode_Fault;
            }
            else {
@@ -2436,7 +2569,7 @@ decode OPCODE default Unknown::unknown() {
        }});
        0x1d: hw_mtpr({{
            // this instruction is only valid in PAL mode
-           if (!PC_PAL(xc->regs.pc)) {
+           if (!xc->inPalMode()) {
                fault = Unimplemented_Opcode_Fault;
            }
            else {