1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
11 // Describe AArch64 instructions format here
14 // Format specifies the encoding used by the instruction. This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
17 class Format<bits<2> val> {
21 def PseudoFrm : Format<0>;
22 def NormalFrm : Format<1>; // Do we need any others?
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26 field bits<32> Inst; // Instruction encoding.
27 // Mask of bits that cause an encoding to be UNPREDICTABLE.
28 // If a bit is set, then if the corresponding bit in the
29 // target encoding differs from its value in the "Inst" field,
30 // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31 field bits<32> Unpredictable = 0;
32 // SoftFail is the generic name for this field, but we alias it so
33 // as to make it more obvious what it means in ARM-land.
34 field bits<32> SoftFail = Unpredictable;
35 let Namespace = "AArch64";
37 bits<2> Form = F.Value;
39 let Constraints = cstr;
42 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
43 : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
45 // Pseudo instructions (don't have encoding information)
46 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
47 : AArch64Inst<PseudoFrm, cstr> {
48 dag OutOperandList = oops;
49 dag InOperandList = iops;
50 let Pattern = pattern;
51 let isCodeGenOnly = 1;
54 // Real instructions (have encoding information)
55 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
56 let Pattern = pattern;
60 // Enum describing whether an instruction is
61 // destructive in its first source operand.
62 class DestructiveInstTypeEnum<bits<1> val> {
65 def NotDestructive : DestructiveInstTypeEnum<0>;
66 def Destructive : DestructiveInstTypeEnum<1>;
68 // Normal instructions
69 class I<dag oops, dag iops, string asm, string operands, string cstr,
71 : EncodedI<cstr, pattern> {
72 dag OutOperandList = oops;
73 dag InOperandList = iops;
74 let AsmString = !strconcat(asm, operands);
76 // Destructive operations (SVE)
77 DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
78 ElementSizeEnum ElementSize = ElementSizeB;
80 let TSFlags{3} = DestructiveInstType.Value;
81 let TSFlags{2-0} = ElementSize.Value;
84 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
85 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
86 class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
88 // Helper fragment for an extract of the high portion of a 128-bit vector.
89 def extract_high_v16i8 :
90 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
91 def extract_high_v8i16 :
92 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
93 def extract_high_v4i32 :
94 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
95 def extract_high_v2i64 :
96 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
98 //===----------------------------------------------------------------------===//
99 // Asm Operand Classes.
102 // Shifter operand for arithmetic shifted encodings.
103 def ShifterOperand : AsmOperandClass {
104 let Name = "Shifter";
107 // Shifter operand for mov immediate encodings.
108 def MovImm32ShifterOperand : AsmOperandClass {
109 let SuperClasses = [ShifterOperand];
110 let Name = "MovImm32Shifter";
111 let RenderMethod = "addShifterOperands";
112 let DiagnosticType = "InvalidMovImm32Shift";
114 def MovImm64ShifterOperand : AsmOperandClass {
115 let SuperClasses = [ShifterOperand];
116 let Name = "MovImm64Shifter";
117 let RenderMethod = "addShifterOperands";
118 let DiagnosticType = "InvalidMovImm64Shift";
121 // Shifter operand for arithmetic register shifted encodings.
122 class ArithmeticShifterOperand<int width> : AsmOperandClass {
123 let SuperClasses = [ShifterOperand];
124 let Name = "ArithmeticShifter" # width;
125 let PredicateMethod = "isArithmeticShifter<" # width # ">";
126 let RenderMethod = "addShifterOperands";
127 let DiagnosticType = "AddSubRegShift" # width;
130 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
131 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
133 // Shifter operand for logical register shifted encodings.
134 class LogicalShifterOperand<int width> : AsmOperandClass {
135 let SuperClasses = [ShifterOperand];
136 let Name = "LogicalShifter" # width;
137 let PredicateMethod = "isLogicalShifter<" # width # ">";
138 let RenderMethod = "addShifterOperands";
139 let DiagnosticType = "AddSubRegShift" # width;
142 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
143 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
145 // Shifter operand for logical vector 128/64-bit shifted encodings.
146 def LogicalVecShifterOperand : AsmOperandClass {
147 let SuperClasses = [ShifterOperand];
148 let Name = "LogicalVecShifter";
149 let RenderMethod = "addShifterOperands";
151 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
152 let SuperClasses = [LogicalVecShifterOperand];
153 let Name = "LogicalVecHalfWordShifter";
154 let RenderMethod = "addShifterOperands";
157 // The "MSL" shifter on the vector MOVI instruction.
158 def MoveVecShifterOperand : AsmOperandClass {
159 let SuperClasses = [ShifterOperand];
160 let Name = "MoveVecShifter";
161 let RenderMethod = "addShifterOperands";
164 // Extend operand for arithmetic encodings.
165 def ExtendOperand : AsmOperandClass {
167 let DiagnosticType = "AddSubRegExtendLarge";
169 def ExtendOperand64 : AsmOperandClass {
170 let SuperClasses = [ExtendOperand];
171 let Name = "Extend64";
172 let DiagnosticType = "AddSubRegExtendSmall";
174 // 'extend' that's a lsl of a 64-bit register.
175 def ExtendOperandLSL64 : AsmOperandClass {
176 let SuperClasses = [ExtendOperand];
177 let Name = "ExtendLSL64";
178 let RenderMethod = "addExtend64Operands";
179 let DiagnosticType = "AddSubRegExtendLarge";
182 // 8-bit floating-point immediate encodings.
183 def FPImmOperand : AsmOperandClass {
185 let ParserMethod = "tryParseFPImm<true>";
186 let DiagnosticType = "InvalidFPImm";
189 def CondCode : AsmOperandClass {
190 let Name = "CondCode";
191 let DiagnosticType = "InvalidCondCode";
194 // A 32-bit register pasrsed as 64-bit
195 def GPR32as64Operand : AsmOperandClass {
196 let Name = "GPR32as64";
198 "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
200 def GPR32as64 : RegisterOperand<GPR32> {
201 let ParserMatchClass = GPR32as64Operand;
204 // A 64-bit register pasrsed as 32-bit
205 def GPR64as32Operand : AsmOperandClass {
206 let Name = "GPR64as32";
208 "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
210 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
211 let ParserMatchClass = GPR64as32Operand;
214 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
215 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
216 // are encoded as the eight bit value 'abcdefgh'.
217 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
219 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
220 let Name = "UImm" # Width # "s" # Scale;
221 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
222 let RenderMethod = "addImmScaledOperands<" # Scale # ">";
223 let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
226 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
227 let Name = "SImm" # Width # "s" # Scale;
228 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
229 let RenderMethod = "addImmScaledOperands<" # Scale # ">";
230 let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
233 //===----------------------------------------------------------------------===//
234 // Operand Definitions.
237 // ADR[P] instruction labels.
238 def AdrpOperand : AsmOperandClass {
239 let Name = "AdrpLabel";
240 let ParserMethod = "tryParseAdrpLabel";
241 let DiagnosticType = "InvalidLabel";
243 def adrplabel : Operand<i64> {
244 let EncoderMethod = "getAdrLabelOpValue";
245 let PrintMethod = "printAdrpLabel";
246 let ParserMatchClass = AdrpOperand;
249 def AdrOperand : AsmOperandClass {
250 let Name = "AdrLabel";
251 let ParserMethod = "tryParseAdrLabel";
252 let DiagnosticType = "InvalidLabel";
254 def adrlabel : Operand<i64> {
255 let EncoderMethod = "getAdrLabelOpValue";
256 let ParserMatchClass = AdrOperand;
259 class SImmOperand<int width> : AsmOperandClass {
260 let Name = "SImm" # width;
261 let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
262 let RenderMethod = "addImmOperands";
263 let PredicateMethod = "isSImm<" # width # ">";
267 class AsmImmRange<int Low, int High> : AsmOperandClass {
268 let Name = "Imm" # Low # "_" # High;
269 let DiagnosticType = "InvalidImm" # Low # "_" # High;
270 let RenderMethod = "addImmOperands";
271 let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
274 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
275 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
276 def simm10Scaled : Operand<i64> {
277 let ParserMatchClass = SImm10s8Operand;
278 let DecoderMethod = "DecodeSImm<10>";
279 let PrintMethod = "printImmScale<8>";
282 def simm9s16 : Operand<i64> {
283 let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
284 let DecoderMethod = "DecodeSImm<9>";
285 let PrintMethod = "printImmScale<16>";
288 // uimm6 predicate - True if the immediate is in the range [0, 63].
289 def UImm6Operand : AsmOperandClass {
291 let DiagnosticType = "InvalidImm0_63";
294 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
295 let ParserMatchClass = UImm6Operand;
298 def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
299 let ParserMatchClass = AsmImmRange<0, 65535>;
302 def SImm9Operand : SImmOperand<9>;
303 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
304 let ParserMatchClass = SImm9Operand;
305 let DecoderMethod = "DecodeSImm<9>";
308 def SImm8Operand : SImmOperand<8>;
309 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
310 let ParserMatchClass = SImm8Operand;
311 let DecoderMethod = "DecodeSImm<8>";
314 def SImm6Operand : SImmOperand<6>;
315 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
316 let ParserMatchClass = SImm6Operand;
317 let DecoderMethod = "DecodeSImm<6>";
320 def SImm5Operand : SImmOperand<5>;
321 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
322 let ParserMatchClass = SImm5Operand;
323 let DecoderMethod = "DecodeSImm<5>";
326 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
327 let ParserMatchClass = SImm5Operand;
328 let DecoderMethod = "DecodeSImm<5>";
331 // simm7sN predicate - True if the immediate is a multiple of N in the range
332 // [-64 * N, 63 * N].
334 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
335 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
336 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
338 def simm7s4 : Operand<i32> {
339 let ParserMatchClass = SImm7s4Operand;
340 let PrintMethod = "printImmScale<4>";
343 def simm7s8 : Operand<i32> {
344 let ParserMatchClass = SImm7s8Operand;
345 let PrintMethod = "printImmScale<8>";
348 def simm7s16 : Operand<i32> {
349 let ParserMatchClass = SImm7s16Operand;
350 let PrintMethod = "printImmScale<16>";
353 def am_indexed7s8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
354 def am_indexed7s16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
355 def am_indexed7s32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
356 def am_indexed7s64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
357 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
359 // uimm5sN predicate - True if the immediate is a multiple of N in the range
361 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
362 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
363 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
365 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
366 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
367 let ParserMatchClass = UImm5s2Operand;
368 let PrintMethod = "printImmScale<2>";
370 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
371 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
372 let ParserMatchClass = UImm5s4Operand;
373 let PrintMethod = "printImmScale<4>";
375 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
376 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
377 let ParserMatchClass = UImm5s8Operand;
378 let PrintMethod = "printImmScale<8>";
381 // uimm6sN predicate - True if the immediate is a multiple of N in the range
383 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
384 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
385 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
386 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
387 def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
389 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
390 let ParserMatchClass = UImm6s1Operand;
392 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
393 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
394 let PrintMethod = "printImmScale<2>";
395 let ParserMatchClass = UImm6s2Operand;
397 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
398 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
399 let PrintMethod = "printImmScale<4>";
400 let ParserMatchClass = UImm6s4Operand;
402 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
403 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
404 let PrintMethod = "printImmScale<8>";
405 let ParserMatchClass = UImm6s8Operand;
407 def uimm6s16 : Operand<i64>, ImmLeaf<i64,
408 [{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
409 let PrintMethod = "printImmScale<16>";
410 let ParserMatchClass = UImm6s16Operand;
413 // simm6sN predicate - True if the immediate is a multiple of N in the range
414 // [-32 * N, 31 * N].
415 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
416 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
417 let ParserMatchClass = SImm6s1Operand;
418 let DecoderMethod = "DecodeSImm<6>";
421 // simm4sN predicate - True if the immediate is a multiple of N in the range
423 def SImm4s1Operand : SImmScaledMemoryIndexed<4, 1>;
424 def SImm4s2Operand : SImmScaledMemoryIndexed<4, 2>;
425 def SImm4s3Operand : SImmScaledMemoryIndexed<4, 3>;
426 def SImm4s4Operand : SImmScaledMemoryIndexed<4, 4>;
427 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
429 def simm4s1 : Operand<i64>, ImmLeaf<i64,
430 [{ return Imm >=-8 && Imm <= 7; }]> {
431 let ParserMatchClass = SImm4s1Operand;
432 let DecoderMethod = "DecodeSImm<4>";
435 def simm4s2 : Operand<i64>, ImmLeaf<i64,
436 [{ return Imm >=-16 && Imm <= 14 && (Imm % 2) == 0x0; }]> {
437 let PrintMethod = "printImmScale<2>";
438 let ParserMatchClass = SImm4s2Operand;
439 let DecoderMethod = "DecodeSImm<4>";
442 def simm4s3 : Operand<i64>, ImmLeaf<i64,
443 [{ return Imm >=-24 && Imm <= 21 && (Imm % 3) == 0x0; }]> {
444 let PrintMethod = "printImmScale<3>";
445 let ParserMatchClass = SImm4s3Operand;
446 let DecoderMethod = "DecodeSImm<4>";
449 def simm4s4 : Operand<i64>, ImmLeaf<i64,
450 [{ return Imm >=-32 && Imm <= 28 && (Imm % 4) == 0x0; }]> {
451 let PrintMethod = "printImmScale<4>";
452 let ParserMatchClass = SImm4s4Operand;
453 let DecoderMethod = "DecodeSImm<4>";
455 def simm4s16 : Operand<i64>, ImmLeaf<i64,
456 [{ return Imm >=-128 && Imm <= 112 && (Imm % 16) == 0x0; }]> {
457 let PrintMethod = "printImmScale<16>";
458 let ParserMatchClass = SImm4s16Operand;
459 let DecoderMethod = "DecodeSImm<4>";
462 def Imm1_8Operand : AsmImmRange<1, 8>;
463 def Imm1_16Operand : AsmImmRange<1, 16>;
464 def Imm1_32Operand : AsmImmRange<1, 32>;
465 def Imm1_64Operand : AsmImmRange<1, 64>;
467 class BranchTarget<int N> : AsmOperandClass {
468 let Name = "BranchTarget" # N;
469 let DiagnosticType = "InvalidLabel";
470 let PredicateMethod = "isBranchTarget<" # N # ">";
473 class PCRelLabel<int N> : BranchTarget<N> {
474 let Name = "PCRelLabel" # N;
477 def BranchTarget14Operand : BranchTarget<14>;
478 def BranchTarget26Operand : BranchTarget<26>;
479 def PCRelLabel19Operand : PCRelLabel<19>;
481 def MovZSymbolG3AsmOperand : AsmOperandClass {
482 let Name = "MovZSymbolG3";
483 let RenderMethod = "addImmOperands";
486 def movz_symbol_g3 : Operand<i32> {
487 let ParserMatchClass = MovZSymbolG3AsmOperand;
490 def MovZSymbolG2AsmOperand : AsmOperandClass {
491 let Name = "MovZSymbolG2";
492 let RenderMethod = "addImmOperands";
495 def movz_symbol_g2 : Operand<i32> {
496 let ParserMatchClass = MovZSymbolG2AsmOperand;
499 def MovZSymbolG1AsmOperand : AsmOperandClass {
500 let Name = "MovZSymbolG1";
501 let RenderMethod = "addImmOperands";
504 def movz_symbol_g1 : Operand<i32> {
505 let ParserMatchClass = MovZSymbolG1AsmOperand;
508 def MovZSymbolG0AsmOperand : AsmOperandClass {
509 let Name = "MovZSymbolG0";
510 let RenderMethod = "addImmOperands";
513 def movz_symbol_g0 : Operand<i32> {
514 let ParserMatchClass = MovZSymbolG0AsmOperand;
517 def MovKSymbolG3AsmOperand : AsmOperandClass {
518 let Name = "MovKSymbolG3";
519 let RenderMethod = "addImmOperands";
522 def movk_symbol_g3 : Operand<i32> {
523 let ParserMatchClass = MovKSymbolG3AsmOperand;
526 def MovKSymbolG2AsmOperand : AsmOperandClass {
527 let Name = "MovKSymbolG2";
528 let RenderMethod = "addImmOperands";
531 def movk_symbol_g2 : Operand<i32> {
532 let ParserMatchClass = MovKSymbolG2AsmOperand;
535 def MovKSymbolG1AsmOperand : AsmOperandClass {
536 let Name = "MovKSymbolG1";
537 let RenderMethod = "addImmOperands";
540 def movk_symbol_g1 : Operand<i32> {
541 let ParserMatchClass = MovKSymbolG1AsmOperand;
544 def MovKSymbolG0AsmOperand : AsmOperandClass {
545 let Name = "MovKSymbolG0";
546 let RenderMethod = "addImmOperands";
549 def movk_symbol_g0 : Operand<i32> {
550 let ParserMatchClass = MovKSymbolG0AsmOperand;
553 class fixedpoint_i32<ValueType FloatVT>
555 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
556 let EncoderMethod = "getFixedPointScaleOpValue";
557 let DecoderMethod = "DecodeFixedPointScaleImm32";
558 let ParserMatchClass = Imm1_32Operand;
561 class fixedpoint_i64<ValueType FloatVT>
563 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
564 let EncoderMethod = "getFixedPointScaleOpValue";
565 let DecoderMethod = "DecodeFixedPointScaleImm64";
566 let ParserMatchClass = Imm1_64Operand;
569 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
570 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
571 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
573 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
574 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
575 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
577 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
578 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
580 let EncoderMethod = "getVecShiftR8OpValue";
581 let DecoderMethod = "DecodeVecShiftR8Imm";
582 let ParserMatchClass = Imm1_8Operand;
584 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
585 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
587 let EncoderMethod = "getVecShiftR16OpValue";
588 let DecoderMethod = "DecodeVecShiftR16Imm";
589 let ParserMatchClass = Imm1_16Operand;
591 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
592 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
594 let EncoderMethod = "getVecShiftR16OpValue";
595 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
596 let ParserMatchClass = Imm1_8Operand;
598 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
599 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
601 let EncoderMethod = "getVecShiftR32OpValue";
602 let DecoderMethod = "DecodeVecShiftR32Imm";
603 let ParserMatchClass = Imm1_32Operand;
605 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
606 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
608 let EncoderMethod = "getVecShiftR32OpValue";
609 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
610 let ParserMatchClass = Imm1_16Operand;
612 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
613 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
615 let EncoderMethod = "getVecShiftR64OpValue";
616 let DecoderMethod = "DecodeVecShiftR64Imm";
617 let ParserMatchClass = Imm1_64Operand;
619 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
620 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
622 let EncoderMethod = "getVecShiftR64OpValue";
623 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
624 let ParserMatchClass = Imm1_32Operand;
627 def Imm0_1Operand : AsmImmRange<0, 1>;
628 def Imm0_7Operand : AsmImmRange<0, 7>;
629 def Imm0_15Operand : AsmImmRange<0, 15>;
630 def Imm0_31Operand : AsmImmRange<0, 31>;
631 def Imm0_63Operand : AsmImmRange<0, 63>;
633 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
634 return (((uint32_t)Imm) < 8);
636 let EncoderMethod = "getVecShiftL8OpValue";
637 let DecoderMethod = "DecodeVecShiftL8Imm";
638 let ParserMatchClass = Imm0_7Operand;
640 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
641 return (((uint32_t)Imm) < 16);
643 let EncoderMethod = "getVecShiftL16OpValue";
644 let DecoderMethod = "DecodeVecShiftL16Imm";
645 let ParserMatchClass = Imm0_15Operand;
647 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
648 return (((uint32_t)Imm) < 32);
650 let EncoderMethod = "getVecShiftL32OpValue";
651 let DecoderMethod = "DecodeVecShiftL32Imm";
652 let ParserMatchClass = Imm0_31Operand;
654 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
655 return (((uint32_t)Imm) < 64);
657 let EncoderMethod = "getVecShiftL64OpValue";
658 let DecoderMethod = "DecodeVecShiftL64Imm";
659 let ParserMatchClass = Imm0_63Operand;
663 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
664 // instructions for splatting repeating bit patterns across the immediate.
665 def logical_imm32_XFORM : SDNodeXForm<imm, [{
666 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
667 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
669 def logical_imm64_XFORM : SDNodeXForm<imm, [{
670 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
671 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
674 let DiagnosticType = "LogicalSecondSource" in {
675 def LogicalImm32Operand : AsmOperandClass {
676 let Name = "LogicalImm32";
677 let PredicateMethod = "isLogicalImm<int32_t>";
678 let RenderMethod = "addLogicalImmOperands<int32_t>";
680 def LogicalImm64Operand : AsmOperandClass {
681 let Name = "LogicalImm64";
682 let PredicateMethod = "isLogicalImm<int64_t>";
683 let RenderMethod = "addLogicalImmOperands<int64_t>";
685 def LogicalImm32NotOperand : AsmOperandClass {
686 let Name = "LogicalImm32Not";
687 let PredicateMethod = "isLogicalImm<int32_t>";
688 let RenderMethod = "addLogicalImmNotOperands<int32_t>";
690 def LogicalImm64NotOperand : AsmOperandClass {
691 let Name = "LogicalImm64Not";
692 let PredicateMethod = "isLogicalImm<int64_t>";
693 let RenderMethod = "addLogicalImmNotOperands<int64_t>";
696 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
697 return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
698 }], logical_imm32_XFORM> {
699 let PrintMethod = "printLogicalImm<int32_t>";
700 let ParserMatchClass = LogicalImm32Operand;
702 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
703 return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
704 }], logical_imm64_XFORM> {
705 let PrintMethod = "printLogicalImm<int64_t>";
706 let ParserMatchClass = LogicalImm64Operand;
708 def logical_imm32_not : Operand<i32> {
709 let ParserMatchClass = LogicalImm32NotOperand;
711 def logical_imm64_not : Operand<i64> {
712 let ParserMatchClass = LogicalImm64NotOperand;
715 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
716 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
717 return ((uint32_t)Imm) < 65536;
719 let ParserMatchClass = AsmImmRange<0, 65535>;
720 let PrintMethod = "printImmHex";
723 // imm0_255 predicate - True if the immediate is in the range [0,255].
724 def Imm0_255Operand : AsmImmRange<0,255>;
726 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
727 return ((uint32_t)Imm) < 256;
729 let ParserMatchClass = Imm0_255Operand;
730 let PrintMethod = "printImm";
733 // imm0_127 predicate - True if the immediate is in the range [0,127]
734 def Imm0_127Operand : AsmImmRange<0, 127>;
735 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
736 return ((uint32_t)Imm) < 128;
738 let ParserMatchClass = Imm0_127Operand;
739 let PrintMethod = "printImm";
742 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
743 // for all shift-amounts.
745 // imm0_63 predicate - True if the immediate is in the range [0,63]
746 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
747 return ((uint64_t)Imm) < 64;
749 let ParserMatchClass = Imm0_63Operand;
752 // imm0_31 predicate - True if the immediate is in the range [0,31]
753 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
754 return ((uint64_t)Imm) < 32;
756 let ParserMatchClass = Imm0_31Operand;
759 // True if the 32-bit immediate is in the range [0,31]
760 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
761 return ((uint64_t)Imm) < 32;
763 let ParserMatchClass = Imm0_31Operand;
766 // imm0_1 predicate - True if the immediate is in the range [0,1]
767 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
768 return ((uint64_t)Imm) < 2;
770 let ParserMatchClass = Imm0_1Operand;
773 // imm0_15 predicate - True if the immediate is in the range [0,15]
774 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
775 return ((uint64_t)Imm) < 16;
777 let ParserMatchClass = Imm0_15Operand;
780 // imm0_7 predicate - True if the immediate is in the range [0,7]
781 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
782 return ((uint64_t)Imm) < 8;
784 let ParserMatchClass = Imm0_7Operand;
787 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
788 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
789 return ((uint32_t)Imm) < 16;
791 let ParserMatchClass = Imm0_15Operand;
794 // An arithmetic shifter operand:
795 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
797 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
798 let PrintMethod = "printShifter";
799 let ParserMatchClass = !cast<AsmOperandClass>(
800 "ArithmeticShifterOperand" # width);
803 def arith_shift32 : arith_shift<i32, 32>;
804 def arith_shift64 : arith_shift<i64, 64>;
806 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
808 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
809 let PrintMethod = "printShiftedRegister";
810 let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
813 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
814 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
816 // An arithmetic shifter operand:
817 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
819 class logical_shift<int width> : Operand<i32> {
820 let PrintMethod = "printShifter";
821 let ParserMatchClass = !cast<AsmOperandClass>(
822 "LogicalShifterOperand" # width);
825 def logical_shift32 : logical_shift<32>;
826 def logical_shift64 : logical_shift<64>;
828 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
830 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
831 let PrintMethod = "printShiftedRegister";
832 let MIOperandInfo = (ops regclass, shiftop);
835 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
836 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
838 // A logical vector shifter operand:
839 // {7-6} - shift type: 00 = lsl
840 // {5-0} - imm6: #0, #8, #16, or #24
841 def logical_vec_shift : Operand<i32> {
842 let PrintMethod = "printShifter";
843 let EncoderMethod = "getVecShifterOpValue";
844 let ParserMatchClass = LogicalVecShifterOperand;
847 // A logical vector half-word shifter operand:
848 // {7-6} - shift type: 00 = lsl
849 // {5-0} - imm6: #0 or #8
850 def logical_vec_hw_shift : Operand<i32> {
851 let PrintMethod = "printShifter";
852 let EncoderMethod = "getVecShifterOpValue";
853 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
856 // A vector move shifter operand:
857 // {0} - imm1: #8 or #16
858 def move_vec_shift : Operand<i32> {
859 let PrintMethod = "printShifter";
860 let EncoderMethod = "getMoveVecShifterOpValue";
861 let ParserMatchClass = MoveVecShifterOperand;
864 let DiagnosticType = "AddSubSecondSource" in {
865 def AddSubImmOperand : AsmOperandClass {
866 let Name = "AddSubImm";
867 let ParserMethod = "tryParseImmWithOptionalShift";
868 let RenderMethod = "addImmWithOptionalShiftOperands<12>";
870 def AddSubImmNegOperand : AsmOperandClass {
871 let Name = "AddSubImmNeg";
872 let ParserMethod = "tryParseImmWithOptionalShift";
873 let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
876 // An ADD/SUB immediate shifter operand:
878 // {7-6} - shift type: 00 = lsl
879 // {5-0} - imm6: #0 or #12
880 class addsub_shifted_imm<ValueType Ty>
881 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
882 let PrintMethod = "printAddSubImm";
883 let EncoderMethod = "getAddSubImmOpValue";
884 let ParserMatchClass = AddSubImmOperand;
885 let MIOperandInfo = (ops i32imm, i32imm);
888 class addsub_shifted_imm_neg<ValueType Ty>
890 let EncoderMethod = "getAddSubImmOpValue";
891 let ParserMatchClass = AddSubImmNegOperand;
892 let MIOperandInfo = (ops i32imm, i32imm);
895 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
896 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
897 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
898 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
900 def gi_addsub_shifted_imm32 :
901 GIComplexOperandMatcher<s32, "selectArithImmed">,
902 GIComplexPatternEquiv<addsub_shifted_imm32>;
904 def gi_addsub_shifted_imm64 :
905 GIComplexOperandMatcher<s64, "selectArithImmed">,
906 GIComplexPatternEquiv<addsub_shifted_imm64>;
908 class neg_addsub_shifted_imm<ValueType Ty>
909 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
910 let PrintMethod = "printAddSubImm";
911 let EncoderMethod = "getAddSubImmOpValue";
912 let ParserMatchClass = AddSubImmOperand;
913 let MIOperandInfo = (ops i32imm, i32imm);
916 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
917 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
919 // An extend operand:
920 // {5-3} - extend type
922 def arith_extend : Operand<i32> {
923 let PrintMethod = "printArithExtend";
924 let ParserMatchClass = ExtendOperand;
926 def arith_extend64 : Operand<i32> {
927 let PrintMethod = "printArithExtend";
928 let ParserMatchClass = ExtendOperand64;
931 // 'extend' that's a lsl of a 64-bit register.
932 def arith_extendlsl64 : Operand<i32> {
933 let PrintMethod = "printArithExtend";
934 let ParserMatchClass = ExtendOperandLSL64;
937 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
938 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
939 let PrintMethod = "printExtendedRegister";
940 let MIOperandInfo = (ops GPR32, arith_extend);
943 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
944 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
945 let PrintMethod = "printExtendedRegister";
946 let MIOperandInfo = (ops GPR32, arith_extend64);
949 // Floating-point immediate.
950 def fpimm16 : Operand<f16>,
952 return AArch64_AM::getFP16Imm(Imm) != -1;
953 }], SDNodeXForm<fpimm, [{
954 APFloat InVal = N->getValueAPF();
955 uint32_t enc = AArch64_AM::getFP16Imm(InVal);
956 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
958 let ParserMatchClass = FPImmOperand;
959 let PrintMethod = "printFPImmOperand";
961 def fpimm32 : Operand<f32>,
963 return AArch64_AM::getFP32Imm(Imm) != -1;
964 }], SDNodeXForm<fpimm, [{
965 APFloat InVal = N->getValueAPF();
966 uint32_t enc = AArch64_AM::getFP32Imm(InVal);
967 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
969 let ParserMatchClass = FPImmOperand;
970 let PrintMethod = "printFPImmOperand";
972 def fpimm64 : Operand<f64>,
974 return AArch64_AM::getFP64Imm(Imm) != -1;
975 }], SDNodeXForm<fpimm, [{
976 APFloat InVal = N->getValueAPF();
977 uint32_t enc = AArch64_AM::getFP64Imm(InVal);
978 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
980 let ParserMatchClass = FPImmOperand;
981 let PrintMethod = "printFPImmOperand";
984 def fpimm8 : Operand<i32> {
985 let ParserMatchClass = FPImmOperand;
986 let PrintMethod = "printFPImmOperand";
989 def fpimm0 : FPImmLeaf<fAny, [{
990 return Imm.isExactlyValue(+0.0);
993 // Vector lane operands
994 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
995 let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
996 let DiagnosticType = "Invalid" # Name;
997 let PredicateMethod = "isVectorIndex<" # Min # ", " # Max # ">";
998 let RenderMethod = "addVectorIndexOperands";
1001 class AsmVectorIndexOpnd<AsmOperandClass mc, code pred>
1002 : Operand<i64>, ImmLeaf<i64, pred> {
1003 let ParserMatchClass = mc;
1004 let PrintMethod = "printVectorIndex";
1007 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1008 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1009 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1010 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1011 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1013 def VectorIndex1 : AsmVectorIndexOpnd<VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1014 def VectorIndexB : AsmVectorIndexOpnd<VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1015 def VectorIndexH : AsmVectorIndexOpnd<VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1016 def VectorIndexS : AsmVectorIndexOpnd<VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1017 def VectorIndexD : AsmVectorIndexOpnd<VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1019 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1020 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1021 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1022 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1023 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1025 def sve_elm_idx_extdup_b
1026 : AsmVectorIndexOpnd<SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1027 def sve_elm_idx_extdup_h
1028 : AsmVectorIndexOpnd<SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1029 def sve_elm_idx_extdup_s
1030 : AsmVectorIndexOpnd<SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1031 def sve_elm_idx_extdup_d
1032 : AsmVectorIndexOpnd<SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1033 def sve_elm_idx_extdup_q
1034 : AsmVectorIndexOpnd<SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1036 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1037 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1038 // are encoded as the eight bit value 'abcdefgh'.
1039 def simdimmtype10 : Operand<i32>,
1041 return AArch64_AM::isAdvSIMDModImmType10(
1042 Imm.bitcastToAPInt().getZExtValue());
1043 }], SDNodeXForm<fpimm, [{
1044 APFloat InVal = N->getValueAPF();
1045 uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1048 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1050 let ParserMatchClass = SIMDImmType10Operand;
1051 let PrintMethod = "printSIMDType10Operand";
1056 // System management
1059 // Base encoding for system instruction operands.
1060 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1061 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1062 list<dag> pattern = []>
1063 : I<oops, iops, asm, operands, "", pattern> {
1064 let Inst{31-22} = 0b1101010100;
1068 // System instructions which do not have an Rt register.
1069 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1070 list<dag> pattern = []>
1071 : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1072 let Inst{4-0} = 0b11111;
1075 // System instructions which have an Rt register.
1076 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1077 : BaseSystemI<L, oops, iops, asm, operands>,
1083 // Hint instructions that take both a CRm and a 3-bit immediate.
1084 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1085 // model patterns with sufficiently fine granularity
1086 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1087 class HintI<string mnemonic>
1088 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1089 [(int_aarch64_hint imm0_127:$imm)]>,
1090 Sched<[WriteHint]> {
1092 let Inst{20-12} = 0b000110010;
1093 let Inst{11-5} = imm;
1096 // System instructions taking a single literal operand which encodes into
1097 // CRm. op2 differentiates the opcodes.
1098 def BarrierAsmOperand : AsmOperandClass {
1099 let Name = "Barrier";
1100 let ParserMethod = "tryParseBarrierOperand";
1102 def barrier_op : Operand<i32> {
1103 let PrintMethod = "printBarrierOption";
1104 let ParserMatchClass = BarrierAsmOperand;
1106 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1107 list<dag> pattern = []>
1108 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1109 Sched<[WriteBarrier]> {
1111 let Inst{20-12} = 0b000110011;
1112 let Inst{11-8} = CRm;
1113 let Inst{7-5} = opc;
1116 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1117 : SimpleSystemI<0, (ins), asm, "", pattern>,
1121 let Inst{31-12} = 0b11010101000000110010;
1122 let Inst{11-8} = CRm;
1123 let Inst{7-5} = op2;
1124 let Inst{4-0} = 0b11111;
1127 // MRS/MSR system instructions. These have different operand classes because
1128 // a different subset of registers can be accessed through each instruction.
1129 def MRSSystemRegisterOperand : AsmOperandClass {
1130 let Name = "MRSSystemRegister";
1131 let ParserMethod = "tryParseSysReg";
1132 let DiagnosticType = "MRS";
1134 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1135 def mrs_sysreg_op : Operand<i32> {
1136 let ParserMatchClass = MRSSystemRegisterOperand;
1137 let DecoderMethod = "DecodeMRSSystemRegister";
1138 let PrintMethod = "printMRSSystemRegister";
1141 def MSRSystemRegisterOperand : AsmOperandClass {
1142 let Name = "MSRSystemRegister";
1143 let ParserMethod = "tryParseSysReg";
1144 let DiagnosticType = "MSR";
1146 def msr_sysreg_op : Operand<i32> {
1147 let ParserMatchClass = MSRSystemRegisterOperand;
1148 let DecoderMethod = "DecodeMSRSystemRegister";
1149 let PrintMethod = "printMSRSystemRegister";
1152 def PSBHintOperand : AsmOperandClass {
1153 let Name = "PSBHint";
1154 let ParserMethod = "tryParsePSBHint";
1156 def psbhint_op : Operand<i32> {
1157 let ParserMatchClass = PSBHintOperand;
1158 let PrintMethod = "printPSBHintOp";
1159 let MCOperandPredicate = [{
1160 // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1161 // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1164 return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1168 def BTIHintOperand : AsmOperandClass {
1169 let Name = "BTIHint";
1170 let ParserMethod = "tryParseBTIHint";
1172 def btihint_op : Operand<i32> {
1173 let ParserMatchClass = BTIHintOperand;
1174 let PrintMethod = "printBTIHintOp";
1175 let MCOperandPredicate = [{
1176 // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1179 return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1183 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1184 "mrs", "\t$Rt, $systemreg"> {
1186 let Inst{20-5} = systemreg;
1189 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1190 // Explicitly modeling each of the system register as a register class
1191 // would do it, but feels like overkill at this point.
1192 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1193 "msr", "\t$systemreg, $Rt"> {
1195 let Inst{20-5} = systemreg;
1198 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1199 let Name = "SystemPStateFieldWithImm0_15";
1200 let ParserMethod = "tryParseSysReg";
1202 def pstatefield4_op : Operand<i32> {
1203 let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1204 let PrintMethod = "printSystemPStateField";
1207 // Instructions to modify PSTATE, no input reg
1208 let Defs = [NZCV] in
1209 class PstateWriteSimple<dag iops, string asm, string operands>
1210 : SimpleSystemI<0, iops, asm, operands> {
1212 let Inst{20-19} = 0b00;
1213 let Inst{15-12} = 0b0100;
1216 class MSRpstateImm0_15
1217 : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1218 "\t$pstatefield, $imm">,
1221 bits<6> pstatefield;
1223 let Inst{18-16} = pstatefield{5-3};
1224 let Inst{11-8} = imm;
1225 let Inst{7-5} = pstatefield{2-0};
1227 let DecoderMethod = "DecodeSystemPStateInstruction";
1228 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1229 // Fail the decoder should attempt to decode the instruction as MSRI.
1230 let hasCompleteDecoder = 0;
1233 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1234 let Name = "SystemPStateFieldWithImm0_1";
1235 let ParserMethod = "tryParseSysReg";
1237 def pstatefield1_op : Operand<i32> {
1238 let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1239 let PrintMethod = "printSystemPStateField";
1242 class MSRpstateImm0_1
1243 : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1244 "\t$pstatefield, $imm">,
1247 bits<6> pstatefield;
1249 let Inst{18-16} = pstatefield{5-3};
1250 let Inst{11-9} = 0b000;
1252 let Inst{7-5} = pstatefield{2-0};
1254 let DecoderMethod = "DecodeSystemPStateInstruction";
1255 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1256 // Fail the decoder should attempt to decode the instruction as MSRI.
1257 let hasCompleteDecoder = 0;
1260 // SYS and SYSL generic system instructions.
1261 def SysCRAsmOperand : AsmOperandClass {
1263 let ParserMethod = "tryParseSysCROperand";
1266 def sys_cr_op : Operand<i32> {
1267 let PrintMethod = "printSysCROperand";
1268 let ParserMatchClass = SysCRAsmOperand;
1271 class SystemXtI<bit L, string asm>
1272 : RtSystemI<L, (outs),
1273 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1274 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1279 let Inst{20-19} = 0b01;
1280 let Inst{18-16} = op1;
1281 let Inst{15-12} = Cn;
1282 let Inst{11-8} = Cm;
1283 let Inst{7-5} = op2;
1286 class SystemLXtI<bit L, string asm>
1287 : RtSystemI<L, (outs),
1288 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1289 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1294 let Inst{20-19} = 0b01;
1295 let Inst{18-16} = op1;
1296 let Inst{15-12} = Cn;
1297 let Inst{11-8} = Cm;
1298 let Inst{7-5} = op2;
1302 // Branch (register) instructions:
1310 // otherwise UNDEFINED
1311 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1312 string operands, list<dag> pattern>
1313 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1314 let Inst{31-25} = 0b1101011;
1315 let Inst{24-21} = opc;
1316 let Inst{20-16} = 0b11111;
1317 let Inst{15-10} = 0b000000;
1318 let Inst{4-0} = 0b00000;
1321 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1322 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1327 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1328 class SpecialReturn<bits<4> opc, string asm>
1329 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1330 let Inst{9-5} = 0b11111;
1334 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1335 : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1339 let Inst{31-30} = sz;
1340 let Inst{29-10} = 0b11100010111111110000;
1345 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1347 : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1348 let Inst{31-25} = 0b1101011;
1349 let Inst{20-11} = 0b1111100001;
1351 let Inst{4-0} = 0b11111;
1354 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1355 : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1358 let Inst{24-22} = 0b100;
1364 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1365 : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1368 let Inst{23-21} = opc;
1372 class AuthReturn<bits<3> op, bits<1> M, string asm>
1373 : AuthBase<M, (outs), (ins), asm, "", []> {
1375 let Inst{23-21} = op;
1376 let Inst{9-0} = 0b1111111111;
1380 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1381 string operands, string cstr, Operand opr>
1382 : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1386 let Inst{31-24} = 0b11111000;
1388 let Inst{22} = offset{9};
1390 let Inst{20-12} = offset{8-0};
1397 multiclass AuthLoad<bit M, string asm, Operand opr> {
1398 def indexed : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1399 (ins GPR64sp:$Rn, opr:$offset),
1400 asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1401 def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1402 (ins GPR64sp:$Rn, opr:$offset),
1403 asm, "\t$Rt, [$Rn, $offset]!",
1404 "$Rn = $wback,@earlyclobber $wback", opr>;
1406 def : InstAlias<asm # "\t$Rt, [$Rn]",
1407 (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1411 // Conditional branch instruction.
1415 // 4-bit immediate. Pretty-printed as <cc>
1416 def ccode : Operand<i32> {
1417 let PrintMethod = "printCondCode";
1418 let ParserMatchClass = CondCode;
1420 def inv_ccode : Operand<i32> {
1421 // AL and NV are invalid in the aliases which use inv_ccode
1422 let PrintMethod = "printInverseCondCode";
1423 let ParserMatchClass = CondCode;
1424 let MCOperandPredicate = [{
1425 return MCOp.isImm() &&
1426 MCOp.getImm() != AArch64CC::AL &&
1427 MCOp.getImm() != AArch64CC::NV;
1431 // Conditional branch target. 19-bit immediate. The low two bits of the target
1432 // offset are implied zero and so are not part of the immediate.
1433 def am_brcond : Operand<OtherVT> {
1434 let EncoderMethod = "getCondBranchTargetOpValue";
1435 let DecoderMethod = "DecodePCRelLabel19";
1436 let PrintMethod = "printAlignedLabel";
1437 let ParserMatchClass = PCRelLabel19Operand;
1438 let OperandType = "OPERAND_PCREL";
1441 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1442 "b", ".$cond\t$target", "",
1443 [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1446 let isTerminator = 1;
1451 let Inst{31-24} = 0b01010100;
1452 let Inst{23-5} = target;
1454 let Inst{3-0} = cond;
1458 // Compare-and-branch instructions.
1460 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1461 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1462 asm, "\t$Rt, $target", "",
1463 [(node regtype:$Rt, bb:$target)]>,
1466 let isTerminator = 1;
1470 let Inst{30-25} = 0b011010;
1472 let Inst{23-5} = target;
1476 multiclass CmpBranch<bit op, string asm, SDNode node> {
1477 def W : BaseCmpBranch<GPR32, op, asm, node> {
1480 def X : BaseCmpBranch<GPR64, op, asm, node> {
1486 // Test-bit-and-branch instructions.
1488 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1489 // the target offset are implied zero and so are not part of the immediate.
1490 def am_tbrcond : Operand<OtherVT> {
1491 let EncoderMethod = "getTestBranchTargetOpValue";
1492 let PrintMethod = "printAlignedLabel";
1493 let ParserMatchClass = BranchTarget14Operand;
1494 let OperandType = "OPERAND_PCREL";
1497 // AsmOperand classes to emit (or not) special diagnostics
1498 def TBZImm0_31Operand : AsmOperandClass {
1499 let Name = "TBZImm0_31";
1500 let PredicateMethod = "isImmInRange<0,31>";
1501 let RenderMethod = "addImmOperands";
1503 def TBZImm32_63Operand : AsmOperandClass {
1504 let Name = "Imm32_63";
1505 let PredicateMethod = "isImmInRange<32,63>";
1506 let DiagnosticType = "InvalidImm0_63";
1507 let RenderMethod = "addImmOperands";
1510 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1511 return (((uint32_t)Imm) < 32);
1513 let ParserMatchClass = matcher;
1516 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1517 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1519 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1520 return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1522 let ParserMatchClass = TBZImm32_63Operand;
1525 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1526 bit op, string asm, SDNode node>
1527 : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1528 asm, "\t$Rt, $bit_off, $target", "",
1529 [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1532 let isTerminator = 1;
1538 let Inst{30-25} = 0b011011;
1540 let Inst{23-19} = bit_off{4-0};
1541 let Inst{18-5} = target;
1544 let DecoderMethod = "DecodeTestAndBranch";
1547 multiclass TestBranch<bit op, string asm, SDNode node> {
1548 def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1552 def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1556 // Alias X-reg with 0-31 imm to W-Reg.
1557 def : InstAlias<asm # "\t$Rd, $imm, $target",
1558 (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1559 tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1560 def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1561 (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1562 tbz_imm0_31_diag:$imm, bb:$target)>;
1566 // Unconditional branch (immediate) instructions.
1568 def am_b_target : Operand<OtherVT> {
1569 let EncoderMethod = "getBranchTargetOpValue";
1570 let PrintMethod = "printAlignedLabel";
1571 let ParserMatchClass = BranchTarget26Operand;
1572 let OperandType = "OPERAND_PCREL";
1574 def am_bl_target : Operand<i64> {
1575 let EncoderMethod = "getBranchTargetOpValue";
1576 let PrintMethod = "printAlignedLabel";
1577 let ParserMatchClass = BranchTarget26Operand;
1578 let OperandType = "OPERAND_PCREL";
1581 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1582 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1585 let Inst{30-26} = 0b00101;
1586 let Inst{25-0} = addr;
1588 let DecoderMethod = "DecodeUnconditionalBranch";
1591 class BranchImm<bit op, string asm, list<dag> pattern>
1592 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1593 class CallImm<bit op, string asm, list<dag> pattern>
1594 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1597 // Basic one-operand data processing instructions.
1600 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1601 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1602 SDPatternOperator node>
1603 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1604 [(set regtype:$Rd, (node regtype:$Rn))]>,
1605 Sched<[WriteI, ReadI]> {
1609 let Inst{30-13} = 0b101101011000000000;
1610 let Inst{12-10} = opc;
1615 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1616 multiclass OneOperandData<bits<3> opc, string asm,
1617 SDPatternOperator node = null_frag> {
1618 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1622 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1627 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1628 : BaseOneOperandData<opc, GPR32, asm, node> {
1632 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1633 : BaseOneOperandData<opc, GPR64, asm, node> {
1637 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1638 : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1640 Sched<[WriteI, ReadI]> {
1643 let Inst{31-15} = 0b11011010110000010;
1644 let Inst{14-12} = opcode_prefix;
1645 let Inst{11-10} = opcode;
1650 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1651 : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1653 let Inst{31-15} = 0b11011010110000010;
1654 let Inst{14-12} = opcode_prefix;
1655 let Inst{11-10} = opcode;
1656 let Inst{9-5} = 0b11111;
1660 class SignAuthTwoOperand<bits<4> opc, string asm,
1661 SDPatternOperator OpNode>
1662 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1663 asm, "\t$Rd, $Rn, $Rm", "",
1664 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1665 Sched<[WriteI, ReadI, ReadI]> {
1669 let Inst{31-21} = 0b10011010110;
1670 let Inst{20-16} = Rm;
1671 let Inst{15-14} = 0b00;
1672 let Inst{13-10} = opc;
1677 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1678 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1679 : I<(outs), iops, asm, ops, "", []>,
1680 Sched<[WriteI, ReadI, ReadI]> {
1684 let Inst{30-15} = 0b0111010000000000;
1686 let Inst{13-10} = 0b0010;
1688 let Inst{4-0} = 0b01101;
1691 class FlagRotate<dag iops, string asm, string ops>
1692 : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1695 let Inst{20-15} = imm;
1696 let Inst{13-10} = 0b0001;
1698 let Inst{3-0} = mask;
1702 // Basic two-operand data processing instructions.
1704 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1706 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1707 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1708 Sched<[WriteI, ReadI, ReadI]> {
1713 let Inst{30} = isSub;
1714 let Inst{28-21} = 0b11010000;
1715 let Inst{20-16} = Rm;
1716 let Inst{15-10} = 0;
1721 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1723 : BaseBaseAddSubCarry<isSub, regtype, asm,
1724 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1726 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1728 : BaseBaseAddSubCarry<isSub, regtype, asm,
1729 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1734 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1735 SDNode OpNode, SDNode OpNode_setflags> {
1736 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1740 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1746 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1751 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1758 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1759 SDPatternOperator OpNode,
1760 RegisterClass in1regtype = regtype,
1761 RegisterClass in2regtype = regtype>
1762 : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
1763 asm, "\t$Rd, $Rn, $Rm", "",
1764 [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
1768 let Inst{30-21} = 0b0011010110;
1769 let Inst{20-16} = Rm;
1770 let Inst{15-14} = 0b00;
1771 let Inst{13-10} = opc;
1776 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1777 SDPatternOperator OpNode>
1778 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1779 let Inst{10} = isSigned;
1782 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1783 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1784 Sched<[WriteID32, ReadID, ReadID]> {
1787 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1788 Sched<[WriteID64, ReadID, ReadID]> {
1793 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1794 SDPatternOperator OpNode = null_frag>
1795 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1796 Sched<[WriteIS, ReadI]> {
1797 let Inst{11-10} = shift_type;
1800 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1801 def Wr : BaseShift<shift_type, GPR32, asm> {
1805 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1809 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1810 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1811 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1813 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1814 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1816 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1817 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1819 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1820 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1823 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1824 : InstAlias<asm#"\t$dst, $src1, $src2",
1825 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1827 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1828 RegisterClass addtype, string asm,
1830 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1831 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1836 let Inst{30-24} = 0b0011011;
1837 let Inst{23-21} = opc;
1838 let Inst{20-16} = Rm;
1839 let Inst{15} = isSub;
1840 let Inst{14-10} = Ra;
1845 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1846 // MADD/MSUB generation is decided by MachineCombiner.cpp
1847 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1848 [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1849 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1853 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1854 [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1855 Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1860 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1861 SDNode AccNode, SDNode ExtNode>
1862 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1863 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1864 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1865 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1869 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1870 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1871 asm, "\t$Rd, $Rn, $Rm", "",
1872 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1873 Sched<[WriteIM64, ReadIM, ReadIM]> {
1877 let Inst{31-24} = 0b10011011;
1878 let Inst{23-21} = opc;
1879 let Inst{20-16} = Rm;
1884 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1885 // (i.e. all bits 1) but is ignored by the processor.
1886 let PostEncoderMethod = "fixMulHigh";
1889 class MulAccumWAlias<string asm, Instruction inst>
1890 : InstAlias<asm#"\t$dst, $src1, $src2",
1891 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1892 class MulAccumXAlias<string asm, Instruction inst>
1893 : InstAlias<asm#"\t$dst, $src1, $src2",
1894 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1895 class WideMulAccumAlias<string asm, Instruction inst>
1896 : InstAlias<asm#"\t$dst, $src1, $src2",
1897 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1899 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1900 SDPatternOperator OpNode, string asm>
1901 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1902 asm, "\t$Rd, $Rn, $Rm", "",
1903 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1904 Sched<[WriteISReg, ReadI, ReadISReg]> {
1910 let Inst{30-21} = 0b0011010110;
1911 let Inst{20-16} = Rm;
1912 let Inst{15-13} = 0b010;
1914 let Inst{11-10} = sz;
1917 let Predicates = [HasCRC];
1921 // Address generation.
1924 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1925 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1930 let Inst{31} = page;
1931 let Inst{30-29} = label{1-0};
1932 let Inst{28-24} = 0b10000;
1933 let Inst{23-5} = label{20-2};
1936 let DecoderMethod = "DecodeAdrInstruction";
1943 def movimm32_imm : Operand<i32> {
1944 let ParserMatchClass = AsmImmRange<0, 65535>;
1945 let EncoderMethod = "getMoveWideImmOpValue";
1946 let PrintMethod = "printImm";
1948 def movimm32_shift : Operand<i32> {
1949 let PrintMethod = "printShifter";
1950 let ParserMatchClass = MovImm32ShifterOperand;
1952 def movimm64_shift : Operand<i32> {
1953 let PrintMethod = "printShifter";
1954 let ParserMatchClass = MovImm64ShifterOperand;
1957 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1958 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1960 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1961 asm, "\t$Rd, $imm$shift", "", []>,
1966 let Inst{30-29} = opc;
1967 let Inst{28-23} = 0b100101;
1968 let Inst{22-21} = shift{5-4};
1969 let Inst{20-5} = imm;
1972 let DecoderMethod = "DecodeMoveImmInstruction";
1975 multiclass MoveImmediate<bits<2> opc, string asm> {
1976 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1980 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1985 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1986 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1988 : I<(outs regtype:$Rd),
1989 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1990 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1991 Sched<[WriteI, ReadI]> {
1995 let Inst{30-29} = opc;
1996 let Inst{28-23} = 0b100101;
1997 let Inst{22-21} = shift{5-4};
1998 let Inst{20-5} = imm;
2001 let DecoderMethod = "DecodeMoveImmInstruction";
2004 multiclass InsertImmediate<bits<2> opc, string asm> {
2005 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2009 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2018 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2019 string asm_inst, string asm_ops,
2020 dag inputs, dag pattern>
2021 : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2022 Sched<[WriteI, ReadI]> {
2025 let Inst{30} = isSub;
2026 let Inst{29} = setFlags;
2027 let Inst{28-24} = 0b10001;
2032 class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2033 RegisterClass srcRegtype, addsub_shifted_imm immtype,
2034 string asm_inst, SDPatternOperator OpNode>
2035 : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2036 (ins srcRegtype:$Rn, immtype:$imm),
2037 (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2039 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2040 let Inst{21-10} = imm{11-0};
2041 let DecoderMethod = "DecodeAddSubImmShift";
2044 class BaseAddSubRegPseudo<RegisterClass regtype,
2045 SDPatternOperator OpNode>
2046 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2047 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2048 Sched<[WriteI, ReadI, ReadI]>;
2050 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2051 arith_shifted_reg shifted_regtype, string asm,
2052 SDPatternOperator OpNode>
2053 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2054 asm, "\t$Rd, $Rn, $Rm", "",
2055 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2056 Sched<[WriteISReg, ReadI, ReadISReg]> {
2057 // The operands are in order to match the 'addr' MI operands, so we
2058 // don't need an encoder method and by-name matching. Just use the default
2059 // in-order handling. Since we're using by-order, make sure the names
2065 let Inst{30} = isSub;
2066 let Inst{29} = setFlags;
2067 let Inst{28-24} = 0b01011;
2068 let Inst{23-22} = shift{7-6};
2070 let Inst{20-16} = src2;
2071 let Inst{15-10} = shift{5-0};
2072 let Inst{9-5} = src1;
2073 let Inst{4-0} = dst;
2075 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2078 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2079 RegisterClass src1Regtype, Operand src2Regtype,
2080 string asm, SDPatternOperator OpNode>
2081 : I<(outs dstRegtype:$R1),
2082 (ins src1Regtype:$R2, src2Regtype:$R3),
2083 asm, "\t$R1, $R2, $R3", "",
2084 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2085 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2090 let Inst{30} = isSub;
2091 let Inst{29} = setFlags;
2092 let Inst{28-24} = 0b01011;
2093 let Inst{23-21} = 0b001;
2094 let Inst{20-16} = Rm;
2095 let Inst{15-13} = ext{5-3};
2096 let Inst{12-10} = ext{2-0};
2100 let DecoderMethod = "DecodeAddSubERegInstruction";
2103 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2104 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2105 RegisterClass src1Regtype, RegisterClass src2Regtype,
2106 Operand ext_op, string asm>
2107 : I<(outs dstRegtype:$Rd),
2108 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2109 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2110 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2115 let Inst{30} = isSub;
2116 let Inst{29} = setFlags;
2117 let Inst{28-24} = 0b01011;
2118 let Inst{23-21} = 0b001;
2119 let Inst{20-16} = Rm;
2120 let Inst{15} = ext{5};
2121 let Inst{12-10} = ext{2-0};
2125 let DecoderMethod = "DecodeAddSubERegInstruction";
2128 // Aliases for register+register add/subtract.
2129 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2130 RegisterClass src1Regtype, RegisterClass src2Regtype,
2132 : InstAlias<asm#"\t$dst, $src1, $src2",
2133 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2136 multiclass AddSub<bit isSub, string mnemonic, string alias,
2137 SDPatternOperator OpNode = null_frag> {
2138 let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2139 // Add/Subtract immediate
2140 // Increase the weight of the immediate variant to try to match it before
2141 // the extended register variant.
2142 // We used to match the register variant before the immediate when the
2143 // register argument could be implicitly zero-extended.
2144 let AddedComplexity = 6 in
2145 def Wri : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2149 let AddedComplexity = 6 in
2150 def Xri : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2155 // Add/Subtract register - Only used for CodeGen
2156 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2157 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2159 // Add/Subtract shifted register
2160 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2164 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2170 // Add/Subtract extended register
2171 let AddedComplexity = 1, hasSideEffects = 0 in {
2172 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2173 arith_extended_reg32<i32>, mnemonic, OpNode> {
2176 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2177 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
2182 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2183 arith_extendlsl64, mnemonic> {
2184 // UXTX and SXTX only.
2185 let Inst{14-13} = 0b11;
2189 // add Rd, Rb, -imm -> sub Rd, Rn, imm
2190 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2191 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2192 addsub_shifted_imm32_neg:$imm), 0>;
2193 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2194 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2195 addsub_shifted_imm64_neg:$imm), 0>;
2197 // Register/register aliases with no shift when SP is not used.
2198 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2199 GPR32, GPR32, GPR32, 0>;
2200 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2201 GPR64, GPR64, GPR64, 0>;
2203 // Register/register aliases with no shift when either the destination or
2204 // first source register is SP.
2205 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2206 GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2207 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2208 GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2209 def : AddSubRegAlias<mnemonic,
2210 !cast<Instruction>(NAME#"Xrx64"),
2211 GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2212 def : AddSubRegAlias<mnemonic,
2213 !cast<Instruction>(NAME#"Xrx64"),
2214 GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2217 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2218 string alias, string cmpAlias> {
2219 let isCompare = 1, Defs = [NZCV] in {
2220 // Add/Subtract immediate
2221 def Wri : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2225 def Xri : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2230 // Add/Subtract register
2231 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2232 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2234 // Add/Subtract shifted register
2235 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2239 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2244 // Add/Subtract extended register
2245 let AddedComplexity = 1 in {
2246 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2247 arith_extended_reg32<i32>, mnemonic, OpNode> {
2250 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2251 arith_extended_reg32<i64>, mnemonic, OpNode> {
2256 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2257 arith_extendlsl64, mnemonic> {
2258 // UXTX and SXTX only.
2259 let Inst{14-13} = 0b11;
2264 // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2265 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2266 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2267 addsub_shifted_imm32_neg:$imm), 0>;
2268 def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2269 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2270 addsub_shifted_imm64_neg:$imm), 0>;
2273 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2274 WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2275 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2276 XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2277 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2278 WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2279 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2280 XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2281 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2282 XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2283 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2284 WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2285 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2286 XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2288 // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2289 def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2290 WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2291 def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2292 XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2294 // Compare shorthands
2295 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2296 WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2297 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2298 XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2299 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2300 WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2301 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2302 XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2304 // Register/register aliases with no shift when SP is not used.
2305 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2306 GPR32, GPR32, GPR32, 0>;
2307 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2308 GPR64, GPR64, GPR64, 0>;
2310 // Register/register aliases with no shift when the first source register
2312 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2313 GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2314 def : AddSubRegAlias<mnemonic,
2315 !cast<Instruction>(NAME#"Xrx64"),
2316 GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2319 class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2321 isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2322 (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2323 (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2327 let Inst{23-22} = 0b10;
2328 let Inst{21-16} = imm6;
2329 let Inst{15-14} = 0b00;
2330 let Inst{13-10} = imm4;
2331 let Unpredictable{15-14} = 0b11;
2334 class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2335 : BaseTwoOperand<0b0000, GPR64, asm_instr, null_frag, GPR64sp, GPR64sp> {
2337 let Inst{29} = setsFlags;
2343 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2345 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2347 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2349 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2350 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2351 Sched<[WriteExtr, ReadExtrHi]> {
2357 let Inst{30-23} = 0b00100111;
2359 let Inst{20-16} = Rm;
2360 let Inst{15-10} = imm;
2365 multiclass ExtractImm<string asm> {
2366 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2368 (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2371 // imm<5> must be zero.
2374 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2376 (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2387 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2388 class BaseBitfieldImm<bits<2> opc,
2389 RegisterClass regtype, Operand imm_type, string asm>
2390 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2391 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2392 Sched<[WriteIS, ReadI]> {
2398 let Inst{30-29} = opc;
2399 let Inst{28-23} = 0b100110;
2400 let Inst{21-16} = immr;
2401 let Inst{15-10} = imms;
2406 multiclass BitfieldImm<bits<2> opc, string asm> {
2407 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2410 // imms<5> and immr<5> must be zero, else ReservedValue().
2414 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2420 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2421 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2422 RegisterClass regtype, Operand imm_type, string asm>
2423 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2425 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2426 Sched<[WriteIS, ReadI]> {
2432 let Inst{30-29} = opc;
2433 let Inst{28-23} = 0b100110;
2434 let Inst{21-16} = immr;
2435 let Inst{15-10} = imms;
2440 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2441 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2444 // imms<5> and immr<5> must be zero, else ReservedValue().
2448 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2458 // Logical (immediate)
2459 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2460 RegisterClass sregtype, Operand imm_type, string asm,
2462 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2463 asm, "\t$Rd, $Rn, $imm", "", pattern>,
2464 Sched<[WriteI, ReadI]> {
2468 let Inst{30-29} = opc;
2469 let Inst{28-23} = 0b100100;
2470 let Inst{22} = imm{12};
2471 let Inst{21-16} = imm{11-6};
2472 let Inst{15-10} = imm{5-0};
2476 let DecoderMethod = "DecodeLogicalImmInstruction";
2479 // Logical (shifted register)
2480 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2481 logical_shifted_reg shifted_regtype, string asm,
2483 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2484 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2485 Sched<[WriteISReg, ReadI, ReadISReg]> {
2486 // The operands are in order to match the 'addr' MI operands, so we
2487 // don't need an encoder method and by-name matching. Just use the default
2488 // in-order handling. Since we're using by-order, make sure the names
2494 let Inst{30-29} = opc;
2495 let Inst{28-24} = 0b01010;
2496 let Inst{23-22} = shift{7-6};
2498 let Inst{20-16} = src2;
2499 let Inst{15-10} = shift{5-0};
2500 let Inst{9-5} = src1;
2501 let Inst{4-0} = dst;
2503 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2506 // Aliases for register+register logical instructions.
2507 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2508 : InstAlias<asm#"\t$dst, $src1, $src2",
2509 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2511 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2513 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2514 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2515 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2516 logical_imm32:$imm))]> {
2518 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2520 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2521 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2522 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2523 logical_imm64:$imm))]> {
2527 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2528 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2529 logical_imm32_not:$imm), 0>;
2530 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2531 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2532 logical_imm64_not:$imm), 0>;
2535 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2537 let isCompare = 1, Defs = [NZCV] in {
2538 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2539 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2541 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2543 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2544 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2547 } // end Defs = [NZCV]
2549 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2550 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2551 logical_imm32_not:$imm), 0>;
2552 def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2553 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2554 logical_imm64_not:$imm), 0>;
2557 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2558 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2559 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2560 Sched<[WriteI, ReadI, ReadI]>;
2562 // Split from LogicalImm as not all instructions have both.
2563 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2564 SDPatternOperator OpNode> {
2565 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2566 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2567 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2570 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2571 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2572 logical_shifted_reg32:$Rm))]> {
2575 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2576 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2577 logical_shifted_reg64:$Rm))]> {
2581 def : LogicalRegAlias<mnemonic,
2582 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2583 def : LogicalRegAlias<mnemonic,
2584 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2587 // Split from LogicalReg to allow setting NZCV Defs
2588 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2589 SDPatternOperator OpNode = null_frag> {
2590 let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2591 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2592 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2594 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2595 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2598 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2599 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2604 def : LogicalRegAlias<mnemonic,
2605 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2606 def : LogicalRegAlias<mnemonic,
2607 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2611 // Conditionally set flags
2614 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2615 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2616 string mnemonic, SDNode OpNode>
2617 : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2618 mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2619 [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2620 (i32 imm:$cond), NZCV))]>,
2621 Sched<[WriteI, ReadI]> {
2631 let Inst{29-21} = 0b111010010;
2632 let Inst{20-16} = imm;
2633 let Inst{15-12} = cond;
2634 let Inst{11-10} = 0b10;
2637 let Inst{3-0} = nzcv;
2640 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2641 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2643 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2644 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2645 [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2646 (i32 imm:$cond), NZCV))]>,
2647 Sched<[WriteI, ReadI, ReadI]> {
2657 let Inst{29-21} = 0b111010010;
2658 let Inst{20-16} = Rm;
2659 let Inst{15-12} = cond;
2660 let Inst{11-10} = 0b00;
2663 let Inst{3-0} = nzcv;
2666 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2667 // immediate operand variants
2668 def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2671 def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2674 // register operand variants
2675 def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2678 def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2684 // Conditional select
2687 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2688 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2689 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2691 (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2692 Sched<[WriteI, ReadI, ReadI]> {
2701 let Inst{29-21} = 0b011010100;
2702 let Inst{20-16} = Rm;
2703 let Inst{15-12} = cond;
2704 let Inst{11-10} = op2;
2709 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2710 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2713 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2718 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2720 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2721 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2723 (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2724 (i32 imm:$cond), NZCV))]>,
2725 Sched<[WriteI, ReadI, ReadI]> {
2734 let Inst{29-21} = 0b011010100;
2735 let Inst{20-16} = Rm;
2736 let Inst{15-12} = cond;
2737 let Inst{11-10} = op2;
2742 def inv_cond_XFORM : SDNodeXForm<imm, [{
2743 AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2744 return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2748 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2749 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2752 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2756 def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2757 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2758 (inv_cond_XFORM imm:$cond))>;
2760 def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2761 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2762 (inv_cond_XFORM imm:$cond))>;
2766 // Special Mask Value
2768 def maski8_or_more : Operand<i32>,
2769 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2771 def maski16_or_more : Operand<i32>,
2772 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2780 // (unsigned immediate)
2781 // Indexed for 8-bit registers. offset is in range [0,4095].
2782 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2783 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2784 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2785 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2786 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2788 def gi_am_indexed8 :
2789 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2790 GIComplexPatternEquiv<am_indexed8>;
2791 def gi_am_indexed16 :
2792 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2793 GIComplexPatternEquiv<am_indexed16>;
2794 def gi_am_indexed32 :
2795 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2796 GIComplexPatternEquiv<am_indexed32>;
2797 def gi_am_indexed64 :
2798 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2799 GIComplexPatternEquiv<am_indexed64>;
2800 def gi_am_indexed128 :
2801 GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2802 GIComplexPatternEquiv<am_indexed128>;
2804 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2805 let Name = "UImm12Offset" # Scale;
2806 let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2807 let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2808 let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2811 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2812 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2813 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2814 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2815 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2817 class uimm12_scaled<int Scale> : Operand<i64> {
2818 let ParserMatchClass
2819 = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2821 = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2822 let PrintMethod = "printUImm12Offset<" # Scale # ">";
2825 def uimm12s1 : uimm12_scaled<1>;
2826 def uimm12s2 : uimm12_scaled<2>;
2827 def uimm12s4 : uimm12_scaled<4>;
2828 def uimm12s8 : uimm12_scaled<8>;
2829 def uimm12s16 : uimm12_scaled<16>;
2831 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2832 string asm, list<dag> pattern>
2833 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2839 let Inst{31-30} = sz;
2840 let Inst{29-27} = 0b111;
2842 let Inst{25-24} = 0b01;
2843 let Inst{23-22} = opc;
2844 let Inst{21-10} = offset;
2848 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2851 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2852 Operand indextype, string asm, list<dag> pattern> {
2853 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2854 def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2855 (ins GPR64sp:$Rn, indextype:$offset),
2859 def : InstAlias<asm # "\t$Rt, [$Rn]",
2860 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2863 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2864 Operand indextype, string asm, list<dag> pattern> {
2865 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2866 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2867 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2871 def : InstAlias<asm # "\t$Rt, [$Rn]",
2872 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2875 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2876 // substitute zero-registers automatically.
2878 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2880 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2881 Operand indextype, string asm, list<dag> pattern> {
2882 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2883 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2884 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2888 def : InstAlias<asm # "\t$Rt, [$Rn]",
2889 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2892 def PrefetchOperand : AsmOperandClass {
2893 let Name = "Prefetch";
2894 let ParserMethod = "tryParsePrefetch";
2896 def prfop : Operand<i32> {
2897 let PrintMethod = "printPrefetchOp";
2898 let ParserMatchClass = PrefetchOperand;
2901 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2902 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2903 : BaseLoadStoreUI<sz, V, opc,
2904 (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2912 // Load literal address: 19-bit immediate. The low two bits of the target
2913 // offset are implied zero and so are not part of the immediate.
2914 def am_ldrlit : Operand<iPTR> {
2915 let EncoderMethod = "getLoadLiteralOpValue";
2916 let DecoderMethod = "DecodePCRelLabel19";
2917 let PrintMethod = "printAlignedLabel";
2918 let ParserMatchClass = PCRelLabel19Operand;
2919 let OperandType = "OPERAND_PCREL";
2922 let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
2923 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
2924 : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2925 asm, "\t$Rt, $label", "", pat>,
2929 let Inst{31-30} = opc;
2930 let Inst{29-27} = 0b011;
2932 let Inst{25-24} = 0b00;
2933 let Inst{23-5} = label;
2937 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2938 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2939 : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2940 asm, "\t$Rt, $label", "", pat>,
2944 let Inst{31-30} = opc;
2945 let Inst{29-27} = 0b011;
2947 let Inst{25-24} = 0b00;
2948 let Inst{23-5} = label;
2953 // Load/store register offset
2956 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2957 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2958 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2959 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2960 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2962 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2963 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2964 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2965 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2966 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2968 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2969 let Name = "Mem" # Reg # "Extend" # Width;
2970 let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2971 let RenderMethod = "addMemExtendOperands";
2972 let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2975 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2976 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2977 // the trivial shift.
2978 let RenderMethod = "addMemExtend8Operands";
2980 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2981 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2982 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2983 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2985 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2986 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2987 // the trivial shift.
2988 let RenderMethod = "addMemExtend8Operands";
2990 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2991 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2992 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2993 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2995 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2997 let ParserMatchClass = ParserClass;
2998 let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2999 let DecoderMethod = "DecodeMemExtend";
3000 let EncoderMethod = "getMemExtendOpValue";
3001 let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3004 def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>;
3005 def ro_Wextend16 : ro_extend<MemWExtend16Operand, "w", 16>;
3006 def ro_Wextend32 : ro_extend<MemWExtend32Operand, "w", 32>;
3007 def ro_Wextend64 : ro_extend<MemWExtend64Operand, "w", 64>;
3008 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3010 def ro_Xextend8 : ro_extend<MemXExtend8Operand, "x", 8>;
3011 def ro_Xextend16 : ro_extend<MemXExtend16Operand, "x", 16>;
3012 def ro_Xextend32 : ro_extend<MemXExtend32Operand, "x", 32>;
3013 def ro_Xextend64 : ro_extend<MemXExtend64Operand, "x", 64>;
3014 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3016 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3017 Operand wextend, Operand xextend> {
3018 // CodeGen-level pattern covering the entire addressing mode.
3019 ComplexPattern Wpat = windex;
3020 ComplexPattern Xpat = xindex;
3022 // Asm-level Operand covering the valid "uxtw #3" style syntax.
3023 Operand Wext = wextend;
3024 Operand Xext = xextend;
3027 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3028 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3029 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3030 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3031 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3034 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3035 string asm, dag ins, dag outs, list<dag> pat>
3036 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3041 let Inst{31-30} = sz;
3042 let Inst{29-27} = 0b111;
3044 let Inst{25-24} = 0b00;
3045 let Inst{23-22} = opc;
3047 let Inst{20-16} = Rm;
3048 let Inst{15} = extend{1}; // sign extend Rm?
3050 let Inst{12} = extend{0}; // do shift?
3051 let Inst{11-10} = 0b10;
3056 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3057 : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3058 (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3060 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3061 string asm, ValueType Ty, SDPatternOperator loadop> {
3062 let AddedComplexity = 10 in
3063 def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3065 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3066 [(set (Ty regtype:$Rt),
3067 (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3068 ro_Wextend8:$extend)))]>,
3069 Sched<[WriteLDIdx, ReadAdrBase]> {
3073 let AddedComplexity = 10 in
3074 def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3076 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3077 [(set (Ty regtype:$Rt),
3078 (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3079 ro_Xextend8:$extend)))]>,
3080 Sched<[WriteLDIdx, ReadAdrBase]> {
3084 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3087 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3088 string asm, ValueType Ty, SDPatternOperator storeop> {
3089 let AddedComplexity = 10 in
3090 def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3091 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3092 [(storeop (Ty regtype:$Rt),
3093 (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3094 ro_Wextend8:$extend))]>,
3095 Sched<[WriteSTIdx, ReadAdrBase]> {
3099 let AddedComplexity = 10 in
3100 def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3101 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3102 [(storeop (Ty regtype:$Rt),
3103 (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3104 ro_Xextend8:$extend))]>,
3105 Sched<[WriteSTIdx, ReadAdrBase]> {
3109 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3112 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3113 string asm, dag ins, dag outs, list<dag> pat>
3114 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3119 let Inst{31-30} = sz;
3120 let Inst{29-27} = 0b111;
3122 let Inst{25-24} = 0b00;
3123 let Inst{23-22} = opc;
3125 let Inst{20-16} = Rm;
3126 let Inst{15} = extend{1}; // sign extend Rm?
3128 let Inst{12} = extend{0}; // do shift?
3129 let Inst{11-10} = 0b10;
3134 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3135 string asm, ValueType Ty, SDPatternOperator loadop> {
3136 let AddedComplexity = 10 in
3137 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3138 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3139 [(set (Ty regtype:$Rt),
3140 (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3141 ro_Wextend16:$extend)))]>,
3142 Sched<[WriteLDIdx, ReadAdrBase]> {
3146 let AddedComplexity = 10 in
3147 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3148 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3149 [(set (Ty regtype:$Rt),
3150 (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3151 ro_Xextend16:$extend)))]>,
3152 Sched<[WriteLDIdx, ReadAdrBase]> {
3156 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3159 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3160 string asm, ValueType Ty, SDPatternOperator storeop> {
3161 let AddedComplexity = 10 in
3162 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3163 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3164 [(storeop (Ty regtype:$Rt),
3165 (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3166 ro_Wextend16:$extend))]>,
3167 Sched<[WriteSTIdx, ReadAdrBase]> {
3171 let AddedComplexity = 10 in
3172 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3173 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3174 [(storeop (Ty regtype:$Rt),
3175 (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3176 ro_Xextend16:$extend))]>,
3177 Sched<[WriteSTIdx, ReadAdrBase]> {
3181 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3184 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3185 string asm, dag ins, dag outs, list<dag> pat>
3186 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3191 let Inst{31-30} = sz;
3192 let Inst{29-27} = 0b111;
3194 let Inst{25-24} = 0b00;
3195 let Inst{23-22} = opc;
3197 let Inst{20-16} = Rm;
3198 let Inst{15} = extend{1}; // sign extend Rm?
3200 let Inst{12} = extend{0}; // do shift?
3201 let Inst{11-10} = 0b10;
3206 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3207 string asm, ValueType Ty, SDPatternOperator loadop> {
3208 let AddedComplexity = 10 in
3209 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3210 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3211 [(set (Ty regtype:$Rt),
3212 (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3213 ro_Wextend32:$extend)))]>,
3214 Sched<[WriteLDIdx, ReadAdrBase]> {
3218 let AddedComplexity = 10 in
3219 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3220 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3221 [(set (Ty regtype:$Rt),
3222 (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3223 ro_Xextend32:$extend)))]>,
3224 Sched<[WriteLDIdx, ReadAdrBase]> {
3228 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3231 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3232 string asm, ValueType Ty, SDPatternOperator storeop> {
3233 let AddedComplexity = 10 in
3234 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3235 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3236 [(storeop (Ty regtype:$Rt),
3237 (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3238 ro_Wextend32:$extend))]>,
3239 Sched<[WriteSTIdx, ReadAdrBase]> {
3243 let AddedComplexity = 10 in
3244 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3245 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3246 [(storeop (Ty regtype:$Rt),
3247 (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3248 ro_Xextend32:$extend))]>,
3249 Sched<[WriteSTIdx, ReadAdrBase]> {
3253 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3256 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3257 string asm, dag ins, dag outs, list<dag> pat>
3258 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3263 let Inst{31-30} = sz;
3264 let Inst{29-27} = 0b111;
3266 let Inst{25-24} = 0b00;
3267 let Inst{23-22} = opc;
3269 let Inst{20-16} = Rm;
3270 let Inst{15} = extend{1}; // sign extend Rm?
3272 let Inst{12} = extend{0}; // do shift?
3273 let Inst{11-10} = 0b10;
3278 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3279 string asm, ValueType Ty, SDPatternOperator loadop> {
3280 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3281 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3282 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3283 [(set (Ty regtype:$Rt),
3284 (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3285 ro_Wextend64:$extend)))]>,
3286 Sched<[WriteLDIdx, ReadAdrBase]> {
3290 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3291 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3292 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3293 [(set (Ty regtype:$Rt),
3294 (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3295 ro_Xextend64:$extend)))]>,
3296 Sched<[WriteLDIdx, ReadAdrBase]> {
3300 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3303 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3304 string asm, ValueType Ty, SDPatternOperator storeop> {
3305 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3306 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3307 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3308 [(storeop (Ty regtype:$Rt),
3309 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3310 ro_Wextend64:$extend))]>,
3311 Sched<[WriteSTIdx, ReadAdrBase]> {
3315 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3316 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3317 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3318 [(storeop (Ty regtype:$Rt),
3319 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3320 ro_Xextend64:$extend))]>,
3321 Sched<[WriteSTIdx, ReadAdrBase]> {
3325 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3328 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3329 string asm, dag ins, dag outs, list<dag> pat>
3330 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3335 let Inst{31-30} = sz;
3336 let Inst{29-27} = 0b111;
3338 let Inst{25-24} = 0b00;
3339 let Inst{23-22} = opc;
3341 let Inst{20-16} = Rm;
3342 let Inst{15} = extend{1}; // sign extend Rm?
3344 let Inst{12} = extend{0}; // do shift?
3345 let Inst{11-10} = 0b10;
3350 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3351 string asm, ValueType Ty, SDPatternOperator loadop> {
3352 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3353 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3354 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3355 [(set (Ty regtype:$Rt),
3356 (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3357 ro_Wextend128:$extend)))]>,
3358 Sched<[WriteLDIdx, ReadAdrBase]> {
3362 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3363 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3364 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3365 [(set (Ty regtype:$Rt),
3366 (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3367 ro_Xextend128:$extend)))]>,
3368 Sched<[WriteLDIdx, ReadAdrBase]> {
3372 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3375 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3376 string asm, ValueType Ty, SDPatternOperator storeop> {
3377 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3378 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3379 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3381 Sched<[WriteSTIdx, ReadAdrBase]> {
3385 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3386 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3387 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3389 Sched<[WriteSTIdx, ReadAdrBase]> {
3393 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3396 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3397 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3398 string asm, list<dag> pat>
3399 : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3405 let Inst{31-30} = sz;
3406 let Inst{29-27} = 0b111;
3408 let Inst{25-24} = 0b00;
3409 let Inst{23-22} = opc;
3411 let Inst{20-16} = Rm;
3412 let Inst{15} = extend{1}; // sign extend Rm?
3414 let Inst{12} = extend{0}; // do shift?
3415 let Inst{11-10} = 0b10;
3420 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3421 def roW : BasePrefetchRO<sz, V, opc, (outs),
3422 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3423 asm, [(AArch64Prefetch imm:$Rt,
3424 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3425 ro_Wextend64:$extend))]> {
3429 def roX : BasePrefetchRO<sz, V, opc, (outs),
3430 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3431 asm, [(AArch64Prefetch imm:$Rt,
3432 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3433 ro_Xextend64:$extend))]> {
3437 def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3438 (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3439 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3443 // Load/store unscaled immediate
3446 def am_unscaled8 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3447 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3448 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3449 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3450 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3452 def gi_am_unscaled8 :
3453 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3454 GIComplexPatternEquiv<am_unscaled8>;
3455 def gi_am_unscaled16 :
3456 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3457 GIComplexPatternEquiv<am_unscaled16>;
3458 def gi_am_unscaled32 :
3459 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3460 GIComplexPatternEquiv<am_unscaled32>;
3461 def gi_am_unscaled64 :
3462 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3463 GIComplexPatternEquiv<am_unscaled64>;
3464 def gi_am_unscaled128 :
3465 GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3466 GIComplexPatternEquiv<am_unscaled128>;
3469 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3470 string asm, list<dag> pattern>
3471 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3475 let Inst{31-30} = sz;
3476 let Inst{29-27} = 0b111;
3478 let Inst{25-24} = 0b00;
3479 let Inst{23-22} = opc;
3481 let Inst{20-12} = offset;
3482 let Inst{11-10} = 0b00;
3486 let DecoderMethod = "DecodeSignedLdStInstruction";
3489 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3490 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3491 RegisterOperand regtype > {
3492 def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3493 (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3498 def : InstAlias<asm # "\t$Rt, [$Rn]",
3499 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3502 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3503 RegisterOperand regtype > {
3504 def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3505 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3511 def : InstAlias<asm # "\t$Rt, [$Rn]",
3512 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3515 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3516 string asm, list<dag> pattern> {
3517 let AddedComplexity = 1 in // try this before LoadUI
3518 def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3519 (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3522 def : InstAlias<asm # "\t$Rt, [$Rn]",
3523 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3526 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3527 string asm, list<dag> pattern> {
3528 let AddedComplexity = 1 in // try this before StoreUI
3529 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3530 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3534 def : InstAlias<asm # "\t$Rt, [$Rn]",
3535 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3538 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3540 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3541 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3542 (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3546 def : InstAlias<asm # "\t$Rt, [$Rn]",
3547 (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3551 // Load/store unscaled immediate, unprivileged
3554 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3555 dag oops, dag iops, string asm>
3556 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3560 let Inst{31-30} = sz;
3561 let Inst{29-27} = 0b111;
3563 let Inst{25-24} = 0b00;
3564 let Inst{23-22} = opc;
3566 let Inst{20-12} = offset;
3567 let Inst{11-10} = 0b10;
3571 let DecoderMethod = "DecodeSignedLdStInstruction";
3574 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3575 RegisterClass regtype, string asm> {
3576 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3577 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3578 (ins GPR64sp:$Rn, simm9:$offset), asm>,
3581 def : InstAlias<asm # "\t$Rt, [$Rn]",
3582 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3585 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3586 RegisterClass regtype, string asm> {
3587 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3588 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3589 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3593 def : InstAlias<asm # "\t$Rt, [$Rn]",
3594 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3598 // Load/store pre-indexed
3601 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3602 string asm, string cstr, list<dag> pat>
3603 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3607 let Inst{31-30} = sz;
3608 let Inst{29-27} = 0b111;
3610 let Inst{25-24} = 0;
3611 let Inst{23-22} = opc;
3613 let Inst{20-12} = offset;
3614 let Inst{11-10} = 0b11;
3618 let DecoderMethod = "DecodeSignedLdStInstruction";
3621 let hasSideEffects = 0 in {
3622 let mayStore = 0, mayLoad = 1 in
3623 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3625 : BaseLoadStorePreIdx<sz, V, opc,
3626 (outs GPR64sp:$wback, regtype:$Rt),
3627 (ins GPR64sp:$Rn, simm9:$offset), asm,
3628 "$Rn = $wback,@earlyclobber $wback", []>,
3629 Sched<[WriteLD, WriteAdr]>;
3631 let mayStore = 1, mayLoad = 0 in
3632 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3633 string asm, SDPatternOperator storeop, ValueType Ty>
3634 : BaseLoadStorePreIdx<sz, V, opc,
3635 (outs GPR64sp:$wback),
3636 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3637 asm, "$Rn = $wback,@earlyclobber $wback",
3638 [(set GPR64sp:$wback,
3639 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3640 Sched<[WriteAdr, WriteST]>;
3641 } // hasSideEffects = 0
3644 // Load/store post-indexed
3647 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3648 string asm, string cstr, list<dag> pat>
3649 : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3653 let Inst{31-30} = sz;
3654 let Inst{29-27} = 0b111;
3656 let Inst{25-24} = 0b00;
3657 let Inst{23-22} = opc;
3659 let Inst{20-12} = offset;
3660 let Inst{11-10} = 0b01;
3664 let DecoderMethod = "DecodeSignedLdStInstruction";
3667 let hasSideEffects = 0 in {
3668 let mayStore = 0, mayLoad = 1 in
3669 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3671 : BaseLoadStorePostIdx<sz, V, opc,
3672 (outs GPR64sp:$wback, regtype:$Rt),
3673 (ins GPR64sp:$Rn, simm9:$offset),
3674 asm, "$Rn = $wback,@earlyclobber $wback", []>,
3675 Sched<[WriteLD, WriteAdr]>;
3677 let mayStore = 1, mayLoad = 0 in
3678 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3679 string asm, SDPatternOperator storeop, ValueType Ty>
3680 : BaseLoadStorePostIdx<sz, V, opc,
3681 (outs GPR64sp:$wback),
3682 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3683 asm, "$Rn = $wback,@earlyclobber $wback",
3684 [(set GPR64sp:$wback,
3685 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3686 Sched<[WriteAdr, WriteST]>;
3687 } // hasSideEffects = 0
3694 // (indexed, offset)
3696 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3698 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3703 let Inst{31-30} = opc;
3704 let Inst{29-27} = 0b101;
3706 let Inst{25-23} = 0b010;
3708 let Inst{21-15} = offset;
3709 let Inst{14-10} = Rt2;
3713 let DecoderMethod = "DecodePairLdStInstruction";
3716 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3717 Operand indextype, string asm> {
3718 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3719 def i : BaseLoadStorePairOffset<opc, V, 1,
3720 (outs regtype:$Rt, regtype:$Rt2),
3721 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3722 Sched<[WriteLD, WriteLDHi]>;
3724 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3725 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3730 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3731 Operand indextype, string asm> {
3732 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3733 def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3734 (ins regtype:$Rt, regtype:$Rt2,
3735 GPR64sp:$Rn, indextype:$offset),
3739 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3740 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3745 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3747 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3752 let Inst{31-30} = opc;
3753 let Inst{29-27} = 0b101;
3755 let Inst{25-23} = 0b011;
3757 let Inst{21-15} = offset;
3758 let Inst{14-10} = Rt2;
3762 let DecoderMethod = "DecodePairLdStInstruction";
3765 let hasSideEffects = 0 in {
3766 let mayStore = 0, mayLoad = 1 in
3767 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3768 Operand indextype, string asm>
3769 : BaseLoadStorePairPreIdx<opc, V, 1,
3770 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3771 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3772 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3774 let mayStore = 1, mayLoad = 0 in
3775 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3776 Operand indextype, string asm>
3777 : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3778 (ins regtype:$Rt, regtype:$Rt2,
3779 GPR64sp:$Rn, indextype:$offset),
3781 Sched<[WriteAdr, WriteSTP]>;
3782 } // hasSideEffects = 0
3786 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3788 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3793 let Inst{31-30} = opc;
3794 let Inst{29-27} = 0b101;
3796 let Inst{25-23} = 0b001;
3798 let Inst{21-15} = offset;
3799 let Inst{14-10} = Rt2;
3803 let DecoderMethod = "DecodePairLdStInstruction";
3806 let hasSideEffects = 0 in {
3807 let mayStore = 0, mayLoad = 1 in
3808 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3809 Operand idxtype, string asm>
3810 : BaseLoadStorePairPostIdx<opc, V, 1,
3811 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3812 (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3813 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3815 let mayStore = 1, mayLoad = 0 in
3816 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3817 Operand idxtype, string asm>
3818 : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3819 (ins regtype:$Rt, regtype:$Rt2,
3820 GPR64sp:$Rn, idxtype:$offset),
3822 Sched<[WriteAdr, WriteSTP]>;
3823 } // hasSideEffects = 0
3827 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3829 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3834 let Inst{31-30} = opc;
3835 let Inst{29-27} = 0b101;
3837 let Inst{25-23} = 0b000;
3839 let Inst{21-15} = offset;
3840 let Inst{14-10} = Rt2;
3844 let DecoderMethod = "DecodePairLdStInstruction";
3847 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3848 Operand indextype, string asm> {
3849 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3850 def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3851 (outs regtype:$Rt, regtype:$Rt2),
3852 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3853 Sched<[WriteLD, WriteLDHi]>;
3856 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3857 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3861 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3862 Operand indextype, string asm> {
3863 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3864 def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3865 (ins regtype:$Rt, regtype:$Rt2,
3866 GPR64sp:$Rn, indextype:$offset),
3870 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3871 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3876 // Load/store exclusive
3879 // True exclusive operations write to and/or read from the system's exclusive
3880 // monitors, which as far as a compiler is concerned can be modelled as a
3881 // random shared memory address. Hence LoadExclusive mayStore.
3883 // Since these instructions have the undefined register bits set to 1 in
3884 // their canonical form, we need a post encoder method to set those bits
3885 // to 1 when encoding these instructions. We do this using the
3886 // fixLoadStoreExclusive function. This function has template parameters:
3888 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3890 // hasRs indicates that the instruction uses the Rs field, so we won't set
3891 // it to 1 (and the same for Rt2). We don't need template parameters for
3892 // the other register fields since Rt and Rn are always used.
3894 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3895 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3896 dag oops, dag iops, string asm, string operands>
3897 : I<oops, iops, asm, operands, "", []> {
3898 let Inst{31-30} = sz;
3899 let Inst{29-24} = 0b001000;
3905 let DecoderMethod = "DecodeExclusiveLdStInstruction";
3908 // Neither Rs nor Rt2 operands.
3909 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3910 dag oops, dag iops, string asm, string operands>
3911 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3914 let Inst{20-16} = 0b11111;
3915 let Unpredictable{20-16} = 0b11111;
3916 let Inst{14-10} = 0b11111;
3917 let Unpredictable{14-10} = 0b11111;
3921 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3924 // Simple load acquires don't set the exclusive monitor
3925 let mayLoad = 1, mayStore = 0 in
3926 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3927 RegisterClass regtype, string asm>
3928 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3929 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3932 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3933 RegisterClass regtype, string asm>
3934 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3935 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3938 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3939 RegisterClass regtype, string asm>
3940 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3941 (outs regtype:$Rt, regtype:$Rt2),
3942 (ins GPR64sp0:$Rn), asm,
3943 "\t$Rt, $Rt2, [$Rn]">,
3944 Sched<[WriteLD, WriteLDHi]> {
3948 let Inst{14-10} = Rt2;
3952 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3955 // Simple store release operations do not check the exclusive monitor.
3956 let mayLoad = 0, mayStore = 1 in
3957 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3958 RegisterClass regtype, string asm>
3959 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3960 (ins regtype:$Rt, GPR64sp0:$Rn),
3961 asm, "\t$Rt, [$Rn]">,
3964 let mayLoad = 1, mayStore = 1 in
3965 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3966 RegisterClass regtype, string asm>
3967 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3968 (ins regtype:$Rt, GPR64sp0:$Rn),
3969 asm, "\t$Ws, $Rt, [$Rn]">,
3974 let Inst{20-16} = Ws;
3978 let Constraints = "@earlyclobber $Ws";
3979 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3982 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3983 RegisterClass regtype, string asm>
3984 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3986 (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3987 asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3993 let Inst{20-16} = Ws;
3994 let Inst{14-10} = Rt2;
3998 let Constraints = "@earlyclobber $Ws";
4001 // Armv8.5-A Memory Tagging Extension
4002 class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4003 string asm_opnds, string cstr, dag oops, dag iops>
4004 : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4008 let Inst{31-24} = 0b11011001;
4009 let Inst{23-22} = opc1;
4011 // Inst{20-12} defined by subclass
4012 let Inst{11-10} = opc2;
4014 // Inst{4-0} defined by subclass
4017 class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4019 : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4020 "$Rn = $wback,@earlyclobber $wback", oops, iops> {
4023 let Inst{20-12} = 0b000000000;
4029 class MemTagLoad<string asm_insn, string asm_opnds>
4030 : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "", (outs GPR64:$Rt),
4031 (ins GPR64sp:$Rn, simm9s16:$offset)> {
4035 let Inst{20-12} = offset;
4041 class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4042 string asm_opnds, string cstr, dag oops, dag iops>
4043 : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4047 let Inst{20-12} = offset;
4048 let Inst{4-0} = 0b11111;
4049 let Unpredictable{4-0} = 0b11111;
4054 multiclass MemTagStore<bits<2> opc1, string insn> {
4056 BaseMemTagStore<opc1, 0b10, insn, "\t[$Rn, $offset]", "",
4057 (outs), (ins GPR64sp:$Rn, simm9s16:$offset)>;
4059 BaseMemTagStore<opc1, 0b11, insn, "\t[$Rn, $offset]!",
4060 "$Rn = $wback,@earlyclobber $wback",
4061 (outs GPR64sp:$wback),
4062 (ins GPR64sp:$Rn, simm9s16:$offset)>;
4064 BaseMemTagStore<opc1, 0b01, insn, "\t[$Rn], $offset",
4065 "$Rn = $wback,@earlyclobber $wback",
4066 (outs GPR64sp:$wback),
4067 (ins GPR64sp:$Rn, simm9s16:$offset)>;
4069 def : InstAlias<insn # "\t[$Rn]",
4070 (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rn, 0)>;
4074 // Exception generation
4077 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4078 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4079 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
4082 let Inst{31-24} = 0b11010100;
4083 let Inst{23-21} = op1;
4084 let Inst{20-5} = imm;
4085 let Inst{4-2} = 0b000;
4090 // UDF : Permanently UNDEFINED instructions. Format: Opc = 0x0000, 16 bit imm.
4092 let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4093 class UDFType<bits<16> opc, string asm>
4094 : I<(outs), (ins uimm16:$imm),
4095 asm, "\t$imm", "", []>,
4098 let Inst{31-16} = opc;
4099 let Inst{15-0} = imm;
4102 let Predicates = [HasFPARMv8] in {
4105 // Floating point to integer conversion
4108 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4109 RegisterClass srcType, RegisterClass dstType,
4110 string asm, list<dag> pattern>
4111 : I<(outs dstType:$Rd), (ins srcType:$Rn),
4112 asm, "\t$Rd, $Rn", "", pattern>,
4113 Sched<[WriteFCvt]> {
4116 let Inst{30-29} = 0b00;
4117 let Inst{28-24} = 0b11110;
4118 let Inst{23-22} = type;
4120 let Inst{20-19} = rmode;
4121 let Inst{18-16} = opcode;
4122 let Inst{15-10} = 0;
4127 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4128 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4129 RegisterClass srcType, RegisterClass dstType,
4130 Operand immType, string asm, list<dag> pattern>
4131 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4132 asm, "\t$Rd, $Rn, $scale", "", pattern>,
4133 Sched<[WriteFCvt]> {
4137 let Inst{30-29} = 0b00;
4138 let Inst{28-24} = 0b11110;
4139 let Inst{23-22} = type;
4141 let Inst{20-19} = rmode;
4142 let Inst{18-16} = opcode;
4143 let Inst{15-10} = scale;
4148 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4149 SDPatternOperator OpN> {
4150 // Unscaled half-precision to 32-bit
4151 def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4152 [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4153 let Inst{31} = 0; // 32-bit GPR flag
4154 let Predicates = [HasFullFP16];
4157 // Unscaled half-precision to 64-bit
4158 def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4159 [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4160 let Inst{31} = 1; // 64-bit GPR flag
4161 let Predicates = [HasFullFP16];
4164 // Unscaled single-precision to 32-bit
4165 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4166 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4167 let Inst{31} = 0; // 32-bit GPR flag
4170 // Unscaled single-precision to 64-bit
4171 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4172 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4173 let Inst{31} = 1; // 64-bit GPR flag
4176 // Unscaled double-precision to 32-bit
4177 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4178 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4179 let Inst{31} = 0; // 32-bit GPR flag
4182 // Unscaled double-precision to 64-bit
4183 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4184 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4185 let Inst{31} = 1; // 64-bit GPR flag
4189 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4190 SDPatternOperator OpN> {
4191 // Scaled half-precision to 32-bit
4192 def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4193 fixedpoint_f16_i32, asm,
4194 [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4195 fixedpoint_f16_i32:$scale)))]> {
4196 let Inst{31} = 0; // 32-bit GPR flag
4198 let Predicates = [HasFullFP16];
4201 // Scaled half-precision to 64-bit
4202 def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4203 fixedpoint_f16_i64, asm,
4204 [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4205 fixedpoint_f16_i64:$scale)))]> {
4206 let Inst{31} = 1; // 64-bit GPR flag
4207 let Predicates = [HasFullFP16];
4210 // Scaled single-precision to 32-bit
4211 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4212 fixedpoint_f32_i32, asm,
4213 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4214 fixedpoint_f32_i32:$scale)))]> {
4215 let Inst{31} = 0; // 32-bit GPR flag
4219 // Scaled single-precision to 64-bit
4220 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4221 fixedpoint_f32_i64, asm,
4222 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4223 fixedpoint_f32_i64:$scale)))]> {
4224 let Inst{31} = 1; // 64-bit GPR flag
4227 // Scaled double-precision to 32-bit
4228 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4229 fixedpoint_f64_i32, asm,
4230 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4231 fixedpoint_f64_i32:$scale)))]> {
4232 let Inst{31} = 0; // 32-bit GPR flag
4236 // Scaled double-precision to 64-bit
4237 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4238 fixedpoint_f64_i64, asm,
4239 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4240 fixedpoint_f64_i64:$scale)))]> {
4241 let Inst{31} = 1; // 64-bit GPR flag
4246 // Integer to floating point conversion
4249 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4250 class BaseIntegerToFP<bit isUnsigned,
4251 RegisterClass srcType, RegisterClass dstType,
4252 Operand immType, string asm, list<dag> pattern>
4253 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4254 asm, "\t$Rd, $Rn, $scale", "", pattern>,
4255 Sched<[WriteFCvt]> {
4259 let Inst{30-24} = 0b0011110;
4260 let Inst{21-17} = 0b00001;
4261 let Inst{16} = isUnsigned;
4262 let Inst{15-10} = scale;
4267 class BaseIntegerToFPUnscaled<bit isUnsigned,
4268 RegisterClass srcType, RegisterClass dstType,
4269 ValueType dvt, string asm, SDNode node>
4270 : I<(outs dstType:$Rd), (ins srcType:$Rn),
4271 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4272 Sched<[WriteFCvt]> {
4276 let Inst{30-24} = 0b0011110;
4277 let Inst{21-17} = 0b10001;
4278 let Inst{16} = isUnsigned;
4279 let Inst{15-10} = 0b000000;
4284 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4286 def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4287 let Inst{31} = 0; // 32-bit GPR flag
4288 let Inst{23-22} = 0b11; // 16-bit FPR flag
4289 let Predicates = [HasFullFP16];
4292 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4293 let Inst{31} = 0; // 32-bit GPR flag
4294 let Inst{23-22} = 0b00; // 32-bit FPR flag
4297 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4298 let Inst{31} = 0; // 32-bit GPR flag
4299 let Inst{23-22} = 0b01; // 64-bit FPR flag
4302 def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4303 let Inst{31} = 1; // 64-bit GPR flag
4304 let Inst{23-22} = 0b11; // 16-bit FPR flag
4305 let Predicates = [HasFullFP16];
4308 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4309 let Inst{31} = 1; // 64-bit GPR flag
4310 let Inst{23-22} = 0b00; // 32-bit FPR flag
4313 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4314 let Inst{31} = 1; // 64-bit GPR flag
4315 let Inst{23-22} = 0b01; // 64-bit FPR flag
4319 def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4321 (fdiv (node GPR32:$Rn),
4322 fixedpoint_f16_i32:$scale))]> {
4323 let Inst{31} = 0; // 32-bit GPR flag
4324 let Inst{23-22} = 0b11; // 16-bit FPR flag
4326 let Predicates = [HasFullFP16];
4329 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4331 (fdiv (node GPR32:$Rn),
4332 fixedpoint_f32_i32:$scale))]> {
4333 let Inst{31} = 0; // 32-bit GPR flag
4334 let Inst{23-22} = 0b00; // 32-bit FPR flag
4338 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4340 (fdiv (node GPR32:$Rn),
4341 fixedpoint_f64_i32:$scale))]> {
4342 let Inst{31} = 0; // 32-bit GPR flag
4343 let Inst{23-22} = 0b01; // 64-bit FPR flag
4347 def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4349 (fdiv (node GPR64:$Rn),
4350 fixedpoint_f16_i64:$scale))]> {
4351 let Inst{31} = 1; // 64-bit GPR flag
4352 let Inst{23-22} = 0b11; // 16-bit FPR flag
4353 let Predicates = [HasFullFP16];
4356 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4358 (fdiv (node GPR64:$Rn),
4359 fixedpoint_f32_i64:$scale))]> {
4360 let Inst{31} = 1; // 64-bit GPR flag
4361 let Inst{23-22} = 0b00; // 32-bit FPR flag
4364 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4366 (fdiv (node GPR64:$Rn),
4367 fixedpoint_f64_i64:$scale))]> {
4368 let Inst{31} = 1; // 64-bit GPR flag
4369 let Inst{23-22} = 0b01; // 64-bit FPR flag
4374 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4377 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4378 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4379 RegisterClass srcType, RegisterClass dstType,
4381 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4382 // We use COPY_TO_REGCLASS for these bitconvert operations.
4383 // copyPhysReg() expands the resultant COPY instructions after
4384 // regalloc is done. This gives greater freedom for the allocator
4385 // and related passes (coalescing, copy propagation, et. al.) to
4386 // be more effective.
4387 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4388 Sched<[WriteFCopy]> {
4391 let Inst{30-24} = 0b0011110;
4393 let Inst{20-19} = rmode;
4394 let Inst{18-16} = opcode;
4395 let Inst{15-10} = 0b000000;
4400 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4401 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4402 RegisterClass srcType, RegisterOperand dstType, string asm,
4404 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4405 "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4406 Sched<[WriteFCopy]> {
4409 let Inst{30-23} = 0b00111101;
4411 let Inst{20-19} = rmode;
4412 let Inst{18-16} = opcode;
4413 let Inst{15-10} = 0b000000;
4417 let DecoderMethod = "DecodeFMOVLaneInstruction";
4420 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4421 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4422 RegisterOperand srcType, RegisterClass dstType, string asm,
4424 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4425 "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4426 Sched<[WriteFCopy]> {
4429 let Inst{30-23} = 0b00111101;
4431 let Inst{20-19} = rmode;
4432 let Inst{18-16} = opcode;
4433 let Inst{15-10} = 0b000000;
4437 let DecoderMethod = "DecodeFMOVLaneInstruction";
4441 multiclass UnscaledConversion<string asm> {
4442 def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4443 let Inst{31} = 0; // 32-bit GPR flag
4444 let Inst{23-22} = 0b11; // 16-bit FPR flag
4445 let Predicates = [HasFullFP16];
4448 def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4449 let Inst{31} = 1; // 64-bit GPR flag
4450 let Inst{23-22} = 0b11; // 16-bit FPR flag
4451 let Predicates = [HasFullFP16];
4454 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4455 let Inst{31} = 0; // 32-bit GPR flag
4456 let Inst{23-22} = 0b00; // 32-bit FPR flag
4459 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4460 let Inst{31} = 1; // 64-bit GPR flag
4461 let Inst{23-22} = 0b01; // 64-bit FPR flag
4464 def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4465 let Inst{31} = 0; // 32-bit GPR flag
4466 let Inst{23-22} = 0b11; // 16-bit FPR flag
4467 let Predicates = [HasFullFP16];
4470 def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4471 let Inst{31} = 1; // 64-bit GPR flag
4472 let Inst{23-22} = 0b11; // 16-bit FPR flag
4473 let Predicates = [HasFullFP16];
4476 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4477 let Inst{31} = 0; // 32-bit GPR flag
4478 let Inst{23-22} = 0b00; // 32-bit FPR flag
4481 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4482 let Inst{31} = 1; // 64-bit GPR flag
4483 let Inst{23-22} = 0b01; // 64-bit FPR flag
4486 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4492 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4500 // Floating point conversion
4503 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4504 RegisterClass srcType, string asm, list<dag> pattern>
4505 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4506 Sched<[WriteFCvt]> {
4509 let Inst{31-24} = 0b00011110;
4510 let Inst{23-22} = type;
4511 let Inst{21-17} = 0b10001;
4512 let Inst{16-15} = opcode;
4513 let Inst{14-10} = 0b10000;
4518 multiclass FPConversion<string asm> {
4519 // Double-precision to Half-precision
4520 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4521 [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4523 // Double-precision to Single-precision
4524 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4525 [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4527 // Half-precision to Double-precision
4528 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4529 [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4531 // Half-precision to Single-precision
4532 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4533 [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4535 // Single-precision to Double-precision
4536 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4537 [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4539 // Single-precision to Half-precision
4540 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4541 [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4545 // Single operand floating point data processing
4548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4549 class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4550 ValueType vt, string asm, SDPatternOperator node>
4551 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4552 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4556 let Inst{31-24} = 0b00011110;
4558 let Inst{20-15} = opcode;
4559 let Inst{14-10} = 0b10000;
4564 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4565 SDPatternOperator node = null_frag> {
4567 def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4568 let Inst{23-22} = 0b11; // 16-bit size flag
4569 let Predicates = [HasFullFP16];
4572 def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4573 let Inst{23-22} = 0b00; // 32-bit size flag
4576 def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4577 let Inst{23-22} = 0b01; // 64-bit size flag
4581 multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4582 SDPatternOperator node = null_frag>{
4584 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4585 let Inst{23-22} = 0b00; // 32-bit registers
4588 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4589 let Inst{23-22} = 0b01; // 64-bit registers
4593 // FRInt[32|64][Z|N] instructions
4594 multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4595 SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4598 // Two operand floating point data processing
4601 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4602 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4603 string asm, list<dag> pat>
4604 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4605 asm, "\t$Rd, $Rn, $Rm", "", pat>,
4610 let Inst{31-24} = 0b00011110;
4612 let Inst{20-16} = Rm;
4613 let Inst{15-12} = opcode;
4614 let Inst{11-10} = 0b10;
4619 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4620 SDPatternOperator node = null_frag> {
4621 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4622 [(set (f16 FPR16:$Rd),
4623 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4624 let Inst{23-22} = 0b11; // 16-bit size flag
4625 let Predicates = [HasFullFP16];
4628 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4629 [(set (f32 FPR32:$Rd),
4630 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4631 let Inst{23-22} = 0b00; // 32-bit size flag
4634 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4635 [(set (f64 FPR64:$Rd),
4636 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4637 let Inst{23-22} = 0b01; // 64-bit size flag
4641 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4642 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4643 [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4644 let Inst{23-22} = 0b11; // 16-bit size flag
4645 let Predicates = [HasFullFP16];
4648 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4649 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4650 let Inst{23-22} = 0b00; // 32-bit size flag
4653 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4654 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4655 let Inst{23-22} = 0b01; // 64-bit size flag
4661 // Three operand floating point data processing
4664 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4665 RegisterClass regtype, string asm, list<dag> pat>
4666 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4667 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4668 Sched<[WriteFMul]> {
4673 let Inst{31-24} = 0b00011111;
4674 let Inst{21} = isNegated;
4675 let Inst{20-16} = Rm;
4676 let Inst{15} = isSub;
4677 let Inst{14-10} = Ra;
4682 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4683 SDPatternOperator node> {
4684 def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4686 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4687 let Inst{23-22} = 0b11; // 16-bit size flag
4688 let Predicates = [HasFullFP16];
4691 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4693 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4694 let Inst{23-22} = 0b00; // 32-bit size flag
4697 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4699 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4700 let Inst{23-22} = 0b01; // 64-bit size flag
4705 // Floating point data comparisons
4708 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4709 class BaseOneOperandFPComparison<bit signalAllNans,
4710 RegisterClass regtype, string asm,
4712 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4713 Sched<[WriteFCmp]> {
4715 let Inst{31-24} = 0b00011110;
4718 let Inst{15-10} = 0b001000;
4720 let Inst{4} = signalAllNans;
4721 let Inst{3-0} = 0b1000;
4723 // Rm should be 0b00000 canonically, but we need to accept any value.
4724 let PostEncoderMethod = "fixOneOperandFPComparison";
4727 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4728 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4729 string asm, list<dag> pat>
4730 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4731 Sched<[WriteFCmp]> {
4734 let Inst{31-24} = 0b00011110;
4736 let Inst{20-16} = Rm;
4737 let Inst{15-10} = 0b001000;
4739 let Inst{4} = signalAllNans;
4740 let Inst{3-0} = 0b0000;
4743 multiclass FPComparison<bit signalAllNans, string asm,
4744 SDPatternOperator OpNode = null_frag> {
4745 let Defs = [NZCV] in {
4746 def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4747 [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4748 let Inst{23-22} = 0b11;
4749 let Predicates = [HasFullFP16];
4752 def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4753 [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4754 let Inst{23-22} = 0b11;
4755 let Predicates = [HasFullFP16];
4758 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4759 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4760 let Inst{23-22} = 0b00;
4763 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4764 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4765 let Inst{23-22} = 0b00;
4768 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4769 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4770 let Inst{23-22} = 0b01;
4773 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4774 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4775 let Inst{23-22} = 0b01;
4781 // Floating point conditional comparisons
4784 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4785 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4786 string mnemonic, list<dag> pat>
4787 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4788 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4789 Sched<[WriteFCmp]> {
4798 let Inst{31-24} = 0b00011110;
4800 let Inst{20-16} = Rm;
4801 let Inst{15-12} = cond;
4802 let Inst{11-10} = 0b01;
4804 let Inst{4} = signalAllNans;
4805 let Inst{3-0} = nzcv;
4808 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4809 SDPatternOperator OpNode = null_frag> {
4810 def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
4811 [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4812 (i32 imm:$cond), NZCV))]> {
4813 let Inst{23-22} = 0b11;
4814 let Predicates = [HasFullFP16];
4817 def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4818 [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4819 (i32 imm:$cond), NZCV))]> {
4820 let Inst{23-22} = 0b00;
4823 def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4824 [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4825 (i32 imm:$cond), NZCV))]> {
4826 let Inst{23-22} = 0b01;
4831 // Floating point conditional select
4834 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4835 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4836 asm, "\t$Rd, $Rn, $Rm, $cond", "",
4838 (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4839 (i32 imm:$cond), NZCV))]>,
4846 let Inst{31-24} = 0b00011110;
4848 let Inst{20-16} = Rm;
4849 let Inst{15-12} = cond;
4850 let Inst{11-10} = 0b11;
4855 multiclass FPCondSelect<string asm> {
4856 let Uses = [NZCV] in {
4857 def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4858 let Inst{23-22} = 0b11;
4859 let Predicates = [HasFullFP16];
4862 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4863 let Inst{23-22} = 0b00;
4866 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4867 let Inst{23-22} = 0b01;
4873 // Floating move immediate
4876 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4877 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4878 [(set regtype:$Rd, fpimmtype:$imm)]>,
4879 Sched<[WriteFImm]> {
4882 let Inst{31-24} = 0b00011110;
4884 let Inst{20-13} = imm;
4885 let Inst{12-5} = 0b10000000;
4889 multiclass FPMoveImmediate<string asm> {
4890 def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4891 let Inst{23-22} = 0b11;
4892 let Predicates = [HasFullFP16];
4895 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4896 let Inst{23-22} = 0b00;
4899 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4900 let Inst{23-22} = 0b01;
4903 } // end of 'let Predicates = [HasFPARMv8]'
4905 //----------------------------------------------------------------------------
4907 //----------------------------------------------------------------------------
4909 let Predicates = [HasNEON] in {
4911 //----------------------------------------------------------------------------
4912 // AdvSIMD three register vector instructions
4913 //----------------------------------------------------------------------------
4915 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4916 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4917 RegisterOperand regtype, string asm, string kind,
4919 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4920 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4921 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4929 let Inst{28-24} = 0b01110;
4930 let Inst{23-21} = size;
4931 let Inst{20-16} = Rm;
4932 let Inst{15-11} = opcode;
4938 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4939 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4940 RegisterOperand regtype, string asm, string kind,
4942 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4943 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4944 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4952 let Inst{28-24} = 0b01110;
4953 let Inst{23-21} = size;
4954 let Inst{20-16} = Rm;
4955 let Inst{15-11} = opcode;
4961 // All operand sizes distinguished in the encoding.
4962 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4963 SDPatternOperator OpNode> {
4964 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4966 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4967 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4969 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4970 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4972 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4973 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4975 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4976 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4978 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4979 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4981 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4982 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4984 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4987 // As above, but D sized elements unsupported.
4988 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4989 SDPatternOperator OpNode> {
4990 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4992 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4993 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4995 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4996 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4998 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4999 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5001 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5002 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5004 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5005 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5007 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5010 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5011 SDPatternOperator OpNode> {
5012 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5014 [(set (v8i8 V64:$dst),
5015 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5016 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5018 [(set (v16i8 V128:$dst),
5019 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5020 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5022 [(set (v4i16 V64:$dst),
5023 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5024 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5026 [(set (v8i16 V128:$dst),
5027 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5028 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5030 [(set (v2i32 V64:$dst),
5031 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5032 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5034 [(set (v4i32 V128:$dst),
5035 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5038 // As above, but only B sized elements supported.
5039 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5040 SDPatternOperator OpNode> {
5041 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5043 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5044 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5046 [(set (v16i8 V128:$Rd),
5047 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5050 // As above, but only floating point elements supported.
5051 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5052 string asm, SDPatternOperator OpNode> {
5053 let Predicates = [HasNEON, HasFullFP16] in {
5054 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5056 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5057 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5059 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5060 } // Predicates = [HasNEON, HasFullFP16]
5061 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5063 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5064 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5066 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5067 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5069 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5072 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5074 SDPatternOperator OpNode> {
5075 let Predicates = [HasNEON, HasFullFP16] in {
5076 def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5078 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5079 def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5081 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5082 } // Predicates = [HasNEON, HasFullFP16]
5083 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5085 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5086 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5088 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5089 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5091 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5094 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5095 string asm, SDPatternOperator OpNode> {
5096 let Predicates = [HasNEON, HasFullFP16] in {
5097 def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5099 [(set (v4f16 V64:$dst),
5100 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5101 def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5103 [(set (v8f16 V128:$dst),
5104 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5105 } // Predicates = [HasNEON, HasFullFP16]
5106 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5108 [(set (v2f32 V64:$dst),
5109 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5110 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5112 [(set (v4f32 V128:$dst),
5113 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5114 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5116 [(set (v2f64 V128:$dst),
5117 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5120 // As above, but D and B sized elements unsupported.
5121 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5122 SDPatternOperator OpNode> {
5123 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5125 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5126 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5128 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5129 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5131 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5132 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5134 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5137 // Logical three vector ops share opcode bits, and only use B sized elements.
5138 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5139 SDPatternOperator OpNode = null_frag> {
5140 def v8i8 : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5142 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5143 def v16i8 : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5145 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5147 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5148 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5149 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5150 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5151 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5152 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5154 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5155 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5156 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5157 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5158 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5159 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5162 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5163 string asm, SDPatternOperator OpNode> {
5164 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5166 [(set (v8i8 V64:$dst),
5167 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5168 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5170 [(set (v16i8 V128:$dst),
5171 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5172 (v16i8 V128:$Rm)))]>;
5174 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5176 (!cast<Instruction>(NAME#"v8i8")
5177 V64:$LHS, V64:$MHS, V64:$RHS)>;
5178 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5180 (!cast<Instruction>(NAME#"v8i8")
5181 V64:$LHS, V64:$MHS, V64:$RHS)>;
5182 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5184 (!cast<Instruction>(NAME#"v8i8")
5185 V64:$LHS, V64:$MHS, V64:$RHS)>;
5187 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5188 (v8i16 V128:$RHS))),
5189 (!cast<Instruction>(NAME#"v16i8")
5190 V128:$LHS, V128:$MHS, V128:$RHS)>;
5191 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5192 (v4i32 V128:$RHS))),
5193 (!cast<Instruction>(NAME#"v16i8")
5194 V128:$LHS, V128:$MHS, V128:$RHS)>;
5195 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5196 (v2i64 V128:$RHS))),
5197 (!cast<Instruction>(NAME#"v16i8")
5198 V128:$LHS, V128:$MHS, V128:$RHS)>;
5201 // ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5202 // bytes from S-sized elements.
5203 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
5204 string kind2, RegisterOperand RegType,
5205 ValueType AccumType, ValueType InputType,
5206 SDPatternOperator OpNode> :
5207 BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
5208 [(set (AccumType RegType:$dst),
5209 (OpNode (AccumType RegType:$Rd),
5210 (InputType RegType:$Rn),
5211 (InputType RegType:$Rm)))]> {
5212 let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5215 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
5216 def v8i8 : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
5217 v2i32, v8i8, OpNode>;
5218 def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
5219 v4i32, v16i8, OpNode>;
5222 // ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5223 // select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5224 // 8H to 4S, when Q=1).
5225 class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5226 string kind2, RegisterOperand RegType,
5227 ValueType AccumType, ValueType InputType,
5228 SDPatternOperator OpNode> :
5229 BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5230 [(set (AccumType RegType:$dst),
5231 (OpNode (AccumType RegType:$Rd),
5232 (InputType RegType:$Rn),
5233 (InputType RegType:$Rm)))]> {
5234 let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5238 multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5239 SDPatternOperator OpNode> {
5240 def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5241 v2f32, v4f16, OpNode>;
5242 def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5243 v4f32, v8f16, OpNode>;
5247 //----------------------------------------------------------------------------
5248 // AdvSIMD two register vector instructions.
5249 //----------------------------------------------------------------------------
5251 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5252 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5253 bits<2> size2, RegisterOperand regtype, string asm,
5254 string dstkind, string srckind, list<dag> pattern>
5255 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5256 "{\t$Rd" # dstkind # ", $Rn" # srckind #
5257 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5264 let Inst{28-24} = 0b01110;
5265 let Inst{23-22} = size;
5267 let Inst{20-19} = size2;
5268 let Inst{18-17} = 0b00;
5269 let Inst{16-12} = opcode;
5270 let Inst{11-10} = 0b10;
5275 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5276 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5277 bits<2> size2, RegisterOperand regtype,
5278 string asm, string dstkind, string srckind,
5280 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5281 "{\t$Rd" # dstkind # ", $Rn" # srckind #
5282 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5289 let Inst{28-24} = 0b01110;
5290 let Inst{23-22} = size;
5292 let Inst{20-19} = size2;
5293 let Inst{18-17} = 0b00;
5294 let Inst{16-12} = opcode;
5295 let Inst{11-10} = 0b10;
5300 // Supports B, H, and S element sizes.
5301 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5302 SDPatternOperator OpNode> {
5303 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5305 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5306 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5307 asm, ".16b", ".16b",
5308 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5309 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5311 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5312 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5314 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5315 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5317 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5318 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5320 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5323 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5324 RegisterOperand regtype, string asm, string dstkind,
5325 string srckind, string amount>
5326 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5327 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5328 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
5334 let Inst{29-24} = 0b101110;
5335 let Inst{23-22} = size;
5336 let Inst{21-10} = 0b100001001110;
5341 multiclass SIMDVectorLShiftLongBySizeBHS {
5342 let hasSideEffects = 0 in {
5343 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5344 "shll", ".8h", ".8b", "8">;
5345 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5346 "shll2", ".8h", ".16b", "8">;
5347 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5348 "shll", ".4s", ".4h", "16">;
5349 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5350 "shll2", ".4s", ".8h", "16">;
5351 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5352 "shll", ".2d", ".2s", "32">;
5353 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5354 "shll2", ".2d", ".4s", "32">;
5358 // Supports all element sizes.
5359 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5360 SDPatternOperator OpNode> {
5361 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5363 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5364 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5366 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5367 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5369 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5370 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5372 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5373 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5375 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5376 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5378 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5381 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5382 SDPatternOperator OpNode> {
5383 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5385 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5387 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5389 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5390 (v16i8 V128:$Rn)))]>;
5391 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5393 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5394 (v4i16 V64:$Rn)))]>;
5395 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5397 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5398 (v8i16 V128:$Rn)))]>;
5399 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5401 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5402 (v2i32 V64:$Rn)))]>;
5403 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5405 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5406 (v4i32 V128:$Rn)))]>;
5409 // Supports all element sizes, except 1xD.
5410 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5411 SDPatternOperator OpNode> {
5412 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5414 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5415 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5416 asm, ".16b", ".16b",
5417 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5418 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5420 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5421 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5423 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5424 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5426 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5427 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5429 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5430 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5432 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5435 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5436 SDPatternOperator OpNode = null_frag> {
5437 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5439 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5440 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5441 asm, ".16b", ".16b",
5442 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5443 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5445 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5446 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5448 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5449 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5451 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5452 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5454 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5455 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5457 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5461 // Supports only B element sizes.
5462 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5463 SDPatternOperator OpNode> {
5464 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5466 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5467 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5468 asm, ".16b", ".16b",
5469 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5473 // Supports only B and H element sizes.
5474 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5475 SDPatternOperator OpNode> {
5476 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5478 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5479 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5480 asm, ".16b", ".16b",
5481 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5482 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5484 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5485 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5487 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5490 // Supports H, S and D element sizes, uses high bit of the size field
5491 // as an extra opcode bit.
5492 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5493 SDPatternOperator OpNode> {
5494 let Predicates = [HasNEON, HasFullFP16] in {
5495 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5497 [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5498 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5500 [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5501 } // Predicates = [HasNEON, HasFullFP16]
5502 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5504 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5505 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5507 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5508 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5510 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5513 // Supports only S and D element sizes
5514 multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5515 SDPatternOperator OpNode = null_frag> {
5517 def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5519 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5520 def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5522 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5523 def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5525 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5528 multiclass FRIntNNTVector<bit U, bit op, string asm,
5529 SDPatternOperator OpNode = null_frag> :
5530 SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5532 // Supports only S element size.
5533 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5534 SDPatternOperator OpNode> {
5535 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5537 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5538 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5540 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5544 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5545 SDPatternOperator OpNode> {
5546 let Predicates = [HasNEON, HasFullFP16] in {
5547 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5549 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5550 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5552 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5553 } // Predicates = [HasNEON, HasFullFP16]
5554 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5556 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5557 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5559 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5560 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5562 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5565 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5566 SDPatternOperator OpNode> {
5567 let Predicates = [HasNEON, HasFullFP16] in {
5568 def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5570 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5571 def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5573 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5574 } // Predicates = [HasNEON, HasFullFP16]
5575 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5577 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5578 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5580 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5581 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5583 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5587 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5588 RegisterOperand inreg, RegisterOperand outreg,
5589 string asm, string outkind, string inkind,
5591 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5592 "{\t$Rd" # outkind # ", $Rn" # inkind #
5593 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5600 let Inst{28-24} = 0b01110;
5601 let Inst{23-22} = size;
5602 let Inst{21-17} = 0b10000;
5603 let Inst{16-12} = opcode;
5604 let Inst{11-10} = 0b10;
5609 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5610 RegisterOperand inreg, RegisterOperand outreg,
5611 string asm, string outkind, string inkind,
5613 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5614 "{\t$Rd" # outkind # ", $Rn" # inkind #
5615 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5622 let Inst{28-24} = 0b01110;
5623 let Inst{23-22} = size;
5624 let Inst{21-17} = 0b10000;
5625 let Inst{16-12} = opcode;
5626 let Inst{11-10} = 0b10;
5631 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5632 SDPatternOperator OpNode> {
5633 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5635 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5636 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5637 asm#"2", ".16b", ".8h", []>;
5638 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5640 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5641 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5642 asm#"2", ".8h", ".4s", []>;
5643 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5645 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5646 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5647 asm#"2", ".4s", ".2d", []>;
5649 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5650 (!cast<Instruction>(NAME # "v16i8")
5651 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5652 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5653 (!cast<Instruction>(NAME # "v8i16")
5654 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5655 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5656 (!cast<Instruction>(NAME # "v4i32")
5657 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5660 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5661 bits<5> opcode, RegisterOperand regtype, string asm,
5662 string kind, string zero, ValueType dty,
5663 ValueType sty, SDNode OpNode>
5664 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5665 "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5666 "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5667 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5674 let Inst{28-24} = 0b01110;
5675 let Inst{23-22} = size;
5677 let Inst{20-19} = size2;
5678 let Inst{18-17} = 0b00;
5679 let Inst{16-12} = opcode;
5680 let Inst{11-10} = 0b10;
5685 // Comparisons support all element sizes, except 1xD.
5686 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5688 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5690 v8i8, v8i8, OpNode>;
5691 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5693 v16i8, v16i8, OpNode>;
5694 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5696 v4i16, v4i16, OpNode>;
5697 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5699 v8i16, v8i16, OpNode>;
5700 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5702 v2i32, v2i32, OpNode>;
5703 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5705 v4i32, v4i32, OpNode>;
5706 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5708 v2i64, v2i64, OpNode>;
5711 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5712 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5713 string asm, SDNode OpNode> {
5715 let Predicates = [HasNEON, HasFullFP16] in {
5716 def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5718 v4i16, v4f16, OpNode>;
5719 def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5721 v8i16, v8f16, OpNode>;
5722 } // Predicates = [HasNEON, HasFullFP16]
5723 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5725 v2i32, v2f32, OpNode>;
5726 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5728 v4i32, v4f32, OpNode>;
5729 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5731 v2i64, v2f64, OpNode>;
5733 let Predicates = [HasNEON, HasFullFP16] in {
5734 def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5735 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5736 def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5737 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5739 def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5740 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5741 def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5742 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5743 def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5744 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5745 let Predicates = [HasNEON, HasFullFP16] in {
5746 def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5747 (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5748 def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5749 (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5751 def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5752 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5753 def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5754 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5755 def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5756 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5759 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5760 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5761 RegisterOperand outtype, RegisterOperand intype,
5762 string asm, string VdTy, string VnTy,
5764 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5765 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5772 let Inst{28-24} = 0b01110;
5773 let Inst{23-22} = size;
5774 let Inst{21-17} = 0b10000;
5775 let Inst{16-12} = opcode;
5776 let Inst{11-10} = 0b10;
5781 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5782 RegisterOperand outtype, RegisterOperand intype,
5783 string asm, string VdTy, string VnTy,
5785 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5786 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5793 let Inst{28-24} = 0b01110;
5794 let Inst{23-22} = size;
5795 let Inst{21-17} = 0b10000;
5796 let Inst{16-12} = opcode;
5797 let Inst{11-10} = 0b10;
5802 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5803 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5804 asm, ".4s", ".4h", []>;
5805 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5806 asm#"2", ".4s", ".8h", []>;
5807 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5808 asm, ".2d", ".2s", []>;
5809 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5810 asm#"2", ".2d", ".4s", []>;
5813 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5814 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5815 asm, ".4h", ".4s", []>;
5816 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5817 asm#"2", ".8h", ".4s", []>;
5818 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5819 asm, ".2s", ".2d", []>;
5820 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5821 asm#"2", ".4s", ".2d", []>;
5824 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5826 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5828 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5829 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5830 asm#"2", ".4s", ".2d", []>;
5832 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5833 (!cast<Instruction>(NAME # "v4f32")
5834 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5837 //----------------------------------------------------------------------------
5838 // AdvSIMD three register different-size vector instructions.
5839 //----------------------------------------------------------------------------
5841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5842 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5843 RegisterOperand outtype, RegisterOperand intype1,
5844 RegisterOperand intype2, string asm,
5845 string outkind, string inkind1, string inkind2,
5847 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5848 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5849 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5855 let Inst{30} = size{0};
5857 let Inst{28-24} = 0b01110;
5858 let Inst{23-22} = size{2-1};
5860 let Inst{20-16} = Rm;
5861 let Inst{15-12} = opcode;
5862 let Inst{11-10} = 0b00;
5867 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5868 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5869 RegisterOperand outtype, RegisterOperand intype1,
5870 RegisterOperand intype2, string asm,
5871 string outkind, string inkind1, string inkind2,
5873 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5874 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5875 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5881 let Inst{30} = size{0};
5883 let Inst{28-24} = 0b01110;
5884 let Inst{23-22} = size{2-1};
5886 let Inst{20-16} = Rm;
5887 let Inst{15-12} = opcode;
5888 let Inst{11-10} = 0b00;
5893 // FIXME: TableGen doesn't know how to deal with expanded types that also
5894 // change the element count (in this case, placing the results in
5895 // the high elements of the result register rather than the low
5896 // elements). Until that's fixed, we can't code-gen those.
5897 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5899 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5901 asm, ".8b", ".8h", ".8h",
5902 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5903 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5905 asm#"2", ".16b", ".8h", ".8h",
5907 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5909 asm, ".4h", ".4s", ".4s",
5910 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5911 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5913 asm#"2", ".8h", ".4s", ".4s",
5915 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5917 asm, ".2s", ".2d", ".2d",
5918 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5919 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5921 asm#"2", ".4s", ".2d", ".2d",
5925 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5926 // a version attached to an instruction.
5927 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5929 (!cast<Instruction>(NAME # "v8i16_v16i8")
5930 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5931 V128:$Rn, V128:$Rm)>;
5932 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5934 (!cast<Instruction>(NAME # "v4i32_v8i16")
5935 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5936 V128:$Rn, V128:$Rm)>;
5937 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5939 (!cast<Instruction>(NAME # "v2i64_v4i32")
5940 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5941 V128:$Rn, V128:$Rm)>;
5944 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5946 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5948 asm, ".8h", ".8b", ".8b",
5949 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5950 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5952 asm#"2", ".8h", ".16b", ".16b", []>;
5953 let Predicates = [HasAES] in {
5954 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5956 asm, ".1q", ".1d", ".1d", []>;
5957 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5959 asm#"2", ".1q", ".2d", ".2d", []>;
5962 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5963 (v8i8 (extract_high_v16i8 V128:$Rm)))),
5964 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5967 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5968 SDPatternOperator OpNode> {
5969 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5971 asm, ".4s", ".4h", ".4h",
5972 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5973 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5975 asm#"2", ".4s", ".8h", ".8h",
5976 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5977 (extract_high_v8i16 V128:$Rm)))]>;
5978 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5980 asm, ".2d", ".2s", ".2s",
5981 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5982 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5984 asm#"2", ".2d", ".4s", ".4s",
5985 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5986 (extract_high_v4i32 V128:$Rm)))]>;
5989 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5990 SDPatternOperator OpNode = null_frag> {
5991 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5993 asm, ".8h", ".8b", ".8b",
5994 [(set (v8i16 V128:$Rd),
5995 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5996 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5998 asm#"2", ".8h", ".16b", ".16b",
5999 [(set (v8i16 V128:$Rd),
6000 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6001 (extract_high_v16i8 V128:$Rm)))))]>;
6002 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6004 asm, ".4s", ".4h", ".4h",
6005 [(set (v4i32 V128:$Rd),
6006 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6007 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6009 asm#"2", ".4s", ".8h", ".8h",
6010 [(set (v4i32 V128:$Rd),
6011 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6012 (extract_high_v8i16 V128:$Rm)))))]>;
6013 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6015 asm, ".2d", ".2s", ".2s",
6016 [(set (v2i64 V128:$Rd),
6017 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6018 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6020 asm#"2", ".2d", ".4s", ".4s",
6021 [(set (v2i64 V128:$Rd),
6022 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6023 (extract_high_v4i32 V128:$Rm)))))]>;
6026 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6028 SDPatternOperator OpNode> {
6029 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6031 asm, ".8h", ".8b", ".8b",
6032 [(set (v8i16 V128:$dst),
6033 (add (v8i16 V128:$Rd),
6034 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6035 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6037 asm#"2", ".8h", ".16b", ".16b",
6038 [(set (v8i16 V128:$dst),
6039 (add (v8i16 V128:$Rd),
6040 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6041 (extract_high_v16i8 V128:$Rm))))))]>;
6042 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6044 asm, ".4s", ".4h", ".4h",
6045 [(set (v4i32 V128:$dst),
6046 (add (v4i32 V128:$Rd),
6047 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6048 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6050 asm#"2", ".4s", ".8h", ".8h",
6051 [(set (v4i32 V128:$dst),
6052 (add (v4i32 V128:$Rd),
6053 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6054 (extract_high_v8i16 V128:$Rm))))))]>;
6055 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6057 asm, ".2d", ".2s", ".2s",
6058 [(set (v2i64 V128:$dst),
6059 (add (v2i64 V128:$Rd),
6060 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6061 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6063 asm#"2", ".2d", ".4s", ".4s",
6064 [(set (v2i64 V128:$dst),
6065 (add (v2i64 V128:$Rd),
6066 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6067 (extract_high_v4i32 V128:$Rm))))))]>;
6070 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6071 SDPatternOperator OpNode = null_frag> {
6072 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6074 asm, ".8h", ".8b", ".8b",
6075 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6076 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6078 asm#"2", ".8h", ".16b", ".16b",
6079 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6080 (extract_high_v16i8 V128:$Rm)))]>;
6081 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6083 asm, ".4s", ".4h", ".4h",
6084 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6085 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6087 asm#"2", ".4s", ".8h", ".8h",
6088 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6089 (extract_high_v8i16 V128:$Rm)))]>;
6090 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6092 asm, ".2d", ".2s", ".2s",
6093 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6094 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6096 asm#"2", ".2d", ".4s", ".4s",
6097 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6098 (extract_high_v4i32 V128:$Rm)))]>;
6101 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6103 SDPatternOperator OpNode> {
6104 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6106 asm, ".8h", ".8b", ".8b",
6107 [(set (v8i16 V128:$dst),
6108 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6109 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6111 asm#"2", ".8h", ".16b", ".16b",
6112 [(set (v8i16 V128:$dst),
6113 (OpNode (v8i16 V128:$Rd),
6114 (extract_high_v16i8 V128:$Rn),
6115 (extract_high_v16i8 V128:$Rm)))]>;
6116 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6118 asm, ".4s", ".4h", ".4h",
6119 [(set (v4i32 V128:$dst),
6120 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6121 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6123 asm#"2", ".4s", ".8h", ".8h",
6124 [(set (v4i32 V128:$dst),
6125 (OpNode (v4i32 V128:$Rd),
6126 (extract_high_v8i16 V128:$Rn),
6127 (extract_high_v8i16 V128:$Rm)))]>;
6128 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6130 asm, ".2d", ".2s", ".2s",
6131 [(set (v2i64 V128:$dst),
6132 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6133 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6135 asm#"2", ".2d", ".4s", ".4s",
6136 [(set (v2i64 V128:$dst),
6137 (OpNode (v2i64 V128:$Rd),
6138 (extract_high_v4i32 V128:$Rn),
6139 (extract_high_v4i32 V128:$Rm)))]>;
6142 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6143 SDPatternOperator Accum> {
6144 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6146 asm, ".4s", ".4h", ".4h",
6147 [(set (v4i32 V128:$dst),
6148 (Accum (v4i32 V128:$Rd),
6149 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6150 (v4i16 V64:$Rm)))))]>;
6151 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6153 asm#"2", ".4s", ".8h", ".8h",
6154 [(set (v4i32 V128:$dst),
6155 (Accum (v4i32 V128:$Rd),
6156 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6157 (extract_high_v8i16 V128:$Rm)))))]>;
6158 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6160 asm, ".2d", ".2s", ".2s",
6161 [(set (v2i64 V128:$dst),
6162 (Accum (v2i64 V128:$Rd),
6163 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6164 (v2i32 V64:$Rm)))))]>;
6165 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6167 asm#"2", ".2d", ".4s", ".4s",
6168 [(set (v2i64 V128:$dst),
6169 (Accum (v2i64 V128:$Rd),
6170 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6171 (extract_high_v4i32 V128:$Rm)))))]>;
6174 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6175 SDPatternOperator OpNode> {
6176 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6178 asm, ".8h", ".8h", ".8b",
6179 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6180 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6182 asm#"2", ".8h", ".8h", ".16b",
6183 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6184 (extract_high_v16i8 V128:$Rm)))]>;
6185 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6187 asm, ".4s", ".4s", ".4h",
6188 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6189 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6191 asm#"2", ".4s", ".4s", ".8h",
6192 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6193 (extract_high_v8i16 V128:$Rm)))]>;
6194 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6196 asm, ".2d", ".2d", ".2s",
6197 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6198 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6200 asm#"2", ".2d", ".2d", ".4s",
6201 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6202 (extract_high_v4i32 V128:$Rm)))]>;
6205 //----------------------------------------------------------------------------
6206 // AdvSIMD bitwise extract from vector
6207 //----------------------------------------------------------------------------
6209 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6210 string asm, string kind>
6211 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6212 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6213 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6214 [(set (vty regtype:$Rd),
6215 (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6222 let Inst{30} = size;
6223 let Inst{29-21} = 0b101110000;
6224 let Inst{20-16} = Rm;
6226 let Inst{14-11} = imm;
6233 multiclass SIMDBitwiseExtract<string asm> {
6234 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6237 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6240 //----------------------------------------------------------------------------
6241 // AdvSIMD zip vector
6242 //----------------------------------------------------------------------------
6244 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6245 string asm, string kind, SDNode OpNode, ValueType valty>
6246 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6247 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6248 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6249 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6255 let Inst{30} = size{0};
6256 let Inst{29-24} = 0b001110;
6257 let Inst{23-22} = size{2-1};
6259 let Inst{20-16} = Rm;
6261 let Inst{14-12} = opc;
6262 let Inst{11-10} = 0b10;
6267 multiclass SIMDZipVector<bits<3>opc, string asm,
6269 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
6270 asm, ".8b", OpNode, v8i8>;
6271 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
6272 asm, ".16b", OpNode, v16i8>;
6273 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
6274 asm, ".4h", OpNode, v4i16>;
6275 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
6276 asm, ".8h", OpNode, v8i16>;
6277 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
6278 asm, ".2s", OpNode, v2i32>;
6279 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
6280 asm, ".4s", OpNode, v4i32>;
6281 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
6282 asm, ".2d", OpNode, v2i64>;
6284 def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6285 (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6286 def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6287 (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6288 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6289 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6290 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6291 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6292 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6293 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6296 //----------------------------------------------------------------------------
6297 // AdvSIMD three register scalar instructions
6298 //----------------------------------------------------------------------------
6300 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6301 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6302 RegisterClass regtype, string asm,
6304 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6305 "\t$Rd, $Rn, $Rm", "", pattern>,
6310 let Inst{31-30} = 0b01;
6312 let Inst{28-24} = 0b11110;
6313 let Inst{23-21} = size;
6314 let Inst{20-16} = Rm;
6315 let Inst{15-11} = opcode;
6321 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6322 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6323 dag oops, dag iops, string asm,
6325 : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6330 let Inst{31-30} = 0b01;
6332 let Inst{28-24} = 0b11110;
6333 let Inst{23-22} = size;
6335 let Inst{20-16} = Rm;
6336 let Inst{15-11} = opcode;
6342 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6343 SDPatternOperator OpNode> {
6344 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6345 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6348 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6349 SDPatternOperator OpNode> {
6350 def v1i64 : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6351 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6352 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6353 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6354 def v1i8 : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6356 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6357 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6358 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6359 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6362 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6363 SDPatternOperator OpNode> {
6364 def v1i32 : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6365 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6366 def v1i16 : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6369 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6370 SDPatternOperator OpNode = null_frag> {
6371 def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6372 (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6374 def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6375 (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6379 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6380 SDPatternOperator OpNode = null_frag> {
6381 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6382 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6383 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6384 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6385 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6386 let Predicates = [HasNEON, HasFullFP16] in {
6387 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6388 [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6389 } // Predicates = [HasNEON, HasFullFP16]
6392 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6393 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6396 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6397 SDPatternOperator OpNode = null_frag> {
6398 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6399 def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6400 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6401 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6402 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6403 let Predicates = [HasNEON, HasFullFP16] in {
6404 def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6406 } // Predicates = [HasNEON, HasFullFP16]
6409 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6410 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6413 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6414 dag oops, dag iops, string asm, string cstr, list<dag> pat>
6415 : I<oops, iops, asm,
6416 "\t$Rd, $Rn, $Rm", cstr, pat>,
6421 let Inst{31-30} = 0b01;
6423 let Inst{28-24} = 0b11110;
6424 let Inst{23-22} = size;
6426 let Inst{20-16} = Rm;
6427 let Inst{15-11} = opcode;
6433 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6434 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6435 SDPatternOperator OpNode = null_frag> {
6436 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6438 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6439 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6441 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6442 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6445 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6446 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6447 SDPatternOperator OpNode = null_frag> {
6448 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6450 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6451 asm, "$Rd = $dst", []>;
6452 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6454 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6456 [(set (i64 FPR64:$dst),
6457 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6460 //----------------------------------------------------------------------------
6461 // AdvSIMD two register scalar instructions
6462 //----------------------------------------------------------------------------
6464 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6465 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6466 RegisterClass regtype, RegisterClass regtype2,
6467 string asm, list<dag> pat>
6468 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6469 "\t$Rd, $Rn", "", pat>,
6473 let Inst{31-30} = 0b01;
6475 let Inst{28-24} = 0b11110;
6476 let Inst{23-22} = size;
6478 let Inst{20-19} = size2;
6479 let Inst{18-17} = 0b00;
6480 let Inst{16-12} = opcode;
6481 let Inst{11-10} = 0b10;
6486 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6487 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6488 RegisterClass regtype, RegisterClass regtype2,
6489 string asm, list<dag> pat>
6490 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6491 "\t$Rd, $Rn", "$Rd = $dst", pat>,
6495 let Inst{31-30} = 0b01;
6497 let Inst{28-24} = 0b11110;
6498 let Inst{23-22} = size;
6499 let Inst{21-17} = 0b10000;
6500 let Inst{16-12} = opcode;
6501 let Inst{11-10} = 0b10;
6507 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6508 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6509 RegisterClass regtype, string asm, string zero>
6510 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6511 "\t$Rd, $Rn, #" # zero, "", []>,
6515 let Inst{31-30} = 0b01;
6517 let Inst{28-24} = 0b11110;
6518 let Inst{23-22} = size;
6520 let Inst{20-19} = size2;
6521 let Inst{18-17} = 0b00;
6522 let Inst{16-12} = opcode;
6523 let Inst{11-10} = 0b10;
6528 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6529 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6530 [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6534 let Inst{31-17} = 0b011111100110000;
6535 let Inst{16-12} = opcode;
6536 let Inst{11-10} = 0b10;
6541 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6542 SDPatternOperator OpNode> {
6543 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6545 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6546 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6549 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6550 SDPatternOperator OpNode> {
6551 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6552 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6553 let Predicates = [HasNEON, HasFullFP16] in {
6554 def v1i16rz : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6557 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6558 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6559 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6560 (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6561 let Predicates = [HasNEON, HasFullFP16] in {
6562 def : InstAlias<asm # "\t$Rd, $Rn, #0",
6563 (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6566 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6567 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6570 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6571 SDPatternOperator OpNode = null_frag> {
6572 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6573 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6575 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6576 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6579 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6580 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6581 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6582 let Predicates = [HasNEON, HasFullFP16] in {
6583 def v1f16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6587 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6588 SDPatternOperator OpNode> {
6589 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6590 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6591 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6592 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6593 let Predicates = [HasNEON, HasFullFP16] in {
6594 def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6595 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6599 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6600 SDPatternOperator OpNode = null_frag> {
6601 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6602 def v1i64 : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6603 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6604 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6605 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6606 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6607 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6610 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6611 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6614 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6616 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6617 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6618 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6619 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6620 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6621 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6622 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6625 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6626 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6631 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6632 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6633 SDPatternOperator OpNode = null_frag> {
6634 def v1i32 : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6635 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6636 def v1i16 : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6637 def v1i8 : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6640 //----------------------------------------------------------------------------
6641 // AdvSIMD scalar pairwise instructions
6642 //----------------------------------------------------------------------------
6644 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6645 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6646 RegisterOperand regtype, RegisterOperand vectype,
6647 string asm, string kind>
6648 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6649 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6653 let Inst{31-30} = 0b01;
6655 let Inst{28-24} = 0b11110;
6656 let Inst{23-22} = size;
6657 let Inst{21-17} = 0b11000;
6658 let Inst{16-12} = opcode;
6659 let Inst{11-10} = 0b10;
6664 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6665 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6669 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6670 let Predicates = [HasNEON, HasFullFP16] in {
6671 def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6674 def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6676 def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6680 //----------------------------------------------------------------------------
6681 // AdvSIMD across lanes instructions
6682 //----------------------------------------------------------------------------
6684 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6685 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6686 RegisterClass regtype, RegisterOperand vectype,
6687 string asm, string kind, list<dag> pattern>
6688 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6689 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6696 let Inst{28-24} = 0b01110;
6697 let Inst{23-22} = size;
6698 let Inst{21-17} = 0b11000;
6699 let Inst{16-12} = opcode;
6700 let Inst{11-10} = 0b10;
6705 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6707 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
6709 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
6711 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6713 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6715 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6719 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6720 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6722 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6724 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6726 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6728 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6732 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6734 let Predicates = [HasNEON, HasFullFP16] in {
6735 def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6737 [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6738 def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6740 [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6741 } // Predicates = [HasNEON, HasFullFP16]
6742 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6744 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6747 //----------------------------------------------------------------------------
6748 // AdvSIMD INS/DUP instructions
6749 //----------------------------------------------------------------------------
6751 // FIXME: There has got to be a better way to factor these. ugh.
6753 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6754 string operands, string constraints, list<dag> pattern>
6755 : I<outs, ins, asm, operands, constraints, pattern>,
6762 let Inst{28-21} = 0b01110000;
6769 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6770 RegisterOperand vecreg, RegisterClass regtype>
6771 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6772 "{\t$Rd" # size # ", $Rn" #
6773 "|" # size # "\t$Rd, $Rn}", "",
6774 [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6775 let Inst{20-16} = imm5;
6776 let Inst{14-11} = 0b0001;
6779 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6780 ValueType vectype, ValueType insreg,
6781 RegisterOperand vecreg, Operand idxtype,
6782 ValueType elttype, SDNode OpNode>
6783 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6784 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6785 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6786 [(set (vectype vecreg:$Rd),
6787 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6788 let Inst{14-11} = 0b0000;
6791 class SIMDDup64FromElement
6792 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6793 VectorIndexD, i64, AArch64duplane64> {
6796 let Inst{19-16} = 0b1000;
6799 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6800 RegisterOperand vecreg>
6801 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6802 VectorIndexS, i64, AArch64duplane32> {
6804 let Inst{20-19} = idx;
6805 let Inst{18-16} = 0b100;
6808 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6809 RegisterOperand vecreg>
6810 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6811 VectorIndexH, i64, AArch64duplane16> {
6813 let Inst{20-18} = idx;
6814 let Inst{17-16} = 0b10;
6817 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6818 RegisterOperand vecreg>
6819 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6820 VectorIndexB, i64, AArch64duplane8> {
6822 let Inst{20-17} = idx;
6826 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6827 Operand idxtype, string asm, list<dag> pattern>
6828 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6829 "{\t$Rd, $Rn" # size # "$idx" #
6830 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6831 let Inst{14-11} = imm4;
6834 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6836 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6837 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6839 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6840 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6842 class SIMDMovAlias<string asm, string size, Instruction inst,
6843 RegisterClass regtype, Operand idxtype>
6844 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6845 "|" # size # "\t$dst, $src$idx}",
6846 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6849 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6851 let Inst{20-17} = idx;
6854 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6856 let Inst{20-17} = idx;
6859 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6861 let Inst{20-18} = idx;
6862 let Inst{17-16} = 0b10;
6864 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6866 let Inst{20-18} = idx;
6867 let Inst{17-16} = 0b10;
6869 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6871 let Inst{20-19} = idx;
6872 let Inst{18-16} = 0b100;
6877 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6879 let Inst{20-17} = idx;
6882 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6884 let Inst{20-18} = idx;
6885 let Inst{17-16} = 0b10;
6887 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6889 let Inst{20-19} = idx;
6890 let Inst{18-16} = 0b100;
6892 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6895 let Inst{19-16} = 0b1000;
6897 def : SIMDMovAlias<"mov", ".s",
6898 !cast<Instruction>(NAME#"vi32"),
6899 GPR32, VectorIndexS>;
6900 def : SIMDMovAlias<"mov", ".d",
6901 !cast<Instruction>(NAME#"vi64"),
6902 GPR64, VectorIndexD>;
6905 class SIMDInsFromMain<string size, ValueType vectype,
6906 RegisterClass regtype, Operand idxtype>
6907 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6908 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6909 "{\t$Rd" # size # "$idx, $Rn" #
6910 "|" # size # "\t$Rd$idx, $Rn}",
6913 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6914 let Inst{14-11} = 0b0011;
6917 class SIMDInsFromElement<string size, ValueType vectype,
6918 ValueType elttype, Operand idxtype>
6919 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6920 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6921 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6922 "|" # size # "\t$Rd$idx, $Rn$idx2}",
6927 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6930 class SIMDInsMainMovAlias<string size, Instruction inst,
6931 RegisterClass regtype, Operand idxtype>
6932 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6933 "|" # size #"\t$dst$idx, $src}",
6934 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6935 class SIMDInsElementMovAlias<string size, Instruction inst,
6937 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6938 # "|" # size #"\t$dst$idx, $src$idx2}",
6939 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6942 multiclass SIMDIns {
6943 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6945 let Inst{20-17} = idx;
6948 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6950 let Inst{20-18} = idx;
6951 let Inst{17-16} = 0b10;
6953 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6955 let Inst{20-19} = idx;
6956 let Inst{18-16} = 0b100;
6958 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6961 let Inst{19-16} = 0b1000;
6964 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6967 let Inst{20-17} = idx;
6969 let Inst{14-11} = idx2;
6971 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6974 let Inst{20-18} = idx;
6975 let Inst{17-16} = 0b10;
6976 let Inst{14-12} = idx2;
6979 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6982 let Inst{20-19} = idx;
6983 let Inst{18-16} = 0b100;
6984 let Inst{14-13} = idx2;
6985 let Inst{12-11} = {?,?};
6987 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6991 let Inst{19-16} = 0b1000;
6992 let Inst{14} = idx2;
6993 let Inst{13-11} = {?,?,?};
6996 // For all forms of the INS instruction, the "mov" mnemonic is the
6997 // preferred alias. Why they didn't just call the instruction "mov" in
6998 // the first place is a very good question indeed...
6999 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7000 GPR32, VectorIndexB>;
7001 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7002 GPR32, VectorIndexH>;
7003 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7004 GPR32, VectorIndexS>;
7005 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7006 GPR64, VectorIndexD>;
7008 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7010 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7012 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7014 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7018 //----------------------------------------------------------------------------
7020 //----------------------------------------------------------------------------
7022 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7023 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7024 RegisterOperand listtype, string asm, string kind>
7025 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7026 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7033 let Inst{29-21} = 0b001110000;
7034 let Inst{20-16} = Vm;
7036 let Inst{14-13} = len;
7038 let Inst{11-10} = 0b00;
7043 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7044 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7045 RegisterOperand listtype, string asm, string kind>
7046 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7047 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7054 let Inst{29-21} = 0b001110000;
7055 let Inst{20-16} = Vm;
7057 let Inst{14-13} = len;
7059 let Inst{11-10} = 0b00;
7064 class SIMDTableLookupAlias<string asm, Instruction inst,
7065 RegisterOperand vectype, RegisterOperand listtype>
7066 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7067 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7069 multiclass SIMDTableLookup<bit op, string asm> {
7070 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7072 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7074 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7076 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7078 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7080 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7082 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7084 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7087 def : SIMDTableLookupAlias<asm # ".8b",
7088 !cast<Instruction>(NAME#"v8i8One"),
7089 V64, VecListOne128>;
7090 def : SIMDTableLookupAlias<asm # ".8b",
7091 !cast<Instruction>(NAME#"v8i8Two"),
7092 V64, VecListTwo128>;
7093 def : SIMDTableLookupAlias<asm # ".8b",
7094 !cast<Instruction>(NAME#"v8i8Three"),
7095 V64, VecListThree128>;
7096 def : SIMDTableLookupAlias<asm # ".8b",
7097 !cast<Instruction>(NAME#"v8i8Four"),
7098 V64, VecListFour128>;
7099 def : SIMDTableLookupAlias<asm # ".16b",
7100 !cast<Instruction>(NAME#"v16i8One"),
7101 V128, VecListOne128>;
7102 def : SIMDTableLookupAlias<asm # ".16b",
7103 !cast<Instruction>(NAME#"v16i8Two"),
7104 V128, VecListTwo128>;
7105 def : SIMDTableLookupAlias<asm # ".16b",
7106 !cast<Instruction>(NAME#"v16i8Three"),
7107 V128, VecListThree128>;
7108 def : SIMDTableLookupAlias<asm # ".16b",
7109 !cast<Instruction>(NAME#"v16i8Four"),
7110 V128, VecListFour128>;
7113 multiclass SIMDTableLookupTied<bit op, string asm> {
7114 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7116 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7118 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7120 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7122 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7124 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7126 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7128 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7131 def : SIMDTableLookupAlias<asm # ".8b",
7132 !cast<Instruction>(NAME#"v8i8One"),
7133 V64, VecListOne128>;
7134 def : SIMDTableLookupAlias<asm # ".8b",
7135 !cast<Instruction>(NAME#"v8i8Two"),
7136 V64, VecListTwo128>;
7137 def : SIMDTableLookupAlias<asm # ".8b",
7138 !cast<Instruction>(NAME#"v8i8Three"),
7139 V64, VecListThree128>;
7140 def : SIMDTableLookupAlias<asm # ".8b",
7141 !cast<Instruction>(NAME#"v8i8Four"),
7142 V64, VecListFour128>;
7143 def : SIMDTableLookupAlias<asm # ".16b",
7144 !cast<Instruction>(NAME#"v16i8One"),
7145 V128, VecListOne128>;
7146 def : SIMDTableLookupAlias<asm # ".16b",
7147 !cast<Instruction>(NAME#"v16i8Two"),
7148 V128, VecListTwo128>;
7149 def : SIMDTableLookupAlias<asm # ".16b",
7150 !cast<Instruction>(NAME#"v16i8Three"),
7151 V128, VecListThree128>;
7152 def : SIMDTableLookupAlias<asm # ".16b",
7153 !cast<Instruction>(NAME#"v16i8Four"),
7154 V128, VecListFour128>;
7158 //----------------------------------------------------------------------------
7159 // AdvSIMD scalar CPY
7160 //----------------------------------------------------------------------------
7161 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7162 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7163 string kind, Operand idxtype>
7164 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7165 "{\t$dst, $src" # kind # "$idx" #
7166 "|\t$dst, $src$idx}", "", []>,
7170 let Inst{31-21} = 0b01011110000;
7171 let Inst{15-10} = 0b000001;
7172 let Inst{9-5} = src;
7173 let Inst{4-0} = dst;
7176 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7177 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7178 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
7179 # "|\t$dst, $src$index}",
7180 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7183 multiclass SIMDScalarCPY<string asm> {
7184 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
7186 let Inst{20-17} = idx;
7189 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7191 let Inst{20-18} = idx;
7192 let Inst{17-16} = 0b10;
7194 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7196 let Inst{20-19} = idx;
7197 let Inst{18-16} = 0b100;
7199 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7202 let Inst{19-16} = 0b1000;
7205 def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7206 VectorIndexD:$idx)))),
7207 (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7209 // 'DUP' mnemonic aliases.
7210 def : SIMDScalarCPYAlias<"dup", ".b",
7211 !cast<Instruction>(NAME#"i8"),
7212 FPR8, V128, VectorIndexB>;
7213 def : SIMDScalarCPYAlias<"dup", ".h",
7214 !cast<Instruction>(NAME#"i16"),
7215 FPR16, V128, VectorIndexH>;
7216 def : SIMDScalarCPYAlias<"dup", ".s",
7217 !cast<Instruction>(NAME#"i32"),
7218 FPR32, V128, VectorIndexS>;
7219 def : SIMDScalarCPYAlias<"dup", ".d",
7220 !cast<Instruction>(NAME#"i64"),
7221 FPR64, V128, VectorIndexD>;
7224 //----------------------------------------------------------------------------
7225 // AdvSIMD modified immediate instructions
7226 //----------------------------------------------------------------------------
7228 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7229 string asm, string op_string,
7230 string cstr, list<dag> pattern>
7231 : I<oops, iops, asm, op_string, cstr, pattern>,
7238 let Inst{28-19} = 0b0111100000;
7239 let Inst{18-16} = imm8{7-5};
7242 let Inst{9-5} = imm8{4-0};
7246 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7247 Operand immtype, dag opt_shift_iop,
7248 string opt_shift, string asm, string kind,
7250 : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7251 !con((ins immtype:$imm8), opt_shift_iop), asm,
7252 "{\t$Rd" # kind # ", $imm8" # opt_shift #
7253 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7255 let DecoderMethod = "DecodeModImmInstruction";
7258 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7259 Operand immtype, dag opt_shift_iop,
7260 string opt_shift, string asm, string kind,
7262 : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7263 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7264 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7265 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7266 "$Rd = $dst", pattern> {
7267 let DecoderMethod = "DecodeModImmTiedInstruction";
7270 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7271 RegisterOperand vectype, string asm,
7272 string kind, list<dag> pattern>
7273 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7274 (ins logical_vec_shift:$shift),
7275 "$shift", asm, kind, pattern> {
7277 let Inst{15} = b15_b12{1};
7278 let Inst{14-13} = shift;
7279 let Inst{12} = b15_b12{0};
7282 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7283 RegisterOperand vectype, string asm,
7284 string kind, list<dag> pattern>
7285 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7286 (ins logical_vec_shift:$shift),
7287 "$shift", asm, kind, pattern> {
7289 let Inst{15} = b15_b12{1};
7290 let Inst{14-13} = shift;
7291 let Inst{12} = b15_b12{0};
7295 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7296 RegisterOperand vectype, string asm,
7297 string kind, list<dag> pattern>
7298 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7299 (ins logical_vec_hw_shift:$shift),
7300 "$shift", asm, kind, pattern> {
7302 let Inst{15} = b15_b12{1};
7304 let Inst{13} = shift{0};
7305 let Inst{12} = b15_b12{0};
7308 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7309 RegisterOperand vectype, string asm,
7310 string kind, list<dag> pattern>
7311 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7312 (ins logical_vec_hw_shift:$shift),
7313 "$shift", asm, kind, pattern> {
7315 let Inst{15} = b15_b12{1};
7317 let Inst{13} = shift{0};
7318 let Inst{12} = b15_b12{0};
7321 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7323 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7325 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7328 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7330 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7334 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7335 bits<2> w_cmode, string asm,
7337 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7339 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7341 (i32 imm:$shift)))]>;
7342 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7344 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7346 (i32 imm:$shift)))]>;
7348 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7350 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7352 (i32 imm:$shift)))]>;
7353 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7355 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7357 (i32 imm:$shift)))]>;
7360 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7361 RegisterOperand vectype, string asm,
7362 string kind, list<dag> pattern>
7363 : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7364 (ins move_vec_shift:$shift),
7365 "$shift", asm, kind, pattern> {
7367 let Inst{15-13} = cmode{3-1};
7368 let Inst{12} = shift;
7371 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7372 RegisterOperand vectype,
7373 Operand imm_type, string asm,
7374 string kind, list<dag> pattern>
7375 : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7376 asm, kind, pattern> {
7377 let Inst{15-12} = cmode;
7380 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7382 : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7383 "\t$Rd, $imm8", "", pattern> {
7384 let Inst{15-12} = cmode;
7385 let DecoderMethod = "DecodeModImmInstruction";
7388 //----------------------------------------------------------------------------
7389 // AdvSIMD indexed element
7390 //----------------------------------------------------------------------------
7392 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7393 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7394 RegisterOperand dst_reg, RegisterOperand lhs_reg,
7395 RegisterOperand rhs_reg, Operand vec_idx, string asm,
7396 string apple_kind, string dst_kind, string lhs_kind,
7397 string rhs_kind, list<dag> pattern>
7398 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7400 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7401 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7410 let Inst{28} = Scalar;
7411 let Inst{27-24} = 0b1111;
7412 let Inst{23-22} = size;
7413 // Bit 21 must be set by the derived class.
7414 let Inst{20-16} = Rm;
7415 let Inst{15-12} = opc;
7416 // Bit 11 must be set by the derived class.
7422 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7423 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7424 RegisterOperand dst_reg, RegisterOperand lhs_reg,
7425 RegisterOperand rhs_reg, Operand vec_idx, string asm,
7426 string apple_kind, string dst_kind, string lhs_kind,
7427 string rhs_kind, list<dag> pattern>
7428 : I<(outs dst_reg:$dst),
7429 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7430 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7431 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7440 let Inst{28} = Scalar;
7441 let Inst{27-24} = 0b1111;
7442 let Inst{23-22} = size;
7443 // Bit 21 must be set by the derived class.
7444 let Inst{20-16} = Rm;
7445 let Inst{15-12} = opc;
7446 // Bit 11 must be set by the derived class.
7452 // ARMv8.2-A Dot Product Instructions (Indexed)
7453 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7454 string lhs_kind, string rhs_kind,
7455 RegisterOperand RegType,
7456 ValueType AccumType, ValueType InputType,
7457 SDPatternOperator OpNode> :
7458 BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7459 VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7460 [(set (AccumType RegType:$dst),
7461 (AccumType (OpNode (AccumType RegType:$Rd),
7462 (InputType RegType:$Rn),
7463 (InputType (bitconvert (AccumType
7464 (AArch64duplane32 (v4i32 V128:$Rm),
7465 VectorIndexS:$idx)))))))]> {
7467 let Inst{21} = idx{0}; // L
7468 let Inst{11} = idx{1}; // H
7471 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7472 SDPatternOperator OpNode> {
7473 def v8i8 : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b",
7474 V64, v2i32, v8i8, OpNode>;
7475 def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b",
7476 V128, v4i32, v16i8, OpNode>;
7479 // ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7480 class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7481 string dst_kind, string lhs_kind,
7482 string rhs_kind, RegisterOperand RegType,
7483 ValueType AccumType, ValueType InputType,
7484 SDPatternOperator OpNode> :
7485 BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7486 VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7487 [(set (AccumType RegType:$dst),
7488 (AccumType (OpNode (AccumType RegType:$Rd),
7489 (InputType RegType:$Rn),
7490 (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7491 VectorIndexH:$idx)))))]> {
7494 let Inst{11} = idx{2}; // H
7495 let Inst{21} = idx{1}; // L
7496 let Inst{20} = idx{0}; // M
7499 multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
7500 SDPatternOperator OpNode> {
7501 def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
7502 V64, v2f32, v4f16, OpNode>;
7503 def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
7504 V128, v4f32, v8f16, OpNode>;
7507 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7508 SDPatternOperator OpNode> {
7509 let Predicates = [HasNEON, HasFullFP16] in {
7510 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7512 V128_lo, VectorIndexH,
7513 asm, ".4h", ".4h", ".4h", ".h",
7514 [(set (v4f16 V64:$Rd),
7515 (OpNode (v4f16 V64:$Rn),
7516 (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7518 let Inst{11} = idx{2};
7519 let Inst{21} = idx{1};
7520 let Inst{20} = idx{0};
7523 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7525 V128_lo, VectorIndexH,
7526 asm, ".8h", ".8h", ".8h", ".h",
7527 [(set (v8f16 V128:$Rd),
7528 (OpNode (v8f16 V128:$Rn),
7529 (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7531 let Inst{11} = idx{2};
7532 let Inst{21} = idx{1};
7533 let Inst{20} = idx{0};
7535 } // Predicates = [HasNEON, HasFullFP16]
7537 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7540 asm, ".2s", ".2s", ".2s", ".s",
7541 [(set (v2f32 V64:$Rd),
7542 (OpNode (v2f32 V64:$Rn),
7543 (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7545 let Inst{11} = idx{1};
7546 let Inst{21} = idx{0};
7549 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7552 asm, ".4s", ".4s", ".4s", ".s",
7553 [(set (v4f32 V128:$Rd),
7554 (OpNode (v4f32 V128:$Rn),
7555 (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7557 let Inst{11} = idx{1};
7558 let Inst{21} = idx{0};
7561 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7564 asm, ".2d", ".2d", ".2d", ".d",
7565 [(set (v2f64 V128:$Rd),
7566 (OpNode (v2f64 V128:$Rn),
7567 (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7569 let Inst{11} = idx{0};
7573 let Predicates = [HasNEON, HasFullFP16] in {
7574 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7575 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7576 asm, ".h", "", "", ".h",
7577 [(set (f16 FPR16Op:$Rd),
7578 (OpNode (f16 FPR16Op:$Rn),
7579 (f16 (vector_extract (v8f16 V128_lo:$Rm),
7580 VectorIndexH:$idx))))]> {
7582 let Inst{11} = idx{2};
7583 let Inst{21} = idx{1};
7584 let Inst{20} = idx{0};
7586 } // Predicates = [HasNEON, HasFullFP16]
7588 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7589 FPR32Op, FPR32Op, V128, VectorIndexS,
7590 asm, ".s", "", "", ".s",
7591 [(set (f32 FPR32Op:$Rd),
7592 (OpNode (f32 FPR32Op:$Rn),
7593 (f32 (vector_extract (v4f32 V128:$Rm),
7594 VectorIndexS:$idx))))]> {
7596 let Inst{11} = idx{1};
7597 let Inst{21} = idx{0};
7600 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7601 FPR64Op, FPR64Op, V128, VectorIndexD,
7602 asm, ".d", "", "", ".d",
7603 [(set (f64 FPR64Op:$Rd),
7604 (OpNode (f64 FPR64Op:$Rn),
7605 (f64 (vector_extract (v2f64 V128:$Rm),
7606 VectorIndexD:$idx))))]> {
7608 let Inst{11} = idx{0};
7613 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7614 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7615 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7616 (AArch64duplane32 (v4f32 V128:$Rm),
7617 VectorIndexS:$idx))),
7618 (!cast<Instruction>(INST # v2i32_indexed)
7619 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7620 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7621 (AArch64dup (f32 FPR32Op:$Rm)))),
7622 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7623 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7626 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7627 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7628 (AArch64duplane32 (v4f32 V128:$Rm),
7629 VectorIndexS:$idx))),
7630 (!cast<Instruction>(INST # "v4i32_indexed")
7631 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7632 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7633 (AArch64dup (f32 FPR32Op:$Rm)))),
7634 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7635 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7637 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7638 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7639 (AArch64duplane64 (v2f64 V128:$Rm),
7640 VectorIndexD:$idx))),
7641 (!cast<Instruction>(INST # "v2i64_indexed")
7642 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7643 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7644 (AArch64dup (f64 FPR64Op:$Rm)))),
7645 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7646 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7648 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7649 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7650 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7651 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7652 V128:$Rm, VectorIndexS:$idx)>;
7653 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7654 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7655 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7656 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7658 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7659 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7660 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7661 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7662 V128:$Rm, VectorIndexD:$idx)>;
7665 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7666 let Predicates = [HasNEON, HasFullFP16] in {
7667 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7668 V128_lo, VectorIndexH,
7669 asm, ".4h", ".4h", ".4h", ".h", []> {
7671 let Inst{11} = idx{2};
7672 let Inst{21} = idx{1};
7673 let Inst{20} = idx{0};
7676 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7678 V128_lo, VectorIndexH,
7679 asm, ".8h", ".8h", ".8h", ".h", []> {
7681 let Inst{11} = idx{2};
7682 let Inst{21} = idx{1};
7683 let Inst{20} = idx{0};
7685 } // Predicates = [HasNEON, HasFullFP16]
7687 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7689 asm, ".2s", ".2s", ".2s", ".s", []> {
7691 let Inst{11} = idx{1};
7692 let Inst{21} = idx{0};
7695 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7698 asm, ".4s", ".4s", ".4s", ".s", []> {
7700 let Inst{11} = idx{1};
7701 let Inst{21} = idx{0};
7704 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7707 asm, ".2d", ".2d", ".2d", ".d", []> {
7709 let Inst{11} = idx{0};
7713 let Predicates = [HasNEON, HasFullFP16] in {
7714 def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7715 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7716 asm, ".h", "", "", ".h", []> {
7718 let Inst{11} = idx{2};
7719 let Inst{21} = idx{1};
7720 let Inst{20} = idx{0};
7722 } // Predicates = [HasNEON, HasFullFP16]
7724 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7725 FPR32Op, FPR32Op, V128, VectorIndexS,
7726 asm, ".s", "", "", ".s", []> {
7728 let Inst{11} = idx{1};
7729 let Inst{21} = idx{0};
7732 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7733 FPR64Op, FPR64Op, V128, VectorIndexD,
7734 asm, ".d", "", "", ".d", []> {
7736 let Inst{11} = idx{0};
7741 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7742 SDPatternOperator OpNode> {
7743 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7744 V128_lo, VectorIndexH,
7745 asm, ".4h", ".4h", ".4h", ".h",
7746 [(set (v4i16 V64:$Rd),
7747 (OpNode (v4i16 V64:$Rn),
7748 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7750 let Inst{11} = idx{2};
7751 let Inst{21} = idx{1};
7752 let Inst{20} = idx{0};
7755 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7757 V128_lo, VectorIndexH,
7758 asm, ".8h", ".8h", ".8h", ".h",
7759 [(set (v8i16 V128:$Rd),
7760 (OpNode (v8i16 V128:$Rn),
7761 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7763 let Inst{11} = idx{2};
7764 let Inst{21} = idx{1};
7765 let Inst{20} = idx{0};
7768 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7771 asm, ".2s", ".2s", ".2s", ".s",
7772 [(set (v2i32 V64:$Rd),
7773 (OpNode (v2i32 V64:$Rn),
7774 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7776 let Inst{11} = idx{1};
7777 let Inst{21} = idx{0};
7780 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7783 asm, ".4s", ".4s", ".4s", ".s",
7784 [(set (v4i32 V128:$Rd),
7785 (OpNode (v4i32 V128:$Rn),
7786 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7788 let Inst{11} = idx{1};
7789 let Inst{21} = idx{0};
7792 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7793 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7794 asm, ".h", "", "", ".h", []> {
7796 let Inst{11} = idx{2};
7797 let Inst{21} = idx{1};
7798 let Inst{20} = idx{0};
7801 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7802 FPR32Op, FPR32Op, V128, VectorIndexS,
7803 asm, ".s", "", "", ".s",
7804 [(set (i32 FPR32Op:$Rd),
7805 (OpNode FPR32Op:$Rn,
7806 (i32 (vector_extract (v4i32 V128:$Rm),
7807 VectorIndexS:$idx))))]> {
7809 let Inst{11} = idx{1};
7810 let Inst{21} = idx{0};
7814 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7815 SDPatternOperator OpNode> {
7816 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7818 V128_lo, VectorIndexH,
7819 asm, ".4h", ".4h", ".4h", ".h",
7820 [(set (v4i16 V64:$Rd),
7821 (OpNode (v4i16 V64:$Rn),
7822 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7824 let Inst{11} = idx{2};
7825 let Inst{21} = idx{1};
7826 let Inst{20} = idx{0};
7829 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7831 V128_lo, VectorIndexH,
7832 asm, ".8h", ".8h", ".8h", ".h",
7833 [(set (v8i16 V128:$Rd),
7834 (OpNode (v8i16 V128:$Rn),
7835 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7837 let Inst{11} = idx{2};
7838 let Inst{21} = idx{1};
7839 let Inst{20} = idx{0};
7842 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7845 asm, ".2s", ".2s", ".2s", ".s",
7846 [(set (v2i32 V64:$Rd),
7847 (OpNode (v2i32 V64:$Rn),
7848 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7850 let Inst{11} = idx{1};
7851 let Inst{21} = idx{0};
7854 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7857 asm, ".4s", ".4s", ".4s", ".s",
7858 [(set (v4i32 V128:$Rd),
7859 (OpNode (v4i32 V128:$Rn),
7860 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7862 let Inst{11} = idx{1};
7863 let Inst{21} = idx{0};
7867 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7868 SDPatternOperator OpNode> {
7869 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7870 V128_lo, VectorIndexH,
7871 asm, ".4h", ".4h", ".4h", ".h",
7872 [(set (v4i16 V64:$dst),
7873 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7874 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7876 let Inst{11} = idx{2};
7877 let Inst{21} = idx{1};
7878 let Inst{20} = idx{0};
7881 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7883 V128_lo, VectorIndexH,
7884 asm, ".8h", ".8h", ".8h", ".h",
7885 [(set (v8i16 V128:$dst),
7886 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7887 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7889 let Inst{11} = idx{2};
7890 let Inst{21} = idx{1};
7891 let Inst{20} = idx{0};
7894 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7897 asm, ".2s", ".2s", ".2s", ".s",
7898 [(set (v2i32 V64:$dst),
7899 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7900 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7902 let Inst{11} = idx{1};
7903 let Inst{21} = idx{0};
7906 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7909 asm, ".4s", ".4s", ".4s", ".s",
7910 [(set (v4i32 V128:$dst),
7911 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7912 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7914 let Inst{11} = idx{1};
7915 let Inst{21} = idx{0};
7919 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7920 SDPatternOperator OpNode> {
7921 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7923 V128_lo, VectorIndexH,
7924 asm, ".4s", ".4s", ".4h", ".h",
7925 [(set (v4i32 V128:$Rd),
7926 (OpNode (v4i16 V64:$Rn),
7927 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7929 let Inst{11} = idx{2};
7930 let Inst{21} = idx{1};
7931 let Inst{20} = idx{0};
7934 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7936 V128_lo, VectorIndexH,
7937 asm#"2", ".4s", ".4s", ".8h", ".h",
7938 [(set (v4i32 V128:$Rd),
7939 (OpNode (extract_high_v8i16 V128:$Rn),
7940 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7941 VectorIndexH:$idx))))]> {
7944 let Inst{11} = idx{2};
7945 let Inst{21} = idx{1};
7946 let Inst{20} = idx{0};
7949 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7952 asm, ".2d", ".2d", ".2s", ".s",
7953 [(set (v2i64 V128:$Rd),
7954 (OpNode (v2i32 V64:$Rn),
7955 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7957 let Inst{11} = idx{1};
7958 let Inst{21} = idx{0};
7961 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7964 asm#"2", ".2d", ".2d", ".4s", ".s",
7965 [(set (v2i64 V128:$Rd),
7966 (OpNode (extract_high_v4i32 V128:$Rn),
7967 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7968 VectorIndexS:$idx))))]> {
7970 let Inst{11} = idx{1};
7971 let Inst{21} = idx{0};
7974 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7975 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7976 asm, ".h", "", "", ".h", []> {
7978 let Inst{11} = idx{2};
7979 let Inst{21} = idx{1};
7980 let Inst{20} = idx{0};
7983 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7984 FPR64Op, FPR32Op, V128, VectorIndexS,
7985 asm, ".s", "", "", ".s", []> {
7987 let Inst{11} = idx{1};
7988 let Inst{21} = idx{0};
7992 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7993 SDPatternOperator Accum> {
7994 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7996 V128_lo, VectorIndexH,
7997 asm, ".4s", ".4s", ".4h", ".h",
7998 [(set (v4i32 V128:$dst),
7999 (Accum (v4i32 V128:$Rd),
8000 (v4i32 (int_aarch64_neon_sqdmull
8002 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8003 VectorIndexH:$idx))))))]> {
8005 let Inst{11} = idx{2};
8006 let Inst{21} = idx{1};
8007 let Inst{20} = idx{0};
8010 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8011 // intermediate EXTRACT_SUBREG would be untyped.
8012 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8013 (i32 (vector_extract (v4i32
8014 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8015 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8016 VectorIndexH:$idx)))),
8019 (!cast<Instruction>(NAME # v4i16_indexed)
8020 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8021 V128_lo:$Rm, VectorIndexH:$idx),
8024 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8026 V128_lo, VectorIndexH,
8027 asm#"2", ".4s", ".4s", ".8h", ".h",
8028 [(set (v4i32 V128:$dst),
8029 (Accum (v4i32 V128:$Rd),
8030 (v4i32 (int_aarch64_neon_sqdmull
8031 (extract_high_v8i16 V128:$Rn),
8033 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8034 VectorIndexH:$idx))))))]> {
8036 let Inst{11} = idx{2};
8037 let Inst{21} = idx{1};
8038 let Inst{20} = idx{0};
8041 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8044 asm, ".2d", ".2d", ".2s", ".s",
8045 [(set (v2i64 V128:$dst),
8046 (Accum (v2i64 V128:$Rd),
8047 (v2i64 (int_aarch64_neon_sqdmull
8049 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8050 VectorIndexS:$idx))))))]> {
8052 let Inst{11} = idx{1};
8053 let Inst{21} = idx{0};
8056 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8059 asm#"2", ".2d", ".2d", ".4s", ".s",
8060 [(set (v2i64 V128:$dst),
8061 (Accum (v2i64 V128:$Rd),
8062 (v2i64 (int_aarch64_neon_sqdmull
8063 (extract_high_v4i32 V128:$Rn),
8065 (AArch64duplane32 (v4i32 V128:$Rm),
8066 VectorIndexS:$idx))))))]> {
8068 let Inst{11} = idx{1};
8069 let Inst{21} = idx{0};
8072 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8073 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8074 asm, ".h", "", "", ".h", []> {
8076 let Inst{11} = idx{2};
8077 let Inst{21} = idx{1};
8078 let Inst{20} = idx{0};
8082 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8083 FPR64Op, FPR32Op, V128, VectorIndexS,
8084 asm, ".s", "", "", ".s",
8085 [(set (i64 FPR64Op:$dst),
8086 (Accum (i64 FPR64Op:$Rd),
8087 (i64 (int_aarch64_neon_sqdmulls_scalar
8089 (i32 (vector_extract (v4i32 V128:$Rm),
8090 VectorIndexS:$idx))))))]> {
8093 let Inst{11} = idx{1};
8094 let Inst{21} = idx{0};
8098 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8099 SDPatternOperator OpNode> {
8100 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8101 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8103 V128_lo, VectorIndexH,
8104 asm, ".4s", ".4s", ".4h", ".h",
8105 [(set (v4i32 V128:$Rd),
8106 (OpNode (v4i16 V64:$Rn),
8107 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8109 let Inst{11} = idx{2};
8110 let Inst{21} = idx{1};
8111 let Inst{20} = idx{0};
8114 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8116 V128_lo, VectorIndexH,
8117 asm#"2", ".4s", ".4s", ".8h", ".h",
8118 [(set (v4i32 V128:$Rd),
8119 (OpNode (extract_high_v8i16 V128:$Rn),
8120 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8121 VectorIndexH:$idx))))]> {
8124 let Inst{11} = idx{2};
8125 let Inst{21} = idx{1};
8126 let Inst{20} = idx{0};
8129 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8132 asm, ".2d", ".2d", ".2s", ".s",
8133 [(set (v2i64 V128:$Rd),
8134 (OpNode (v2i32 V64:$Rn),
8135 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8137 let Inst{11} = idx{1};
8138 let Inst{21} = idx{0};
8141 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8144 asm#"2", ".2d", ".2d", ".4s", ".s",
8145 [(set (v2i64 V128:$Rd),
8146 (OpNode (extract_high_v4i32 V128:$Rn),
8147 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8148 VectorIndexS:$idx))))]> {
8150 let Inst{11} = idx{1};
8151 let Inst{21} = idx{0};
8156 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8157 SDPatternOperator OpNode> {
8158 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8159 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8161 V128_lo, VectorIndexH,
8162 asm, ".4s", ".4s", ".4h", ".h",
8163 [(set (v4i32 V128:$dst),
8164 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8165 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8167 let Inst{11} = idx{2};
8168 let Inst{21} = idx{1};
8169 let Inst{20} = idx{0};
8172 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8174 V128_lo, VectorIndexH,
8175 asm#"2", ".4s", ".4s", ".8h", ".h",
8176 [(set (v4i32 V128:$dst),
8177 (OpNode (v4i32 V128:$Rd),
8178 (extract_high_v8i16 V128:$Rn),
8179 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8180 VectorIndexH:$idx))))]> {
8182 let Inst{11} = idx{2};
8183 let Inst{21} = idx{1};
8184 let Inst{20} = idx{0};
8187 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8190 asm, ".2d", ".2d", ".2s", ".s",
8191 [(set (v2i64 V128:$dst),
8192 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8193 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8195 let Inst{11} = idx{1};
8196 let Inst{21} = idx{0};
8199 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8202 asm#"2", ".2d", ".2d", ".4s", ".s",
8203 [(set (v2i64 V128:$dst),
8204 (OpNode (v2i64 V128:$Rd),
8205 (extract_high_v4i32 V128:$Rn),
8206 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8207 VectorIndexS:$idx))))]> {
8209 let Inst{11} = idx{1};
8210 let Inst{21} = idx{0};
8215 //----------------------------------------------------------------------------
8216 // AdvSIMD scalar shift by immediate
8217 //----------------------------------------------------------------------------
8219 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8220 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8221 RegisterClass regtype1, RegisterClass regtype2,
8222 Operand immtype, string asm, list<dag> pattern>
8223 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8224 asm, "\t$Rd, $Rn, $imm", "", pattern>,
8229 let Inst{31-30} = 0b01;
8231 let Inst{28-23} = 0b111110;
8232 let Inst{22-16} = fixed_imm;
8233 let Inst{15-11} = opc;
8239 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8240 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8241 RegisterClass regtype1, RegisterClass regtype2,
8242 Operand immtype, string asm, list<dag> pattern>
8243 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8244 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8249 let Inst{31-30} = 0b01;
8251 let Inst{28-23} = 0b111110;
8252 let Inst{22-16} = fixed_imm;
8253 let Inst{15-11} = opc;
8260 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8261 let Predicates = [HasNEON, HasFullFP16] in {
8262 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8263 FPR16, FPR16, vecshiftR16, asm, []> {
8264 let Inst{19-16} = imm{3-0};
8266 } // Predicates = [HasNEON, HasFullFP16]
8267 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8268 FPR32, FPR32, vecshiftR32, asm, []> {
8269 let Inst{20-16} = imm{4-0};
8271 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8272 FPR64, FPR64, vecshiftR64, asm, []> {
8273 let Inst{21-16} = imm{5-0};
8277 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8278 SDPatternOperator OpNode> {
8279 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8280 FPR64, FPR64, vecshiftR64, asm,
8281 [(set (i64 FPR64:$Rd),
8282 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8283 let Inst{21-16} = imm{5-0};
8286 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8287 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8290 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8291 SDPatternOperator OpNode = null_frag> {
8292 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8293 FPR64, FPR64, vecshiftR64, asm,
8294 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8295 (i32 vecshiftR64:$imm)))]> {
8296 let Inst{21-16} = imm{5-0};
8299 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8300 (i32 vecshiftR64:$imm))),
8301 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8305 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8306 SDPatternOperator OpNode> {
8307 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8308 FPR64, FPR64, vecshiftL64, asm,
8309 [(set (v1i64 FPR64:$Rd),
8310 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8311 let Inst{21-16} = imm{5-0};
8315 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8316 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8317 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8318 FPR64, FPR64, vecshiftL64, asm, []> {
8319 let Inst{21-16} = imm{5-0};
8323 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8324 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8325 SDPatternOperator OpNode = null_frag> {
8326 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8327 FPR8, FPR16, vecshiftR8, asm, []> {
8328 let Inst{18-16} = imm{2-0};
8331 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8332 FPR16, FPR32, vecshiftR16, asm, []> {
8333 let Inst{19-16} = imm{3-0};
8336 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8337 FPR32, FPR64, vecshiftR32, asm,
8338 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8339 let Inst{20-16} = imm{4-0};
8343 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8344 SDPatternOperator OpNode> {
8345 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8346 FPR8, FPR8, vecshiftL8, asm, []> {
8347 let Inst{18-16} = imm{2-0};
8350 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8351 FPR16, FPR16, vecshiftL16, asm, []> {
8352 let Inst{19-16} = imm{3-0};
8355 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8356 FPR32, FPR32, vecshiftL32, asm,
8357 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8358 let Inst{20-16} = imm{4-0};
8361 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8362 FPR64, FPR64, vecshiftL64, asm,
8363 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8364 let Inst{21-16} = imm{5-0};
8367 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8368 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8371 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8372 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8373 FPR8, FPR8, vecshiftR8, asm, []> {
8374 let Inst{18-16} = imm{2-0};
8377 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8378 FPR16, FPR16, vecshiftR16, asm, []> {
8379 let Inst{19-16} = imm{3-0};
8382 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8383 FPR32, FPR32, vecshiftR32, asm, []> {
8384 let Inst{20-16} = imm{4-0};
8387 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8388 FPR64, FPR64, vecshiftR64, asm, []> {
8389 let Inst{21-16} = imm{5-0};
8393 //----------------------------------------------------------------------------
8394 // AdvSIMD vector x indexed element
8395 //----------------------------------------------------------------------------
8397 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8398 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8399 RegisterOperand dst_reg, RegisterOperand src_reg,
8401 string asm, string dst_kind, string src_kind,
8403 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8404 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8405 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8412 let Inst{28-23} = 0b011110;
8413 let Inst{22-16} = fixed_imm;
8414 let Inst{15-11} = opc;
8420 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8421 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8422 RegisterOperand vectype1, RegisterOperand vectype2,
8424 string asm, string dst_kind, string src_kind,
8426 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8427 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8428 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8435 let Inst{28-23} = 0b011110;
8436 let Inst{22-16} = fixed_imm;
8437 let Inst{15-11} = opc;
8443 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8445 let Predicates = [HasNEON, HasFullFP16] in {
8446 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8447 V64, V64, vecshiftR16,
8449 [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8451 let Inst{19-16} = imm;
8454 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8455 V128, V128, vecshiftR16,
8457 [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8459 let Inst{19-16} = imm;
8461 } // Predicates = [HasNEON, HasFullFP16]
8462 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8463 V64, V64, vecshiftR32,
8465 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8467 let Inst{20-16} = imm;
8470 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8471 V128, V128, vecshiftR32,
8473 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8475 let Inst{20-16} = imm;
8478 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8479 V128, V128, vecshiftR64,
8481 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8483 let Inst{21-16} = imm;
8487 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8489 let Predicates = [HasNEON, HasFullFP16] in {
8490 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8491 V64, V64, vecshiftR16,
8493 [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8495 let Inst{19-16} = imm;
8498 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8499 V128, V128, vecshiftR16,
8501 [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8503 let Inst{19-16} = imm;
8505 } // Predicates = [HasNEON, HasFullFP16]
8507 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8508 V64, V64, vecshiftR32,
8510 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8512 let Inst{20-16} = imm;
8515 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8516 V128, V128, vecshiftR32,
8518 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8520 let Inst{20-16} = imm;
8523 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8524 V128, V128, vecshiftR64,
8526 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8528 let Inst{21-16} = imm;
8532 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8533 SDPatternOperator OpNode> {
8534 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8535 V64, V128, vecshiftR16Narrow,
8537 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8539 let Inst{18-16} = imm;
8542 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8543 V128, V128, vecshiftR16Narrow,
8544 asm#"2", ".16b", ".8h", []> {
8546 let Inst{18-16} = imm;
8547 let hasSideEffects = 0;
8550 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8551 V64, V128, vecshiftR32Narrow,
8553 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8555 let Inst{19-16} = imm;
8558 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8559 V128, V128, vecshiftR32Narrow,
8560 asm#"2", ".8h", ".4s", []> {
8562 let Inst{19-16} = imm;
8563 let hasSideEffects = 0;
8566 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8567 V64, V128, vecshiftR64Narrow,
8569 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8571 let Inst{20-16} = imm;
8574 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8575 V128, V128, vecshiftR64Narrow,
8576 asm#"2", ".4s", ".2d", []> {
8578 let Inst{20-16} = imm;
8579 let hasSideEffects = 0;
8582 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8583 // themselves, so put them here instead.
8585 // Patterns involving what's effectively an insert high and a normal
8586 // intrinsic, represented by CONCAT_VECTORS.
8587 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8588 vecshiftR16Narrow:$imm)),
8589 (!cast<Instruction>(NAME # "v16i8_shift")
8590 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8591 V128:$Rn, vecshiftR16Narrow:$imm)>;
8592 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8593 vecshiftR32Narrow:$imm)),
8594 (!cast<Instruction>(NAME # "v8i16_shift")
8595 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8596 V128:$Rn, vecshiftR32Narrow:$imm)>;
8597 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8598 vecshiftR64Narrow:$imm)),
8599 (!cast<Instruction>(NAME # "v4i32_shift")
8600 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8601 V128:$Rn, vecshiftR64Narrow:$imm)>;
8604 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8605 SDPatternOperator OpNode> {
8606 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8607 V64, V64, vecshiftL8,
8609 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8610 (i32 vecshiftL8:$imm)))]> {
8612 let Inst{18-16} = imm;
8615 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8616 V128, V128, vecshiftL8,
8617 asm, ".16b", ".16b",
8618 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8619 (i32 vecshiftL8:$imm)))]> {
8621 let Inst{18-16} = imm;
8624 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8625 V64, V64, vecshiftL16,
8627 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8628 (i32 vecshiftL16:$imm)))]> {
8630 let Inst{19-16} = imm;
8633 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8634 V128, V128, vecshiftL16,
8636 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8637 (i32 vecshiftL16:$imm)))]> {
8639 let Inst{19-16} = imm;
8642 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8643 V64, V64, vecshiftL32,
8645 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8646 (i32 vecshiftL32:$imm)))]> {
8648 let Inst{20-16} = imm;
8651 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8652 V128, V128, vecshiftL32,
8654 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8655 (i32 vecshiftL32:$imm)))]> {
8657 let Inst{20-16} = imm;
8660 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8661 V128, V128, vecshiftL64,
8663 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8664 (i32 vecshiftL64:$imm)))]> {
8666 let Inst{21-16} = imm;
8670 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8671 SDPatternOperator OpNode> {
8672 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8673 V64, V64, vecshiftR8,
8675 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8676 (i32 vecshiftR8:$imm)))]> {
8678 let Inst{18-16} = imm;
8681 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8682 V128, V128, vecshiftR8,
8683 asm, ".16b", ".16b",
8684 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8685 (i32 vecshiftR8:$imm)))]> {
8687 let Inst{18-16} = imm;
8690 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8691 V64, V64, vecshiftR16,
8693 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8694 (i32 vecshiftR16:$imm)))]> {
8696 let Inst{19-16} = imm;
8699 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8700 V128, V128, vecshiftR16,
8702 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8703 (i32 vecshiftR16:$imm)))]> {
8705 let Inst{19-16} = imm;
8708 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8709 V64, V64, vecshiftR32,
8711 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8712 (i32 vecshiftR32:$imm)))]> {
8714 let Inst{20-16} = imm;
8717 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8718 V128, V128, vecshiftR32,
8720 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8721 (i32 vecshiftR32:$imm)))]> {
8723 let Inst{20-16} = imm;
8726 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8727 V128, V128, vecshiftR64,
8729 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8730 (i32 vecshiftR64:$imm)))]> {
8732 let Inst{21-16} = imm;
8736 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8737 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8738 SDPatternOperator OpNode = null_frag> {
8739 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8740 V64, V64, vecshiftR8, asm, ".8b", ".8b",
8741 [(set (v8i8 V64:$dst),
8742 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8743 (i32 vecshiftR8:$imm)))]> {
8745 let Inst{18-16} = imm;
8748 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8749 V128, V128, vecshiftR8, asm, ".16b", ".16b",
8750 [(set (v16i8 V128:$dst),
8751 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8752 (i32 vecshiftR8:$imm)))]> {
8754 let Inst{18-16} = imm;
8757 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8758 V64, V64, vecshiftR16, asm, ".4h", ".4h",
8759 [(set (v4i16 V64:$dst),
8760 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8761 (i32 vecshiftR16:$imm)))]> {
8763 let Inst{19-16} = imm;
8766 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8767 V128, V128, vecshiftR16, asm, ".8h", ".8h",
8768 [(set (v8i16 V128:$dst),
8769 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8770 (i32 vecshiftR16:$imm)))]> {
8772 let Inst{19-16} = imm;
8775 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8776 V64, V64, vecshiftR32, asm, ".2s", ".2s",
8777 [(set (v2i32 V64:$dst),
8778 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8779 (i32 vecshiftR32:$imm)))]> {
8781 let Inst{20-16} = imm;
8784 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8785 V128, V128, vecshiftR32, asm, ".4s", ".4s",
8786 [(set (v4i32 V128:$dst),
8787 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8788 (i32 vecshiftR32:$imm)))]> {
8790 let Inst{20-16} = imm;
8793 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8794 V128, V128, vecshiftR64,
8795 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8796 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8797 (i32 vecshiftR64:$imm)))]> {
8799 let Inst{21-16} = imm;
8803 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8804 SDPatternOperator OpNode = null_frag> {
8805 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8806 V64, V64, vecshiftL8,
8808 [(set (v8i8 V64:$dst),
8809 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8810 (i32 vecshiftL8:$imm)))]> {
8812 let Inst{18-16} = imm;
8815 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8816 V128, V128, vecshiftL8,
8817 asm, ".16b", ".16b",
8818 [(set (v16i8 V128:$dst),
8819 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8820 (i32 vecshiftL8:$imm)))]> {
8822 let Inst{18-16} = imm;
8825 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8826 V64, V64, vecshiftL16,
8828 [(set (v4i16 V64:$dst),
8829 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8830 (i32 vecshiftL16:$imm)))]> {
8832 let Inst{19-16} = imm;
8835 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8836 V128, V128, vecshiftL16,
8838 [(set (v8i16 V128:$dst),
8839 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8840 (i32 vecshiftL16:$imm)))]> {
8842 let Inst{19-16} = imm;
8845 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8846 V64, V64, vecshiftL32,
8848 [(set (v2i32 V64:$dst),
8849 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8850 (i32 vecshiftL32:$imm)))]> {
8852 let Inst{20-16} = imm;
8855 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8856 V128, V128, vecshiftL32,
8858 [(set (v4i32 V128:$dst),
8859 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8860 (i32 vecshiftL32:$imm)))]> {
8862 let Inst{20-16} = imm;
8865 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8866 V128, V128, vecshiftL64,
8868 [(set (v2i64 V128:$dst),
8869 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8870 (i32 vecshiftL64:$imm)))]> {
8872 let Inst{21-16} = imm;
8876 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8877 SDPatternOperator OpNode> {
8878 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8879 V128, V64, vecshiftL8, asm, ".8h", ".8b",
8880 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8882 let Inst{18-16} = imm;
8885 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8886 V128, V128, vecshiftL8,
8887 asm#"2", ".8h", ".16b",
8888 [(set (v8i16 V128:$Rd),
8889 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8891 let Inst{18-16} = imm;
8894 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8895 V128, V64, vecshiftL16, asm, ".4s", ".4h",
8896 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8898 let Inst{19-16} = imm;
8901 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8902 V128, V128, vecshiftL16,
8903 asm#"2", ".4s", ".8h",
8904 [(set (v4i32 V128:$Rd),
8905 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8908 let Inst{19-16} = imm;
8911 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8912 V128, V64, vecshiftL32, asm, ".2d", ".2s",
8913 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8915 let Inst{20-16} = imm;
8918 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8919 V128, V128, vecshiftL32,
8920 asm#"2", ".2d", ".4s",
8921 [(set (v2i64 V128:$Rd),
8922 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8924 let Inst{20-16} = imm;
8930 // Vector load/store
8932 // SIMD ldX/stX no-index memory references don't allow the optional
8933 // ", #0" constant and handle post-indexing explicitly, so we use
8934 // a more specialized parse method for them. Otherwise, it's the same as
8935 // the general GPR64sp handling.
8937 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8938 string asm, dag oops, dag iops, list<dag> pattern>
8939 : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8944 let Inst{29-23} = 0b0011000;
8946 let Inst{21-16} = 0b000000;
8947 let Inst{15-12} = opcode;
8948 let Inst{11-10} = size;
8953 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8954 string asm, dag oops, dag iops>
8955 : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8961 let Inst{29-23} = 0b0011001;
8964 let Inst{20-16} = Xm;
8965 let Inst{15-12} = opcode;
8966 let Inst{11-10} = size;
8971 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8972 // register post-index addressing from the zero register.
8973 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
8974 int Offset, int Size> {
8975 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8976 // "ld1\t$Vt, [$Rn], #16"
8977 // may get mapped to
8978 // (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8979 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8980 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8982 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8985 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8986 // "ld1.8b\t$Vt, [$Rn], #16"
8987 // may get mapped to
8988 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8989 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8990 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8992 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8995 // E.g. "ld1.8b { v0, v1 }, [x1]"
8996 // "ld1\t$Vt, [$Rn]"
8997 // may get mapped to
8998 // (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8999 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9000 (!cast<Instruction>(BaseName # Count # "v" # layout)
9001 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9004 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9005 // "ld1\t$Vt, [$Rn], $Xm"
9006 // may get mapped to
9007 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9008 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9009 (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9011 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9012 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9015 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9016 int Offset128, int Offset64, bits<4> opcode> {
9017 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9018 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9019 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9020 (ins GPR64sp:$Rn), []>;
9021 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9022 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9023 (ins GPR64sp:$Rn), []>;
9024 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9025 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9026 (ins GPR64sp:$Rn), []>;
9027 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9028 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9029 (ins GPR64sp:$Rn), []>;
9030 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9031 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9032 (ins GPR64sp:$Rn), []>;
9033 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9034 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9035 (ins GPR64sp:$Rn), []>;
9036 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9037 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9038 (ins GPR64sp:$Rn), []>;
9041 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9042 (outs GPR64sp:$wback,
9043 !cast<RegisterOperand>(veclist # "16b"):$Vt),
9045 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9046 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9047 (outs GPR64sp:$wback,
9048 !cast<RegisterOperand>(veclist # "8h"):$Vt),
9050 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9051 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9052 (outs GPR64sp:$wback,
9053 !cast<RegisterOperand>(veclist # "4s"):$Vt),
9055 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9056 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9057 (outs GPR64sp:$wback,
9058 !cast<RegisterOperand>(veclist # "2d"):$Vt),
9060 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9061 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9062 (outs GPR64sp:$wback,
9063 !cast<RegisterOperand>(veclist # "8b"):$Vt),
9065 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9066 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9067 (outs GPR64sp:$wback,
9068 !cast<RegisterOperand>(veclist # "4h"):$Vt),
9070 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9071 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9072 (outs GPR64sp:$wback,
9073 !cast<RegisterOperand>(veclist # "2s"):$Vt),
9075 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9078 defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9079 defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9080 defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9081 defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9082 defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9083 defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9084 defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9087 // Only ld1/st1 has a v1d version.
9088 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9089 int Offset128, int Offset64, bits<4> opcode> {
9090 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9091 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9092 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9094 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9095 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9097 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9098 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9100 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9101 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9103 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9104 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9106 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9107 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9109 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9110 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9113 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9114 (outs GPR64sp:$wback),
9115 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9117 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9118 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9119 (outs GPR64sp:$wback),
9120 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9122 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9123 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9124 (outs GPR64sp:$wback),
9125 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9127 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9128 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9129 (outs GPR64sp:$wback),
9130 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9132 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9133 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9134 (outs GPR64sp:$wback),
9135 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9137 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9138 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9139 (outs GPR64sp:$wback),
9140 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9142 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9143 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9144 (outs GPR64sp:$wback),
9145 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9147 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9150 defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9151 defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9152 defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9153 defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9154 defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9155 defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9156 defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9159 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9160 int Offset128, int Offset64, bits<4> opcode>
9161 : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9163 // LD1 instructions have extra "1d" variants.
9164 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9165 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9166 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9167 (ins GPR64sp:$Rn), []>;
9169 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9170 (outs GPR64sp:$wback,
9171 !cast<RegisterOperand>(veclist # "1d"):$Vt),
9173 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9176 defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9179 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9180 int Offset128, int Offset64, bits<4> opcode>
9181 : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9183 // ST1 instructions have extra "1d" variants.
9184 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9185 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9186 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9189 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9190 (outs GPR64sp:$wback),
9191 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9193 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9196 defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9199 multiclass SIMDLd1Multiple<string asm> {
9200 defm One : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8, 0b0111>;
9201 defm Two : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9202 defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9203 defm Four : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9206 multiclass SIMDSt1Multiple<string asm> {
9207 defm One : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8, 0b0111>;
9208 defm Two : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9209 defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9210 defm Four : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9213 multiclass SIMDLd2Multiple<string asm> {
9214 defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9217 multiclass SIMDSt2Multiple<string asm> {
9218 defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9221 multiclass SIMDLd3Multiple<string asm> {
9222 defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9225 multiclass SIMDSt3Multiple<string asm> {
9226 defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9229 multiclass SIMDLd4Multiple<string asm> {
9230 defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9233 multiclass SIMDSt4Multiple<string asm> {
9234 defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9238 // AdvSIMD Load/store single-element
9241 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9242 string asm, string operands, string cst,
9243 dag oops, dag iops, list<dag> pattern>
9244 : I<oops, iops, asm, operands, cst, pattern> {
9248 let Inst{29-24} = 0b001101;
9251 let Inst{15-13} = opcode;
9256 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9257 string asm, string operands, string cst,
9258 dag oops, dag iops, list<dag> pattern>
9259 : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9263 let Inst{29-24} = 0b001101;
9266 let Inst{15-13} = opcode;
9272 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9273 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9274 DAGOperand listtype>
9275 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9276 (outs listtype:$Vt), (ins GPR64sp:$Rn),
9280 let Inst{20-16} = 0b00000;
9282 let Inst{11-10} = size;
9284 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9285 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9286 string asm, DAGOperand listtype, DAGOperand GPR64pi>
9287 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9289 (outs GPR64sp:$wback, listtype:$Vt),
9290 (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9294 let Inst{20-16} = Xm;
9296 let Inst{11-10} = size;
9299 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9300 int Offset, int Size> {
9301 // E.g. "ld1r { v0.8b }, [x1], #1"
9302 // "ld1r.8b\t$Vt, [$Rn], #1"
9303 // may get mapped to
9304 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9305 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9306 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9308 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9311 // E.g. "ld1r.8b { v0 }, [x1], #1"
9312 // "ld1r.8b\t$Vt, [$Rn], #1"
9313 // may get mapped to
9314 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9315 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9316 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9318 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9321 // E.g. "ld1r.8b { v0 }, [x1]"
9322 // "ld1r.8b\t$Vt, [$Rn]"
9323 // may get mapped to
9324 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9325 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9326 (!cast<Instruction>(BaseName # "v" # layout)
9327 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9330 // E.g. "ld1r.8b { v0 }, [x1], x2"
9331 // "ld1r.8b\t$Vt, [$Rn], $Xm"
9332 // may get mapped to
9333 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9334 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9335 (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9337 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9338 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9341 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9342 int Offset1, int Offset2, int Offset4, int Offset8> {
9343 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9344 !cast<DAGOperand>("VecList" # Count # "8b")>;
9345 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9346 !cast<DAGOperand>("VecList" # Count #"16b")>;
9347 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9348 !cast<DAGOperand>("VecList" # Count #"4h")>;
9349 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9350 !cast<DAGOperand>("VecList" # Count #"8h")>;
9351 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9352 !cast<DAGOperand>("VecList" # Count #"2s")>;
9353 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9354 !cast<DAGOperand>("VecList" # Count #"4s")>;
9355 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9356 !cast<DAGOperand>("VecList" # Count #"1d")>;
9357 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9358 !cast<DAGOperand>("VecList" # Count #"2d")>;
9360 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9361 !cast<DAGOperand>("VecList" # Count # "8b"),
9362 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9363 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9364 !cast<DAGOperand>("VecList" # Count # "16b"),
9365 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9366 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9367 !cast<DAGOperand>("VecList" # Count # "4h"),
9368 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9369 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9370 !cast<DAGOperand>("VecList" # Count # "8h"),
9371 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9372 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9373 !cast<DAGOperand>("VecList" # Count # "2s"),
9374 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9375 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9376 !cast<DAGOperand>("VecList" # Count # "4s"),
9377 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9378 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9379 !cast<DAGOperand>("VecList" # Count # "1d"),
9380 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9381 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9382 !cast<DAGOperand>("VecList" # Count # "2d"),
9383 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9385 defm : SIMDLdrAliases<NAME, asm, "8b", Count, Offset1, 64>;
9386 defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9387 defm : SIMDLdrAliases<NAME, asm, "4h", Count, Offset2, 64>;
9388 defm : SIMDLdrAliases<NAME, asm, "8h", Count, Offset2, 128>;
9389 defm : SIMDLdrAliases<NAME, asm, "2s", Count, Offset4, 64>;
9390 defm : SIMDLdrAliases<NAME, asm, "4s", Count, Offset4, 128>;
9391 defm : SIMDLdrAliases<NAME, asm, "1d", Count, Offset8, 64>;
9392 defm : SIMDLdrAliases<NAME, asm, "2d", Count, Offset8, 128>;
9395 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9396 dag oops, dag iops, list<dag> pattern>
9397 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9399 // idx encoded in Q:S:size fields.
9401 let Inst{30} = idx{3};
9403 let Inst{20-16} = 0b00000;
9404 let Inst{12} = idx{2};
9405 let Inst{11-10} = idx{1-0};
9407 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9408 dag oops, dag iops, list<dag> pattern>
9409 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9410 oops, iops, pattern> {
9411 // idx encoded in Q:S:size fields.
9413 let Inst{30} = idx{3};
9415 let Inst{20-16} = 0b00000;
9416 let Inst{12} = idx{2};
9417 let Inst{11-10} = idx{1-0};
9419 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9421 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9422 "$Rn = $wback", oops, iops, []> {
9423 // idx encoded in Q:S:size fields.
9426 let Inst{30} = idx{3};
9428 let Inst{20-16} = Xm;
9429 let Inst{12} = idx{2};
9430 let Inst{11-10} = idx{1-0};
9432 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9434 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9435 "$Rn = $wback", oops, iops, []> {
9436 // idx encoded in Q:S:size fields.
9439 let Inst{30} = idx{3};
9441 let Inst{20-16} = Xm;
9442 let Inst{12} = idx{2};
9443 let Inst{11-10} = idx{1-0};
9446 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9447 dag oops, dag iops, list<dag> pattern>
9448 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9450 // idx encoded in Q:S:size<1> fields.
9452 let Inst{30} = idx{2};
9454 let Inst{20-16} = 0b00000;
9455 let Inst{12} = idx{1};
9456 let Inst{11} = idx{0};
9457 let Inst{10} = size;
9459 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9460 dag oops, dag iops, list<dag> pattern>
9461 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9462 oops, iops, pattern> {
9463 // idx encoded in Q:S:size<1> fields.
9465 let Inst{30} = idx{2};
9467 let Inst{20-16} = 0b00000;
9468 let Inst{12} = idx{1};
9469 let Inst{11} = idx{0};
9470 let Inst{10} = size;
9473 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9475 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9476 "$Rn = $wback", oops, iops, []> {
9477 // idx encoded in Q:S:size<1> fields.
9480 let Inst{30} = idx{2};
9482 let Inst{20-16} = Xm;
9483 let Inst{12} = idx{1};
9484 let Inst{11} = idx{0};
9485 let Inst{10} = size;
9487 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9489 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9490 "$Rn = $wback", oops, iops, []> {
9491 // idx encoded in Q:S:size<1> fields.
9494 let Inst{30} = idx{2};
9496 let Inst{20-16} = Xm;
9497 let Inst{12} = idx{1};
9498 let Inst{11} = idx{0};
9499 let Inst{10} = size;
9501 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9502 dag oops, dag iops, list<dag> pattern>
9503 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9505 // idx encoded in Q:S fields.
9507 let Inst{30} = idx{1};
9509 let Inst{20-16} = 0b00000;
9510 let Inst{12} = idx{0};
9511 let Inst{11-10} = size;
9513 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9514 dag oops, dag iops, list<dag> pattern>
9515 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9516 oops, iops, pattern> {
9517 // idx encoded in Q:S fields.
9519 let Inst{30} = idx{1};
9521 let Inst{20-16} = 0b00000;
9522 let Inst{12} = idx{0};
9523 let Inst{11-10} = size;
9525 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9526 string asm, dag oops, dag iops>
9527 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9528 "$Rn = $wback", oops, iops, []> {
9529 // idx encoded in Q:S fields.
9532 let Inst{30} = idx{1};
9534 let Inst{20-16} = Xm;
9535 let Inst{12} = idx{0};
9536 let Inst{11-10} = size;
9538 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9539 string asm, dag oops, dag iops>
9540 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9541 "$Rn = $wback", oops, iops, []> {
9542 // idx encoded in Q:S fields.
9545 let Inst{30} = idx{1};
9547 let Inst{20-16} = Xm;
9548 let Inst{12} = idx{0};
9549 let Inst{11-10} = size;
9551 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9552 dag oops, dag iops, list<dag> pattern>
9553 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9555 // idx encoded in Q field.
9559 let Inst{20-16} = 0b00000;
9561 let Inst{11-10} = size;
9563 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9564 dag oops, dag iops, list<dag> pattern>
9565 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9566 oops, iops, pattern> {
9567 // idx encoded in Q field.
9571 let Inst{20-16} = 0b00000;
9573 let Inst{11-10} = size;
9575 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9576 string asm, dag oops, dag iops>
9577 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9578 "$Rn = $wback", oops, iops, []> {
9579 // idx encoded in Q field.
9584 let Inst{20-16} = Xm;
9586 let Inst{11-10} = size;
9588 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9589 string asm, dag oops, dag iops>
9590 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9591 "$Rn = $wback", oops, iops, []> {
9592 // idx encoded in Q field.
9597 let Inst{20-16} = Xm;
9599 let Inst{11-10} = size;
9602 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9603 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9604 RegisterOperand listtype,
9605 RegisterOperand GPR64pi> {
9606 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9607 (outs listtype:$dst),
9608 (ins listtype:$Vt, VectorIndexB:$idx,
9611 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9612 (outs GPR64sp:$wback, listtype:$dst),
9613 (ins listtype:$Vt, VectorIndexB:$idx,
9614 GPR64sp:$Rn, GPR64pi:$Xm)>;
9616 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9617 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9618 RegisterOperand listtype,
9619 RegisterOperand GPR64pi> {
9620 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9621 (outs listtype:$dst),
9622 (ins listtype:$Vt, VectorIndexH:$idx,
9625 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9626 (outs GPR64sp:$wback, listtype:$dst),
9627 (ins listtype:$Vt, VectorIndexH:$idx,
9628 GPR64sp:$Rn, GPR64pi:$Xm)>;
9630 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9631 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9632 RegisterOperand listtype,
9633 RegisterOperand GPR64pi> {
9634 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9635 (outs listtype:$dst),
9636 (ins listtype:$Vt, VectorIndexS:$idx,
9639 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9640 (outs GPR64sp:$wback, listtype:$dst),
9641 (ins listtype:$Vt, VectorIndexS:$idx,
9642 GPR64sp:$Rn, GPR64pi:$Xm)>;
9644 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9645 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9646 RegisterOperand listtype, RegisterOperand GPR64pi> {
9647 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9648 (outs listtype:$dst),
9649 (ins listtype:$Vt, VectorIndexD:$idx,
9652 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9653 (outs GPR64sp:$wback, listtype:$dst),
9654 (ins listtype:$Vt, VectorIndexD:$idx,
9655 GPR64sp:$Rn, GPR64pi:$Xm)>;
9657 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9658 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9659 RegisterOperand listtype, RegisterOperand GPR64pi> {
9660 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9661 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9664 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9665 (outs GPR64sp:$wback),
9666 (ins listtype:$Vt, VectorIndexB:$idx,
9667 GPR64sp:$Rn, GPR64pi:$Xm)>;
9669 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9670 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9671 RegisterOperand listtype, RegisterOperand GPR64pi> {
9672 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9673 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9676 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9677 (outs GPR64sp:$wback),
9678 (ins listtype:$Vt, VectorIndexH:$idx,
9679 GPR64sp:$Rn, GPR64pi:$Xm)>;
9681 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9682 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9683 RegisterOperand listtype, RegisterOperand GPR64pi> {
9684 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9685 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9688 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9689 (outs GPR64sp:$wback),
9690 (ins listtype:$Vt, VectorIndexS:$idx,
9691 GPR64sp:$Rn, GPR64pi:$Xm)>;
9693 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9694 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9695 RegisterOperand listtype, RegisterOperand GPR64pi> {
9696 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9697 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9700 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9701 (outs GPR64sp:$wback),
9702 (ins listtype:$Vt, VectorIndexD:$idx,
9703 GPR64sp:$Rn, GPR64pi:$Xm)>;
9706 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9707 string Count, int Offset, Operand idxtype> {
9708 // E.g. "ld1 { v0.8b }[0], [x1], #1"
9709 // "ld1\t$Vt, [$Rn], #1"
9710 // may get mapped to
9711 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9712 def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9713 (!cast<Instruction>(NAME # Type # "_POST")
9715 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9716 idxtype:$idx, XZR), 1>;
9718 // E.g. "ld1.8b { v0 }[0], [x1], #1"
9719 // "ld1.8b\t$Vt, [$Rn], #1"
9720 // may get mapped to
9721 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9722 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9723 (!cast<Instruction>(NAME # Type # "_POST")
9725 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9726 idxtype:$idx, XZR), 0>;
9728 // E.g. "ld1.8b { v0 }[0], [x1]"
9729 // "ld1.8b\t$Vt, [$Rn]"
9730 // may get mapped to
9731 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9732 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9733 (!cast<Instruction>(NAME # Type)
9734 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9735 idxtype:$idx, GPR64sp:$Rn), 0>;
9737 // E.g. "ld1.8b { v0 }[0], [x1], x2"
9738 // "ld1.8b\t$Vt, [$Rn], $Xm"
9739 // may get mapped to
9740 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9741 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9742 (!cast<Instruction>(NAME # Type # "_POST")
9744 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9746 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9749 multiclass SIMDLdSt1SingleAliases<string asm> {
9750 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
9751 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9752 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9753 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9756 multiclass SIMDLdSt2SingleAliases<string asm> {
9757 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
9758 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
9759 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
9760 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9763 multiclass SIMDLdSt3SingleAliases<string asm> {
9764 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
9765 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
9766 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9767 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9770 multiclass SIMDLdSt4SingleAliases<string asm> {
9771 defm "" : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
9772 defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
9773 defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9774 defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9776 } // end of 'let Predicates = [HasNEON]'
9778 //----------------------------------------------------------------------------
9779 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9780 //----------------------------------------------------------------------------
9782 let Predicates = [HasNEON, HasRDM] in {
9784 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9785 RegisterOperand regtype, string asm,
9786 string kind, list<dag> pattern>
9787 : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9790 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9791 SDPatternOperator Accum> {
9792 def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9793 [(set (v4i16 V64:$dst),
9794 (Accum (v4i16 V64:$Rd),
9795 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9796 (v4i16 V64:$Rm)))))]>;
9797 def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9798 [(set (v8i16 V128:$dst),
9799 (Accum (v8i16 V128:$Rd),
9800 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9801 (v8i16 V128:$Rm)))))]>;
9802 def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9803 [(set (v2i32 V64:$dst),
9804 (Accum (v2i32 V64:$Rd),
9805 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9806 (v2i32 V64:$Rm)))))]>;
9807 def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9808 [(set (v4i32 V128:$dst),
9809 (Accum (v4i32 V128:$Rd),
9810 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9811 (v4i32 V128:$Rm)))))]>;
9814 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9815 SDPatternOperator Accum> {
9816 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9817 V64, V64, V128_lo, VectorIndexH,
9818 asm, ".4h", ".4h", ".4h", ".h",
9819 [(set (v4i16 V64:$dst),
9820 (Accum (v4i16 V64:$Rd),
9821 (v4i16 (int_aarch64_neon_sqrdmulh
9823 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9824 VectorIndexH:$idx))))))]> {
9826 let Inst{11} = idx{2};
9827 let Inst{21} = idx{1};
9828 let Inst{20} = idx{0};
9831 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9832 V128, V128, V128_lo, VectorIndexH,
9833 asm, ".8h", ".8h", ".8h", ".h",
9834 [(set (v8i16 V128:$dst),
9835 (Accum (v8i16 V128:$Rd),
9836 (v8i16 (int_aarch64_neon_sqrdmulh
9838 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9839 VectorIndexH:$idx))))))]> {
9841 let Inst{11} = idx{2};
9842 let Inst{21} = idx{1};
9843 let Inst{20} = idx{0};
9846 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9847 V64, V64, V128, VectorIndexS,
9848 asm, ".2s", ".2s", ".2s", ".s",
9849 [(set (v2i32 V64:$dst),
9850 (Accum (v2i32 V64:$Rd),
9851 (v2i32 (int_aarch64_neon_sqrdmulh
9853 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9854 VectorIndexS:$idx))))))]> {
9856 let Inst{11} = idx{1};
9857 let Inst{21} = idx{0};
9860 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9861 // an intermediate EXTRACT_SUBREG would be untyped.
9862 // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9863 // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9864 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9865 (i32 (vector_extract
9866 (v4i32 (insert_subvector
9868 (v2i32 (int_aarch64_neon_sqrdmulh
9870 (v2i32 (AArch64duplane32
9872 VectorIndexS:$idx)))),
9876 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9877 (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9882 VectorIndexS:$idx)),
9885 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9886 V128, V128, V128, VectorIndexS,
9887 asm, ".4s", ".4s", ".4s", ".s",
9888 [(set (v4i32 V128:$dst),
9889 (Accum (v4i32 V128:$Rd),
9890 (v4i32 (int_aarch64_neon_sqrdmulh
9892 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9893 VectorIndexS:$idx))))))]> {
9895 let Inst{11} = idx{1};
9896 let Inst{21} = idx{0};
9899 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9900 // an intermediate EXTRACT_SUBREG would be untyped.
9901 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9902 (i32 (vector_extract
9903 (v4i32 (int_aarch64_neon_sqrdmulh
9905 (v4i32 (AArch64duplane32
9907 VectorIndexS:$idx)))),
9910 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9911 (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9916 VectorIndexS:$idx)),
9919 def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9920 FPR16Op, FPR16Op, V128_lo,
9921 VectorIndexH, asm, ".h", "", "", ".h",
9924 let Inst{11} = idx{2};
9925 let Inst{21} = idx{1};
9926 let Inst{20} = idx{0};
9929 def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9930 FPR32Op, FPR32Op, V128, VectorIndexS,
9931 asm, ".s", "", "", ".s",
9932 [(set (i32 FPR32Op:$dst),
9933 (Accum (i32 FPR32Op:$Rd),
9934 (i32 (int_aarch64_neon_sqrdmulh
9936 (i32 (vector_extract (v4i32 V128:$Rm),
9937 VectorIndexS:$idx))))))]> {
9939 let Inst{11} = idx{1};
9940 let Inst{21} = idx{0};
9943 } // let Predicates = [HasNeon, HasRDM]
9945 //----------------------------------------------------------------------------
9946 // ARMv8.3 Complex ADD/MLA instructions
9947 //----------------------------------------------------------------------------
9949 class ComplexRotationOperand<int Angle, int Remainder, string Type>
9951 let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
9952 let DiagnosticType = "InvalidComplexRotation" # Type;
9953 let Name = "ComplexRotation" # Type;
9955 def complexrotateop : Operand<i32> {
9956 let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
9957 let PrintMethod = "printComplexRotationOp<90, 0>";
9959 def complexrotateopodd : Operand<i32> {
9960 let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
9961 let PrintMethod = "printComplexRotationOp<180, 90>";
9964 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9965 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
9966 RegisterOperand regtype, Operand rottype,
9967 string asm, string kind, list<dag> pattern>
9968 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9969 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9970 "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
9979 let Inst{28-24} = 0b01110;
9980 let Inst{23-22} = size;
9982 let Inst{20-16} = Rm;
9983 let Inst{15-13} = opcode;
9984 // Non-tied version (FCADD) only has one rotation bit
9992 //8.3 CompNum - Floating-point complex number support
9993 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
9994 string asm, SDPatternOperator OpNode>{
9995 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
9996 def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
9998 [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10001 (rottype i32:$rot)))]>;
10003 def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10005 [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10008 (rottype i32:$rot)))]>;
10011 let Predicates = [HasComplxNum, HasNEON] in {
10012 def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10014 [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10017 (rottype i32:$rot)))]>;
10019 def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10021 [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10024 (rottype i32:$rot)))]>;
10026 def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10028 [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10031 (rottype i32:$rot)))]>;
10035 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10036 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10038 RegisterOperand regtype,
10039 Operand rottype, string asm,
10040 string kind, list<dag> pattern>
10041 : I<(outs regtype:$dst),
10042 (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10043 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10044 "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10053 let Inst{28-24} = 0b01110;
10054 let Inst{23-22} = size;
10056 let Inst{20-16} = Rm;
10057 let Inst{15-13} = opcode;
10058 let Inst{12-11} = rot;
10060 let Inst{9-5} = Rn;
10061 let Inst{4-0} = Rd;
10064 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10065 Operand rottype, string asm,
10066 SDPatternOperator OpNode> {
10067 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10068 def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10069 rottype, asm, ".4h",
10070 [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10073 (rottype i32:$rot)))]>;
10075 def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10076 rottype, asm, ".8h",
10077 [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10080 (rottype i32:$rot)))]>;
10083 let Predicates = [HasComplxNum, HasNEON] in {
10084 def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10085 rottype, asm, ".2s",
10086 [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10089 (rottype i32:$rot)))]>;
10091 def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10092 rottype, asm, ".4s",
10093 [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10096 (rottype i32:$rot)))]>;
10098 def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10099 rottype, asm, ".2d",
10100 [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10103 (rottype i32:$rot)))]>;
10107 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10108 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10109 bit opc1, bit opc2, RegisterOperand dst_reg,
10110 RegisterOperand lhs_reg,
10111 RegisterOperand rhs_reg, Operand vec_idx,
10112 Operand rottype, string asm, string apple_kind,
10113 string dst_kind, string lhs_kind,
10114 string rhs_kind, list<dag> pattern>
10115 : I<(outs dst_reg:$dst),
10116 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10118 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10119 "$idx, $rot" # "|" # apple_kind #
10120 "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10130 let Inst{28} = Scalar;
10131 let Inst{27-24} = 0b1111;
10132 let Inst{23-22} = size;
10133 // Bit 21 must be set by the derived class.
10134 let Inst{20-16} = Rm;
10135 let Inst{15} = opc1;
10136 let Inst{14-13} = rot;
10137 let Inst{12} = opc2;
10138 // Bit 11 must be set by the derived class.
10140 let Inst{9-5} = Rn;
10141 let Inst{4-0} = Rd;
10144 // The complex instructions index by pairs of elements, so the VectorIndexes
10145 // don't match the lane types, and the index bits are different to the other
10147 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10148 string asm, SDPatternOperator OpNode> {
10149 let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10150 def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10151 V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10155 let Inst{21} = idx{0};
10158 def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10159 V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10160 ".8h", ".8h", ".h", []> {
10162 let Inst{11} = idx{1};
10163 let Inst{21} = idx{0};
10165 } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10167 let Predicates = [HasComplxNum, HasNEON] in {
10168 def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10169 V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10170 ".4s", ".4s", ".s", []> {
10172 let Inst{11} = idx{0};
10175 } // Predicates = [HasComplxNum, HasNEON]
10178 //----------------------------------------------------------------------------
10179 // Crypto extensions
10180 //----------------------------------------------------------------------------
10182 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10183 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10185 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10189 let Inst{31-16} = 0b0100111000101000;
10190 let Inst{15-12} = opc;
10191 let Inst{11-10} = 0b10;
10192 let Inst{9-5} = Rn;
10193 let Inst{4-0} = Rd;
10196 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10197 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10198 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10200 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10201 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10203 [(set (v16i8 V128:$dst),
10204 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10206 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10207 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10208 dag oops, dag iops, list<dag> pat>
10209 : I<oops, iops, asm,
10210 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10211 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10216 let Inst{31-21} = 0b01011110000;
10217 let Inst{20-16} = Rm;
10219 let Inst{14-12} = opc;
10220 let Inst{11-10} = 0b00;
10221 let Inst{9-5} = Rn;
10222 let Inst{4-0} = Rd;
10225 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10226 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10227 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10228 [(set (v4i32 FPR128:$dst),
10229 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10230 (v4i32 V128:$Rm)))]>;
10232 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10233 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10234 (ins V128:$Rd, V128:$Rn, V128:$Rm),
10235 [(set (v4i32 V128:$dst),
10236 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10237 (v4i32 V128:$Rm)))]>;
10239 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10240 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10241 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10242 [(set (v4i32 FPR128:$dst),
10243 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10244 (v4i32 V128:$Rm)))]>;
10246 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10247 class SHA2OpInst<bits<4> opc, string asm, string kind,
10248 string cstr, dag oops, dag iops,
10250 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10251 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10255 let Inst{31-16} = 0b0101111000101000;
10256 let Inst{15-12} = opc;
10257 let Inst{11-10} = 0b10;
10258 let Inst{9-5} = Rn;
10259 let Inst{4-0} = Rd;
10262 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10263 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10264 (ins V128:$Rd, V128:$Rn),
10265 [(set (v4i32 V128:$dst),
10266 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10268 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10269 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10270 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10272 // Armv8.2-A Crypto extensions
10273 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10275 : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10278 let Inst{31-25} = 0b1100111;
10279 let Inst{9-5} = Vn;
10280 let Inst{4-0} = Vd;
10283 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10284 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10286 let Inst{31-25} = 0b1100111;
10287 let Inst{24-21} = 0b0110;
10288 let Inst{20-15} = 0b000001;
10289 let Inst{14} = op0;
10290 let Inst{13-12} = 0b00;
10291 let Inst{11-10} = op1;
10293 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10294 : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10295 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10296 : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10298 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10299 string asmops, string cst>
10300 : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10302 let Inst{24-21} = 0b0011;
10303 let Inst{20-16} = Vm;
10304 let Inst{15} = 0b1;
10305 let Inst{14} = op0;
10306 let Inst{13-12} = 0b00;
10307 let Inst{11-10} = op1;
10309 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10310 : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10311 "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10312 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10313 : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10314 "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10315 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10316 : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10317 "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10318 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10319 : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10320 "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10321 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10322 : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10323 asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10325 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10326 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10330 let Inst{24-23} = 0b00;
10331 let Inst{22-21} = op0;
10332 let Inst{20-16} = Vm;
10333 let Inst{15} = 0b0;
10334 let Inst{14-10} = Va;
10336 class CryptoRRRR_16B<bits<2>op0, string asm>
10337 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10339 class CryptoRRRR_4S<bits<2>op0, string asm>
10340 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10343 class CryptoRRRi6<string asm>
10344 : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10345 "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10348 let Inst{24-21} = 0b0100;
10349 let Inst{20-16} = Vm;
10350 let Inst{15-10} = imm;
10351 let Inst{9-5} = Vn;
10352 let Inst{4-0} = Vd;
10355 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10356 : BaseCryptoV82<(outs V128:$Vdst),
10357 (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10358 asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10361 let Inst{24-21} = 0b0010;
10362 let Inst{20-16} = Vm;
10363 let Inst{15} = 0b1;
10364 let Inst{14} = op0;
10365 let Inst{13-12} = imm;
10366 let Inst{11-10} = op1;
10369 //----------------------------------------------------------------------------
10370 // v8.1 atomic instructions extension:
10374 // * LDOPregister<OP>, and aliases STOPregister<OP>
10376 // Instruction encodings:
10378 // 31 30|29 24|23|22|21|20 16|15|14 10|9 5|4 0
10379 // CAS SZ |001000|1 |A |1 |Rs |R |11111 |Rn |Rt
10380 // CASP 0|SZ|001000|0 |A |1 |Rs |R |11111 |Rn |Rt
10381 // SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt
10382 // LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt
10383 // ST SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |11111
10385 // Instruction syntax:
10387 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10388 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10389 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10390 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10391 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10392 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10393 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10394 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10395 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10396 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10398 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10399 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10400 string cstr, list<dag> pattern>
10401 : I<oops, iops, asm, operands, cstr, pattern> {
10409 let Inst{31-30} = Sz;
10410 let Inst{29-24} = 0b001000;
10412 let Inst{22} = Acq;
10413 let Inst{21} = 0b1;
10414 let Inst{20-16} = Rs;
10415 let Inst{15} = Rel;
10416 let Inst{14-10} = 0b11111;
10417 let Inst{9-5} = Rn;
10418 let Inst{4-0} = Rt;
10419 let Predicates = [HasLSE];
10422 class BaseCAS<string order, string size, RegisterClass RC>
10423 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10424 "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10426 Sched<[WriteAtomic]> {
10430 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10431 let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10432 let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10433 let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10434 let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10437 class BaseCASP<string order, string size, RegisterOperand RC>
10438 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10439 "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10441 Sched<[WriteAtomic]> {
10445 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10446 let Sz = 0b00, Acq = Acq, Rel = Rel in
10447 def W : BaseCASP<order, "", WSeqPairClassOperand>;
10448 let Sz = 0b01, Acq = Acq, Rel = Rel in
10449 def X : BaseCASP<order, "", XSeqPairClassOperand>;
10452 let Predicates = [HasLSE] in
10453 class BaseSWP<string order, string size, RegisterClass RC>
10454 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10455 "\t$Rs, $Rt, [$Rn]","",[]>,
10456 Sched<[WriteAtomic]> {
10461 bits<3> opc = 0b000;
10464 let Inst{31-30} = Sz;
10465 let Inst{29-24} = 0b111000;
10466 let Inst{23} = Acq;
10467 let Inst{22} = Rel;
10468 let Inst{21} = 0b1;
10469 let Inst{20-16} = Rs;
10470 let Inst{15} = 0b1;
10471 let Inst{14-12} = opc;
10472 let Inst{11-10} = 0b00;
10473 let Inst{9-5} = Rn;
10474 let Inst{4-0} = Rt;
10475 let Predicates = [HasLSE];
10478 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10479 let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10480 let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10481 let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10482 let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10485 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10486 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10487 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10488 "\t$Rs, $Rt, [$Rn]","",[]>,
10489 Sched<[WriteAtomic]> {
10497 let Inst{31-30} = Sz;
10498 let Inst{29-24} = 0b111000;
10499 let Inst{23} = Acq;
10500 let Inst{22} = Rel;
10501 let Inst{21} = 0b1;
10502 let Inst{20-16} = Rs;
10503 let Inst{15} = 0b0;
10504 let Inst{14-12} = opc;
10505 let Inst{11-10} = 0b00;
10506 let Inst{9-5} = Rn;
10507 let Inst{4-0} = Rt;
10508 let Predicates = [HasLSE];
10511 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10513 let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10514 def B : BaseLDOPregister<op, order, "b", GPR32>;
10515 let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10516 def H : BaseLDOPregister<op, order, "h", GPR32>;
10517 let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10518 def W : BaseLDOPregister<op, order, "", GPR32>;
10519 let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10520 def X : BaseLDOPregister<op, order, "", GPR64>;
10523 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10524 // complex DAG for DstRHS.
10525 let Predicates = [HasLSE] in
10526 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10527 string size, dag SrcRHS, dag DstRHS> {
10528 def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10529 (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10530 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10531 (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10532 def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10533 (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10534 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10535 (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10536 def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10537 (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10540 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10541 string size, dag RHS> {
10542 defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10545 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10546 string size, dag LHS, dag RHS> {
10547 defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10550 multiclass LDOPregister_patterns<string inst, string op> {
10551 defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10552 defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10553 defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10554 defm : LDOPregister_patterns_ord<inst, "B", op, "8", (i32 GPR32:$Rm)>;
10557 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10558 defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10560 (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10561 defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10563 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10564 defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10566 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10567 defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10569 (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10572 let Predicates = [HasLSE] in
10573 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10574 string size, dag OLD, dag NEW> {
10575 def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10576 (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10577 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10578 (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10579 def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10580 (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10581 def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10582 (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10583 def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10584 (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10587 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10588 string size, dag OLD, dag NEW> {
10589 defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10592 multiclass CASregister_patterns<string inst, string op> {
10593 defm : CASregister_patterns_ord<inst, "X", op, "64",
10594 (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10595 defm : CASregister_patterns_ord<inst, "W", op, "32",
10596 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10597 defm : CASregister_patterns_ord<inst, "H", op, "16",
10598 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10599 defm : CASregister_patterns_ord<inst, "B", op, "8",
10600 (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10603 let Predicates = [HasLSE] in
10604 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10605 Instruction inst> :
10606 InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10608 multiclass STOPregister<string asm, string instr> {
10609 def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10610 !cast<Instruction>(instr # "LB")>;
10611 def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10612 !cast<Instruction>(instr # "LH")>;
10613 def : BaseSTOPregister<asm # "l", GPR32, WZR,
10614 !cast<Instruction>(instr # "LW")>;
10615 def : BaseSTOPregister<asm # "l", GPR64, XZR,
10616 !cast<Instruction>(instr # "LX")>;
10617 def : BaseSTOPregister<asm # "b", GPR32, WZR,
10618 !cast<Instruction>(instr # "B")>;
10619 def : BaseSTOPregister<asm # "h", GPR32, WZR,
10620 !cast<Instruction>(instr # "H")>;
10621 def : BaseSTOPregister<asm, GPR32, WZR,
10622 !cast<Instruction>(instr # "W")>;
10623 def : BaseSTOPregister<asm, GPR64, XZR,
10624 !cast<Instruction>(instr # "X")>;
10627 //----------------------------------------------------------------------------
10628 // Allow the size specifier tokens to be upper case, not just lower.
10629 def : TokenAlias<".4B", ".4b">; // Add dot product
10630 def : TokenAlias<".8B", ".8b">;
10631 def : TokenAlias<".4H", ".4h">;
10632 def : TokenAlias<".2S", ".2s">;
10633 def : TokenAlias<".1D", ".1d">;
10634 def : TokenAlias<".16B", ".16b">;
10635 def : TokenAlias<".8H", ".8h">;
10636 def : TokenAlias<".4S", ".4s">;
10637 def : TokenAlias<".2D", ".2d">;
10638 def : TokenAlias<".1Q", ".1q">;
10639 def : TokenAlias<".2H", ".2h">;
10640 def : TokenAlias<".B", ".b">;
10641 def : TokenAlias<".H", ".h">;
10642 def : TokenAlias<".S", ".s">;
10643 def : TokenAlias<".D", ".d">;
10644 def : TokenAlias<".Q", ".q">;