[ARM] Add v8.1a "Privileged Access Never" extension
authorVladimir Sukharev <vladimir.sukharev@arm.com>
Thu, 16 Apr 2015 11:34:25 +0000 (11:34 +0000)
committerVladimir Sukharev <vladimir.sukharev@arm.com>
Thu, 16 Apr 2015 11:34:25 +0000 (11:34 +0000)
Reviewers: jmolloy

Subscribers: llvm-commits

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

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

lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/ARM/basic-arm-instructions-v8.1a.s
test/MC/Disassembler/ARM/armv8.1a.txt
test/MC/Disassembler/ARM/thumb-v8.1a.txt

index 3f9fbf9ee8b49f3fcf0bec0deb215c8d25ca87bf..52f35554995700662d828ed451ebbd40bd8cf0fd 100644 (file)
@@ -1420,7 +1420,8 @@ multiclass AsI1_rbin_s_is<InstrItinClass iii, InstrItinClass iir,
 let isCompare = 1, Defs = [CPSR] in {
 multiclass AI1_cmp_irs<bits<4> opcod, string opc,
                      InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
-                       PatFrag opnode, bit Commutable = 0> {
+                       PatFrag opnode, bit Commutable = 0,
+                       string rrDecoderMethod = ""> {
   def ri : AI1<opcod, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, iii,
                opc, "\t$Rn, $imm",
                [(opnode GPR:$Rn, mod_imm:$imm)]>,
@@ -1448,6 +1449,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
     let Inst{15-12} = 0b0000;
     let Inst{11-4} = 0b00000000;
     let Inst{3-0} = Rm;
+    let DecoderMethod = rrDecoderMethod;
 
     let Unpredictable{15-12} = 0b1111;
   }
@@ -4265,6 +4267,30 @@ def CRC32CH : AI_crc32<1, 0b01, "ch", int_arm_crc32ch>;
 def CRC32W  : AI_crc32<0, 0b10, "w", int_arm_crc32w>;
 def CRC32CW : AI_crc32<1, 0b10, "cw", int_arm_crc32cw>;
 
+//===----------------------------------------------------------------------===//
+// ARMv8.1a Privilege Access Never extension
+//
+// SETPAN #imm1
+
+def SETPAN : AInoP<(outs), (ins imm0_1:$imm), MiscFrm, NoItinerary, "setpan",
+                "\t$imm", []>, Requires<[IsARM, HasV8, HasV8_1a]> {
+  bits<1> imm;
+
+  let Inst{31-28} = 0b1111;
+  let Inst{27-20} = 0b00010001;
+  let Inst{19-16} = 0b0000;
+  let Inst{15-10} = 0b000000;
+  let Inst{9} = imm;
+  let Inst{8} = 0b0;
+  let Inst{7-4} = 0b0000;
+  let Inst{3-0} = 0b0000;
+
+  let Unpredictable{19-16} = 0b1111;
+  let Unpredictable{15-10} = 0b111111;
+  let Unpredictable{8} = 0b1;
+  let Unpredictable{3-0} = 0b1111;
+}
+
 //===----------------------------------------------------------------------===//
 //  Comparison Instructions...
 //
@@ -4369,7 +4395,8 @@ def : ARMPat<(ARMcmpZ GPR:$src, mod_imm_neg:$imm),
 // Note that TST/TEQ don't set all the same flags that CMP does!
 defm TST  : AI1_cmp_irs<0b1000, "tst",
                         IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr,
-                      BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>, 1>;
+                      BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>, 1,
+                      "DecodeTSTInstruction">;
 defm TEQ  : AI1_cmp_irs<0b1001, "teq",
                         IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr,
                       BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>, 1>;
index 4515a8129f71ca28f4ef86ce6bd7758b284d528b..103ee002cacb04f96c9d03a86c4e23dc907703db 100644 (file)
@@ -4280,6 +4280,23 @@ def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1,
 
 
 
+//===----------------------------------------------------------------------===//
+// ARMv8.1 Privilege Access Never extension
+//
+// SETPAN #imm1
+
+def t2SETPAN : T1I<(outs), (ins imm0_1:$imm), NoItinerary, "setpan\t$imm", []>,
+               T1Misc<0b0110000>, Requires<[IsThumb2, HasV8, HasV8_1a]> {
+  bits<1> imm;
+
+  let Inst{4} = 0b1;
+  let Inst{3} = imm;
+  let Inst{2-0} = 0b000;
+
+  let Unpredictable{4} = 0b1;
+  let Unpredictable{2-0} = 0b111;
+}
+
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns
 //
index 4b9fcbe38fcdcf7b00f6ddad4fcadf6408164dc1..b9ad2c8bcd2aa8a5a335449769caa1cab009ad87 100644 (file)
@@ -5441,7 +5441,7 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
       Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" ||
       Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" ||
       Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" ||
-      Mnemonic.startswith("aes") || Mnemonic == "hvc" ||
+      Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" ||
       Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
       (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) {
     // These mnemonics are never predicable
index 4a53e96906df8b4615b58641ade1c0e5621dfcfc..4c169a8ef55f7a5b2eea5d13f71c63c5a26c2478 100644 (file)
@@ -212,6 +212,10 @@ static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeTSTInstruction(MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val,
@@ -2119,6 +2123,54 @@ static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn,
   return S;
 }
 
+static DecodeStatus DecodeTSTInstruction(MCInst &Inst, unsigned Insn,
+                                  uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  unsigned Pred = fieldFromInstruction(Insn, 28, 4);
+  unsigned Rn = fieldFromInstruction(Insn, 16, 4);
+  unsigned Rm = fieldFromInstruction(Insn, 0, 4);
+
+  if (Pred == 0xF)
+    return DecodeSETPANInstruction(Inst, Insn, Address, Decoder);
+
+  if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+    return MCDisassembler::Fail;
+  if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+    return MCDisassembler::Fail;
+  if (!Check(S, DecodePredicateOperand(Inst, Pred, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  return S;
+}
+
+static DecodeStatus DecodeSETPANInstruction(MCInst &Inst, unsigned Insn,
+                                  uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  unsigned Imm = fieldFromInstruction(Insn, 9, 1);
+
+  const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+  uint64_t FeatureBits = Dis->getSubtargetInfo().getFeatureBits();
+  if ((FeatureBits & ARM::HasV8_1aOps) == 0 || 
+      (FeatureBits & ARM::HasV8Ops) == 0 )
+    return MCDisassembler::Fail;
+
+  // Decoder can be called from DecodeTST, which does not check the full
+  // encoding is valid.
+  if (fieldFromInstruction(Insn, 20,12) != 0xf11 ||
+      fieldFromInstruction(Insn, 4,4) != 0)
+    return MCDisassembler::Fail;
+  if (fieldFromInstruction(Insn, 10,10) != 0 ||
+      fieldFromInstruction(Insn, 0,4) != 0)
+    S = MCDisassembler::SoftFail;
+
+  Inst.setOpcode(ARM::SETPAN);
+  Inst.addOperand(MCOperand::CreateImm(Imm));
+
+  return S;
+}
+
 static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val,
                            uint64_t Address, const void *Decoder) {
   DecodeStatus S = MCDisassembler::Success;
index 3101d19284ed6dfe83b65da61dca88db93c84a90..005f27bb3983c83994683dec96d4c0566d6d9f41 100644 (file)
 //CHECK-V8: error: instruction requires: armv8.1a
 //CHECK-V8:  vqrdmlsh.s32  q0, q1, d2[0]
 //CHECK-V8:  ^
+
+  setpan  #0
+//CHECK-V81aTHUMB:  setpan  #0                @       encoding: [0x10,0xb6]
+//CHECK-V81aARM:    setpan  #0                @       encoding: [0x00,0x00,0x10,0xf1]
+//CHECK-V8: error: instruction requires: armv8.1a
+//CHECK-V8:  setpan  #0
+//CHECK-V8:  ^
+
+  setpan  #1
+//CHECK-V81aTHUMB:  setpan  #1                @       encoding: [0x18,0xb6]
+//CHECK-V81aARM:    setpan  #1                @       encoding: [0x00,0x02,0x10,0xf1]
+//CHECK-V8: error: instruction requires: armv8.1a
+//CHECK-V8:  setpan  #1
+//CHECK-V8:  ^
+  setpan
+  setpan #-1
+  setpan #2
+//CHECK-ERROR: error: too few operands for instruction
+//CHECK-ERROR:  setpan
+//CHECK-ERROR:  ^
+//CHECK-ERROR: error: invalid operand for instruction
+//CHECK-ERROR:  setpan #-1
+//CHECK-ERROR:         ^
+//CHECK-ERROR: error: invalid operand for instruction
+//CHECK-ERROR:  setpan #2
+//CHECK-ERROR:         ^
+
+  it eq
+  setpaneq #0
+//CHECK-THUMB-ERROR: error: instruction 'setpan' is not predicable, but condition code specified
+//CHECK-THUMB-ERROR:  setpaneq #0
+//CHECK-THUMB-ERROR:  ^
index de0c89ee790426bae51f77aac47ac1213971768b..929643bd5610991b066284b3f4af4625c87483f3 100644 (file)
 # CHECK-V8: [0x42,0x0f,0x92,0xf3]
 # CHECK-V8: warning: invalid instruction encoding
 # CHECK-V8: [0x42,0x0f,0xa1,0xf2]
+
+# The SETPAN(v8.1a) and TST(v8) instructions occupy the same space, but SETPAN 
+# uses the encoding for the invalid NV predicate operand. This test checks that 
+# the disassembler is correctly disambiguating and decoding these instructions.
+
+[0x00 0x00 0x10 0xf1]
+# CHECK: setpan #0
+
+[0x00 0x02 0x10 0xf1]
+# CHECK: setpan #1
+
+[0x00 0x00 0x10 0xe1]
+# CHECK: tst r0, r0
+
+[0x00 0x02 0x10 0xe1]
+# CHECK: tst r0, r0, lsl #4
index 10fea46694eb7f112d9c2e66ce8bdb44e9e7f4ee..3de8c272ffa981f861dd9ff7c4255e5b84ec20b1 100644 (file)
 # CHECK-V8: warning: invalid instruction encoding
 # CHECK-V8: [0xa2,0xff,0x42,0x0f]
 # CHECK-V8: ^
+
+[0x10,0xb6]
+# CHECK-V81a: setpan #0
+# CHECK-V8: warning: invalid instruction encoding
+# CHECK-V8: [0x10,0xb6]
+# CHECK-V8: ^
+
+[0x18,0xb6]
+# CHECK-V81a: setpan #1
+# CHECK-V8: warning: invalid instruction encoding
+# CHECK-V8: [0x18,0xb6]
+# CHECK-V8: ^