summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:10 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:10 -0500
commit1d5233958ad208e3b229e394ba5ab689b82d8cac (patch)
treede69dd4bac297c10f9e6355b06b5e1f5f12c9e90
parent7b397925af7fd9864189387179137dd4ac40dfad (diff)
downloadgem5-1d5233958ad208e3b229e394ba5ab689b82d8cac.tar.xz
ARM: Implement the V7 version of alignment checking.
-rw-r--r--src/arch/arm/insts/macromem.hh3
-rw-r--r--src/arch/arm/isa/insts/branch.isa15
-rw-r--r--src/arch/arm/isa/insts/ldr.isa28
-rw-r--r--src/arch/arm/isa/insts/mem.isa5
-rw-r--r--src/arch/arm/isa/insts/str.isa16
-rw-r--r--src/arch/arm/isa/insts/swap.isa8
-rw-r--r--src/arch/arm/tlb.cc13
-rw-r--r--src/arch/arm/tlb.hh15
8 files changed, 80 insertions, 23 deletions
diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh
index 21a37a29e..436a5b4a3 100644
--- a/src/arch/arm/insts/macromem.hh
+++ b/src/arch/arm/insts/macromem.hh
@@ -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)
{
}
};
diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa
index b79f610b6..1aa37f483 100644
--- a/src/arch/arm/isa/insts/branch.isa
+++ b/src/arch/arm/isa/insts/branch.isa
@@ -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,
diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa
index cb4c5c869..b216daa6d 100644
--- a/src/arch/arm/isa/insts/ldr.isa
+++ b/src/arch/arm/isa/insts/ldr.isa
@@ -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)
diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa
index 7f893bbed..db3665a54 100644
--- a/src/arch/arm/isa/insts/mem.isa
+++ b/src/arch/arm/isa/insts/mem.isa
@@ -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
diff --git a/src/arch/arm/isa/insts/str.isa b/src/arch/arm/isa/insts/str.isa
index cf9eed74e..c22245947 100644
--- a/src/arch/arm/isa/insts/str.isa
+++ b/src/arch/arm/isa/insts/str.isa
@@ -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)
diff --git a/src/arch/arm/isa/insts/swap.isa b/src/arch/arm/isa/insts/swap.isa
index 6cbca6d6c..9456c1314 100644
--- a/src/arch/arm/isa/insts/swap.isa
+++ b/src/arch/arm/isa/insts/swap.isa
@@ -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
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 5ed77aea1..94f4019d6 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -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;
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index d2c035b31..d6fe981b9 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -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