[ARM] Add the non-MVE instructions in Arm v8.1-M.

This adds support for the new family of conditional selection /
increment / negation instructions; the low-overhead branch
instructions (e.g. BF, WLS, DLS); the CLRM instruction to zero a whole
list of registers at once; the new VMRS/VMSR and VLDR/VSTR
instructions to get data in and out of 8.1-M system registers,
particularly including the new VPR register used by MVE vector
predication.

To support this, we also add a register name 'zr' (used by the CSEL
family to force one of the inputs to the constant 0), and operand
types for lists of registers that are also allowed to include APSR or
VPR (used by CLRM). The VLDR/VSTR instructions also need some new
addressing modes.

The low-overhead branch instructions exist in their own separate
architecture extension, which we treat as enabled by default, but you
can say -mattr=-lob or equivalent to turn it off.

Reviewers: dmgreen, samparker, SjoerdMeijer, t.p.northover

Reviewed By: samparker

Subscribers: miyuki, javed.absar, kristof.beyls, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D62667

llvm-svn: 362953
This commit is contained in:
Simon Tatham 2019-06-10 15:36:34 +00:00
parent 76c7f236e1
commit fe244eb083
35 changed files with 5063 additions and 92 deletions

View File

@ -135,4 +135,7 @@ ELF_RELOC(R_ARM_PRIVATE_15, 0x7f)
ELF_RELOC(R_ARM_ME_TOO, 0x80)
ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81)
ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82)
ELF_RELOC(R_ARM_THM_BF16, 0x88)
ELF_RELOC(R_ARM_THM_BF12, 0x89)
ELF_RELOC(R_ARM_THM_BF18, 0x8a)
ELF_RELOC(R_ARM_IRELATIVE, 0xa0)

View File

@ -121,7 +121,7 @@ ARM_ARCH("armv8-m.base", ARMV8MBaseline, "8-M.Baseline", "v8m.base",
ARM_ARCH("armv8-m.main", ARMV8MMainline, "8-M.Mainline", "v8m.main",
ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIVTHUMB)
ARM_ARCH("armv8.1-m.main", ARMV8_1MMainline, "8.1-M.Mainline", "v8.1m.main",
ARMBuildAttrs::CPUArch::v8_1_M_Main, FK_FP_ARMV8_FULLFP16_SP_D16, ARM::AEK_HWDIVTHUMB | ARM::AEK_RAS)
ARMBuildAttrs::CPUArch::v8_1_M_Main, FK_FP_ARMV8_FULLFP16_SP_D16, ARM::AEK_HWDIVTHUMB | ARM::AEK_RAS | ARM::AEK_LOB)
// Non-standard Arch names.
ARM_ARCH("iwmmxt", IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE,
FK_NONE, ARM::AEK_NONE)
@ -164,6 +164,7 @@ ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr)
ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
ARM_ARCH_EXT_NAME("fp16fml", ARM::AEK_FP16FML, "+fp16fml", "-fp16fml")
ARM_ARCH_EXT_NAME("sb", ARM::AEK_SB, "+sb", "-sb")
ARM_ARCH_EXT_NAME("lob", ARM::AEK_LOB, "+lob", "-lob")
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME

View File

@ -51,6 +51,7 @@ enum ArchExtKind : unsigned {
AEK_SVE2SHA3 = 1 << 22,
AEK_BITPERM = 1 << 23,
AEK_FP_DP = 1 << 24,
AEK_LOB = 1 << 25,
// Unsupported extensions.
AEK_OS = 0x8000000,
AEK_IWMMXT = 0x10000000,

View File

@ -405,6 +405,12 @@ def FeatureUseAA : SubtargetFeature<"use-aa", "UseAA", "true",
def FeatureSB : SubtargetFeature<"sb", "HasSB", "true",
"Enable v8.5a Speculation Barrier" >;
// Armv8.1-M extensions
def FeatureLOB : SubtargetFeature<"lob", "HasLOB", "true",
"Enable Low Overhead Branch "
"extensions">;
//===----------------------------------------------------------------------===//
// ARM architecture class
//
@ -805,7 +811,8 @@ def ARMv81mMainline : Architecture<"armv8.1-m.main", "ARMv81mMainline",
Feature8MSecExt,
FeatureAcquireRelease,
FeatureMClass,
FeatureRAS]>;
FeatureRAS,
FeatureLOB]>;
// Aliases
def IWMMXT : Architecture<"iwmmxt", "ARMv5te", [ARMv5te]>;

View File

@ -762,6 +762,14 @@ void ARMAsmPrinter::emitAttributes() {
//===----------------------------------------------------------------------===//
static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
unsigned LabelId, MCContext &Ctx) {
MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
+ "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));
return Label;
}
static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,
unsigned LabelId, MCContext &Ctx) {
@ -1436,6 +1444,65 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
case ARM::t2BFi:
case ARM::t2BFic:
case ARM::t2BFLi:
case ARM::t2BFr:
case ARM::t2BFLr: {
// This is a Branch Future instruction.
const MCExpr *BranchLabel = MCSymbolRefExpr::create(
getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
MI->getOperand(0).getIndex(), OutContext),
OutContext);
auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
if (MI->getOperand(1).isReg()) {
// For BFr/BFLr
MCInst.addReg(MI->getOperand(1).getReg());
} else {
// For BFi/BFLi/BFic
const MCExpr *BranchTarget;
if (MI->getOperand(1).isMBB())
BranchTarget = MCSymbolRefExpr::create(
MI->getOperand(1).getMBB()->getSymbol(), OutContext);
else if (MI->getOperand(1).isGlobal()) {
const GlobalValue *GV = MI->getOperand(1).getGlobal();
BranchTarget = MCSymbolRefExpr::create(
GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
} else if (MI->getOperand(1).isSymbol()) {
BranchTarget = MCSymbolRefExpr::create(
GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
OutContext);
}
MCInst.addExpr(BranchTarget);
}
if (Opc == ARM::t2BFic) {
const MCExpr *ElseLabel = MCSymbolRefExpr::create(
getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
MI->getOperand(2).getIndex(), OutContext),
OutContext);
MCInst.addExpr(ElseLabel);
MCInst.addImm(MI->getOperand(3).getImm());
} else {
MCInst.addImm(MI->getOperand(2).getImm())
.addReg(MI->getOperand(3).getReg());
}
EmitToStreamer(*OutStreamer, MCInst);
return;
}
case ARM::t2BF_LabelPseudo: {
// This is a pseudo op for a label used by a branch future instruction
// Emit the label.
OutStreamer->EmitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),
getFunctionNumber(),
MI->getOperand(0).getIndex(), OutContext));
return;
}
case ARM::tPICADD: {
// This is a pseudo op for a label + instruction sequence, which looks like:
// LPC0:

View File

@ -203,6 +203,8 @@ getReservedRegs(const MachineFunction &MF) const {
for (MCSubRegIterator SI(Reg, this); SI.isValid(); ++SI)
if (Reserved.test(*SI))
markSuperRegs(Reserved, Reg);
// For v8.1m architecture
markSuperRegs(Reserved, ARM::ZR);
assert(checkAllSuperRegsMarked(Reserved));
return Reserved;

View File

@ -367,6 +367,16 @@ def reglist : Operand<i32> {
let DecoderMethod = "DecodeRegListOperand";
}
// A list of general purpose registers and APSR separated by comma.
// Used by CLRM
def RegListWithAPSRAsmOperand : AsmOperandClass { let Name = "RegListWithAPSR"; }
def reglist_with_apsr : Operand<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = RegListWithAPSRAsmOperand;
let PrintMethod = "printRegisterList";
let DecoderMethod = "DecodeRegListOperand";
}
def GPRPairOp : RegisterOperand<GPRPair, "printGPRPairOperand">;
def DPRRegListAsmOperand : AsmOperandClass {
@ -391,6 +401,21 @@ def spr_reglist : Operand<i32> {
let DecoderMethod = "DecodeSPRRegListOperand";
}
def FPSRegListWithVPRAsmOperand : AsmOperandClass { let Name =
"FPSRegListWithVPR"; }
def fp_sreglist_with_vpr : Operand<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = FPSRegListWithVPRAsmOperand;
let PrintMethod = "printRegisterList";
}
def FPDRegListWithVPRAsmOperand : AsmOperandClass { let Name =
"FPDRegListWithVPR"; }
def fp_dreglist_with_vpr : Operand<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = FPDRegListWithVPRAsmOperand;
let PrintMethod = "printRegisterList";
}
// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
def cpinst_operand : Operand<i32> {
let PrintMethod = "printCPInstOperand";

View File

@ -150,6 +150,26 @@ def lo5AllOne : PatLeaf<(i32 imm), [{
// Define Thumb2 specific addressing modes.
// t2_addr_offset_none := reg
def MemNoOffsetT2AsmOperand
: AsmOperandClass { let Name = "MemNoOffsetT2"; }
def t2_addr_offset_none : MemOperand {
let PrintMethod = "printAddrMode7Operand";
let DecoderMethod = "DecodeGPRnopcRegisterClass";
let ParserMatchClass = MemNoOffsetT2AsmOperand;
let MIOperandInfo = (ops GPRnopc:$base);
}
// t2_nosp_addr_offset_none := reg
def MemNoOffsetT2NoSpAsmOperand
: AsmOperandClass { let Name = "MemNoOffsetT2NoSp"; }
def t2_nosp_addr_offset_none : MemOperand {
let PrintMethod = "printAddrMode7Operand";
let DecoderMethod = "Decodet2rGPRRegisterClass";
let ParserMatchClass = MemNoOffsetT2NoSpAsmOperand;
let MIOperandInfo = (ops t2rGPR:$base);
}
// t2addrmode_imm12 := reg + imm12
def t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";}
def t2addrmode_imm12 : MemOperand,
@ -247,10 +267,38 @@ def t2addrmode_imm8s4_pre : T2AddrMode_Imm8s4 {
def t2am_imm8s4_offset_asmoperand : AsmOperandClass { let Name = "Imm8s4"; }
def t2am_imm8s4_offset : MemOperand {
let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
let EncoderMethod = "getT2Imm8s4OpValue";
let EncoderMethod = "getT2ScaledImmOpValue<8,2>";
let DecoderMethod = "DecodeT2Imm8S4";
}
// t2addrmode_imm7s4 := reg +/- (imm7 << 2)
def MemImm7s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm7s4Offset";}
class T2AddrMode_Imm7s4 : MemOperand {
let EncoderMethod = "getT2AddrModeImm7s4OpValue";
let DecoderMethod = "DecodeT2AddrModeImm7<2,0>";
let ParserMatchClass = MemImm7s4OffsetAsmOperand;
let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm);
}
def t2addrmode_imm7s4 : T2AddrMode_Imm7s4 {
// They are printed the same way as the imm8 version
let PrintMethod = "printT2AddrModeImm8s4Operand<false>";
}
def t2addrmode_imm7s4_pre : T2AddrMode_Imm7s4 {
// They are printed the same way as the imm8 version
let PrintMethod = "printT2AddrModeImm8s4Operand<true>";
}
def t2am_imm7s4_offset_asmoperand : AsmOperandClass { let Name = "Imm7s4"; }
def t2am_imm7s4_offset : MemOperand {
// They are printed the same way as the imm8 version
let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
let ParserMatchClass = t2am_imm7s4_offset_asmoperand;
let EncoderMethod = "getT2ScaledImmOpValue<7,2>";
let DecoderMethod = "DecodeT2Imm7S4";
}
// t2addrmode_imm0_1020s4 := reg + (imm8 << 2)
def MemImm0_1020s4OffsetAsmOperand : AsmOperandClass {
let Name = "MemImm0_1020s4Offset";
@ -289,6 +337,55 @@ def addrmode_tbh : MemOperand {
let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
}
// Define ARMv8.1-M specific addressing modes.
// Label operands for BF/BFL/WLS/DLS/LE
class BFLabelOp<string signed, string isNeg, string size, string fixup>
: Operand<OtherVT> {
let EncoderMethod = !strconcat("getBFTargetOpValue<", isNeg, ", ",
fixup, ">");
let OperandType = "OPERAND_PCREL";
let DecoderMethod = !strconcat("DecodeBFLabelOperand<", signed, ", ",
isNeg, ", ", size, ">");
}
def bflabel_u4 : BFLabelOp<"false", "false", "4", "ARM::fixup_bf_branch">;
def bflabel_s12 : BFLabelOp<"true", "false", "12", "ARM::fixup_bfc_target">;
def bflabel_s16 : BFLabelOp<"true", "false", "16", "ARM::fixup_bf_target">;
def bflabel_s18 : BFLabelOp<"true", "false", "18", "ARM::fixup_bfl_target">;
def wlslabel_u11 : BFLabelOp<"false", "false", "11", "ARM::fixup_wls">;
def lelabel_u11 : BFLabelOp<"false", "true", "11", "ARM::fixup_le">;
def bfafter_target : Operand<OtherVT> {
let EncoderMethod = "getBFAfterTargetOpValue";
let OperandType = "OPERAND_PCREL";
let DecoderMethod = "DecodeBFAfterTargetOperand";
}
// pred operand excluding AL
def pred_noal_asmoperand : AsmOperandClass {
let Name = "CondCodeNoAL";
let RenderMethod = "addITCondCodeOperands";
let PredicateMethod = "isITCondCodeNoAL";
let ParserMethod = "parseITCondCode";
}
def pred_noal : Operand<i32> {
let PrintMethod = "printMandatoryPredicateOperand";
let ParserMatchClass = pred_noal_asmoperand;
let DecoderMethod = "DecodePredNoALOperand";
}
// CSEL aliases inverted predicate
def pred_noal_inv_asmoperand : AsmOperandClass {
let Name = "CondCodeNoALInv";
let RenderMethod = "addITCondCodeInvOperands";
let PredicateMethod = "isITCondCodeNoAL";
let ParserMethod = "parseITCondCode";
}
def pred_noal_inv : Operand<i32> {
let PrintMethod = "printMandatoryInvertedPredicateOperand";
let ParserMatchClass = pred_noal_inv_asmoperand;
}
//===----------------------------------------------------------------------===//
// Multiclass helpers...
//
@ -4911,3 +5008,213 @@ def : t2InstAlias<"pld${p} $addr",
def : InstAlias<"pli${p} $addr",
(t2PLIpci t2ldr_pcrel_imm12:$addr, pred:$p), 0>,
Requires<[IsThumb2,HasV7]>;
//===----------------------------------------------------------------------===//
// ARMv8.1m instructions
//
class V8_1MI<dag oops, dag iops, AddrMode am, InstrItinClass itin, string asm,
string ops, string cstr, list<dag> pattern>
: Thumb2XI<oops, iops, am, 4, itin, !strconcat(asm, "\t", ops), cstr,
pattern>,
Requires<[HasV8_1MMainline]>;
def t2CLRM : V8_1MI<(outs),
(ins pred:$p, reglist_with_apsr:$regs, variable_ops),
AddrModeNone, NoItinerary, "clrm", "${p}\t$regs", "", []> {
bits<16> regs;
let Inst{31-16} = 0b1110100010011111;
let Inst{15-14} = regs{15-14};
let Inst{13} = 0b0;
let Inst{12-0} = regs{12-0};
}
class t2BF<dag iops, string asm, string ops>
: V8_1MI<(outs ), iops, AddrModeNone, NoItinerary, asm, ops, "", []> {
let Inst{31-27} = 0b11110;
let Inst{15-14} = 0b11;
let Inst{12} = 0b0;
let Inst{0} = 0b1;
let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB];
}
def t2BF_LabelPseudo
: t2PseudoInst<(outs ), (ins pclabel:$cp), 0, NoItinerary, []> {
let isTerminator = 1;
let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB];
}
def t2BFi : t2BF<(ins bflabel_u4:$b_label, bflabel_s16:$label, pred:$p),
!strconcat("bf", "${p}"), "$b_label, $label"> {
bits<4> b_label;
bits<16> label;
let Inst{26-23} = b_label{3-0};
let Inst{22-21} = 0b10;
let Inst{20-16} = label{15-11};
let Inst{13} = 0b1;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
}
def t2BFic : t2BF<(ins bflabel_u4:$b_label, bflabel_s12:$label,
bfafter_target:$ba_label, pred_noal:$bcond), "bfcsel",
"$b_label, $label, $ba_label, $bcond"> {
bits<4> bcond;
bits<12> label;
bits<1> ba_label;
bits<4> b_label;
let Inst{26-23} = b_label{3-0};
let Inst{22} = 0b0;
let Inst{21-18} = bcond{3-0};
let Inst{17} = ba_label{0};
let Inst{16} = label{11};
let Inst{13} = 0b1;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
}
def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
!strconcat("bfx", "${p}"), "$b_label, $Rn"> {
bits<4> b_label;
bits<4> Rn;
let Inst{26-23} = b_label{3-0};
let Inst{22-20} = 0b110;
let Inst{19-16} = Rn{3-0};
let Inst{13-1} = 0b1000000000000;
}
def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p),
!strconcat("bfl", "${p}"), "$b_label, $label"> {
bits<4> b_label;
bits<18> label;
let Inst{26-23} = b_label{3-0};
let Inst{22-16} = label{17-11};
let Inst{13} = 0b0;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
}
def t2BFLr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
!strconcat("bflx", "${p}"), "$b_label, $Rn"> {
bits<4> b_label;
bits<4> Rn;
let Inst{26-23} = b_label{3-0};
let Inst{22-20} = 0b111;
let Inst{19-16} = Rn{3-0};
let Inst{13-1} = 0b1000000000000;
}
class t2LOL<dag oops, dag iops, string asm, string ops>
: V8_1MI<oops, iops, AddrModeNone, NoItinerary, asm, ops, "", [] > {
let Inst{31-23} = 0b111100000;
let Inst{15-14} = 0b11;
let Inst{0} = 0b1;
let isBranch = 1;
let isTerminator = 1;
let DecoderMethod = "DecodeLOLoop";
let Predicates = [IsThumb2, HasV8_1MMainline, HasLOB];
}
def t2WLS : t2LOL<(outs GPRlr:$LR),
(ins rGPR:$Rn, wlslabel_u11:$label),
"wls", "$LR, $Rn, $label"> {
bits<4> Rn;
bits<11> label;
let Inst{22-20} = 0b100;
let Inst{19-16} = Rn{3-0};
let Inst{13-12} = 0b00;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
let usesCustomInserter = 1;
}
def t2DLS : t2LOL<(outs GPRlr:$LR), (ins rGPR:$Rn),
"dls", "$LR, $Rn"> {
bits<4> Rn;
let isBranch = 0;
let isTerminator = 0;
let Inst{22-20} = 0b100;
let Inst{19-16} = Rn{3-0};
let Inst{13-1} = 0b1000000000000;
let usesCustomInserter = 1;
}
def t2LEUpdate : t2LOL<(outs GPRlr:$LRout),
(ins GPRlr:$LRin, lelabel_u11:$label),
"le", "$LRin, $label"> {
bits<11> label;
let Inst{22-16} = 0b0001111;
let Inst{13-12} = 0b00;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
let usesCustomInserter = 1;
}
def t2LE : t2LOL<(outs ), (ins lelabel_u11:$label), "le", "$label"> {
bits<11> label;
let Inst{22-16} = 0b0101111;
let Inst{13-12} = 0b00;
let Inst{11} = label{0};
let Inst{10-1} = label{10-1};
}
let Uses = [CPSR] in {
class CS<string iname, list<dag> pattern=[]>
: V8_1MI<(outs rGPR:$Rd), (ins GPRwithZR:$Rn, GPRwithZR:$Rm, pred_noal:$fcond),
AddrModeNone, NoItinerary, iname, "$Rd, $Rn, $Rm, $fcond", "", pattern> {
bits<4> Rd;
bits<4> Rm;
bits<4> Rn;
bits<4> fcond;
let Inst{31-20} = 0b111010100101;
let Inst{19-16} = Rn{3-0};
let Inst{11-8} = Rd{3-0};
let Inst{7-4} = fcond{3-0};
let Inst{3-0} = Rm{3-0};
}
}
def t2CSEL : CS<"csel"> {
let Inst{15-12} = 0b1000;
}
def t2CSINC : CS<"csinc"> {
let Inst{15-12} = 0b1001;
}
def t2CSINV : CS<"csinv"> {
let Inst{15-12} = 0b1010;
}
def t2CSNEG : CS<"csneg"> {
let Inst{15-12} = 0b1011;
}
// CS aliases.
let Predicates = [HasV8_1MMainline] in {
def : InstAlias<"csetm\t$Rd, $fcond",
(t2CSINV rGPR:$Rd, ZR, ZR, pred_noal_inv:$fcond)>;
def : InstAlias<"cset\t$Rd, $fcond",
(t2CSINC rGPR:$Rd, ZR, ZR, pred_noal_inv:$fcond)>;
def : InstAlias<"cinc\t$Rd, $Rn, $fcond",
(t2CSINC rGPR:$Rd, GPRwithZR:$Rn, GPRwithZR:$Rn, pred_noal_inv:$fcond)>;
def : InstAlias<"cinv\t$Rd, $Rn, $fcond",
(t2CSINV rGPR:$Rd, GPRwithZR:$Rn, GPRwithZR:$Rn, pred_noal_inv:$fcond)>;
def : InstAlias<"cneg\t$Rd, $Rn, $fcond",
(t2CSNEG rGPR:$Rd, GPRwithZR:$Rn, GPRwithZR:$Rn, pred_noal_inv:$fcond)>;
}

View File

@ -2299,14 +2299,14 @@ class MovFromVFP<bits<4> opc19_16, dag oops, dag iops, string opc, string asm,
let Inst{3-0} = 0b0000;
}
// APSR is the application level alias of CPSR. This FPSCR N, Z, C, V flags
// to APSR.
let Defs = [CPSR], Uses = [FPSCR_NZCV], Predicates = [HasFPRegs],
Rt = 0b1111 /* apsr_nzcv */ in
def FMSTAT : MovFromVFP<0b0001 /* fpscr */, (outs), (ins),
"vmrs", "\tAPSR_nzcv, fpscr", [(arm_fmstat)]>;
let DecoderMethod = "DecodeForVMRSandVMSR" in {
// APSR is the application level alias of CPSR. This FPSCR N, Z, C, V flags
// to APSR.
let Defs = [CPSR], Uses = [FPSCR_NZCV], Predicates = [HasFPRegs],
Rt = 0b1111 /* apsr_nzcv */ in
def FMSTAT : MovFromVFP<0b0001 /* fpscr */, (outs), (ins),
"vmrs", "\tAPSR_nzcv, fpscr", [(arm_fmstat)]>;
// Application level FPSCR -> GPR
let hasSideEffects = 1, Uses = [FPSCR], Predicates = [HasFPRegs] in
def VMRS : MovFromVFP<0b0001 /* fpscr */, (outs GPRnopc:$Rt), (ins),
@ -2331,6 +2331,33 @@ let DecoderMethod = "DecodeForVMRSandVMSR" in {
"vmrs", "\t$Rt, fpinst", []>;
def VMRS_FPINST2 : MovFromVFP<0b1010 /* fpinst2 */, (outs GPRnopc:$Rt),
(ins), "vmrs", "\t$Rt, fpinst2", []>;
let Predicates = [HasV8_1MMainline, HasFPRegs] in {
// System level FPSCR_NZCVQC -> GPR
def VMRS_FPSCR_NZCVQC
: MovFromVFP<0b0010 /* fpscr_nzcvqc */,
(outs GPR:$Rt), (ins cl_FPSCR_NZCV:$fpscr_in),
"vmrs", "\t$Rt, fpscr_nzcvqc", []>;
}
}
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
// System level FPSCR -> GPR, with context saving for security extensions
def VMRS_FPCXTNS : MovFromVFP<0b1110 /* fpcxtns */, (outs GPR:$Rt), (ins),
"vmrs", "\t$Rt, fpcxtns", []>;
}
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
// System level FPSCR -> GPR, with context saving for security extensions
def VMRS_FPCXTS : MovFromVFP<0b1111 /* fpcxts */, (outs GPR:$Rt), (ins),
"vmrs", "\t$Rt, fpcxts", []>;
}
let Predicates = [HasV8_1MMainline, HasMVEInt] in {
// System level VPR/P0 -> GPR
let Uses = [VPR] in
def VMRS_VPR : MovFromVFP<0b1100 /* vpr */, (outs GPR:$Rt), (ins),
"vmrs", "\t$Rt, vpr", []>;
def VMRS_P0 : MovFromVFP<0b1101 /* p0 */, (outs GPR:$Rt), (ins VCCR:$cond),
"vmrs", "\t$Rt, p0", []>;
}
}
@ -2353,6 +2380,7 @@ class MovToVFP<bits<4> opc19_16, dag oops, dag iops, string opc, string asm,
let Inst{11-8} = 0b1010;
let Inst{7} = 0;
let Inst{4} = 1;
let Predicates = [HasVFP2];
}
let DecoderMethod = "DecodeForVMRSandVMSR" in {
@ -2373,6 +2401,33 @@ let DecoderMethod = "DecodeForVMRSandVMSR" in {
def VMSR_FPINST2 : MovToVFP<0b1010 /* fpinst2 */, (outs), (ins GPRnopc:$src),
"vmsr", "\tfpinst2, $src", []>;
}
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
// System level GPR -> FPSCR with context saving for security extensions
def VMSR_FPCXTNS : MovToVFP<0b1110 /* fpcxtns */, (outs), (ins GPR:$src),
"vmsr", "\tfpcxtns, $src", []>;
}
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
// System level GPR -> FPSCR with context saving for security extensions
def VMSR_FPCXTS : MovToVFP<0b1111 /* fpcxts */, (outs), (ins GPR:$src),
"vmsr", "\tfpcxts, $src", []>;
}
let Predicates = [HasV8_1MMainline, HasFPRegs] in {
// System level GPR -> FPSCR_NZCVQC
def VMSR_FPSCR_NZCVQC
: MovToVFP<0b0010 /* fpscr_nzcvqc */,
(outs cl_FPSCR_NZCV:$fpscr_out), (ins GPR:$src),
"vmsr", "\tfpscr_nzcvqc, $src", []>;
}
let Predicates = [HasV8_1MMainline, HasMVEInt] in {
// System level GPR -> VPR/P0
let Defs = [VPR] in
def VMSR_VPR : MovToVFP<0b1100 /* vpr */, (outs), (ins GPR:$src),
"vmsr", "\tvpr, $src", []>;
def VMSR_P0 : MovToVFP<0b1101 /* p0 */, (outs VCCR:$cond), (ins GPR:$src),
"vmsr", "\tp0, $src", []>;
}
}
//===----------------------------------------------------------------------===//
@ -2549,3 +2604,126 @@ def : VFP3InstAlias<"fconstd${p} $Dd, $val",
(FCONSTD DPR:$Dd, vfp_f64imm:$val, pred:$p)>;
def : VFP3InstAlias<"fconsts${p} $Sd, $val",
(FCONSTS SPR:$Sd, vfp_f32imm:$val, pred:$p)>;
def VSCCLRMD : VFPXI<(outs), (ins pred:$p, fp_dreglist_with_vpr:$regs, variable_ops),
AddrModeNone, 4, IndexModeNone, VFPMiscFrm, NoItinerary,
"vscclrm{$p}\t$regs", "", []>, Sched<[]> {
bits<13> regs;
let Inst{31-23} = 0b111011001;
let Inst{22} = regs{12};
let Inst{21-16} = 0b011111;
let Inst{15-12} = regs{11-8};
let Inst{11-8} = 0b1011;
let Inst{7-0} = regs{7-0};
let DecoderMethod = "DecodeVSCCLRM";
list<Predicate> Predicates = [HasV8_1MMainline, Has8MSecExt];
}
def VSCCLRMS : VFPXI<(outs), (ins pred:$p, fp_sreglist_with_vpr:$regs, variable_ops),
AddrModeNone, 4, IndexModeNone, VFPMiscFrm, NoItinerary,
"vscclrm{$p}\t$regs", "", []>, Sched<[]> {
bits<13> regs;
let Inst{31-23} = 0b111011001;
let Inst{22} = regs{8};
let Inst{21-16} = 0b011111;
let Inst{15-12} = regs{12-9};
let Inst{11-8} = 0b1010;
let Inst{7-0} = regs{7-0};
let DecoderMethod = "DecodeVSCCLRM";
list<Predicate> Predicates = [HasV8_1MMainline, Has8MSecExt];
}
//===----------------------------------------------------------------------===//
// Store VFP System Register to memory.
//
class vfp_vstrldr<bit opc, bit P, bit W, bits<4> SysReg, string sysreg,
dag oops, dag iops, IndexMode im, string Dest, string cstr>
: VFPI<oops, iops, AddrModeT2_i7s4, 4, im, VFPLdStFrm, IIC_fpSTAT,
!if(opc,"vldr","vstr"), !strconcat("\t", sysreg, ", ", Dest), cstr, []>,
Sched<[]> {
bits<12> addr;
let Inst{27-25} = 0b110;
let Inst{24} = P;
let Inst{23} = addr{7};
let Inst{22} = SysReg{3};
let Inst{21} = W;
let Inst{20} = opc;
let Inst{19-16} = addr{11-8};
let Inst{15-13} = SysReg{2-0};
let Inst{12-7} = 0b011111;
let Inst{6-0} = addr{6-0};
list<Predicate> Predicates = [HasFPRegs, HasV8_1MMainline];
let mayLoad = opc;
let mayStore = !if(opc, 0b0, 0b1);
let hasSideEffects = 1;
}
multiclass vfp_vstrldr_sysreg<bit opc, bits<4> SysReg, string sysreg,
dag oops=(outs), dag iops=(ins)> {
def _off :
vfp_vstrldr<opc, 1, 0, SysReg, sysreg,
oops, !con(iops, (ins t2addrmode_imm7s4:$addr)),
IndexModePost, "$addr", "" > {
let DecoderMethod = "DecodeVSTRVLDR_SYSREG<false>";
}
def _pre :
vfp_vstrldr<opc, 1, 1, SysReg, sysreg,
!con(oops, (outs GPRnopc:$wb)),
!con(iops, (ins t2addrmode_imm7s4_pre:$addr)),
IndexModePre, "$addr!", "$addr.base = $wb"> {
let DecoderMethod = "DecodeVSTRVLDR_SYSREG<true>";
}
def _post :
vfp_vstrldr<opc, 0, 1, SysReg, sysreg,
!con(oops, (outs GPRnopc:$wb)),
!con(iops, (ins t2_addr_offset_none:$Rn,
t2am_imm7s4_offset:$addr)),
IndexModePost, "$Rn$addr", "$Rn.base = $wb"> {
bits<4> Rn;
let Inst{19-16} = Rn{3-0};
let DecoderMethod = "DecodeVSTRVLDR_SYSREG<true>";
}
}
let Defs = [FPSCR] in {
defm VSTR_FPSCR : vfp_vstrldr_sysreg<0b0,0b0001, "fpscr">;
defm VSTR_FPSCR_NZCVQC : vfp_vstrldr_sysreg<0b0,0b0010, "fpscr_nzcvqc">;
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
defm VSTR_FPCXTNS : vfp_vstrldr_sysreg<0b0,0b1110, "fpcxtns">;
defm VSTR_FPCXTS : vfp_vstrldr_sysreg<0b0,0b1111, "fpcxts">;
}
}
let Predicates = [HasV8_1MMainline, HasMVEInt] in {
let Uses = [VPR] in {
defm VSTR_VPR : vfp_vstrldr_sysreg<0b0,0b1100, "vpr">;
}
defm VSTR_P0 : vfp_vstrldr_sysreg<0b0,0b1101, "p0",
(outs), (ins VCCR:$P0)>;
}
let Uses = [FPSCR] in {
defm VLDR_FPSCR : vfp_vstrldr_sysreg<0b1,0b0001, "fpscr">;
defm VLDR_FPSCR_NZCVQC : vfp_vstrldr_sysreg<0b1,0b0010, "fpscr_nzcvqc">;
let Predicates = [HasV8_1MMainline, Has8MSecExt] in {
defm VLDR_FPCXTNS : vfp_vstrldr_sysreg<0b1,0b1110, "fpcxtns">;
defm VLDR_FPCXTS : vfp_vstrldr_sysreg<0b1,0b1111, "fpcxts">;
}
}
let Predicates = [HasV8_1MMainline, HasMVEInt] in {
let Defs = [VPR] in {
defm VLDR_VPR : vfp_vstrldr_sysreg<0b1,0b1100, "vpr">;
}
defm VLDR_P0 : vfp_vstrldr_sysreg<0b1,0b1101, "p0",
(outs VCCR:$P0), (ins)>;
}

View File

@ -95,6 +95,8 @@ def HasCRC : Predicate<"Subtarget->hasCRC()">,
AssemblerPredicate<"FeatureCRC", "crc">;
def HasRAS : Predicate<"Subtarget->hasRAS()">,
AssemblerPredicate<"FeatureRAS", "ras">;
def HasLOB : Predicate<"Subtarget->hasLOB()">,
AssemblerPredicate<"FeatureLOB", "lob">;
def HasFP16 : Predicate<"Subtarget->hasFP16()">,
AssemblerPredicate<"FeatureFP16","half-float conversions">;
def HasFullFP16 : Predicate<"Subtarget->hasFullFP16()">,

View File

@ -197,6 +197,17 @@ def MVFR0 : ARMReg<7, "mvfr0">;
def FPEXC : ARMReg<8, "fpexc">;
def FPINST : ARMReg<9, "fpinst">;
def FPINST2 : ARMReg<10, "fpinst2">;
// These encodings aren't actual instruction encodings, their encoding depends
// on the instruction they are used in and for VPR 32 was chosen such that it
// always comes last in spr_reglist_with_vpr.
def VPR : ARMReg<32, "vpr">;
def FPSCR_NZCVQC
: ARMReg<2, "fpscr_nzcvqc">;
def P0 : ARMReg<13, "p0">;
def FPCXTNS : ARMReg<14, "fpcxtns">;
def FPCXTS : ARMReg<15, "fpcxts">;
def ZR : ARMReg<15, "zr">, DwarfRegNum<[15]>;
// Register classes.
//
@ -245,6 +256,21 @@ def GPRwithAPSR : RegisterClass<"ARM", [i32], 32, (add (sub GPR, PC), APSR_NZCV)
let DiagnosticString = "operand must be a register in range [r0, r14] or apsr_nzcv";
}
// GPRs without the PC and SP registers but with APSR. Used by CLRM instruction.
def GPRwithAPSRnosp : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12), LR, APSR)> {
let isAllocatable = 0;
}
def GPRwithZR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12),
LR, ZR)> {
let AltOrders = [(add LR, GPRwithZR), (trunc GPRwithZR, 8)];
let AltOrderSelect = [{
return 1 + MF.getSubtarget<ARMSubtarget>().isThumb1Only();
}];
let DiagnosticString = "operand must be a register in range [r0, r12] or r14 or zr";
}
// GPRsp - Only the SP is legal. Used by Thumb1 instructions that want the
// implied SP argument list.
// FIXME: It would be better to not use this at all and refactor the
@ -254,6 +280,10 @@ def GPRsp : RegisterClass<"ARM", [i32], 32, (add SP)> {
let DiagnosticString = "operand must be a register sp";
}
// GPRlr - Only LR is legal. Used by ARMv8.1-M Low Overhead Loop instructions
// where LR is the only legal loop counter register.
def GPRlr : RegisterClass<"ARM", [i32], 32, (add LR)>;
// restricted GPR register class. Many Thumb2 instructions allow the full
// register range for operands, but have undefined behaviours when PC
// or SP (R13 or R15) are used. The ARM ISA refers to these operands
@ -266,6 +296,15 @@ def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
let DiagnosticType = "rGPR";
}
// t2rGPR : All Thumb 2 registers with the exception of SP and PC.
def t2rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
let AltOrders = [(add LR, t2rGPR), (trunc t2rGPR, 8)];
let AltOrderSelect = [{
return 1 + MF.getSubtarget<ARMSubtarget>().isThumb1Only();
}];
let DiagnosticType = "rGPR";
}
// Thumb registers are R0-R7 normally. Some instructions can still use
// the general GPR register class above (MOV, e.g.)
def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)> {
@ -298,6 +337,15 @@ def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> {
let isAllocatable = 0;
}
// MVE Condition code register.
def VCCR : RegisterClass<"ARM", [i32, v16i1, v8i1, v4i1], 32, (add VPR)> {
// let CopyCost = -1; // Don't allow copying of status registers.
}
// FPSCR, when the flags at the top of it are used as the input or
// output to an instruction such as MVE VADC.
def cl_FPSCR_NZCV : RegisterClass<"ARM", [i32], 32, (add FPSCR_NZCV)>;
// Scalar single precision floating point register class..
// FIXME: Allocation order changed to s0, s2, ... or s0, s4, ... as a quick hack
// to avoid partial-write dependencies on D or Q (depending on platform)
@ -348,6 +396,13 @@ def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32, v4f16], 6
let DiagnosticType = "DPR";
}
// Scalar single and double precision floating point and VPR register class,
// this is only used for parsing, don't use it anywhere else as the size and
// types don't match!
def FPWithVPR : RegisterClass<"ARM", [f32], 32, (add SPR, DPR, VPR)> {
let isAllocatable = 0;
}
// Subset of DPR that are accessible with VFP2 (and so that also have
// 32-bit SPR subregs).
def DPR_VFP2 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32, v4f16], 64,

View File

@ -94,6 +94,9 @@ def CortexA57Model : SchedMachineModel {
// FIXME: Remove when all errors have been fixed.
let FullInstRWOverlapCheck = 0;
let UnsupportedFeatures = [HasV8_1MMainline, HasMVEInt, HasMVEFloat,
HasFPRegsV8_1M];
}
//===----------------------------------------------------------------------===//

View File

@ -343,6 +343,9 @@ protected:
/// HasRAS - if true, the processor supports RAS extensions
bool HasRAS = false;
/// HasLOB - if true, the processor supports the Low Overhead Branch extension
bool HasLOB = false;
/// If true, the instructions "vmov.i32 d0, #0" and "vmov.i32 q0, #0" are
/// particularly effective at zeroing a VFP register.
bool HasZeroCycleZeroing = false;
@ -608,6 +611,7 @@ public:
bool hasDotProd() const { return HasDotProd; }
bool hasCRC() const { return HasCRC; }
bool hasRAS() const { return HasRAS; }
bool hasLOB() const { return HasLOB; }
bool hasVirtualization() const { return HasVirtualization; }
bool useNEONForSinglePrecisionFP() const {

View File

@ -384,7 +384,7 @@ class ARMAsmParser : public MCTargetAsmParser {
int tryParseRegister();
bool tryParseRegisterWithWriteBack(OperandVector &);
int tryParseShiftRegister(OperandVector &);
bool parseRegisterList(OperandVector &);
bool parseRegisterList(OperandVector &, bool EnforceOrder = true);
bool parseMemory(OperandVector &);
bool parseOperand(OperandVector &, StringRef Mnemonic);
bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
@ -479,7 +479,9 @@ class ARMAsmParser : public MCTargetAsmParser {
bool hasV8MMainline() const {
return getSTI().getFeatureBits()[ARM::HasV8MMainlineOps];
}
bool hasV8_1MMainline() const {
return getSTI().getFeatureBits()[ARM::HasV8_1MMainlineOps];
}
bool has8MSecExt() const {
return getSTI().getFeatureBits()[ARM::Feature8MSecExt];
}
@ -660,8 +662,11 @@ class ARMOperand : public MCParsedAsmOperand {
k_VectorIndex,
k_Register,
k_RegisterList,
k_RegisterListWithAPSR,
k_DPRRegisterList,
k_SPRRegisterList,
k_FPSRegisterListWithVPR,
k_FPDRegisterListWithVPR,
k_VectorList,
k_VectorListAllLanes,
k_VectorListIndexed,
@ -862,8 +867,11 @@ public:
}
const SmallVectorImpl<unsigned> &getRegList() const {
assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
Kind == k_SPRRegisterList) && "Invalid access!");
assert((Kind == k_RegisterList || Kind == k_RegisterListWithAPSR ||
Kind == k_DPRRegisterList || Kind == k_SPRRegisterList ||
Kind == k_FPSRegisterListWithVPR ||
Kind == k_FPDRegisterListWithVPR) &&
"Invalid access!");
return Registers;
}
@ -1027,6 +1035,9 @@ public:
bool isImm8s4() const {
return isImmediateS4<-1020, 1020>();
}
bool isImm7s4() const {
return isImmediateS4<-508, 508>();
}
bool isImm0_1020s4() const {
return isImmediateS4<0, 1020>();
}
@ -1168,8 +1179,13 @@ public:
bool isReg() const override { return Kind == k_Register; }
bool isRegList() const { return Kind == k_RegisterList; }
bool isRegListWithAPSR() const {
return Kind == k_RegisterListWithAPSR || Kind == k_RegisterList;
}
bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
bool isFPSRegListWithVPR() const { return Kind == k_FPSRegisterListWithVPR; }
bool isFPDRegListWithVPR() const { return Kind == k_FPDRegisterListWithVPR; }
bool isToken() const override { return Kind == k_Token; }
bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
@ -1250,6 +1266,30 @@ public:
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
(alignOK || Memory.Alignment == Alignment);
}
bool isMemNoOffsetT2(bool alignOK = false, unsigned Alignment = 0) const {
if (!isMem())
return false;
if (!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains(
Memory.BaseRegNum))
return false;
// No offset of any kind.
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
(alignOK || Memory.Alignment == Alignment);
}
bool isMemNoOffsetT2NoSp(bool alignOK = false, unsigned Alignment = 0) const {
if (!isMem())
return false;
if (!ARMMCRegisterClasses[ARM::rGPRRegClassID].contains(
Memory.BaseRegNum))
return false;
// No offset of any kind.
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
(alignOK || Memory.Alignment == Alignment);
}
bool isMemPCRelImm12() const {
if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
@ -1521,7 +1561,22 @@ public:
return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) ||
Val == std::numeric_limits<int32_t>::min();
}
bool isMemImm7s4Offset() const {
// If we have an immediate that's not a constant, treat it as a label
// reference needing a fixup. If it is a constant, it's something else
// and we reject it.
if (isImm() && !isa<MCConstantExpr>(getImm()))
return true;
if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0 ||
!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains(
Memory.BaseRegNum))
return false;
// Immediate offset a multiple of 4 in range [-508, 508].
if (!Memory.OffsetImm) return true;
int64_t Val = Memory.OffsetImm->getValue();
// Special case, #-0 is INT32_MIN.
return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN;
}
bool isMemImm0_1020s4Offset() const {
if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
@ -1993,6 +2048,12 @@ public:
return (Value % Angle == Remainder && Value <= 270);
}
bool isITCondCodeNoAL() const {
if (!isITCondCode()) return false;
auto CC = (ARMCC::CondCodes) getCondCode();
return CC != ARMCC::AL;
}
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
if (!Expr)
@ -2045,6 +2106,11 @@ public:
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode())));
}
void addITCondCodeInvOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(unsigned(ARMCC::getOppositeCondition(getCondCode()))));
}
void addCCOutOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getReg()));
@ -2090,6 +2156,14 @@ public:
Inst.addOperand(MCOperand::createReg(*I));
}
void addRegListWithAPSROperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const SmallVectorImpl<unsigned> &RegList = getRegList();
for (SmallVectorImpl<unsigned>::const_iterator
I = RegList.begin(), E = RegList.end(); I != E; ++I)
Inst.addOperand(MCOperand::createReg(*I));
}
void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
addRegListOperands(Inst, N);
}
@ -2098,6 +2172,14 @@ public:
addRegListOperands(Inst, N);
}
void addFPSRegListWithVPROperands(MCInst &Inst, unsigned N) const {
addRegListOperands(Inst, N);
}
void addFPDRegListWithVPROperands(MCInst &Inst, unsigned N) const {
addRegListOperands(Inst, N);
}
void addRotImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// Encoded as val>>3. The printer handles display as 8, 16, 24.
@ -2185,6 +2267,14 @@ public:
Inst.addOperand(MCOperand::createImm(CE->getValue()));
}
void addImm7s4Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// FIXME: We really want to scale the value here, but the VSTR/VLDR_VSYSR
// instruction don't encode operands that way yet.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::createImm(CE->getValue()));
}
void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate is scaled by four in the encoding and is stored
@ -2319,6 +2409,11 @@ public:
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
}
void addMemNoOffsetT2Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
}
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
int32_t Imm = Memory.OffsetImm->getValue();
@ -2536,6 +2631,22 @@ public:
Inst.addOperand(MCOperand::createImm(Val));
}
void addMemImm7s4OffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
// If we have an immediate that's not a constant, treat it as a label
// reference needing a fixup. If it is a constant, it's something else
// and we reject it.
if (isImm()) {
Inst.addOperand(MCOperand::createExpr(getImm()));
Inst.addOperand(MCOperand::createImm(0));
return;
}
int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
Inst.addOperand(MCOperand::createImm(Val));
}
void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
// The lower two bits are always zero and as such are not encoded.
@ -3045,19 +3156,31 @@ public:
assert(Regs.size() > 0 && "RegList contains no registers?");
KindTy Kind = k_RegisterList;
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second))
Kind = k_DPRRegisterList;
else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
contains(Regs.front().second))
Kind = k_SPRRegisterList;
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(
Regs.front().second)) {
if (Regs.back().second == ARM::VPR)
Kind = k_FPDRegisterListWithVPR;
else
Kind = k_DPRRegisterList;
} else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(
Regs.front().second)) {
if (Regs.back().second == ARM::VPR)
Kind = k_FPSRegisterListWithVPR;
else
Kind = k_SPRRegisterList;
}
// Sort based on the register encoding values.
array_pod_sort(Regs.begin(), Regs.end());
if (Kind == k_RegisterList && Regs.back().second == ARM::APSR)
Kind = k_RegisterListWithAPSR;
auto Op = make_unique<ARMOperand>(Kind);
for (SmallVectorImpl<std::pair<unsigned, unsigned>>::const_iterator
I = Regs.begin(), E = Regs.end(); I != E; ++I)
Op->Registers.push_back(I->second);
Op->StartLoc = StartLoc;
Op->EndLoc = EndLoc;
return Op;
@ -3325,8 +3448,11 @@ void ARMOperand::print(raw_ostream &OS) const {
<< ", width: " << Bitfield.Width << ">";
break;
case k_RegisterList:
case k_RegisterListWithAPSR:
case k_DPRRegisterList:
case k_SPRRegisterList: {
case k_SPRRegisterList:
case k_FPSRegisterListWithVPR:
case k_FPDRegisterListWithVPR: {
OS << "<register_list ";
const SmallVectorImpl<unsigned> &RegList = getRegList();
@ -3753,7 +3879,8 @@ static unsigned getNextRegister(unsigned Reg) {
}
/// Parse a register list.
bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
bool EnforceOrder) {
MCAsmParser &Parser = getParser();
if (Parser.getTok().isNot(AsmToken::LCurly))
return TokError("Token is not a Left Curly Brace");
@ -3786,6 +3913,8 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
else if (ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID];
else
return Error(RegLoc, "invalid register in register list");
@ -3839,14 +3968,32 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
Reg = getDRegFromQReg(Reg);
isQReg = true;
}
if (!RC->contains(Reg) &&
RC->getID() == ARMMCRegisterClasses[ARM::GPRRegClassID].getID() &&
ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) {
// switch the register classes, as GPRwithAPSRnospRegClassID is a partial
// subset of GPRRegClassId except it contains APSR as well.
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID];
}
if (Reg == ARM::VPR && (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID])) {
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID];
EReg = MRI->getEncodingValue(Reg);
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
continue;
}
// The register must be in the same register class as the first.
if (!RC->contains(Reg))
return Error(RegLoc, "invalid register in register list");
// List must be monotonically increasing.
if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
// In most cases, the list must be monotonically increasing. An
// exception is CLRM, which is order-independent anyway, so
// there's no potential for confusion if you write clrm {r2,r1}
// instead of clrm {r1,r2}.
if (EnforceOrder &&
MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
Warning(RegLoc, "register list not in ascending order");
else
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
return Error(RegLoc, "register list not in ascending order");
}
if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
@ -3856,6 +4003,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
}
// VFP register lists must also be contiguous.
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] &&
Reg != OldReg + 1)
return Error(RegLoc, "non-contiguous register range");
EReg = MRI->getEncodingValue(Reg);
@ -5464,7 +5612,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
case AsmToken::LBrac:
return parseMemory(Operands);
case AsmToken::LCurly:
return parseRegisterList(Operands);
return parseRegisterList(Operands, !Mnemonic.startswith("clr"));
case AsmToken::Dollar:
case AsmToken::Hash:
// #42 -> immediate.
@ -5653,7 +5801,12 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Mnemonic == "bxns" || Mnemonic == "blxns" ||
Mnemonic == "vudot" || Mnemonic == "vsdot" ||
Mnemonic == "vcmla" || Mnemonic == "vcadd" ||
Mnemonic == "vfmal" || Mnemonic == "vfmsl")
Mnemonic == "vfmal" || Mnemonic == "vfmsl" ||
Mnemonic == "wls" || Mnemonic == "le" || Mnemonic == "dls" ||
Mnemonic == "csel" || Mnemonic == "csinc" ||
Mnemonic == "csinv" || Mnemonic == "csneg" || Mnemonic == "cinc" ||
Mnemonic == "cinv" || Mnemonic == "cneg" || Mnemonic == "cset" ||
Mnemonic == "csetm")
return Mnemonic;
// First, split out any predication code. Ignore mnemonics we know aren't
@ -5746,7 +5899,12 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
Mnemonic == "vcmla" || Mnemonic == "vcadd" ||
Mnemonic == "vfmal" || Mnemonic == "vfmsl" ||
Mnemonic == "sb" || Mnemonic == "ssbb" ||
Mnemonic == "pssbb") {
Mnemonic == "pssbb" ||
Mnemonic == "bfcsel" || Mnemonic == "wls" ||
Mnemonic == "dls" || Mnemonic == "le" || Mnemonic == "csel" ||
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" ||
Mnemonic == "cinc" || Mnemonic == "cinv" || Mnemonic == "cneg" ||
Mnemonic == "cset" || Mnemonic == "csetm") {
// These mnemonics are never predicable
CanAcceptPredicationCode = false;
} else if (!isThumb()) {
@ -6478,7 +6636,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
} else if (isThumbTwo() && MCID.isPredicable() &&
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
Inst.getOpcode() != ARM::t2Bcc) {
Inst.getOpcode() != ARM::t2Bcc &&
Inst.getOpcode() != ARM::t2BFic) {
return Error(Loc, "predicated instructions must be in IT block");
} else if (!isThumb() && !useImplicitITARM() && MCID.isPredicable() &&
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
@ -6876,6 +7035,77 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
"code specified");
break;
}
case ARM::t2WLS: {
int idx = Opcode == ARM::t2WLS ? 3 : 4;
if (!static_cast<ARMOperand &>(*Operands[idx]).isUnsignedOffset<11, 1>())
return Error(Operands[idx]->getStartLoc(),
"loop end is out of range or not a positive multiple of 2");
break;
}
case ARM::t2LEUpdate: {
if (Inst.getOperand(2).isImm() &&
!(Inst.getOperand(2).getImm() < 0 &&
Inst.getOperand(2).getImm() >= -4094 &&
(Inst.getOperand(2).getImm() & 1) == 0))
return Error(Operands[2]->getStartLoc(),
"loop start is out of range or not a negative multiple of 2");
break;
}
case ARM::t2BFi:
case ARM::t2BFr:
case ARM::t2BFLi:
case ARM::t2BFLr: {
if (!static_cast<ARMOperand &>(*Operands[2]).isUnsignedOffset<4, 1>() ||
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0))
return Error(Operands[2]->getStartLoc(),
"branch location out of range or not a multiple of 2");
if (Opcode == ARM::t2BFi) {
if (!static_cast<ARMOperand &>(*Operands[3]).isSignedOffset<16, 1>())
return Error(Operands[3]->getStartLoc(),
"branch target out of range or not a multiple of 2");
} else if (Opcode == ARM::t2BFLi) {
if (!static_cast<ARMOperand &>(*Operands[3]).isSignedOffset<18, 1>())
return Error(Operands[3]->getStartLoc(),
"branch target out of range or not a multiple of 2");
}
break;
}
case ARM::t2BFic: {
if (!static_cast<ARMOperand &>(*Operands[1]).isUnsignedOffset<4, 1>() ||
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0))
return Error(Operands[1]->getStartLoc(),
"branch location out of range or not a multiple of 2");
if (!static_cast<ARMOperand &>(*Operands[2]).isSignedOffset<16, 1>())
return Error(Operands[2]->getStartLoc(),
"branch target out of range or not a multiple of 2");
assert(Inst.getOperand(0).isImm() == Inst.getOperand(2).isImm() &&
"branch location and else branch target should either both be "
"immediates or both labels");
if (Inst.getOperand(0).isImm() && Inst.getOperand(2).isImm()) {
int Diff = Inst.getOperand(2).getImm() - Inst.getOperand(0).getImm();
if (Diff != 4 && Diff != 2)
return Error(
Operands[3]->getStartLoc(),
"else branch target must be 2 or 4 greater than the branch location");
}
break;
}
case ARM::t2CLRM: {
for (unsigned i = 2; i < Inst.getNumOperands(); i++) {
if (Inst.getOperand(i).isReg() &&
!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(
Inst.getOperand(i).getReg())) {
return Error(Operands[2]->getStartLoc(),
"invalid register in register list. Valid registers are "
"r0-r12, lr/r14 and APSR.");
}
}
break;
}
case ARM::DSB:
case ARM::t2DSB: {
@ -9169,11 +9399,29 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return Match_RequiresV8;
}
// Use of SP for VMRS/VMSR is only allowed in ARM mode with the exception of
// ARMv8-A.
if ((Inst.getOpcode() == ARM::VMRS || Inst.getOpcode() == ARM::VMSR) &&
Inst.getOperand(0).getReg() == ARM::SP && (isThumb() && !hasV8Ops()))
return Match_InvalidOperand;
switch (Inst.getOpcode()) {
case ARM::VMRS:
case ARM::VMSR:
case ARM::VMRS_FPCXTS:
case ARM::VMRS_FPCXTNS:
case ARM::VMSR_FPCXTS:
case ARM::VMSR_FPCXTNS:
case ARM::VMRS_FPSCR_NZCVQC:
case ARM::VMSR_FPSCR_NZCVQC:
case ARM::FMSTAT:
case ARM::VMRS_VPR:
case ARM::VMRS_P0:
case ARM::VMSR_VPR:
case ARM::VMSR_P0:
// Use of SP for VMRS/VMSR is only allowed in ARM mode with the exception of
// ARMv8-A.
if (Inst.getOperand(0).isReg() && Inst.getOperand(0).getReg() == ARM::SP &&
(isThumb() && !hasV8Ops()))
return Match_InvalidOperand;
break;
default:
break;
}
for (unsigned I = 0; I < MCID.NumOperands; ++I)
if (MCID.OpInfo[I].RegClass == ARM::rGPRRegClassID) {
@ -10636,6 +10884,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
{ ARM::AEK_FP16, {Feature_HasV8_2aBit},
{ARM::FeatureFPARMv8, ARM::FeatureFullFP16} },
{ ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS} },
{ ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB} },
// FIXME: Unsupported extensions.
{ ARM::AEK_OS, {}, {} },
{ ARM::AEK_IWMMXT, {}, {} },

View File

@ -144,12 +144,17 @@ static bool Check(DecodeStatus &Out, DecodeStatus In) {
// Definitions are further down.
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCLRMGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst,
unsigned RegNo, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRwithAPSRRegisterClass(MCInst &Inst,
unsigned RegNo, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRwithZRRegisterClass(MCInst &Inst,
unsigned RegNo, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
@ -361,8 +366,13 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
uint64_t Address, const void* Decoder);
static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2Imm7S4(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm7s4(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst,unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2Imm8(MCInst &Inst, unsigned Val,
@ -411,6 +421,23 @@ static DecodeStatus DecoderForMRRC2AndMCRR2(MCInst &Inst, unsigned Val,
static DecodeStatus DecodeForVMRSandVMSR(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
template <bool isSigned, bool isNeg, int size>
static DecodeStatus DecodeBFLabelOperand(MCInst &Inst, unsigned val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBFAfterTargetOperand(MCInst &Inst, unsigned val,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePredNoALOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
template<bool Writeback>
static DecodeStatus DecodeVSTRVLDR_SYSREG(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
#include "ARMGenDisassemblerTables.inc"
static MCDisassembler *createARMDisassembler(const Target &T,
@ -604,6 +631,10 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
case ARM::t2CPS3p:
case ARM::t2CPS2p:
case ARM::t2CPS1p:
case ARM::t2CSEL:
case ARM::t2CSINC:
case ARM::t2CSINV:
case ARM::t2CSNEG:
case ARM::tMOVSr:
case ARM::tSETEND:
// Some instructions (mostly conditional branches) are not
@ -892,6 +923,13 @@ static const uint16_t GPRDecoderTable[] = {
ARM::R12, ARM::SP, ARM::LR, ARM::PC
};
static const uint16_t CLRMGPRDecoderTable[] = {
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
ARM::R4, ARM::R5, ARM::R6, ARM::R7,
ARM::R8, ARM::R9, ARM::R10, ARM::R11,
ARM::R12, 0, ARM::LR, ARM::APSR
};
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 15)
@ -902,6 +940,20 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
static DecodeStatus DecodeCLRMGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 15)
return MCDisassembler::Fail;
unsigned Register = CLRMGPRDecoderTable[RegNo];
if (Register == 0)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createReg(Register));
return MCDisassembler::Success;
}
static DecodeStatus
DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
@ -930,6 +982,24 @@ DecodeGPRwithAPSRRegisterClass(MCInst &Inst, unsigned RegNo,
return S;
}
static DecodeStatus
DecodeGPRwithZRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
if (RegNo == 15)
{
Inst.addOperand(MCOperand::createReg(ARM::ZR));
return MCDisassembler::Success;
}
if (RegNo == 13)
S = MCDisassembler::SoftFail;
Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
return S;
}
static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 7)
@ -1239,6 +1309,7 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Val,
bool NeedDisjointWriteback = false;
unsigned WritebackReg = 0;
bool CLRM = false;
switch (Inst.getOpcode()) {
default:
break;
@ -1253,17 +1324,26 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Val,
NeedDisjointWriteback = true;
WritebackReg = Inst.getOperand(0).getReg();
break;
case ARM::t2CLRM:
CLRM = true;
break;
}
// Empty register lists are not allowed.
if (Val == 0) return MCDisassembler::Fail;
for (unsigned i = 0; i < 16; ++i) {
if (Val & (1 << i)) {
if (!Check(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder)))
return MCDisassembler::Fail;
// Writeback not allowed if Rn is in the target list.
if (NeedDisjointWriteback && WritebackReg == Inst.end()[-1].getReg())
Check(S, MCDisassembler::SoftFail);
if (CLRM) {
if (!Check(S, DecodeCLRMGPRRegisterClass(Inst, i, Address, Decoder))) {
return MCDisassembler::Fail;
}
} else {
if (!Check(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder)))
return MCDisassembler::Fail;
// Writeback not allowed if Rn is in the target list.
if (NeedDisjointWriteback && WritebackReg == Inst.end()[-1].getReg())
Check(S, MCDisassembler::SoftFail);
}
}
}
@ -1356,6 +1436,8 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
unsigned imm = fieldFromInstruction(Insn, 0, 8);
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
unsigned U = fieldFromInstruction(Insn, 23, 1);
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
switch (Inst.getOpcode()) {
case ARM::LDC_OFFSET:
@ -1390,15 +1472,42 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
case ARM::t2STCL_PRE:
case ARM::t2STCL_POST:
case ARM::t2STCL_OPTION:
if (coproc == 0xA || coproc == 0xB)
case ARM::t2LDC2_OFFSET:
case ARM::t2LDC2L_OFFSET:
case ARM::t2LDC2_PRE:
case ARM::t2LDC2L_PRE:
case ARM::t2STC2_OFFSET:
case ARM::t2STC2L_OFFSET:
case ARM::t2STC2_PRE:
case ARM::t2STC2L_PRE:
case ARM::LDC2_OFFSET:
case ARM::LDC2L_OFFSET:
case ARM::LDC2_PRE:
case ARM::LDC2L_PRE:
case ARM::STC2_OFFSET:
case ARM::STC2L_OFFSET:
case ARM::STC2_PRE:
case ARM::STC2L_PRE:
case ARM::t2LDC2_OPTION:
case ARM::t2STC2_OPTION:
case ARM::t2LDC2_POST:
case ARM::t2LDC2L_POST:
case ARM::t2STC2_POST:
case ARM::t2STC2L_POST:
case ARM::LDC2_POST:
case ARM::LDC2L_POST:
case ARM::STC2_POST:
case ARM::STC2L_POST:
if (coproc == 0xA || coproc == 0xB ||
(featureBits[ARM::HasV8_1MMainlineOps] &&
(coproc == 0x8 || coproc == 0x9 || coproc == 0xA || coproc == 0xB ||
coproc == 0xE || coproc == 0xF)))
return MCDisassembler::Fail;
break;
default:
break;
}
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if (featureBits[ARM::HasV8Ops] && (coproc != 14))
return MCDisassembler::Fail;
@ -3735,6 +3844,21 @@ static DecodeStatus DecodeT2Imm8S4(MCInst &Inst, unsigned Val,
return MCDisassembler::Success;
}
static DecodeStatus DecodeT2Imm7S4(MCInst &Inst, unsigned Val, uint64_t Address,
const void *Decoder) {
if (Val == 0)
Inst.addOperand(MCOperand::createImm(INT32_MIN));
else {
int imm = Val & 0x7F;
if (!(Val & 0x80))
imm *= -1;
Inst.addOperand(MCOperand::createImm(imm * 4));
}
return MCDisassembler::Success;
}
static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
@ -3750,6 +3874,22 @@ static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val,
return S;
}
static DecodeStatus DecodeT2AddrModeImm7s4(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
unsigned Rn = fieldFromInstruction(Val, 8, 4);
unsigned imm = fieldFromInstruction(Val, 0, 8);
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
return MCDisassembler::Fail;
if (!Check(S, DecodeT2Imm7S4(Inst, imm, Address, Decoder)))
return MCDisassembler::Fail;
return S;
}
static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst,unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
@ -4005,6 +4145,13 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Val,
if (featureBits[ARM::HasV8Ops] && !(Val == 14 || Val == 15))
return MCDisassembler::Fail;
// For Armv8.1-M Mainline coprocessors matching 100x,101x or 111x should
// decode as VFP/MVE instructions.
if (featureBits[ARM::HasV8_1MMainlineOps] &&
((Val & 0xE) == 0x8 || (Val & 0xE) == 0xA ||
(Val & 0xE) == 0xE))
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Val));
return MCDisassembler::Success;
}
@ -5370,14 +5517,37 @@ static DecodeStatus DecodeForVMRSandVMSR(MCInst &Inst, unsigned Val,
((const MCDisassembler *)Decoder)->getSubtargetInfo().getFeatureBits();
DecodeStatus S = MCDisassembler::Success;
unsigned Rt = fieldFromInstruction(Val, 12, 4);
// Add explicit operand for the destination sysreg, for cases where
// we have to model it for code generation purposes.
switch (Inst.getOpcode()) {
case ARM::VMSR_FPSCR_NZCVQC:
Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
break;
case ARM::VMSR_P0:
Inst.addOperand(MCOperand::createReg(ARM::VPR));
break;
}
if (featureBits[ARM::ModeThumb] && !featureBits[ARM::HasV8Ops]) {
if (Rt == 13 || Rt == 15)
S = MCDisassembler::SoftFail;
Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
} else
Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder));
if (Inst.getOpcode() != ARM::FMSTAT) {
unsigned Rt = fieldFromInstruction(Val, 12, 4);
if (featureBits[ARM::ModeThumb] && !featureBits[ARM::HasV8Ops]) {
if (Rt == 13 || Rt == 15)
S = MCDisassembler::SoftFail;
Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
} else
Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder));
}
// Add explicit operand for the source sysreg, similarly to above.
switch (Inst.getOpcode()) {
case ARM::VMRS_FPSCR_NZCVQC:
Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
break;
case ARM::VMRS_P0:
Inst.addOperand(MCOperand::createReg(ARM::VPR));
break;
}
if (featureBits[ARM::ModeThumb]) {
Inst.addOperand(MCOperand::createImm(ARMCC::AL));
@ -5390,3 +5560,169 @@ static DecodeStatus DecodeForVMRSandVMSR(MCInst &Inst, unsigned Val,
return S;
}
template <bool isSigned, bool isNeg, int size>
static DecodeStatus DecodeBFLabelOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
if (Val == 0)
S = MCDisassembler::SoftFail;
uint64_t DecVal;
if (isSigned)
DecVal = SignExtend32<size + 1>(Val << 1);
else
DecVal = (Val << 1);
if (!tryAddingSymbolicOperand(Address, Address + DecVal + 4, true, 4, Inst,
Decoder))
Inst.addOperand(MCOperand::createImm(isNeg ? -DecVal : DecVal));
return S;
}
static DecodeStatus DecodeBFAfterTargetOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
uint64_t LocImm = Inst.getOperand(0).getImm();
Val = LocImm + (2 << Val);
if (!tryAddingSymbolicOperand(Address, Address + Val + 4, true, 4, Inst,
Decoder))
Inst.addOperand(MCOperand::createImm(Val));
return MCDisassembler::Success;
}
static DecodeStatus DecodePredNoALOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
if (Val >= ARMCC::AL) // also exclude the non-condition NV
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Val));
return MCDisassembler::Success;
}
static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
unsigned Imm = fieldFromInstruction(Insn, 11, 1) |
fieldFromInstruction(Insn, 1, 10) << 1;
switch (Inst.getOpcode()) {
case ARM::t2LEUpdate:
Inst.addOperand(MCOperand::createReg(ARM::LR));
Inst.addOperand(MCOperand::createReg(ARM::LR));
LLVM_FALLTHROUGH;
case ARM::t2LE:
if (!Check(S, DecodeBFLabelOperand<false, true, 11>(Inst, Imm, Address,
Decoder)))
return MCDisassembler::Fail;
break;
case ARM::t2WLS:
Inst.addOperand(MCOperand::createReg(ARM::LR));
if (!Check(S,
DecoderGPRRegisterClass(Inst, fieldFromInstruction(Insn, 16, 4),
Address, Decoder)) ||
!Check(S, DecodeBFLabelOperand<false, false, 11>(Inst, Imm, Address,
Decoder)))
return MCDisassembler::Fail;
break;
case ARM::t2DLS:
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
if (Rn == 0xF) {
return MCDisassembler::Fail;
} else {
Inst.addOperand(MCOperand::createReg(ARM::LR));
if (!Check(S, DecoderGPRRegisterClass(Inst,
fieldFromInstruction(Insn, 16, 4),
Address, Decoder)))
return MCDisassembler::Fail;
}
break;
}
return S;
}
static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
Inst.addOperand(MCOperand::createImm(ARMCC::AL));
Inst.addOperand(MCOperand::createReg(0));
if (Inst.getOpcode() == ARM::VSCCLRMD) {
unsigned reglist = (fieldFromInstruction(Insn, 1, 7) << 1) |
(fieldFromInstruction(Insn, 12, 4) << 8) |
(fieldFromInstruction(Insn, 22, 1) << 12);
if (!Check(S, DecodeDPRRegListOperand(Inst, reglist, Address, Decoder))) {
return MCDisassembler::Fail;
}
} else {
unsigned reglist = fieldFromInstruction(Insn, 0, 8) |
(fieldFromInstruction(Insn, 22, 1) << 8) |
(fieldFromInstruction(Insn, 12, 4) << 9);
if (!Check(S, DecodeSPRRegListOperand(Inst, reglist, Address, Decoder))) {
return MCDisassembler::Fail;
}
}
Inst.addOperand(MCOperand::createReg(ARM::VPR));
return S;
}
static unsigned FixedRegForVSTRVLDR_SYSREG(unsigned Opcode) {
switch (Opcode) {
case ARM::VSTR_P0_off:
case ARM::VSTR_P0_pre:
case ARM::VSTR_P0_post:
case ARM::VLDR_P0_off:
case ARM::VLDR_P0_pre:
case ARM::VLDR_P0_post:
return ARM::P0;
default:
return 0;
}
}
template<bool Writeback>
static DecodeStatus DecodeVSTRVLDR_SYSREG(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
switch (Inst.getOpcode()) {
case ARM::VSTR_FPSCR_pre:
case ARM::VSTR_FPSCR_NZCVQC_pre:
case ARM::VLDR_FPSCR_pre:
case ARM::VLDR_FPSCR_NZCVQC_pre:
case ARM::VSTR_FPSCR_off:
case ARM::VSTR_FPSCR_NZCVQC_off:
case ARM::VLDR_FPSCR_off:
case ARM::VLDR_FPSCR_NZCVQC_off:
case ARM::VSTR_FPSCR_post:
case ARM::VSTR_FPSCR_NZCVQC_post:
case ARM::VLDR_FPSCR_post:
case ARM::VLDR_FPSCR_NZCVQC_post:
const FeatureBitset &featureBits =
((const MCDisassembler *)Decoder)->getSubtargetInfo().getFeatureBits();
if (!featureBits[ARM::HasMVEIntegerOps] && !featureBits[ARM::FeatureVFP2])
return MCDisassembler::Fail;
}
DecodeStatus S = MCDisassembler::Success;
if (unsigned Sysreg = FixedRegForVSTRVLDR_SYSREG(Inst.getOpcode()))
Inst.addOperand(MCOperand::createReg(Sysreg));
unsigned Rn = fieldFromInstruction(Val, 16, 4);
unsigned addr = fieldFromInstruction(Val, 0, 7) |
(fieldFromInstruction(Val, 23, 1) << 7) | (Rn << 8);
if (Writeback) {
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
return MCDisassembler::Fail;
}
if (!Check(S, DecodeT2AddrModeImm7s4(Inst, addr, Address, Decoder)))
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(ARMCC::AL));
Inst.addOperand(MCOperand::createReg(0));
return S;
}

View File

@ -29,6 +29,7 @@
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
@ -104,6 +105,13 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_t2_movw_lo16", 0, 20, 0},
{"fixup_arm_mod_imm", 0, 12, 0},
{"fixup_t2_so_imm", 0, 26, 0},
{"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfcsel_else_target", 0, 32, 0},
{"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}
};
const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {
// This table *must* be in the order that the fixup_* kinds are defined in
@ -155,6 +163,13 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_t2_movw_lo16", 12, 20, 0},
{"fixup_arm_mod_imm", 20, 12, 0},
{"fixup_t2_so_imm", 26, 6, 0},
{"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfcsel_else_target", 0, 32, 0},
{"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}
};
if (Kind < FirstTargetFixupKind)
@ -256,6 +271,56 @@ const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup,
return "will be converted to nop";
break;
}
case ARM::fixup_bf_branch: {
int64_t Offset = int64_t(Value) - 4;
if (Offset < 0 || Offset > 30)
return "out of range pc-relative fixup value";
break;
}
case ARM::fixup_bf_target: {
int64_t Offset = int64_t(Value) - 4;
if (Offset > 65534 || Offset < -65536)
return "out of range pc-relative fixup value";
break;
}
case ARM::fixup_bfl_target: {
int64_t Offset = int64_t(Value) - 4;
if (Offset > 262142 || Offset < -262144)
return "out of range pc-relative fixup value";
break;
}
case ARM::fixup_bfc_target: {
int64_t Offset = int64_t(Value) - 4;
if (Offset > 4094 || Offset < -4096)
return "out of range pc-relative fixup value";
break;
}
case ARM::fixup_bfcsel_else_target: {
if (Value != 2 && Value != 4)
return "out of range label-relative fixup value";
break;
}
case ARM::fixup_wls: {
uint64_t Offset = Value - 4;
if (Offset > 4094)
return "out of range pc-relative fixup value";
break;
}
case ARM::fixup_le: {
// The offset field in the LE and LETP instructions is an 11-bit
// value shifted left by 2 (i.e. 0,2,4,...,4094), and it is
// interpreted as a negative offset from the value read from pc,
// i.e. from instruction_address+4.
//
// So an LE instruction can in principle address the instruction
// immediately after itself, or (not very usefully) the address
// half way through the 4-byte LE.
uint64_t Offset = -Value + 4;
if (Offset > 4094)
return "out of range pc-relative fixup value";
break;
}
default:
llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!");
}
@ -760,6 +825,60 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
EncValue |= (Value & 0xff);
return swapHalfWords(EncValue, Endian == support::little);
}
case ARM::fixup_bf_branch: {
const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
if (FixupDiagnostic) {
Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
return 0;
}
uint32_t out = (((Value - 4) >> 1) & 0xf) << 23;
return swapHalfWords(out, Endian == support::little);
}
case ARM::fixup_bf_target:
case ARM::fixup_bfl_target:
case ARM::fixup_bfc_target: {
const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
if (FixupDiagnostic) {
Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
return 0;
}
uint32_t out = 0;
uint32_t HighBitMask = (Kind == ARM::fixup_bf_target ? 0xf800 :
Kind == ARM::fixup_bfl_target ? 0x3f800 : 0x800);
out |= (((Value - 4) >> 1) & 0x1) << 11;
out |= (((Value - 4) >> 1) & 0x7fe);
out |= (((Value - 4) >> 1) & HighBitMask) << 5;
return swapHalfWords(out, Endian == support::little);
}
case ARM::fixup_bfcsel_else_target: {
// If this is a fixup of a branch future's else target then it should be a
// constant MCExpr representing the distance between the branch targetted
// and the instruction after that same branch.
Value = Target.getConstant();
const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
if (FixupDiagnostic) {
Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
return 0;
}
uint32_t out = ((Value >> 2) & 1) << 17;
return swapHalfWords(out, Endian == support::little);
}
case ARM::fixup_wls:
case ARM::fixup_le: {
const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
if (FixupDiagnostic) {
Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
return 0;
}
uint64_t real_value = Value - 4;
uint32_t out = 0;
if (Kind == ARM::fixup_le)
real_value = -real_value;
out |= ((real_value >> 1) & 0x1) << 11;
out |= ((real_value >> 1) & 0x7fe);
return swapHalfWords(out, Endian == support::little);
}
}
}
@ -854,6 +973,13 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM::fixup_t2_movt_hi16:
case ARM::fixup_t2_movw_lo16:
case ARM::fixup_t2_so_imm:
case ARM::fixup_bf_branch:
case ARM::fixup_bf_target:
case ARM::fixup_bfl_target:
case ARM::fixup_bfc_target:
case ARM::fixup_bfcsel_else_target:
case ARM::fixup_wls:
case ARM::fixup_le:
return 4;
case FK_SecRel_2:
@ -910,6 +1036,13 @@ static unsigned getFixupKindContainerSizeBytes(unsigned Kind) {
case ARM::fixup_t2_movw_lo16:
case ARM::fixup_arm_mod_imm:
case ARM::fixup_t2_so_imm:
case ARM::fixup_bf_branch:
case ARM::fixup_bf_target:
case ARM::fixup_bfl_target:
case ARM::fixup_bfc_target:
case ARM::fixup_bfcsel_else_target:
case ARM::fixup_wls:
case ARM::fixup_le:
// Instruction size is 4 bytes.
return 4;
}

View File

@ -137,6 +137,12 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
default:
return ELF::R_ARM_THM_CALL;
}
case ARM::fixup_bf_target:
return ELF::R_ARM_THM_BF16;
case ARM::fixup_bfc_target:
return ELF::R_ARM_THM_BF12;
case ARM::fixup_bfl_target:
return ELF::R_ARM_THM_BF18;
}
}
switch ((unsigned)Fixup.getKind()) {

View File

@ -103,6 +103,15 @@ enum Fixups {
// Fixup for Thumb2 8-bit rotated operand
fixup_t2_so_imm,
// Fixups for Branch Future.
fixup_bf_branch,
fixup_bf_target,
fixup_bfl_target,
fixup_bfc_target,
fixup_bfcsel_else_target,
fixup_wls,
fixup_le,
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind

View File

@ -771,11 +771,13 @@ void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
assert(std::is_sorted(MI->begin() + OpNum, MI->end(),
[&](const MCOperand &LHS, const MCOperand &RHS) {
return MRI.getEncodingValue(LHS.getReg()) <
MRI.getEncodingValue(RHS.getReg());
}));
if (MI->getOpcode() != ARM::t2CLRM) {
assert(std::is_sorted(MI->begin() + OpNum, MI->end(),
[&](const MCOperand &LHS, const MCOperand &RHS) {
return MRI.getEncodingValue(LHS.getReg()) <
MRI.getEncodingValue(RHS.getReg());
}));
}
O << "{";
for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
@ -930,6 +932,15 @@ void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
O << ARMCondCodeToString(CC);
}
void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
raw_ostream &O) {
if ((ARMCC::CondCodes)MI->getOperand(OpNum).getImm() == ARMCC::HS)
O << "cs";
else
printMandatoryPredicateOperand(MI, OpNum, STI, O);
}
void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
unsigned OpNum,
const MCSubtargetInfo &STI,
@ -938,6 +949,14 @@ void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
O << ARMCondCodeToString(CC);
}
void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst *MI,
unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
O << ARMCondCodeToString(ARMCC::getOppositeCondition(CC));
}
void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {

View File

@ -170,6 +170,13 @@ public:
void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O);
void printMandatoryRestrictedPredicateOperand(const MCInst *MI,
unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O);
void printMandatoryInvertedPredicateOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O);
void printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
void printRegisterList(const MCInst *MI, unsigned OpNum,

View File

@ -49,7 +49,7 @@ namespace {
class ARMMCCodeEmitter : public MCCodeEmitter {
const MCInstrInfo &MCII;
const MCContext &CTX;
MCContext &CTX;
bool IsLittleEndian;
public:
@ -180,18 +180,24 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// getT2AddrModeImm7s4OpValue - Return encoding info for 'reg +/- imm7<<2'
/// operand.
uint32_t getT2AddrModeImm7s4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2'
/// operand.
uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2'
/// getT2ScaledImmOpValue - Return encoding info for '+/- immX<<Y'
/// operand.
uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
template<unsigned Bits, unsigned Shift>
uint32_t getT2ScaledImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
/// operand as needed by load/store instructions.
@ -416,6 +422,15 @@ public:
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;
template <bool isNeg, ARM::Fixups fixup>
uint32_t getBFTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
uint32_t getBFAfterTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
};
} // end anonymous namespace
@ -894,12 +909,11 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
return Binary;
}
/// getT2Imm8s4OpValue - Return encoding info for
/// '+/- imm8<<2' operand.
template<unsigned Bits, unsigned Shift>
uint32_t ARMMCCodeEmitter::
getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
getT2ScaledImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
// FIXME: The immediate operand should have already been encoded like this
// before ever getting here. The encoder method should just need to combine
// the MI operands for the register and the offset into a single
@ -907,25 +921,23 @@ getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
// style, unfortunately. As-is, we can't represent the distinct encoding
// for #-0.
// {8} = (U)nsigned (add == '1', sub == '0')
// {7-0} = imm8
int32_t Imm8 = MI.getOperand(OpIdx).getImm();
bool isAdd = Imm8 >= 0;
// {Bits} = (U)nsigned (add == '1', sub == '0')
// {(Bits-1)-0} = immediate
int32_t Imm = MI.getOperand(OpIdx).getImm();
bool isAdd = Imm >= 0;
// Immediate is always encoded as positive. The 'U' bit controls add vs sub.
if (Imm8 < 0)
Imm8 = -(uint32_t)Imm8;
if (Imm < 0)
Imm = -(uint32_t)Imm;
// Scaled by 4.
Imm8 /= 4;
Imm >>= Shift;
uint32_t Binary = Imm8 & 0xff;
uint32_t Binary = Imm & ((1U << Bits) - 1);
// Immediate is always encoded as positive. The 'U' bit controls add vs sub.
if (isAdd)
Binary |= (1 << 8);
Binary |= (1U << Bits);
return Binary;
}
/// getT2AddrModeImm8s4OpValue - Return encoding info for
/// 'reg +/- imm8<<2' operand.
uint32_t ARMMCCodeEmitter::
@ -967,6 +979,33 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
return Binary;
}
/// getT2AddrModeImm7s4OpValue - Return encoding info for
/// 'reg +/- imm7<<2' operand.
uint32_t
ARMMCCodeEmitter::getT2AddrModeImm7s4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
// {11-8} = reg
// {7} = (A)dd (add == '1', sub == '0')
// {6-0} = imm7
unsigned Reg, Imm7;
// If The first operand isn't a register, we have a label reference.
bool isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm7, Fixups, STI);
// FIXME: The immediate operand should have already been encoded like this
// before ever getting here. The encoder method should just need to combine
// the MI operands for the register and the offset into a single
// representation for the complex operand in the .td file. This isn't just
// style, unfortunately. As-is, we can't represent the distinct encoding
// for #-0.
uint32_t Binary = (Imm7 >> 2) & 0xff;
// Immediate is always encoded as positive. The 'A' bit controls add vs sub.
if (isAdd)
Binary |= (1 << 7);
Binary |= (Reg << 8);
return Binary;
}
/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for
/// 'reg + imm8<<2' operand.
uint32_t ARMMCCodeEmitter::
@ -1499,7 +1538,7 @@ unsigned ARMMCCodeEmitter::
getRegisterListOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
// VLDM/VSTM:
// VLDM/VSTM/VSCCLRM:
// {12-8} = Vd
// {7-0} = Number of registers
//
@ -1508,28 +1547,40 @@ getRegisterListOpValue(const MCInst &MI, unsigned Op,
unsigned Reg = MI.getOperand(Op).getReg();
bool SPRRegs = ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg);
bool DPRRegs = ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg);
bool CLRMRegs = MI.getOpcode() == ARM::t2CLRM;
unsigned Binary = 0;
if (SPRRegs || DPRRegs) {
// VLDM/VSTM
// VLDM/VSTM/VSCCLRM
unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg);
unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
Binary |= (RegNo & 0x1f) << 8;
// Ignore VPR
if (MI.getOpcode() == ARM::VSCCLRMD || MI.getOpcode() == ARM::VSCCLRMS)
--NumRegs;
if (SPRRegs)
Binary |= NumRegs;
else
Binary |= NumRegs * 2;
} else {
const MCRegisterInfo &MRI = *CTX.getRegisterInfo();
assert(std::is_sorted(MI.begin() + Op, MI.end(),
[&](const MCOperand &LHS, const MCOperand &RHS) {
return MRI.getEncodingValue(LHS.getReg()) <
MRI.getEncodingValue(RHS.getReg());
}));
if (!CLRMRegs) {
assert(std::is_sorted(MI.begin() + Op, MI.end(),
[&](const MCOperand &LHS, const MCOperand &RHS) {
return MRI.getEncodingValue(LHS.getReg()) <
MRI.getEncodingValue(RHS.getReg());
}));
}
for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
unsigned RegNo = MRI.getEncodingValue(MI.getOperand(I).getReg());
unsigned RegNo;
if (CLRMRegs && MI.getOperand(I).getReg() == ARM::APSR) {
RegNo = 15;
} else {
RegNo = MRI.getEncodingValue(MI.getOperand(I).getReg());
}
Binary |= 1 << RegNo;
}
}
@ -1675,6 +1726,39 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
++MCNumEmitted; // Keep track of the # of mi's emitted.
}
template <bool isNeg, ARM::Fixups fixup>
uint32_t
ARMMCCodeEmitter::getBFTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand MO = MI.getOperand(OpIdx);
if (MO.isExpr())
return ::getBranchTargetOpValue(MI, OpIdx, fixup, Fixups, STI);
return isNeg ? -(MO.getImm() >> 1) : (MO.getImm() >> 1);
}
uint32_t
ARMMCCodeEmitter::getBFAfterTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand MO = MI.getOperand(OpIdx);
const MCOperand BranchMO = MI.getOperand(0);
if (MO.isExpr()) {
assert(BranchMO.isExpr());
const MCExpr *DiffExpr = MCBinaryExpr::createSub(
MO.getExpr(), BranchMO.getExpr(), CTX);
MCFixupKind Kind = MCFixupKind(ARM::fixup_bfcsel_else_target);
Fixups.push_back(llvm::MCFixup::create(0, DiffExpr, Kind, MI.getLoc()));
return 0;
}
assert(MO.isImm() && BranchMO.isImm());
int Diff = MO.getImm() - BranchMO.getImm();
assert(Diff == 4 || Diff == 2);
return Diff == 4;
}
#include "ARMGenMCCodeEmitter.inc"
MCCodeEmitter *llvm::createARMLEMCCodeEmitter(const MCInstrInfo &MCII,

View File

@ -277,14 +277,29 @@ class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
public:
ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const override {
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
unsigned OpId;
switch (Inst.getOpcode()) {
default:
OpId = 0;
break;
case ARM::t2WLS:
case ARM::t2LEUpdate:
OpId = 2;
break;
case ARM::t2LE:
OpId = 1;
break;
}
// We only handle PCRel branches for now.
if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
if (Info->get(Inst.getOpcode()).OpInfo[OpId].OperandType !=
MCOI::OPERAND_PCREL)
return false;
int64_t Imm = Inst.getOperand(0).getImm();
Target = Addr+Imm+4; // In Thumb mode the PC is always off by 4 bytes.
// In Thumb mode the PC is always off by 4 bytes.
Target = Addr + Inst.getOperand(OpId).getImm() + 4;
return true;
}
};

View File

@ -161,7 +161,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
// otherwise).
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
MachineRegisterInfo *MRI = &MF.getRegInfo();
MRI->constrainRegClass(SrcReg, &ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
MRI->constrainRegClass(SrcReg, &ARM::GPRPair_with_gsub_1_in_GPRwithAPSRnospRegClass);
}
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));
@ -203,7 +203,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
MachineRegisterInfo *MRI = &MF.getRegInfo();
MRI->constrainRegClass(DestReg,
&ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
&ARM::GPRPair_with_gsub_1_in_GPRwithAPSRnospRegClass);
}
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8));

View File

@ -6,7 +6,7 @@ target triple = "armv7-eabi"
declare void @bar1()
define void @foo()#0 {
; CHECK: foo Clobbered Registers: $apsr $apsr_nzcv $cpsr $fpexc $fpinst $fpscr $fpscr_nzcv $fpsid $itstate $pc $sp $spsr $d0 $d1 $d2 $d3 $d4 $d5 $d6 $d7 $d16 $d17 $d18 $d19 $d20 $d21 $d22 $d23 $d24 $d25 $d26 $d27 $d28 $d29 $d30 $d31 $fpinst2 $mvfr0 $mvfr1 $mvfr2 $q0 $q1 $q2 $q3 $q8 $q9 $q10 $q11 $q12 $q13 $q14 $q15 $r0 $r1 $r2 $r3 $r12 $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $s8 $s9 $s10 $s11 $s12 $s13 $s14 $s15 $d0_d2 $d1_d3 $d2_d4 $d3_d5 $d4_d6 $d5_d7 $d6_d8 $d7_d9 $d14_d16 $d15_d17 $d16_d18 $d17_d19 $d18_d20 $d19_d21 $d20_d22 $d21_d23 $d22_d24 $d23_d25 $d24_d26 $d25_d27 $d26_d28 $d27_d29 $d28_d30 $d29_d31 $q0_q1 $q1_q2 $q2_q3 $q3_q4 $q7_q8 $q8_q9 $q9_q10 $q10_q11 $q11_q12 $q12_q13 $q13_q14 $q14_q15 $q0_q1_q2_q3 $q1_q2_q3_q4 $q2_q3_q4_q5 $q3_q4_q5_q6 $q5_q6_q7_q8 $q6_q7_q8_q9 $q7_q8_q9_q10 $q8_q9_q10_q11 $q9_q10_q11_q12 $q10_q11_q12_q13 $q11_q12_q13_q14 $q12_q13_q14_q15 $r12_sp $r0_r1 $r2_r3 $d0_d1_d2 $d1_d2_d3 $d2_d3_d4 $d3_d4_d5 $d4_d5_d6 $d5_d6_d7 $d6_d7_d8 $d7_d8_d9 $d14_d15_d16 $d15_d16_d17 $d16_d17_d18 $d17_d18_d19 $d18_d19_d20 $d19_d20_d21 $d20_d21_d22 $d21_d22_d23 $d22_d23_d24 $d23_d24_d25 $d24_d25_d26 $d25_d26_d27 $d26_d27_d28 $d27_d28_d29 $d28_d29_d30 $d29_d30_d31 $d0_d2_d4 $d1_d3_d5 $d2_d4_d6 $d3_d5_d7 $d4_d6_d8 $d5_d7_d9 $d6_d8_d10 $d7_d9_d11 $d12_d14_d16 $d13_d15_d17 $d14_d16_d18 $d15_d17_d19 $d16_d18_d20 $d17_d19_d21 $d18_d20_d22 $d19_d21_d23 $d20_d22_d24 $d21_d23_d25 $d22_d24_d26 $d23_d25_d27 $d24_d26_d28 $d25_d27_d29 $d26_d28_d30 $d27_d29_d31 $d0_d2_d4_d6 $d1_d3_d5_d7 $d2_d4_d6_d8 $d3_d5_d7_d9 $d4_d6_d8_d10 $d5_d7_d9_d11 $d6_d8_d10_d12 $d7_d9_d11_d13 $d10_d12_d14_d16 $d11_d13_d15_d17 $d12_d14_d16_d18 $d13_d15_d17_d19 $d14_d16_d18_d20 $d15_d17_d19_d21 $d16_d18_d20_d22 $d17_d19_d21_d23 $d18_d20_d22_d24 $d19_d21_d23_d25 $d20_d22_d24_d26 $d21_d23_d25_d27 $d22_d24_d26_d28 $d23_d25_d27_d29 $d24_d26_d28_d30 $d25_d27_d29_d31 $d1_d2 $d3_d4 $d5_d6 $d7_d8 $d15_d16 $d17_d18 $d19_d20 $d21_d22 $d23_d24 $d25_d26 $d27_d28 $d29_d30 $d1_d2_d3_d4 $d3_d4_d5_d6 $d5_d6_d7_d8 $d7_d8_d9_d10 $d13_d14_d15_d16 $d15_d16_d17_d18 $d17_d18_d19_d20 $d19_d20_d21_d22 $d21_d22_d23_d24 $d23_d24_d25_d26 $d25_d26_d27_d28 $d27_d28_d29_d30
; CHECK: foo Clobbered Registers: $apsr $apsr_nzcv $cpsr $fpcxtns $fpcxts $fpexc $fpinst $fpscr $fpscr_nzcv $fpscr_nzcvqc $fpsid $itstate $pc $sp $spsr $vpr $zr $d0 $d1 $d2 $d3 $d4 $d5 $d6 $d7 $d16 $d17 $d18 $d19 $d20 $d21 $d22 $d23 $d24 $d25 $d26 $d27 $d28 $d29 $d30 $d31 $fpinst2 $mvfr0 $mvfr1 $mvfr2 $p0 $q0 $q1 $q2 $q3 $q8 $q9 $q10 $q11 $q12 $q13 $q14 $q15 $r0 $r1 $r2 $r3 $r12 $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $s8 $s9 $s10 $s11 $s12 $s13 $s14 $s15 $d0_d2 $d1_d3 $d2_d4 $d3_d5 $d4_d6 $d5_d7 $d6_d8 $d7_d9 $d14_d16 $d15_d17 $d16_d18 $d17_d19 $d18_d20 $d19_d21 $d20_d22 $d21_d23 $d22_d24 $d23_d25 $d24_d26 $d25_d27 $d26_d28 $d27_d29 $d28_d30 $d29_d31 $q0_q1 $q1_q2 $q2_q3 $q3_q4 $q7_q8 $q8_q9 $q9_q10 $q10_q11 $q11_q12 $q12_q13 $q13_q14 $q14_q15 $q0_q1_q2_q3 $q1_q2_q3_q4 $q2_q3_q4_q5 $q3_q4_q5_q6 $q5_q6_q7_q8 $q6_q7_q8_q9 $q7_q8_q9_q10 $q8_q9_q10_q11 $q9_q10_q11_q12 $q10_q11_q12_q13 $q11_q12_q13_q14 $q12_q13_q14_q15 $r12_sp $r0_r1 $r2_r3 $d0_d1_d2 $d1_d2_d3 $d2_d3_d4 $d3_d4_d5 $d4_d5_d6 $d5_d6_d7 $d6_d7_d8 $d7_d8_d9 $d14_d15_d16 $d15_d16_d17 $d16_d17_d18 $d17_d18_d19 $d18_d19_d20 $d19_d20_d21 $d20_d21_d22 $d21_d22_d23 $d22_d23_d24 $d23_d24_d25 $d24_d25_d26 $d25_d26_d27 $d26_d27_d28 $d27_d28_d29 $d28_d29_d30 $d29_d30_d31 $d0_d2_d4 $d1_d3_d5 $d2_d4_d6 $d3_d5_d7 $d4_d6_d8 $d5_d7_d9 $d6_d8_d10 $d7_d9_d11 $d12_d14_d16 $d13_d15_d17 $d14_d16_d18 $d15_d17_d19 $d16_d18_d20 $d17_d19_d21 $d18_d20_d22 $d19_d21_d23 $d20_d22_d24 $d21_d23_d25 $d22_d24_d26 $d23_d25_d27 $d24_d26_d28 $d25_d27_d29 $d26_d28_d30 $d27_d29_d31 $d0_d2_d4_d6 $d1_d3_d5_d7 $d2_d4_d6_d8 $d3_d5_d7_d9 $d4_d6_d8_d10 $d5_d7_d9_d11 $d6_d8_d10_d12 $d7_d9_d11_d13 $d10_d12_d14_d16 $d11_d13_d15_d17 $d12_d14_d16_d18 $d13_d15_d17_d19 $d14_d16_d18_d20 $d15_d17_d19_d21 $d16_d18_d20_d22 $d17_d19_d21_d23 $d18_d20_d22_d24 $d19_d21_d23_d25 $d20_d22_d24_d26 $d21_d23_d25_d27 $d22_d24_d26_d28 $d23_d25_d27_d29 $d24_d26_d28_d30 $d25_d27_d29_d31 $d1_d2 $d3_d4 $d5_d6 $d7_d8 $d15_d16 $d17_d18 $d19_d20 $d21_d22 $d23_d24 $d25_d26 $d27_d28 $d29_d30 $d1_d2_d3_d4 $d3_d4_d5_d6 $d5_d6_d7_d8 $d7_d8_d9_d10 $d13_d14_d15_d16 $d15_d16_d17_d18 $d17_d18_d19_d20 $d19_d20_d21_d22 $d21_d22_d23_d24 $d23_d24_d25_d26 $d25_d26_d27_d28 $d27_d28_d29_d30
call void @bar1()
call void @bar2()
ret void

28
test/MC/ARM/clrm-asm.s Normal file
View File

@ -0,0 +1,28 @@
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK %s
// RUN: FileCheck --check-prefix=ERROR < %t %s
// CHECK: clrm {r0, r1, r2, r3} @ encoding: [0x9f,0xe8,0x0f,0x00]
clrm {r0, r1, r2, r3}
// CHECK: clrm {r1, r2, r3, r4} @ encoding: [0x9f,0xe8,0x1e,0x00]
// ERROR-NOT: register list not in ascending order
clrm {r3, r4, r1, r2}
// CHECK: clrm {r0, apsr, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr} @ encoding: [0x9f,0xe8,0xff,0xdf]
clrm {r0-r12, lr, apsr}
// CHECK: clrm {apsr, lr} @ encoding: [0x9f,0xe8,0x00,0xc0]
clrm {apsr, lr}
// CHECK: clrm {r0, apsr, r1, r2, r3, r4, lr} @ encoding: [0x9f,0xe8,0x1f,0xc0]
clrm {r0-r4, apsr, lr}
// ERROR: invalid register in register list. Valid registers are r0-r12, lr/r14 and APSR.
clrm {sp}
// ERROR: invalid register in register list. Valid registers are r0-r12, lr/r14 and APSR.
clrm {r13}
// ERROR: invalid register in register list. Valid registers are r0-r12, lr/r14 and APSR.
clrm {r0-r12, sp}

View File

@ -0,0 +1,98 @@
// RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,+mve -show-encoding < %s \
// RUN: | FileCheck --check-prefix=CHECK %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-8msecext,+mve -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK-NOSEC %s
// RUN: FileCheck --check-prefix=ERROR-NOSEC < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,-mve,+vfp2 -show-encoding < %s 2> %t \
// RUN: | FileCheck --check-prefix=CHECK-NOMVE %s
// RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s
// RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,+mve,-vfp2 -show-encoding < %s \
// RUN: | FileCheck --check-prefix=CHECK-NOVFP %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-8msecext,-mve,-vfp2 -show-encoding < %s 2> %t
// RUN: FileCheck --check-prefix=ERROR-NONE < %t %s
// RUN: not llvm-mc -triple=thumbv8m.main-none-eabi -mattr=+8msecext,+vfp2 -show-encoding < %s 2> %t
// RUN: FileCheck --check-prefix=ERROR-V8M < %t %s
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOVFP: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
// CHECK-NOMVE: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
// CHECK-NOSEC: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
// CHECK: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
vmsr fpscr_nzcvqc, r0
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOVFP: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
// CHECK-NOMVE: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
// CHECK-NOSEC: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
// CHECK: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
vmrs r10, fpscr_nzcvqc
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// CHECK-NOVFP: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
// CHECK-NOMVE: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
vmrs r0, fpcxtns
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// CHECK-NOVFP: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
// CHECK-NOMVE: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
vmsr fpcxtns, r10
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// CHECK-NOVFP: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
// CHECK-NOMVE: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
vmsr fpcxts, r5
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// CHECK-NOVFP: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
// CHECK-NOMVE: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
vmrs r3, fpcxtns
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// CHECK-NOVFP: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
// CHECK-NOMVE: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
vmrs r0, fpcxts
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOSEC: vmrs r0, vpr @ encoding: [0xfc,0xee,0x10,0x0a]
// CHECK: vmrs r0, vpr @ encoding: [0xfc,0xee,0x10,0x0a]
vmrs r0, vpr
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOSEC: vmrs r4, p0 @ encoding: [0xfd,0xee,0x10,0x4a]
// CHECK: vmrs r4, p0 @ encoding: [0xfd,0xee,0x10,0x4a]
vmrs r4, p0
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOSEC: vmsr vpr, r0 @ encoding: [0xec,0xee,0x10,0x0a]
// CHECK: vmsr vpr, r0 @ encoding: [0xec,0xee,0x10,0x0a]
vmsr vpr, r0
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOSEC: vmsr p0, r4 @ encoding: [0xed,0xee,0x10,0x4a]
// CHECK: vmsr p0, r4 @ encoding: [0xed,0xee,0x10,0x4a]
vmsr p0, r4

1098
test/MC/ARM/thumbv8.1m.s Normal file

File diff suppressed because it is too large Load Diff

39
test/MC/ARM/vscclrm-asm.s Normal file
View File

@ -0,0 +1,39 @@
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK %s
// RUN: FileCheck --check-prefix=ERROR < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-arm-none-eabi -mattr=-8msecext < %s 2>%t
// RUN: FileCheck --check-prefix=NOSEC < %t %s
// CHECK: vscclrm {s0, s1, s2, s3, vpr} @ encoding: [0x9f,0xec,0x04,0x0a]
// NOSEC: instruction requires: ARMv8-M Security Extensions
vscclrm {s0-s3, vpr}
// CHECK: vscclrm {s3, s4, s5, s6, s7, s8, vpr} @ encoding: [0xdf,0xec,0x06,0x1a]
// NOSEC: instruction requires: ARMv8-M Security Extensions
vscclrm {s3-s8, vpr}
// CHECK: vscclrm {s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, vpr} @ encoding: [0x9f,0xec,0x0c,0x9a]
vscclrm {s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, vpr}
// CHECK: vscclrm {s31, vpr} @ encoding: [0xdf,0xec,0x01,0xfa]
vscclrm {s31, vpr}
// CHECK: vscclrm {d0, d1, vpr} @ encoding: [0x9f,0xec,0x04,0x0b]
vscclrm {d0-d1, vpr}
// CHECK: vscclrm {d5, d6, d7, vpr} @ encoding: [0x9f,0xec,0x06,0x5b]
vscclrm {d5-d7, vpr}
// CHECK: it hi @ encoding: [0x88,0xbf]
it hi
// CHECK: vscclrmhi {s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr} @ encoding: [0xdf,0xec,0x1d,0x1a]
vscclrmhi {s3-s31, vpr}
// ERROR: non-contiguous register range
vscclrm {s0, s3-s4, vpr}
// ERROR: register expected
vscclrm {s32, vpr}
// ERROR: invalid operand for instruction
vscclrm {s0-s1}

461
test/MC/ARM/vstrldr_sys.s Normal file
View File

@ -0,0 +1,461 @@
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,+mve,+8msecext -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK %s
// RUN: FileCheck --check-prefix=ERROR < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-vfp2,+mve,+8msecext -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK-NOVFP %s
// RUN: FileCheck --check-prefix=ERROR-NOVFP < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,-mve,+8msecext -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK-NOMVE %s
// RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,+mve,-8msecext -show-encoding < %s 2>%t \
// RUN: | FileCheck --check-prefix=CHECK-NOSEC %s
// RUN: FileCheck --check-prefix=ERROR-NOSEC < %t %s
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-vfp2,-mve,-8msecext -show-encoding < %s 2>%t
// RUN: FileCheck --check-prefix=ERROR-NONE < %t %s
// RUN: not llvm-mc -triple=thumbv8m.main-none-eabi -mattr=+vfp2,+8msecext -show-encoding < %s 2>%t
// RUN: FileCheck --check-prefix=ERROR-V8M < %t %s
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK-NOMVE: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK-NOVFP: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
vstr fpscr, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
// CHECK-NOMVE: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
// CHECK-NOVFP: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
// CHECK: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
vstr fpscr_nzcvqc, [r9, #-24]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
// CHECK-NOMVE: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
// CHECK-NOVFP: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
// CHECK: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
vstr fpscr_nzcvqc, [r9, #-24]!
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
// CHECK-NOMVE: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
// CHECK-NOVFP: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
// CHECK: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
vstr fpscr_nzcvqc, [r9], #-24
// CHECK-NOSEC: it hi @ encoding: [0x88,0xbf]
// CHECK-NOMVE: it hi @ encoding: [0x88,0xbf]
// CHECK-NOVFP: it hi @ encoding: [0x88,0xbf]
// CHECK: it hi @ encoding: [0x88,0xbf]
it hi
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK-NOMVE: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK-NOVFP: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
// CHECK: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
vstrhi fpscr, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK-NOMVE: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK-NOVFP: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
vldr fpscr, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
// CHECK-NOMVE: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
// CHECK-NOVFP: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
// CHECK: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
vldr fpscr_nzcvqc, [r9, #-24]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
// CHECK-NOMVE: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
// CHECK-NOVFP: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
// CHECK: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
vldr fpscr_nzcvqc, [r9, #-24]!
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
// CHECK-NOMVE: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
// CHECK-NOVFP: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
// CHECK: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
vldr fpscr_nzcvqc, [r9], #-24
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
// CHECK-NOMVE: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
// CHECK-NOVFP: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
// CHECK: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
vldr fpscr_nzcvqc, [sp], #-52
// CHECK-NOSEC: it hi @ encoding: [0x88,0xbf]
// CHECK-NOMVE: it hi @ encoding: [0x88,0xbf]
// CHECK-NOVFP: it hi @ encoding: [0x88,0xbf]
// CHECK: it hi @ encoding: [0x88,0xbf]
it hi
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: fp registers
// CHECK-NOSEC: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK-NOMVE: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK-NOVFP: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
// CHECK: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
vldrhi fpscr, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
// CHECK-NOVFP: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
// CHECK: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
vstr fpcxts, [r12, #508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
// CHECK-NOVFP: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
// CHECK: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
vstr fpcxts, [r12, #508]!
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
// CHECK-NOVFP: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
// CHECK: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
vstr fpcxts, [r12], #508
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
// CHECK-NOVFP: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
// CHECK: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
vstr fpcxts, [sp], #-24
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
// CHECK-NOVFP: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
// CHECK: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
vldr fpcxts, [r12, #508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
// CHECK-NOVFP: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
// CHECK: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
vldr fpcxts, [r12, #508]!
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
// CHECK-NOVFP: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
// CHECK: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
vldr fpcxts, [r12], #508
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
// CHECK-NOVFP: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
// CHECK: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
vldr fpcxts, [sp], #-24
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
// CHECK: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
vstr fpcxtns, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
// CHECK: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
vstr fpcxtns, [r9, #-24]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
// CHECK: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
vstr fpcxtns, [r6, #500]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
// CHECK: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
vstr fpcxtns, [lr, #-508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
// CHECK: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
vstr fpcxtns, [r12, #508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
// CHECK-NOVFP: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
// CHECK: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
vstr fpcxtns, [sp], #-24
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
// CHECK: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
vldr fpcxtns, [r0]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
// CHECK: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
vldr fpcxtns, [r9, #-24]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
// CHECK: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
vldr fpcxtns, [r6, #500]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
// CHECK: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
vldr fpcxtns, [lr, #-508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
// CHECK: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
vldr fpcxtns, [r12, #508]
// ERROR-V8M: instruction requires: armv8.1m.main
// ERROR-NONE: instruction requires: ARMv8-M Security Extensions
// ERROR-NOSEC: instruction requires: ARMv8-M Security Extensions
// CHECK-NOMVE: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
// CHECK-NOVFP: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
// CHECK: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
vldr fpcxtns, [sp], #-24
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
// CHECK: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
vstr vpr, [r6, #500]
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
// CHECK: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
vstr p0, [lr, #-508]
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
// CHECK: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
vstr vpr, [r6, #500]!
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
// CHECK: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
vstr p0, [lr, #-508]!
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
// CHECK: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
vstr vpr, [r6], #500
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
// CHECK: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
vstr p0, [lr], #-508
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
// CHECK: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
vstr p0, [sp], #-24
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
// CHECK: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
vldr vpr, [r6, #500]
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
// CHECK: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
vldr p0, [lr, #-508]
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
// CHECK: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
vldr vpr, [r6, #500]!
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
// CHECK: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
vldr p0, [lr, #-508]!
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
// CHECK: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
vldr vpr, [r6], #500
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
// CHECK: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
vldr p0, [lr], #-508
// ERROR-V8M: instruction requires: mve armv8.1m.main
// ERROR-NONE: instruction requires: mve
// CHECK-NOSEC: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
// ERROR-NOMVE: instruction requires: mve
// CHECK-NOVFP: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
// CHECK: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
vldr p0, [sp], #-24
// ERROR-NOSEC: invalid instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpcxtns, [pc, #4]!
// ERROR-NOSEC: invalid instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vstr fpcxtns, [r0, #-507]
// ERROR-NOSEC: invalid instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpcxtns, [r2, #512]
// ERROR-NOSEC: invalid instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpcxtns, [pc], #-24
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vstr vpr, [r0, #-507]
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr p0, [r2, #512]
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr p0, [r2, #2]
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr p0, [pc], #4
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpscr, [pc, #4]!
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpscr_nzcvqc, [r8], #-53
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpscr_nzcvqc, [r8], #2
// ERROR-NOSEC: invalid operand for instruction
// ERROR-NOMVE: invalid operand for instruction
// ERROR-NOVFP: invalid operand for instruction
// ERROR: invalid operand for instruction
vldr fpscr_nzcvqc, [pc], #-52

View File

@ -0,0 +1,20 @@
# RUN: not llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -show-encoding < %s 2> %t | FileCheck %s
# RUN: FileCheck --check-prefix=ERROR < %t %s
[0x9f,0xe8,0x0f,0x00]
# CHECK: clrm {r0, r1, r2, r3} @ encoding: [0x9f,0xe8,0x0f,0x00]
[0x9f,0xe8,0xff,0xdf]
# CHECK: clrm {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr, apsr} @ encoding: [0x9f,0xe8,0xff,0xdf]
[0x9f,0xe8,0x00,0x10]
# CHECK: clrm {r12} @ encoding: [0x9f,0xe8,0x00,0x10]
[0x9f,0xe8,0x00,0x40]
# CHECK: clrm {lr} @ encoding: [0x9f,0xe8,0x00,0x40]
[0x9f,0xe8,0x00,0x80]
# CHECK: clrm {apsr} @ encoding: [0x9f,0xe8,0x00,0x80]
[0x9f,0xe8,0x00,0x00]
# ERROR: [[@LINE-1]]:2: warning: invalid instruction encoding

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,+mve -show-encoding -disassemble < %s \
# RUN: | FileCheck --check-prefix=CHECK %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-8msecext,+mve -show-encoding -disassemble < %s 2>%t \
# RUN: | FileCheck --check-prefix=CHECK-NOSEC %s
# RUN: FileCheck --check-prefix=ERROR-NOSEC < %t %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,-mve,+vfp2 -show-encoding -disassemble < %s 2> %t \
# RUN: | FileCheck --check-prefix=CHECK-NOMVE %s
# RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s
# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext,+mve,-vfp2 -show-encoding -disassemble < %s \
# RUN: | FileCheck --check-prefix=CHECK-NOVFP %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-8msecext,-mve,-vfp2 -show-encoding -disassemble < %s 2> %t
# RUN: FileCheck --check-prefix=ERROR-NONE < %t %s
# RUN: not llvm-mc -triple=thumbv8m.main-none-eabi -mattr=+8msecext,+vfp2 -show-encoding -disassemble < %s 2> %t
# RUN: FileCheck --check-prefix=ERROR-V8M < %t %s
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
# CHECK-NOMVE: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
# CHECK-NOSEC: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
# CHECK: vmsr fpscr_nzcvqc, r0 @ encoding: [0xe2,0xee,0x10,0x0a]
[0xe2,0xee,0x10,0x0a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
# CHECK-NOMVE: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
# CHECK-NOSEC: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
# CHECK: vmrs r10, fpscr_nzcvqc @ encoding: [0xf2,0xee,0x10,0xaa]
[0xf2,0xee,0x10,0xaa]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
# CHECK-NOMVE: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
# ERROR-NOSEC: invalid instruction encoding
# CHECK: vmrs r0, fpcxtns @ encoding: [0xfe,0xee,0x10,0x0a]
[0xfe,0xee,0x10,0x0a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
# CHECK-NOMVE: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
# ERROR-NOSEC: invalid instruction encoding
# CHECK: vmsr fpcxtns, r10 @ encoding: [0xee,0xee,0x10,0xaa]
[0xee,0xee,0x10,0xaa]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
# CHECK-NOMVE: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
# ERROR-NOSEC: invalid instruction encoding
# CHECK: vmsr fpcxts, r5 @ encoding: [0xef,0xee,0x10,0x5a]
[0xef,0xee,0x10,0x5a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
# CHECK-NOMVE: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
# ERROR-NOSEC: invalid instruction encoding
# CHECK: vmrs r3, fpcxtns @ encoding: [0xfe,0xee,0x10,0x3a]
[0xfe,0xee,0x10,0x3a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# CHECK-NOVFP: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
# CHECK-NOMVE: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
# ERROR-NOSEC: invalid instruction encoding
# CHECK: vmrs r0, fpcxts @ encoding: [0xff,0xee,0x10,0x0a]
[0xff,0xee,0x10,0x0a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# ERROR-NOMVE: invalid instruction encoding
# CHECK-NOSEC: vmrs r0, vpr @ encoding: [0xfc,0xee,0x10,0x0a]
# CHECK: vmrs r0, vpr @ encoding: [0xfc,0xee,0x10,0x0a]
[0xfc,0xee,0x10,0x0a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# ERROR-NOMVE: invalid instruction encoding
# CHECK-NOSEC: vmrs r4, p0 @ encoding: [0xfd,0xee,0x10,0x4a]
# CHECK: vmrs r4, p0 @ encoding: [0xfd,0xee,0x10,0x4a]
[0xfd,0xee,0x10,0x4a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# ERROR-NOMVE: invalid instruction encoding
# CHECK-NOSEC: vmsr vpr, r0 @ encoding: [0xec,0xee,0x10,0x0a]
# CHECK: vmsr vpr, r0 @ encoding: [0xec,0xee,0x10,0x0a]
[0xec,0xee,0x10,0x0a]
# ERROR-V8M: invalid instruction encoding
# ERROR-NONE: invalid instruction encoding
# ERROR-NOMVE: invalid instruction encoding
# CHECK-NOSEC: vmsr p0, r4 @ encoding: [0xed,0xee,0x10,0x4a]
# CHECK: vmsr p0, r4 @ encoding: [0xed,0xee,0x10,0x4a]
[0xed,0xee,0x10,0x4a]

View File

@ -0,0 +1,104 @@
# RUN: llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -show-encoding %s 2> %t | FileCheck %s
# RUN: FileCheck --check-prefix=ERROR < %t %s
[0x52 0xea 0x22 0x9e]
# CHECK: cinc lr, r2, lo @ encoding: [0x52,0xea,0x22,0x9e]
[0x57 0xea 0x47 0x9e]
# CHECK: cinc lr, r7, pl @ encoding: [0x57,0xea,0x47,0x9e]
[0x5c 0xea 0x3c 0xae]
# CHECK: cinv lr, r12, hs @ encoding: [0x5c,0xea,0x3c,0xae]
[0x5a 0xea 0x3a 0xbe]
# CHECK: cneg lr, r10, hs @ encoding: [0x5a,0xea,0x3a,0xbe]
[0x59 0xea 0x7b 0x89]
# CHECK: csel r9, r9, r11, vc @ encoding: [0x59,0xea,0x7b,0x89]
[0x5f 0xea 0x1f 0x9e]
# CHECK: cset lr, eq @ encoding: [0x5f,0xea,0x1f,0x9e]
[0x5f 0xea 0x3f 0xae]
# CHECK: csetm lr, hs @ encoding: [0x5f,0xea,0x3f,0xae]
[0x5a 0xea 0xd7 0x9e]
# CHECK: csinc lr, r10, r7, le @ encoding: [0x5a,0xea,0xd7,0x9e]
[0x55 0xea 0x2f 0xae]
# CHECK: csinv lr, r5, zr, hs @ encoding: [0x55,0xea,0x2f,0xae]
[0x52 0xea 0x42 0xae]
# CHECK: cinv lr, r2, pl @ encoding: [0x52,0xea,0x42,0xae]
[0x51 0xea 0x7b 0xbe]
# CHECK: csneg lr, r1, r11, vc @ encoding: [0x51,0xea,0x7b,0xbe]
[0x50,0xea,0x01,0x80]
# CHECK: csel r0, r0, r1, eq @ encoding: [0x50,0xea,0x01,0x80]
[0x5d 0xea 0x22 0x9e]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x47 0x9e]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x3c 0xae]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x3a 0xbe]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x7b 0x89]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x1f 0x9e]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x3f 0xae]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0xd7 0x9e]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x2f 0xae]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x42 0xae]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5d 0xea 0x7b 0xbe]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x52 0xea 0x22 0x9d]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x57 0xea 0x47 0x9d]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5c 0xea 0x3c 0xad]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5a 0xea 0x3a 0xbd]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x59 0xea 0x7b 0x8d]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5f 0xea 0x1f 0x9d]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5f 0xea 0x3f 0xad]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x5a 0xea 0xd7 0x9d]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x55 0xea 0x2f 0xad]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x52 0xea 0x42 0xad]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding
[0x51 0xea 0x7b 0xbd]
# ERROR: [[@LINE-1]]:2: warning: potentially undefined instruction encoding

View File

@ -0,0 +1,26 @@
# RUN: llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -mattr=+8msecext -show-encoding %s 2>1 | FileCheck %s
[0x9f 0xec 0x04 0x0a]
# CHECK: vscclrm {s0, s1, s2, s3, vpr}
[0xdf,0xec,0x06,0x1a]
# CHECK: vscclrm {s3, s4, s5, s6, s7, s8, vpr} @ encoding: [0xdf,0xec,0x06,0x1a]
[0x9f 0xec 0x0c 0x9a]
# CHECK: vscclrm {s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, vpr}
[0xdf 0xec 0x01 0xfa]
# CHECK: vscclrm {s31, vpr}
[0x9f,0xec,0x04,0x0b]
# CHECK: vscclrm {d0, d1, vpr} @ encoding: [0x9f,0xec,0x04,0x0b]
[0x9f,0xec,0x06,0x5b]
# CHECK: vscclrm {d5, d6, d7, vpr} @ encoding: [0x9f,0xec,0x06,0x5b]
[0x88 0xbf]
# CHECK: it hi
[0xdf 0xec 0x1d 0x1a]
# CHECK: vscclrmhi {s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}

View File

@ -0,0 +1,328 @@
# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,+mve,+8msecext -show-encoding -disassemble < %s 2>%t \
# RUN: | FileCheck --check-prefix=CHECK %s
# RUN: FileCheck --check-prefix=ERROR < %t %s
# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-vfp2,+mve,+8msecext -show-encoding -disassemble < %s 2>%t \
# RUN: | FileCheck --check-prefix=CHECK-NOVFP %s
# RUN: FileCheck --check-prefix=ERROR-NOVFP < %t %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,-mve,+8msecext -show-encoding -disassemble < %s 2>%t \
# RUN: | FileCheck --check-prefix=CHECK-NOMVE %s
# RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+vfp2,+mve,-8msecext -show-encoding -disassemble < %s 2>%t \
# RUN: | FileCheck --check-prefix=CHECK-NOSEC %s
# RUN: FileCheck --check-prefix=ERROR-NOSEC < %t %s
# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=-vfp2,-mve,-8msecext -show-encoding -disassemble < %s 2>%t
# RUN: FileCheck --check-prefix=ERROR-NONE < %t %s
# ERROR-NONE: invalid instruction encoding
# CHECK-NOSEC: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK-NOMVE: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK-NOVFP: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK: vstr fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
[0x80,0xed,0x80,0x2f]
# CHECK-NOSEC: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
# CHECK-NOMVE: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
# CHECK-NOVFP: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
# CHECK: vstr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x09,0xed,0x86,0x4f]
[0x09,0xed,0x86,0x4f]
# CHECK-NOSEC: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
# CHECK-NOMVE: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
# CHECK-NOVFP: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
# CHECK: vstr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x29,0xed,0x86,0x4f]
[0x29,0xed,0x86,0x4f]
# CHECK-NOSEC: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
# CHECK-NOMVE: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
# CHECK-NOVFP: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
# CHECK: vstr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x29,0xec,0x86,0x4f]
[0x29,0xec,0x86,0x4f]
# CHECK-NOSEC: it hi @ encoding: [0x88,0xbf]
# CHECK-NOMVE: it hi @ encoding: [0x88,0xbf]
# CHECK-NOVFP: it hi @ encoding: [0x88,0xbf]
# CHECK: it hi @ encoding: [0x88,0xbf]
[0x88,0xbf]
# CHECK-NOSEC: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK-NOMVE: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK-NOVFP: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
# CHECK: vstrhi fpscr, [r0] @ encoding: [0x80,0xed,0x80,0x2f]
[0x80,0xed,0x80,0x2f]
# CHECK-NOSEC: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK-NOMVE: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK-NOVFP: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK: vldr fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
[0x90,0xed,0x80,0x2f]
# CHECK-NOSEC: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
# CHECK-NOMVE: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
# CHECK-NOVFP: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
# CHECK: vldr fpscr_nzcvqc, [r9, #-24] @ encoding: [0x19,0xed,0x86,0x4f]
[0x19,0xed,0x86,0x4f]
# CHECK-NOSEC: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
# CHECK-NOMVE: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
# CHECK-NOVFP: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
# CHECK: vldr fpscr_nzcvqc, [r9, #-24]! @ encoding: [0x39,0xed,0x86,0x4f]
[0x39,0xed,0x86,0x4f]
# CHECK-NOSEC: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
# CHECK-NOMVE: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
# CHECK-NOVFP: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
# CHECK: vldr fpscr_nzcvqc, [r9], #-24 @ encoding: [0x39,0xec,0x86,0x4f]
[0x39,0xec,0x86,0x4f]
# CHECK-NOSEC: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
# CHECK-NOMVE: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
# CHECK-NOVFP: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
# CHECK: vldr fpscr_nzcvqc, [sp], #-52 @ encoding: [0x3d,0xec,0x8d,0x4f]
[0x3d,0xec,0x8d,0x4f]
# CHECK-NOSEC: it hi @ encoding: [0x88,0xbf]
# CHECK-NOMVE: it hi @ encoding: [0x88,0xbf]
# CHECK-NOVFP: it hi @ encoding: [0x88,0xbf]
# CHECK: it hi @ encoding: [0x88,0xbf]
[0x88,0xbf]
# CHECK-NOSEC: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK-NOMVE: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK-NOVFP: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
# CHECK: vldrhi fpscr, [r0] @ encoding: [0x90,0xed,0x80,0x2f]
[0x90,0xed,0x80,0x2f]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
# CHECK-NOVFP: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
# CHECK: vstr fpcxts, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xef]
[0xcc,0xed,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
# CHECK-NOVFP: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
# CHECK: vstr fpcxts, [r12, #508]! @ encoding: [0xec,0xed,0xff,0xef]
[0xec,0xed,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
# CHECK-NOVFP: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
# CHECK: vstr fpcxts, [r12], #508 @ encoding: [0xec,0xec,0xff,0xef]
[0xec,0xec,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
# CHECK-NOVFP: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
# CHECK: vstr fpcxts, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xef]
[0x6d,0xec,0x86,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
# CHECK-NOVFP: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
# CHECK: vldr fpcxts, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xef]
[0xdc,0xed,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
# CHECK-NOVFP: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
# CHECK: vldr fpcxts, [r12, #508]! @ encoding: [0xfc,0xed,0xff,0xef]
[0xfc,0xed,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
# CHECK-NOVFP: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
# CHECK: vldr fpcxts, [r12], #508 @ encoding: [0xfc,0xec,0xff,0xef]
[0xfc,0xec,0xff,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
# CHECK-NOVFP: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
# CHECK: vldr fpcxts, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xef]
[0x7d,0xec,0x86,0xef]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
# CHECK: vstr fpcxtns, [r0] @ encoding: [0xc0,0xed,0x80,0xcf]
[0xc0,0xed,0x80,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
# CHECK: vstr fpcxtns, [r9, #-24] @ encoding: [0x49,0xed,0x86,0xcf]
[0x49,0xed,0x86,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
# CHECK: vstr fpcxtns, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0xcf]
[0xc6,0xed,0xfd,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
# CHECK: vstr fpcxtns, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xcf]
[0x4e,0xed,0xff,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
# CHECK: vstr fpcxtns, [r12, #508] @ encoding: [0xcc,0xed,0xff,0xcf]
[0xcc,0xed,0xff,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
# CHECK-NOVFP: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
# CHECK: vstr fpcxtns, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xcf]
[0x6d,0xec,0x86,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
# CHECK: vldr fpcxtns, [r0] @ encoding: [0xd0,0xed,0x80,0xcf]
[0xd0,0xed,0x80,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
# CHECK: vldr fpcxtns, [r9, #-24] @ encoding: [0x59,0xed,0x86,0xcf]
[0x59,0xed,0x86,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
# CHECK: vldr fpcxtns, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0xcf]
[0xd6,0xed,0xfd,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
# CHECK: vldr fpcxtns, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xcf]
[0x5e,0xed,0xff,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
# CHECK: vldr fpcxtns, [r12, #508] @ encoding: [0xdc,0xed,0xff,0xcf]
[0xdc,0xed,0xff,0xcf]
# ERROR-NOSEC invalid instruction encoding
# CHECK-NOMVE: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
# CHECK-NOVFP: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
# CHECK: vldr fpcxtns, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xcf]
[0x7d,0xec,0x86,0xcf]
# CHECK-NOSEC: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
# CHECK: vstr vpr, [r6, #500] @ encoding: [0xc6,0xed,0xfd,0x8f]
[0xc6,0xed,0xfd,0x8f]
# CHECK-NOSEC: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
# CHECK: vstr p0, [lr, #-508] @ encoding: [0x4e,0xed,0xff,0xaf]
[0x4e,0xed,0xff,0xaf]
# CHECK-NOSEC: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
# CHECK: vstr vpr, [r6, #500]! @ encoding: [0xe6,0xed,0xfd,0x8f]
[0xe6,0xed,0xfd,0x8f]
# CHECK-NOSEC: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
# CHECK: vstr p0, [lr, #-508]! @ encoding: [0x6e,0xed,0xff,0xaf]
[0x6e,0xed,0xff,0xaf]
# CHECK-NOSEC: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
# CHECK: vstr vpr, [r6], #500 @ encoding: [0xe6,0xec,0xfd,0x8f]
[0xe6,0xec,0xfd,0x8f]
# CHECK-NOSEC: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
# CHECK: vstr p0, [lr], #-508 @ encoding: [0x6e,0xec,0xff,0xaf]
[0x6e,0xec,0xff,0xaf]
# CHECK-NOSEC: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
# CHECK: vstr p0, [sp], #-24 @ encoding: [0x6d,0xec,0x86,0xaf]
[0x6d,0xec,0x86,0xaf]
# CHECK-NOSEC: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
# CHECK: vldr vpr, [r6, #500] @ encoding: [0xd6,0xed,0xfd,0x8f]
[0xd6,0xed,0xfd,0x8f]
# CHECK-NOSEC: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
# CHECK: vldr p0, [lr, #-508] @ encoding: [0x5e,0xed,0xff,0xaf]
[0x5e,0xed,0xff,0xaf]
# CHECK-NOSEC: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
# CHECK: vldr vpr, [r6, #500]! @ encoding: [0xf6,0xed,0xfd,0x8f]
[0xf6,0xed,0xfd,0x8f]
# CHECK-NOSEC: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
# CHECK: vldr p0, [lr, #-508]! @ encoding: [0x7e,0xed,0xff,0xaf]
[0x7e,0xed,0xff,0xaf]
# CHECK-NOSEC: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
# CHECK: vldr vpr, [r6], #500 @ encoding: [0xf6,0xec,0xfd,0x8f]
[0xf6,0xec,0xfd,0x8f]
# CHECK-NOSEC: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
# CHECK: vldr p0, [lr], #-508 @ encoding: [0x7e,0xec,0xff,0xaf]
[0x7e,0xec,0xff,0xaf]
# CHECK-NOSEC: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
# ERROR-NOMVE invalid instruction encoding
# CHECK-NOVFP: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
# CHECK: vldr p0, [sp], #-24 @ encoding: [0x7d,0xec,0x86,0xaf]
[0x7d,0xec,0x86,0xaf]
# ERROR-NOSEC: invalid instruction encoding
# ERROR-NOMVE: potentially undefined instruction encoding
# ERROR-NOVFP: potentially undefined instruction encoding
# ERROR: potentially undefined instruction encoding
[0x7f,0xec,0x86,0xcf]
# ERROR-NOSEC: invalid instruction encoding
# ERROR-NOMVE: potentially undefined instruction encoding
# ERROR-NOVFP: potentially undefined instruction encoding
# ERROR: potentially undefined instruction encoding
[0x7f,0xec,0x86,0xcf]
# ERROR-NOSEC: potentially undefined instruction encoding
# ERROR-NOMVE: invalid instruction encoding
# ERROR-NOVFP: potentially undefined instruction encoding
# ERROR: potentially undefined instruction encoding
[0xff,0xec,0x81,0xaf]
# ERROR-NOSEC: potentially undefined instruction encoding
# ERROR-NOMVE: potentially undefined instruction encoding
# ERROR-NOVFP: potentially undefined instruction encoding
# ERROR: potentially undefined instruction encoding
[0xbf,0xed,0x81,0x2f]
# ERROR-NOSEC: potentially undefined instruction encoding
# ERROR-NOMVE: potentially undefined instruction encoding
# ERROR-NOVFP: potentially undefined instruction encoding
# ERROR: potentially undefined instruction encoding
[0x3f,0xec,0x8d,0x4f]