ARM: Implement the V7 version of alignment checking.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:10 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:10 +0000 (12:58 -0500)
src/arch/arm/insts/macromem.hh
src/arch/arm/isa/insts/branch.isa
src/arch/arm/isa/insts/ldr.isa
src/arch/arm/isa/insts/mem.isa
src/arch/arm/isa/insts/str.isa
src/arch/arm/isa/insts/swap.isa
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh

index 21a37a29eda652c246b29805cdaa2938c782bce3..436a5b4a393dc41f3bcc2c45441d4b402493657a 100644 (file)
@@ -43,6 +43,7 @@
 #define __ARCH_ARM_MACROMEM_HH__
 
 #include "arch/arm/insts/pred_inst.hh"
+#include "arch/arm/tlb.hh"
 
 namespace ArmISA
 {
@@ -88,7 +89,7 @@ class MicroMemOp : public MicroIntOp
     MicroMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
                RegIndex _ura, RegIndex _urb, bool _up, uint8_t _imm)
             : MicroIntOp(mnem, machInst, __opClass, _ura, _urb, _imm),
-              up(_up), memAccessFlags(0)
+              up(_up), memAccessFlags(TLB::MustBeOne | TLB::AlignWord)
     {
     }
 };
index b79f610b6ae92408416a83f0f268e1b54d1d7844..1aa37f48382f7f4221a6f004b5cecad0bd007be3 100644 (file)
@@ -153,14 +153,23 @@ let {{
     #TBB, TBH
     for isTbh in (0, 1):
         if isTbh:
-            eaCode = "EA = Op1 + Op2 * 2"
+            eaCode = '''
+            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
+                                      ArmISA::TLB::AlignHalfWord |
+                                      ArmISA::TLB::MustBeOne;
+            EA = Op1 + Op2 * 2
+            '''
             accCode = "NPC = readPC(xc) + 2 * (Mem.uh);"
             mnem = "tbh"
         else:
-            eaCode = "EA = Op1 + Op2"
+            eaCode = '''
+            unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned |
+                                      ArmISA::TLB::AlignByte |
+                                      ArmISA::TLB::MustBeOne;
+            EA = Op1 + Op2
+            '''
             accCode = "NPC = readPC(xc) + 2 * (Mem.ub);"
             mnem = "tbb"
-        eaCode = "unsigned memAccessFlags = 0;\n" + eaCode
         iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
                             {'ea_code': eaCode,
                              'memacc_code': accCode,
index cb4c5c869e2e16a075421879da161c26be83dbac..b216daa6d6d8e153ce63ccdbc5d04eef1421ab85 100644 (file)
@@ -92,20 +92,23 @@ let {{
             eaCode += offset
         eaCode += ";"
 
+        memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)]
         if prefetch:
             Name = "%s_%s" % (mnem.upper(), Name)
-            memFlags = ["Request::PREFETCH"]
+            memFlags.append("Request::PREFETCH")
             accCode = '''
             uint64_t temp = Mem%s;\n
             temp = temp;
             ''' % buildMemSuffix(sign, size)
         else:
             if ldrex:
-                memFlags = ["Request::LLSC"]
+                memFlags.append("Request::LLSC")
                 Name = "%s_%s" % (mnem.upper(), Name)
-            else:
-                memFlags = []
             accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size)
+
+        if not prefetch and not ldrex:
+            memFlags.append("ArmISA::TLB::AllowUnaligned")
+
         if writeback:
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryImm", post, writeback)
@@ -142,7 +145,8 @@ let {{
 
         (newHeader,
          newDecoder,
-         newExec) = RfeBase(name, Name, eaCode, accCode, [], [])
+         newExec) = RfeBase(name, Name, eaCode, accCode,
+             ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], [])
 
         header_output += newHeader
         decoder_output += newDecoder
@@ -166,18 +170,22 @@ let {{
             eaCode += offset
         eaCode += ";"
 
+        memFlags = ["%d" % (size - 1), "ArmISA::TLB::MustBeOne"]
         if prefetch:
             Name = "%s_%s" % (mnem.upper(), Name)
-            memFlags = ["Request::PREFETCH"]
+            memFlags.append("Request::PREFETCH")
             accCode = '''
             uint64_t temp = Mem%s;\n
             temp = temp;
             ''' % buildMemSuffix(sign, size)
         else:
-            memFlags = []
             accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size)
         if writeback:
             accCode += "Base = Base %s;\n" % offset
+
+        if not prefetch:
+            memFlags.append("ArmISA::TLB::AllowUnaligned")
+
         base = buildMemBase("MemoryReg", post, writeback)
 
         emitLoad(name, Name, False, eaCode, accCode, \
@@ -211,6 +219,9 @@ let {{
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryDImm", post, writeback)
 
+        memFlags.extend(["ArmISA::TLB::MustBeOne",
+                         "ArmISA::TLB::AlignWord"])
+
         emitLoad(name, Name, True, eaCode, accCode, \
                  memFlags, [], base, double=True)
 
@@ -239,7 +250,8 @@ let {{
         base = buildMemBase("MemoryDReg", post, writeback)
 
         emitLoad(name, Name, False, eaCode, accCode,
-                 [], [], base, double=True)
+                 ["ArmISA::TLB::MustBeOne", "ArmISA::TLB::AlignWord"],
+                 [], base, double=True)
 
     def buildLoads(mnem, size=4, sign=False, user=False):
         buildImmLoad(mnem, True, True, True, size, sign, user)
index 7f893bbede836f5d0026bddbed4a0d349eac62f7..db3665a54542348ef4d2b2bf9d8877948fb03ea9 100644 (file)
@@ -50,10 +50,7 @@ let {{
         # This shouldn't be part of the eaCode, but until the exec templates
         # are converted over it's the easiest place to put it.
         eaCode += '\n    unsigned memAccessFlags = '
-        if memFlags:
-            eaCode += (string.join(memFlags, '|') + ';')
-        else:
-            eaCode += '0;'
+        eaCode += (string.join(memFlags, '|') + ';')
 
         codeBlobs["ea_code"] = eaCode
 
index cf9eed74e6073e05689ac2714db04e0b91d45dfd..c22245947bad636115b2132d7bd44e8f7fab0d23 100644 (file)
@@ -98,7 +98,10 @@ let {{
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryImm", post, writeback)
 
-        emitStore(name, Name, True, eaCode, accCode, [], [], base)
+        emitStore(name, Name, True, eaCode, accCode, \
+                ["ArmISA::TLB::MustBeOne", \
+                 "ArmISA::TLB::AllowUnaligned", \
+                 "%d" % (size - 1)], [], base)
 
     def buildRegStore(mnem, post, add, writeback, \
                       size=4, sign=False, user=False):
@@ -123,7 +126,10 @@ let {{
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryReg", post, writeback)
 
-        emitStore(name, Name, False, eaCode, accCode, [], [], base)
+        emitStore(name, Name, False, eaCode, accCode, \
+                ["ArmISA::TLB::MustBeOne", \
+                 "ArmISA::TLB::AllowUnaligned", \
+                 "%d" % (size - 1)], [], base)
 
     def buildDoubleImmStore(mnem, post, add, writeback):
         name = mnem
@@ -146,7 +152,8 @@ let {{
         base = buildMemBase("MemoryDImm", post, writeback)
 
         emitStore(name, Name, True, eaCode, accCode, \
-                  [], [], base, double=True)
+                ["ArmISA::TLB::MustBeOne",
+                 "ArmISA::TLB::AlignWord"], [], base, double=True)
 
     def buildDoubleRegStore(mnem, post, add, writeback):
         name = mnem
@@ -170,7 +177,8 @@ let {{
         base = buildMemBase("MemoryDReg", post, writeback)
 
         emitStore(name, Name, False, eaCode, accCode, \
-                  [], [], base, double=True)
+                ["ArmISA::TLB::MustBeOne", \
+                 "ArmISA::TLB::AlignWord"], [], base, double=True)
 
     def buildStores(mnem, size=4, sign=False, user=False):
         buildImmStore(mnem, True, True, True, size, sign, user)
index 6cbca6d6c576f40a5fa5242671769ca7ea850c6e..9456c1314107869c0c4f6747019ecfbc6ad13196 100644 (file)
@@ -45,7 +45,9 @@ let {{
      newDecoder,
      newExec) = SwapBase("swp", "Swp", "EA = Base;",
                          "Mem = Op1;", "Dest = memData;",
-                         ["Request::MEM_SWAP"], [])
+                         ["Request::MEM_SWAP",
+                          "ArmISA::TLB::AlignWord",
+                          "ArmISA::TLB::MustBeOne"], [])
     header_output += newHeader
     decoder_output += newDecoder
     exec_output += newExec
@@ -54,7 +56,9 @@ let {{
      newDecoder,
      newExec) = SwapBase("swpb", "Swpb", "EA = Base;",
                          "Mem.ub = Op1.ub;", "Dest.ub = (uint8_t)memData;",
-                         ["Request::MEM_SWAP"], [])
+                         ["Request::MEM_SWAP",
+                          "ArmISA::TLB::AlignByte",
+                          "ArmISA::TLB::MustBeOne"], [])
     header_output += newHeader
     decoder_output += newDecoder
     exec_output += newExec
index 5ed77aea199f24a15a4c2c07ccc858a9542fe147..94f4019d63a6078624c3c9549ad12a3e13abe8a2 100644 (file)
@@ -291,6 +291,18 @@ Fault
 TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
 {
     Addr vaddr = req->getVaddr() & ~PcModeMask;
+    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
+    uint32_t flags = req->getFlags();
+
+    if (mode != Execute) {
+        assert(flags & MustBeOne);
+
+        if (sctlr.a || (flags & AllowUnaligned) == 0) {
+            if ((vaddr & flags & AlignmentMask) != 0) {
+                return new DataAbort;
+            }
+        }
+    }
 #if !FULL_SYSTEM
     Process * p = tc->getProcessPtr();
 
@@ -301,7 +313,6 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
 
     return NoFault;
 #else
-    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
     if (!sctlr.m) {
         req->setPaddr(vaddr);
         return NoFault;
index d2c035b31afac3889aa643d39284bd50bfad88c3..d6fe981b985bf36dc66899a201f42e45b1a2892f 100644 (file)
@@ -86,6 +86,21 @@ struct TlbEntry
 
 class TLB : public BaseTLB
 {
+  public:
+    enum ArmFlags {
+        AlignmentMask = 0x7,
+
+        AlignByte = 0x0,
+        AlignHalfWord = 0x1,
+        AlignWord = 0x3,
+        AlignDoubleWord = 0x7,
+
+        AllowUnaligned = 0x8,
+        // Because zero otherwise looks like a valid setting and may be used
+        // accidentally, this bit must be non-zero to show it was used on
+        // purpose.
+        MustBeOne = 0x10
+    };
   protected:
     typedef std::multimap<Addr, int> PageTable;
     PageTable lookupTable;     // Quick lookup into page table