aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/AArch64InstrFormats.td
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/AArch64InstrFormats.td')
-rw-r--r--lib/Target/AArch64/AArch64InstrFormats.td633
1 files changed, 573 insertions, 60 deletions
diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td
index c44daf306ea9..80c5092a4eed 100644
--- a/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/lib/Target/AArch64/AArch64InstrFormats.td
@@ -189,6 +189,11 @@ def GPR32as64 : RegisterOperand<GPR32> {
// are encoded as the eight bit value 'abcdefgh'.
def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
+// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
+def SImm10s8Operand : AsmOperandClass {
+ let Name = "SImm10s8";
+ let DiagnosticType = "InvalidMemoryIndexedSImm10";
+}
//===----------------------------------------------------------------------===//
// Operand Definitions.
@@ -216,6 +221,12 @@ def adrlabel : Operand<i64> {
let ParserMatchClass = AdrOperand;
}
+def simm10Scaled : Operand<i64> {
+ let ParserMatchClass = SImm10s8Operand;
+ let DecoderMethod = "DecodeSImm<10>";
+ let PrintMethod = "printImmScale<8>";
+}
+
// simm9 predicate - True if the immediate is in the range [-256, 255].
def SImm9Operand : AsmOperandClass {
let Name = "SImm9";
@@ -489,14 +500,14 @@ let DiagnosticType = "LogicalSecondSource" in {
let Name = "LogicalImm64Not";
}
}
-def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
- return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
+def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
+ return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
}], logical_imm32_XFORM> {
let PrintMethod = "printLogicalImm32";
let ParserMatchClass = LogicalImm32Operand;
}
-def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
- return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
+def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
+ return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
}], logical_imm64_XFORM> {
let PrintMethod = "printLogicalImm64";
let ParserMatchClass = LogicalImm64Operand;
@@ -743,8 +754,8 @@ class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
// Floating-point immediate.
def fpimm16 : Operand<f16>,
- PatLeaf<(f16 fpimm), [{
- return AArch64_AM::getFP16Imm(N->getValueAPF()) != -1;
+ FPImmLeaf<f16, [{
+ return AArch64_AM::getFP16Imm(Imm) != -1;
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = AArch64_AM::getFP16Imm(InVal);
@@ -754,8 +765,8 @@ def fpimm16 : Operand<f16>,
let PrintMethod = "printFPImmOperand";
}
def fpimm32 : Operand<f32>,
- PatLeaf<(f32 fpimm), [{
- return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
+ FPImmLeaf<f32, [{
+ return AArch64_AM::getFP32Imm(Imm) != -1;
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = AArch64_AM::getFP32Imm(InVal);
@@ -765,8 +776,8 @@ def fpimm32 : Operand<f32>,
let PrintMethod = "printFPImmOperand";
}
def fpimm64 : Operand<f64>,
- PatLeaf<(f64 fpimm), [{
- return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
+ FPImmLeaf<f64, [{
+ return AArch64_AM::getFP64Imm(Imm) != -1;
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = AArch64_AM::getFP64Imm(InVal);
@@ -781,8 +792,8 @@ def fpimm8 : Operand<i32> {
let PrintMethod = "printFPImmOperand";
}
-def fpimm0 : PatLeaf<(fpimm), [{
- return N->isExactlyValue(+0.0);
+def fpimm0 : FPImmLeaf<fAny, [{
+ return Imm.isExactlyValue(+0.0);
}]>;
// Vector lane operands
@@ -836,10 +847,9 @@ def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
// are encoded as the eight bit value 'abcdefgh'.
def simdimmtype10 : Operand<i32>,
- PatLeaf<(f64 fpimm), [{
- return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
- .bitcastToAPInt()
- .getZExtValue());
+ FPImmLeaf<f64, [{
+ return AArch64_AM::isAdvSIMDModImmType10(
+ Imm.bitcastToAPInt().getZExtValue());
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
@@ -913,6 +923,17 @@ class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
let Inst{7-5} = opc;
}
+class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
+ : SimpleSystemI<0, (ins), asm, "", pattern>,
+ Sched<[]> {
+ bits<4> CRm;
+ let CRm = 0b0011;
+ let Inst{31-12} = 0b11010101000000110010;
+ let Inst{11-8} = CRm;
+ let Inst{7-5} = op2;
+ let Inst{4-0} = 0b11111;
+}
+
// MRS/MSR system instructions. These have different operand classes because
// a different subset of registers can be accessed through each instruction.
def MRSSystemRegisterOperand : AsmOperandClass {
@@ -1098,6 +1119,83 @@ class SpecialReturn<bits<4> opc, string asm>
let Inst{9-5} = 0b11111;
}
+let mayLoad = 1 in
+class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
+ : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
+ Sched<[]> {
+ bits<5> Rn;
+ bits<5> Rt;
+ let Inst{31-30} = sz;
+ let Inst{29-10} = 0b11100010111111110000;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rt;
+}
+
+class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
+ list<dag> pattern>
+ : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
+ let Inst{31-25} = 0b1101011;
+ let Inst{20-11} = 0b1111100001;
+ let Inst{10} = M;
+ let Inst{4-0} = 0b11111;
+}
+
+class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
+ : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
+ bits<5> Rn;
+ bits<5> Rm;
+ let Inst{24-22} = 0b100;
+ let Inst{21} = op;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rm;
+}
+
+class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
+ : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
+ bits<5> Rn;
+ let Inst{24} = 0;
+ let Inst{23-21} = opc;
+ let Inst{9-5} = Rn;
+}
+
+class AuthReturn<bits<3> op, bits<1> M, string asm>
+ : AuthBase<M, (outs), (ins), asm, "", []> {
+ let Inst{24} = 0;
+ let Inst{23-21} = op;
+ let Inst{9-0} = 0b1111111111;
+}
+
+let mayLoad = 1 in
+class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
+ string operands, string cstr, Operand opr>
+ : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
+ bits<10> offset;
+ bits<5> Rn;
+ bits<5> Rt;
+ let Inst{31-24} = 0b11111000;
+ let Inst{23} = M;
+ let Inst{22} = offset{9};
+ let Inst{21} = 1;
+ let Inst{20-12} = offset{8-0};
+ let Inst{11} = W;
+ let Inst{10} = 1;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rt;
+}
+
+multiclass AuthLoad<bit M, string asm, Operand opr> {
+ def indexed : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
+ (ins GPR64sp:$Rn, opr:$offset),
+ asm, "\t$Rt, [$Rn, $offset]", "", opr>;
+ def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
+ (ins GPR64sp:$Rn, opr:$offset),
+ asm, "\t$Rt, [$Rn, $offset]!",
+ "$Rn = $wback,@earlyclobber $wback", opr>;
+
+ def : InstAlias<asm # "\t$Rt, [$Rn]",
+ (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
+}
+
//---
// Conditional branch instruction.
//---
@@ -1320,6 +1418,46 @@ class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
let Inst{31} = 1;
}
+class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
+ : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
+ []>,
+ Sched<[WriteI, ReadI]> {
+ bits<5> Rd;
+ bits<5> Rn;
+ let Inst{31-15} = 0b11011010110000010;
+ let Inst{14-12} = opcode_prefix;
+ let Inst{11-10} = opcode;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rd;
+}
+
+class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
+ : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
+ bits<5> Rd;
+ let Inst{31-15} = 0b11011010110000010;
+ let Inst{14-12} = opcode_prefix;
+ let Inst{11-10} = opcode;
+ let Inst{9-5} = 0b11111;
+ let Inst{4-0} = Rd;
+}
+
+class SignAuthTwoOperand<bits<4> opc, string asm,
+ SDPatternOperator OpNode>
+ : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
+ asm, "\t$Rd, $Rn, $Rm", "",
+ [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
+ Sched<[WriteI, ReadI, ReadI]> {
+ bits<5> Rd;
+ bits<5> Rn;
+ bits<5> Rm;
+ let Inst{31-21} = 0b10011010110;
+ let Inst{20-16} = Rm;
+ let Inst{15-14} = 0b00;
+ let Inst{13-10} = opc;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rd;
+}
+
//---
// Basic two-operand data processing instructions.
//---
@@ -2378,6 +2516,22 @@ def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
+def gi_am_indexed8 :
+ GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
+ GIComplexPatternEquiv<am_indexed8>;
+def gi_am_indexed16 :
+ GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
+ GIComplexPatternEquiv<am_indexed16>;
+def gi_am_indexed32 :
+ GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
+ GIComplexPatternEquiv<am_indexed32>;
+def gi_am_indexed64 :
+ GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
+ GIComplexPatternEquiv<am_indexed64>;
+def gi_am_indexed128 :
+ GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
+ GIComplexPatternEquiv<am_indexed128>;
+
class UImm12OffsetOperand<int Scale> : AsmOperandClass {
let Name = "UImm12Offset" # Scale;
let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
@@ -2449,6 +2603,23 @@ multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
(!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
}
+// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
+// substitute zero-registers automatically.
+//
+// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
+// into StoreUI.
+multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
+ Operand indextype, string asm, list<dag> pattern> {
+ let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
+ def ui : BaseLoadStoreUI<sz, V, opc, (outs),
+ (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
+ asm, pattern>,
+ Sched<[WriteST]>;
+
+ def : InstAlias<asm # "\t$Rt, [$Rn]",
+ (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
+}
+
def PrefetchOperand : AsmOperandClass {
let Name = "Prefetch";
let ParserMethod = "tryParsePrefetch";
@@ -2933,22 +3104,18 @@ multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
string asm, ValueType Ty, SDPatternOperator storeop> {
- let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
+ let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
(ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
- [(storeop (Ty regtype:$Rt),
- (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
- ro_Wextend128:$extend))]>,
+ []>,
Sched<[WriteSTIdx, ReadAdrBase]> {
let Inst{13} = 0b0;
}
- let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
+ let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
(ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
- [(storeop (Ty regtype:$Rt),
- (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
- ro_Xextend128:$extend))]>,
+ []>,
Sched<[WriteSTIdx, ReadAdrBase]> {
let Inst{13} = 0b1;
}
@@ -3012,6 +3179,23 @@ def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
+def gi_am_unscaled8 :
+ GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
+ GIComplexPatternEquiv<am_unscaled8>;
+def gi_am_unscaled16 :
+ GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
+ GIComplexPatternEquiv<am_unscaled16>;
+def gi_am_unscaled32 :
+ GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
+ GIComplexPatternEquiv<am_unscaled32>;
+def gi_am_unscaled64 :
+ GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
+ GIComplexPatternEquiv<am_unscaled64>;
+def gi_am_unscaled128 :
+ GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
+ GIComplexPatternEquiv<am_unscaled128>;
+
+
class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
string asm, list<dag> pattern>
: I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
@@ -4374,6 +4558,12 @@ class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
let Inst{4-0} = Rd;
}
+class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
+ string kind2> :
+ BaseSIMDThreeSameVector<Q, U, 0b100, 0b10010, V128, asm, kind1, [] > {
+ let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
+}
+
// All operand sizes distinguished in the encoding.
multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
SDPatternOperator OpNode> {
@@ -6801,6 +6991,16 @@ class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
let Inst{4-0} = Rd;
}
+// ARMv8.2 Index Dot product instructions
+class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
+ string lhs_kind, string rhs_kind> :
+ BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, V128, V128, V128, VectorIndexS,
+ asm, "", dst_kind, lhs_kind, rhs_kind, []> {
+ bits<2> idx;
+ let Inst{21} = idx{0}; // L
+ let Inst{11} = idx{1}; // H
+}
+
multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
SDPatternOperator OpNode> {
let Predicates = [HasNEON, HasFullFP16] in {
@@ -9241,6 +9441,238 @@ multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
} // let Predicates = [HasNeon, HasRDM]
//----------------------------------------------------------------------------
+// ARMv8.3 Complex ADD/MLA instructions
+//----------------------------------------------------------------------------
+
+class ComplexRotationOperand<int Angle, int Remainder, string Type>
+ : AsmOperandClass {
+ let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
+ let DiagnosticType = "InvalidComplexRotation" # Type;
+ let Name = "ComplexRotation" # Type;
+}
+def complexrotateop : Operand<i32> {
+ let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
+ let PrintMethod = "printComplexRotationOp<90, 0>";
+}
+def complexrotateopodd : Operand<i32> {
+ let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
+ let PrintMethod = "printComplexRotationOp<180, 90>";
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
+class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
+ RegisterOperand regtype, Operand rottype,
+ string asm, string kind, list<dag> pattern>
+ : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
+ "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
+ "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
+ Sched<[WriteV]> {
+ bits<5> Rd;
+ bits<5> Rn;
+ bits<5> Rm;
+ bits<1> rot;
+ let Inst{31} = 0;
+ let Inst{30} = Q;
+ let Inst{29} = U;
+ let Inst{28-24} = 0b01110;
+ let Inst{23-22} = size;
+ let Inst{21} = 0;
+ let Inst{20-16} = Rm;
+ let Inst{15-13} = opcode;
+ // Non-tied version (FCADD) only has one rotation bit
+ let Inst{12} = rot;
+ let Inst{11} = 0;
+ let Inst{10} = 1;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rd;
+}
+
+multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
+ string asm, SDPatternOperator OpNode>{
+ let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
+ def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
+ asm, ".4h",
+ [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
+ (v4f16 V64:$Rn),
+ (v4f16 V64:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
+ asm, ".8h",
+ [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
+ (v8f16 V128:$Rn),
+ (v8f16 V128:$Rm),
+ (rottype i32:$rot)))]>;
+ }
+
+ let Predicates = [HasV8_3a, HasNEON] in {
+ def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
+ asm, ".2s",
+ [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
+ (v2f32 V64:$Rn),
+ (v2f32 V64:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
+ asm, ".4s",
+ [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
+ (v4f32 V128:$Rn),
+ (v4f32 V128:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
+ asm, ".2d",
+ [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
+ (v2f64 V128:$Rn),
+ (v2f64 V128:$Rm),
+ (rottype i32:$rot)))]>;
+ }
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
+class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
+ bits<3> opcode,
+ RegisterOperand regtype,
+ Operand rottype, string asm,
+ string kind, list<dag> pattern>
+ : I<(outs regtype:$dst),
+ (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
+ "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
+ "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
+ Sched<[WriteV]> {
+ bits<5> Rd;
+ bits<5> Rn;
+ bits<5> Rm;
+ bits<2> rot;
+ let Inst{31} = 0;
+ let Inst{30} = Q;
+ let Inst{29} = U;
+ let Inst{28-24} = 0b01110;
+ let Inst{23-22} = size;
+ let Inst{21} = 0;
+ let Inst{20-16} = Rm;
+ let Inst{15-13} = opcode;
+ let Inst{12-11} = rot;
+ let Inst{10} = 1;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rd;
+}
+
+multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
+ Operand rottype, string asm,
+ SDPatternOperator OpNode> {
+ let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
+ def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
+ rottype, asm, ".4h",
+ [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
+ (v4f16 V64:$Rn),
+ (v4f16 V64:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
+ rottype, asm, ".8h",
+ [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
+ (v8f16 V128:$Rn),
+ (v8f16 V128:$Rm),
+ (rottype i32:$rot)))]>;
+ }
+
+ let Predicates = [HasV8_3a, HasNEON] in {
+ def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
+ rottype, asm, ".2s",
+ [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
+ (v2f32 V64:$Rn),
+ (v2f32 V64:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
+ rottype, asm, ".4s",
+ [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
+ (v4f32 V128:$Rn),
+ (v4f32 V128:$Rm),
+ (rottype i32:$rot)))]>;
+
+ def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
+ rottype, asm, ".2d",
+ [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
+ (v2f64 V128:$Rn),
+ (v2f64 V128:$Rm),
+ (rottype i32:$rot)))]>;
+ }
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
+class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
+ bit opc1, bit opc2, RegisterOperand dst_reg,
+ RegisterOperand lhs_reg,
+ RegisterOperand rhs_reg, Operand vec_idx,
+ Operand rottype, string asm, string apple_kind,
+ string dst_kind, string lhs_kind,
+ string rhs_kind, list<dag> pattern>
+ : I<(outs dst_reg:$dst),
+ (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
+ asm,
+ "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
+ "$idx, $rot" # "|" # apple_kind #
+ "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
+ Sched<[WriteV]> {
+ bits<5> Rd;
+ bits<5> Rn;
+ bits<5> Rm;
+ bits<2> rot;
+
+ let Inst{31} = 0;
+ let Inst{30} = Q;
+ let Inst{29} = U;
+ let Inst{28} = Scalar;
+ let Inst{27-24} = 0b1111;
+ let Inst{23-22} = size;
+ // Bit 21 must be set by the derived class.
+ let Inst{20-16} = Rm;
+ let Inst{15} = opc1;
+ let Inst{14-13} = rot;
+ let Inst{12} = opc2;
+ // Bit 11 must be set by the derived class.
+ let Inst{10} = 0;
+ let Inst{9-5} = Rn;
+ let Inst{4-0} = Rd;
+}
+
+// The complex instructions index by pairs of elements, so the VectorIndexes
+// don't match the lane types, and the index bits are different to the other
+// classes.
+multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
+ string asm, SDPatternOperator OpNode> {
+ let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in {
+ def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
+ V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
+ ".4h", ".h", []> {
+ bits<1> idx;
+ let Inst{11} = 0;
+ let Inst{21} = idx{0};
+ }
+
+ def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
+ V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
+ ".8h", ".8h", ".h", []> {
+ bits<2> idx;
+ let Inst{11} = idx{1};
+ let Inst{21} = idx{0};
+ }
+ } // Predicates = [HasV8_3a,HasNEON,HasFullFP16]
+
+ let Predicates = [HasV8_3a,HasNEON] in {
+ def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
+ V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
+ ".4s", ".4s", ".s", []> {
+ bits<1> idx;
+ let Inst{11} = idx{0};
+ let Inst{21} = 0;
+ }
+ } // Predicates = [HasV8_3a,HasNEON]
+}
+
+//----------------------------------------------------------------------------
// Crypto extensions
//----------------------------------------------------------------------------
@@ -9398,10 +9830,10 @@ class BaseCAS<string order, string size, RegisterClass RC>
}
multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
- let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
- let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
- let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
- let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
+ let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
+ let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
+ let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
+ let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
}
class BaseCASP<string order, string size, RegisterOperand RC>
@@ -9413,10 +9845,10 @@ class BaseCASP<string order, string size, RegisterOperand RC>
}
multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
- let Sz = 0b00, Acq = Acq, Rel = Rel in
- def s : BaseCASP<order, "", WSeqPairClassOperand>;
- let Sz = 0b01, Acq = Acq, Rel = Rel in
- def d : BaseCASP<order, "", XSeqPairClassOperand>;
+ let Sz = 0b00, Acq = Acq, Rel = Rel in
+ def W : BaseCASP<order, "", WSeqPairClassOperand>;
+ let Sz = 0b01, Acq = Acq, Rel = Rel in
+ def X : BaseCASP<order, "", XSeqPairClassOperand>;
}
let Predicates = [HasLSE] in
@@ -9446,10 +9878,10 @@ class BaseSWP<string order, string size, RegisterClass RC>
}
multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
- let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
- let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
- let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
- let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
+ let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
+ let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
+ let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
+ let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
}
let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
@@ -9480,14 +9912,94 @@ class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
string order> {
- let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
- def b : BaseLDOPregister<op, order, "b", GPR32>;
- let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
- def h : BaseLDOPregister<op, order, "h", GPR32>;
- let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
- def s : BaseLDOPregister<op, order, "", GPR32>;
- let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
- def d : BaseLDOPregister<op, order, "", GPR64>;
+ let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
+ def B : BaseLDOPregister<op, order, "b", GPR32>;
+ let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
+ def H : BaseLDOPregister<op, order, "h", GPR32>;
+ let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
+ def W : BaseLDOPregister<op, order, "", GPR32>;
+ let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
+ def X : BaseLDOPregister<op, order, "", GPR64>;
+}
+
+// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
+// complex DAG for DstRHS.
+let Predicates = [HasLSE] in
+multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
+ string size, dag SrcRHS, dag DstRHS> {
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
+ (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
+ (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
+ (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
+ (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
+ (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
+}
+
+multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
+ string size, dag RHS> {
+ defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
+}
+
+multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
+ string size, dag LHS, dag RHS> {
+ defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
+}
+
+multiclass LDOPregister_patterns<string inst, string op> {
+ defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
+ defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
+ defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
+ defm : LDOPregister_patterns_ord<inst, "B", op, "8", (i32 GPR32:$Rm)>;
+}
+
+multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
+ defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
+ (i64 GPR64:$Rm),
+ (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
+ defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
+ (i32 GPR32:$Rm),
+ (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
+ defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
+ (i32 GPR32:$Rm),
+ (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
+ defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
+ (i32 GPR32:$Rm),
+ (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
+}
+
+let Predicates = [HasLSE] in
+multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
+ string size, dag OLD, dag NEW> {
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
+ (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
+ (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
+ (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
+ (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
+ def : Pat<(!cast<SDNode>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
+ (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
+}
+
+multiclass CASregister_patterns_ord<string inst, string suffix, string op,
+ string size, dag OLD, dag NEW> {
+ defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
+}
+
+multiclass CASregister_patterns<string inst, string op> {
+ defm : CASregister_patterns_ord<inst, "X", op, "64",
+ (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
+ defm : CASregister_patterns_ord<inst, "W", op, "32",
+ (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
+ defm : CASregister_patterns_ord<inst, "H", op, "16",
+ (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
+ defm : CASregister_patterns_ord<inst, "B", op, "8",
+ (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
}
let Predicates = [HasLSE] in
@@ -9496,26 +10008,27 @@ class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
multiclass STOPregister<string asm, string instr> {
- def : BaseSTOPregister<asm # "lb", GPR32, WZR,
- !cast<Instruction>(instr # "Lb")>;
- def : BaseSTOPregister<asm # "lh", GPR32, WZR,
- !cast<Instruction>(instr # "Lh")>;
- def : BaseSTOPregister<asm # "l", GPR32, WZR,
- !cast<Instruction>(instr # "Ls")>;
- def : BaseSTOPregister<asm # "l", GPR64, XZR,
- !cast<Instruction>(instr # "Ld")>;
- def : BaseSTOPregister<asm # "b", GPR32, WZR,
- !cast<Instruction>(instr # "b")>;
- def : BaseSTOPregister<asm # "h", GPR32, WZR,
- !cast<Instruction>(instr # "h")>;
- def : BaseSTOPregister<asm, GPR32, WZR,
- !cast<Instruction>(instr # "s")>;
- def : BaseSTOPregister<asm, GPR64, XZR,
- !cast<Instruction>(instr # "d")>;
+ def : BaseSTOPregister<asm # "lb", GPR32, WZR,
+ !cast<Instruction>(instr # "LB")>;
+ def : BaseSTOPregister<asm # "lh", GPR32, WZR,
+ !cast<Instruction>(instr # "LH")>;
+ def : BaseSTOPregister<asm # "l", GPR32, WZR,
+ !cast<Instruction>(instr # "LW")>;
+ def : BaseSTOPregister<asm # "l", GPR64, XZR,
+ !cast<Instruction>(instr # "LX")>;
+ def : BaseSTOPregister<asm # "b", GPR32, WZR,
+ !cast<Instruction>(instr # "B")>;
+ def : BaseSTOPregister<asm # "h", GPR32, WZR,
+ !cast<Instruction>(instr # "H")>;
+ def : BaseSTOPregister<asm, GPR32, WZR,
+ !cast<Instruction>(instr # "W")>;
+ def : BaseSTOPregister<asm, GPR64, XZR,
+ !cast<Instruction>(instr # "X")>;
}
//----------------------------------------------------------------------------
// Allow the size specifier tokens to be upper case, not just lower.
+def : TokenAlias<".4B", ".4b">; // Add dot product
def : TokenAlias<".8B", ".8b">;
def : TokenAlias<".4H", ".4h">;
def : TokenAlias<".2S", ".2s">;