[AArch64] Add ARMv8.2-A UAO PSTATE bit
authorOliver Stannard <oliver.stannard@arm.com>
Thu, 26 Nov 2015 15:32:30 +0000 (15:32 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Thu, 26 Nov 2015 15:32:30 +0000 (15:32 +0000)
ARMv8.2-A adds a new PSTATE bit, PSTATE.UAO, which allows the LDTR/STTR
instructions to behave the same as LDR/STR with respect to execute-only
pages at higher privilege levels. New variants of the MSR/MRS
instructions are added to allow reading and writing this bit. It is a
required part of ARMv8.2-A, so no additional subtarget features are
required.

Differential Revision: http://reviews.llvm.org/D15020

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254157 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
lib/Target/AArch64/Utils/AArch64BaseInfo.h
test/MC/AArch64/armv8.2a-uao.s [new file with mode: 0644]
test/MC/Disassembler/AArch64/armv8.2a-uao.txt [new file with mode: 0644]

index 7b7003236877d68ce40d4a8f0fb7bd5c6052c4d4..4311198403fa551d491002701d3e77a1ea4efd07 100644 (file)
@@ -2266,7 +2266,7 @@ SDNode *AArch64DAGToDAGISel::SelectWriteRegister(SDNode *N) {
               && "Expected a constant integer expression.");
     uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
     unsigned State;
-    if (Reg == AArch64PState::PAN) {
+    if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO) {
       assert(Immed < 2 && "Bad imm");
       State = AArch64::MSRpstateImm1;
     } else {
index fbf1534954ae4cd4887f89d0e09e1439ac113fce..48dfcbbf74aaab0ce6199b17e36f8afecd14ef1d 100644 (file)
@@ -888,7 +888,8 @@ public:
   }
   bool isSystemPStateFieldWithImm0_1() const {
     if (!isSysReg()) return false;
-    return SysReg.PStateField == AArch64PState::PAN;
+    return (SysReg.PStateField == AArch64PState::PAN ||
+            SysReg.PStateField == AArch64PState::UAO);
   }
   bool isSystemPStateFieldWithImm0_15() const {
     if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
index 00e0eef266a7e94626073dc451c570b7c5b69267..f1f968e73123efb4db65ffd9acaf827b603c1f2c 100644 (file)
@@ -1516,7 +1516,8 @@ static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst,
 
   uint64_t pstate_field = (op1 << 3) | op2;
 
-  if (pstate_field == AArch64PState::PAN && crm > 1)
+  if ((pstate_field == AArch64PState::PAN  ||
+       pstate_field == AArch64PState::UAO) && crm > 1)
     return Fail;
 
   Inst.addOperand(MCOperand::createImm(pstate_field));
index 1feb3380eef2d4e03ffc63c5cd0b9f75d507708e..f657eaab8151a87812bba01154faca4dc42c0704 100644 (file)
@@ -146,6 +146,9 @@ const AArch64NamedImmMapper::Mapping AArch64PState::PStateMapper::PStateMappings
 
   // v8.1a "Privileged Access Never" extension-specific PStates
   {"pan", PAN, {AArch64::HasV8_1aOps}},
+
+  // v8.2a
+  {"uao", UAO, {AArch64::HasV8_2aOps}},
 };
 
 AArch64PState::PStateMapper::PStateMapper()
@@ -802,6 +805,9 @@ const AArch64NamedImmMapper::Mapping AArch64SysReg::SysRegMapper::SysRegMappings
   {"cntv_cval_el02", CNTV_CVAL_EL02, {AArch64::HasV8_1aOps}},
   {"spsr_el12", SPSR_EL12, {AArch64::HasV8_1aOps}},
   {"elr_el12", ELR_EL12, {AArch64::HasV8_1aOps}},
+
+  // v8.2a registers
+  {"uao",           UAO,           {AArch64::HasV8_2aOps}},
 };
 
 uint32_t
index 729bcd44c310659530d1f7bb3f7c52c30f68ada6..79fb61502d82628d857f23f3c903e89d51051908 100644 (file)
@@ -463,6 +463,9 @@ namespace AArch64PState {
 
     // v8.1a "Privileged Access Never" extension-specific PStates
     PAN = 0x04,
+
+    // v8.2a "User Access Override" extension-specific PStates
+    UAO = 0x03
   };
 
   struct PStateMapper : AArch64NamedImmMapper {
@@ -1191,6 +1194,9 @@ namespace AArch64SysReg {
     SPSR_EL12         = 0xea00, // 11  101  0100  0000  000
     ELR_EL12          = 0xea01, // 11  101  0100  0000  001
 
+    // v8.2a registers
+    UAO               = 0xc214, // 11  000  0100  0010  100
+
     // Cyclone specific system registers
     CPM_IOACC_CTL_EL3 = 0xff90,
   };
diff --git a/test/MC/AArch64/armv8.2a-uao.s b/test/MC/AArch64/armv8.2a-uao.s
new file mode 100644 (file)
index 0000000..ec5e962
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.2a < %s 2> %t | FileCheck %s
+// RUN: FileCheck --check-prefix=CHECK-ERROR %s < %t
+
+  msr uao, #0
+  msr uao, #1
+// CHECK: msr     UAO, #0                 // encoding: [0x7f,0x40,0x00,0xd5]
+// CHECK: msr     UAO, #1                 // encoding: [0x7f,0x41,0x00,0xd5]
+
+  msr uao, #2
+// CHECK-ERROR: error: immediate must be an integer in range [0, 1].
+// CHECK-ERROR:   msr uao, #2
+// CHECK-ERROR:            ^
+
+  msr uao, x1
+  mrs x2, uao
+// CHECK: msr     UAO, x1                 // encoding: [0x81,0x42,0x18,0xd5]
+// CHECK: mrs     x2, UAO                 // encoding: [0x82,0x42,0x38,0xd5]
diff --git a/test/MC/Disassembler/AArch64/armv8.2a-uao.txt b/test/MC/Disassembler/AArch64/armv8.2a-uao.txt
new file mode 100644 (file)
index 0000000..b8300f4
--- /dev/null
@@ -0,0 +1,19 @@
+# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.2a --disassemble < %s | FileCheck %s
+# RUN: llvm-mc -triple aarch64-none-linux-gnu --disassemble < %s 2>&1 | FileCheck --check-prefix=NO_V82A %s
+
+[0x7f,0x40,0x00,0xd5]
+[0x7f,0x41,0x00,0xd5]
+[0x7f,0x42,0x00,0xd5]
+# CHECK: msr UAO, #0
+# CHECK: msr UAO, #1
+# CHECK: msr S0_0_C4_C2_3, xzr
+# NO_V82A: msr S0_0_C4_C0_3, xzr
+# NO_V82A: msr S0_0_C4_C1_3, xzr
+# NO_V82A: msr S0_0_C4_C2_3, xzr
+
+[0x81,0x42,0x18,0xd5]
+[0x82,0x42,0x38,0xd5]
+# CHECK: msr UAO, x1
+# CHECK: mrs x2, UAO
+# NO_V82A: msr S3_0_C4_C2_4, x1
+# NO_V82A: mrs x2, S3_0_C4_C2_4