first pass at merging m5 with linux
[gem5.git] / arch / alpha / isa_desc
index b5536525d1f3ba2583a160fb575aa6949d4f9e61..0d1e7138f7265b5f38a75482a6740953cd045d4d 100644 (file)
@@ -18,20 +18,19 @@ let {{
 #include <fenv.h>
 #endif
 
-#include "cpu/static_inst.hh"
 #include "base/cprintf.hh"
 #include "base/misc.hh"
-#include "cpu/full_cpu/op_class.hh"
-
 #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/exetrace.hh"
+#include "cpu/full_cpu/dyn_inst.hh"
+#include "cpu/simple_cpu/simple_cpu.hh"
+#include "cpu/static_inst.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 AlphaISA;
@@ -142,7 +141,8 @@ declare {{
     /// @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)
+    template <class XC>
+    inline Fault checkFpEnableFault(XC *xc)
     {
        Fault fault = No_Fault; // dummy... this ipr access should not fault
        if (!ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
@@ -151,7 +151,8 @@ declare {{
        return fault;
     }
 #else
-    inline Fault checkFpEnableFault(ExecContext *xc)
+    template <class XC>
+    inline Fault checkFpEnableFault(XC *xc)
     {
        return No_Fault;
     }
@@ -238,42 +239,27 @@ def template BasicDeclare {{
            %(constructor)s;
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           SimpleCPU *memAccessObj __attribute__((unused)) = cpu;
-           Fault fault = No_Fault;
+       %(exec_func_declarations)s
+    };
+}};
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_rd)s;
-           %(code)s;
+def template BasicExecute {{
+    Fault %(class_name)s::execute(%(cpu_model)s *xc,
+                                 Trace::InstRecord *traceData)
+    {
+       Fault fault = No_Fault;
 
-           if (fault == No_Fault) {
-               %(simple_wb)s;
-           }
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_rd)s;
+       %(code)s;
 
-           return fault;
+       if (fault == No_Fault) {
+           %(op_wb)s;
        }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           DynInst *memAccessObj __attribute__((unused)) = dynInst;
-           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;
-       }
-    };
+       return fault;
+    }
 }};
 
 def template BasicDecode {{
@@ -287,7 +273,7 @@ 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')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 
@@ -314,18 +300,6 @@ declare {{
 
        ~Nop() { }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       {
-           return No_Fault;
-       }
-
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       {
-           return No_Fault;
-       }
-
        std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
        {
 #ifdef SS_COMPATIBLE_DISASSEMBLY
@@ -334,6 +308,12 @@ declare {{
            return csprintf("%-10s (%s)", "nop", originalDisassembly);
 #endif
        }
+
+       Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+        { return No_Fault; }
+
+       Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+        { return No_Fault; }
     };
 
     /// Helper function for decoding nops.  Substitute Nop object
@@ -349,7 +329,7 @@ declare {{
 }};
 
 def format Nop() {{
-    return ('', 'return new Nop("%s", machInst);\n' % name)
+    return ('', 'return new Nop("%s", machInst);\n' % name, 'return No_Fault;')
 }};
 
 
@@ -369,7 +349,7 @@ def template OperateNopCheckDecode {{
 def format BasicOperateWithNopCheck(code, *opt_args) {{
     iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
                        opt_args)
-    return iop.subst('BasicDeclare', 'OperateNopCheckDecode')
+    return iop.subst('BasicDeclare', 'OperateNopCheckDecode', 'BasicExecute')
 }};
 
 
@@ -453,21 +433,24 @@ 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')
+    (decls, exec_code) = iop.subst('BasicDeclare', 'BasicExecute')
 
     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')
+        (imm_decls, imm_exec_code) = \
+                  imm_iop.subst('BasicDeclare', 'BasicExecute')
+       decls += imm_decls
+        exec_code += imm_exec_code
         # decode checks IMM bit to pick correct version
        decode = iop.subst('RegOrImmDecode')
     else:
         # no imm version: just check for nop
         decode = iop.subst('OperateNopCheckDecode')
 
-    return (decls, decode)
+    return (decls, decode, exec_code)
 }};
 
 
@@ -537,16 +520,16 @@ 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)
+       getC99RoundingMode(uint64_t fpcr_val)
        {
            if (roundingMode == Dynamic) {
-               return alphaToC99RoundingMode[bits(xc->readFpcr(), 59, 58)];
+               return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
            }
            else {
                return alphaToC99RoundingMode[roundingMode];
@@ -560,13 +543,19 @@ declare {{
        {
            std::string mnem_str(mnemonic);
 
-           mnem_str += ((_destRegIdx[0] >= FP_Base_DepTag)
-                        ? fpTrappingModeSuffix[trappingMode]
-                        : intTrappingModeSuffix[trappingMode]);
-           mnem_str += roundingModeSuffix[roundingMode];
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+           std::string suffix("");
+           suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+                      ? fpTrappingModeSuffix[trappingMode]
+                      : intTrappingModeSuffix[trappingMode]);
+           suffix += roundingModeSuffix[roundingMode];
 
-           std::stringstream ss;
+           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
@@ -611,124 +600,6 @@ declare {{
 }};
 
 
-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;
-
-#if defined(linux)
-           fesetround(getC99RoundingMode(xc));
-#endif
-
-           %(code)s;
-
-#if defined(linux)
-           fesetround(FE_TONEAREST);
-#endif
-
-           if (fault == No_Fault) {
-               %(dtld_wb)s;
-           }
-
-           return fault;
-       }
-    };
-}};
-
 def template FloatingPointDecode {{
  {
      bool fast = (FP_TRAPMODE == AlphaFP::Imprecise
@@ -745,15 +616,34 @@ def template FloatingPointDecode {{
  }
 }};
 
-
 // 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')
+    iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+    decode = iop.subst('FloatingPointDecode')
+
+    fast_iop = InstObjParams(name, Name + 'Fast', 'AlphaFP',
+    CodeBlock(code), opt_args)
+    (fast_declare, fast_exec) = fast_iop.subst('BasicDeclare', 'BasicExecute')
+
+    gen_code_prefix = r'''
+#if defined(linux)
+    fesetround(getC99RoundingMode(xc->readFpcr()));
+#endif
+'''
+    gen_code_suffix = r'''
+#if defined(linux)
+    fesetround(FE_TONEAREST);
+#endif
+'''
+
+    gen_iop = InstObjParams(name, Name + 'General', 'AlphaFP',
+    CodeBlock(gen_code_prefix + code + gen_code_suffix), opt_args)
+    (gen_declare, gen_exec) = gen_iop.subst('BasicDeclare', 'BasicExecute')
+    
+    return (fast_declare + gen_declare, decode, fast_exec + gen_exec)
 }};
 
 
@@ -826,13 +716,11 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute eacomp"); }
+       Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+        { panic("attempt to execute eacomp"); }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute eacomp"); }
+       Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+        { panic("attempt to execute eacomp"); }
     };
 
     /**
@@ -848,13 +736,11 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute memacc"); }
+       Fault execute(SimpleCPUExecContext *, Trace::InstRecord *)
+        { panic("attempt to execute memacc"); }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
-       { panic("attempt to execute memacc"); }
+       Fault execute(FullCPUExecContext *, Trace::InstRecord *)
+        { panic("attempt to execute memacc"); }
     };
 
 }};
@@ -862,7 +748,7 @@ declare {{
 
 def format LoadAddress(code) {{
     iop = InstObjParams(name, Name, 'Memory', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 
@@ -920,72 +806,42 @@ def template LoadStoreDeclare {{
            %(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;
-           }
+       %(exec_func_declarations)s
+    };
+}};
 
-           if (fault == No_Fault) {
-               %(postacc_code)s;
-           }
+def template LoadStoreExecute {{
+    Fault %(class_name)s::execute(%(cpu_model)s *xc,
+                                 Trace::InstRecord *traceData)
+    {
+       Addr EA;
+       Fault fault = No_Fault;
 
-           if (fault == No_Fault) {
-               %(simple_nonmem_wb)s;
-           }
+       %(fp_enable_check)s;
+       %(op_decl)s;
+       %(op_nonmem_rd)s;
+       %(ea_code)s;
 
-           return fault;
+       if (fault == No_Fault) {
+           %(op_mem_rd)s;
+           %(memacc_code)s;
        }
 
-       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;
-           }
-
-           if (fault == No_Fault) {
-               %(dtld_mem_wb)s;
-           }
-
-           if (fault == No_Fault) {
-               %(postacc_code)s;
-           }
+       if (fault == No_Fault) {
+           %(op_mem_wb)s;
+       }
 
-           if (fault == No_Fault) {
-               %(dtld_nonmem_wb)s;
-           }
+       if (fault == No_Fault) {
+           %(postacc_code)s;
+       }
 
-           return fault;
+       if (fault == No_Fault) {
+           %(op_nonmem_wb)s;
        }
-    };
-}};
 
+       return fault;
+    }
+}};
 
 def template PrefetchDeclare {{
     /**
@@ -993,52 +849,77 @@ def template PrefetchDeclare {{
      */
     class %(class_name)s : public %(base_class)s
     {
-      public:
-       /// Constructor
-       %(class_name)s(MachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+      protected:
+
+       /**
+        * "Fake" effective address computation class for "%(mnemonic)s".
+        */
+       class EAComp : public EACompBase
        {
-           %(constructor)s;
-       }
+         public:
+           /// Constructor
+           EAComp(MachInst machInst)
+               : EACompBase(machInst)
+           {
+               %(ea_constructor)s;
+           }
+       };
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
-                     Trace::InstRecord *traceData)
+       /**
+        * "Fake" memory access instruction class for "%(mnemonic)s".
+        */
+       class MemAcc : public MemAccBase
        {
-           Addr EA;
-           Fault fault = No_Fault;
+         public:
+           /// Constructor
+           MemAcc(MachInst machInst)
+               : MemAccBase(machInst, %(op_class)s)
+           {
+               %(memacc_constructor)s;
+           }
+       };
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(simple_nonmem_rd)s;
-           %(ea_code)s;
+       /// Pointer to EAComp object.
+       StaticInstPtr<AlphaISA> eaCompPtr;
+       /// Pointer to MemAcc object.
+       StaticInstPtr<AlphaISA> memAccPtr;
 
-           if (fault == No_Fault) {
-               cpu->prefetch(EA, memAccessFlags);
-           }
+      public:
 
-           return No_Fault;
-       }
+       StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
+       StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
-                     Trace::InstRecord *traceData)
+       /// Constructor
+       %(class_name)s(MachInst machInst)
+            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
+              eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
        {
-           Addr EA;
-           Fault fault = No_Fault;
+           %(constructor)s;
+       }
 
-           %(fp_enable_check)s;
-           %(exec_decl)s;
-           %(dtld_nonmem_rd)s;
-           %(ea_code)s;
+       %(exec_func_declarations)s
+    };
+}};
 
-           if (fault == No_Fault) {
-               dynInst->prefetch(EA, memAccessFlags);
-           }
+def template PrefetchExecute {{
+    Fault %(class_name)s::execute(%(cpu_model)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
@@ -1071,7 +952,8 @@ global LoadStoreBase
 def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
                  base_class = 'Memory', flags = [],
                  declare_template = 'LoadStoreDeclare',
-                 decode_template = 'BasicDecode'):
+                 decode_template = 'BasicDecode',
+                 exec_template = 'LoadStoreExecute'):
     # Segregate flags into instruction flags (handled by InstObjParams)
     # and memory access flags (handled here).
 
@@ -1102,7 +984,7 @@ 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)
+    return iop.subst(declare_template, decode_template, exec_template)
 }};
 
 
@@ -1116,7 +998,7 @@ def format LoadOrNop(ea_code, memacc_code, *flags) {{
 // 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) = \
+    (decls, decode, exec_code) = \
        LoadStoreBase(name, Name, ea_code, memacc_code,
                      decode_template = 'LoadPrefetchCheckDecode')
 
@@ -1125,12 +1007,13 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
     # convert flags from tuple to list to make them mutable
     pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'RdPort']
 
-    (pfdecls, pfdecode) = \
+    (pfdecls, pfdecode, pfexec) = \
        LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
                      flags = pf_flags,
-                     declare_template = 'PrefetchDeclare')
+                     declare_template = 'PrefetchDeclare',
+                     exec_template = 'PrefetchExecute')
 
-    return (decls + pfdecls, decode)
+    return (decls + pfdecls, decode, exec_code + pfexec)
 }};
 
 
@@ -1218,7 +1101,7 @@ declare {{
        {
        }
 
-       Addr branchTarget(Addr branchPC)
+       Addr branchTarget(Addr branchPC) const
        {
            return branchPC + 4 + disp;
        }
@@ -1280,6 +1163,13 @@ declare {{
        {
        }
 
+       Addr branchTarget(ExecContext *xc) const
+       {
+           Addr NPC = xc->readPC() + 4;
+           uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+           return (Rb & ~3) | (NPC & 1);
+       }
+
        std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
        {
            std::stringstream ss;
@@ -1315,7 +1205,7 @@ 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')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 let {{
@@ -1325,17 +1215,20 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
     nolink_code = 'NPC = %s;\n' % npc_expr
     nolink_iop = InstObjParams(name, Name, base_class,
                                CodeBlock(nolink_code), flags)
-    decls = nolink_iop.subst('BasicDeclare')
+    (decls, exec_code) = nolink_iop.subst('BasicDeclare', 'BasicExecute')
 
     # 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')
+    (link_decls, link_exec_code) = \
+       link_iop.subst('BasicDeclare', 'BasicExecute')
+    decls += link_decls
+    exec_code += link_exec_code
 
     # 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 (decls, nolink_iop.subst('JumpOrBranchDecode'), exec_code)
 }};
 
 def format UncondBranch(*flags) {{
@@ -1378,7 +1271,7 @@ declare {{
 
 def format EmulatedCallPal(code) {{
     iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 declare {{
@@ -1392,6 +1285,8 @@ 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,
@@ -1399,9 +1294,22 @@ declare {{
            : AlphaStaticInst(mnem, _machInst, __opClass),
              palFunc(PALFUNC)
        {
-           int palPriv = ((machInst & 0x80) != 0);
-           int shortPalFunc = (machInst & 0x3f);
-           palOffset = 0x2001 + (palPriv << 12) + (shortPalFunc << 6);
+           // 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 generateDisassembly(Addr pc, const SymbolTable *symtab)
@@ -1414,7 +1322,7 @@ declare {{
 
 def format CallPal(code) {{
     iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 //
@@ -1516,7 +1424,7 @@ declare {{
 
 def format HwMoveIPR(code) {{
     iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
-    return iop.subst('BasicDeclare', 'BasicDecode')
+    return iop.subst('BasicDeclare', 'BasicDecode', 'BasicExecute')
 }};
 
 declare {{
@@ -1536,7 +1444,7 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
+       Fault execute(SimpleCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
            panic("attempt to execute unimplemented instruction '%s' "
@@ -1544,11 +1452,11 @@ declare {{
            return Unimplemented_Opcode_Fault;
        }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+       Fault execute(FullCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
            // don't panic if this is a misspeculated instruction
-           if (!xc->spec_mode)
+           if (!xc->misspeculating())
                panic("attempt to execute unimplemented instruction '%s' "
                      "(inst 0x%08x, opcode 0x%x)",
                      mnemonic, machInst, OPCODE);
@@ -1583,22 +1491,22 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
+       Fault execute(SimpleCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
            if (!warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+               warn("instruction '%s' unimplemented\n", mnemonic);
                warned = true;
            }
 
            return No_Fault;
        }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+       Fault execute(FullCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
-           if (!xc->spec_mode && !warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+           if (!xc->misspeculating() && !warned) {
+               warn("instruction '%s' unimplemented\n", mnemonic);
                warned = true;
            }
 
@@ -1634,12 +1542,12 @@ def template WarnUnimplDeclare {{
 
 def format FailUnimpl() {{
     iop = InstObjParams(name, 'FailUnimplemented')
-    return ('', iop.subst('BasicDecodeWithMnemonic'))
+    return ('', iop.subst('BasicDecodeWithMnemonic'), '')
 }};
 
 def format WarnUnimpl() {{
     iop = InstObjParams(name, Name, 'WarnUnimplemented')
-    return iop.subst('WarnUnimplDeclare', 'BasicDecode')
+    return iop.subst('WarnUnimplDeclare', 'BasicDecode') + ['']
 }};
 
 declare {{
@@ -1657,7 +1565,7 @@ declare {{
        {
        }
 
-       Fault execute(SimpleCPU *cpu, ExecContext *xc,
+       Fault execute(SimpleCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
            panic("attempt to execute unknown instruction "
@@ -1665,11 +1573,11 @@ declare {{
            return Unimplemented_Opcode_Fault;
        }
 
-       Fault execute(FullCPU *cpu, SpecExecContext *xc, DynInst *dynInst,
+       Fault execute(FullCPUExecContext *xc,
                      Trace::InstRecord *traceData)
        {
            // don't panic if this is a misspeculated instruction
-           if (!xc->spec_mode)
+           if (!xc->misspeculating())
                panic("attempt to execute unknown instruction "
                      "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
            return Unimplemented_Opcode_Fault;
@@ -1684,7 +1592,7 @@ declare {{
 }};
 
 def format Unknown() {{
-    return ('', 'return new Unknown(machInst);\n')
+    return ('', 'return new Unknown(machInst);\n', '')
 }};
 
 declare {{
@@ -1785,13 +1693,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 +1715,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 +2215,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 +2222,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 +2282,48 @@ 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);
+
+               Annotate::Callpal(xc->xcBase(), 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,30 +2357,57 @@ decode OPCODE default Unknown::unknown() {
        // M5 special opcodes use the reserved 0x01 opcode space
        0x01: decode M5FUNC {
            0x00: arm({{
-               Annotate::ARM(xc);
-               xc->kernelStats.arm();
+               if (!xc->misspeculating()) {
+                   Annotate::ARM(xc->xcBase());
+                   xc->xcBase()->kernelStats.arm();
+               }
            }});
            0x01: quiesce({{
-               Annotate::QUIESCE(xc);
-               xc->setStatus(ExecContext::Suspended);
-               xc->kernelStats.quiesce();
+               if (!xc->misspeculating())
+                   AlphaPseudo::quiesce(xc->xcBase());
            }});
            0x10: ivlb({{
-               Annotate::BeginInterval(xc);
-               xc->kernelStats.ivlb();
+               if (!xc->misspeculating()) {
+                   Annotate::BeginInterval(xc->xcBase());
+                   xc->xcBase()->kernelStats.ivlb();
+               }
+           }}, No_OpClass);
+           0x11: ivle({{
+               if (!xc->misspeculating())
+                   Annotate::EndInterval(xc->xcBase());
+           }}, No_OpClass);
+           0x20: m5exit_old({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::m5exit_old(xc->xcBase());
            }}, No_OpClass);
-           0x11: ivle({{ Annotate::EndInterval(xc); }}, No_OpClass);
-           0x20: m5exit({{
+           0x21: m5exit({{
                if (!xc->misspeculating())
-                   m5_exit();
+                   AlphaPseudo::m5exit(xc->xcBase());
            }}, No_OpClass);
+            0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
+            0x40: resetstats({{
+               if (!xc->misspeculating())
+                   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());
+           }});
        }
     }
 
     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 {
@@ -2422,7 +2416,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 {