Copy implementations
[gem5.git] / arch / alpha / isa_desc
index 89ec05c0e26a5c3e17e8614160128d5ffbd06903..41f7388e08bab8006e1c8a0f2f009431c3691156 100644 (file)
@@ -18,20 +18,21 @@ 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/full_cpu.hh"
+#include "cpu/full_cpu/op_class.hh"
+#include "cpu/full_cpu/spec_state.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;
@@ -537,7 +538,7 @@ declare {{
              trappingMode((enum TrappingMode)FP_TRAPMODE)
        {
            if (trappingMode != Imprecise) {
-               warn("Warning: precise FP traps unimplemented\n");
+               warn("precise FP traps unimplemented\n");
            }
        }
 
@@ -560,13 +561,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
@@ -993,10 +1000,50 @@ def template PrefetchDeclare {{
      */
     class %(class_name)s : public %(base_class)s
     {
+      protected:
+
+       /**
+        * "Fake" effective address computation class for "%(mnemonic)s".
+        */
+       class EAComp : public EACompBase
+       {
+         public:
+           /// Constructor
+           EAComp(MachInst machInst)
+               : EACompBase(machInst)
+           {
+               %(ea_constructor)s;
+           }
+       };
+
+       /**
+        * "Fake" memory access instruction class for "%(mnemonic)s".
+        */
+       class MemAcc : public MemAccBase
+       {
+         public:
+           /// Constructor
+           MemAcc(MachInst machInst)
+               : MemAccBase(machInst, %(op_class)s)
+           {
+               %(memacc_constructor)s;
+           }
+       };
+
+       /// 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)
+            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
+              eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
        {
            %(constructor)s;
        }
@@ -1218,7 +1265,7 @@ declare {{
        {
        }
 
-       Addr branchTarget(Addr branchPC)
+       Addr branchTarget(Addr branchPC) const
        {
            return branchPC + 4 + disp;
        }
@@ -1280,6 +1327,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;
@@ -1392,6 +1446,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 +1455,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)
@@ -1587,7 +1656,7 @@ declare {{
                      Trace::InstRecord *traceData)
        {
            if (!warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+               warn("instruction '%s' unimplemented\n", mnemonic);
                warned = true;
            }
 
@@ -1598,7 +1667,7 @@ declare {{
                      Trace::InstRecord *traceData)
        {
            if (!xc->spec_mode && !warned) {
-               warn("Warning: instruction '%s' unimplemented\n", mnemonic);
+               warn("instruction '%s' unimplemented\n", mnemonic);
                warned = true;
            }
 
@@ -1785,13 +1854,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 = memAccessObj->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 +1876,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 =memAccessObj->copy(EA);}},
+                        IsMemRef, IsStore, IsCopy);
     }
 
     format StoreCond {
@@ -2299,10 +2376,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();
@@ -2316,18 +2389,43 @@ decode OPCODE default Unknown::unknown() {
 
        format BasicOperate {
            0xc000: rpcc({{ Ra = curTick; }});
+
+           // 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);
+               if (!xc->misspeculating()) {
+                   xc->regs.intrflag = 0;
+               }
+           }});
            0xf000: rs({{
                Ra = xc->regs.intrflag;
-               xc->regs.intrflag = 1;
-           }}, No_OpClass);
+               if (!xc->misspeculating()) {
+                   xc->regs.intrflag = 1;
+               }
+           }});
        }
 #else
        format FailUnimpl {
@@ -2339,24 +2437,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, palFunc);
+
+               if (dopal) {
+                   AlphaISA::swap_palshadow(&xc->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)
@@ -2396,11 +2518,8 @@ decode OPCODE default Unknown::unknown() {
                }
            }});
            0x01: quiesce({{
-               if (!xc->misspeculating()) {
-                   Annotate::QUIESCE(xc);
-                   xc->setStatus(ExecContext::Suspended);
-                   xc->kernelStats.quiesce();
-               }
+               if (!xc->misspeculating())
+                   AlphaPseudo::quiesce(xc);
            }});
            0x10: ivlb({{
                if (!xc->misspeculating()) {
@@ -2412,14 +2531,30 @@ decode OPCODE default Unknown::unknown() {
                if (!xc->misspeculating())
                    Annotate::EndInterval(xc);
            }}, No_OpClass);
-           0x20: m5exit({{
+           0x20: m5exit_old({{
                if (!xc->misspeculating())
-                   m5_exit();
+                   AlphaPseudo::m5exit_old(xc);
            }}, No_OpClass);
-            0x30: initparam({{ Ra = xc->cpu->system->init_param; }});
+           0x21: m5exit({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::m5exit(xc);
+           }}, No_OpClass);
+            0x30: initparam({{ Ra = cpu->system->init_param; }});
             0x40: resetstats({{
                if (!xc->misspeculating())
-                   Statistics::reset();
+                   AlphaPseudo::resetstats(xc);
+           }});
+            0x41: dumpstats({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::dumpstats(xc);
+           }});
+            0x42: dumpresetstats({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::dumpresetstats(xc);
+           }});
+            0x43: m5checkpoint({{
+               if (!xc->misspeculating())
+                   AlphaPseudo::m5checkpoint(xc);
            }});
        }
     }