+//===----- AArch64InstrInfo.td - AArch64 Instruction Info ----*- tablegen -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the AArch64 scalar instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
include "AArch64InstrFormats.td"
//===----------------------------------------------------------------------===//
// is not optional in that case (but can explicitly be 0), and the
// entire suffix can be skipped (e.g. "add sp, x3, x2").
-multiclass extend_operands<string PREFIX> {
+multiclass extend_operands<string PREFIX, string Diag> {
def _asmoperand : AsmOperandClass {
let Name = PREFIX;
let RenderMethod = "addRegExtendOperands";
let PredicateMethod = "isRegExtend<A64SE::" # PREFIX # ">";
+ let DiagnosticType = "AddSubRegExtend" # Diag;
}
def _operand : Operand<i64>,
}
}
-defm UXTB : extend_operands<"UXTB">;
-defm UXTH : extend_operands<"UXTH">;
-defm UXTW : extend_operands<"UXTW">;
-defm UXTX : extend_operands<"UXTX">;
-defm SXTB : extend_operands<"SXTB">;
-defm SXTH : extend_operands<"SXTH">;
-defm SXTW : extend_operands<"SXTW">;
-defm SXTX : extend_operands<"SXTX">;
+defm UXTB : extend_operands<"UXTB", "Small">;
+defm UXTH : extend_operands<"UXTH", "Small">;
+defm UXTW : extend_operands<"UXTW", "Small">;
+defm UXTX : extend_operands<"UXTX", "Large">;
+defm SXTB : extend_operands<"SXTB", "Small">;
+defm SXTH : extend_operands<"SXTH", "Small">;
+defm SXTW : extend_operands<"SXTW", "Small">;
+defm SXTX : extend_operands<"SXTX", "Large">;
def LSL_extasmoperand : AsmOperandClass {
let Name = "RegExtendLSL";
let RenderMethod = "addRegExtendOperands";
+ let DiagnosticType = "AddSubRegExtendLarge";
}
def LSL_extoperand : Operand<i64> {
// Derived PredicateMethod fields are different for each
def addsubimm_lsl0_asmoperand : AsmOperandClass {
let Name = "AddSubImmLSL0";
+ // If an error is reported against this operand, instruction could also be a
+ // register variant.
+ let DiagnosticType = "AddSubSecondSource";
}
def addsubimm_lsl12_asmoperand : AsmOperandClass {
let Name = "AddSubImmLSL12";
+ let DiagnosticType = "AddSubSecondSource";
}
}
def _asmoperand_i32 : AsmOperandClass {
let Name = "Shift" # form # "i32";
let RenderMethod = "addShiftOperands";
- let PredicateMethod
- = "isShift<A64SE::" # form # ", false>";
+ let PredicateMethod = "isShift<A64SE::" # form # ", false>";
+ let DiagnosticType = "AddSubRegShift32";
}
// Note that the operand type is intentionally i64 because the DAGCombiner
def _asmoperand_i64 : AsmOperandClass {
let Name = "Shift" # form # "i64";
let RenderMethod = "addShiftOperands";
- let PredicateMethod
- = "isShift<A64SE::" # form # ", true>";
+ let PredicateMethod = "isShift<A64SE::" # form # ", true>";
+ let DiagnosticType = "AddSubRegShift64";
}
def _i64 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 63; }]> {
let Name = "UImm5";
let PredicateMethod = "isUImm<5>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm5";
}
def uimm6_asmoperand : AsmOperandClass {
let Name = "UImm6";
let PredicateMethod = "isUImm<6>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm6";
}
def bitfield32_imm : Operand<i64>,
let Name = "BFX32Width";
let PredicateMethod = "isBitfieldWidth<32>";
let RenderMethod = "addBFXWidthOperands";
+ let DiagnosticType = "Width32";
}
def bfx32_width : Operand<i64>, ImmLeaf<i64, [{ return true; }]> {
let Name = "BFX64Width";
let PredicateMethod = "isBitfieldWidth<64>";
let RenderMethod = "addBFXWidthOperands";
+ let DiagnosticType = "Width64";
}
def bfx64_width : Operand<i64> {
let Name = "BFI32LSB";
let PredicateMethod = "isUImm<5>";
let RenderMethod = "addBFILSBOperands<32>";
+ let DiagnosticType = "UImm5";
}
def bfi32_lsb : Operand<i64>,
let Name = "BFI64LSB";
let PredicateMethod = "isUImm<6>";
let RenderMethod = "addBFILSBOperands<64>";
+ let DiagnosticType = "UImm6";
}
def bfi64_lsb : Operand<i64>,
let Name = "BFI32Width";
let PredicateMethod = "isBitfieldWidth<32>";
let RenderMethod = "addBFIWidthOperands";
+ let DiagnosticType = "Width32";
}
def bfi32_width : Operand<i64>,
let Name = "BFI64Width";
let PredicateMethod = "isBitfieldWidth<64>";
let RenderMethod = "addBFIWidthOperands";
+ let DiagnosticType = "Width64";
}
def bfi64_width : Operand<i64>,
let Name = "Label" # width # "_" # scale;
let PredicateMethod = "isLabel<" # width # "," # scale # ">";
let RenderMethod = "addLabelOperands<" # width # ", " # scale # ">";
+ let DiagnosticType = "Label";
}
def label_wid19_scal4_asmoperand : label_asmoperand<19, 4>;
def cond_code_asmoperand : AsmOperandClass {
let Name = "CondCode";
+ let DiagnosticType = "CondCode";
}
def cond_code : Operand<i32>, ImmLeaf<i32, [{
let Name = "UImm4";
let PredicateMethod = "isUImm<4>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm4";
}
def uimm4 : Operand<i32> {
let RenderMethod = "addCondCodeOperands";
let PredicateMethod = "isCondCode";
let ParserMethod = "ParseCondCodeOperand";
+ let DiagnosticType = "CondCode";
}
def cond_code_op : Operand<i32> {
let RenderMethod = "addInvCondCodeOperands";
let PredicateMethod = "isCondCode";
let ParserMethod = "ParseCondCodeOperand";
+ let DiagnosticType = "CondCode";
}
def inv_cond_code_op : Operand<i32> {
itin>;
multiclass A64I_dp_1src <bits<6> opcode, string asmop> {
- let neverHasSideEffects = 1 in {
+ let hasSideEffects = 0 in {
def ww : A64I_dp_1src_impl<0b0, opcode, asmop, [], GPR32, NoItinerary>;
def xx : A64I_dp_1src_impl<0b1, opcode, asmop, [], GPR64, NoItinerary>;
}
//===----------------------------------------------------------------------===//
// Data Processing (2 sources) instructions
//===----------------------------------------------------------------------===//
-// Contains: UDIV, SDIV, LSLV, LSRV, ASRV, RORV + aliases LSL, LSR, ASR, ROR
+// Contains: CRC32C?[BHWX], UDIV, SDIV, LSLV, LSRV, ASRV, RORV + aliases LSL,
+// LSR, ASR, ROR
+
class dp_2src_impl<bit sf, bits<6> opcode, string asmop, list<dag> patterns,
RegisterClass GPRsp,
patterns,
itin>;
+multiclass dp_2src_crc<bit c, string asmop> {
+ def B_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 0},
+ !strconcat(asmop, "b"), [], GPR32, NoItinerary>;
+ def H_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 1},
+ !strconcat(asmop, "h"), [], GPR32, NoItinerary>;
+ def W_www : dp_2src_impl<0b0, {0, 1, 0, c, 1, 0},
+ !strconcat(asmop, "w"), [], GPR32, NoItinerary>;
+ def X_wwx : A64I_dp_2src<0b1, {0, 1, 0, c, 1, 1}, 0b0,
+ !strconcat(asmop, "x\t$Rd, $Rn, $Rm"),
+ (outs GPR32:$Rd), (ins GPR32:$Rn, GPR64:$Rm), [],
+ NoItinerary>;
+}
+
multiclass dp_2src_zext <bits<6> opcode, string asmop, SDPatternOperator op> {
def www : dp_2src_impl<0b0,
opcode,
}
// Here we define the data processing 2 source instructions.
+defm CRC32 : dp_2src_crc<0b0, "crc32">;
+defm CRC32C : dp_2src_crc<0b1, "crc32c">;
+
defm UDIV : dp_2src<0b000010, "udiv", udiv>;
defm SDIV : dp_2src<0b000011, "sdiv", sdiv>;
let Name = "UImm16";
let PredicateMethod = "isUImm<16>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm16";
}
def uimm16 : Operand<i32> {
def fpzero_asmoperand : AsmOperandClass {
let Name = "FPZero";
let ParserMethod = "ParseFPImmOperand";
+ let DiagnosticType = "FPZero";
}
def fpz32 : Operand<f32>,
let Name = "CVTFixedPos32";
let RenderMethod = "addCVTFixedPosOperands";
let PredicateMethod = "isCVTFixedPos<32>";
+ let DiagnosticType = "CVTFixedPos32";
}
// Also encoded as "64 - <specified imm>" but #1-#64 allowed.
let Name = "CVTFixedPos64";
let RenderMethod = "addCVTFixedPosOperands";
let PredicateMethod = "isCVTFixedPos<64>";
+ let DiagnosticType = "CVTFixedPos64";
}
// We need the cartesian product of f32/f64 i32/i64 operands for
def lane1_asmoperand : AsmOperandClass {
let Name = "Lane1";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "Lane1";
}
def lane1 : Operand<i32> {
def fpimm_asmoperand : AsmOperandClass {
let Name = "FMOVImm";
let ParserMethod = "ParseFPImmOperand";
+ let DiagnosticType = "FPImm";
}
// The MCOperand for these instructions are the encoded 8-bit values.
def ldrlit_label_asmoperand : AsmOperandClass {
let Name = "LoadLitLabel";
let RenderMethod = "addLabelOperands<19, 4>";
+ let DiagnosticType = "Label";
}
def ldrlit_label : Operand<i64> {
let PredicateMethod = "isUImm";
let RenderMethod = "addImmOperands";
let ParserMethod = "ParseNamedImmOperand<" # mapper # ">";
+ let DiagnosticType = "NamedImm_" # prefix;
}
def _op : Operand<i32> {
def LDRx_lit : A64I_LDRlitSimple<0b01, 0b0, GPR64>;
}
-def LDRs_lit : A64I_LDRlitSimple<0b00, 0b1, FPR32,
- [(set (f32 FPR32:$Rt), (load constpool:$Imm19))]>;
-def LDRd_lit : A64I_LDRlitSimple<0b01, 0b1, FPR64,
- [(set (f64 FPR64:$Rt), (load constpool:$Imm19))]>;
+def LDRs_lit : A64I_LDRlitSimple<0b00, 0b1, FPR32>;
+def LDRd_lit : A64I_LDRlitSimple<0b01, 0b1, FPR64>;
let mayLoad = 1 in {
def LDRq_lit : A64I_LDRlitSimple<0b10, 0b1, FPR128>;
let PredicateMethod = "isWrappedReg";
let RenderMethod = "addRegOperands";
let ParserMethod = "ParseLSXAddressOperand";
+ // Diagnostics are provided by ParserMethod
}
def GPR64xsp0 : RegisterOperand<GPR64xsp> {
let Name = "OffsetUImm12_" # MemSize;
let PredicateMethod = "isOffsetUImm12<" # MemSize # ">";
let RenderMethod = "addOffsetUImm12Operands<" # MemSize # ">";
+ let DiagnosticType = "LoadStoreUImm12_" # MemSize;
}
// Pattern is really no more than an ImmLeaf, but predicated on MemSize which
let Name = "SImm9";
let PredicateMethod = "isSImm<9>";
let RenderMethod = "addSImmOperands<9>";
+ let DiagnosticType = "LoadStoreSImm9";
}
def simm9 : Operand<i64>,
let Name = "AddrRegExtend_" # MemSize # "_" # Rm;
let PredicateMethod = "isAddrRegExtend<" # MemSize # "," # RmSize # ">";
let RenderMethod = "addAddrRegExtendOperands<" # MemSize # ">";
+ let DiagnosticType = "LoadStoreExtend" # RmSize # "_" # MemSize;
}
def regext : Operand<i64> {
let Name = "SImm7_Scaled" # MemSize;
let PredicateMethod = "isSImm7Scaled<" # MemSize # ">";
let RenderMethod = "addSImm7ScaledOperands<" # MemSize # ">";
+ let DiagnosticType = "LoadStoreSImm7_" # MemSize;
}
def simm7 : Operand<i64> {
let Name = "LogicalImm" # note # size;
let PredicateMethod = "isLogicalImm" # note # "<" # size # ">";
let RenderMethod = "addLogicalImmOperands<" # size # ">";
+ let DiagnosticType = "LogicalSecondSource";
}
def _operand
let Name = instname # width # "Shifted" # shift;
let PredicateMethod = "is" # instname # width # "Imm";
let RenderMethod = "addMoveWideImmOperands";
-
let ParserMethod = "ParseImmWithLSLOperand";
+ let DiagnosticType = "MOVWUImm16";
}
def _imm : Operand<i32> {
}
let isMoveImm = 1, isReMaterializable = 1,
- isAsCheapAsAMove = 1, neverHasSideEffects = 1 in {
+ isAsCheapAsAMove = 1, hasSideEffects = 0 in {
defm MOVN : A64I_movwSizes<0b00, "movn",
(ins movn32_imm:$FullImm),
(ins movn64_imm:$FullImm)>;
def adrp_label_asmoperand : AsmOperandClass {
let Name = "AdrpLabel";
let RenderMethod = "addLabelOperands<21, 4096>";
+ let DiagnosticType = "Label";
}
def adrp_label : Operand<i64> {
let OperandType = "OPERAND_PCREL";
}
-let neverHasSideEffects = 1 in {
+let hasSideEffects = 0 in {
def ADRxi : A64I_PCADR<0b0, (outs GPR64:$Rd), (ins adr_label:$Label),
"adr\t$Rd, $Label", [], NoItinerary>;
let Name = "UImm3";
let PredicateMethod = "isUImm<3>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm3";
}
def uimm3 : Operand<i32> {
let Name = "UImm7";
let PredicateMethod = "isUImm<7>";
let RenderMethod = "addImmOperands";
+ let DiagnosticType = "UImm7";
}
def uimm7 : Operand<i32> {
def mrs_asmoperand : AsmOperandClass {
let Name = "MRS";
let ParserMethod = "ParseSysRegOperand";
+ let DiagnosticType = "MRS";
}
def mrs_op : Operand<i32> {
// AArch64Operand rather than an immediate. The overlap is small enough that
// it could be resolved with hackery now, but who can say in future?
let ParserMethod = "ParseSysRegOperand";
+ let DiagnosticType = "MSR";
}
def msr_op : Operand<i32> {
let Name = "MSRPState";
// See comment above about parser.
let ParserMethod = "ParseSysRegOperand";
+ let DiagnosticType = "MSR";
}
def pstate_op : Operand<i32> {
let PredicateMethod = "isUImm<4>";
let RenderMethod = "addImmOperands";
let ParserMethod = "ParseCRxOperand";
+ // Diagnostics are handled in all cases by ParseCRxOperand.
}
def CRx : Operand<i32> {
}
-//===----------------------------------------------------------------------===//
-// Constant island entries
-//===----------------------------------------------------------------------===//
-
-// The constant island pass needs to create "instructions" in the middle of the
-// instruction stream to reresent its constants.
-
-def cpinst_operand : Operand<i32>;
-
-def CONSTPOOL_ENTRY : PseudoInst<(outs), (ins cpinst_operand:$instid,
- cpinst_operand:$cpidx,
- i32imm:$size), []> {
- let neverHasSideEffects = 1;
- let isNotDuplicable = 1;
-}
-
//===----------------------------------------------------------------------===//
// Miscellaneous patterns
//===----------------------------------------------------------------------===//
ALIGN),
(ADRPxi texternalsym:$Hi), (i64 texternalsym:$Lo12)>;
+defm : uimm12_pats<(A64WrapperSmall tconstpool:$Hi, tconstpool:$Lo12, ALIGN),
+ (ADRPxi tconstpool:$Hi), (i64 tconstpool:$Lo12)>;
// We also want to use uimm12 instructions for local variables at the moment.
def tframeindex_XFORM : SDNodeXForm<frameindex, [{