mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 01:12:59 +00:00
[ARM] Add v8.1a "Privileged Access Never" extension
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
This commit is contained in:
parent
0b86f54604
commit
5ade5fcee4
@ -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>;
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -172,3 +172,35 @@
|
||||
//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: ^
|
||||
|
@ -34,3 +34,19 @@
|
||||
# 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
|
||||
|
@ -96,3 +96,15 @@
|
||||
# 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: ^
|
||||
|
Loading…
Reference in New Issue
Block a user