1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
10 // Describe AArch64 instructions format here
13 // Format specifies the encoding used by the instruction. This is part of the
14 // ad-hoc solution used to emit machine instruction encodings by our machine
16 class Format<bits<2> val> {
20 def PseudoFrm : Format<0>;
21 def NormalFrm : Format<1>; // Do we need any others?
23 // AArch64 Instruction Format
24 class AArch64Inst<Format f, string cstr> : Instruction {
25 field bits<32> Inst; // Instruction encoding.
26 // Mask of bits that cause an encoding to be UNPREDICTABLE.
27 // If a bit is set, then if the corresponding bit in the
28 // target encoding differs from its value in the "Inst" field,
29 // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
30 field bits<32> Unpredictable = 0;
31 // SoftFail is the generic name for this field, but we alias it so
32 // as to make it more obvious what it means in ARM-land.
33 field bits<32> SoftFail = Unpredictable;
34 let Namespace = "AArch64";
36 bits<2> Form = F.Value;
38 let Constraints = cstr;
41 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
42 : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
44 // Pseudo instructions (don't have encoding information)
45 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
46 : AArch64Inst<PseudoFrm, cstr> {
47 dag OutOperandList = oops;
48 dag InOperandList = iops;
49 let Pattern = pattern;
50 let isCodeGenOnly = 1;
53 // Real instructions (have encoding information)
54 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
55 let Pattern = pattern;
59 // Enum describing whether an instruction is
60 // destructive in its first source operand.
61 class DestructiveInstTypeEnum<bits<1> val> {
64 def NotDestructive : DestructiveInstTypeEnum<0>;
65 def Destructive : DestructiveInstTypeEnum<1>;
67 // Normal instructions
68 class I<dag oops, dag iops, string asm, string operands, string cstr,
70 : EncodedI<cstr, pattern> {
71 dag OutOperandList = oops;
72 dag InOperandList = iops;
73 let AsmString = !strconcat(asm, operands);
75 // Destructive operations (SVE)
76 DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
77 ElementSizeEnum ElementSize = ElementSizeB;
79 let TSFlags{3} = DestructiveInstType.Value;
80 let TSFlags{2-0} = ElementSize.Value;
83 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
84 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
85 class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
87 // Helper fragment for an extract of the high portion of a 128-bit vector.
88 def extract_high_v16i8 :
89 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
90 def extract_high_v8i16 :
91 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
92 def extract_high_v4i32 :
93 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
94 def extract_high_v2i64 :
95 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
97 //===----------------------------------------------------------------------===//
98 // Asm Operand Classes.
101 // Shifter operand for arithmetic shifted encodings.
102 def ShifterOperand : AsmOperandClass {
103 let Name = "Shifter";
106 // Shifter operand for mov immediate encodings.
107 def MovImm32ShifterOperand : AsmOperandClass {
108 let SuperClasses = [ShifterOperand];
109 let Name = "MovImm32Shifter";
110 let RenderMethod = "addShifterOperands";
111 let DiagnosticType = "InvalidMovImm32Shift";
113 def MovImm64ShifterOperand : AsmOperandClass {
114 let SuperClasses = [ShifterOperand];
115 let Name = "MovImm64Shifter";
116 let RenderMethod = "addShifterOperands";
117 let DiagnosticType = "InvalidMovImm64Shift";
120 // Shifter operand for arithmetic register shifted encodings.
121 class ArithmeticShifterOperand<int width> : AsmOperandClass {
122 let SuperClasses = [ShifterOperand];
123 let Name = "ArithmeticShifter" # width;
124 let PredicateMethod = "isArithmeticShifter<" # width # ">";
125 let RenderMethod = "addShifterOperands";
126 let DiagnosticType = "AddSubRegShift" # width;
129 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
130 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
132 // Shifter operand for logical register shifted encodings.
133 class LogicalShifterOperand<int width> : AsmOperandClass {
134 let SuperClasses = [ShifterOperand];
135 let Name = "LogicalShifter" # width;
136 let PredicateMethod = "isLogicalShifter<" # width # ">";
137 let RenderMethod = "addShifterOperands";
138 let DiagnosticType = "AddSubRegShift" # width;
141 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
142 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
144 // Shifter operand for logical vector 128/64-bit shifted encodings.
145 def LogicalVecShifterOperand : AsmOperandClass {
146 let SuperClasses = [ShifterOperand];
147 let Name = "LogicalVecShifter";
148 let RenderMethod = "addShifterOperands";
150 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
151 let SuperClasses = [LogicalVecShifterOperand];
152 let Name = "LogicalVecHalfWordShifter";
153 let RenderMethod = "addShifterOperands";
156 // The "MSL" shifter on the vector MOVI instruction.
157 def MoveVecShifterOperand : AsmOperandClass {
158 let SuperClasses = [ShifterOperand];
159 let Name = "MoveVecShifter";
160 let RenderMethod = "addShifterOperands";
163 // Extend operand for arithmetic encodings.
164 def ExtendOperand : AsmOperandClass {
166 let DiagnosticType = "AddSubRegExtendLarge";
168 def ExtendOperand64 : AsmOperandClass {
169 let SuperClasses = [ExtendOperand];
170 let Name = "Extend64";
171 let DiagnosticType = "AddSubRegExtendSmall";
173 // 'extend' that's a lsl of a 64-bit register.
174 def ExtendOperandLSL64 : AsmOperandClass {
175 let SuperClasses = [ExtendOperand];
176 let Name = "ExtendLSL64";
177 let RenderMethod = "addExtend64Operands";
178 let DiagnosticType = "AddSubRegExtendLarge";
181 // 8-bit floating-point immediate encodings.
182 def FPImmOperand : AsmOperandClass {
184 let ParserMethod = "tryParseFPImm<true>";
185 let DiagnosticType = "InvalidFPImm";
188 def CondCode : AsmOperandClass {
189 let Name = "CondCode";
190 let DiagnosticType = "InvalidCondCode";
193 // A 32-bit register pasrsed as 64-bit
194 def GPR32as64Operand : AsmOperandClass {
195 let Name = "GPR32as64";
197 "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
199 def GPR32as64 : RegisterOperand<GPR32> {
200 let ParserMatchClass = GPR32as64Operand;
203 // A 64-bit register pasrsed as 32-bit
204 def GPR64as32Operand : AsmOperandClass {
205 let Name = "GPR64as32";
207 "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
209 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
210 let ParserMatchClass = GPR64as32Operand;
213 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
214 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
215 // are encoded as the eight bit value 'abcdefgh'.
216 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
218 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
219 let Name = "UImm" # Width # "s" # Scale;
220 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
221 let RenderMethod = "addImmScaledOperands<" # Scale # ">";
222 let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
225 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
226 let Name = "SImm" # Width # "s" # Scale;
227 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
228 let RenderMethod = "addImmScaledOperands<" # Scale # ">";
229 let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
232 //===----------------------------------------------------------------------===//
233 // Operand Definitions.
236 // ADR[P] instruction labels.
237 def AdrpOperand : AsmOperandClass {
238 let Name = "AdrpLabel";
239 let ParserMethod = "tryParseAdrpLabel";
240 let DiagnosticType = "InvalidLabel";
242 def adrplabel : Operand<i64> {
243 let EncoderMethod = "getAdrLabelOpValue";
244 let PrintMethod = "printAdrpLabel";
245 let ParserMatchClass = AdrpOperand;
248 def AdrOperand : AsmOperandClass {
249 let Name = "AdrLabel";
250 let ParserMethod = "tryParseAdrLabel";
251 let DiagnosticType = "InvalidLabel";
253 def adrlabel : Operand<i64> {
254 let EncoderMethod = "getAdrLabelOpValue";
255 let ParserMatchClass = AdrOperand;
258 class SImmOperand<int width> : AsmOperandClass {
259 let Name = "SImm" # width;
260 let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
261 let RenderMethod = "addImmOperands";
262 let PredicateMethod = "isSImm<" # width # ">";
266 class AsmImmRange<int Low, int High> : AsmOperandClass {
267 let Name = "Imm" # Low # "_" # High;
268 let DiagnosticType = "InvalidImm" # Low # "_" # High;
269 let RenderMethod = "addImmOperands";
270 let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
273 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
274 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
275 def simm10Scaled : Operand<i64> {
276 let ParserMatchClass = SImm10s8Operand;
277 let DecoderMethod = "DecodeSImm<10>";
278 let PrintMethod = "printImmScale<8>";
281 def simm9s16 : Operand<i64> {
282 let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
283 let DecoderMethod = "DecodeSImm<9>";
284 let PrintMethod = "printImmScale<16>";
287 // uimm6 predicate - True if the immediate is in the range [0, 63].
288 def UImm6Operand : AsmOperandClass {
290 let DiagnosticType = "InvalidImm0_63";
293 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
294 let ParserMatchClass = UImm6Operand;
297 def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
298 let ParserMatchClass = AsmImmRange<0, 65535>;
301 def SImm9Operand : SImmOperand<9>;
302 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
303 let ParserMatchClass = SImm9Operand;
304 let DecoderMethod = "DecodeSImm<9>";
307 def SImm8Operand : SImmOperand<8>;
308 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
309 let ParserMatchClass = SImm8Operand;
310 let DecoderMethod = "DecodeSImm<8>";
313 def SImm6Operand : SImmOperand<6>;
314 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
315 let ParserMatchClass = SImm6Operand;
316 let DecoderMethod = "DecodeSImm<6>";
319 def SImm5Operand : SImmOperand<5>;
320 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
321 let ParserMatchClass = SImm5Operand;
322 let DecoderMethod = "DecodeSImm<5>";
325 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
326 let ParserMatchClass = SImm5Operand;
327 let DecoderMethod = "DecodeSImm<5>";
330 // simm7sN predicate - True if the immediate is a multiple of N in the range
331 // [-64 * N, 63 * N].
333 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
334 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
335 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
337 def simm7s4 : Operand<i32> {
338 let ParserMatchClass = SImm7s4Operand;
339 let PrintMethod = "printImmScale<4>";
342 def simm7s8 : Operand<i32> {
343 let ParserMatchClass = SImm7s8Operand;
344 let PrintMethod = "printImmScale<8>";
347 def simm7s16 : Operand<i32> {
348 let ParserMatchClass = SImm7s16Operand;
349 let PrintMethod = "printImmScale<16>";
352 def am_indexed7s8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
353 def am_indexed7s16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
354 def am_indexed7s32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
355 def am_indexed7s64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
356 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
358 def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
359 def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
361 // uimm5sN predicate - True if the immediate is a multiple of N in the range
363 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
364 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
365 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
367 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
368 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
369 let ParserMatchClass = UImm5s2Operand;
370 let PrintMethod = "printImmScale<2>";
372 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
373 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
374 let ParserMatchClass = UImm5s4Operand;
375 let PrintMethod = "printImmScale<4>";
377 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
378 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
379 let ParserMatchClass = UImm5s8Operand;
380 let PrintMethod = "printImmScale<8>";
383 // uimm6sN predicate - True if the immediate is a multiple of N in the range
385 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
386 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
387 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
388 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
389 def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
391 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
392 let ParserMatchClass = UImm6s1Operand;
394 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
395 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
396 let PrintMethod = "printImmScale<2>";
397 let ParserMatchClass = UImm6s2Operand;
399 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
400 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
401 let PrintMethod = "printImmScale<4>";
402 let ParserMatchClass = UImm6s4Operand;
404 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
405 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
406 let PrintMethod = "printImmScale<8>";
407 let ParserMatchClass = UImm6s8Operand;
409 def uimm6s16 : Operand<i64>, ImmLeaf<i64,
410 [{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
411 let PrintMethod = "printImmScale<16>";
412 let ParserMatchClass = UImm6s16Operand;
415 // simm6sN predicate - True if the immediate is a multiple of N in the range
416 // [-32 * N, 31 * N].
417 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
418 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
419 let ParserMatchClass = SImm6s1Operand;
420 let DecoderMethod = "DecodeSImm<6>";
423 // simm4sN predicate - True if the immediate is a multiple of N in the range
425 def SImm4s1Operand : SImmScaledMemoryIndexed<4, 1>;
426 def SImm4s2Operand : SImmScaledMemoryIndexed<4, 2>;
427 def SImm4s3Operand : SImmScaledMemoryIndexed<4, 3>;
428 def SImm4s4Operand : SImmScaledMemoryIndexed<4, 4>;
429 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
431 def simm4s1 : Operand<i64>, ImmLeaf<i64,
432 [{ return Imm >=-8 && Imm <= 7; }]> {
433 let ParserMatchClass = SImm4s1Operand;
434 let DecoderMethod = "DecodeSImm<4>";
437 def simm4s2 : Operand<i64>, ImmLeaf<i64,
438 [{ return Imm >=-16 && Imm <= 14 && (Imm % 2) == 0x0; }]> {
439 let PrintMethod = "printImmScale<2>";
440 let ParserMatchClass = SImm4s2Operand;
441 let DecoderMethod = "DecodeSImm<4>";
444 def simm4s3 : Operand<i64>, ImmLeaf<i64,
445 [{ return Imm >=-24 && Imm <= 21 && (Imm % 3) == 0x0; }]> {
446 let PrintMethod = "printImmScale<3>";
447 let ParserMatchClass = SImm4s3Operand;
448 let DecoderMethod = "DecodeSImm<4>";
451 def simm4s4 : Operand<i64>, ImmLeaf<i64,
452 [{ return Imm >=-32 && Imm <= 28 && (Imm % 4) == 0x0; }]> {
453 let PrintMethod = "printImmScale<4>";
454 let ParserMatchClass = SImm4s4Operand;
455 let DecoderMethod = "DecodeSImm<4>";
457 def simm4s16 : Operand<i64>, ImmLeaf<i64,
458 [{ return Imm >=-128 && Imm <= 112 && (Imm % 16) == 0x0; }]> {
459 let PrintMethod = "printImmScale<16>";
460 let ParserMatchClass = SImm4s16Operand;
461 let DecoderMethod = "DecodeSImm<4>";
464 def Imm1_8Operand : AsmImmRange<1, 8>;
465 def Imm1_16Operand : AsmImmRange<1, 16>;
466 def Imm1_32Operand : AsmImmRange<1, 32>;
467 def Imm1_64Operand : AsmImmRange<1, 64>;
469 class BranchTarget<int N> : AsmOperandClass {
470 let Name = "BranchTarget" # N;
471 let DiagnosticType = "InvalidLabel";
472 let PredicateMethod = "isBranchTarget<" # N # ">";
475 class PCRelLabel<int N> : BranchTarget<N> {
476 let Name = "PCRelLabel" # N;
479 def BranchTarget14Operand : BranchTarget<14>;
480 def BranchTarget26Operand : BranchTarget<26>;
481 def PCRelLabel19Operand : PCRelLabel<19>;
483 def MovWSymbolG3AsmOperand : AsmOperandClass {
484 let Name = "MovWSymbolG3";
485 let RenderMethod = "addImmOperands";
488 def movw_symbol_g3 : Operand<i32> {
489 let ParserMatchClass = MovWSymbolG3AsmOperand;
492 def MovWSymbolG2AsmOperand : AsmOperandClass {
493 let Name = "MovWSymbolG2";
494 let RenderMethod = "addImmOperands";
497 def movw_symbol_g2 : Operand<i32> {
498 let ParserMatchClass = MovWSymbolG2AsmOperand;
501 def MovWSymbolG1AsmOperand : AsmOperandClass {
502 let Name = "MovWSymbolG1";
503 let RenderMethod = "addImmOperands";
506 def movw_symbol_g1 : Operand<i32> {
507 let ParserMatchClass = MovWSymbolG1AsmOperand;
510 def MovWSymbolG0AsmOperand : AsmOperandClass {
511 let Name = "MovWSymbolG0";
512 let RenderMethod = "addImmOperands";
515 def movw_symbol_g0 : Operand<i32> {
516 let ParserMatchClass = MovWSymbolG0AsmOperand;
519 class fixedpoint_i32<ValueType FloatVT>
521 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
522 let EncoderMethod = "getFixedPointScaleOpValue";
523 let DecoderMethod = "DecodeFixedPointScaleImm32";
524 let ParserMatchClass = Imm1_32Operand;
527 class fixedpoint_i64<ValueType FloatVT>
529 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
530 let EncoderMethod = "getFixedPointScaleOpValue";
531 let DecoderMethod = "DecodeFixedPointScaleImm64";
532 let ParserMatchClass = Imm1_64Operand;
535 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
536 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
537 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
539 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
540 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
541 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
543 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
544 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
546 let EncoderMethod = "getVecShiftR8OpValue";
547 let DecoderMethod = "DecodeVecShiftR8Imm";
548 let ParserMatchClass = Imm1_8Operand;
550 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
551 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
553 let EncoderMethod = "getVecShiftR16OpValue";
554 let DecoderMethod = "DecodeVecShiftR16Imm";
555 let ParserMatchClass = Imm1_16Operand;
557 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
558 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
560 let EncoderMethod = "getVecShiftR16OpValue";
561 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
562 let ParserMatchClass = Imm1_8Operand;
564 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
565 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
567 let EncoderMethod = "getVecShiftR32OpValue";
568 let DecoderMethod = "DecodeVecShiftR32Imm";
569 let ParserMatchClass = Imm1_32Operand;
571 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
572 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
574 let EncoderMethod = "getVecShiftR32OpValue";
575 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
576 let ParserMatchClass = Imm1_16Operand;
578 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
579 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
581 let EncoderMethod = "getVecShiftR64OpValue";
582 let DecoderMethod = "DecodeVecShiftR64Imm";
583 let ParserMatchClass = Imm1_64Operand;
585 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
586 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
588 let EncoderMethod = "getVecShiftR64OpValue";
589 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
590 let ParserMatchClass = Imm1_32Operand;
593 def Imm0_1Operand : AsmImmRange<0, 1>;
594 def Imm0_7Operand : AsmImmRange<0, 7>;
595 def Imm0_15Operand : AsmImmRange<0, 15>;
596 def Imm0_31Operand : AsmImmRange<0, 31>;
597 def Imm0_63Operand : AsmImmRange<0, 63>;
599 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
600 return (((uint32_t)Imm) < 8);
602 let EncoderMethod = "getVecShiftL8OpValue";
603 let DecoderMethod = "DecodeVecShiftL8Imm";
604 let ParserMatchClass = Imm0_7Operand;
606 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
607 return (((uint32_t)Imm) < 16);
609 let EncoderMethod = "getVecShiftL16OpValue";
610 let DecoderMethod = "DecodeVecShiftL16Imm";
611 let ParserMatchClass = Imm0_15Operand;
613 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
614 return (((uint32_t)Imm) < 32);
616 let EncoderMethod = "getVecShiftL32OpValue";
617 let DecoderMethod = "DecodeVecShiftL32Imm";
618 let ParserMatchClass = Imm0_31Operand;
620 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
621 return (((uint32_t)Imm) < 64);
623 let EncoderMethod = "getVecShiftL64OpValue";
624 let DecoderMethod = "DecodeVecShiftL64Imm";
625 let ParserMatchClass = Imm0_63Operand;
629 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
630 // instructions for splatting repeating bit patterns across the immediate.
631 def logical_imm32_XFORM : SDNodeXForm<imm, [{
632 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
633 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
635 def logical_imm64_XFORM : SDNodeXForm<imm, [{
636 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
637 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
640 def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
641 GISDNodeXFormEquiv<logical_imm32_XFORM>;
642 def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
643 GISDNodeXFormEquiv<logical_imm64_XFORM>;
645 let DiagnosticType = "LogicalSecondSource" in {
646 def LogicalImm32Operand : AsmOperandClass {
647 let Name = "LogicalImm32";
648 let PredicateMethod = "isLogicalImm<int32_t>";
649 let RenderMethod = "addLogicalImmOperands<int32_t>";
651 def LogicalImm64Operand : AsmOperandClass {
652 let Name = "LogicalImm64";
653 let PredicateMethod = "isLogicalImm<int64_t>";
654 let RenderMethod = "addLogicalImmOperands<int64_t>";
656 def LogicalImm32NotOperand : AsmOperandClass {
657 let Name = "LogicalImm32Not";
658 let PredicateMethod = "isLogicalImm<int32_t>";
659 let RenderMethod = "addLogicalImmNotOperands<int32_t>";
661 def LogicalImm64NotOperand : AsmOperandClass {
662 let Name = "LogicalImm64Not";
663 let PredicateMethod = "isLogicalImm<int64_t>";
664 let RenderMethod = "addLogicalImmNotOperands<int64_t>";
667 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
668 return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
669 }], logical_imm32_XFORM> {
670 let PrintMethod = "printLogicalImm<int32_t>";
671 let ParserMatchClass = LogicalImm32Operand;
673 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
674 return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
675 }], logical_imm64_XFORM> {
676 let PrintMethod = "printLogicalImm<int64_t>";
677 let ParserMatchClass = LogicalImm64Operand;
679 def logical_imm32_not : Operand<i32> {
680 let ParserMatchClass = LogicalImm32NotOperand;
682 def logical_imm64_not : Operand<i64> {
683 let ParserMatchClass = LogicalImm64NotOperand;
686 // iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
687 let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
688 def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
689 return ((uint32_t)Imm) < 65536;
692 def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
693 return ((uint64_t)Imm) < 65536;
697 // imm0_255 predicate - True if the immediate is in the range [0,255].
698 def Imm0_255Operand : AsmImmRange<0,255>;
700 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
701 return ((uint32_t)Imm) < 256;
703 let ParserMatchClass = Imm0_255Operand;
704 let PrintMethod = "printImm";
707 // imm0_127 predicate - True if the immediate is in the range [0,127]
708 def Imm0_127Operand : AsmImmRange<0, 127>;
709 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
710 return ((uint32_t)Imm) < 128;
712 let ParserMatchClass = Imm0_127Operand;
713 let PrintMethod = "printImm";
716 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
717 // for all shift-amounts.
719 // imm0_63 predicate - True if the immediate is in the range [0,63]
720 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
721 return ((uint64_t)Imm) < 64;
723 let ParserMatchClass = Imm0_63Operand;
726 // imm0_31 predicate - True if the immediate is in the range [0,31]
727 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
728 return ((uint64_t)Imm) < 32;
730 let ParserMatchClass = Imm0_31Operand;
733 // True if the 32-bit immediate is in the range [0,31]
734 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
735 return ((uint64_t)Imm) < 32;
737 let ParserMatchClass = Imm0_31Operand;
740 // imm0_1 predicate - True if the immediate is in the range [0,1]
741 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
742 return ((uint64_t)Imm) < 2;
744 let ParserMatchClass = Imm0_1Operand;
747 // imm0_15 predicate - True if the immediate is in the range [0,15]
748 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
749 return ((uint64_t)Imm) < 16;
751 let ParserMatchClass = Imm0_15Operand;
754 // imm0_7 predicate - True if the immediate is in the range [0,7]
755 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
756 return ((uint64_t)Imm) < 8;
758 let ParserMatchClass = Imm0_7Operand;
761 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
762 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
763 return ((uint32_t)Imm) < 16;
765 let ParserMatchClass = Imm0_15Operand;
768 // An arithmetic shifter operand:
769 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
771 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
772 let PrintMethod = "printShifter";
773 let ParserMatchClass = !cast<AsmOperandClass>(
774 "ArithmeticShifterOperand" # width);
777 def arith_shift32 : arith_shift<i32, 32>;
778 def arith_shift64 : arith_shift<i64, 64>;
780 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
782 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
783 let PrintMethod = "printShiftedRegister";
784 let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
787 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
788 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
790 def gi_arith_shifted_reg32 :
791 GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
792 GIComplexPatternEquiv<arith_shifted_reg32>;
794 def gi_arith_shifted_reg64 :
795 GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
796 GIComplexPatternEquiv<arith_shifted_reg64>;
798 // An arithmetic shifter operand:
799 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
801 class logical_shift<int width> : Operand<i32> {
802 let PrintMethod = "printShifter";
803 let ParserMatchClass = !cast<AsmOperandClass>(
804 "LogicalShifterOperand" # width);
807 def logical_shift32 : logical_shift<32>;
808 def logical_shift64 : logical_shift<64>;
810 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
812 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
813 let PrintMethod = "printShiftedRegister";
814 let MIOperandInfo = (ops regclass, shiftop);
817 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
818 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
820 def gi_logical_shifted_reg32 :
821 GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
822 GIComplexPatternEquiv<logical_shifted_reg32>;
824 def gi_logical_shifted_reg64 :
825 GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
826 GIComplexPatternEquiv<logical_shifted_reg64>;
828 // A logical vector shifter operand:
829 // {7-6} - shift type: 00 = lsl
830 // {5-0} - imm6: #0, #8, #16, or #24
831 def logical_vec_shift : Operand<i32> {
832 let PrintMethod = "printShifter";
833 let EncoderMethod = "getVecShifterOpValue";
834 let ParserMatchClass = LogicalVecShifterOperand;
837 // A logical vector half-word shifter operand:
838 // {7-6} - shift type: 00 = lsl
839 // {5-0} - imm6: #0 or #8
840 def logical_vec_hw_shift : Operand<i32> {
841 let PrintMethod = "printShifter";
842 let EncoderMethod = "getVecShifterOpValue";
843 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
846 // A vector move shifter operand:
847 // {0} - imm1: #8 or #16
848 def move_vec_shift : Operand<i32> {
849 let PrintMethod = "printShifter";
850 let EncoderMethod = "getMoveVecShifterOpValue";
851 let ParserMatchClass = MoveVecShifterOperand;
854 let DiagnosticType = "AddSubSecondSource" in {
855 def AddSubImmOperand : AsmOperandClass {
856 let Name = "AddSubImm";
857 let ParserMethod = "tryParseImmWithOptionalShift";
858 let RenderMethod = "addImmWithOptionalShiftOperands<12>";
860 def AddSubImmNegOperand : AsmOperandClass {
861 let Name = "AddSubImmNeg";
862 let ParserMethod = "tryParseImmWithOptionalShift";
863 let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
866 // An ADD/SUB immediate shifter operand:
868 // {7-6} - shift type: 00 = lsl
869 // {5-0} - imm6: #0 or #12
870 class addsub_shifted_imm<ValueType Ty>
871 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
872 let PrintMethod = "printAddSubImm";
873 let EncoderMethod = "getAddSubImmOpValue";
874 let ParserMatchClass = AddSubImmOperand;
875 let MIOperandInfo = (ops i32imm, i32imm);
878 class addsub_shifted_imm_neg<ValueType Ty>
880 let EncoderMethod = "getAddSubImmOpValue";
881 let ParserMatchClass = AddSubImmNegOperand;
882 let MIOperandInfo = (ops i32imm, i32imm);
885 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
886 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
887 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
888 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
890 def gi_addsub_shifted_imm32 :
891 GIComplexOperandMatcher<s32, "selectArithImmed">,
892 GIComplexPatternEquiv<addsub_shifted_imm32>;
894 def gi_addsub_shifted_imm64 :
895 GIComplexOperandMatcher<s64, "selectArithImmed">,
896 GIComplexPatternEquiv<addsub_shifted_imm64>;
898 class neg_addsub_shifted_imm<ValueType Ty>
899 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
900 let PrintMethod = "printAddSubImm";
901 let EncoderMethod = "getAddSubImmOpValue";
902 let ParserMatchClass = AddSubImmOperand;
903 let MIOperandInfo = (ops i32imm, i32imm);
906 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
907 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
909 def gi_neg_addsub_shifted_imm32 :
910 GIComplexOperandMatcher<s32, "selectNegArithImmed">,
911 GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
913 def gi_neg_addsub_shifted_imm64 :
914 GIComplexOperandMatcher<s64, "selectNegArithImmed">,
915 GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
917 // An extend operand:
918 // {5-3} - extend type
920 def arith_extend : Operand<i32> {
921 let PrintMethod = "printArithExtend";
922 let ParserMatchClass = ExtendOperand;
924 def arith_extend64 : Operand<i32> {
925 let PrintMethod = "printArithExtend";
926 let ParserMatchClass = ExtendOperand64;
929 // 'extend' that's a lsl of a 64-bit register.
930 def arith_extendlsl64 : Operand<i32> {
931 let PrintMethod = "printArithExtend";
932 let ParserMatchClass = ExtendOperandLSL64;
935 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
936 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
937 let PrintMethod = "printExtendedRegister";
938 let MIOperandInfo = (ops GPR32, arith_extend);
941 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
942 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
943 let PrintMethod = "printExtendedRegister";
944 let MIOperandInfo = (ops GPR32, arith_extend64);
947 def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
948 def gi_arith_extended_reg32_i32 :
949 GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
950 GIComplexPatternEquiv<arith_extended_reg32_i32>;
952 def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
953 def gi_arith_extended_reg32_i64 :
954 GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
955 GIComplexPatternEquiv<arith_extended_reg32_i64>;
957 def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
958 def gi_arith_extended_reg32to64_i64 :
959 GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
960 GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
962 // Floating-point immediate.
963 def fpimm16 : Operand<f16>,
965 return AArch64_AM::getFP16Imm(Imm) != -1;
966 }], SDNodeXForm<fpimm, [{
967 APFloat InVal = N->getValueAPF();
968 uint32_t enc = AArch64_AM::getFP16Imm(InVal);
969 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
971 let ParserMatchClass = FPImmOperand;
972 let PrintMethod = "printFPImmOperand";
974 def fpimm32 : Operand<f32>,
976 return AArch64_AM::getFP32Imm(Imm) != -1;
977 }], SDNodeXForm<fpimm, [{
978 APFloat InVal = N->getValueAPF();
979 uint32_t enc = AArch64_AM::getFP32Imm(InVal);
980 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
982 let ParserMatchClass = FPImmOperand;
983 let PrintMethod = "printFPImmOperand";
985 def fpimm64 : Operand<f64>,
987 return AArch64_AM::getFP64Imm(Imm) != -1;
988 }], SDNodeXForm<fpimm, [{
989 APFloat InVal = N->getValueAPF();
990 uint32_t enc = AArch64_AM::getFP64Imm(InVal);
991 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
993 let ParserMatchClass = FPImmOperand;
994 let PrintMethod = "printFPImmOperand";
997 def fpimm8 : Operand<i32> {
998 let ParserMatchClass = FPImmOperand;
999 let PrintMethod = "printFPImmOperand";
1002 def fpimm0 : FPImmLeaf<fAny, [{
1003 return Imm.isExactlyValue(+0.0);
1006 // Vector lane operands
1007 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1008 let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1009 let DiagnosticType = "Invalid" # Name;
1010 let PredicateMethod = "isVectorIndex<" # Min # ", " # Max # ">";
1011 let RenderMethod = "addVectorIndexOperands";
1014 class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc, code pred>
1015 : Operand<ty>, ImmLeaf<ty, pred> {
1016 let ParserMatchClass = mc;
1017 let PrintMethod = "printVectorIndex";
1020 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1021 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1022 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1023 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1024 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1026 def VectorIndex1 : AsmVectorIndexOpnd<i64, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1027 def VectorIndexB : AsmVectorIndexOpnd<i64, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1028 def VectorIndexH : AsmVectorIndexOpnd<i64, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1029 def VectorIndexS : AsmVectorIndexOpnd<i64, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1030 def VectorIndexD : AsmVectorIndexOpnd<i64, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1032 def VectorIndex132b : AsmVectorIndexOpnd<i32, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1033 def VectorIndexB32b : AsmVectorIndexOpnd<i32, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1034 def VectorIndexH32b : AsmVectorIndexOpnd<i32, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1035 def VectorIndexS32b : AsmVectorIndexOpnd<i32, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1036 def VectorIndexD32b : AsmVectorIndexOpnd<i32, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1038 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1039 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1040 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1041 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1042 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1044 def sve_elm_idx_extdup_b
1045 : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1046 def sve_elm_idx_extdup_h
1047 : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1048 def sve_elm_idx_extdup_s
1049 : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1050 def sve_elm_idx_extdup_d
1051 : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1052 def sve_elm_idx_extdup_q
1053 : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1055 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1056 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1057 // are encoded as the eight bit value 'abcdefgh'.
1058 def simdimmtype10 : Operand<i32>,
1060 return AArch64_AM::isAdvSIMDModImmType10(
1061 Imm.bitcastToAPInt().getZExtValue());
1062 }], SDNodeXForm<fpimm, [{
1063 APFloat InVal = N->getValueAPF();
1064 uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1067 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1069 let ParserMatchClass = SIMDImmType10Operand;
1070 let PrintMethod = "printSIMDType10Operand";
1075 // System management
1078 // Base encoding for system instruction operands.
1079 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1080 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1081 list<dag> pattern = []>
1082 : I<oops, iops, asm, operands, "", pattern> {
1083 let Inst{31-22} = 0b1101010100;
1087 // System instructions which do not have an Rt register.
1088 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1089 list<dag> pattern = []>
1090 : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1091 let Inst{4-0} = 0b11111;
1094 // System instructions which have an Rt register.
1095 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1096 : BaseSystemI<L, oops, iops, asm, operands>,
1102 // System instructions for transactional memory extension
1103 class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1104 string asm, string operands, list<dag> pattern>
1105 : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1107 let Inst{20-12} = 0b000110011;
1108 let Inst{11-8} = CRm;
1109 let Inst{7-5} = op2;
1110 let DecoderMethod = "";
1116 // System instructions for transactional memory - single input operand
1117 class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1118 : TMBaseSystemI<0b1, CRm, 0b011,
1119 (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1124 // System instructions for transactional memory - no operand
1125 class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1126 : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1127 let Inst{4-0} = 0b11111;
1130 // System instructions for exit from transactions
1131 class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1132 : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1135 let Inst{31-24} = 0b11010100;
1136 let Inst{23-21} = op1;
1137 let Inst{20-5} = imm;
1138 let Inst{4-0} = 0b00000;
1141 // Hint instructions that take both a CRm and a 3-bit immediate.
1142 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1143 // model patterns with sufficiently fine granularity
1144 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1145 class HintI<string mnemonic>
1146 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1147 [(int_aarch64_hint imm0_127:$imm)]>,
1148 Sched<[WriteHint]> {
1150 let Inst{20-12} = 0b000110010;
1151 let Inst{11-5} = imm;
1154 // System instructions taking a single literal operand which encodes into
1155 // CRm. op2 differentiates the opcodes.
1156 def BarrierAsmOperand : AsmOperandClass {
1157 let Name = "Barrier";
1158 let ParserMethod = "tryParseBarrierOperand";
1160 def barrier_op : Operand<i32> {
1161 let PrintMethod = "printBarrierOption";
1162 let ParserMatchClass = BarrierAsmOperand;
1164 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1165 list<dag> pattern = []>
1166 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1167 Sched<[WriteBarrier]> {
1169 let Inst{20-12} = 0b000110011;
1170 let Inst{11-8} = CRm;
1171 let Inst{7-5} = opc;
1174 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1175 : SimpleSystemI<0, (ins), asm, "", pattern>,
1179 let Inst{31-12} = 0b11010101000000110010;
1180 let Inst{11-8} = CRm;
1181 let Inst{7-5} = op2;
1182 let Inst{4-0} = 0b11111;
1185 // MRS/MSR system instructions. These have different operand classes because
1186 // a different subset of registers can be accessed through each instruction.
1187 def MRSSystemRegisterOperand : AsmOperandClass {
1188 let Name = "MRSSystemRegister";
1189 let ParserMethod = "tryParseSysReg";
1190 let DiagnosticType = "MRS";
1192 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1193 def mrs_sysreg_op : Operand<i32> {
1194 let ParserMatchClass = MRSSystemRegisterOperand;
1195 let DecoderMethod = "DecodeMRSSystemRegister";
1196 let PrintMethod = "printMRSSystemRegister";
1199 def MSRSystemRegisterOperand : AsmOperandClass {
1200 let Name = "MSRSystemRegister";
1201 let ParserMethod = "tryParseSysReg";
1202 let DiagnosticType = "MSR";
1204 def msr_sysreg_op : Operand<i32> {
1205 let ParserMatchClass = MSRSystemRegisterOperand;
1206 let DecoderMethod = "DecodeMSRSystemRegister";
1207 let PrintMethod = "printMSRSystemRegister";
1210 def PSBHintOperand : AsmOperandClass {
1211 let Name = "PSBHint";
1212 let ParserMethod = "tryParsePSBHint";
1214 def psbhint_op : Operand<i32> {
1215 let ParserMatchClass = PSBHintOperand;
1216 let PrintMethod = "printPSBHintOp";
1217 let MCOperandPredicate = [{
1218 // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1219 // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1222 return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1226 def BTIHintOperand : AsmOperandClass {
1227 let Name = "BTIHint";
1228 let ParserMethod = "tryParseBTIHint";
1230 def btihint_op : Operand<i32> {
1231 let ParserMatchClass = BTIHintOperand;
1232 let PrintMethod = "printBTIHintOp";
1233 let MCOperandPredicate = [{
1234 // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1237 return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1241 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1242 "mrs", "\t$Rt, $systemreg"> {
1244 let Inst{20-5} = systemreg;
1247 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1248 // Explicitly modeling each of the system register as a register class
1249 // would do it, but feels like overkill at this point.
1250 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1251 "msr", "\t$systemreg, $Rt"> {
1253 let Inst{20-5} = systemreg;
1256 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1257 let Name = "SystemPStateFieldWithImm0_15";
1258 let ParserMethod = "tryParseSysReg";
1260 def pstatefield4_op : Operand<i32> {
1261 let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1262 let PrintMethod = "printSystemPStateField";
1265 // Instructions to modify PSTATE, no input reg
1266 let Defs = [NZCV] in
1267 class PstateWriteSimple<dag iops, string asm, string operands>
1268 : SimpleSystemI<0, iops, asm, operands> {
1270 let Inst{20-19} = 0b00;
1271 let Inst{15-12} = 0b0100;
1274 class MSRpstateImm0_15
1275 : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1276 "\t$pstatefield, $imm">,
1279 bits<6> pstatefield;
1281 let Inst{18-16} = pstatefield{5-3};
1282 let Inst{11-8} = imm;
1283 let Inst{7-5} = pstatefield{2-0};
1285 let DecoderMethod = "DecodeSystemPStateInstruction";
1286 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1287 // Fail the decoder should attempt to decode the instruction as MSRI.
1288 let hasCompleteDecoder = 0;
1291 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1292 let Name = "SystemPStateFieldWithImm0_1";
1293 let ParserMethod = "tryParseSysReg";
1295 def pstatefield1_op : Operand<i32> {
1296 let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1297 let PrintMethod = "printSystemPStateField";
1300 class MSRpstateImm0_1
1301 : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1302 "\t$pstatefield, $imm">,
1305 bits<6> pstatefield;
1307 let Inst{18-16} = pstatefield{5-3};
1308 let Inst{11-9} = 0b000;
1310 let Inst{7-5} = pstatefield{2-0};
1312 let DecoderMethod = "DecodeSystemPStateInstruction";
1313 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1314 // Fail the decoder should attempt to decode the instruction as MSRI.
1315 let hasCompleteDecoder = 0;
1318 // SYS and SYSL generic system instructions.
1319 def SysCRAsmOperand : AsmOperandClass {
1321 let ParserMethod = "tryParseSysCROperand";
1324 def sys_cr_op : Operand<i32> {
1325 let PrintMethod = "printSysCROperand";
1326 let ParserMatchClass = SysCRAsmOperand;
1329 class SystemXtI<bit L, string asm>
1330 : RtSystemI<L, (outs),
1331 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1332 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1337 let Inst{20-19} = 0b01;
1338 let Inst{18-16} = op1;
1339 let Inst{15-12} = Cn;
1340 let Inst{11-8} = Cm;
1341 let Inst{7-5} = op2;
1344 class SystemLXtI<bit L, string asm>
1345 : RtSystemI<L, (outs),
1346 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1347 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1352 let Inst{20-19} = 0b01;
1353 let Inst{18-16} = op1;
1354 let Inst{15-12} = Cn;
1355 let Inst{11-8} = Cm;
1356 let Inst{7-5} = op2;
1360 // Branch (register) instructions:
1368 // otherwise UNDEFINED
1369 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1370 string operands, list<dag> pattern>
1371 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1372 let Inst{31-25} = 0b1101011;
1373 let Inst{24-21} = opc;
1374 let Inst{20-16} = 0b11111;
1375 let Inst{15-10} = 0b000000;
1376 let Inst{4-0} = 0b00000;
1379 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1380 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1385 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1386 class SpecialReturn<bits<4> opc, string asm>
1387 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1388 let Inst{9-5} = 0b11111;
1392 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1393 : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1397 let Inst{31-30} = sz;
1398 let Inst{29-10} = 0b11100010111111110000;
1403 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1405 : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1406 let Inst{31-25} = 0b1101011;
1407 let Inst{20-11} = 0b1111100001;
1409 let Inst{4-0} = 0b11111;
1412 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1413 : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1416 let Inst{24-22} = 0b100;
1422 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1423 : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1426 let Inst{23-21} = opc;
1430 class AuthReturn<bits<3> op, bits<1> M, string asm>
1431 : AuthBase<M, (outs), (ins), asm, "", []> {
1433 let Inst{23-21} = op;
1434 let Inst{9-0} = 0b1111111111;
1438 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1439 string operands, string cstr, Operand opr>
1440 : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1444 let Inst{31-24} = 0b11111000;
1446 let Inst{22} = offset{9};
1448 let Inst{20-12} = offset{8-0};
1455 multiclass AuthLoad<bit M, string asm, Operand opr> {
1456 def indexed : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1457 (ins GPR64sp:$Rn, opr:$offset),
1458 asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1459 def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1460 (ins GPR64sp:$Rn, opr:$offset),
1461 asm, "\t$Rt, [$Rn, $offset]!",
1462 "$Rn = $wback,@earlyclobber $wback", opr>;
1464 def : InstAlias<asm # "\t$Rt, [$Rn]",
1465 (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1469 // Conditional branch instruction.
1473 // 4-bit immediate. Pretty-printed as <cc>
1474 def ccode : Operand<i32> {
1475 let PrintMethod = "printCondCode";
1476 let ParserMatchClass = CondCode;
1478 def inv_ccode : Operand<i32> {
1479 // AL and NV are invalid in the aliases which use inv_ccode
1480 let PrintMethod = "printInverseCondCode";
1481 let ParserMatchClass = CondCode;
1482 let MCOperandPredicate = [{
1483 return MCOp.isImm() &&
1484 MCOp.getImm() != AArch64CC::AL &&
1485 MCOp.getImm() != AArch64CC::NV;
1489 // Conditional branch target. 19-bit immediate. The low two bits of the target
1490 // offset are implied zero and so are not part of the immediate.
1491 def am_brcond : Operand<OtherVT> {
1492 let EncoderMethod = "getCondBranchTargetOpValue";
1493 let DecoderMethod = "DecodePCRelLabel19";
1494 let PrintMethod = "printAlignedLabel";
1495 let ParserMatchClass = PCRelLabel19Operand;
1496 let OperandType = "OPERAND_PCREL";
1499 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1500 "b", ".$cond\t$target", "",
1501 [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1504 let isTerminator = 1;
1509 let Inst{31-24} = 0b01010100;
1510 let Inst{23-5} = target;
1512 let Inst{3-0} = cond;
1516 // Compare-and-branch instructions.
1518 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1519 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1520 asm, "\t$Rt, $target", "",
1521 [(node regtype:$Rt, bb:$target)]>,
1524 let isTerminator = 1;
1528 let Inst{30-25} = 0b011010;
1530 let Inst{23-5} = target;
1534 multiclass CmpBranch<bit op, string asm, SDNode node> {
1535 def W : BaseCmpBranch<GPR32, op, asm, node> {
1538 def X : BaseCmpBranch<GPR64, op, asm, node> {
1544 // Test-bit-and-branch instructions.
1546 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1547 // the target offset are implied zero and so are not part of the immediate.
1548 def am_tbrcond : Operand<OtherVT> {
1549 let EncoderMethod = "getTestBranchTargetOpValue";
1550 let PrintMethod = "printAlignedLabel";
1551 let ParserMatchClass = BranchTarget14Operand;
1552 let OperandType = "OPERAND_PCREL";
1555 // AsmOperand classes to emit (or not) special diagnostics
1556 def TBZImm0_31Operand : AsmOperandClass {
1557 let Name = "TBZImm0_31";
1558 let PredicateMethod = "isImmInRange<0,31>";
1559 let RenderMethod = "addImmOperands";
1561 def TBZImm32_63Operand : AsmOperandClass {
1562 let Name = "Imm32_63";
1563 let PredicateMethod = "isImmInRange<32,63>";
1564 let DiagnosticType = "InvalidImm0_63";
1565 let RenderMethod = "addImmOperands";
1568 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1569 return (((uint32_t)Imm) < 32);
1571 let ParserMatchClass = matcher;
1574 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1575 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1577 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1578 return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1580 let ParserMatchClass = TBZImm32_63Operand;
1583 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1584 bit op, string asm, SDNode node>
1585 : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1586 asm, "\t$Rt, $bit_off, $target", "",
1587 [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1590 let isTerminator = 1;
1596 let Inst{30-25} = 0b011011;
1598 let Inst{23-19} = bit_off{4-0};
1599 let Inst{18-5} = target;
1602 let DecoderMethod = "DecodeTestAndBranch";
1605 multiclass TestBranch<bit op, string asm, SDNode node> {
1606 def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1610 def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1614 // Alias X-reg with 0-31 imm to W-Reg.
1615 def : InstAlias<asm # "\t$Rd, $imm, $target",
1616 (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1617 tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1618 def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1619 (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1620 tbz_imm0_31_diag:$imm, bb:$target)>;
1624 // Unconditional branch (immediate) instructions.
1626 def am_b_target : Operand<OtherVT> {
1627 let EncoderMethod = "getBranchTargetOpValue";
1628 let PrintMethod = "printAlignedLabel";
1629 let ParserMatchClass = BranchTarget26Operand;
1630 let OperandType = "OPERAND_PCREL";
1632 def am_bl_target : Operand<i64> {
1633 let EncoderMethod = "getBranchTargetOpValue";
1634 let PrintMethod = "printAlignedLabel";
1635 let ParserMatchClass = BranchTarget26Operand;
1636 let OperandType = "OPERAND_PCREL";
1639 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1640 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1643 let Inst{30-26} = 0b00101;
1644 let Inst{25-0} = addr;
1646 let DecoderMethod = "DecodeUnconditionalBranch";
1649 class BranchImm<bit op, string asm, list<dag> pattern>
1650 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1651 class CallImm<bit op, string asm, list<dag> pattern>
1652 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1655 // Basic one-operand data processing instructions.
1658 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1659 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1660 SDPatternOperator node>
1661 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1662 [(set regtype:$Rd, (node regtype:$Rn))]>,
1663 Sched<[WriteI, ReadI]> {
1667 let Inst{30-13} = 0b101101011000000000;
1668 let Inst{12-10} = opc;
1673 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1674 multiclass OneOperandData<bits<3> opc, string asm,
1675 SDPatternOperator node = null_frag> {
1676 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1680 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1685 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1686 : BaseOneOperandData<opc, GPR32, asm, node> {
1690 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1691 : BaseOneOperandData<opc, GPR64, asm, node> {
1695 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1696 : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1698 Sched<[WriteI, ReadI]> {
1701 let Inst{31-15} = 0b11011010110000010;
1702 let Inst{14-12} = opcode_prefix;
1703 let Inst{11-10} = opcode;
1708 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1709 : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1711 let Inst{31-15} = 0b11011010110000010;
1712 let Inst{14-12} = opcode_prefix;
1713 let Inst{11-10} = opcode;
1714 let Inst{9-5} = 0b11111;
1718 class SignAuthTwoOperand<bits<4> opc, string asm,
1719 SDPatternOperator OpNode>
1720 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1721 asm, "\t$Rd, $Rn, $Rm", "",
1722 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1723 Sched<[WriteI, ReadI, ReadI]> {
1727 let Inst{31-21} = 0b10011010110;
1728 let Inst{20-16} = Rm;
1729 let Inst{15-14} = 0b00;
1730 let Inst{13-10} = opc;
1735 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1736 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1737 : I<(outs), iops, asm, ops, "", []>,
1738 Sched<[WriteI, ReadI, ReadI]> {
1742 let Inst{30-15} = 0b0111010000000000;
1744 let Inst{13-10} = 0b0010;
1746 let Inst{4-0} = 0b01101;
1749 class FlagRotate<dag iops, string asm, string ops>
1750 : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1753 let Inst{20-15} = imm;
1754 let Inst{13-10} = 0b0001;
1756 let Inst{3-0} = mask;
1760 // Basic two-operand data processing instructions.
1762 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1764 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1765 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1766 Sched<[WriteI, ReadI, ReadI]> {
1771 let Inst{30} = isSub;
1772 let Inst{28-21} = 0b11010000;
1773 let Inst{20-16} = Rm;
1774 let Inst{15-10} = 0;
1779 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1781 : BaseBaseAddSubCarry<isSub, regtype, asm,
1782 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1784 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1786 : BaseBaseAddSubCarry<isSub, regtype, asm,
1787 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1792 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1793 SDNode OpNode, SDNode OpNode_setflags> {
1794 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1798 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1804 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1809 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1816 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1817 SDPatternOperator OpNode,
1818 RegisterClass in1regtype = regtype,
1819 RegisterClass in2regtype = regtype>
1820 : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
1821 asm, "\t$Rd, $Rn, $Rm", "",
1822 [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
1826 let Inst{30-21} = 0b0011010110;
1827 let Inst{20-16} = Rm;
1828 let Inst{15-14} = 0b00;
1829 let Inst{13-10} = opc;
1834 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1835 SDPatternOperator OpNode>
1836 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1837 let Inst{10} = isSigned;
1840 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1841 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1842 Sched<[WriteID32, ReadID, ReadID]> {
1845 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1846 Sched<[WriteID64, ReadID, ReadID]> {
1851 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1852 SDPatternOperator OpNode = null_frag>
1853 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1854 Sched<[WriteIS, ReadI]> {
1855 let Inst{11-10} = shift_type;
1858 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1859 def Wr : BaseShift<shift_type, GPR32, asm> {
1863 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1867 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1868 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1869 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1871 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1872 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1874 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1875 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1877 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1878 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1880 def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
1881 (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1882 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1884 def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
1885 (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1886 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1889 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1890 : InstAlias<asm#"\t$dst, $src1, $src2",
1891 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1893 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1894 RegisterClass addtype, string asm,
1896 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1897 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1902 let Inst{30-24} = 0b0011011;
1903 let Inst{23-21} = opc;
1904 let Inst{20-16} = Rm;
1905 let Inst{15} = isSub;
1906 let Inst{14-10} = Ra;
1911 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1912 // MADD/MSUB generation is decided by MachineCombiner.cpp
1913 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1914 [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1915 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1919 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1920 [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1921 Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1926 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1927 SDNode AccNode, SDNode ExtNode>
1928 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1929 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1930 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1931 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1935 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1936 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1937 asm, "\t$Rd, $Rn, $Rm", "",
1938 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1939 Sched<[WriteIM64, ReadIM, ReadIM]> {
1943 let Inst{31-24} = 0b10011011;
1944 let Inst{23-21} = opc;
1945 let Inst{20-16} = Rm;
1950 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1951 // (i.e. all bits 1) but is ignored by the processor.
1952 let PostEncoderMethod = "fixMulHigh";
1955 class MulAccumWAlias<string asm, Instruction inst>
1956 : InstAlias<asm#"\t$dst, $src1, $src2",
1957 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1958 class MulAccumXAlias<string asm, Instruction inst>
1959 : InstAlias<asm#"\t$dst, $src1, $src2",
1960 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1961 class WideMulAccumAlias<string asm, Instruction inst>
1962 : InstAlias<asm#"\t$dst, $src1, $src2",
1963 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1965 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1966 SDPatternOperator OpNode, string asm>
1967 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1968 asm, "\t$Rd, $Rn, $Rm", "",
1969 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1970 Sched<[WriteISReg, ReadI, ReadISReg]> {
1976 let Inst{30-21} = 0b0011010110;
1977 let Inst{20-16} = Rm;
1978 let Inst{15-13} = 0b010;
1980 let Inst{11-10} = sz;
1983 let Predicates = [HasCRC];
1987 // Address generation.
1990 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1991 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1996 let Inst{31} = page;
1997 let Inst{30-29} = label{1-0};
1998 let Inst{28-24} = 0b10000;
1999 let Inst{23-5} = label{20-2};
2002 let DecoderMethod = "DecodeAdrInstruction";
2009 def movimm32_imm : Operand<i32> {
2010 let ParserMatchClass = AsmImmRange<0, 65535>;
2011 let EncoderMethod = "getMoveWideImmOpValue";
2012 let PrintMethod = "printImm";
2014 def movimm32_shift : Operand<i32> {
2015 let PrintMethod = "printShifter";
2016 let ParserMatchClass = MovImm32ShifterOperand;
2018 def movimm64_shift : Operand<i32> {
2019 let PrintMethod = "printShifter";
2020 let ParserMatchClass = MovImm64ShifterOperand;
2023 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2024 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2026 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2027 asm, "\t$Rd, $imm$shift", "", []>,
2032 let Inst{30-29} = opc;
2033 let Inst{28-23} = 0b100101;
2034 let Inst{22-21} = shift{5-4};
2035 let Inst{20-5} = imm;
2038 let DecoderMethod = "DecodeMoveImmInstruction";
2041 multiclass MoveImmediate<bits<2> opc, string asm> {
2042 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2046 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2051 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2052 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2054 : I<(outs regtype:$Rd),
2055 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2056 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2057 Sched<[WriteI, ReadI]> {
2061 let Inst{30-29} = opc;
2062 let Inst{28-23} = 0b100101;
2063 let Inst{22-21} = shift{5-4};
2064 let Inst{20-5} = imm;
2067 let DecoderMethod = "DecodeMoveImmInstruction";
2070 multiclass InsertImmediate<bits<2> opc, string asm> {
2071 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2075 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2084 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2085 string asm_inst, string asm_ops,
2086 dag inputs, dag pattern>
2087 : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2088 Sched<[WriteI, ReadI]> {
2091 let Inst{30} = isSub;
2092 let Inst{29} = setFlags;
2093 let Inst{28-24} = 0b10001;
2098 class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2099 RegisterClass srcRegtype, addsub_shifted_imm immtype,
2100 string asm_inst, SDPatternOperator OpNode>
2101 : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2102 (ins srcRegtype:$Rn, immtype:$imm),
2103 (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2105 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2106 let Inst{21-10} = imm{11-0};
2107 let DecoderMethod = "DecodeAddSubImmShift";
2110 class BaseAddSubRegPseudo<RegisterClass regtype,
2111 SDPatternOperator OpNode>
2112 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2113 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2114 Sched<[WriteI, ReadI, ReadI]>;
2116 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2117 arith_shifted_reg shifted_regtype, string asm,
2118 SDPatternOperator OpNode>
2119 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2120 asm, "\t$Rd, $Rn, $Rm", "",
2121 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2122 Sched<[WriteISReg, ReadI, ReadISReg]> {
2123 // The operands are in order to match the 'addr' MI operands, so we
2124 // don't need an encoder method and by-name matching. Just use the default
2125 // in-order handling. Since we're using by-order, make sure the names
2131 let Inst{30} = isSub;
2132 let Inst{29} = setFlags;
2133 let Inst{28-24} = 0b01011;
2134 let Inst{23-22} = shift{7-6};
2136 let Inst{20-16} = src2;
2137 let Inst{15-10} = shift{5-0};
2138 let Inst{9-5} = src1;
2139 let Inst{4-0} = dst;
2141 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2144 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2145 RegisterClass src1Regtype, Operand src2Regtype,
2146 string asm, SDPatternOperator OpNode>
2147 : I<(outs dstRegtype:$R1),
2148 (ins src1Regtype:$R2, src2Regtype:$R3),
2149 asm, "\t$R1, $R2, $R3", "",
2150 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2151 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2156 let Inst{30} = isSub;
2157 let Inst{29} = setFlags;
2158 let Inst{28-24} = 0b01011;
2159 let Inst{23-21} = 0b001;
2160 let Inst{20-16} = Rm;
2161 let Inst{15-13} = ext{5-3};
2162 let Inst{12-10} = ext{2-0};
2166 let DecoderMethod = "DecodeAddSubERegInstruction";
2169 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2170 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2171 RegisterClass src1Regtype, RegisterClass src2Regtype,
2172 Operand ext_op, string asm>
2173 : I<(outs dstRegtype:$Rd),
2174 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2175 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2176 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2181 let Inst{30} = isSub;
2182 let Inst{29} = setFlags;
2183 let Inst{28-24} = 0b01011;
2184 let Inst{23-21} = 0b001;
2185 let Inst{20-16} = Rm;
2186 let Inst{15} = ext{5};
2187 let Inst{12-10} = ext{2-0};
2191 let DecoderMethod = "DecodeAddSubERegInstruction";
2194 // Aliases for register+register add/subtract.
2195 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2196 RegisterClass src1Regtype, RegisterClass src2Regtype,
2198 : InstAlias<asm#"\t$dst, $src1, $src2",
2199 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2202 multiclass AddSub<bit isSub, string mnemonic, string alias,
2203 SDPatternOperator OpNode = null_frag> {
2204 let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2205 // Add/Subtract immediate
2206 // Increase the weight of the immediate variant to try to match it before
2207 // the extended register variant.
2208 // We used to match the register variant before the immediate when the
2209 // register argument could be implicitly zero-extended.
2210 let AddedComplexity = 6 in
2211 def Wri : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2215 let AddedComplexity = 6 in
2216 def Xri : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2221 // Add/Subtract register - Only used for CodeGen
2222 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2223 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2225 // Add/Subtract shifted register
2226 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2230 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2236 // Add/Subtract extended register
2237 let AddedComplexity = 1, hasSideEffects = 0 in {
2238 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2239 arith_extended_reg32_i32, mnemonic, OpNode> {
2242 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2243 arith_extended_reg32to64_i64, mnemonic, OpNode> {
2248 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2249 arith_extendlsl64, mnemonic> {
2250 // UXTX and SXTX only.
2251 let Inst{14-13} = 0b11;
2255 // add Rd, Rb, -imm -> sub Rd, Rn, imm
2256 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2257 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2258 addsub_shifted_imm32_neg:$imm), 0>;
2259 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2260 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2261 addsub_shifted_imm64_neg:$imm), 0>;
2263 // Register/register aliases with no shift when SP is not used.
2264 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2265 GPR32, GPR32, GPR32, 0>;
2266 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2267 GPR64, GPR64, GPR64, 0>;
2269 // Register/register aliases with no shift when either the destination or
2270 // first source register is SP.
2271 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2272 GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2273 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2274 GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2275 def : AddSubRegAlias<mnemonic,
2276 !cast<Instruction>(NAME#"Xrx64"),
2277 GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2278 def : AddSubRegAlias<mnemonic,
2279 !cast<Instruction>(NAME#"Xrx64"),
2280 GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2283 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2284 string alias, string cmpAlias> {
2285 let isCompare = 1, Defs = [NZCV] in {
2286 // Add/Subtract immediate
2287 def Wri : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2291 def Xri : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2296 // Add/Subtract register
2297 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2298 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2300 // Add/Subtract shifted register
2301 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2305 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2310 // Add/Subtract extended register
2311 let AddedComplexity = 1 in {
2312 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2313 arith_extended_reg32_i32, mnemonic, OpNode> {
2316 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2317 arith_extended_reg32_i64, mnemonic, OpNode> {
2322 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2323 arith_extendlsl64, mnemonic> {
2324 // UXTX and SXTX only.
2325 let Inst{14-13} = 0b11;
2330 // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2331 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2332 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2333 addsub_shifted_imm32_neg:$imm), 0>;
2334 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2335 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2336 addsub_shifted_imm64_neg:$imm), 0>;
2339 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2340 WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2341 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2342 XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2343 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2344 WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2345 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2346 XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2347 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2348 XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2349 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2350 WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2351 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2352 XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2354 // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2355 def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2356 WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2357 def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2358 XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2360 // Compare shorthands
2361 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2362 WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2363 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2364 XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2365 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2366 WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2367 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2368 XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2370 // Register/register aliases with no shift when SP is not used.
2371 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2372 GPR32, GPR32, GPR32, 0>;
2373 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2374 GPR64, GPR64, GPR64, 0>;
2376 // Register/register aliases with no shift when the first source register
2378 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2379 GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2380 def : AddSubRegAlias<mnemonic,
2381 !cast<Instruction>(NAME#"Xrx64"),
2382 GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2385 class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2387 isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2388 (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2389 (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2393 let Inst{23-22} = 0b10;
2394 let Inst{21-16} = imm6;
2395 let Inst{15-14} = 0b00;
2396 let Inst{13-10} = imm4;
2397 let Unpredictable{15-14} = 0b11;
2400 class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2401 : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2403 let Inst{29} = setsFlags;
2409 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2411 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2413 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2415 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2416 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2417 Sched<[WriteExtr, ReadExtrHi]> {
2423 let Inst{30-23} = 0b00100111;
2425 let Inst{20-16} = Rm;
2426 let Inst{15-10} = imm;
2431 multiclass ExtractImm<string asm> {
2432 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2434 (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2437 // imm<5> must be zero.
2440 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2442 (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2453 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2454 class BaseBitfieldImm<bits<2> opc,
2455 RegisterClass regtype, Operand imm_type, string asm>
2456 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2457 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2458 Sched<[WriteIS, ReadI]> {
2464 let Inst{30-29} = opc;
2465 let Inst{28-23} = 0b100110;
2466 let Inst{21-16} = immr;
2467 let Inst{15-10} = imms;
2472 multiclass BitfieldImm<bits<2> opc, string asm> {
2473 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2476 // imms<5> and immr<5> must be zero, else ReservedValue().
2480 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2486 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2487 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2488 RegisterClass regtype, Operand imm_type, string asm>
2489 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2491 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2492 Sched<[WriteIS, ReadI]> {
2498 let Inst{30-29} = opc;
2499 let Inst{28-23} = 0b100110;
2500 let Inst{21-16} = immr;
2501 let Inst{15-10} = imms;
2506 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2507 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2510 // imms<5> and immr<5> must be zero, else ReservedValue().
2514 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2524 // Logical (immediate)
2525 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2526 RegisterClass sregtype, Operand imm_type, string asm,
2528 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2529 asm, "\t$Rd, $Rn, $imm", "", pattern>,
2530 Sched<[WriteI, ReadI]> {
2534 let Inst{30-29} = opc;
2535 let Inst{28-23} = 0b100100;
2536 let Inst{22} = imm{12};
2537 let Inst{21-16} = imm{11-6};
2538 let Inst{15-10} = imm{5-0};
2542 let DecoderMethod = "DecodeLogicalImmInstruction";
2545 // Logical (shifted register)
2546 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2547 logical_shifted_reg shifted_regtype, string asm,
2549 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2550 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2551 Sched<[WriteISReg, ReadI, ReadISReg]> {
2552 // The operands are in order to match the 'addr' MI operands, so we
2553 // don't need an encoder method and by-name matching. Just use the default
2554 // in-order handling. Since we're using by-order, make sure the names
2560 let Inst{30-29} = opc;
2561 let Inst{28-24} = 0b01010;
2562 let Inst{23-22} = shift{7-6};
2564 let Inst{20-16} = src2;
2565 let Inst{15-10} = shift{5-0};
2566 let Inst{9-5} = src1;
2567 let Inst{4-0} = dst;
2569 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2572 // Aliases for register+register logical instructions.
2573 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2574 : InstAlias<asm#"\t$dst, $src1, $src2",
2575 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2577 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2579 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2580 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2581 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2582 logical_imm32:$imm))]> {
2584 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2586 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2587 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2588 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2589 logical_imm64:$imm))]> {
2593 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2594 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2595 logical_imm32_not:$imm), 0>;
2596 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2597 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2598 logical_imm64_not:$imm), 0>;
2601 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2603 let isCompare = 1, Defs = [NZCV] in {
2604 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2605 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2607 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2609 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2610 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2613 } // end Defs = [NZCV]
2615 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2616 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2617 logical_imm32_not:$imm), 0>;
2618 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2619 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2620 logical_imm64_not:$imm), 0>;
2623 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2624 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2625 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2626 Sched<[WriteI, ReadI, ReadI]>;
2628 // Split from LogicalImm as not all instructions have both.
2629 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2630 SDPatternOperator OpNode> {
2631 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2632 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2633 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2636 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2637 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2638 logical_shifted_reg32:$Rm))]> {
2641 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2642 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2643 logical_shifted_reg64:$Rm))]> {
2647 def : LogicalRegAlias<mnemonic,
2648 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2649 def : LogicalRegAlias<mnemonic,
2650 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2653 // Split from LogicalReg to allow setting NZCV Defs
2654 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2655 SDPatternOperator OpNode = null_frag> {
2656 let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2657 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2658 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2660 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2661 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2664 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2665 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2670 def : LogicalRegAlias<mnemonic,
2671 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2672 def : LogicalRegAlias<mnemonic,
2673 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2677 // Conditionally set flags
2680 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2681 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2682 string mnemonic, SDNode OpNode>
2683 : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2684 mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2685 [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2686 (i32 imm:$cond), NZCV))]>,
2687 Sched<[WriteI, ReadI]> {
2697 let Inst{29-21} = 0b111010010;
2698 let Inst{20-16} = imm;
2699 let Inst{15-12} = cond;
2700 let Inst{11-10} = 0b10;
2703 let Inst{3-0} = nzcv;
2706 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2707 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2709 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2710 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2711 [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2712 (i32 imm:$cond), NZCV))]>,
2713 Sched<[WriteI, ReadI, ReadI]> {
2723 let Inst{29-21} = 0b111010010;
2724 let Inst{20-16} = Rm;
2725 let Inst{15-12} = cond;
2726 let Inst{11-10} = 0b00;
2729 let Inst{3-0} = nzcv;
2732 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2733 // immediate operand variants
2734 def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2737 def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2740 // register operand variants
2741 def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2744 def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2750 // Conditional select
2753 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2754 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2755 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2757 (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2758 Sched<[WriteI, ReadI, ReadI]> {
2767 let Inst{29-21} = 0b011010100;
2768 let Inst{20-16} = Rm;
2769 let Inst{15-12} = cond;
2770 let Inst{11-10} = op2;
2775 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2776 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2779 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2784 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2786 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2787 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2789 (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2790 (i32 imm:$cond), NZCV))]>,
2791 Sched<[WriteI, ReadI, ReadI]> {
2800 let Inst{29-21} = 0b011010100;
2801 let Inst{20-16} = Rm;
2802 let Inst{15-12} = cond;
2803 let Inst{11-10} = op2;
2808 def inv_cond_XFORM : SDNodeXForm<imm, [{
2809 AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2810 return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2814 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2815 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2818 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2822 def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2823 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2824 (inv_cond_XFORM imm:$cond))>;
2826 def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2827 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2828 (inv_cond_XFORM imm:$cond))>;
2832 // Special Mask Value
2834 def maski8_or_more : Operand<i32>,
2835 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2837 def maski16_or_more : Operand<i32>,
2838 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2846 // (unsigned immediate)
2847 // Indexed for 8-bit registers. offset is in range [0,4095].
2848 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2849 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2850 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2851 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2852 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2854 def gi_am_indexed8 :
2855 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2856 GIComplexPatternEquiv<am_indexed8>;
2857 def gi_am_indexed16 :
2858 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2859 GIComplexPatternEquiv<am_indexed16>;
2860 def gi_am_indexed32 :
2861 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2862 GIComplexPatternEquiv<am_indexed32>;
2863 def gi_am_indexed64 :
2864 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2865 GIComplexPatternEquiv<am_indexed64>;
2866 def gi_am_indexed128 :
2867 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2868 GIComplexPatternEquiv<am_indexed128>;
2870 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2871 let Name = "UImm12Offset" # Scale;
2872 let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2873 let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2874 let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2877 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2878 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2879 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2880 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2881 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2883 class uimm12_scaled<int Scale> : Operand<i64> {
2884 let ParserMatchClass
2885 = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2887 = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2888 let PrintMethod = "printUImm12Offset<" # Scale # ">";
2891 def uimm12s1 : uimm12_scaled<1>;
2892 def uimm12s2 : uimm12_scaled<2>;
2893 def uimm12s4 : uimm12_scaled<4>;
2894 def uimm12s8 : uimm12_scaled<8>;
2895 def uimm12s16 : uimm12_scaled<16>;
2897 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2898 string asm, list<dag> pattern>
2899 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2905 let Inst{31-30} = sz;
2906 let Inst{29-27} = 0b111;
2908 let Inst{25-24} = 0b01;
2909 let Inst{23-22} = opc;
2910 let Inst{21-10} = offset;
2914 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2917 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2918 Operand indextype, string asm, list<dag> pattern> {
2919 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2920 def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2921 (ins GPR64sp:$Rn, indextype:$offset),
2925 def : InstAlias<asm # "\t$Rt, [$Rn]",
2926 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2929 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2930 Operand indextype, string asm, list<dag> pattern> {
2931 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2932 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2933 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2937 def : InstAlias<asm # "\t$Rt, [$Rn]",
2938 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2941 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2942 // substitute zero-registers automatically.
2944 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2946 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2947 Operand indextype, string asm, list<dag> pattern> {
2948 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2949 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2950 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2954 def : InstAlias<asm # "\t$Rt, [$Rn]",
2955 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2958 def PrefetchOperand : AsmOperandClass {
2959 let Name = "Prefetch";
2960 let ParserMethod = "tryParsePrefetch";
2962 def prfop : Operand<i32> {
2963 let PrintMethod = "printPrefetchOp";
2964 let ParserMatchClass = PrefetchOperand;
2967 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2968 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2969 : BaseLoadStoreUI<sz, V, opc,
2970 (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2978 // Load literal address: 19-bit immediate. The low two bits of the target
2979 // offset are implied zero and so are not part of the immediate.
2980 def am_ldrlit : Operand<iPTR> {
2981 let EncoderMethod = "getLoadLiteralOpValue";
2982 let DecoderMethod = "DecodePCRelLabel19";
2983 let PrintMethod = "printAlignedLabel";
2984 let ParserMatchClass = PCRelLabel19Operand;
2985 let OperandType = "OPERAND_PCREL";
2988 let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
2989 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
2990 : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2991 asm, "\t$Rt, $label", "", pat>,
2995 let Inst{31-30} = opc;
2996 let Inst{29-27} = 0b011;
2998 let Inst{25-24} = 0b00;
2999 let Inst{23-5} = label;
3003 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3004 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3005 : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3006 asm, "\t$Rt, $label", "", pat>,
3010 let Inst{31-30} = opc;
3011 let Inst{29-27} = 0b011;
3013 let Inst{25-24} = 0b00;
3014 let Inst{23-5} = label;
3019 // Load/store register offset
3022 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3023 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3024 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3025 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3026 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3028 def gi_ro_Xindexed8 :
3029 GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3030 GIComplexPatternEquiv<ro_Xindexed8>;
3031 def gi_ro_Xindexed16 :
3032 GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3033 GIComplexPatternEquiv<ro_Xindexed16>;
3034 def gi_ro_Xindexed32 :
3035 GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3036 GIComplexPatternEquiv<ro_Xindexed32>;
3037 def gi_ro_Xindexed64 :
3038 GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3039 GIComplexPatternEquiv<ro_Xindexed64>;
3040 def gi_ro_Xindexed128 :
3041 GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3042 GIComplexPatternEquiv<ro_Xindexed128>;
3044 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3045 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3046 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3047 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3048 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3050 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3051 let Name = "Mem" # Reg # "Extend" # Width;
3052 let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3053 let RenderMethod = "addMemExtendOperands";
3054 let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3057 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3058 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3059 // the trivial shift.
3060 let RenderMethod = "addMemExtend8Operands";
3062 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3063 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3064 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3065 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3067 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3068 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3069 // the trivial shift.
3070 let RenderMethod = "addMemExtend8Operands";
3072 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3073 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3074 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3075 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3077 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3079 let ParserMatchClass = ParserClass;
3080 let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3081 let DecoderMethod = "DecodeMemExtend";
3082 let EncoderMethod = "getMemExtendOpValue";
3083 let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3086 def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>;
3087 def ro_Wextend16 : ro_extend<MemWExtend16Operand, "w", 16>;
3088 def ro_Wextend32 : ro_extend<MemWExtend32Operand, "w", 32>;
3089 def ro_Wextend64 : ro_extend<MemWExtend64Operand, "w", 64>;
3090 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3092 def ro_Xextend8 : ro_extend<MemXExtend8Operand, "x", 8>;
3093 def ro_Xextend16 : ro_extend<MemXExtend16Operand, "x", 16>;
3094 def ro_Xextend32 : ro_extend<MemXExtend32Operand, "x", 32>;
3095 def ro_Xextend64 : ro_extend<MemXExtend64Operand, "x", 64>;
3096 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3098 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3099 Operand wextend, Operand xextend> {
3100 // CodeGen-level pattern covering the entire addressing mode.
3101 ComplexPattern Wpat = windex;
3102 ComplexPattern Xpat = xindex;
3104 // Asm-level Operand covering the valid "uxtw #3" style syntax.
3105 Operand Wext = wextend;
3106 Operand Xext = xextend;
3109 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3110 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3111 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3112 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3113 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3116 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3117 string asm, dag ins, dag outs, list<dag> pat>
3118 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3123 let Inst{31-30} = sz;
3124 let Inst{29-27} = 0b111;
3126 let Inst{25-24} = 0b00;
3127 let Inst{23-22} = opc;
3129 let Inst{20-16} = Rm;
3130 let Inst{15} = extend{1}; // sign extend Rm?
3132 let Inst{12} = extend{0}; // do shift?
3133 let Inst{11-10} = 0b10;
3138 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3139 : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3140 (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3142 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3143 string asm, ValueType Ty, SDPatternOperator loadop> {
3144 let AddedComplexity = 10 in
3145 def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3147 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3148 [(set (Ty regtype:$Rt),
3149 (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3150 ro_Wextend8:$extend)))]>,
3151 Sched<[WriteLDIdx, ReadAdrBase]> {
3155 let AddedComplexity = 10 in
3156 def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3158 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3159 [(set (Ty regtype:$Rt),
3160 (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3161 ro_Xextend8:$extend)))]>,
3162 Sched<[WriteLDIdx, ReadAdrBase]> {
3166 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3169 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3170 string asm, ValueType Ty, SDPatternOperator storeop> {
3171 let AddedComplexity = 10 in
3172 def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3173 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3174 [(storeop (Ty regtype:$Rt),
3175 (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3176 ro_Wextend8:$extend))]>,
3177 Sched<[WriteSTIdx, ReadAdrBase]> {
3181 let AddedComplexity = 10 in
3182 def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3183 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3184 [(storeop (Ty regtype:$Rt),
3185 (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3186 ro_Xextend8:$extend))]>,
3187 Sched<[WriteSTIdx, ReadAdrBase]> {
3191 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3194 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3195 string asm, dag ins, dag outs, list<dag> pat>
3196 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3201 let Inst{31-30} = sz;
3202 let Inst{29-27} = 0b111;
3204 let Inst{25-24} = 0b00;
3205 let Inst{23-22} = opc;
3207 let Inst{20-16} = Rm;
3208 let Inst{15} = extend{1}; // sign extend Rm?
3210 let Inst{12} = extend{0}; // do shift?
3211 let Inst{11-10} = 0b10;
3216 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3217 string asm, ValueType Ty, SDPatternOperator loadop> {
3218 let AddedComplexity = 10 in
3219 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3220 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3221 [(set (Ty regtype:$Rt),
3222 (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3223 ro_Wextend16:$extend)))]>,
3224 Sched<[WriteLDIdx, ReadAdrBase]> {
3228 let AddedComplexity = 10 in
3229 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3230 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3231 [(set (Ty regtype:$Rt),
3232 (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3233 ro_Xextend16:$extend)))]>,
3234 Sched<[WriteLDIdx, ReadAdrBase]> {
3238 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3241 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3242 string asm, ValueType Ty, SDPatternOperator storeop> {
3243 let AddedComplexity = 10 in
3244 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3245 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3246 [(storeop (Ty regtype:$Rt),
3247 (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3248 ro_Wextend16:$extend))]>,
3249 Sched<[WriteSTIdx, ReadAdrBase]> {
3253 let AddedComplexity = 10 in
3254 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3255 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3256 [(storeop (Ty regtype:$Rt),
3257 (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3258 ro_Xextend16:$extend))]>,
3259 Sched<[WriteSTIdx, ReadAdrBase]> {
3263 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3266 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3267 string asm, dag ins, dag outs, list<dag> pat>
3268 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3273 let Inst{31-30} = sz;
3274 let Inst{29-27} = 0b111;
3276 let Inst{25-24} = 0b00;
3277 let Inst{23-22} = opc;
3279 let Inst{20-16} = Rm;
3280 let Inst{15} = extend{1}; // sign extend Rm?
3282 let Inst{12} = extend{0}; // do shift?
3283 let Inst{11-10} = 0b10;
3288 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3289 string asm, ValueType Ty, SDPatternOperator loadop> {
3290 let AddedComplexity = 10 in
3291 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3292 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3293 [(set (Ty regtype:$Rt),
3294 (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3295 ro_Wextend32:$extend)))]>,
3296 Sched<[WriteLDIdx, ReadAdrBase]> {
3300 let AddedComplexity = 10 in
3301 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3302 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3303 [(set (Ty regtype:$Rt),
3304 (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3305 ro_Xextend32:$extend)))]>,
3306 Sched<[WriteLDIdx, ReadAdrBase]> {
3310 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3313 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3314 string asm, ValueType Ty, SDPatternOperator storeop> {
3315 let AddedComplexity = 10 in
3316 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3317 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3318 [(storeop (Ty regtype:$Rt),
3319 (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3320 ro_Wextend32:$extend))]>,
3321 Sched<[WriteSTIdx, ReadAdrBase]> {
3325 let AddedComplexity = 10 in
3326 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3327 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3328 [(storeop (Ty regtype:$Rt),
3329 (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3330 ro_Xextend32:$extend))]>,
3331 Sched<[WriteSTIdx, ReadAdrBase]> {
3335 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3338 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3339 string asm, dag ins, dag outs, list<dag> pat>
3340 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3345 let Inst{31-30} = sz;
3346 let Inst{29-27} = 0b111;
3348 let Inst{25-24} = 0b00;
3349 let Inst{23-22} = opc;
3351 let Inst{20-16} = Rm;
3352 let Inst{15} = extend{1}; // sign extend Rm?
3354 let Inst{12} = extend{0}; // do shift?
3355 let Inst{11-10} = 0b10;
3360 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3361 string asm, ValueType Ty, SDPatternOperator loadop> {
3362 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3363 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3364 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3365 [(set (Ty regtype:$Rt),
3366 (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3367 ro_Wextend64:$extend)))]>,
3368 Sched<[WriteLDIdx, ReadAdrBase]> {
3372 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3373 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3374 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3375 [(set (Ty regtype:$Rt),
3376 (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3377 ro_Xextend64:$extend)))]>,
3378 Sched<[WriteLDIdx, ReadAdrBase]> {
3382 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3385 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3386 string asm, ValueType Ty, SDPatternOperator storeop> {
3387 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3388 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3389 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3390 [(storeop (Ty regtype:$Rt),
3391 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3392 ro_Wextend64:$extend))]>,
3393 Sched<[WriteSTIdx, ReadAdrBase]> {
3397 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3398 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3399 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3400 [(storeop (Ty regtype:$Rt),
3401 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3402 ro_Xextend64:$extend))]>,
3403 Sched<[WriteSTIdx, ReadAdrBase]> {
3407 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3410 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3411 string asm, dag ins, dag outs, list<dag> pat>
3412 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3417 let Inst{31-30} = sz;
3418 let Inst{29-27} = 0b111;
3420 let Inst{25-24} = 0b00;
3421 let Inst{23-22} = opc;
3423 let Inst{20-16} = Rm;
3424 let Inst{15} = extend{1}; // sign extend Rm?
3426 let Inst{12} = extend{0}; // do shift?
3427 let Inst{11-10} = 0b10;
3432 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3433 string asm, ValueType Ty, SDPatternOperator loadop> {
3434 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3435 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3436 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3437 [(set (Ty regtype:$Rt),
3438 (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3439 ro_Wextend128:$extend)))]>,
3440 Sched<[WriteLDIdx, ReadAdrBase]> {
3444 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3445 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3446 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3447 [(set (Ty regtype:$Rt),
3448 (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3449 ro_Xextend128:$extend)))]>,
3450 Sched<[WriteLDIdx, ReadAdrBase]> {
3454 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3457 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3458 string asm, ValueType Ty, SDPatternOperator storeop> {
3459 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3460 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3461 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3463 Sched<[WriteSTIdx, ReadAdrBase]> {
3467 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3468 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3469 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3471 Sched<[WriteSTIdx, ReadAdrBase]> {
3475 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3478 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3479 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3480 string asm, list<dag> pat>
3481 : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3487 let Inst{31-30} = sz;
3488 let Inst{29-27} = 0b111;
3490 let Inst{25-24} = 0b00;
3491 let Inst{23-22} = opc;
3493 let Inst{20-16} = Rm;
3494 let Inst{15} = extend{1}; // sign extend Rm?
3496 let Inst{12} = extend{0}; // do shift?
3497 let Inst{11-10} = 0b10;
3502 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3503 def roW : BasePrefetchRO<sz, V, opc, (outs),
3504 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3505 asm, [(AArch64Prefetch imm:$Rt,
3506 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3507 ro_Wextend64:$extend))]> {
3511 def roX : BasePrefetchRO<sz, V, opc, (outs),
3512 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3513 asm, [(AArch64Prefetch imm:$Rt,
3514 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3515 ro_Xextend64:$extend))]> {
3519 def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3520 (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3521 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3525 // Load/store unscaled immediate
3528 def am_unscaled8 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3529 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3530 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3531 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3532 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3534 def gi_am_unscaled8 :
3535 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3536 GIComplexPatternEquiv<am_unscaled8>;
3537 def gi_am_unscaled16 :
3538 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3539 GIComplexPatternEquiv<am_unscaled16>;
3540 def gi_am_unscaled32 :
3541 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3542 GIComplexPatternEquiv<am_unscaled32>;
3543 def gi_am_unscaled64 :
3544 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3545 GIComplexPatternEquiv<am_unscaled64>;
3546 def gi_am_unscaled128 :
3547 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3548 GIComplexPatternEquiv<am_unscaled128>;
3551 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3552 string asm, list<dag> pattern>
3553 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3557 let Inst{31-30} = sz;
3558 let Inst{29-27} = 0b111;
3560 let Inst{25-24} = 0b00;
3561 let Inst{23-22} = opc;
3563 let Inst{20-12} = offset;
3564 let Inst{11-10} = 0b00;
3568 let DecoderMethod = "DecodeSignedLdStInstruction";
3571 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3572 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3573 RegisterOperand regtype > {
3574 def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3575 (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3580 def : InstAlias<asm # "\t$Rt, [$Rn]",
3581 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3584 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3585 RegisterOperand regtype > {
3586 def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3587 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3593 def : InstAlias<asm # "\t$Rt, [$Rn]",
3594 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3597 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3598 string asm, list<dag> pattern> {
3599 let AddedComplexity = 1 in // try this before LoadUI
3600 def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3601 (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3604 def : InstAlias<asm # "\t$Rt, [$Rn]",
3605 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3608 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3609 string asm, list<dag> pattern> {
3610 let AddedComplexity = 1 in // try this before StoreUI
3611 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3612 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3616 def : InstAlias<asm # "\t$Rt, [$Rn]",
3617 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3620 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3622 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3623 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3624 (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3628 def : InstAlias<asm # "\t$Rt, [$Rn]",
3629 (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3633 // Load/store unscaled immediate, unprivileged
3636 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3637 dag oops, dag iops, string asm>
3638 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3642 let Inst{31-30} = sz;
3643 let Inst{29-27} = 0b111;
3645 let Inst{25-24} = 0b00;
3646 let Inst{23-22} = opc;
3648 let Inst{20-12} = offset;
3649 let Inst{11-10} = 0b10;
3653 let DecoderMethod = "DecodeSignedLdStInstruction";
3656 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3657 RegisterClass regtype, string asm> {
3658 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3659 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3660 (ins GPR64sp:$Rn, simm9:$offset), asm>,
3663 def : InstAlias<asm # "\t$Rt, [$Rn]",
3664 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3667 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3668 RegisterClass regtype, string asm> {
3669 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3670 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3671 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3675 def : InstAlias<asm # "\t$Rt, [$Rn]",
3676 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3680 // Load/store pre-indexed
3683 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3684 string asm, string cstr, list<dag> pat>
3685 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3689 let Inst{31-30} = sz;
3690 let Inst{29-27} = 0b111;
3692 let Inst{25-24} = 0;
3693 let Inst{23-22} = opc;
3695 let Inst{20-12} = offset;
3696 let Inst{11-10} = 0b11;
3700 let DecoderMethod = "DecodeSignedLdStInstruction";
3703 let hasSideEffects = 0 in {
3704 let mayStore = 0, mayLoad = 1 in
3705 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3707 : BaseLoadStorePreIdx<sz, V, opc,
3708 (outs GPR64sp:$wback, regtype:$Rt),
3709 (ins GPR64sp:$Rn, simm9:$offset), asm,
3710 "$Rn = $wback,@earlyclobber $wback", []>,
3711 Sched<[WriteLD, WriteAdr]>;
3713 let mayStore = 1, mayLoad = 0 in
3714 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3715 string asm, SDPatternOperator storeop, ValueType Ty>
3716 : BaseLoadStorePreIdx<sz, V, opc,
3717 (outs GPR64sp:$wback),
3718 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3719 asm, "$Rn = $wback,@earlyclobber $wback",
3720 [(set GPR64sp:$wback,
3721 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3722 Sched<[WriteAdr, WriteST]>;
3723 } // hasSideEffects = 0
3726 // Load/store post-indexed
3729 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3730 string asm, string cstr, list<dag> pat>
3731 : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3735 let Inst{31-30} = sz;
3736 let Inst{29-27} = 0b111;
3738 let Inst{25-24} = 0b00;
3739 let Inst{23-22} = opc;
3741 let Inst{20-12} = offset;
3742 let Inst{11-10} = 0b01;
3746 let DecoderMethod = "DecodeSignedLdStInstruction";
3749 let hasSideEffects = 0 in {
3750 let mayStore = 0, mayLoad = 1 in
3751 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3753 : BaseLoadStorePostIdx<sz, V, opc,
3754 (outs GPR64sp:$wback, regtype:$Rt),
3755 (ins GPR64sp:$Rn, simm9:$offset),
3756 asm, "$Rn = $wback,@earlyclobber $wback", []>,
3757 Sched<[WriteLD, WriteAdr]>;
3759 let mayStore = 1, mayLoad = 0 in
3760 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3761 string asm, SDPatternOperator storeop, ValueType Ty>
3762 : BaseLoadStorePostIdx<sz, V, opc,
3763 (outs GPR64sp:$wback),
3764 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3765 asm, "$Rn = $wback,@earlyclobber $wback",
3766 [(set GPR64sp:$wback,
3767 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3768 Sched<[WriteAdr, WriteST]>;
3769 } // hasSideEffects = 0
3776 // (indexed, offset)
3778 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3780 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3785 let Inst{31-30} = opc;
3786 let Inst{29-27} = 0b101;
3788 let Inst{25-23} = 0b010;
3790 let Inst{21-15} = offset;
3791 let Inst{14-10} = Rt2;
3795 let DecoderMethod = "DecodePairLdStInstruction";
3798 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3799 Operand indextype, string asm> {
3800 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3801 def i : BaseLoadStorePairOffset<opc, V, 1,
3802 (outs regtype:$Rt, regtype:$Rt2),
3803 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3804 Sched<[WriteLD, WriteLDHi]>;
3806 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3807 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3812 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3813 Operand indextype, string asm> {
3814 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3815 def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3816 (ins regtype:$Rt, regtype:$Rt2,
3817 GPR64sp:$Rn, indextype:$offset),
3821 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3822 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3827 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3829 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3834 let Inst{31-30} = opc;
3835 let Inst{29-27} = 0b101;
3837 let Inst{25-23} = 0b011;
3839 let Inst{21-15} = offset;
3840 let Inst{14-10} = Rt2;
3844 let DecoderMethod = "DecodePairLdStInstruction";
3847 let hasSideEffects = 0 in {
3848 let mayStore = 0, mayLoad = 1 in
3849 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3850 Operand indextype, string asm>
3851 : BaseLoadStorePairPreIdx<opc, V, 1,
3852 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3853 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3854 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3856 let mayStore = 1, mayLoad = 0 in
3857 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3858 Operand indextype, string asm>
3859 : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3860 (ins regtype:$Rt, regtype:$Rt2,
3861 GPR64sp:$Rn, indextype:$offset),
3863 Sched<[WriteAdr, WriteSTP]>;
3864 } // hasSideEffects = 0
3868 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3870 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3875 let Inst{31-30} = opc;
3876 let Inst{29-27} = 0b101;
3878 let Inst{25-23} = 0b001;
3880 let Inst{21-15} = offset;
3881 let Inst{14-10} = Rt2;
3885 let DecoderMethod = "DecodePairLdStInstruction";
3888 let hasSideEffects = 0 in {
3889 let mayStore = 0, mayLoad = 1 in
3890 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3891 Operand idxtype, string asm>
3892 : BaseLoadStorePairPostIdx<opc, V, 1,
3893 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3894 (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3895 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3897 let mayStore = 1, mayLoad = 0 in
3898 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3899 Operand idxtype, string asm>
3900 : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3901 (ins regtype:$Rt, regtype:$Rt2,
3902 GPR64sp:$Rn, idxtype:$offset),
3904 Sched<[WriteAdr, WriteSTP]>;
3905 } // hasSideEffects = 0
3909 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3911 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3916 let Inst{31-30} = opc;
3917 let Inst{29-27} = 0b101;
3919 let Inst{25-23} = 0b000;
3921 let Inst{21-15} = offset;
3922 let Inst{14-10} = Rt2;
3926 let DecoderMethod = "DecodePairLdStInstruction";
3929 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3930 Operand indextype, string asm> {
3931 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3932 def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3933 (outs regtype:$Rt, regtype:$Rt2),
3934 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3935 Sched<[WriteLD, WriteLDHi]>;
3938 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3939 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3943 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3944 Operand indextype, string asm> {
3945 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3946 def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3947 (ins regtype:$Rt, regtype:$Rt2,
3948 GPR64sp:$Rn, indextype:$offset),
3952 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3953 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3958 // Load/store exclusive
3961 // True exclusive operations write to and/or read from the system's exclusive
3962 // monitors, which as far as a compiler is concerned can be modelled as a
3963 // random shared memory address. Hence LoadExclusive mayStore.
3965 // Since these instructions have the undefined register bits set to 1 in
3966 // their canonical form, we need a post encoder method to set those bits
3967 // to 1 when encoding these instructions. We do this using the
3968 // fixLoadStoreExclusive function. This function has template parameters:
3970 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3972 // hasRs indicates that the instruction uses the Rs field, so we won't set
3973 // it to 1 (and the same for Rt2). We don't need template parameters for
3974 // the other register fields since Rt and Rn are always used.
3976 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3977 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3978 dag oops, dag iops, string asm, string operands>
3979 : I<oops, iops, asm, operands, "", []> {
3980 let Inst{31-30} = sz;
3981 let Inst{29-24} = 0b001000;
3987 let DecoderMethod = "DecodeExclusiveLdStInstruction";
3990 // Neither Rs nor Rt2 operands.
3991 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3992 dag oops, dag iops, string asm, string operands>
3993 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3996 let Inst{20-16} = 0b11111;
3997 let Unpredictable{20-16} = 0b11111;
3998 let Inst{14-10} = 0b11111;
3999 let Unpredictable{14-10} = 0b11111;
4003 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4006 // Simple load acquires don't set the exclusive monitor
4007 let mayLoad = 1, mayStore = 0 in
4008 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4009 RegisterClass regtype, string asm>
4010 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4011 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4014 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4015 RegisterClass regtype, string asm>
4016 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4017 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4020 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4021 RegisterClass regtype, string asm>
4022 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4023 (outs regtype:$Rt, regtype:$Rt2),
4024 (ins GPR64sp0:$Rn), asm,
4025 "\t$Rt, $Rt2, [$Rn]">,
4026 Sched<[WriteLD, WriteLDHi]> {
4030 let Inst{14-10} = Rt2;
4034 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4037 // Simple store release operations do not check the exclusive monitor.
4038 let mayLoad = 0, mayStore = 1 in
4039 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4040 RegisterClass regtype, string asm>
4041 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4042 (ins regtype:$Rt, GPR64sp0:$Rn),
4043 asm, "\t$Rt, [$Rn]">,
4046 let mayLoad = 1, mayStore = 1 in
4047 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4048 RegisterClass regtype, string asm>
4049 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4050 (ins regtype:$Rt, GPR64sp0:$Rn),
4051 asm, "\t$Ws, $Rt, [$Rn]">,
4056 let Inst{20-16} = Ws;
4060 let Constraints = "@earlyclobber $Ws";
4061 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4064 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4065 RegisterClass regtype, string asm>
4066 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4068 (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4069 asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4075 let Inst{20-16} = Ws;
4076 let Inst{14-10} = Rt2;
4080 let Constraints = "@earlyclobber $Ws";
4083 // Armv8.5-A Memory Tagging Extension
4084 class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4085 string asm_opnds, string cstr, dag oops, dag iops>
4086 : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4090 let Inst{31-24} = 0b11011001;
4091 let Inst{23-22} = opc1;
4093 // Inst{20-12} defined by subclass
4094 let Inst{11-10} = opc2;
4096 // Inst{4-0} defined by subclass
4099 class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4101 : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4105 let Inst{20-12} = 0b000000000;
4111 class MemTagLoad<string asm_insn, string asm_opnds>
4112 : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4113 (outs GPR64:$wback),
4114 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4118 let Inst{20-12} = offset;
4124 class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4125 string asm_opnds, string cstr, dag oops, dag iops>
4126 : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4130 let Inst{20-12} = offset;
4136 multiclass MemTagStore<bits<2> opc1, string insn> {
4138 BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4139 (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4141 BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4143 (outs GPR64sp:$wback),
4144 (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4146 BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4148 (outs GPR64sp:$wback),
4149 (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4151 def : InstAlias<insn # "\t$Rt, [$Rn]",
4152 (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4156 // Exception generation
4159 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4160 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4161 : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4164 let Inst{31-24} = 0b11010100;
4165 let Inst{23-21} = op1;
4166 let Inst{20-5} = imm;
4167 let Inst{4-2} = 0b000;
4172 // UDF : Permanently UNDEFINED instructions. Format: Opc = 0x0000, 16 bit imm.
4174 let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4175 class UDFType<bits<16> opc, string asm>
4176 : I<(outs), (ins uimm16:$imm),
4177 asm, "\t$imm", "", []>,
4180 let Inst{31-16} = opc;
4181 let Inst{15-0} = imm;
4184 let Predicates = [HasFPARMv8] in {
4187 // Floating point to integer conversion
4190 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4191 RegisterClass srcType, RegisterClass dstType,
4192 string asm, list<dag> pattern>
4193 : I<(outs dstType:$Rd), (ins srcType:$Rn),
4194 asm, "\t$Rd, $Rn", "", pattern>,
4195 Sched<[WriteFCvt]> {
4198 let Inst{30-29} = 0b00;
4199 let Inst{28-24} = 0b11110;
4200 let Inst{23-22} = type;
4202 let Inst{20-19} = rmode;
4203 let Inst{18-16} = opcode;
4204 let Inst{15-10} = 0;
4209 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4210 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4211 RegisterClass srcType, RegisterClass dstType,
4212 Operand immType, string asm, list<dag> pattern>
4213 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4214 asm, "\t$Rd, $Rn, $scale", "", pattern>,
4215 Sched<[WriteFCvt]> {
4219 let Inst{30-29} = 0b00;
4220 let Inst{28-24} = 0b11110;
4221 let Inst{23-22} = type;
4223 let Inst{20-19} = rmode;
4224 let Inst{18-16} = opcode;
4225 let Inst{15-10} = scale;
4230 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4231 SDPatternOperator OpN> {
4232 // Unscaled half-precision to 32-bit
4233 def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4234 [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4235 let Inst{31} = 0; // 32-bit GPR flag
4236 let Predicates = [HasFullFP16];
4239 // Unscaled half-precision to 64-bit
4240 def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4241 [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4242 let Inst{31} = 1; // 64-bit GPR flag
4243 let Predicates = [HasFullFP16];
4246 // Unscaled single-precision to 32-bit
4247 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4248 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4249 let Inst{31} = 0; // 32-bit GPR flag
4252 // Unscaled single-precision to 64-bit
4253 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4254 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4255 let Inst{31} = 1; // 64-bit GPR flag
4258 // Unscaled double-precision to 32-bit
4259 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4260 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4261 let Inst{31} = 0; // 32-bit GPR flag
4264 // Unscaled double-precision to 64-bit
4265 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4266 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4267 let Inst{31} = 1; // 64-bit GPR flag
4271 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4272 SDPatternOperator OpN> {
4273 // Scaled half-precision to 32-bit
4274 def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4275 fixedpoint_f16_i32, asm,
4276 [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4277 fixedpoint_f16_i32:$scale)))]> {
4278 let Inst{31} = 0; // 32-bit GPR flag
4280 let Predicates = [HasFullFP16];
4283 // Scaled half-precision to 64-bit
4284 def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4285 fixedpoint_f16_i64, asm,
4286 [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4287 fixedpoint_f16_i64:$scale)))]> {
4288 let Inst{31} = 1; // 64-bit GPR flag
4289 let Predicates = [HasFullFP16];
4292 // Scaled single-precision to 32-bit
4293 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4294 fixedpoint_f32_i32, asm,
4295 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4296 fixedpoint_f32_i32:$scale)))]> {
4297 let Inst{31} = 0; // 32-bit GPR flag
4301 // Scaled single-precision to 64-bit
4302 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4303 fixedpoint_f32_i64, asm,
4304 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4305 fixedpoint_f32_i64:$scale)))]> {
4306 let Inst{31} = 1; // 64-bit GPR flag
4309 // Scaled double-precision to 32-bit
4310 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4311 fixedpoint_f64_i32, asm,
4312 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4313 fixedpoint_f64_i32:$scale)))]> {
4314 let Inst{31} = 0; // 32-bit GPR flag
4318 // Scaled double-precision to 64-bit
4319 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4320 fixedpoint_f64_i64, asm,
4321 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4322 fixedpoint_f64_i64:$scale)))]> {
4323 let Inst{31} = 1; // 64-bit GPR flag
4328 // Integer to floating point conversion
4331 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4332 class BaseIntegerToFP<bit isUnsigned,
4333 RegisterClass srcType, RegisterClass dstType,
4334 Operand immType, string asm, list<dag> pattern>
4335 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4336 asm, "\t$Rd, $Rn, $scale", "", pattern>,
4337 Sched<[WriteFCvt]> {
4341 let Inst{30-24} = 0b0011110;
4342 let Inst{21-17} = 0b00001;
4343 let Inst{16} = isUnsigned;
4344 let Inst{15-10} = scale;
4349 class BaseIntegerToFPUnscaled<bit isUnsigned,
4350 RegisterClass srcType, RegisterClass dstType,
4351 ValueType dvt, string asm, SDNode node>
4352 : I<(outs dstType:$Rd), (ins srcType:$Rn),
4353 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4354 Sched<[WriteFCvt]> {
4358 let Inst{30-24} = 0b0011110;
4359 let Inst{21-17} = 0b10001;
4360 let Inst{16} = isUnsigned;
4361 let Inst{15-10} = 0b000000;
4366 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4368 def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4369 let Inst{31} = 0; // 32-bit GPR flag
4370 let Inst{23-22} = 0b11; // 16-bit FPR flag
4371 let Predicates = [HasFullFP16];
4374 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4375 let Inst{31} = 0; // 32-bit GPR flag
4376 let Inst{23-22} = 0b00; // 32-bit FPR flag
4379 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4380 let Inst{31} = 0; // 32-bit GPR flag
4381 let Inst{23-22} = 0b01; // 64-bit FPR flag
4384 def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4385 let Inst{31} = 1; // 64-bit GPR flag
4386 let Inst{23-22} = 0b11; // 16-bit FPR flag
4387 let Predicates = [HasFullFP16];
4390 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4391 let Inst{31} = 1; // 64-bit GPR flag
4392 let Inst{23-22} = 0b00; // 32-bit FPR flag
4395 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4396 let Inst{31} = 1; // 64-bit GPR flag
4397 let Inst{23-22} = 0b01; // 64-bit FPR flag
4401 def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4403 (fdiv (node GPR32:$Rn),
4404 fixedpoint_f16_i32:$scale))]> {
4405 let Inst{31} = 0; // 32-bit GPR flag
4406 let Inst{23-22} = 0b11; // 16-bit FPR flag
4408 let Predicates = [HasFullFP16];
4411 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4413 (fdiv (node GPR32:$Rn),
4414 fixedpoint_f32_i32:$scale))]> {
4415 let Inst{31} = 0; // 32-bit GPR flag
4416 let Inst{23-22} = 0b00; // 32-bit FPR flag
4420 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4422 (fdiv (node GPR32:$Rn),
4423 fixedpoint_f64_i32:$scale))]> {
4424 let Inst{31} = 0; // 32-bit GPR flag
4425 let Inst{23-22} = 0b01; // 64-bit FPR flag
4429 def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4431 (fdiv (node GPR64:$Rn),
4432 fixedpoint_f16_i64:$scale))]> {
4433 let Inst{31} = 1; // 64-bit GPR flag
4434 let Inst{23-22} = 0b11; // 16-bit FPR flag
4435 let Predicates = [HasFullFP16];
4438 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4440 (fdiv (node GPR64:$Rn),
4441 fixedpoint_f32_i64:$scale))]> {
4442 let Inst{31} = 1; // 64-bit GPR flag
4443 let Inst{23-22} = 0b00; // 32-bit FPR flag
4446 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4448 (fdiv (node GPR64:$Rn),
4449 fixedpoint_f64_i64:$scale))]> {
4450 let Inst{31} = 1; // 64-bit GPR flag
4451 let Inst{23-22} = 0b01; // 64-bit FPR flag
4456 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4459 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4460 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4461 RegisterClass srcType, RegisterClass dstType,
4463 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4464 // We use COPY_TO_REGCLASS for these bitconvert operations.
4465 // copyPhysReg() expands the resultant COPY instructions after
4466 // regalloc is done. This gives greater freedom for the allocator
4467 // and related passes (coalescing, copy propagation, et. al.) to
4468 // be more effective.
4469 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4470 Sched<[WriteFCopy]> {
4473 let Inst{30-24} = 0b0011110;
4475 let Inst{20-19} = rmode;
4476 let Inst{18-16} = opcode;
4477 let Inst{15-10} = 0b000000;
4482 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4483 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4484 RegisterClass srcType, RegisterOperand dstType, string asm,
4486 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4487 "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4488 Sched<[WriteFCopy]> {
4491 let Inst{30-23} = 0b00111101;
4493 let Inst{20-19} = rmode;
4494 let Inst{18-16} = opcode;
4495 let Inst{15-10} = 0b000000;
4499 let DecoderMethod = "DecodeFMOVLaneInstruction";
4502 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4503 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4504 RegisterOperand srcType, RegisterClass dstType, string asm,
4506 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4507 "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4508 Sched<[WriteFCopy]> {
4511 let Inst{30-23} = 0b00111101;
4513 let Inst{20-19} = rmode;
4514 let Inst{18-16} = opcode;
4515 let Inst{15-10} = 0b000000;
4519 let DecoderMethod = "DecodeFMOVLaneInstruction";
4523 multiclass UnscaledConversion<string asm> {
4524 def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4525 let Inst{31} = 0; // 32-bit GPR flag
4526 let Inst{23-22} = 0b11; // 16-bit FPR flag
4527 let Predicates = [HasFullFP16];
4530 def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4531 let Inst{31} = 1; // 64-bit GPR flag
4532 let Inst{23-22} = 0b11; // 16-bit FPR flag
4533 let Predicates = [HasFullFP16];
4536 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4537 let Inst{31} = 0; // 32-bit GPR flag
4538 let Inst{23-22} = 0b00; // 32-bit FPR flag
4541 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4542 let Inst{31} = 1; // 64-bit GPR flag
4543 let Inst{23-22} = 0b01; // 64-bit FPR flag
4546 def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4547 let Inst{31} = 0; // 32-bit GPR flag
4548 let Inst{23-22} = 0b11; // 16-bit FPR flag
4549 let Predicates = [HasFullFP16];
4552 def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4553 let Inst{31} = 1; // 64-bit GPR flag
4554 let Inst{23-22} = 0b11; // 16-bit FPR flag
4555 let Predicates = [HasFullFP16];
4558 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4559 let Inst{31} = 0; // 32-bit GPR flag
4560 let Inst{23-22} = 0b00; // 32-bit FPR flag
4563 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4564 let Inst{31} = 1; // 64-bit GPR flag
4565 let Inst{23-22} = 0b01; // 64-bit FPR flag
4568 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4574 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4582 // Floating point conversion
4585 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4586 RegisterClass srcType, string asm, list<dag> pattern>
4587 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4588 Sched<[WriteFCvt]> {
4591 let Inst{31-24} = 0b00011110;
4592 let Inst{23-22} = type;
4593 let Inst{21-17} = 0b10001;
4594 let Inst{16-15} = opcode;
4595 let Inst{14-10} = 0b10000;
4600 multiclass FPConversion<string asm> {
4601 // Double-precision to Half-precision
4602 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4603 [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4605 // Double-precision to Single-precision
4606 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4607 [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4609 // Half-precision to Double-precision
4610 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4611 [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4613 // Half-precision to Single-precision
4614 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4615 [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4617 // Single-precision to Double-precision
4618 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4619 [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4621 // Single-precision to Half-precision
4622 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4623 [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4627 // Single operand floating point data processing
4630 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4631 class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4632 ValueType vt, string asm, SDPatternOperator node>
4633 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4634 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4638 let Inst{31-24} = 0b00011110;
4640 let Inst{20-15} = opcode;
4641 let Inst{14-10} = 0b10000;
4646 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4647 SDPatternOperator node = null_frag> {
4649 def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4650 let Inst{23-22} = 0b11; // 16-bit size flag
4651 let Predicates = [HasFullFP16];
4654 def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4655 let Inst{23-22} = 0b00; // 32-bit size flag
4658 def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4659 let Inst{23-22} = 0b01; // 64-bit size flag
4663 multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4664 SDPatternOperator node = null_frag>{
4666 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4667 let Inst{23-22} = 0b00; // 32-bit registers
4670 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4671 let Inst{23-22} = 0b01; // 64-bit registers
4675 // FRInt[32|64][Z|N] instructions
4676 multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4677 SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4680 // Two operand floating point data processing
4683 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4684 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4685 string asm, list<dag> pat>
4686 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4687 asm, "\t$Rd, $Rn, $Rm", "", pat>,
4692 let Inst{31-24} = 0b00011110;
4694 let Inst{20-16} = Rm;
4695 let Inst{15-12} = opcode;
4696 let Inst{11-10} = 0b10;
4701 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4702 SDPatternOperator node = null_frag> {
4703 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4704 [(set (f16 FPR16:$Rd),
4705 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4706 let Inst{23-22} = 0b11; // 16-bit size flag
4707 let Predicates = [HasFullFP16];
4710 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4711 [(set (f32 FPR32:$Rd),
4712 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4713 let Inst{23-22} = 0b00; // 32-bit size flag
4716 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4717 [(set (f64 FPR64:$Rd),
4718 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4719 let Inst{23-22} = 0b01; // 64-bit size flag
4723 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4724 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4725 [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4726 let Inst{23-22} = 0b11; // 16-bit size flag
4727 let Predicates = [HasFullFP16];
4730 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4731 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4732 let Inst{23-22} = 0b00; // 32-bit size flag
4735 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4736 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4737 let Inst{23-22} = 0b01; // 64-bit size flag
4743 // Three operand floating point data processing
4746 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4747 RegisterClass regtype, string asm, list<dag> pat>
4748 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4749 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4750 Sched<[WriteFMul]> {
4755 let Inst{31-24} = 0b00011111;
4756 let Inst{21} = isNegated;
4757 let Inst{20-16} = Rm;
4758 let Inst{15} = isSub;
4759 let Inst{14-10} = Ra;
4764 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4765 SDPatternOperator node> {
4766 def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4768 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4769 let Inst{23-22} = 0b11; // 16-bit size flag
4770 let Predicates = [HasFullFP16];
4773 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4775 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4776 let Inst{23-22} = 0b00; // 32-bit size flag
4779 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4781 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4782 let Inst{23-22} = 0b01; // 64-bit size flag
4787 // Floating point data comparisons
4790 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4791 class BaseOneOperandFPComparison<bit signalAllNans,
4792 RegisterClass regtype, string asm,
4794 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4795 Sched<[WriteFCmp]> {
4797 let Inst{31-24} = 0b00011110;
4800 let Inst{15-10} = 0b001000;
4802 let Inst{4} = signalAllNans;
4803 let Inst{3-0} = 0b1000;
4805 // Rm should be 0b00000 canonically, but we need to accept any value.
4806 let PostEncoderMethod = "fixOneOperandFPComparison";
4809 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4810 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4811 string asm, list<dag> pat>
4812 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4813 Sched<[WriteFCmp]> {
4816 let Inst{31-24} = 0b00011110;
4818 let Inst{20-16} = Rm;
4819 let Inst{15-10} = 0b001000;
4821 let Inst{4} = signalAllNans;
4822 let Inst{3-0} = 0b0000;
4825 multiclass FPComparison<bit signalAllNans, string asm,
4826 SDPatternOperator OpNode = null_frag> {
4827 let Defs = [NZCV] in {
4828 def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4829 [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4830 let Inst{23-22} = 0b11;
4831 let Predicates = [HasFullFP16];
4834 def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4835 [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4836 let Inst{23-22} = 0b11;
4837 let Predicates = [HasFullFP16];
4840 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4841 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4842 let Inst{23-22} = 0b00;
4845 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4846 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4847 let Inst{23-22} = 0b00;
4850 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4851 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4852 let Inst{23-22} = 0b01;
4855 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4856 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4857 let Inst{23-22} = 0b01;
4863 // Floating point conditional comparisons
4866 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4867 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4868 string mnemonic, list<dag> pat>
4869 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4870 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4871 Sched<[WriteFCmp]> {
4880 let Inst{31-24} = 0b00011110;
4882 let Inst{20-16} = Rm;
4883 let Inst{15-12} = cond;
4884 let Inst{11-10} = 0b01;
4886 let Inst{4} = signalAllNans;
4887 let Inst{3-0} = nzcv;
4890 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4891 SDPatternOperator OpNode = null_frag> {
4892 def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
4893 [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4894 (i32 imm:$cond), NZCV))]> {
4895 let Inst{23-22} = 0b11;
4896 let Predicates = [HasFullFP16];
4899 def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4900 [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4901 (i32 imm:$cond), NZCV))]> {
4902 let Inst{23-22} = 0b00;
4905 def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4906 [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4907 (i32 imm:$cond), NZCV))]> {
4908 let Inst{23-22} = 0b01;
4913 // Floating point conditional select
4916 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4917 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4918 asm, "\t$Rd, $Rn, $Rm, $cond", "",
4920 (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4921 (i32 imm:$cond), NZCV))]>,
4928 let Inst{31-24} = 0b00011110;
4930 let Inst{20-16} = Rm;
4931 let Inst{15-12} = cond;
4932 let Inst{11-10} = 0b11;
4937 multiclass FPCondSelect<string asm> {
4938 let Uses = [NZCV] in {
4939 def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4940 let Inst{23-22} = 0b11;
4941 let Predicates = [HasFullFP16];
4944 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4945 let Inst{23-22} = 0b00;
4948 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4949 let Inst{23-22} = 0b01;
4955 // Floating move immediate
4958 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4959 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4960 [(set regtype:$Rd, fpimmtype:$imm)]>,
4961 Sched<[WriteFImm]> {
4964 let Inst{31-24} = 0b00011110;
4966 let Inst{20-13} = imm;
4967 let Inst{12-5} = 0b10000000;
4971 multiclass FPMoveImmediate<string asm> {
4972 def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4973 let Inst{23-22} = 0b11;
4974 let Predicates = [HasFullFP16];
4977 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4978 let Inst{23-22} = 0b00;
4981 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4982 let Inst{23-22} = 0b01;
4985 } // end of 'let Predicates = [HasFPARMv8]'
4987 //----------------------------------------------------------------------------
4989 //----------------------------------------------------------------------------
4991 let Predicates = [HasNEON] in {
4993 //----------------------------------------------------------------------------
4994 // AdvSIMD three register vector instructions
4995 //----------------------------------------------------------------------------
4997 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4998 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4999 RegisterOperand regtype, string asm, string kind,
5001 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5002 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5003 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5011 let Inst{28-24} = 0b01110;
5012 let Inst{23-21} = size;
5013 let Inst{20-16} = Rm;
5014 let Inst{15-11} = opcode;
5020 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5021 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5022 RegisterOperand regtype, string asm, string kind,
5024 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5025 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5026 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5034 let Inst{28-24} = 0b01110;
5035 let Inst{23-21} = size;
5036 let Inst{20-16} = Rm;
5037 let Inst{15-11} = opcode;
5043 // All operand sizes distinguished in the encoding.
5044 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5045 SDPatternOperator OpNode> {
5046 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5048 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5049 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5051 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5052 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5054 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5055 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5057 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5058 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5060 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5061 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5063 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5064 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5066 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5069 // As above, but D sized elements unsupported.
5070 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5071 SDPatternOperator OpNode> {
5072 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5074 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5075 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5077 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5078 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5080 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5081 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5083 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5084 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5086 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5087 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5089 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5092 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5093 SDPatternOperator OpNode> {
5094 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5096 [(set (v8i8 V64:$dst),
5097 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5098 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5100 [(set (v16i8 V128:$dst),
5101 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5102 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5104 [(set (v4i16 V64:$dst),
5105 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5106 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5108 [(set (v8i16 V128:$dst),
5109 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5110 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5112 [(set (v2i32 V64:$dst),
5113 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5114 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5116 [(set (v4i32 V128:$dst),
5117 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5120 // As above, but only B sized elements supported.
5121 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5122 SDPatternOperator OpNode> {
5123 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5125 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5126 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5128 [(set (v16i8 V128:$Rd),
5129 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5132 // As above, but only floating point elements supported.
5133 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5134 string asm, SDPatternOperator OpNode> {
5135 let Predicates = [HasNEON, HasFullFP16] in {
5136 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5138 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5139 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5141 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5142 } // Predicates = [HasNEON, HasFullFP16]
5143 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5145 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5146 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5148 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5149 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5151 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5154 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5156 SDPatternOperator OpNode> {
5157 let Predicates = [HasNEON, HasFullFP16] in {
5158 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5160 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5161 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5163 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5164 } // Predicates = [HasNEON, HasFullFP16]
5165 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5167 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5168 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5170 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5171 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5173 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5176 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5177 string asm, SDPatternOperator OpNode> {
5178 let Predicates = [HasNEON, HasFullFP16] in {
5179 def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5181 [(set (v4f16 V64:$dst),
5182 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5183 def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5185 [(set (v8f16 V128:$dst),
5186 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5187 } // Predicates = [HasNEON, HasFullFP16]
5188 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5190 [(set (v2f32 V64:$dst),
5191 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5192 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5194 [(set (v4f32 V128:$dst),
5195 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5196 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5198 [(set (v2f64 V128:$dst),
5199 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5202 // As above, but D and B sized elements unsupported.
5203 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5204 SDPatternOperator OpNode> {
5205 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5207 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5208 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5210 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5211 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5213 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5214 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5216 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5219 // Logical three vector ops share opcode bits, and only use B sized elements.
5220 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5221 SDPatternOperator OpNode = null_frag> {
5222 def v8i8 : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5224 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5225 def v16i8 : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5227 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5229 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5230 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5231 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5232 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5233 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5234 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5236 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5237 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5238 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5239 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5240 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5241 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5244 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5245 string asm, SDPatternOperator OpNode> {
5246 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5248 [(set (v8i8 V64:$dst),
5249 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5250 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5252 [(set (v16i8 V128:$dst),
5253 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5254 (v16i8 V128:$Rm)))]>;
5256 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5258 (!cast<Instruction>(NAME#"v8i8")
5259 V64:$LHS, V64:$MHS, V64:$RHS)>;
5260 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5262 (!cast<Instruction>(NAME#"v8i8")
5263 V64:$LHS, V64:$MHS, V64:$RHS)>;
5264 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5266 (!cast<Instruction>(NAME#"v8i8")
5267 V64:$LHS, V64:$MHS, V64:$RHS)>;
5269 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5270 (v8i16 V128:$RHS))),
5271 (!cast<Instruction>(NAME#"v16i8")
5272 V128:$LHS, V128:$MHS, V128:$RHS)>;
5273 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5274 (v4i32 V128:$RHS))),
5275 (!cast<Instruction>(NAME#"v16i8")
5276 V128:$LHS, V128:$MHS, V128:$RHS)>;
5277 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5278 (v2i64 V128:$RHS))),
5279 (!cast<Instruction>(NAME#"v16i8")
5280 V128:$LHS, V128:$MHS, V128:$RHS)>;
5283 // ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5284 // bytes from S-sized elements.
5285 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
5286 string kind2, RegisterOperand RegType,
5287 ValueType AccumType, ValueType InputType,
5288 SDPatternOperator OpNode> :
5289 BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
5290 [(set (AccumType RegType:$dst),
5291 (OpNode (AccumType RegType:$Rd),
5292 (InputType RegType:$Rn),
5293 (InputType RegType:$Rm)))]> {
5294 let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5297 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
5298 def v8i8 : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
5299 v2i32, v8i8, OpNode>;
5300 def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
5301 v4i32, v16i8, OpNode>;
5304 // ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5305 // select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5306 // 8H to 4S, when Q=1).
5307 class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5308 string kind2, RegisterOperand RegType,
5309 ValueType AccumType, ValueType InputType,
5310 SDPatternOperator OpNode> :
5311 BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5312 [(set (AccumType RegType:$dst),
5313 (OpNode (AccumType RegType:$Rd),
5314 (InputType RegType:$Rn),
5315 (InputType RegType:$Rm)))]> {
5316 let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5320 multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5321 SDPatternOperator OpNode> {
5322 def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5323 v2f32, v4f16, OpNode>;
5324 def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5325 v4f32, v8f16, OpNode>;
5329 //----------------------------------------------------------------------------
5330 // AdvSIMD two register vector instructions.
5331 //----------------------------------------------------------------------------
5333 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5334 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5335 bits<2> size2, RegisterOperand regtype, string asm,
5336 string dstkind, string srckind, list<dag> pattern>
5337 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5338 "{\t$Rd" # dstkind # ", $Rn" # srckind #
5339 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5346 let Inst{28-24} = 0b01110;
5347 let Inst{23-22} = size;
5349 let Inst{20-19} = size2;
5350 let Inst{18-17} = 0b00;
5351 let Inst{16-12} = opcode;
5352 let Inst{11-10} = 0b10;
5357 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5358 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5359 bits<2> size2, RegisterOperand regtype,
5360 string asm, string dstkind, string srckind,
5362 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5363 "{\t$Rd" # dstkind # ", $Rn" # srckind #
5364 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5371 let Inst{28-24} = 0b01110;
5372 let Inst{23-22} = size;
5374 let Inst{20-19} = size2;
5375 let Inst{18-17} = 0b00;
5376 let Inst{16-12} = opcode;
5377 let Inst{11-10} = 0b10;
5382 // Supports B, H, and S element sizes.
5383 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5384 SDPatternOperator OpNode> {
5385 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5387 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5388 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5389 asm, ".16b", ".16b",
5390 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5391 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5393 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5394 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5396 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5397 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5399 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5400 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5402 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5405 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5406 RegisterOperand regtype, string asm, string dstkind,
5407 string srckind, string amount>
5408 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5409 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5410 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
5416 let Inst{29-24} = 0b101110;
5417 let Inst{23-22} = size;
5418 let Inst{21-10} = 0b100001001110;
5423 multiclass SIMDVectorLShiftLongBySizeBHS {
5424 let hasSideEffects = 0 in {
5425 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5426 "shll", ".8h", ".8b", "8">;
5427 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5428 "shll2", ".8h", ".16b", "8">;
5429 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5430 "shll", ".4s", ".4h", "16">;
5431 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5432 "shll2", ".4s", ".8h", "16">;
5433 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5434 "shll", ".2d", ".2s", "32">;
5435 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5436 "shll2", ".2d", ".4s", "32">;
5440 // Supports all element sizes.
5441 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5442 SDPatternOperator OpNode> {
5443 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5445 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5446 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5448 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5449 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5451 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5452 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5454 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5455 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5457 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5458 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5460 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5463 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5464 SDPatternOperator OpNode> {
5465 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5467 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5469 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5471 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5472 (v16i8 V128:$Rn)))]>;
5473 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5475 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5476 (v4i16 V64:$Rn)))]>;
5477 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5479 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5480 (v8i16 V128:$Rn)))]>;
5481 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5483 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5484 (v2i32 V64:$Rn)))]>;
5485 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5487 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5488 (v4i32 V128:$Rn)))]>;
5491 // Supports all element sizes, except 1xD.
5492 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5493 SDPatternOperator OpNode> {
5494 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5496 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5497 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5498 asm, ".16b", ".16b",
5499 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5500 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5502 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5503 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5505 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5506 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5508 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5509 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5511 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5512 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5514 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5517 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5518 SDPatternOperator OpNode = null_frag> {
5519 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5521 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5522 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5523 asm, ".16b", ".16b",
5524 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5525 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5527 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5528 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5530 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5531 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5533 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5534 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5536 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5537 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5539 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5543 // Supports only B element sizes.
5544 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5545 SDPatternOperator OpNode> {
5546 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5548 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5549 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5550 asm, ".16b", ".16b",
5551 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5555 // Supports only B and H element sizes.
5556 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5557 SDPatternOperator OpNode> {
5558 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5560 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5561 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5562 asm, ".16b", ".16b",
5563 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5564 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5566 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5567 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5569 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5572 // Supports H, S and D element sizes, uses high bit of the size field
5573 // as an extra opcode bit.
5574 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5575 SDPatternOperator OpNode> {
5576 let Predicates = [HasNEON, HasFullFP16] in {
5577 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5579 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5580 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5582 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5583 } // Predicates = [HasNEON, HasFullFP16]
5584 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5586 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5587 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5589 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5590 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5592 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5595 // Supports only S and D element sizes
5596 multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5597 SDPatternOperator OpNode = null_frag> {
5599 def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5601 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5602 def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5604 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5605 def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5607 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5610 multiclass FRIntNNTVector<bit U, bit op, string asm,
5611 SDPatternOperator OpNode = null_frag> :
5612 SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5614 // Supports only S element size.
5615 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5616 SDPatternOperator OpNode> {
5617 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5619 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5620 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5622 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5626 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5627 SDPatternOperator OpNode> {
5628 let Predicates = [HasNEON, HasFullFP16] in {
5629 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5631 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5632 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5634 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5635 } // Predicates = [HasNEON, HasFullFP16]
5636 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5638 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5639 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5641 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5642 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5644 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5647 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5648 SDPatternOperator OpNode> {
5649 let Predicates = [HasNEON, HasFullFP16] in {
5650 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5652 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5653 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5655 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5656 } // Predicates = [HasNEON, HasFullFP16]
5657 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5659 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5660 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5662 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5663 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5665 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5669 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5670 RegisterOperand inreg, RegisterOperand outreg,
5671 string asm, string outkind, string inkind,
5673 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5674 "{\t$Rd" # outkind # ", $Rn" # inkind #
5675 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5682 let Inst{28-24} = 0b01110;
5683 let Inst{23-22} = size;
5684 let Inst{21-17} = 0b10000;
5685 let Inst{16-12} = opcode;
5686 let Inst{11-10} = 0b10;
5691 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5692 RegisterOperand inreg, RegisterOperand outreg,
5693 string asm, string outkind, string inkind,
5695 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5696 "{\t$Rd" # outkind # ", $Rn" # inkind #
5697 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5704 let Inst{28-24} = 0b01110;
5705 let Inst{23-22} = size;
5706 let Inst{21-17} = 0b10000;
5707 let Inst{16-12} = opcode;
5708 let Inst{11-10} = 0b10;
5713 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5714 SDPatternOperator OpNode> {
5715 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5717 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5718 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5719 asm#"2", ".16b", ".8h", []>;
5720 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5722 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5723 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5724 asm#"2", ".8h", ".4s", []>;
5725 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5727 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5728 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5729 asm#"2", ".4s", ".2d", []>;
5731 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5732 (!cast<Instruction>(NAME # "v16i8")
5733 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5734 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5735 (!cast<Instruction>(NAME # "v8i16")
5736 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5737 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5738 (!cast<Instruction>(NAME # "v4i32")
5739 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5742 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5743 bits<5> opcode, RegisterOperand regtype, string asm,
5744 string kind, string zero, ValueType dty,
5745 ValueType sty, SDNode OpNode>
5746 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5747 "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5748 "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5749 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5756 let Inst{28-24} = 0b01110;
5757 let Inst{23-22} = size;
5759 let Inst{20-19} = size2;
5760 let Inst{18-17} = 0b00;
5761 let Inst{16-12} = opcode;
5762 let Inst{11-10} = 0b10;
5767 // Comparisons support all element sizes, except 1xD.
5768 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5770 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5772 v8i8, v8i8, OpNode>;
5773 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5775 v16i8, v16i8, OpNode>;
5776 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5778 v4i16, v4i16, OpNode>;
5779 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5781 v8i16, v8i16, OpNode>;
5782 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5784 v2i32, v2i32, OpNode>;
5785 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5787 v4i32, v4i32, OpNode>;
5788 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5790 v2i64, v2i64, OpNode>;
5793 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5794 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5795 string asm, SDNode OpNode> {
5797 let Predicates = [HasNEON, HasFullFP16] in {
5798 def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5800 v4i16, v4f16, OpNode>;
5801 def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5803 v8i16, v8f16, OpNode>;
5804 } // Predicates = [HasNEON, HasFullFP16]
5805 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5807 v2i32, v2f32, OpNode>;
5808 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5810 v4i32, v4f32, OpNode>;
5811 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5813 v2i64, v2f64, OpNode>;
5815 let Predicates = [HasNEON, HasFullFP16] in {
5816 def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5817 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5818 def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5819 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5821 def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5822 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5823 def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5824 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5825 def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5826 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5827 let Predicates = [HasNEON, HasFullFP16] in {
5828 def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5829 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5830 def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5831 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5833 def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5834 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5835 def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5836 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5837 def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5838 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5842 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5843 RegisterOperand outtype, RegisterOperand intype,
5844 string asm, string VdTy, string VnTy,
5846 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5847 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5854 let Inst{28-24} = 0b01110;
5855 let Inst{23-22} = size;
5856 let Inst{21-17} = 0b10000;
5857 let Inst{16-12} = opcode;
5858 let Inst{11-10} = 0b10;
5863 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5864 RegisterOperand outtype, RegisterOperand intype,
5865 string asm, string VdTy, string VnTy,
5867 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5868 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5875 let Inst{28-24} = 0b01110;
5876 let Inst{23-22} = size;
5877 let Inst{21-17} = 0b10000;
5878 let Inst{16-12} = opcode;
5879 let Inst{11-10} = 0b10;
5884 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5885 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5886 asm, ".4s", ".4h", []>;
5887 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5888 asm#"2", ".4s", ".8h", []>;
5889 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5890 asm, ".2d", ".2s", []>;
5891 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5892 asm#"2", ".2d", ".4s", []>;
5895 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5896 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5897 asm, ".4h", ".4s", []>;
5898 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5899 asm#"2", ".8h", ".4s", []>;
5900 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5901 asm, ".2s", ".2d", []>;
5902 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5903 asm#"2", ".4s", ".2d", []>;
5906 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5908 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5910 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5911 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5912 asm#"2", ".4s", ".2d", []>;
5914 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5915 (!cast<Instruction>(NAME # "v4f32")
5916 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5919 //----------------------------------------------------------------------------
5920 // AdvSIMD three register different-size vector instructions.
5921 //----------------------------------------------------------------------------
5923 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5924 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5925 RegisterOperand outtype, RegisterOperand intype1,
5926 RegisterOperand intype2, string asm,
5927 string outkind, string inkind1, string inkind2,
5929 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5930 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5931 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5937 let Inst{30} = size{0};
5939 let Inst{28-24} = 0b01110;
5940 let Inst{23-22} = size{2-1};
5942 let Inst{20-16} = Rm;
5943 let Inst{15-12} = opcode;
5944 let Inst{11-10} = 0b00;
5949 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5950 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5951 RegisterOperand outtype, RegisterOperand intype1,
5952 RegisterOperand intype2, string asm,
5953 string outkind, string inkind1, string inkind2,
5955 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5956 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5957 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5963 let Inst{30} = size{0};
5965 let Inst{28-24} = 0b01110;
5966 let Inst{23-22} = size{2-1};
5968 let Inst{20-16} = Rm;
5969 let Inst{15-12} = opcode;
5970 let Inst{11-10} = 0b00;
5975 // FIXME: TableGen doesn't know how to deal with expanded types that also
5976 // change the element count (in this case, placing the results in
5977 // the high elements of the result register rather than the low
5978 // elements). Until that's fixed, we can't code-gen those.
5979 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5981 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5983 asm, ".8b", ".8h", ".8h",
5984 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5985 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5987 asm#"2", ".16b", ".8h", ".8h",
5989 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5991 asm, ".4h", ".4s", ".4s",
5992 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5993 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5995 asm#"2", ".8h", ".4s", ".4s",
5997 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5999 asm, ".2s", ".2d", ".2d",
6000 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6001 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6003 asm#"2", ".4s", ".2d", ".2d",
6007 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6008 // a version attached to an instruction.
6009 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6011 (!cast<Instruction>(NAME # "v8i16_v16i8")
6012 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6013 V128:$Rn, V128:$Rm)>;
6014 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6016 (!cast<Instruction>(NAME # "v4i32_v8i16")
6017 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6018 V128:$Rn, V128:$Rm)>;
6019 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6021 (!cast<Instruction>(NAME # "v2i64_v4i32")
6022 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6023 V128:$Rn, V128:$Rm)>;
6026 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6028 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6030 asm, ".8h", ".8b", ".8b",
6031 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6032 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6034 asm#"2", ".8h", ".16b", ".16b", []>;
6035 let Predicates = [HasAES] in {
6036 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6038 asm, ".1q", ".1d", ".1d", []>;
6039 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6041 asm#"2", ".1q", ".2d", ".2d", []>;
6044 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6045 (v8i8 (extract_high_v16i8 V128:$Rm)))),
6046 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6049 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6050 SDPatternOperator OpNode> {
6051 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6053 asm, ".4s", ".4h", ".4h",
6054 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6055 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6057 asm#"2", ".4s", ".8h", ".8h",
6058 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6059 (extract_high_v8i16 V128:$Rm)))]>;
6060 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6062 asm, ".2d", ".2s", ".2s",
6063 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6064 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6066 asm#"2", ".2d", ".4s", ".4s",
6067 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6068 (extract_high_v4i32 V128:$Rm)))]>;
6071 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6072 SDPatternOperator OpNode = null_frag> {
6073 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6075 asm, ".8h", ".8b", ".8b",
6076 [(set (v8i16 V128:$Rd),
6077 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6078 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6080 asm#"2", ".8h", ".16b", ".16b",
6081 [(set (v8i16 V128:$Rd),
6082 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6083 (extract_high_v16i8 V128:$Rm)))))]>;
6084 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6086 asm, ".4s", ".4h", ".4h",
6087 [(set (v4i32 V128:$Rd),
6088 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6089 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6091 asm#"2", ".4s", ".8h", ".8h",
6092 [(set (v4i32 V128:$Rd),
6093 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6094 (extract_high_v8i16 V128:$Rm)))))]>;
6095 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6097 asm, ".2d", ".2s", ".2s",
6098 [(set (v2i64 V128:$Rd),
6099 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6100 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6102 asm#"2", ".2d", ".4s", ".4s",
6103 [(set (v2i64 V128:$Rd),
6104 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6105 (extract_high_v4i32 V128:$Rm)))))]>;
6108 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6110 SDPatternOperator OpNode> {
6111 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6113 asm, ".8h", ".8b", ".8b",
6114 [(set (v8i16 V128:$dst),
6115 (add (v8i16 V128:$Rd),
6116 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6117 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6119 asm#"2", ".8h", ".16b", ".16b",
6120 [(set (v8i16 V128:$dst),
6121 (add (v8i16 V128:$Rd),
6122 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6123 (extract_high_v16i8 V128:$Rm))))))]>;
6124 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6126 asm, ".4s", ".4h", ".4h",
6127 [(set (v4i32 V128:$dst),
6128 (add (v4i32 V128:$Rd),
6129 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6130 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6132 asm#"2", ".4s", ".8h", ".8h",
6133 [(set (v4i32 V128:$dst),
6134 (add (v4i32 V128:$Rd),
6135 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6136 (extract_high_v8i16 V128:$Rm))))))]>;
6137 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6139 asm, ".2d", ".2s", ".2s",
6140 [(set (v2i64 V128:$dst),
6141 (add (v2i64 V128:$Rd),
6142 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6143 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6145 asm#"2", ".2d", ".4s", ".4s",
6146 [(set (v2i64 V128:$dst),
6147 (add (v2i64 V128:$Rd),
6148 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6149 (extract_high_v4i32 V128:$Rm))))))]>;
6152 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6153 SDPatternOperator OpNode = null_frag> {
6154 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6156 asm, ".8h", ".8b", ".8b",
6157 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6158 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6160 asm#"2", ".8h", ".16b", ".16b",
6161 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6162 (extract_high_v16i8 V128:$Rm)))]>;
6163 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6165 asm, ".4s", ".4h", ".4h",
6166 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6167 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6169 asm#"2", ".4s", ".8h", ".8h",
6170 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6171 (extract_high_v8i16 V128:$Rm)))]>;
6172 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6174 asm, ".2d", ".2s", ".2s",
6175 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6176 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6178 asm#"2", ".2d", ".4s", ".4s",
6179 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6180 (extract_high_v4i32 V128:$Rm)))]>;
6183 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6185 SDPatternOperator OpNode> {
6186 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6188 asm, ".8h", ".8b", ".8b",
6189 [(set (v8i16 V128:$dst),
6190 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6191 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6193 asm#"2", ".8h", ".16b", ".16b",
6194 [(set (v8i16 V128:$dst),
6195 (OpNode (v8i16 V128:$Rd),
6196 (extract_high_v16i8 V128:$Rn),
6197 (extract_high_v16i8 V128:$Rm)))]>;
6198 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6200 asm, ".4s", ".4h", ".4h",
6201 [(set (v4i32 V128:$dst),
6202 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6203 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6205 asm#"2", ".4s", ".8h", ".8h",
6206 [(set (v4i32 V128:$dst),
6207 (OpNode (v4i32 V128:$Rd),
6208 (extract_high_v8i16 V128:$Rn),
6209 (extract_high_v8i16 V128:$Rm)))]>;
6210 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6212 asm, ".2d", ".2s", ".2s",
6213 [(set (v2i64 V128:$dst),
6214 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6215 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6217 asm#"2", ".2d", ".4s", ".4s",
6218 [(set (v2i64 V128:$dst),
6219 (OpNode (v2i64 V128:$Rd),
6220 (extract_high_v4i32 V128:$Rn),
6221 (extract_high_v4i32 V128:$Rm)))]>;
6224 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6225 SDPatternOperator Accum> {
6226 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6228 asm, ".4s", ".4h", ".4h",
6229 [(set (v4i32 V128:$dst),
6230 (Accum (v4i32 V128:$Rd),
6231 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6232 (v4i16 V64:$Rm)))))]>;
6233 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6235 asm#"2", ".4s", ".8h", ".8h",
6236 [(set (v4i32 V128:$dst),
6237 (Accum (v4i32 V128:$Rd),
6238 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6239 (extract_high_v8i16 V128:$Rm)))))]>;
6240 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6242 asm, ".2d", ".2s", ".2s",
6243 [(set (v2i64 V128:$dst),
6244 (Accum (v2i64 V128:$Rd),
6245 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6246 (v2i32 V64:$Rm)))))]>;
6247 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6249 asm#"2", ".2d", ".4s", ".4s",
6250 [(set (v2i64 V128:$dst),
6251 (Accum (v2i64 V128:$Rd),
6252 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6253 (extract_high_v4i32 V128:$Rm)))))]>;
6256 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6257 SDPatternOperator OpNode> {
6258 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6260 asm, ".8h", ".8h", ".8b",
6261 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6262 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6264 asm#"2", ".8h", ".8h", ".16b",
6265 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6266 (extract_high_v16i8 V128:$Rm)))]>;
6267 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6269 asm, ".4s", ".4s", ".4h",
6270 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6271 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6273 asm#"2", ".4s", ".4s", ".8h",
6274 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6275 (extract_high_v8i16 V128:$Rm)))]>;
6276 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6278 asm, ".2d", ".2d", ".2s",
6279 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6280 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6282 asm#"2", ".2d", ".2d", ".4s",
6283 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6284 (extract_high_v4i32 V128:$Rm)))]>;
6287 //----------------------------------------------------------------------------
6288 // AdvSIMD bitwise extract from vector
6289 //----------------------------------------------------------------------------
6291 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6292 string asm, string kind>
6293 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6294 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6295 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6296 [(set (vty regtype:$Rd),
6297 (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6304 let Inst{30} = size;
6305 let Inst{29-21} = 0b101110000;
6306 let Inst{20-16} = Rm;
6308 let Inst{14-11} = imm;
6315 multiclass SIMDBitwiseExtract<string asm> {
6316 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6319 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6322 //----------------------------------------------------------------------------
6323 // AdvSIMD zip vector
6324 //----------------------------------------------------------------------------
6326 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6327 string asm, string kind, SDNode OpNode, ValueType valty>
6328 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6329 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6330 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6331 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6337 let Inst{30} = size{0};
6338 let Inst{29-24} = 0b001110;
6339 let Inst{23-22} = size{2-1};
6341 let Inst{20-16} = Rm;
6343 let Inst{14-12} = opc;
6344 let Inst{11-10} = 0b10;
6349 multiclass SIMDZipVector<bits<3>opc, string asm,
6351 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
6352 asm, ".8b", OpNode, v8i8>;
6353 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
6354 asm, ".16b", OpNode, v16i8>;
6355 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
6356 asm, ".4h", OpNode, v4i16>;
6357 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
6358 asm, ".8h", OpNode, v8i16>;
6359 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
6360 asm, ".2s", OpNode, v2i32>;
6361 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
6362 asm, ".4s", OpNode, v4i32>;
6363 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
6364 asm, ".2d", OpNode, v2i64>;
6366 def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6367 (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6368 def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6369 (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6370 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6371 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6372 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6373 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6374 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6375 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6378 //----------------------------------------------------------------------------
6379 // AdvSIMD three register scalar instructions
6380 //----------------------------------------------------------------------------
6382 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6383 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6384 RegisterClass regtype, string asm,
6386 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6387 "\t$Rd, $Rn, $Rm", "", pattern>,
6392 let Inst{31-30} = 0b01;
6394 let Inst{28-24} = 0b11110;
6395 let Inst{23-21} = size;
6396 let Inst{20-16} = Rm;
6397 let Inst{15-11} = opcode;
6403 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6404 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6405 dag oops, dag iops, string asm,
6407 : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6412 let Inst{31-30} = 0b01;
6414 let Inst{28-24} = 0b11110;
6415 let Inst{23-22} = size;
6417 let Inst{20-16} = Rm;
6418 let Inst{15-11} = opcode;
6424 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6425 SDPatternOperator OpNode> {
6426 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6427 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6430 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6431 SDPatternOperator OpNode> {
6432 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6433 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6434 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6435 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6436 def v1i8 : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6438 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6439 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6440 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6441 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6444 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6445 SDPatternOperator OpNode> {
6446 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6447 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6448 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6451 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6452 SDPatternOperator OpNode = null_frag> {
6453 def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6454 (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6456 def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6457 (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6461 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6462 SDPatternOperator OpNode = null_frag> {
6463 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6464 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6465 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6466 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6467 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6468 let Predicates = [HasNEON, HasFullFP16] in {
6469 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6470 [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6471 } // Predicates = [HasNEON, HasFullFP16]
6474 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6475 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6478 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6479 SDPatternOperator OpNode = null_frag> {
6480 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6481 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6482 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6483 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6484 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6485 let Predicates = [HasNEON, HasFullFP16] in {
6486 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6488 } // Predicates = [HasNEON, HasFullFP16]
6491 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6492 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6495 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6496 dag oops, dag iops, string asm, string cstr, list<dag> pat>
6497 : I<oops, iops, asm,
6498 "\t$Rd, $Rn, $Rm", cstr, pat>,
6503 let Inst{31-30} = 0b01;
6505 let Inst{28-24} = 0b11110;
6506 let Inst{23-22} = size;
6508 let Inst{20-16} = Rm;
6509 let Inst{15-11} = opcode;
6515 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6516 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6517 SDPatternOperator OpNode = null_frag> {
6518 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6520 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6521 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6523 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6524 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6527 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6528 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6529 SDPatternOperator OpNode = null_frag> {
6530 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6532 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6533 asm, "$Rd = $dst", []>;
6534 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6536 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6538 [(set (i64 FPR64:$dst),
6539 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6542 //----------------------------------------------------------------------------
6543 // AdvSIMD two register scalar instructions
6544 //----------------------------------------------------------------------------
6546 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6547 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6548 RegisterClass regtype, RegisterClass regtype2,
6549 string asm, list<dag> pat>
6550 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6551 "\t$Rd, $Rn", "", pat>,
6555 let Inst{31-30} = 0b01;
6557 let Inst{28-24} = 0b11110;
6558 let Inst{23-22} = size;
6560 let Inst{20-19} = size2;
6561 let Inst{18-17} = 0b00;
6562 let Inst{16-12} = opcode;
6563 let Inst{11-10} = 0b10;
6568 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6569 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6570 RegisterClass regtype, RegisterClass regtype2,
6571 string asm, list<dag> pat>
6572 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6573 "\t$Rd, $Rn", "$Rd = $dst", pat>,
6577 let Inst{31-30} = 0b01;
6579 let Inst{28-24} = 0b11110;
6580 let Inst{23-22} = size;
6581 let Inst{21-17} = 0b10000;
6582 let Inst{16-12} = opcode;
6583 let Inst{11-10} = 0b10;
6589 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6590 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6591 RegisterClass regtype, string asm, string zero>
6592 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6593 "\t$Rd, $Rn, #" # zero, "", []>,
6597 let Inst{31-30} = 0b01;
6599 let Inst{28-24} = 0b11110;
6600 let Inst{23-22} = size;
6602 let Inst{20-19} = size2;
6603 let Inst{18-17} = 0b00;
6604 let Inst{16-12} = opcode;
6605 let Inst{11-10} = 0b10;
6610 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6611 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6612 [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6616 let Inst{31-17} = 0b011111100110000;
6617 let Inst{16-12} = opcode;
6618 let Inst{11-10} = 0b10;
6623 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6624 SDPatternOperator OpNode> {
6625 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6627 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6628 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6631 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6632 SDPatternOperator OpNode> {
6633 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6634 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6635 let Predicates = [HasNEON, HasFullFP16] in {
6636 def v1i16rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6639 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6640 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6641 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6642 (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6643 let Predicates = [HasNEON, HasFullFP16] in {
6644 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6645 (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6648 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6649 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6652 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6653 SDPatternOperator OpNode = null_frag> {
6654 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6655 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6657 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6658 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6661 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6662 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6663 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6664 let Predicates = [HasNEON, HasFullFP16] in {
6665 def v1f16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6669 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6670 SDPatternOperator OpNode> {
6671 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6672 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6673 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6674 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6675 let Predicates = [HasNEON, HasFullFP16] in {
6676 def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6677 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6681 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6682 SDPatternOperator OpNode = null_frag> {
6683 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6684 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6685 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6686 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6687 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6688 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6689 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6692 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6693 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6696 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6698 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6699 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6700 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6701 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6702 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6703 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6704 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6707 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6708 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6713 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6714 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6715 SDPatternOperator OpNode = null_frag> {
6716 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6717 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6718 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6719 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6722 //----------------------------------------------------------------------------
6723 // AdvSIMD scalar pairwise instructions
6724 //----------------------------------------------------------------------------
6726 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6727 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6728 RegisterOperand regtype, RegisterOperand vectype,
6729 string asm, string kind>
6730 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6731 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6735 let Inst{31-30} = 0b01;
6737 let Inst{28-24} = 0b11110;
6738 let Inst{23-22} = size;
6739 let Inst{21-17} = 0b11000;
6740 let Inst{16-12} = opcode;
6741 let Inst{11-10} = 0b10;
6746 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6747 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6751 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6752 let Predicates = [HasNEON, HasFullFP16] in {
6753 def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6756 def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6758 def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6762 //----------------------------------------------------------------------------
6763 // AdvSIMD across lanes instructions
6764 //----------------------------------------------------------------------------
6766 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6767 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6768 RegisterClass regtype, RegisterOperand vectype,
6769 string asm, string kind, list<dag> pattern>
6770 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6771 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6778 let Inst{28-24} = 0b01110;
6779 let Inst{23-22} = size;
6780 let Inst{21-17} = 0b11000;
6781 let Inst{16-12} = opcode;
6782 let Inst{11-10} = 0b10;
6787 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6789 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
6791 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
6793 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6795 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6797 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6801 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6802 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6804 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6806 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6808 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6810 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6814 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6816 let Predicates = [HasNEON, HasFullFP16] in {
6817 def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6819 [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6820 def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6822 [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6823 } // Predicates = [HasNEON, HasFullFP16]
6824 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6826 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6829 //----------------------------------------------------------------------------
6830 // AdvSIMD INS/DUP instructions
6831 //----------------------------------------------------------------------------
6833 // FIXME: There has got to be a better way to factor these. ugh.
6835 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6836 string operands, string constraints, list<dag> pattern>
6837 : I<outs, ins, asm, operands, constraints, pattern>,
6844 let Inst{28-21} = 0b01110000;
6851 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6852 RegisterOperand vecreg, RegisterClass regtype>
6853 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6854 "{\t$Rd" # size # ", $Rn" #
6855 "|" # size # "\t$Rd, $Rn}", "",
6856 [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6857 let Inst{20-16} = imm5;
6858 let Inst{14-11} = 0b0001;
6861 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6862 ValueType vectype, ValueType insreg,
6863 RegisterOperand vecreg, Operand idxtype,
6864 ValueType elttype, SDNode OpNode>
6865 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6866 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6867 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6868 [(set (vectype vecreg:$Rd),
6869 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6870 let Inst{14-11} = 0b0000;
6873 class SIMDDup64FromElement
6874 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6875 VectorIndexD, i64, AArch64duplane64> {
6878 let Inst{19-16} = 0b1000;
6881 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6882 RegisterOperand vecreg>
6883 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6884 VectorIndexS, i64, AArch64duplane32> {
6886 let Inst{20-19} = idx;
6887 let Inst{18-16} = 0b100;
6890 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6891 RegisterOperand vecreg>
6892 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6893 VectorIndexH, i64, AArch64duplane16> {
6895 let Inst{20-18} = idx;
6896 let Inst{17-16} = 0b10;
6899 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6900 RegisterOperand vecreg>
6901 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6902 VectorIndexB, i64, AArch64duplane8> {
6904 let Inst{20-17} = idx;
6908 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6909 Operand idxtype, string asm, list<dag> pattern>
6910 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6911 "{\t$Rd, $Rn" # size # "$idx" #
6912 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6913 let Inst{14-11} = imm4;
6916 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6918 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6919 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6921 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6922 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6924 class SIMDMovAlias<string asm, string size, Instruction inst,
6925 RegisterClass regtype, Operand idxtype>
6926 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6927 "|" # size # "\t$dst, $src$idx}",
6928 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6931 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6933 let Inst{20-17} = idx;
6936 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6938 let Inst{20-17} = idx;
6941 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6943 let Inst{20-18} = idx;
6944 let Inst{17-16} = 0b10;
6946 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6948 let Inst{20-18} = idx;
6949 let Inst{17-16} = 0b10;
6951 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6953 let Inst{20-19} = idx;
6954 let Inst{18-16} = 0b100;
6959 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6961 let Inst{20-17} = idx;
6964 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6966 let Inst{20-18} = idx;
6967 let Inst{17-16} = 0b10;
6969 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6971 let Inst{20-19} = idx;
6972 let Inst{18-16} = 0b100;
6974 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6977 let Inst{19-16} = 0b1000;
6979 def : SIMDMovAlias<"mov", ".s",
6980 !cast<Instruction>(NAME#"vi32"),
6981 GPR32, VectorIndexS>;
6982 def : SIMDMovAlias<"mov", ".d",
6983 !cast<Instruction>(NAME#"vi64"),
6984 GPR64, VectorIndexD>;
6987 class SIMDInsFromMain<string size, ValueType vectype,
6988 RegisterClass regtype, Operand idxtype>
6989 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6990 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6991 "{\t$Rd" # size # "$idx, $Rn" #
6992 "|" # size # "\t$Rd$idx, $Rn}",
6995 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6996 let Inst{14-11} = 0b0011;
6999 class SIMDInsFromElement<string size, ValueType vectype,
7000 ValueType elttype, Operand idxtype>
7001 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7002 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7003 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7004 "|" # size # "\t$Rd$idx, $Rn$idx2}",
7009 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7012 class SIMDInsMainMovAlias<string size, Instruction inst,
7013 RegisterClass regtype, Operand idxtype>
7014 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7015 "|" # size #"\t$dst$idx, $src}",
7016 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7017 class SIMDInsElementMovAlias<string size, Instruction inst,
7019 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
7020 # "|" # size #"\t$dst$idx, $src$idx2}",
7021 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7024 multiclass SIMDIns {
7025 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7027 let Inst{20-17} = idx;
7030 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7032 let Inst{20-18} = idx;
7033 let Inst{17-16} = 0b10;
7035 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7037 let Inst{20-19} = idx;
7038 let Inst{18-16} = 0b100;
7040 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7043 let Inst{19-16} = 0b1000;
7046 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7049 let Inst{20-17} = idx;
7051 let Inst{14-11} = idx2;
7053 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7056 let Inst{20-18} = idx;
7057 let Inst{17-16} = 0b10;
7058 let Inst{14-12} = idx2;
7061 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7064 let Inst{20-19} = idx;
7065 let Inst{18-16} = 0b100;
7066 let Inst{14-13} = idx2;
7067 let Inst{12-11} = {?,?};
7069 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7073 let Inst{19-16} = 0b1000;
7074 let Inst{14} = idx2;
7075 let Inst{13-11} = {?,?,?};
7078 // For all forms of the INS instruction, the "mov" mnemonic is the
7079 // preferred alias. Why they didn't just call the instruction "mov" in
7080 // the first place is a very good question indeed...
7081 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7082 GPR32, VectorIndexB>;
7083 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7084 GPR32, VectorIndexH>;
7085 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7086 GPR32, VectorIndexS>;
7087 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7088 GPR64, VectorIndexD>;
7090 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7092 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7094 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7096 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7100 //----------------------------------------------------------------------------
7102 //----------------------------------------------------------------------------
7104 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7105 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7106 RegisterOperand listtype, string asm, string kind>
7107 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7108 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7115 let Inst{29-21} = 0b001110000;
7116 let Inst{20-16} = Vm;
7118 let Inst{14-13} = len;
7120 let Inst{11-10} = 0b00;
7125 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7126 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7127 RegisterOperand listtype, string asm, string kind>
7128 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7129 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7136 let Inst{29-21} = 0b001110000;
7137 let Inst{20-16} = Vm;
7139 let Inst{14-13} = len;
7141 let Inst{11-10} = 0b00;
7146 class SIMDTableLookupAlias<string asm, Instruction inst,
7147 RegisterOperand vectype, RegisterOperand listtype>
7148 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7149 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7151 multiclass SIMDTableLookup<bit op, string asm> {
7152 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7154 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7156 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7158 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7160 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7162 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7164 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7166 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7169 def : SIMDTableLookupAlias<asm # ".8b",
7170 !cast<Instruction>(NAME#"v8i8One"),
7171 V64, VecListOne128>;
7172 def : SIMDTableLookupAlias<asm # ".8b",
7173 !cast<Instruction>(NAME#"v8i8Two"),
7174 V64, VecListTwo128>;
7175 def : SIMDTableLookupAlias<asm # ".8b",
7176 !cast<Instruction>(NAME#"v8i8Three"),
7177 V64, VecListThree128>;
7178 def : SIMDTableLookupAlias<asm # ".8b",
7179 !cast<Instruction>(NAME#"v8i8Four"),
7180 V64, VecListFour128>;
7181 def : SIMDTableLookupAlias<asm # ".16b",
7182 !cast<Instruction>(NAME#"v16i8One"),
7183 V128, VecListOne128>;
7184 def : SIMDTableLookupAlias<asm # ".16b",
7185 !cast<Instruction>(NAME#"v16i8Two"),
7186 V128, VecListTwo128>;
7187 def : SIMDTableLookupAlias<asm # ".16b",
7188 !cast<Instruction>(NAME#"v16i8Three"),
7189 V128, VecListThree128>;
7190 def : SIMDTableLookupAlias<asm # ".16b",
7191 !cast<Instruction>(NAME#"v16i8Four"),
7192 V128, VecListFour128>;
7195 multiclass SIMDTableLookupTied<bit op, string asm> {
7196 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7198 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7200 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7202 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7204 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7206 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7208 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7210 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7213 def : SIMDTableLookupAlias<asm # ".8b",
7214 !cast<Instruction>(NAME#"v8i8One"),
7215 V64, VecListOne128>;
7216 def : SIMDTableLookupAlias<asm # ".8b",
7217 !cast<Instruction>(NAME#"v8i8Two"),
7218 V64, VecListTwo128>;
7219 def : SIMDTableLookupAlias<asm # ".8b",
7220 !cast<Instruction>(NAME#"v8i8Three"),
7221 V64, VecListThree128>;
7222 def : SIMDTableLookupAlias<asm # ".8b",
7223 !cast<Instruction>(NAME#"v8i8Four"),
7224 V64, VecListFour128>;
7225 def : SIMDTableLookupAlias<asm # ".16b",
7226 !cast<Instruction>(NAME#"v16i8One"),
7227 V128, VecListOne128>;
7228 def : SIMDTableLookupAlias<asm # ".16b",
7229 !cast<Instruction>(NAME#"v16i8Two"),
7230 V128, VecListTwo128>;
7231 def : SIMDTableLookupAlias<asm # ".16b",
7232 !cast<Instruction>(NAME#"v16i8Three"),
7233 V128, VecListThree128>;
7234 def : SIMDTableLookupAlias<asm # ".16b",
7235 !cast<Instruction>(NAME#"v16i8Four"),
7236 V128, VecListFour128>;
7240 //----------------------------------------------------------------------------
7241 // AdvSIMD scalar CPY
7242 //----------------------------------------------------------------------------
7243 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7244 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7245 string kind, Operand idxtype>
7246 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7247 "{\t$dst, $src" # kind # "$idx" #
7248 "|\t$dst, $src$idx}", "", []>,
7252 let Inst{31-21} = 0b01011110000;
7253 let Inst{15-10} = 0b000001;
7254 let Inst{9-5} = src;
7255 let Inst{4-0} = dst;
7258 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7259 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7260 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
7261 # "|\t$dst, $src$index}",
7262 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7265 multiclass SIMDScalarCPY<string asm> {
7266 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
7268 let Inst{20-17} = idx;
7271 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7273 let Inst{20-18} = idx;
7274 let Inst{17-16} = 0b10;
7276 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7278 let Inst{20-19} = idx;
7279 let Inst{18-16} = 0b100;
7281 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7284 let Inst{19-16} = 0b1000;
7287 def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7288 VectorIndexD:$idx)))),
7289 (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7291 // 'DUP' mnemonic aliases.
7292 def : SIMDScalarCPYAlias<"dup", ".b",
7293 !cast<Instruction>(NAME#"i8"),
7294 FPR8, V128, VectorIndexB>;
7295 def : SIMDScalarCPYAlias<"dup", ".h",
7296 !cast<Instruction>(NAME#"i16"),
7297 FPR16, V128, VectorIndexH>;
7298 def : SIMDScalarCPYAlias<"dup", ".s",
7299 !cast<Instruction>(NAME#"i32"),
7300 FPR32, V128, VectorIndexS>;
7301 def : SIMDScalarCPYAlias<"dup", ".d",
7302 !cast<Instruction>(NAME#"i64"),
7303 FPR64, V128, VectorIndexD>;
7306 //----------------------------------------------------------------------------
7307 // AdvSIMD modified immediate instructions
7308 //----------------------------------------------------------------------------
7310 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7311 string asm, string op_string,
7312 string cstr, list<dag> pattern>
7313 : I<oops, iops, asm, op_string, cstr, pattern>,
7320 let Inst{28-19} = 0b0111100000;
7321 let Inst{18-16} = imm8{7-5};
7324 let Inst{9-5} = imm8{4-0};
7328 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7329 Operand immtype, dag opt_shift_iop,
7330 string opt_shift, string asm, string kind,
7332 : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7333 !con((ins immtype:$imm8), opt_shift_iop), asm,
7334 "{\t$Rd" # kind # ", $imm8" # opt_shift #
7335 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7337 let DecoderMethod = "DecodeModImmInstruction";
7340 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7341 Operand immtype, dag opt_shift_iop,
7342 string opt_shift, string asm, string kind,
7344 : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7345 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7346 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7347 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7348 "$Rd = $dst", pattern> {
7349 let DecoderMethod = "DecodeModImmTiedInstruction";
7352 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7353 RegisterOperand vectype, string asm,
7354 string kind, list<dag> pattern>
7355 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7356 (ins logical_vec_shift:$shift),
7357 "$shift", asm, kind, pattern> {
7359 let Inst{15} = b15_b12{1};
7360 let Inst{14-13} = shift;
7361 let Inst{12} = b15_b12{0};
7364 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7365 RegisterOperand vectype, string asm,
7366 string kind, list<dag> pattern>
7367 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7368 (ins logical_vec_shift:$shift),
7369 "$shift", asm, kind, pattern> {
7371 let Inst{15} = b15_b12{1};
7372 let Inst{14-13} = shift;
7373 let Inst{12} = b15_b12{0};
7377 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7378 RegisterOperand vectype, string asm,
7379 string kind, list<dag> pattern>
7380 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7381 (ins logical_vec_hw_shift:$shift),
7382 "$shift", asm, kind, pattern> {
7384 let Inst{15} = b15_b12{1};
7386 let Inst{13} = shift{0};
7387 let Inst{12} = b15_b12{0};
7390 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7391 RegisterOperand vectype, string asm,
7392 string kind, list<dag> pattern>
7393 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7394 (ins logical_vec_hw_shift:$shift),
7395 "$shift", asm, kind, pattern> {
7397 let Inst{15} = b15_b12{1};
7399 let Inst{13} = shift{0};
7400 let Inst{12} = b15_b12{0};
7403 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7405 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7407 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7410 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7412 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7416 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7417 bits<2> w_cmode, string asm,
7419 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7421 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7423 (i32 imm:$shift)))]>;
7424 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7426 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7428 (i32 imm:$shift)))]>;
7430 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7432 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7434 (i32 imm:$shift)))]>;
7435 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7437 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7439 (i32 imm:$shift)))]>;
7442 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7443 RegisterOperand vectype, string asm,
7444 string kind, list<dag> pattern>
7445 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7446 (ins move_vec_shift:$shift),
7447 "$shift", asm, kind, pattern> {
7449 let Inst{15-13} = cmode{3-1};
7450 let Inst{12} = shift;
7453 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7454 RegisterOperand vectype,
7455 Operand imm_type, string asm,
7456 string kind, list<dag> pattern>
7457 : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7458 asm, kind, pattern> {
7459 let Inst{15-12} = cmode;
7462 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7464 : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7465 "\t$Rd, $imm8", "", pattern> {
7466 let Inst{15-12} = cmode;
7467 let DecoderMethod = "DecodeModImmInstruction";
7470 //----------------------------------------------------------------------------
7471 // AdvSIMD indexed element
7472 //----------------------------------------------------------------------------
7474 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7475 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7476 RegisterOperand dst_reg, RegisterOperand lhs_reg,
7477 RegisterOperand rhs_reg, Operand vec_idx, string asm,
7478 string apple_kind, string dst_kind, string lhs_kind,
7479 string rhs_kind, list<dag> pattern>
7480 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7482 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7483 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7492 let Inst{28} = Scalar;
7493 let Inst{27-24} = 0b1111;
7494 let Inst{23-22} = size;
7495 // Bit 21 must be set by the derived class.
7496 let Inst{20-16} = Rm;
7497 let Inst{15-12} = opc;
7498 // Bit 11 must be set by the derived class.
7504 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7505 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7506 RegisterOperand dst_reg, RegisterOperand lhs_reg,
7507 RegisterOperand rhs_reg, Operand vec_idx, string asm,
7508 string apple_kind, string dst_kind, string lhs_kind,
7509 string rhs_kind, list<dag> pattern>
7510 : I<(outs dst_reg:$dst),
7511 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7512 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7513 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7522 let Inst{28} = Scalar;
7523 let Inst{27-24} = 0b1111;
7524 let Inst{23-22} = size;
7525 // Bit 21 must be set by the derived class.
7526 let Inst{20-16} = Rm;
7527 let Inst{15-12} = opc;
7528 // Bit 11 must be set by the derived class.
7534 // ARMv8.2-A Dot Product Instructions (Indexed)
7535 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7536 string lhs_kind, string rhs_kind,
7537 RegisterOperand RegType,
7538 ValueType AccumType, ValueType InputType,
7539 SDPatternOperator OpNode> :
7540 BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7541 VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7542 [(set (AccumType RegType:$dst),
7543 (AccumType (OpNode (AccumType RegType:$Rd),
7544 (InputType RegType:$Rn),
7545 (InputType (bitconvert (AccumType
7546 (AArch64duplane32 (v4i32 V128:$Rm),
7547 VectorIndexS:$idx)))))))]> {
7549 let Inst{21} = idx{0}; // L
7550 let Inst{11} = idx{1}; // H
7553 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7554 SDPatternOperator OpNode> {
7555 def v8i8 : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b",
7556 V64, v2i32, v8i8, OpNode>;
7557 def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b",
7558 V128, v4i32, v16i8, OpNode>;
7561 // ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7562 class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7563 string dst_kind, string lhs_kind,
7564 string rhs_kind, RegisterOperand RegType,
7565 ValueType AccumType, ValueType InputType,
7566 SDPatternOperator OpNode> :
7567 BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7568 VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7569 [(set (AccumType RegType:$dst),
7570 (AccumType (OpNode (AccumType RegType:$Rd),
7571 (InputType RegType:$Rn),
7572 (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7573 VectorIndexH:$idx)))))]> {
7576 let Inst{11} = idx{2}; // H
7577 let Inst{21} = idx{1}; // L
7578 let Inst{20} = idx{0}; // M
7581 multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
7582 SDPatternOperator OpNode> {
7583 def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
7584 V64, v2f32, v4f16, OpNode>;
7585 def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
7586 V128, v4f32, v8f16, OpNode>;
7589 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7590 SDPatternOperator OpNode> {
7591 let Predicates = [HasNEON, HasFullFP16] in {
7592 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7594 V128_lo, VectorIndexH,
7595 asm, ".4h", ".4h", ".4h", ".h",
7596 [(set (v4f16 V64:$Rd),
7597 (OpNode (v4f16 V64:$Rn),
7598 (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7600 let Inst{11} = idx{2};
7601 let Inst{21} = idx{1};
7602 let Inst{20} = idx{0};
7605 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7607 V128_lo, VectorIndexH,
7608 asm, ".8h", ".8h", ".8h", ".h",
7609 [(set (v8f16 V128:$Rd),
7610 (OpNode (v8f16 V128:$Rn),
7611 (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7613 let Inst{11} = idx{2};
7614 let Inst{21} = idx{1};
7615 let Inst{20} = idx{0};
7617 } // Predicates = [HasNEON, HasFullFP16]
7619 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7622 asm, ".2s", ".2s", ".2s", ".s",
7623 [(set (v2f32 V64:$Rd),
7624 (OpNode (v2f32 V64:$Rn),
7625 (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7627 let Inst{11} = idx{1};
7628 let Inst{21} = idx{0};
7631 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7634 asm, ".4s", ".4s", ".4s", ".s",
7635 [(set (v4f32 V128:$Rd),
7636 (OpNode (v4f32 V128:$Rn),
7637 (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7639 let Inst{11} = idx{1};
7640 let Inst{21} = idx{0};
7643 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7646 asm, ".2d", ".2d", ".2d", ".d",
7647 [(set (v2f64 V128:$Rd),
7648 (OpNode (v2f64 V128:$Rn),
7649 (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7651 let Inst{11} = idx{0};
7655 let Predicates = [HasNEON, HasFullFP16] in {
7656 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7657 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7658 asm, ".h", "", "", ".h",
7659 [(set (f16 FPR16Op:$Rd),
7660 (OpNode (f16 FPR16Op:$Rn),
7661 (f16 (vector_extract (v8f16 V128_lo:$Rm),
7662 VectorIndexH:$idx))))]> {
7664 let Inst{11} = idx{2};
7665 let Inst{21} = idx{1};
7666 let Inst{20} = idx{0};
7668 } // Predicates = [HasNEON, HasFullFP16]
7670 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7671 FPR32Op, FPR32Op, V128, VectorIndexS,
7672 asm, ".s", "", "", ".s",
7673 [(set (f32 FPR32Op:$Rd),
7674 (OpNode (f32 FPR32Op:$Rn),
7675 (f32 (vector_extract (v4f32 V128:$Rm),
7676 VectorIndexS:$idx))))]> {
7678 let Inst{11} = idx{1};
7679 let Inst{21} = idx{0};
7682 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7683 FPR64Op, FPR64Op, V128, VectorIndexD,
7684 asm, ".d", "", "", ".d",
7685 [(set (f64 FPR64Op:$Rd),
7686 (OpNode (f64 FPR64Op:$Rn),
7687 (f64 (vector_extract (v2f64 V128:$Rm),
7688 VectorIndexD:$idx))))]> {
7690 let Inst{11} = idx{0};
7695 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7696 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7697 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7698 (AArch64duplane32 (v4f32 V128:$Rm),
7699 VectorIndexS:$idx))),
7700 (!cast<Instruction>(INST # v2i32_indexed)
7701 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7702 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7703 (AArch64dup (f32 FPR32Op:$Rm)))),
7704 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7705 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7708 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7709 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7710 (AArch64duplane32 (v4f32 V128:$Rm),
7711 VectorIndexS:$idx))),
7712 (!cast<Instruction>(INST # "v4i32_indexed")
7713 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7714 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7715 (AArch64dup (f32 FPR32Op:$Rm)))),
7716 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7717 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7719 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7720 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7721 (AArch64duplane64 (v2f64 V128:$Rm),
7722 VectorIndexD:$idx))),
7723 (!cast<Instruction>(INST # "v2i64_indexed")
7724 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7725 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7726 (AArch64dup (f64 FPR64Op:$Rm)))),
7727 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7728 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7730 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7731 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7732 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7733 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7734 V128:$Rm, VectorIndexS:$idx)>;
7735 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7736 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7737 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7738 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7740 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7741 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7742 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7743 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7744 V128:$Rm, VectorIndexD:$idx)>;
7747 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7748 let Predicates = [HasNEON, HasFullFP16] in {
7749 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7750 V128_lo, VectorIndexH,
7751 asm, ".4h", ".4h", ".4h", ".h", []> {
7753 let Inst{11} = idx{2};
7754 let Inst{21} = idx{1};
7755 let Inst{20} = idx{0};
7758 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7760 V128_lo, VectorIndexH,
7761 asm, ".8h", ".8h", ".8h", ".h", []> {
7763 let Inst{11} = idx{2};
7764 let Inst{21} = idx{1};
7765 let Inst{20} = idx{0};
7767 } // Predicates = [HasNEON, HasFullFP16]
7769 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7771 asm, ".2s", ".2s", ".2s", ".s", []> {
7773 let Inst{11} = idx{1};
7774 let Inst{21} = idx{0};
7777 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7780 asm, ".4s", ".4s", ".4s", ".s", []> {
7782 let Inst{11} = idx{1};
7783 let Inst{21} = idx{0};
7786 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7789 asm, ".2d", ".2d", ".2d", ".d", []> {
7791 let Inst{11} = idx{0};
7795 let Predicates = [HasNEON, HasFullFP16] in {
7796 def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7797 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7798 asm, ".h", "", "", ".h", []> {
7800 let Inst{11} = idx{2};
7801 let Inst{21} = idx{1};
7802 let Inst{20} = idx{0};
7804 } // Predicates = [HasNEON, HasFullFP16]
7806 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7807 FPR32Op, FPR32Op, V128, VectorIndexS,
7808 asm, ".s", "", "", ".s", []> {
7810 let Inst{11} = idx{1};
7811 let Inst{21} = idx{0};
7814 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7815 FPR64Op, FPR64Op, V128, VectorIndexD,
7816 asm, ".d", "", "", ".d", []> {
7818 let Inst{11} = idx{0};
7823 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7824 SDPatternOperator OpNode> {
7825 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7826 V128_lo, VectorIndexH,
7827 asm, ".4h", ".4h", ".4h", ".h",
7828 [(set (v4i16 V64:$Rd),
7829 (OpNode (v4i16 V64:$Rn),
7830 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7832 let Inst{11} = idx{2};
7833 let Inst{21} = idx{1};
7834 let Inst{20} = idx{0};
7837 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7839 V128_lo, VectorIndexH,
7840 asm, ".8h", ".8h", ".8h", ".h",
7841 [(set (v8i16 V128:$Rd),
7842 (OpNode (v8i16 V128:$Rn),
7843 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7845 let Inst{11} = idx{2};
7846 let Inst{21} = idx{1};
7847 let Inst{20} = idx{0};
7850 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7853 asm, ".2s", ".2s", ".2s", ".s",
7854 [(set (v2i32 V64:$Rd),
7855 (OpNode (v2i32 V64:$Rn),
7856 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7858 let Inst{11} = idx{1};
7859 let Inst{21} = idx{0};
7862 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7865 asm, ".4s", ".4s", ".4s", ".s",
7866 [(set (v4i32 V128:$Rd),
7867 (OpNode (v4i32 V128:$Rn),
7868 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7870 let Inst{11} = idx{1};
7871 let Inst{21} = idx{0};
7874 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7875 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7876 asm, ".h", "", "", ".h", []> {
7878 let Inst{11} = idx{2};
7879 let Inst{21} = idx{1};
7880 let Inst{20} = idx{0};
7883 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7884 FPR32Op, FPR32Op, V128, VectorIndexS,
7885 asm, ".s", "", "", ".s",
7886 [(set (i32 FPR32Op:$Rd),
7887 (OpNode FPR32Op:$Rn,
7888 (i32 (vector_extract (v4i32 V128:$Rm),
7889 VectorIndexS:$idx))))]> {
7891 let Inst{11} = idx{1};
7892 let Inst{21} = idx{0};
7896 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7897 SDPatternOperator OpNode> {
7898 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7900 V128_lo, VectorIndexH,
7901 asm, ".4h", ".4h", ".4h", ".h",
7902 [(set (v4i16 V64:$Rd),
7903 (OpNode (v4i16 V64:$Rn),
7904 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7906 let Inst{11} = idx{2};
7907 let Inst{21} = idx{1};
7908 let Inst{20} = idx{0};
7911 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7913 V128_lo, VectorIndexH,
7914 asm, ".8h", ".8h", ".8h", ".h",
7915 [(set (v8i16 V128:$Rd),
7916 (OpNode (v8i16 V128:$Rn),
7917 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7919 let Inst{11} = idx{2};
7920 let Inst{21} = idx{1};
7921 let Inst{20} = idx{0};
7924 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7927 asm, ".2s", ".2s", ".2s", ".s",
7928 [(set (v2i32 V64:$Rd),
7929 (OpNode (v2i32 V64:$Rn),
7930 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7932 let Inst{11} = idx{1};
7933 let Inst{21} = idx{0};
7936 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7939 asm, ".4s", ".4s", ".4s", ".s",
7940 [(set (v4i32 V128:$Rd),
7941 (OpNode (v4i32 V128:$Rn),
7942 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7944 let Inst{11} = idx{1};
7945 let Inst{21} = idx{0};
7949 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7950 SDPatternOperator OpNode> {
7951 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7952 V128_lo, VectorIndexH,
7953 asm, ".4h", ".4h", ".4h", ".h",
7954 [(set (v4i16 V64:$dst),
7955 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7956 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7958 let Inst{11} = idx{2};
7959 let Inst{21} = idx{1};
7960 let Inst{20} = idx{0};
7963 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7965 V128_lo, VectorIndexH,
7966 asm, ".8h", ".8h", ".8h", ".h",
7967 [(set (v8i16 V128:$dst),
7968 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7969 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7971 let Inst{11} = idx{2};
7972 let Inst{21} = idx{1};
7973 let Inst{20} = idx{0};
7976 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7979 asm, ".2s", ".2s", ".2s", ".s",
7980 [(set (v2i32 V64:$dst),
7981 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7982 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7984 let Inst{11} = idx{1};
7985 let Inst{21} = idx{0};
7988 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7991 asm, ".4s", ".4s", ".4s", ".s",
7992 [(set (v4i32 V128:$dst),
7993 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7994 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7996 let Inst{11} = idx{1};
7997 let Inst{21} = idx{0};
8001 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8002 SDPatternOperator OpNode> {
8003 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8005 V128_lo, VectorIndexH,
8006 asm, ".4s", ".4s", ".4h", ".h",
8007 [(set (v4i32 V128:$Rd),
8008 (OpNode (v4i16 V64:$Rn),
8009 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8011 let Inst{11} = idx{2};
8012 let Inst{21} = idx{1};
8013 let Inst{20} = idx{0};
8016 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8018 V128_lo, VectorIndexH,
8019 asm#"2", ".4s", ".4s", ".8h", ".h",
8020 [(set (v4i32 V128:$Rd),
8021 (OpNode (extract_high_v8i16 V128:$Rn),
8022 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8023 VectorIndexH:$idx))))]> {
8026 let Inst{11} = idx{2};
8027 let Inst{21} = idx{1};
8028 let Inst{20} = idx{0};
8031 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8034 asm, ".2d", ".2d", ".2s", ".s",
8035 [(set (v2i64 V128:$Rd),
8036 (OpNode (v2i32 V64:$Rn),
8037 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8039 let Inst{11} = idx{1};
8040 let Inst{21} = idx{0};
8043 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8046 asm#"2", ".2d", ".2d", ".4s", ".s",
8047 [(set (v2i64 V128:$Rd),
8048 (OpNode (extract_high_v4i32 V128:$Rn),
8049 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8050 VectorIndexS:$idx))))]> {
8052 let Inst{11} = idx{1};
8053 let Inst{21} = idx{0};
8056 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8057 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8058 asm, ".h", "", "", ".h", []> {
8060 let Inst{11} = idx{2};
8061 let Inst{21} = idx{1};
8062 let Inst{20} = idx{0};
8065 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8066 FPR64Op, FPR32Op, V128, VectorIndexS,
8067 asm, ".s", "", "", ".s", []> {
8069 let Inst{11} = idx{1};
8070 let Inst{21} = idx{0};
8074 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8075 SDPatternOperator Accum> {
8076 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8078 V128_lo, VectorIndexH,
8079 asm, ".4s", ".4s", ".4h", ".h",
8080 [(set (v4i32 V128:$dst),
8081 (Accum (v4i32 V128:$Rd),
8082 (v4i32 (int_aarch64_neon_sqdmull
8084 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8085 VectorIndexH:$idx))))))]> {
8087 let Inst{11} = idx{2};
8088 let Inst{21} = idx{1};
8089 let Inst{20} = idx{0};
8092 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8093 // intermediate EXTRACT_SUBREG would be untyped.
8094 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8095 (i32 (vector_extract (v4i32
8096 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8097 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8098 VectorIndexH:$idx)))),
8101 (!cast<Instruction>(NAME # v4i16_indexed)
8102 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8103 V128_lo:$Rm, VectorIndexH:$idx),
8106 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8108 V128_lo, VectorIndexH,
8109 asm#"2", ".4s", ".4s", ".8h", ".h",
8110 [(set (v4i32 V128:$dst),
8111 (Accum (v4i32 V128:$Rd),
8112 (v4i32 (int_aarch64_neon_sqdmull
8113 (extract_high_v8i16 V128:$Rn),
8115 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8116 VectorIndexH:$idx))))))]> {
8118 let Inst{11} = idx{2};
8119 let Inst{21} = idx{1};
8120 let Inst{20} = idx{0};
8123 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8126 asm, ".2d", ".2d", ".2s", ".s",
8127 [(set (v2i64 V128:$dst),
8128 (Accum (v2i64 V128:$Rd),
8129 (v2i64 (int_aarch64_neon_sqdmull
8131 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8132 VectorIndexS:$idx))))))]> {
8134 let Inst{11} = idx{1};
8135 let Inst{21} = idx{0};
8138 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8141 asm#"2", ".2d", ".2d", ".4s", ".s",
8142 [(set (v2i64 V128:$dst),
8143 (Accum (v2i64 V128:$Rd),
8144 (v2i64 (int_aarch64_neon_sqdmull
8145 (extract_high_v4i32 V128:$Rn),
8147 (AArch64duplane32 (v4i32 V128:$Rm),
8148 VectorIndexS:$idx))))))]> {
8150 let Inst{11} = idx{1};
8151 let Inst{21} = idx{0};
8154 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8155 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8156 asm, ".h", "", "", ".h", []> {
8158 let Inst{11} = idx{2};
8159 let Inst{21} = idx{1};
8160 let Inst{20} = idx{0};
8164 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8165 FPR64Op, FPR32Op, V128, VectorIndexS,
8166 asm, ".s", "", "", ".s",
8167 [(set (i64 FPR64Op:$dst),
8168 (Accum (i64 FPR64Op:$Rd),
8169 (i64 (int_aarch64_neon_sqdmulls_scalar
8171 (i32 (vector_extract (v4i32 V128:$Rm),
8172 VectorIndexS:$idx))))))]> {
8175 let Inst{11} = idx{1};
8176 let Inst{21} = idx{0};
8180 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8181 SDPatternOperator OpNode> {
8182 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8183 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8185 V128_lo, VectorIndexH,
8186 asm, ".4s", ".4s", ".4h", ".h",
8187 [(set (v4i32 V128:$Rd),
8188 (OpNode (v4i16 V64:$Rn),
8189 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8191 let Inst{11} = idx{2};
8192 let Inst{21} = idx{1};
8193 let Inst{20} = idx{0};
8196 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8198 V128_lo, VectorIndexH,
8199 asm#"2", ".4s", ".4s", ".8h", ".h",
8200 [(set (v4i32 V128:$Rd),
8201 (OpNode (extract_high_v8i16 V128:$Rn),
8202 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8203 VectorIndexH:$idx))))]> {
8206 let Inst{11} = idx{2};
8207 let Inst{21} = idx{1};
8208 let Inst{20} = idx{0};
8211 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8214 asm, ".2d", ".2d", ".2s", ".s",
8215 [(set (v2i64 V128:$Rd),
8216 (OpNode (v2i32 V64:$Rn),
8217 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8219 let Inst{11} = idx{1};
8220 let Inst{21} = idx{0};
8223 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8226 asm#"2", ".2d", ".2d", ".4s", ".s",
8227 [(set (v2i64 V128:$Rd),
8228 (OpNode (extract_high_v4i32 V128:$Rn),
8229 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8230 VectorIndexS:$idx))))]> {
8232 let Inst{11} = idx{1};
8233 let Inst{21} = idx{0};
8238 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8239 SDPatternOperator OpNode> {
8240 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8241 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8243 V128_lo, VectorIndexH,
8244 asm, ".4s", ".4s", ".4h", ".h",
8245 [(set (v4i32 V128:$dst),
8246 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8247 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8249 let Inst{11} = idx{2};
8250 let Inst{21} = idx{1};
8251 let Inst{20} = idx{0};
8254 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8256 V128_lo, VectorIndexH,
8257 asm#"2", ".4s", ".4s", ".8h", ".h",
8258 [(set (v4i32 V128:$dst),
8259 (OpNode (v4i32 V128:$Rd),
8260 (extract_high_v8i16 V128:$Rn),
8261 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8262 VectorIndexH:$idx))))]> {
8264 let Inst{11} = idx{2};
8265 let Inst{21} = idx{1};
8266 let Inst{20} = idx{0};
8269 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8272 asm, ".2d", ".2d", ".2s", ".s",
8273 [(set (v2i64 V128:$dst),
8274 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8275 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8277 let Inst{11} = idx{1};
8278 let Inst{21} = idx{0};
8281 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8284 asm#"2", ".2d", ".2d", ".4s", ".s",
8285 [(set (v2i64 V128:$dst),
8286 (OpNode (v2i64 V128:$Rd),
8287 (extract_high_v4i32 V128:$Rn),
8288 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8289 VectorIndexS:$idx))))]> {
8291 let Inst{11} = idx{1};
8292 let Inst{21} = idx{0};
8297 //----------------------------------------------------------------------------
8298 // AdvSIMD scalar shift by immediate
8299 //----------------------------------------------------------------------------
8301 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8302 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8303 RegisterClass regtype1, RegisterClass regtype2,
8304 Operand immtype, string asm, list<dag> pattern>
8305 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8306 asm, "\t$Rd, $Rn, $imm", "", pattern>,
8311 let Inst{31-30} = 0b01;
8313 let Inst{28-23} = 0b111110;
8314 let Inst{22-16} = fixed_imm;
8315 let Inst{15-11} = opc;
8321 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8322 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8323 RegisterClass regtype1, RegisterClass regtype2,
8324 Operand immtype, string asm, list<dag> pattern>
8325 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8326 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8331 let Inst{31-30} = 0b01;
8333 let Inst{28-23} = 0b111110;
8334 let Inst{22-16} = fixed_imm;
8335 let Inst{15-11} = opc;
8342 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8343 let Predicates = [HasNEON, HasFullFP16] in {
8344 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8345 FPR16, FPR16, vecshiftR16, asm, []> {
8346 let Inst{19-16} = imm{3-0};
8348 } // Predicates = [HasNEON, HasFullFP16]
8349 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8350 FPR32, FPR32, vecshiftR32, asm, []> {
8351 let Inst{20-16} = imm{4-0};
8353 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8354 FPR64, FPR64, vecshiftR64, asm, []> {
8355 let Inst{21-16} = imm{5-0};
8359 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8360 SDPatternOperator OpNode> {
8361 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8362 FPR64, FPR64, vecshiftR64, asm,
8363 [(set (i64 FPR64:$Rd),
8364 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8365 let Inst{21-16} = imm{5-0};
8368 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8369 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8372 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8373 SDPatternOperator OpNode = null_frag> {
8374 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8375 FPR64, FPR64, vecshiftR64, asm,
8376 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8377 (i32 vecshiftR64:$imm)))]> {
8378 let Inst{21-16} = imm{5-0};
8381 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8382 (i32 vecshiftR64:$imm))),
8383 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8387 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8388 SDPatternOperator OpNode> {
8389 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8390 FPR64, FPR64, vecshiftL64, asm,
8391 [(set (v1i64 FPR64:$Rd),
8392 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8393 let Inst{21-16} = imm{5-0};
8397 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8398 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8399 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8400 FPR64, FPR64, vecshiftL64, asm, []> {
8401 let Inst{21-16} = imm{5-0};
8405 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8406 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8407 SDPatternOperator OpNode = null_frag> {
8408 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8409 FPR8, FPR16, vecshiftR8, asm, []> {
8410 let Inst{18-16} = imm{2-0};
8413 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8414 FPR16, FPR32, vecshiftR16, asm, []> {
8415 let Inst{19-16} = imm{3-0};
8418 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8419 FPR32, FPR64, vecshiftR32, asm,
8420 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8421 let Inst{20-16} = imm{4-0};
8425 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8426 SDPatternOperator OpNode> {
8427 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8428 FPR8, FPR8, vecshiftL8, asm, []> {
8429 let Inst{18-16} = imm{2-0};
8432 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8433 FPR16, FPR16, vecshiftL16, asm, []> {
8434 let Inst{19-16} = imm{3-0};
8437 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8438 FPR32, FPR32, vecshiftL32, asm,
8439 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8440 let Inst{20-16} = imm{4-0};
8443 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8444 FPR64, FPR64, vecshiftL64, asm,
8445 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8446 let Inst{21-16} = imm{5-0};
8449 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8450 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8453 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8454 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8455 FPR8, FPR8, vecshiftR8, asm, []> {
8456 let Inst{18-16} = imm{2-0};
8459 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8460 FPR16, FPR16, vecshiftR16, asm, []> {
8461 let Inst{19-16} = imm{3-0};
8464 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8465 FPR32, FPR32, vecshiftR32, asm, []> {
8466 let Inst{20-16} = imm{4-0};
8469 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8470 FPR64, FPR64, vecshiftR64, asm, []> {
8471 let Inst{21-16} = imm{5-0};
8475 //----------------------------------------------------------------------------
8476 // AdvSIMD vector x indexed element
8477 //----------------------------------------------------------------------------
8479 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8480 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8481 RegisterOperand dst_reg, RegisterOperand src_reg,
8483 string asm, string dst_kind, string src_kind,
8485 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8486 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8487 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8494 let Inst{28-23} = 0b011110;
8495 let Inst{22-16} = fixed_imm;
8496 let Inst{15-11} = opc;
8502 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8503 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8504 RegisterOperand vectype1, RegisterOperand vectype2,
8506 string asm, string dst_kind, string src_kind,
8508 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8509 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8510 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8517 let Inst{28-23} = 0b011110;
8518 let Inst{22-16} = fixed_imm;
8519 let Inst{15-11} = opc;
8525 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8527 let Predicates = [HasNEON, HasFullFP16] in {
8528 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8529 V64, V64, vecshiftR16,
8531 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8533 let Inst{19-16} = imm;
8536 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8537 V128, V128, vecshiftR16,
8539 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8541 let Inst{19-16} = imm;
8543 } // Predicates = [HasNEON, HasFullFP16]
8544 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8545 V64, V64, vecshiftR32,
8547 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8549 let Inst{20-16} = imm;
8552 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8553 V128, V128, vecshiftR32,
8555 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8557 let Inst{20-16} = imm;
8560 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8561 V128, V128, vecshiftR64,
8563 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8565 let Inst{21-16} = imm;
8569 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8571 let Predicates = [HasNEON, HasFullFP16] in {
8572 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8573 V64, V64, vecshiftR16,
8575 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8577 let Inst{19-16} = imm;
8580 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8581 V128, V128, vecshiftR16,
8583 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8585 let Inst{19-16} = imm;
8587 } // Predicates = [HasNEON, HasFullFP16]
8589 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8590 V64, V64, vecshiftR32,
8592 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8594 let Inst{20-16} = imm;
8597 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8598 V128, V128, vecshiftR32,
8600 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8602 let Inst{20-16} = imm;
8605 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8606 V128, V128, vecshiftR64,
8608 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8610 let Inst{21-16} = imm;
8614 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8615 SDPatternOperator OpNode> {
8616 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8617 V64, V128, vecshiftR16Narrow,
8619 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8621 let Inst{18-16} = imm;
8624 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8625 V128, V128, vecshiftR16Narrow,
8626 asm#"2", ".16b", ".8h", []> {
8628 let Inst{18-16} = imm;
8629 let hasSideEffects = 0;
8632 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8633 V64, V128, vecshiftR32Narrow,
8635 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8637 let Inst{19-16} = imm;
8640 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8641 V128, V128, vecshiftR32Narrow,
8642 asm#"2", ".8h", ".4s", []> {
8644 let Inst{19-16} = imm;
8645 let hasSideEffects = 0;
8648 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8649 V64, V128, vecshiftR64Narrow,
8651 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8653 let Inst{20-16} = imm;
8656 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8657 V128, V128, vecshiftR64Narrow,
8658 asm#"2", ".4s", ".2d", []> {
8660 let Inst{20-16} = imm;
8661 let hasSideEffects = 0;
8664 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8665 // themselves, so put them here instead.
8667 // Patterns involving what's effectively an insert high and a normal
8668 // intrinsic, represented by CONCAT_VECTORS.
8669 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8670 vecshiftR16Narrow:$imm)),
8671 (!cast<Instruction>(NAME # "v16i8_shift")
8672 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8673 V128:$Rn, vecshiftR16Narrow:$imm)>;
8674 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8675 vecshiftR32Narrow:$imm)),
8676 (!cast<Instruction>(NAME # "v8i16_shift")
8677 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8678 V128:$Rn, vecshiftR32Narrow:$imm)>;
8679 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8680 vecshiftR64Narrow:$imm)),
8681 (!cast<Instruction>(NAME # "v4i32_shift")
8682 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8683 V128:$Rn, vecshiftR64Narrow:$imm)>;
8686 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8687 SDPatternOperator OpNode> {
8688 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8689 V64, V64, vecshiftL8,
8691 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8692 (i32 vecshiftL8:$imm)))]> {
8694 let Inst{18-16} = imm;
8697 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8698 V128, V128, vecshiftL8,
8699 asm, ".16b", ".16b",
8700 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8701 (i32 vecshiftL8:$imm)))]> {
8703 let Inst{18-16} = imm;
8706 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8707 V64, V64, vecshiftL16,
8709 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8710 (i32 vecshiftL16:$imm)))]> {
8712 let Inst{19-16} = imm;
8715 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8716 V128, V128, vecshiftL16,
8718 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8719 (i32 vecshiftL16:$imm)))]> {
8721 let Inst{19-16} = imm;
8724 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8725 V64, V64, vecshiftL32,
8727 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8728 (i32 vecshiftL32:$imm)))]> {
8730 let Inst{20-16} = imm;
8733 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8734 V128, V128, vecshiftL32,
8736 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8737 (i32 vecshiftL32:$imm)))]> {
8739 let Inst{20-16} = imm;
8742 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8743 V128, V128, vecshiftL64,
8745 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8746 (i32 vecshiftL64:$imm)))]> {
8748 let Inst{21-16} = imm;
8752 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8753 SDPatternOperator OpNode> {
8754 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8755 V64, V64, vecshiftR8,
8757 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8758 (i32 vecshiftR8:$imm)))]> {
8760 let Inst{18-16} = imm;
8763 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8764 V128, V128, vecshiftR8,
8765 asm, ".16b", ".16b",
8766 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8767 (i32 vecshiftR8:$imm)))]> {
8769 let Inst{18-16} = imm;
8772 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8773 V64, V64, vecshiftR16,
8775 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8776 (i32 vecshiftR16:$imm)))]> {
8778 let Inst{19-16} = imm;
8781 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8782 V128, V128, vecshiftR16,
8784 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8785 (i32 vecshiftR16:$imm)))]> {
8787 let Inst{19-16} = imm;
8790 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8791 V64, V64, vecshiftR32,
8793 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8794 (i32 vecshiftR32:$imm)))]> {
8796 let Inst{20-16} = imm;
8799 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8800 V128, V128, vecshiftR32,
8802 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8803 (i32 vecshiftR32:$imm)))]> {
8805 let Inst{20-16} = imm;
8808 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8809 V128, V128, vecshiftR64,
8811 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8812 (i32 vecshiftR64:$imm)))]> {
8814 let Inst{21-16} = imm;
8818 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8819 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8820 SDPatternOperator OpNode = null_frag> {
8821 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8822 V64, V64, vecshiftR8, asm, ".8b", ".8b",
8823 [(set (v8i8 V64:$dst),
8824 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8825 (i32 vecshiftR8:$imm)))]> {
8827 let Inst{18-16} = imm;
8830 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8831 V128, V128, vecshiftR8, asm, ".16b", ".16b",
8832 [(set (v16i8 V128:$dst),
8833 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8834 (i32 vecshiftR8:$imm)))]> {
8836 let Inst{18-16} = imm;
8839 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8840 V64, V64, vecshiftR16, asm, ".4h", ".4h",
8841 [(set (v4i16 V64:$dst),
8842 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8843 (i32 vecshiftR16:$imm)))]> {
8845 let Inst{19-16} = imm;
8848 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8849 V128, V128, vecshiftR16, asm, ".8h", ".8h",
8850 [(set (v8i16 V128:$dst),
8851 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8852 (i32 vecshiftR16:$imm)))]> {
8854 let Inst{19-16} = imm;
8857 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8858 V64, V64, vecshiftR32, asm, ".2s", ".2s",
8859 [(set (v2i32 V64:$dst),
8860 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8861 (i32 vecshiftR32:$imm)))]> {
8863 let Inst{20-16} = imm;
8866 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8867 V128, V128, vecshiftR32, asm, ".4s", ".4s",
8868 [(set (v4i32 V128:$dst),
8869 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8870 (i32 vecshiftR32:$imm)))]> {
8872 let Inst{20-16} = imm;
8875 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8876 V128, V128, vecshiftR64,
8877 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8878 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8879 (i32 vecshiftR64:$imm)))]> {
8881 let Inst{21-16} = imm;
8885 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8886 SDPatternOperator OpNode = null_frag> {
8887 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8888 V64, V64, vecshiftL8,
8890 [(set (v8i8 V64:$dst),
8891 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8892 (i32 vecshiftL8:$imm)))]> {
8894 let Inst{18-16} = imm;
8897 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8898 V128, V128, vecshiftL8,
8899 asm, ".16b", ".16b",
8900 [(set (v16i8 V128:$dst),
8901 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8902 (i32 vecshiftL8:$imm)))]> {
8904 let Inst{18-16} = imm;
8907 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8908 V64, V64, vecshiftL16,
8910 [(set (v4i16 V64:$dst),
8911 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8912 (i32 vecshiftL16:$imm)))]> {
8914 let Inst{19-16} = imm;
8917 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8918 V128, V128, vecshiftL16,
8920 [(set (v8i16 V128:$dst),
8921 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8922 (i32 vecshiftL16:$imm)))]> {
8924 let Inst{19-16} = imm;
8927 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8928 V64, V64, vecshiftL32,
8930 [(set (v2i32 V64:$dst),
8931 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8932 (i32 vecshiftL32:$imm)))]> {
8934 let Inst{20-16} = imm;
8937 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8938 V128, V128, vecshiftL32,
8940 [(set (v4i32 V128:$dst),
8941 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8942 (i32 vecshiftL32:$imm)))]> {
8944 let Inst{20-16} = imm;
8947 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8948 V128, V128, vecshiftL64,
8950 [(set (v2i64 V128:$dst),
8951 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8952 (i32 vecshiftL64:$imm)))]> {
8954 let Inst{21-16} = imm;
8958 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8959 SDPatternOperator OpNode> {
8960 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8961 V128, V64, vecshiftL8, asm, ".8h", ".8b",
8962 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8964 let Inst{18-16} = imm;
8967 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8968 V128, V128, vecshiftL8,
8969 asm#"2", ".8h", ".16b",
8970 [(set (v8i16 V128:$Rd),
8971 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8973 let Inst{18-16} = imm;
8976 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8977 V128, V64, vecshiftL16, asm, ".4s", ".4h",
8978 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8980 let Inst{19-16} = imm;
8983 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8984 V128, V128, vecshiftL16,
8985 asm#"2", ".4s", ".8h",
8986 [(set (v4i32 V128:$Rd),
8987 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8990 let Inst{19-16} = imm;
8993 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8994 V128, V64, vecshiftL32, asm, ".2d", ".2s",
8995 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8997 let Inst{20-16} = imm;
9000 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9001 V128, V128, vecshiftL32,
9002 asm#"2", ".2d", ".4s",
9003 [(set (v2i64 V128:$Rd),
9004 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9006 let Inst{20-16} = imm;
9012 // Vector load/store
9014 // SIMD ldX/stX no-index memory references don't allow the optional
9015 // ", #0" constant and handle post-indexing explicitly, so we use
9016 // a more specialized parse method for them. Otherwise, it's the same as
9017 // the general GPR64sp handling.
9019 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9020 string asm, dag oops, dag iops, list<dag> pattern>
9021 : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9026 let Inst{29-23} = 0b0011000;
9028 let Inst{21-16} = 0b000000;
9029 let Inst{15-12} = opcode;
9030 let Inst{11-10} = size;
9035 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9036 string asm, dag oops, dag iops>
9037 : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9043 let Inst{29-23} = 0b0011001;
9046 let Inst{20-16} = Xm;
9047 let Inst{15-12} = opcode;
9048 let Inst{11-10} = size;
9053 // The immediate form of AdvSIMD post-indexed addressing is encoded with
9054 // register post-index addressing from the zero register.
9055 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9056 int Offset, int Size> {
9057 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9058 // "ld1\t$Vt, [$Rn], #16"
9059 // may get mapped to
9060 // (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9061 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9062 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9064 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9067 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9068 // "ld1.8b\t$Vt, [$Rn], #16"
9069 // may get mapped to
9070 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9071 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9072 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9074 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9077 // E.g. "ld1.8b { v0, v1 }, [x1]"
9078 // "ld1\t$Vt, [$Rn]"
9079 // may get mapped to
9080 // (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9081 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9082 (!cast<Instruction>(BaseName # Count # "v" # layout)
9083 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9086 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9087 // "ld1\t$Vt, [$Rn], $Xm"
9088 // may get mapped to
9089 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9090 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9091 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9093 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9094 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9097 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9098 int Offset128, int Offset64, bits<4> opcode> {
9099 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9100 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9101 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9102 (ins GPR64sp:$Rn), []>;
9103 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9104 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9105 (ins GPR64sp:$Rn), []>;
9106 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9107 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9108 (ins GPR64sp:$Rn), []>;
9109 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9110 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9111 (ins GPR64sp:$Rn), []>;
9112 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9113 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9114 (ins GPR64sp:$Rn), []>;
9115 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9116 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9117 (ins GPR64sp:$Rn), []>;
9118 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9119 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9120 (ins GPR64sp:$Rn), []>;
9123 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9124 (outs GPR64sp:$wback,
9125 !cast<RegisterOperand>(veclist # "16b"):$Vt),
9127 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9128 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9129 (outs GPR64sp:$wback,
9130 !cast<RegisterOperand>(veclist # "8h"):$Vt),
9132 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9133 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9134 (outs GPR64sp:$wback,
9135 !cast<RegisterOperand>(veclist # "4s"):$Vt),
9137 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9138 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9139 (outs GPR64sp:$wback,
9140 !cast<RegisterOperand>(veclist # "2d"):$Vt),
9142 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9143 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9144 (outs GPR64sp:$wback,
9145 !cast<RegisterOperand>(veclist # "8b"):$Vt),
9147 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9148 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9149 (outs GPR64sp:$wback,
9150 !cast<RegisterOperand>(veclist # "4h"):$Vt),
9152 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9153 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9154 (outs GPR64sp:$wback,
9155 !cast<RegisterOperand>(veclist # "2s"):$Vt),
9157 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9160 defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9161 defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9162 defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9163 defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9164 defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9165 defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9166 defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9169 // Only ld1/st1 has a v1d version.
9170 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9171 int Offset128, int Offset64, bits<4> opcode> {
9172 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9173 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9174 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9176 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9177 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9179 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9180 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9182 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9183 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9185 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9186 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9188 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9189 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9191 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9192 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9195 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9196 (outs GPR64sp:$wback),
9197 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9199 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9200 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9201 (outs GPR64sp:$wback),
9202 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9204 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9205 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9206 (outs GPR64sp:$wback),
9207 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9209 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9210 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9211 (outs GPR64sp:$wback),
9212 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9214 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9215 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9216 (outs GPR64sp:$wback),
9217 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9219 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9220 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9221 (outs GPR64sp:$wback),
9222 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9224 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9225 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9226 (outs GPR64sp:$wback),
9227 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9229 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9232 defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9233 defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9234 defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9235 defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9236 defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9237 defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9238 defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9241 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9242 int Offset128, int Offset64, bits<4> opcode>
9243 : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9245 // LD1 instructions have extra "1d" variants.
9246 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9247 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9248 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9249 (ins GPR64sp:$Rn), []>;
9251 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9252 (outs GPR64sp:$wback,
9253 !cast<RegisterOperand>(veclist # "1d"):$Vt),
9255 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9258 defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9261 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9262 int Offset128, int Offset64, bits<4> opcode>
9263 : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9265 // ST1 instructions have extra "1d" variants.
9266 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9267 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9268 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9271 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9272 (outs GPR64sp:$wback),
9273 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9275 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9278 defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9281 multiclass SIMDLd1Multiple<string asm> {
9282 defm One : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8, 0b0111>;
9283 defm Two : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9284 defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9285 defm Four : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9288 multiclass SIMDSt1Multiple<string asm> {
9289 defm One : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8, 0b0111>;
9290 defm Two : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9291 defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9292 defm Four : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9295 multiclass SIMDLd2Multiple<string asm> {
9296 defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9299 multiclass SIMDSt2Multiple<string asm> {
9300 defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9303 multiclass SIMDLd3Multiple<string asm> {
9304 defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9307 multiclass SIMDSt3Multiple<string asm> {
9308 defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9311 multiclass SIMDLd4Multiple<string asm> {
9312 defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9315 multiclass SIMDSt4Multiple<string asm> {
9316 defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9320 // AdvSIMD Load/store single-element
9323 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9324 string asm, string operands, string cst,
9325 dag oops, dag iops, list<dag> pattern>
9326 : I<oops, iops, asm, operands, cst, pattern> {
9330 let Inst{29-24} = 0b001101;
9333 let Inst{15-13} = opcode;
9338 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9339 string asm, string operands, string cst,
9340 dag oops, dag iops, list<dag> pattern>
9341 : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9345 let Inst{29-24} = 0b001101;
9348 let Inst{15-13} = opcode;
9354 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9355 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9356 DAGOperand listtype>
9357 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9358 (outs listtype:$Vt), (ins GPR64sp:$Rn),
9362 let Inst{20-16} = 0b00000;
9364 let Inst{11-10} = size;
9366 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9367 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9368 string asm, DAGOperand listtype, DAGOperand GPR64pi>
9369 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9371 (outs GPR64sp:$wback, listtype:$Vt),
9372 (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9376 let Inst{20-16} = Xm;
9378 let Inst{11-10} = size;
9381 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9382 int Offset, int Size> {
9383 // E.g. "ld1r { v0.8b }, [x1], #1"
9384 // "ld1r.8b\t$Vt, [$Rn], #1"
9385 // may get mapped to
9386 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9387 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9388 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9390 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9393 // E.g. "ld1r.8b { v0 }, [x1], #1"
9394 // "ld1r.8b\t$Vt, [$Rn], #1"
9395 // may get mapped to
9396 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9397 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9398 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9400 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9403 // E.g. "ld1r.8b { v0 }, [x1]"
9404 // "ld1r.8b\t$Vt, [$Rn]"
9405 // may get mapped to
9406 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9407 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9408 (!cast<Instruction>(BaseName # "v" # layout)
9409 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9412 // E.g. "ld1r.8b { v0 }, [x1], x2"
9413 // "ld1r.8b\t$Vt, [$Rn], $Xm"
9414 // may get mapped to
9415 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9416 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9417 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9419 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9420 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9423 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9424 int Offset1, int Offset2, int Offset4, int Offset8> {
9425 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9426 !cast<DAGOperand>("VecList" # Count # "8b")>;
9427 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9428 !cast<DAGOperand>("VecList" # Count #"16b")>;
9429 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9430 !cast<DAGOperand>("VecList" # Count #"4h")>;
9431 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9432 !cast<DAGOperand>("VecList" # Count #"8h")>;
9433 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9434 !cast<DAGOperand>("VecList" # Count #"2s")>;
9435 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9436 !cast<DAGOperand>("VecList" # Count #"4s")>;
9437 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9438 !cast<DAGOperand>("VecList" # Count #"1d")>;
9439 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9440 !cast<DAGOperand>("VecList" # Count #"2d")>;
9442 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9443 !cast<DAGOperand>("VecList" # Count # "8b"),
9444 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9445 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9446 !cast<DAGOperand>("VecList" # Count # "16b"),
9447 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9448 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9449 !cast<DAGOperand>("VecList" # Count # "4h"),
9450 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9451 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9452 !cast<DAGOperand>("VecList" # Count # "8h"),
9453 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9454 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9455 !cast<DAGOperand>("VecList" # Count # "2s"),
9456 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9457 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9458 !cast<DAGOperand>("VecList" # Count # "4s"),
9459 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9460 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9461 !cast<DAGOperand>("VecList" # Count # "1d"),
9462 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9463 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9464 !cast<DAGOperand>("VecList" # Count # "2d"),
9465 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9467 defm : SIMDLdrAliases<NAME, asm, "8b", Count, Offset1, 64>;
9468 defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9469 defm : SIMDLdrAliases<NAME, asm, "4h", Count, Offset2, 64>;
9470 defm : SIMDLdrAliases<NAME, asm, "8h", Count, Offset2, 128>;
9471 defm : SIMDLdrAliases<NAME, asm, "2s", Count, Offset4, 64>;
9472 defm : SIMDLdrAliases<NAME, asm, "4s", Count, Offset4, 128>;
9473 defm : SIMDLdrAliases<NAME, asm, "1d", Count, Offset8, 64>;
9474 defm : SIMDLdrAliases<NAME, asm, "2d", Count, Offset8, 128>;
9477 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9478 dag oops, dag iops, list<dag> pattern>
9479 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9481 // idx encoded in Q:S:size fields.
9483 let Inst{30} = idx{3};
9485 let Inst{20-16} = 0b00000;
9486 let Inst{12} = idx{2};
9487 let Inst{11-10} = idx{1-0};
9489 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9490 dag oops, dag iops, list<dag> pattern>
9491 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9492 oops, iops, pattern> {
9493 // idx encoded in Q:S:size fields.
9495 let Inst{30} = idx{3};
9497 let Inst{20-16} = 0b00000;
9498 let Inst{12} = idx{2};
9499 let Inst{11-10} = idx{1-0};
9501 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9503 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9504 "$Rn = $wback", oops, iops, []> {
9505 // idx encoded in Q:S:size fields.
9508 let Inst{30} = idx{3};
9510 let Inst{20-16} = Xm;
9511 let Inst{12} = idx{2};
9512 let Inst{11-10} = idx{1-0};
9514 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9516 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9517 "$Rn = $wback", oops, iops, []> {
9518 // idx encoded in Q:S:size fields.
9521 let Inst{30} = idx{3};
9523 let Inst{20-16} = Xm;
9524 let Inst{12} = idx{2};
9525 let Inst{11-10} = idx{1-0};
9528 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9529 dag oops, dag iops, list<dag> pattern>
9530 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9532 // idx encoded in Q:S:size<1> fields.
9534 let Inst{30} = idx{2};
9536 let Inst{20-16} = 0b00000;
9537 let Inst{12} = idx{1};
9538 let Inst{11} = idx{0};
9539 let Inst{10} = size;
9541 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9542 dag oops, dag iops, list<dag> pattern>
9543 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9544 oops, iops, pattern> {
9545 // idx encoded in Q:S:size<1> fields.
9547 let Inst{30} = idx{2};
9549 let Inst{20-16} = 0b00000;
9550 let Inst{12} = idx{1};
9551 let Inst{11} = idx{0};
9552 let Inst{10} = size;
9555 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9557 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9558 "$Rn = $wback", oops, iops, []> {
9559 // idx encoded in Q:S:size<1> fields.
9562 let Inst{30} = idx{2};
9564 let Inst{20-16} = Xm;
9565 let Inst{12} = idx{1};
9566 let Inst{11} = idx{0};
9567 let Inst{10} = size;
9569 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9571 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9572 "$Rn = $wback", oops, iops, []> {
9573 // idx encoded in Q:S:size<1> fields.
9576 let Inst{30} = idx{2};
9578 let Inst{20-16} = Xm;
9579 let Inst{12} = idx{1};
9580 let Inst{11} = idx{0};
9581 let Inst{10} = size;
9583 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9584 dag oops, dag iops, list<dag> pattern>
9585 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9587 // idx encoded in Q:S fields.
9589 let Inst{30} = idx{1};
9591 let Inst{20-16} = 0b00000;
9592 let Inst{12} = idx{0};
9593 let Inst{11-10} = size;
9595 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9596 dag oops, dag iops, list<dag> pattern>
9597 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9598 oops, iops, pattern> {
9599 // idx encoded in Q:S fields.
9601 let Inst{30} = idx{1};
9603 let Inst{20-16} = 0b00000;
9604 let Inst{12} = idx{0};
9605 let Inst{11-10} = size;
9607 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9608 string asm, dag oops, dag iops>
9609 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9610 "$Rn = $wback", oops, iops, []> {
9611 // idx encoded in Q:S fields.
9614 let Inst{30} = idx{1};
9616 let Inst{20-16} = Xm;
9617 let Inst{12} = idx{0};
9618 let Inst{11-10} = size;
9620 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9621 string asm, dag oops, dag iops>
9622 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9623 "$Rn = $wback", oops, iops, []> {
9624 // idx encoded in Q:S fields.
9627 let Inst{30} = idx{1};
9629 let Inst{20-16} = Xm;
9630 let Inst{12} = idx{0};
9631 let Inst{11-10} = size;
9633 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9634 dag oops, dag iops, list<dag> pattern>
9635 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9637 // idx encoded in Q field.
9641 let Inst{20-16} = 0b00000;
9643 let Inst{11-10} = size;
9645 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9646 dag oops, dag iops, list<dag> pattern>
9647 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9648 oops, iops, pattern> {
9649 // idx encoded in Q field.
9653 let Inst{20-16} = 0b00000;
9655 let Inst{11-10} = size;
9657 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9658 string asm, dag oops, dag iops>
9659 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9660 "$Rn = $wback", oops, iops, []> {
9661 // idx encoded in Q field.
9666 let Inst{20-16} = Xm;
9668 let Inst{11-10} = size;
9670 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9671 string asm, dag oops, dag iops>
9672 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9673 "$Rn = $wback", oops, iops, []> {
9674 // idx encoded in Q field.
9679 let Inst{20-16} = Xm;
9681 let Inst{11-10} = size;
9684 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9685 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9686 RegisterOperand listtype,
9687 RegisterOperand GPR64pi> {
9688 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9689 (outs listtype:$dst),
9690 (ins listtype:$Vt, VectorIndexB:$idx,
9693 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9694 (outs GPR64sp:$wback, listtype:$dst),
9695 (ins listtype:$Vt, VectorIndexB:$idx,
9696 GPR64sp:$Rn, GPR64pi:$Xm)>;
9698 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9699 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9700 RegisterOperand listtype,
9701 RegisterOperand GPR64pi> {
9702 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9703 (outs listtype:$dst),
9704 (ins listtype:$Vt, VectorIndexH:$idx,
9707 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9708 (outs GPR64sp:$wback, listtype:$dst),
9709 (ins listtype:$Vt, VectorIndexH:$idx,
9710 GPR64sp:$Rn, GPR64pi:$Xm)>;
9712 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9713 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9714 RegisterOperand listtype,
9715 RegisterOperand GPR64pi> {
9716 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9717 (outs listtype:$dst),
9718 (ins listtype:$Vt, VectorIndexS:$idx,
9721 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9722 (outs GPR64sp:$wback, listtype:$dst),
9723 (ins listtype:$Vt, VectorIndexS:$idx,
9724 GPR64sp:$Rn, GPR64pi:$Xm)>;
9726 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9727 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9728 RegisterOperand listtype, RegisterOperand GPR64pi> {
9729 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9730 (outs listtype:$dst),
9731 (ins listtype:$Vt, VectorIndexD:$idx,
9734 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9735 (outs GPR64sp:$wback, listtype:$dst),
9736 (ins listtype:$Vt, VectorIndexD:$idx,
9737 GPR64sp:$Rn, GPR64pi:$Xm)>;
9739 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9740 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9741 RegisterOperand listtype, RegisterOperand GPR64pi> {
9742 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9743 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9746 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9747 (outs GPR64sp:$wback),
9748 (ins listtype:$Vt, VectorIndexB:$idx,
9749 GPR64sp:$Rn, GPR64pi:$Xm)>;
9751 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9752 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9753 RegisterOperand listtype, RegisterOperand GPR64pi> {
9754 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9755 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9758 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9759 (outs GPR64sp:$wback),
9760 (ins listtype:$Vt, VectorIndexH:$idx,
9761 GPR64sp:$Rn, GPR64pi:$Xm)>;
9763 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9764 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9765 RegisterOperand listtype, RegisterOperand GPR64pi> {
9766 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9767 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9770 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9771 (outs GPR64sp:$wback),
9772 (ins listtype:$Vt, VectorIndexS:$idx,
9773 GPR64sp:$Rn, GPR64pi:$Xm)>;
9775 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9776 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9777 RegisterOperand listtype, RegisterOperand GPR64pi> {
9778 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9779 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9782 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9783 (outs GPR64sp:$wback),
9784 (ins listtype:$Vt, VectorIndexD:$idx,
9785 GPR64sp:$Rn, GPR64pi:$Xm)>;
9788 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9789 string Count, int Offset, Operand idxtype> {
9790 // E.g. "ld1 { v0.8b }[0], [x1], #1"
9791 // "ld1\t$Vt, [$Rn], #1"
9792 // may get mapped to
9793 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9794 def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9795 (!cast<Instruction>(NAME # Type # "_POST")
9797 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9798 idxtype:$idx, XZR), 1>;
9800 // E.g. "ld1.8b { v0 }[0], [x1], #1"
9801 // "ld1.8b\t$Vt, [$Rn], #1"
9802 // may get mapped to
9803 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9804 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9805 (!cast<Instruction>(NAME # Type # "_POST")
9807 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9808 idxtype:$idx, XZR), 0>;
9810 // E.g. "ld1.8b { v0 }[0], [x1]"
9811 // "ld1.8b\t$Vt, [$Rn]"
9812 // may get mapped to
9813 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9814 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9815 (!cast<Instruction>(NAME # Type)
9816 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9817 idxtype:$idx, GPR64sp:$Rn), 0>;
9819 // E.g. "ld1.8b { v0 }[0], [x1], x2"
9820 // "ld1.8b\t$Vt, [$Rn], $Xm"
9821 // may get mapped to
9822 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9823 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9824 (!cast<Instruction>(NAME # Type # "_POST")
9826 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9828 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9831 multiclass SIMDLdSt1SingleAliases<string asm> {
9832 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
9833 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9834 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9835 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9838 multiclass SIMDLdSt2SingleAliases<string asm> {
9839 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
9840 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
9841 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
9842 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9845 multiclass SIMDLdSt3SingleAliases<string asm> {
9846 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
9847 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
9848 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9849 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9852 multiclass SIMDLdSt4SingleAliases<string asm> {
9853 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
9854 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
9855 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9856 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9858 } // end of 'let Predicates = [HasNEON]'
9860 //----------------------------------------------------------------------------
9861 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9862 //----------------------------------------------------------------------------
9864 let Predicates = [HasNEON, HasRDM] in {
9866 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9867 RegisterOperand regtype, string asm,
9868 string kind, list<dag> pattern>
9869 : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9872 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9873 SDPatternOperator Accum> {
9874 def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9875 [(set (v4i16 V64:$dst),
9876 (Accum (v4i16 V64:$Rd),
9877 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9878 (v4i16 V64:$Rm)))))]>;
9879 def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9880 [(set (v8i16 V128:$dst),
9881 (Accum (v8i16 V128:$Rd),
9882 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9883 (v8i16 V128:$Rm)))))]>;
9884 def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9885 [(set (v2i32 V64:$dst),
9886 (Accum (v2i32 V64:$Rd),
9887 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9888 (v2i32 V64:$Rm)))))]>;
9889 def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9890 [(set (v4i32 V128:$dst),
9891 (Accum (v4i32 V128:$Rd),
9892 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9893 (v4i32 V128:$Rm)))))]>;
9896 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9897 SDPatternOperator Accum> {
9898 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9899 V64, V64, V128_lo, VectorIndexH,
9900 asm, ".4h", ".4h", ".4h", ".h",
9901 [(set (v4i16 V64:$dst),
9902 (Accum (v4i16 V64:$Rd),
9903 (v4i16 (int_aarch64_neon_sqrdmulh
9905 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9906 VectorIndexH:$idx))))))]> {
9908 let Inst{11} = idx{2};
9909 let Inst{21} = idx{1};
9910 let Inst{20} = idx{0};
9913 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9914 V128, V128, V128_lo, VectorIndexH,
9915 asm, ".8h", ".8h", ".8h", ".h",
9916 [(set (v8i16 V128:$dst),
9917 (Accum (v8i16 V128:$Rd),
9918 (v8i16 (int_aarch64_neon_sqrdmulh
9920 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9921 VectorIndexH:$idx))))))]> {
9923 let Inst{11} = idx{2};
9924 let Inst{21} = idx{1};
9925 let Inst{20} = idx{0};
9928 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9929 V64, V64, V128, VectorIndexS,
9930 asm, ".2s", ".2s", ".2s", ".s",
9931 [(set (v2i32 V64:$dst),
9932 (Accum (v2i32 V64:$Rd),
9933 (v2i32 (int_aarch64_neon_sqrdmulh
9935 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9936 VectorIndexS:$idx))))))]> {
9938 let Inst{11} = idx{1};
9939 let Inst{21} = idx{0};
9942 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9943 // an intermediate EXTRACT_SUBREG would be untyped.
9944 // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9945 // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9946 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9947 (i32 (vector_extract
9948 (v4i32 (insert_subvector
9950 (v2i32 (int_aarch64_neon_sqrdmulh
9952 (v2i32 (AArch64duplane32
9954 VectorIndexS:$idx)))),
9958 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9959 (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9964 VectorIndexS:$idx)),
9967 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9968 V128, V128, V128, VectorIndexS,
9969 asm, ".4s", ".4s", ".4s", ".s",
9970 [(set (v4i32 V128:$dst),
9971 (Accum (v4i32 V128:$Rd),
9972 (v4i32 (int_aarch64_neon_sqrdmulh
9974 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9975 VectorIndexS:$idx))))))]> {
9977 let Inst{11} = idx{1};
9978 let Inst{21} = idx{0};
9981 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9982 // an intermediate EXTRACT_SUBREG would be untyped.
9983 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9984 (i32 (vector_extract
9985 (v4i32 (int_aarch64_neon_sqrdmulh
9987 (v4i32 (AArch64duplane32
9989 VectorIndexS:$idx)))),
9992 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9993 (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9998 VectorIndexS:$idx)),
10001 def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10002 FPR16Op, FPR16Op, V128_lo,
10003 VectorIndexH, asm, ".h", "", "", ".h",
10006 let Inst{11} = idx{2};
10007 let Inst{21} = idx{1};
10008 let Inst{20} = idx{0};
10011 def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10012 FPR32Op, FPR32Op, V128, VectorIndexS,
10013 asm, ".s", "", "", ".s",
10014 [(set (i32 FPR32Op:$dst),
10015 (Accum (i32 FPR32Op:$Rd),
10016 (i32 (int_aarch64_neon_sqrdmulh
10018 (i32 (vector_extract (v4i32 V128:$Rm),
10019 VectorIndexS:$idx))))))]> {
10021 let Inst{11} = idx{1};
10022 let Inst{21} = idx{0};
10025 } // let Predicates = [HasNeon, HasRDM]
10027 //----------------------------------------------------------------------------
10028 // ARMv8.3 Complex ADD/MLA instructions
10029 //----------------------------------------------------------------------------
10031 class ComplexRotationOperand<int Angle, int Remainder, string Type>
10032 : AsmOperandClass {
10033 let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10034 let DiagnosticType = "InvalidComplexRotation" # Type;
10035 let Name = "ComplexRotation" # Type;
10037 def complexrotateop : Operand<i32> {
10038 let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10039 let PrintMethod = "printComplexRotationOp<90, 0>";
10041 def complexrotateopodd : Operand<i32> {
10042 let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10043 let PrintMethod = "printComplexRotationOp<180, 90>";
10046 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10047 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10048 RegisterOperand regtype, Operand rottype,
10049 string asm, string kind, list<dag> pattern>
10050 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10051 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10052 "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10061 let Inst{28-24} = 0b01110;
10062 let Inst{23-22} = size;
10064 let Inst{20-16} = Rm;
10065 let Inst{15-13} = opcode;
10066 // Non-tied version (FCADD) only has one rotation bit
10067 let Inst{12} = rot;
10070 let Inst{9-5} = Rn;
10071 let Inst{4-0} = Rd;
10074 //8.3 CompNum - Floating-point complex number support
10075 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10076 string asm, SDPatternOperator OpNode>{
10077 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10078 def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10080 [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10083 (rottype i32:$rot)))]>;
10085 def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10087 [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10090 (rottype i32:$rot)))]>;
10093 let Predicates = [HasComplxNum, HasNEON] in {
10094 def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10096 [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10099 (rottype i32:$rot)))]>;
10101 def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10103 [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10106 (rottype i32:$rot)))]>;
10108 def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10110 [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10113 (rottype i32:$rot)))]>;
10117 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10118 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10120 RegisterOperand regtype,
10121 Operand rottype, string asm,
10122 string kind, list<dag> pattern>
10123 : I<(outs regtype:$dst),
10124 (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10125 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10126 "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10135 let Inst{28-24} = 0b01110;
10136 let Inst{23-22} = size;
10138 let Inst{20-16} = Rm;
10139 let Inst{15-13} = opcode;
10140 let Inst{12-11} = rot;
10142 let Inst{9-5} = Rn;
10143 let Inst{4-0} = Rd;
10146 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10147 Operand rottype, string asm,
10148 SDPatternOperator OpNode> {
10149 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10150 def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10151 rottype, asm, ".4h",
10152 [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10155 (rottype i32:$rot)))]>;
10157 def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10158 rottype, asm, ".8h",
10159 [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10162 (rottype i32:$rot)))]>;
10165 let Predicates = [HasComplxNum, HasNEON] in {
10166 def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10167 rottype, asm, ".2s",
10168 [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10171 (rottype i32:$rot)))]>;
10173 def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10174 rottype, asm, ".4s",
10175 [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10178 (rottype i32:$rot)))]>;
10180 def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10181 rottype, asm, ".2d",
10182 [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10185 (rottype i32:$rot)))]>;
10189 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10190 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10191 bit opc1, bit opc2, RegisterOperand dst_reg,
10192 RegisterOperand lhs_reg,
10193 RegisterOperand rhs_reg, Operand vec_idx,
10194 Operand rottype, string asm, string apple_kind,
10195 string dst_kind, string lhs_kind,
10196 string rhs_kind, list<dag> pattern>
10197 : I<(outs dst_reg:$dst),
10198 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10200 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10201 "$idx, $rot" # "|" # apple_kind #
10202 "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10212 let Inst{28} = Scalar;
10213 let Inst{27-24} = 0b1111;
10214 let Inst{23-22} = size;
10215 // Bit 21 must be set by the derived class.
10216 let Inst{20-16} = Rm;
10217 let Inst{15} = opc1;
10218 let Inst{14-13} = rot;
10219 let Inst{12} = opc2;
10220 // Bit 11 must be set by the derived class.
10222 let Inst{9-5} = Rn;
10223 let Inst{4-0} = Rd;
10226 // The complex instructions index by pairs of elements, so the VectorIndexes
10227 // don't match the lane types, and the index bits are different to the other
10229 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10230 string asm, SDPatternOperator OpNode> {
10231 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10232 def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10233 V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10237 let Inst{21} = idx{0};
10240 def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10241 V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10242 ".8h", ".8h", ".h", []> {
10244 let Inst{11} = idx{1};
10245 let Inst{21} = idx{0};
10247 } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10249 let Predicates = [HasComplxNum, HasNEON] in {
10250 def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10251 V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10252 ".4s", ".4s", ".s", []> {
10254 let Inst{11} = idx{0};
10257 } // Predicates = [HasComplxNum, HasNEON]
10260 //----------------------------------------------------------------------------
10261 // Crypto extensions
10262 //----------------------------------------------------------------------------
10264 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10265 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10267 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10271 let Inst{31-16} = 0b0100111000101000;
10272 let Inst{15-12} = opc;
10273 let Inst{11-10} = 0b10;
10274 let Inst{9-5} = Rn;
10275 let Inst{4-0} = Rd;
10278 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10279 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10280 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10282 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10283 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10285 [(set (v16i8 V128:$dst),
10286 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10288 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10289 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10290 dag oops, dag iops, list<dag> pat>
10291 : I<oops, iops, asm,
10292 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10293 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10298 let Inst{31-21} = 0b01011110000;
10299 let Inst{20-16} = Rm;
10301 let Inst{14-12} = opc;
10302 let Inst{11-10} = 0b00;
10303 let Inst{9-5} = Rn;
10304 let Inst{4-0} = Rd;
10307 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10308 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10309 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10310 [(set (v4i32 FPR128:$dst),
10311 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10312 (v4i32 V128:$Rm)))]>;
10314 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10315 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10316 (ins V128:$Rd, V128:$Rn, V128:$Rm),
10317 [(set (v4i32 V128:$dst),
10318 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10319 (v4i32 V128:$Rm)))]>;
10321 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10322 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10323 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10324 [(set (v4i32 FPR128:$dst),
10325 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10326 (v4i32 V128:$Rm)))]>;
10328 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10329 class SHA2OpInst<bits<4> opc, string asm, string kind,
10330 string cstr, dag oops, dag iops,
10332 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10333 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10337 let Inst{31-16} = 0b0101111000101000;
10338 let Inst{15-12} = opc;
10339 let Inst{11-10} = 0b10;
10340 let Inst{9-5} = Rn;
10341 let Inst{4-0} = Rd;
10344 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10345 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10346 (ins V128:$Rd, V128:$Rn),
10347 [(set (v4i32 V128:$dst),
10348 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10350 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10351 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10352 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10354 // Armv8.2-A Crypto extensions
10355 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10357 : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10360 let Inst{31-25} = 0b1100111;
10361 let Inst{9-5} = Vn;
10362 let Inst{4-0} = Vd;
10365 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10366 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10368 let Inst{31-25} = 0b1100111;
10369 let Inst{24-21} = 0b0110;
10370 let Inst{20-15} = 0b000001;
10371 let Inst{14} = op0;
10372 let Inst{13-12} = 0b00;
10373 let Inst{11-10} = op1;
10375 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10376 : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10377 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10378 : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10380 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10381 string asmops, string cst>
10382 : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10384 let Inst{24-21} = 0b0011;
10385 let Inst{20-16} = Vm;
10386 let Inst{15} = 0b1;
10387 let Inst{14} = op0;
10388 let Inst{13-12} = 0b00;
10389 let Inst{11-10} = op1;
10391 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10392 : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10393 "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10394 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10395 : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10396 "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10397 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10398 : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10399 "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10400 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10401 : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10402 "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10403 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10404 : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10405 asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10407 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10408 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10412 let Inst{24-23} = 0b00;
10413 let Inst{22-21} = op0;
10414 let Inst{20-16} = Vm;
10415 let Inst{15} = 0b0;
10416 let Inst{14-10} = Va;
10418 class CryptoRRRR_16B<bits<2>op0, string asm>
10419 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10421 class CryptoRRRR_4S<bits<2>op0, string asm>
10422 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10425 class CryptoRRRi6<string asm>
10426 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10427 "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10430 let Inst{24-21} = 0b0100;
10431 let Inst{20-16} = Vm;
10432 let Inst{15-10} = imm;
10433 let Inst{9-5} = Vn;
10434 let Inst{4-0} = Vd;
10437 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10438 : BaseCryptoV82<(outs V128:$Vdst),
10439 (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10440 asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10443 let Inst{24-21} = 0b0010;
10444 let Inst{20-16} = Vm;
10445 let Inst{15} = 0b1;
10446 let Inst{14} = op0;
10447 let Inst{13-12} = imm;
10448 let Inst{11-10} = op1;
10451 //----------------------------------------------------------------------------
10452 // v8.1 atomic instructions extension:
10456 // * LDOPregister<OP>, and aliases STOPregister<OP>
10458 // Instruction encodings:
10460 // 31 30|29 24|23|22|21|20 16|15|14 10|9 5|4 0
10461 // CAS SZ |001000|1 |A |1 |Rs |R |11111 |Rn |Rt
10462 // CASP 0|SZ|001000|0 |A |1 |Rs |R |11111 |Rn |Rt
10463 // SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt
10464 // LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt
10465 // ST SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |11111
10467 // Instruction syntax:
10469 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10470 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10471 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10472 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10473 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10474 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10475 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10476 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10477 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10478 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10480 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10481 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10482 string cstr, list<dag> pattern>
10483 : I<oops, iops, asm, operands, cstr, pattern> {
10491 let Inst{31-30} = Sz;
10492 let Inst{29-24} = 0b001000;
10494 let Inst{22} = Acq;
10495 let Inst{21} = 0b1;
10496 let Inst{20-16} = Rs;
10497 let Inst{15} = Rel;
10498 let Inst{14-10} = 0b11111;
10499 let Inst{9-5} = Rn;
10500 let Inst{4-0} = Rt;
10501 let Predicates = [HasLSE];
10504 class BaseCAS<string order, string size, RegisterClass RC>
10505 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10506 "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10508 Sched<[WriteAtomic]> {
10512 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10513 let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10514 let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10515 let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10516 let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10519 class BaseCASP<string order, string size, RegisterOperand RC>
10520 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10521 "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10523 Sched<[WriteAtomic]> {
10527 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10528 let Sz = 0b00, Acq = Acq, Rel = Rel in
10529 def W : BaseCASP<order, "", WSeqPairClassOperand>;
10530 let Sz = 0b01, Acq = Acq, Rel = Rel in
10531 def X : BaseCASP<order, "", XSeqPairClassOperand>;
10534 let Predicates = [HasLSE] in
10535 class BaseSWP<string order, string size, RegisterClass RC>
10536 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10537 "\t$Rs, $Rt, [$Rn]","",[]>,
10538 Sched<[WriteAtomic]> {
10543 bits<3> opc = 0b000;
10546 let Inst{31-30} = Sz;
10547 let Inst{29-24} = 0b111000;
10548 let Inst{23} = Acq;
10549 let Inst{22} = Rel;
10550 let Inst{21} = 0b1;
10551 let Inst{20-16} = Rs;
10552 let Inst{15} = 0b1;
10553 let Inst{14-12} = opc;
10554 let Inst{11-10} = 0b00;
10555 let Inst{9-5} = Rn;
10556 let Inst{4-0} = Rt;
10557 let Predicates = [HasLSE];
10560 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10561 let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10562 let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10563 let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10564 let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10567 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10568 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10569 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10570 "\t$Rs, $Rt, [$Rn]","",[]>,
10571 Sched<[WriteAtomic]> {
10579 let Inst{31-30} = Sz;
10580 let Inst{29-24} = 0b111000;
10581 let Inst{23} = Acq;
10582 let Inst{22} = Rel;
10583 let Inst{21} = 0b1;
10584 let Inst{20-16} = Rs;
10585 let Inst{15} = 0b0;
10586 let Inst{14-12} = opc;
10587 let Inst{11-10} = 0b00;
10588 let Inst{9-5} = Rn;
10589 let Inst{4-0} = Rt;
10590 let Predicates = [HasLSE];
10593 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10595 let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10596 def B : BaseLDOPregister<op, order, "b", GPR32>;
10597 let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10598 def H : BaseLDOPregister<op, order, "h", GPR32>;
10599 let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10600 def W : BaseLDOPregister<op, order, "", GPR32>;
10601 let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10602 def X : BaseLDOPregister<op, order, "", GPR64>;
10605 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10606 // complex DAG for DstRHS.
10607 let Predicates = [HasLSE] in
10608 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10609 string size, dag SrcRHS, dag DstRHS> {
10610 def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10611 (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10612 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10613 (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10614 def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10615 (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10616 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10617 (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10618 def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10619 (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10622 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10623 string size, dag RHS> {
10624 defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10627 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10628 string size, dag LHS, dag RHS> {
10629 defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10632 multiclass LDOPregister_patterns<string inst, string op> {
10633 defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10634 defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10635 defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10636 defm : LDOPregister_patterns_ord<inst, "B", op, "8", (i32 GPR32:$Rm)>;
10639 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10640 defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10642 (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10643 defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10645 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10646 defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10648 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10649 defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10651 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10654 let Predicates = [HasLSE] in
10655 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10656 string size, dag OLD, dag NEW> {
10657 def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10658 (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10659 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10660 (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10661 def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10662 (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10663 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10664 (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10665 def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10666 (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10669 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10670 string size, dag OLD, dag NEW> {
10671 defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10674 multiclass CASregister_patterns<string inst, string op> {
10675 defm : CASregister_patterns_ord<inst, "X", op, "64",
10676 (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10677 defm : CASregister_patterns_ord<inst, "W", op, "32",
10678 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10679 defm : CASregister_patterns_ord<inst, "H", op, "16",
10680 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10681 defm : CASregister_patterns_ord<inst, "B", op, "8",
10682 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10685 let Predicates = [HasLSE] in
10686 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10687 Instruction inst> :
10688 InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10690 multiclass STOPregister<string asm, string instr> {
10691 def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10692 !cast<Instruction>(instr # "LB")>;
10693 def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10694 !cast<Instruction>(instr # "LH")>;
10695 def : BaseSTOPregister<asm # "l", GPR32, WZR,
10696 !cast<Instruction>(instr # "LW")>;
10697 def : BaseSTOPregister<asm # "l", GPR64, XZR,
10698 !cast<Instruction>(instr # "LX")>;
10699 def : BaseSTOPregister<asm # "b", GPR32, WZR,
10700 !cast<Instruction>(instr # "B")>;
10701 def : BaseSTOPregister<asm # "h", GPR32, WZR,
10702 !cast<Instruction>(instr # "H")>;
10703 def : BaseSTOPregister<asm, GPR32, WZR,
10704 !cast<Instruction>(instr # "W")>;
10705 def : BaseSTOPregister<asm, GPR64, XZR,
10706 !cast<Instruction>(instr # "X")>;
10709 //----------------------------------------------------------------------------
10710 // Allow the size specifier tokens to be upper case, not just lower.
10711 def : TokenAlias<".4B", ".4b">; // Add dot product
10712 def : TokenAlias<".8B", ".8b">;
10713 def : TokenAlias<".4H", ".4h">;
10714 def : TokenAlias<".2S", ".2s">;
10715 def : TokenAlias<".1D", ".1d">;
10716 def : TokenAlias<".16B", ".16b">;
10717 def : TokenAlias<".8H", ".8h">;
10718 def : TokenAlias<".4S", ".4s">;
10719 def : TokenAlias<".2D", ".2d">;
10720 def : TokenAlias<".1Q", ".1q">;
10721 def : TokenAlias<".2H", ".2h">;
10722 def : TokenAlias<".B", ".b">;
10723 def : TokenAlias<".H", ".h">;
10724 def : TokenAlias<".S", ".s">;
10725 def : TokenAlias<".D", ".d">;
10726 def : TokenAlias<".Q", ".q">;