mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / arm / types.hh
index b4ef07d8a2308893ddc24320eda20e08eb59320d..a608a2046a7ca1306c578829dd00550403688e80 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2017-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 
 #include "arch/generic/types.hh"
 #include "base/bitunion.hh"
-#include "base/hashmap.hh"
-#include "base/misc.hh"
+#include "base/logging.hh"
 #include "base/types.hh"
+#include "debug/Decoder.hh"
 
 namespace ArmISA
 {
     typedef uint32_t MachInst;
 
+    BitUnion8(ITSTATE)
+        /* Note that the split (cond, mask) below is not as in ARM ARM.
+         * But it is more convenient for simulation. The condition
+         * is always the concatenation of the top 3 bits and the next bit,
+         * which applies when one of the bottom 4 bits is set.
+         * Refer to predecoder.cc for the use case.
+         */
+        Bitfield<7, 4> cond;
+        Bitfield<3, 0> mask;
+        // Bitfields for moving to/from CPSR
+        Bitfield<7, 2> top6;
+        Bitfield<1, 0> bottom2;
+    EndBitUnion(ITSTATE)
+
     BitUnion64(ExtMachInst)
-        Bitfield<63, 56> newItstate;
+        // Decoder state
+        Bitfield<63, 62> decoderFault; // See DecoderFault
+        Bitfield<61> illegalExecution;
+
+        // SVE vector length, encoded in the same format as the ZCR_EL<x>.LEN
+        // bitfields
+        Bitfield<59, 56> sveLen;
+
         // ITSTATE bits
         Bitfield<55, 48> itstate;
         Bitfield<55, 52> itstateCond;
@@ -67,6 +88,7 @@ namespace ArmISA
         // Bitfields to select mode.
         Bitfield<36>     thumb;
         Bitfield<35>     bigThumb;
+        Bitfield<34>     aarch64;
 
         // Made up bitfields that make life easier.
         Bitfield<33>     sevenAndFour;
@@ -128,9 +150,9 @@ namespace ArmISA
         Bitfield<3,  0>  immedLo3_0;
 
         Bitfield<15, 0>  regList;
-        
+
         Bitfield<23, 0>  offset;
-        
+
         Bitfield<23, 0>  immed23_0;
 
         Bitfield<11, 8>  cpNum;
@@ -198,15 +220,19 @@ namespace ArmISA
 
         enum FlagBits {
             ThumbBit = (1 << 0),
-            JazelleBit = (1 << 1)
+            JazelleBit = (1 << 1),
+            AArch64Bit = (1 << 2)
         };
+
         uint8_t flags;
         uint8_t nextFlags;
-        uint8_t forcedItStateValue;
+        uint8_t _itstate;
+        uint8_t _nextItstate;
         uint8_t _size;
-        bool forcedItStateValid;
+        bool _illegalExec;
       public:
-        PCState() : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
+        PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0),
+                    _size(0), _illegalExec(false)
         {}
 
         void
@@ -216,9 +242,22 @@ namespace ArmISA
             npc(val + (thumb() ? 2 : 4));
         }
 
-        PCState(Addr val) : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
+        PCState(Addr val) : flags(0), nextFlags(0), _itstate(0),
+                            _nextItstate(0), _size(0), _illegalExec(false)
         { set(val); }
 
+        bool
+        illegalExec() const
+        {
+            return _illegalExec;
+        }
+
+        void
+        illegalExec(bool val)
+        {
+            _illegalExec = val;
+        }
+
         bool
         thumb() const
         {
@@ -289,39 +328,89 @@ namespace ArmISA
                 nextFlags &= ~JazelleBit;
         }
 
-        uint8_t
-        forcedItState() const
+        bool
+        aarch64() const
         {
-            return forcedItStateValue;
+            return flags & AArch64Bit;
         }
 
         void
-        forcedItState(uint8_t value)
+        aarch64(bool val)
         {
-            forcedItStateValue = value;
-            // Not valid unless the advance is called.
-            forcedItStateValid = false;
+            if (val)
+                flags |= AArch64Bit;
+            else
+                flags &= ~AArch64Bit;
         }
 
         bool
-        forcedItStateIsValid() const
+        nextAArch64() const
+        {
+            return nextFlags & AArch64Bit;
+        }
+
+        void
+        nextAArch64(bool val)
+        {
+            if (val)
+                nextFlags |= AArch64Bit;
+            else
+                nextFlags &= ~AArch64Bit;
+        }
+
+
+        uint8_t
+        itstate() const
         {
-            return forcedItStateValid;
+            return _itstate;
+        }
+
+        void
+        itstate(uint8_t value)
+        {
+            _itstate = value;
+        }
+
+        uint8_t
+        nextItstate() const
+        {
+            return _nextItstate;
+        }
+
+        void
+        nextItstate(uint8_t value)
+        {
+            _nextItstate = value;
         }
 
         void
         advance()
         {
             Base::advance();
-            npc(pc() + (thumb() ? 2 : 4));
             flags = nextFlags;
+            npc(pc() + (thumb() ? 2 : 4));
 
-            // Validate the itState
-            if (forcedItStateValue != 0 && !forcedItStateValid) {
-                forcedItStateValid = true;
-            } else {
-                forcedItStateValid = false;
-                forcedItStateValue = 0;
+            if (_nextItstate) {
+                _itstate = _nextItstate;
+                _nextItstate = 0;
+            } else if (_itstate) {
+                ITSTATE it = _itstate;
+                uint8_t cond_mask = it.mask;
+                uint8_t thumb_cond = it.cond;
+                DPRINTF(Decoder, "Advancing ITSTATE from %#x,%#x.\n",
+                        thumb_cond, cond_mask);
+                cond_mask <<= 1;
+                uint8_t new_bit = bits(cond_mask, 4);
+                cond_mask &= mask(4);
+                if (cond_mask == 0)
+                    thumb_cond = 0;
+                else
+                    replaceBits(thumb_cond, 0, new_bit);
+                DPRINTF(Decoder, "Advancing ITSTATE to %#x,%#x.\n",
+                        thumb_cond, cond_mask);
+                it.mask = cond_mask;
+                it.cond = thumb_cond;
+                _itstate = it;
             }
         }
 
@@ -340,9 +429,15 @@ namespace ArmISA
         }
 
         void
-        instNPC(uint32_t val)
+        instNPC(Addr val)
         {
-            npc(val &~ mask(nextThumb() ? 1 : 2));
+            // @todo: review this when AArch32/64 interprocessing is
+            // supported
+            if (aarch64())
+                npc(val);  // AArch64 doesn't force PC alignment, a PC
+                           // Alignment Fault can be raised instead
+            else
+                npc(val &~ mask(nextThumb() ? 1 : 2));
         }
 
         Addr
@@ -353,7 +448,7 @@ namespace ArmISA
 
         // Perform an interworking branch.
         void
-        instIWNPC(uint32_t val)
+        instIWNPC(Addr val)
         {
             bool thumbEE = (thumb() && jazelle());
 
@@ -383,7 +478,7 @@ namespace ArmISA
         // Perform an interworking branch in ARM mode, a regular branch
         // otherwise.
         void
-        instAIWNPC(uint32_t val)
+        instAIWNPC(Addr val)
         {
             if (!thumb() && !jazelle())
                 instIWNPC(val);
@@ -395,29 +490,40 @@ namespace ArmISA
         operator == (const PCState &opc) const
         {
             return Base::operator == (opc) &&
-                flags == opc.flags && nextFlags == opc.nextFlags;
+                flags == opc.flags && nextFlags == opc.nextFlags &&
+                _itstate == opc._itstate &&
+                _nextItstate == opc._nextItstate &&
+                _illegalExec == opc._illegalExec;
+        }
+
+        bool
+        operator != (const PCState &opc) const
+        {
+            return !(*this == opc);
         }
 
         void
-        serialize(std::ostream &os)
+        serialize(CheckpointOut &cp) const override
         {
-            Base::serialize(os);
+            Base::serialize(cp);
             SERIALIZE_SCALAR(flags);
             SERIALIZE_SCALAR(_size);
             SERIALIZE_SCALAR(nextFlags);
-            SERIALIZE_SCALAR(forcedItStateValue);
-            SERIALIZE_SCALAR(forcedItStateValid);
+            SERIALIZE_SCALAR(_itstate);
+            SERIALIZE_SCALAR(_nextItstate);
+            SERIALIZE_SCALAR(_illegalExec);
         }
 
         void
-        unserialize(Checkpoint *cp, const std::string &section)
+        unserialize(CheckpointIn &cp) override
         {
-            Base::unserialize(cp, section);
+            Base::unserialize(cp);
             UNSERIALIZE_SCALAR(flags);
             UNSERIALIZE_SCALAR(_size);
             UNSERIALIZE_SCALAR(nextFlags);
-            UNSERIALIZE_SCALAR(forcedItStateValue);
-            UNSERIALIZE_SCALAR(forcedItStateValid);
+            UNSERIALIZE_SCALAR(_itstate);
+            UNSERIALIZE_SCALAR(_nextItstate);
+            UNSERIALIZE_SCALAR(_illegalExec);
         }
     };
 
@@ -429,8 +535,17 @@ namespace ArmISA
         ROR
     };
 
-    typedef uint64_t LargestRead;
-    // Need to use 64 bits to make sure that read requests get handled properly
+    // Extension types for ARM instructions
+    enum ArmExtendType {
+        UXTB = 0,
+        UXTH = 1,
+        UXTW = 2,
+        UXTX = 3,
+        SXTB = 4,
+        SXTH = 5,
+        SXTW = 6,
+        SXTX = 7
+    };
 
     typedef int RegContextParam;
     typedef int RegContextVal;
@@ -467,28 +582,156 @@ namespace ArmISA
         RND_NEAREST
     };
 
+    enum ExceptionLevel {
+        EL0 = 0,
+        EL1,
+        EL2,
+        EL3
+    };
+
     enum OperatingMode {
+        MODE_EL0T = 0x0,
+        MODE_EL1T = 0x4,
+        MODE_EL1H = 0x5,
+        MODE_EL2T = 0x8,
+        MODE_EL2H = 0x9,
+        MODE_EL3T = 0xC,
+        MODE_EL3H = 0xD,
         MODE_USER = 16,
         MODE_FIQ = 17,
         MODE_IRQ = 18,
         MODE_SVC = 19,
         MODE_MON = 22,
         MODE_ABORT = 23,
+        MODE_HYP = 26,
         MODE_UNDEFINED = 27,
         MODE_SYSTEM = 31,
         MODE_MAXMODE = MODE_SYSTEM
     };
 
+    enum ExceptionClass {
+        EC_INVALID                 = -1,
+        EC_UNKNOWN                 = 0x0,
+        EC_TRAPPED_WFI_WFE         = 0x1,
+        EC_TRAPPED_CP15_MCR_MRC    = 0x3,
+        EC_TRAPPED_CP15_MCRR_MRRC  = 0x4,
+        EC_TRAPPED_CP14_MCR_MRC    = 0x5,
+        EC_TRAPPED_CP14_LDC_STC    = 0x6,
+        EC_TRAPPED_HCPTR           = 0x7,
+        EC_TRAPPED_SIMD_FP         = 0x7,   // AArch64 alias
+        EC_TRAPPED_CP10_MRC_VMRS   = 0x8,
+        EC_TRAPPED_BXJ             = 0xA,
+        EC_TRAPPED_CP14_MCRR_MRRC  = 0xC,
+        EC_ILLEGAL_INST            = 0xE,
+        EC_SVC_TO_HYP              = 0x11,
+        EC_SVC                     = 0x11,  // AArch64 alias
+        EC_HVC                     = 0x12,
+        EC_SMC_TO_HYP              = 0x13,
+        EC_SMC                     = 0x13,  // AArch64 alias
+        EC_SVC_64                  = 0x15,
+        EC_HVC_64                  = 0x16,
+        EC_SMC_64                  = 0x17,
+        EC_TRAPPED_MSR_MRS_64      = 0x18,
+        EC_TRAPPED_SVE             = 0x19,
+        EC_PREFETCH_ABORT_TO_HYP   = 0x20,
+        EC_PREFETCH_ABORT_LOWER_EL = 0x20,  // AArch64 alias
+        EC_PREFETCH_ABORT_FROM_HYP = 0x21,
+        EC_PREFETCH_ABORT_CURR_EL  = 0x21,  // AArch64 alias
+        EC_PC_ALIGNMENT            = 0x22,
+        EC_DATA_ABORT_TO_HYP       = 0x24,
+        EC_DATA_ABORT_LOWER_EL     = 0x24,  // AArch64 alias
+        EC_DATA_ABORT_FROM_HYP     = 0x25,
+        EC_DATA_ABORT_CURR_EL      = 0x25,  // AArch64 alias
+        EC_STACK_PTR_ALIGNMENT     = 0x26,
+        EC_FP_EXCEPTION            = 0x28,
+        EC_FP_EXCEPTION_64         = 0x2C,
+        EC_SERROR                  = 0x2F,
+        EC_SOFTWARE_BREAKPOINT     = 0x38,
+        EC_SOFTWARE_BREAKPOINT_64  = 0x3C,
+    };
+
+    /**
+     * Instruction decoder fault codes in ExtMachInst.
+     */
+    enum DecoderFault : std::uint8_t {
+        OK = 0x0, ///< No fault
+        UNALIGNED = 0x1, ///< Unaligned instruction fault
+
+        PANIC = 0x3, ///< Internal gem5 error
+    };
+
+    BitUnion8(OperatingMode64)
+        Bitfield<0> spX;
+        Bitfield<3, 2> el;
+        Bitfield<4> width;
+    EndBitUnion(OperatingMode64)
+
+    static bool inline
+    opModeIs64(OperatingMode mode)
+    {
+        return ((OperatingMode64)(uint8_t)mode).width == 0;
+    }
+
+    static bool inline
+    opModeIsH(OperatingMode mode)
+    {
+        return (mode == MODE_EL1H || mode == MODE_EL2H || mode == MODE_EL3H);
+    }
+
+    static bool inline
+    opModeIsT(OperatingMode mode)
+    {
+        return (mode == MODE_EL0T || mode == MODE_EL1T || mode == MODE_EL2T ||
+                mode == MODE_EL3T);
+    }
+
+    static ExceptionLevel inline
+    opModeToEL(OperatingMode mode)
+    {
+        bool aarch32 = ((mode >> 4) & 1) ? true : false;
+        if (aarch32) {
+            switch (mode) {
+              case MODE_USER:
+                return EL0;
+              case MODE_FIQ:
+              case MODE_IRQ:
+              case MODE_SVC:
+              case MODE_ABORT:
+              case MODE_UNDEFINED:
+              case MODE_SYSTEM:
+                return EL1;
+              case MODE_HYP:
+                return EL2;
+              case MODE_MON:
+                return EL3;
+              default:
+                panic("Invalid operating mode: %d", mode);
+                break;
+            }
+        } else {
+            // aarch64
+            return (ExceptionLevel) ((mode >> 2) & 3);
+        }
+    }
+
     static inline bool
-    badMode(OperatingMode mode)
+    unknownMode(OperatingMode mode)
     {
         switch (mode) {
+          case MODE_EL0T:
+          case MODE_EL1T:
+          case MODE_EL1H:
+          case MODE_EL2T:
+          case MODE_EL2H:
+          case MODE_EL3T:
+          case MODE_EL3H:
           case MODE_USER:
           case MODE_FIQ:
           case MODE_IRQ:
           case MODE_SVC:
           case MODE_MON:
           case MODE_ABORT:
+          case MODE_HYP:
           case MODE_UNDEFINED:
           case MODE_SYSTEM:
             return false;
@@ -497,19 +740,37 @@ namespace ArmISA
         }
     }
 
-    struct CoreSpecific {
-        // Empty for now on the ARM
-    };
+    static inline bool
+    unknownMode32(OperatingMode mode)
+    {
+        switch (mode) {
+          case MODE_USER:
+          case MODE_FIQ:
+          case MODE_IRQ:
+          case MODE_SVC:
+          case MODE_MON:
+          case MODE_ABORT:
+          case MODE_HYP:
+          case MODE_UNDEFINED:
+          case MODE_SYSTEM:
+            return false;
+          default:
+            return true;
+        }
+    }
 
+    constexpr unsigned MaxSveVecLenInBits = 2048;
+    static_assert(MaxSveVecLenInBits >= 128 &&
+                  MaxSveVecLenInBits <= 2048 &&
+                  MaxSveVecLenInBits % 128 == 0,
+                  "Unsupported max. SVE vector length");
+    constexpr unsigned MaxSveVecLenInBytes  = MaxSveVecLenInBits >> 3;
+    constexpr unsigned MaxSveVecLenInWords  = MaxSveVecLenInBits >> 5;
+    constexpr unsigned MaxSveVecLenInDWords = MaxSveVecLenInBits >> 6;
+
+    constexpr unsigned VecRegSizeBytes = MaxSveVecLenInBytes;
+    constexpr unsigned VecPredRegSizeBits = MaxSveVecLenInBytes;
+    constexpr unsigned VecPredRegHasPackedRepr = false;
 } // namespace ArmISA
 
-namespace __hash_namespace {
-    template<>
-    struct hash<ArmISA::ExtMachInst> : public hash<uint32_t> {
-        size_t operator()(const ArmISA::ExtMachInst &emi) const {
-            return hash<uint32_t>::operator()((uint32_t)emi);
-        };
-    };
-}
-
 #endif