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 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44 : AArch64Inst<PseudoFrm, cstr> {
45 dag OutOperandList = oops;
46 dag InOperandList = iops;
47 let Pattern = pattern;
48 let isCodeGenOnly = 1;
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
53 let Pattern = pattern;
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
60 : EncodedI<cstr, pattern> {
61 dag OutOperandList = oops;
62 dag InOperandList = iops;
63 let AsmString = !strconcat(asm, operands);
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91 let SuperClasses = [ShifterOperand];
92 let Name = "MovImm32Shifter";
93 let RenderMethod = "addShifterOperands";
94 let DiagnosticType = "InvalidMovImm32Shift";
96 def MovImm64ShifterOperand : AsmOperandClass {
97 let SuperClasses = [ShifterOperand];
98 let Name = "MovImm64Shifter";
99 let RenderMethod = "addShifterOperands";
100 let DiagnosticType = "InvalidMovImm64Shift";
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105 let SuperClasses = [ShifterOperand];
106 let Name = "ArithmeticShifter" # width;
107 let PredicateMethod = "isArithmeticShifter<" # width # ">";
108 let RenderMethod = "addShifterOperands";
109 let DiagnosticType = "AddSubRegShift" # width;
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117 let SuperClasses = [ShifterOperand];
118 let Name = "LogicalShifter" # width;
119 let PredicateMethod = "isLogicalShifter<" # width # ">";
120 let RenderMethod = "addShifterOperands";
121 let DiagnosticType = "AddSubRegShift" # width;
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129 let SuperClasses = [ShifterOperand];
130 let Name = "LogicalVecShifter";
131 let RenderMethod = "addShifterOperands";
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134 let SuperClasses = [LogicalVecShifterOperand];
135 let Name = "LogicalVecHalfWordShifter";
136 let RenderMethod = "addShifterOperands";
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141 let SuperClasses = [ShifterOperand];
142 let Name = "MoveVecShifter";
143 let RenderMethod = "addShifterOperands";
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
149 let DiagnosticType = "AddSubRegExtendLarge";
151 def ExtendOperand64 : AsmOperandClass {
152 let SuperClasses = [ExtendOperand];
153 let Name = "Extend64";
154 let DiagnosticType = "AddSubRegExtendSmall";
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158 let SuperClasses = [ExtendOperand];
159 let Name = "ExtendLSL64";
160 let RenderMethod = "addExtend64Operands";
161 let DiagnosticType = "AddSubRegExtendLarge";
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
167 let ParserMethod = "tryParseFPImm";
168 let DiagnosticType = "InvalidFPImm";
171 def CondCode : AsmOperandClass {
172 let Name = "CondCode";
173 let DiagnosticType = "InvalidCondCode";
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178 let Name = "GPR32as64";
180 def GPR32as64 : RegisterOperand<GPR32> {
181 let ParserMatchClass = GPR32as64Operand;
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196 let Name = "AdrpLabel";
197 let ParserMethod = "tryParseAdrpLabel";
198 let DiagnosticType = "InvalidLabel";
200 def adrplabel : Operand<i64> {
201 let EncoderMethod = "getAdrLabelOpValue";
202 let PrintMethod = "printAdrpLabel";
203 let ParserMatchClass = AdrpOperand;
206 def AdrOperand : AsmOperandClass {
207 let Name = "AdrLabel";
208 let ParserMethod = "tryParseAdrLabel";
209 let DiagnosticType = "InvalidLabel";
211 def adrlabel : Operand<i64> {
212 let EncoderMethod = "getAdrLabelOpValue";
213 let ParserMatchClass = AdrOperand;
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
219 let DiagnosticType = "InvalidMemoryIndexedSImm9";
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222 let ParserMatchClass = SImm9Operand;
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228 let Name = "SImm7s" # Scale;
229 let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
236 def simm7s4 : Operand<i32> {
237 let ParserMatchClass = SImm7s4Operand;
238 let PrintMethod = "printImmScale<4>";
241 def simm7s8 : Operand<i32> {
242 let ParserMatchClass = SImm7s8Operand;
243 let PrintMethod = "printImmScale<8>";
246 def simm7s16 : Operand<i32> {
247 let ParserMatchClass = SImm7s16Operand;
248 let PrintMethod = "printImmScale<16>";
251 def am_indexed7s8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
252 def am_indexed7s16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
253 def am_indexed7s32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
254 def am_indexed7s64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
255 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
257 class AsmImmRange<int Low, int High> : AsmOperandClass {
258 let Name = "Imm" # Low # "_" # High;
259 let DiagnosticType = "InvalidImm" # Low # "_" # High;
262 def Imm1_8Operand : AsmImmRange<1, 8>;
263 def Imm1_16Operand : AsmImmRange<1, 16>;
264 def Imm1_32Operand : AsmImmRange<1, 32>;
265 def Imm1_64Operand : AsmImmRange<1, 64>;
267 def MovZSymbolG3AsmOperand : AsmOperandClass {
268 let Name = "MovZSymbolG3";
269 let RenderMethod = "addImmOperands";
272 def movz_symbol_g3 : Operand<i32> {
273 let ParserMatchClass = MovZSymbolG3AsmOperand;
276 def MovZSymbolG2AsmOperand : AsmOperandClass {
277 let Name = "MovZSymbolG2";
278 let RenderMethod = "addImmOperands";
281 def movz_symbol_g2 : Operand<i32> {
282 let ParserMatchClass = MovZSymbolG2AsmOperand;
285 def MovZSymbolG1AsmOperand : AsmOperandClass {
286 let Name = "MovZSymbolG1";
287 let RenderMethod = "addImmOperands";
290 def movz_symbol_g1 : Operand<i32> {
291 let ParserMatchClass = MovZSymbolG1AsmOperand;
294 def MovZSymbolG0AsmOperand : AsmOperandClass {
295 let Name = "MovZSymbolG0";
296 let RenderMethod = "addImmOperands";
299 def movz_symbol_g0 : Operand<i32> {
300 let ParserMatchClass = MovZSymbolG0AsmOperand;
303 def MovKSymbolG3AsmOperand : AsmOperandClass {
304 let Name = "MovKSymbolG3";
305 let RenderMethod = "addImmOperands";
308 def movk_symbol_g3 : Operand<i32> {
309 let ParserMatchClass = MovKSymbolG3AsmOperand;
312 def MovKSymbolG2AsmOperand : AsmOperandClass {
313 let Name = "MovKSymbolG2";
314 let RenderMethod = "addImmOperands";
317 def movk_symbol_g2 : Operand<i32> {
318 let ParserMatchClass = MovKSymbolG2AsmOperand;
321 def MovKSymbolG1AsmOperand : AsmOperandClass {
322 let Name = "MovKSymbolG1";
323 let RenderMethod = "addImmOperands";
326 def movk_symbol_g1 : Operand<i32> {
327 let ParserMatchClass = MovKSymbolG1AsmOperand;
330 def MovKSymbolG0AsmOperand : AsmOperandClass {
331 let Name = "MovKSymbolG0";
332 let RenderMethod = "addImmOperands";
335 def movk_symbol_g0 : Operand<i32> {
336 let ParserMatchClass = MovKSymbolG0AsmOperand;
339 class fixedpoint_i32<ValueType FloatVT>
341 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
342 let EncoderMethod = "getFixedPointScaleOpValue";
343 let DecoderMethod = "DecodeFixedPointScaleImm32";
344 let ParserMatchClass = Imm1_32Operand;
347 class fixedpoint_i64<ValueType FloatVT>
349 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
350 let EncoderMethod = "getFixedPointScaleOpValue";
351 let DecoderMethod = "DecodeFixedPointScaleImm64";
352 let ParserMatchClass = Imm1_64Operand;
355 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
356 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
357 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
359 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
360 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
361 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
363 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
364 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
366 let EncoderMethod = "getVecShiftR8OpValue";
367 let DecoderMethod = "DecodeVecShiftR8Imm";
368 let ParserMatchClass = Imm1_8Operand;
370 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
371 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
373 let EncoderMethod = "getVecShiftR16OpValue";
374 let DecoderMethod = "DecodeVecShiftR16Imm";
375 let ParserMatchClass = Imm1_16Operand;
377 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
378 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
380 let EncoderMethod = "getVecShiftR16OpValue";
381 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
382 let ParserMatchClass = Imm1_8Operand;
384 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
385 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
387 let EncoderMethod = "getVecShiftR32OpValue";
388 let DecoderMethod = "DecodeVecShiftR32Imm";
389 let ParserMatchClass = Imm1_32Operand;
391 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
392 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
394 let EncoderMethod = "getVecShiftR32OpValue";
395 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
396 let ParserMatchClass = Imm1_16Operand;
398 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
399 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
401 let EncoderMethod = "getVecShiftR64OpValue";
402 let DecoderMethod = "DecodeVecShiftR64Imm";
403 let ParserMatchClass = Imm1_64Operand;
405 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
406 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
408 let EncoderMethod = "getVecShiftR64OpValue";
409 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
410 let ParserMatchClass = Imm1_32Operand;
413 def Imm0_1Operand : AsmImmRange<0, 1>;
414 def Imm0_7Operand : AsmImmRange<0, 7>;
415 def Imm0_15Operand : AsmImmRange<0, 15>;
416 def Imm0_31Operand : AsmImmRange<0, 31>;
417 def Imm0_63Operand : AsmImmRange<0, 63>;
419 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
420 return (((uint32_t)Imm) < 8);
422 let EncoderMethod = "getVecShiftL8OpValue";
423 let DecoderMethod = "DecodeVecShiftL8Imm";
424 let ParserMatchClass = Imm0_7Operand;
426 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
427 return (((uint32_t)Imm) < 16);
429 let EncoderMethod = "getVecShiftL16OpValue";
430 let DecoderMethod = "DecodeVecShiftL16Imm";
431 let ParserMatchClass = Imm0_15Operand;
433 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
434 return (((uint32_t)Imm) < 32);
436 let EncoderMethod = "getVecShiftL32OpValue";
437 let DecoderMethod = "DecodeVecShiftL32Imm";
438 let ParserMatchClass = Imm0_31Operand;
440 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
441 return (((uint32_t)Imm) < 64);
443 let EncoderMethod = "getVecShiftL64OpValue";
444 let DecoderMethod = "DecodeVecShiftL64Imm";
445 let ParserMatchClass = Imm0_63Operand;
449 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
450 // instructions for splatting repeating bit patterns across the immediate.
451 def logical_imm32_XFORM : SDNodeXForm<imm, [{
452 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
453 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
455 def logical_imm64_XFORM : SDNodeXForm<imm, [{
456 uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
457 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
460 let DiagnosticType = "LogicalSecondSource" in {
461 def LogicalImm32Operand : AsmOperandClass {
462 let Name = "LogicalImm32";
464 def LogicalImm64Operand : AsmOperandClass {
465 let Name = "LogicalImm64";
467 def LogicalImm32NotOperand : AsmOperandClass {
468 let Name = "LogicalImm32Not";
470 def LogicalImm64NotOperand : AsmOperandClass {
471 let Name = "LogicalImm64Not";
474 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
475 return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
476 }], logical_imm32_XFORM> {
477 let PrintMethod = "printLogicalImm32";
478 let ParserMatchClass = LogicalImm32Operand;
480 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
481 return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
482 }], logical_imm64_XFORM> {
483 let PrintMethod = "printLogicalImm64";
484 let ParserMatchClass = LogicalImm64Operand;
486 def logical_imm32_not : Operand<i32> {
487 let ParserMatchClass = LogicalImm32NotOperand;
489 def logical_imm64_not : Operand<i64> {
490 let ParserMatchClass = LogicalImm64NotOperand;
493 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
494 def Imm0_65535Operand : AsmImmRange<0, 65535>;
495 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
496 return ((uint32_t)Imm) < 65536;
498 let ParserMatchClass = Imm0_65535Operand;
499 let PrintMethod = "printHexImm";
502 // imm0_255 predicate - True if the immediate is in the range [0,255].
503 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
504 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
505 return ((uint32_t)Imm) < 256;
507 let ParserMatchClass = Imm0_255Operand;
508 let PrintMethod = "printHexImm";
511 // imm0_127 predicate - True if the immediate is in the range [0,127]
512 def Imm0_127Operand : AsmImmRange<0, 127>;
513 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
514 return ((uint32_t)Imm) < 128;
516 let ParserMatchClass = Imm0_127Operand;
517 let PrintMethod = "printHexImm";
520 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
521 // for all shift-amounts.
523 // imm0_63 predicate - True if the immediate is in the range [0,63]
524 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
525 return ((uint64_t)Imm) < 64;
527 let ParserMatchClass = Imm0_63Operand;
530 // imm0_31 predicate - True if the immediate is in the range [0,31]
531 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
532 return ((uint64_t)Imm) < 32;
534 let ParserMatchClass = Imm0_31Operand;
537 // True if the 32-bit immediate is in the range [0,31]
538 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
539 return ((uint64_t)Imm) < 32;
541 let ParserMatchClass = Imm0_31Operand;
544 // imm0_1 predicate - True if the immediate is in the range [0,1]
545 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
546 return ((uint64_t)Imm) < 2;
548 let ParserMatchClass = Imm0_1Operand;
551 // imm0_15 predicate - True if the immediate is in the range [0,15]
552 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
553 return ((uint64_t)Imm) < 16;
555 let ParserMatchClass = Imm0_15Operand;
558 // imm0_7 predicate - True if the immediate is in the range [0,7]
559 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
560 return ((uint64_t)Imm) < 8;
562 let ParserMatchClass = Imm0_7Operand;
565 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
566 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
567 return ((uint32_t)Imm) < 16;
569 let ParserMatchClass = Imm0_15Operand;
572 // An arithmetic shifter operand:
573 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
575 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
576 let PrintMethod = "printShifter";
577 let ParserMatchClass = !cast<AsmOperandClass>(
578 "ArithmeticShifterOperand" # width);
581 def arith_shift32 : arith_shift<i32, 32>;
582 def arith_shift64 : arith_shift<i64, 64>;
584 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
586 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
587 let PrintMethod = "printShiftedRegister";
588 let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
591 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
592 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
594 // An arithmetic shifter operand:
595 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
597 class logical_shift<int width> : Operand<i32> {
598 let PrintMethod = "printShifter";
599 let ParserMatchClass = !cast<AsmOperandClass>(
600 "LogicalShifterOperand" # width);
603 def logical_shift32 : logical_shift<32>;
604 def logical_shift64 : logical_shift<64>;
606 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
608 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
609 let PrintMethod = "printShiftedRegister";
610 let MIOperandInfo = (ops regclass, shiftop);
613 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
614 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
616 // A logical vector shifter operand:
617 // {7-6} - shift type: 00 = lsl
618 // {5-0} - imm6: #0, #8, #16, or #24
619 def logical_vec_shift : Operand<i32> {
620 let PrintMethod = "printShifter";
621 let EncoderMethod = "getVecShifterOpValue";
622 let ParserMatchClass = LogicalVecShifterOperand;
625 // A logical vector half-word shifter operand:
626 // {7-6} - shift type: 00 = lsl
627 // {5-0} - imm6: #0 or #8
628 def logical_vec_hw_shift : Operand<i32> {
629 let PrintMethod = "printShifter";
630 let EncoderMethod = "getVecShifterOpValue";
631 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
634 // A vector move shifter operand:
635 // {0} - imm1: #8 or #16
636 def move_vec_shift : Operand<i32> {
637 let PrintMethod = "printShifter";
638 let EncoderMethod = "getMoveVecShifterOpValue";
639 let ParserMatchClass = MoveVecShifterOperand;
642 let DiagnosticType = "AddSubSecondSource" in {
643 def AddSubImmOperand : AsmOperandClass {
644 let Name = "AddSubImm";
645 let ParserMethod = "tryParseAddSubImm";
647 def AddSubImmNegOperand : AsmOperandClass {
648 let Name = "AddSubImmNeg";
649 let ParserMethod = "tryParseAddSubImm";
652 // An ADD/SUB immediate shifter operand:
654 // {7-6} - shift type: 00 = lsl
655 // {5-0} - imm6: #0 or #12
656 class addsub_shifted_imm<ValueType Ty>
657 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
658 let PrintMethod = "printAddSubImm";
659 let EncoderMethod = "getAddSubImmOpValue";
660 let ParserMatchClass = AddSubImmOperand;
661 let MIOperandInfo = (ops i32imm, i32imm);
664 class addsub_shifted_imm_neg<ValueType Ty>
666 let EncoderMethod = "getAddSubImmOpValue";
667 let ParserMatchClass = AddSubImmNegOperand;
668 let MIOperandInfo = (ops i32imm, i32imm);
671 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
672 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
673 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
674 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
676 class neg_addsub_shifted_imm<ValueType Ty>
677 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
678 let PrintMethod = "printAddSubImm";
679 let EncoderMethod = "getAddSubImmOpValue";
680 let ParserMatchClass = AddSubImmOperand;
681 let MIOperandInfo = (ops i32imm, i32imm);
684 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
685 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
687 // An extend operand:
688 // {5-3} - extend type
690 def arith_extend : Operand<i32> {
691 let PrintMethod = "printArithExtend";
692 let ParserMatchClass = ExtendOperand;
694 def arith_extend64 : Operand<i32> {
695 let PrintMethod = "printArithExtend";
696 let ParserMatchClass = ExtendOperand64;
699 // 'extend' that's a lsl of a 64-bit register.
700 def arith_extendlsl64 : Operand<i32> {
701 let PrintMethod = "printArithExtend";
702 let ParserMatchClass = ExtendOperandLSL64;
705 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
706 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
707 let PrintMethod = "printExtendedRegister";
708 let MIOperandInfo = (ops GPR32, arith_extend);
711 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
712 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
713 let PrintMethod = "printExtendedRegister";
714 let MIOperandInfo = (ops GPR32, arith_extend64);
717 // Floating-point immediate.
718 def fpimm16 : Operand<f16>,
719 PatLeaf<(f16 fpimm), [{
720 return AArch64_AM::getFP16Imm(N->getValueAPF()) != -1;
721 }], SDNodeXForm<fpimm, [{
722 APFloat InVal = N->getValueAPF();
723 uint32_t enc = AArch64_AM::getFP16Imm(InVal);
724 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
726 let ParserMatchClass = FPImmOperand;
727 let PrintMethod = "printFPImmOperand";
729 def fpimm32 : Operand<f32>,
730 PatLeaf<(f32 fpimm), [{
731 return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
732 }], SDNodeXForm<fpimm, [{
733 APFloat InVal = N->getValueAPF();
734 uint32_t enc = AArch64_AM::getFP32Imm(InVal);
735 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
737 let ParserMatchClass = FPImmOperand;
738 let PrintMethod = "printFPImmOperand";
740 def fpimm64 : Operand<f64>,
741 PatLeaf<(f64 fpimm), [{
742 return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
743 }], SDNodeXForm<fpimm, [{
744 APFloat InVal = N->getValueAPF();
745 uint32_t enc = AArch64_AM::getFP64Imm(InVal);
746 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
748 let ParserMatchClass = FPImmOperand;
749 let PrintMethod = "printFPImmOperand";
752 def fpimm8 : Operand<i32> {
753 let ParserMatchClass = FPImmOperand;
754 let PrintMethod = "printFPImmOperand";
757 def fpimm0 : PatLeaf<(fpimm), [{
758 return N->isExactlyValue(+0.0);
761 // Vector lane operands
762 class AsmVectorIndex<string Suffix> : AsmOperandClass {
763 let Name = "VectorIndex" # Suffix;
764 let DiagnosticType = "InvalidIndex" # Suffix;
766 def VectorIndex1Operand : AsmVectorIndex<"1">;
767 def VectorIndexBOperand : AsmVectorIndex<"B">;
768 def VectorIndexHOperand : AsmVectorIndex<"H">;
769 def VectorIndexSOperand : AsmVectorIndex<"S">;
770 def VectorIndexDOperand : AsmVectorIndex<"D">;
772 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
773 return ((uint64_t)Imm) == 1;
775 let ParserMatchClass = VectorIndex1Operand;
776 let PrintMethod = "printVectorIndex";
777 let MIOperandInfo = (ops i64imm);
779 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
780 return ((uint64_t)Imm) < 16;
782 let ParserMatchClass = VectorIndexBOperand;
783 let PrintMethod = "printVectorIndex";
784 let MIOperandInfo = (ops i64imm);
786 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
787 return ((uint64_t)Imm) < 8;
789 let ParserMatchClass = VectorIndexHOperand;
790 let PrintMethod = "printVectorIndex";
791 let MIOperandInfo = (ops i64imm);
793 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
794 return ((uint64_t)Imm) < 4;
796 let ParserMatchClass = VectorIndexSOperand;
797 let PrintMethod = "printVectorIndex";
798 let MIOperandInfo = (ops i64imm);
800 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
801 return ((uint64_t)Imm) < 2;
803 let ParserMatchClass = VectorIndexDOperand;
804 let PrintMethod = "printVectorIndex";
805 let MIOperandInfo = (ops i64imm);
808 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
809 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
810 // are encoded as the eight bit value 'abcdefgh'.
811 def simdimmtype10 : Operand<i32>,
812 PatLeaf<(f64 fpimm), [{
813 return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
816 }], SDNodeXForm<fpimm, [{
817 APFloat InVal = N->getValueAPF();
818 uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
821 return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
823 let ParserMatchClass = SIMDImmType10Operand;
824 let PrintMethod = "printSIMDType10Operand";
832 // Base encoding for system instruction operands.
833 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
834 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
835 list<dag> pattern = []>
836 : I<oops, iops, asm, operands, "", pattern> {
837 let Inst{31-22} = 0b1101010100;
841 // System instructions which do not have an Rt register.
842 class SimpleSystemI<bit L, dag iops, string asm, string operands,
843 list<dag> pattern = []>
844 : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
845 let Inst{4-0} = 0b11111;
848 // System instructions which have an Rt register.
849 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
850 : BaseSystemI<L, oops, iops, asm, operands>,
856 // Hint instructions that take both a CRm and a 3-bit immediate.
857 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
858 // model patterns with sufficiently fine granularity
859 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
860 class HintI<string mnemonic>
861 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
862 [(int_aarch64_hint imm0_127:$imm)]>,
865 let Inst{20-12} = 0b000110010;
866 let Inst{11-5} = imm;
869 // System instructions taking a single literal operand which encodes into
870 // CRm. op2 differentiates the opcodes.
871 def BarrierAsmOperand : AsmOperandClass {
872 let Name = "Barrier";
873 let ParserMethod = "tryParseBarrierOperand";
875 def barrier_op : Operand<i32> {
876 let PrintMethod = "printBarrierOption";
877 let ParserMatchClass = BarrierAsmOperand;
879 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
880 list<dag> pattern = []>
881 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
882 Sched<[WriteBarrier]> {
884 let Inst{20-12} = 0b000110011;
885 let Inst{11-8} = CRm;
889 // MRS/MSR system instructions. These have different operand classes because
890 // a different subset of registers can be accessed through each instruction.
891 def MRSSystemRegisterOperand : AsmOperandClass {
892 let Name = "MRSSystemRegister";
893 let ParserMethod = "tryParseSysReg";
894 let DiagnosticType = "MRS";
896 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
897 def mrs_sysreg_op : Operand<i32> {
898 let ParserMatchClass = MRSSystemRegisterOperand;
899 let DecoderMethod = "DecodeMRSSystemRegister";
900 let PrintMethod = "printMRSSystemRegister";
903 def MSRSystemRegisterOperand : AsmOperandClass {
904 let Name = "MSRSystemRegister";
905 let ParserMethod = "tryParseSysReg";
906 let DiagnosticType = "MSR";
908 def msr_sysreg_op : Operand<i32> {
909 let ParserMatchClass = MSRSystemRegisterOperand;
910 let DecoderMethod = "DecodeMSRSystemRegister";
911 let PrintMethod = "printMSRSystemRegister";
914 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
915 "mrs", "\t$Rt, $systemreg"> {
917 let Inst{20-5} = systemreg;
920 // FIXME: Some of these def NZCV, others don't. Best way to model that?
921 // Explicitly modeling each of the system register as a register class
922 // would do it, but feels like overkill at this point.
923 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
924 "msr", "\t$systemreg, $Rt"> {
926 let Inst{20-5} = systemreg;
929 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
930 let Name = "SystemPStateFieldWithImm0_15";
931 let ParserMethod = "tryParseSysReg";
933 def pstatefield4_op : Operand<i32> {
934 let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
935 let PrintMethod = "printSystemPStateField";
939 class MSRpstateImm0_15
940 : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
941 "msr", "\t$pstatefield, $imm">,
945 let Inst{20-19} = 0b00;
946 let Inst{18-16} = pstatefield{5-3};
947 let Inst{15-12} = 0b0100;
948 let Inst{11-8} = imm;
949 let Inst{7-5} = pstatefield{2-0};
951 let DecoderMethod = "DecodeSystemPStateInstruction";
952 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
953 // Fail the decoder should attempt to decode the instruction as MSRI.
954 let hasCompleteDecoder = 0;
957 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
958 let Name = "SystemPStateFieldWithImm0_1";
959 let ParserMethod = "tryParseSysReg";
961 def pstatefield1_op : Operand<i32> {
962 let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
963 let PrintMethod = "printSystemPStateField";
967 class MSRpstateImm0_1
968 : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
969 "msr", "\t$pstatefield, $imm">,
973 let Inst{20-19} = 0b00;
974 let Inst{18-16} = pstatefield{5-3};
975 let Inst{15-9} = 0b0100000;
977 let Inst{7-5} = pstatefield{2-0};
979 let DecoderMethod = "DecodeSystemPStateInstruction";
980 // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
981 // Fail the decoder should attempt to decode the instruction as MSRI.
982 let hasCompleteDecoder = 0;
985 // SYS and SYSL generic system instructions.
986 def SysCRAsmOperand : AsmOperandClass {
988 let ParserMethod = "tryParseSysCROperand";
991 def sys_cr_op : Operand<i32> {
992 let PrintMethod = "printSysCROperand";
993 let ParserMatchClass = SysCRAsmOperand;
996 class SystemXtI<bit L, string asm>
997 : RtSystemI<L, (outs),
998 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
999 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1004 let Inst{20-19} = 0b01;
1005 let Inst{18-16} = op1;
1006 let Inst{15-12} = Cn;
1007 let Inst{11-8} = Cm;
1008 let Inst{7-5} = op2;
1011 class SystemLXtI<bit L, string asm>
1012 : RtSystemI<L, (outs),
1013 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1014 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1019 let Inst{20-19} = 0b01;
1020 let Inst{18-16} = op1;
1021 let Inst{15-12} = Cn;
1022 let Inst{11-8} = Cm;
1023 let Inst{7-5} = op2;
1027 // Branch (register) instructions:
1035 // otherwise UNDEFINED
1036 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1037 string operands, list<dag> pattern>
1038 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1039 let Inst{31-25} = 0b1101011;
1040 let Inst{24-21} = opc;
1041 let Inst{20-16} = 0b11111;
1042 let Inst{15-10} = 0b000000;
1043 let Inst{4-0} = 0b00000;
1046 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1047 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1052 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1053 class SpecialReturn<bits<4> opc, string asm>
1054 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1055 let Inst{9-5} = 0b11111;
1059 // Conditional branch instruction.
1063 // 4-bit immediate. Pretty-printed as <cc>
1064 def ccode : Operand<i32> {
1065 let PrintMethod = "printCondCode";
1066 let ParserMatchClass = CondCode;
1068 def inv_ccode : Operand<i32> {
1069 // AL and NV are invalid in the aliases which use inv_ccode
1070 let PrintMethod = "printInverseCondCode";
1071 let ParserMatchClass = CondCode;
1072 let MCOperandPredicate = [{
1073 return MCOp.isImm() &&
1074 MCOp.getImm() != AArch64CC::AL &&
1075 MCOp.getImm() != AArch64CC::NV;
1079 // Conditional branch target. 19-bit immediate. The low two bits of the target
1080 // offset are implied zero and so are not part of the immediate.
1081 def PCRelLabel19Operand : AsmOperandClass {
1082 let Name = "PCRelLabel19";
1083 let DiagnosticType = "InvalidLabel";
1085 def am_brcond : Operand<OtherVT> {
1086 let EncoderMethod = "getCondBranchTargetOpValue";
1087 let DecoderMethod = "DecodePCRelLabel19";
1088 let PrintMethod = "printAlignedLabel";
1089 let ParserMatchClass = PCRelLabel19Operand;
1092 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1093 "b", ".$cond\t$target", "",
1094 [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1097 let isTerminator = 1;
1102 let Inst{31-24} = 0b01010100;
1103 let Inst{23-5} = target;
1105 let Inst{3-0} = cond;
1109 // Compare-and-branch instructions.
1111 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1112 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1113 asm, "\t$Rt, $target", "",
1114 [(node regtype:$Rt, bb:$target)]>,
1117 let isTerminator = 1;
1121 let Inst{30-25} = 0b011010;
1123 let Inst{23-5} = target;
1127 multiclass CmpBranch<bit op, string asm, SDNode node> {
1128 def W : BaseCmpBranch<GPR32, op, asm, node> {
1131 def X : BaseCmpBranch<GPR64, op, asm, node> {
1137 // Test-bit-and-branch instructions.
1139 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1140 // the target offset are implied zero and so are not part of the immediate.
1141 def BranchTarget14Operand : AsmOperandClass {
1142 let Name = "BranchTarget14";
1144 def am_tbrcond : Operand<OtherVT> {
1145 let EncoderMethod = "getTestBranchTargetOpValue";
1146 let PrintMethod = "printAlignedLabel";
1147 let ParserMatchClass = BranchTarget14Operand;
1150 // AsmOperand classes to emit (or not) special diagnostics
1151 def TBZImm0_31Operand : AsmOperandClass {
1152 let Name = "TBZImm0_31";
1153 let PredicateMethod = "isImm0_31";
1154 let RenderMethod = "addImm0_31Operands";
1156 def TBZImm32_63Operand : AsmOperandClass {
1157 let Name = "Imm32_63";
1158 let DiagnosticType = "InvalidImm0_63";
1161 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1162 return (((uint32_t)Imm) < 32);
1164 let ParserMatchClass = matcher;
1167 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1168 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1170 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1171 return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1173 let ParserMatchClass = TBZImm32_63Operand;
1176 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1177 bit op, string asm, SDNode node>
1178 : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1179 asm, "\t$Rt, $bit_off, $target", "",
1180 [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1183 let isTerminator = 1;
1189 let Inst{30-25} = 0b011011;
1191 let Inst{23-19} = bit_off{4-0};
1192 let Inst{18-5} = target;
1195 let DecoderMethod = "DecodeTestAndBranch";
1198 multiclass TestBranch<bit op, string asm, SDNode node> {
1199 def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1203 def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1207 // Alias X-reg with 0-31 imm to W-Reg.
1208 def : InstAlias<asm # "\t$Rd, $imm, $target",
1209 (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1210 tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1211 def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1212 (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1213 tbz_imm0_31_diag:$imm, bb:$target)>;
1217 // Unconditional branch (immediate) instructions.
1219 def BranchTarget26Operand : AsmOperandClass {
1220 let Name = "BranchTarget26";
1221 let DiagnosticType = "InvalidLabel";
1223 def am_b_target : Operand<OtherVT> {
1224 let EncoderMethod = "getBranchTargetOpValue";
1225 let PrintMethod = "printAlignedLabel";
1226 let ParserMatchClass = BranchTarget26Operand;
1228 def am_bl_target : Operand<i64> {
1229 let EncoderMethod = "getBranchTargetOpValue";
1230 let PrintMethod = "printAlignedLabel";
1231 let ParserMatchClass = BranchTarget26Operand;
1234 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1235 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1238 let Inst{30-26} = 0b00101;
1239 let Inst{25-0} = addr;
1241 let DecoderMethod = "DecodeUnconditionalBranch";
1244 class BranchImm<bit op, string asm, list<dag> pattern>
1245 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1246 class CallImm<bit op, string asm, list<dag> pattern>
1247 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1250 // Basic one-operand data processing instructions.
1253 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1254 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1255 SDPatternOperator node>
1256 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1257 [(set regtype:$Rd, (node regtype:$Rn))]>,
1258 Sched<[WriteI, ReadI]> {
1262 let Inst{30-13} = 0b101101011000000000;
1263 let Inst{12-10} = opc;
1268 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1269 multiclass OneOperandData<bits<3> opc, string asm,
1270 SDPatternOperator node = null_frag> {
1271 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1275 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1280 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1281 : BaseOneOperandData<opc, GPR32, asm, node> {
1285 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1286 : BaseOneOperandData<opc, GPR64, asm, node> {
1291 // Basic two-operand data processing instructions.
1293 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1295 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1296 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1297 Sched<[WriteI, ReadI, ReadI]> {
1302 let Inst{30} = isSub;
1303 let Inst{28-21} = 0b11010000;
1304 let Inst{20-16} = Rm;
1305 let Inst{15-10} = 0;
1310 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1312 : BaseBaseAddSubCarry<isSub, regtype, asm,
1313 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1315 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1317 : BaseBaseAddSubCarry<isSub, regtype, asm,
1318 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1323 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1324 SDNode OpNode, SDNode OpNode_setflags> {
1325 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1329 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1335 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1340 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1347 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1348 SDPatternOperator OpNode>
1349 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1350 asm, "\t$Rd, $Rn, $Rm", "",
1351 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1355 let Inst{30-21} = 0b0011010110;
1356 let Inst{20-16} = Rm;
1357 let Inst{15-14} = 0b00;
1358 let Inst{13-10} = opc;
1363 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1364 SDPatternOperator OpNode>
1365 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1366 let Inst{10} = isSigned;
1369 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1370 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1371 Sched<[WriteID32, ReadID, ReadID]> {
1374 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1375 Sched<[WriteID64, ReadID, ReadID]> {
1380 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1381 SDPatternOperator OpNode = null_frag>
1382 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1383 Sched<[WriteIS, ReadI]> {
1384 let Inst{11-10} = shift_type;
1387 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1388 def Wr : BaseShift<shift_type, GPR32, asm> {
1392 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1396 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1397 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1398 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1400 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1401 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1403 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1404 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1406 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1407 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1410 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1411 : InstAlias<asm#"\t$dst, $src1, $src2",
1412 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1414 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1415 RegisterClass addtype, string asm,
1417 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1418 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1423 let Inst{30-24} = 0b0011011;
1424 let Inst{23-21} = opc;
1425 let Inst{20-16} = Rm;
1426 let Inst{15} = isSub;
1427 let Inst{14-10} = Ra;
1432 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1433 // MADD/MSUB generation is decided by MachineCombiner.cpp
1434 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1435 [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1436 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1440 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1441 [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1442 Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1447 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1448 SDNode AccNode, SDNode ExtNode>
1449 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1450 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1451 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1452 Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1456 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1457 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1458 asm, "\t$Rd, $Rn, $Rm", "",
1459 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1460 Sched<[WriteIM64, ReadIM, ReadIM]> {
1464 let Inst{31-24} = 0b10011011;
1465 let Inst{23-21} = opc;
1466 let Inst{20-16} = Rm;
1471 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1472 // (i.e. all bits 1) but is ignored by the processor.
1473 let PostEncoderMethod = "fixMulHigh";
1476 class MulAccumWAlias<string asm, Instruction inst>
1477 : InstAlias<asm#"\t$dst, $src1, $src2",
1478 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1479 class MulAccumXAlias<string asm, Instruction inst>
1480 : InstAlias<asm#"\t$dst, $src1, $src2",
1481 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1482 class WideMulAccumAlias<string asm, Instruction inst>
1483 : InstAlias<asm#"\t$dst, $src1, $src2",
1484 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1486 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1487 SDPatternOperator OpNode, string asm>
1488 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1489 asm, "\t$Rd, $Rn, $Rm", "",
1490 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1491 Sched<[WriteISReg, ReadI, ReadISReg]> {
1497 let Inst{30-21} = 0b0011010110;
1498 let Inst{20-16} = Rm;
1499 let Inst{15-13} = 0b010;
1501 let Inst{11-10} = sz;
1504 let Predicates = [HasCRC];
1508 // Address generation.
1511 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1512 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1517 let Inst{31} = page;
1518 let Inst{30-29} = label{1-0};
1519 let Inst{28-24} = 0b10000;
1520 let Inst{23-5} = label{20-2};
1523 let DecoderMethod = "DecodeAdrInstruction";
1530 def movimm32_imm : Operand<i32> {
1531 let ParserMatchClass = Imm0_65535Operand;
1532 let EncoderMethod = "getMoveWideImmOpValue";
1533 let PrintMethod = "printHexImm";
1535 def movimm32_shift : Operand<i32> {
1536 let PrintMethod = "printShifter";
1537 let ParserMatchClass = MovImm32ShifterOperand;
1539 def movimm64_shift : Operand<i32> {
1540 let PrintMethod = "printShifter";
1541 let ParserMatchClass = MovImm64ShifterOperand;
1544 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1545 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1547 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1548 asm, "\t$Rd, $imm$shift", "", []>,
1553 let Inst{30-29} = opc;
1554 let Inst{28-23} = 0b100101;
1555 let Inst{22-21} = shift{5-4};
1556 let Inst{20-5} = imm;
1559 let DecoderMethod = "DecodeMoveImmInstruction";
1562 multiclass MoveImmediate<bits<2> opc, string asm> {
1563 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1567 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1572 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1573 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1575 : I<(outs regtype:$Rd),
1576 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1577 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1578 Sched<[WriteI, ReadI]> {
1582 let Inst{30-29} = opc;
1583 let Inst{28-23} = 0b100101;
1584 let Inst{22-21} = shift{5-4};
1585 let Inst{20-5} = imm;
1588 let DecoderMethod = "DecodeMoveImmInstruction";
1591 multiclass InsertImmediate<bits<2> opc, string asm> {
1592 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1596 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1605 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1606 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1607 string asm, SDPatternOperator OpNode>
1608 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1609 asm, "\t$Rd, $Rn, $imm", "",
1610 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1611 Sched<[WriteI, ReadI]> {
1615 let Inst{30} = isSub;
1616 let Inst{29} = setFlags;
1617 let Inst{28-24} = 0b10001;
1618 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1619 let Inst{21-10} = imm{11-0};
1622 let DecoderMethod = "DecodeBaseAddSubImm";
1625 class BaseAddSubRegPseudo<RegisterClass regtype,
1626 SDPatternOperator OpNode>
1627 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1628 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1629 Sched<[WriteI, ReadI, ReadI]>;
1631 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1632 arith_shifted_reg shifted_regtype, string asm,
1633 SDPatternOperator OpNode>
1634 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1635 asm, "\t$Rd, $Rn, $Rm", "",
1636 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1637 Sched<[WriteISReg, ReadI, ReadISReg]> {
1638 // The operands are in order to match the 'addr' MI operands, so we
1639 // don't need an encoder method and by-name matching. Just use the default
1640 // in-order handling. Since we're using by-order, make sure the names
1646 let Inst{30} = isSub;
1647 let Inst{29} = setFlags;
1648 let Inst{28-24} = 0b01011;
1649 let Inst{23-22} = shift{7-6};
1651 let Inst{20-16} = src2;
1652 let Inst{15-10} = shift{5-0};
1653 let Inst{9-5} = src1;
1654 let Inst{4-0} = dst;
1656 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1659 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1660 RegisterClass src1Regtype, Operand src2Regtype,
1661 string asm, SDPatternOperator OpNode>
1662 : I<(outs dstRegtype:$R1),
1663 (ins src1Regtype:$R2, src2Regtype:$R3),
1664 asm, "\t$R1, $R2, $R3", "",
1665 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1666 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1671 let Inst{30} = isSub;
1672 let Inst{29} = setFlags;
1673 let Inst{28-24} = 0b01011;
1674 let Inst{23-21} = 0b001;
1675 let Inst{20-16} = Rm;
1676 let Inst{15-13} = ext{5-3};
1677 let Inst{12-10} = ext{2-0};
1681 let DecoderMethod = "DecodeAddSubERegInstruction";
1684 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1685 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1686 RegisterClass src1Regtype, RegisterClass src2Regtype,
1687 Operand ext_op, string asm>
1688 : I<(outs dstRegtype:$Rd),
1689 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1690 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1691 Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1696 let Inst{30} = isSub;
1697 let Inst{29} = setFlags;
1698 let Inst{28-24} = 0b01011;
1699 let Inst{23-21} = 0b001;
1700 let Inst{20-16} = Rm;
1701 let Inst{15} = ext{5};
1702 let Inst{12-10} = ext{2-0};
1706 let DecoderMethod = "DecodeAddSubERegInstruction";
1709 // Aliases for register+register add/subtract.
1710 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1711 RegisterClass src1Regtype, RegisterClass src2Regtype,
1713 : InstAlias<asm#"\t$dst, $src1, $src2",
1714 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1717 multiclass AddSub<bit isSub, string mnemonic, string alias,
1718 SDPatternOperator OpNode = null_frag> {
1719 let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1720 // Add/Subtract immediate
1721 // Increase the weight of the immediate variant to try to match it before
1722 // the extended register variant.
1723 // We used to match the register variant before the immediate when the
1724 // register argument could be implicitly zero-extended.
1725 let AddedComplexity = 6 in
1726 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1730 let AddedComplexity = 6 in
1731 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1736 // Add/Subtract register - Only used for CodeGen
1737 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1738 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1740 // Add/Subtract shifted register
1741 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1745 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1751 // Add/Subtract extended register
1752 let AddedComplexity = 1, hasSideEffects = 0 in {
1753 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1754 arith_extended_reg32<i32>, mnemonic, OpNode> {
1757 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1758 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1763 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1764 arith_extendlsl64, mnemonic> {
1765 // UXTX and SXTX only.
1766 let Inst{14-13} = 0b11;
1770 // add Rd, Rb, -imm -> sub Rd, Rn, imm
1771 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1772 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1773 addsub_shifted_imm32_neg:$imm), 0>;
1774 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1775 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1776 addsub_shifted_imm64_neg:$imm), 0>;
1778 // Register/register aliases with no shift when SP is not used.
1779 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1780 GPR32, GPR32, GPR32, 0>;
1781 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1782 GPR64, GPR64, GPR64, 0>;
1784 // Register/register aliases with no shift when either the destination or
1785 // first source register is SP.
1786 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1787 GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1788 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1789 GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1790 def : AddSubRegAlias<mnemonic,
1791 !cast<Instruction>(NAME#"Xrx64"),
1792 GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1793 def : AddSubRegAlias<mnemonic,
1794 !cast<Instruction>(NAME#"Xrx64"),
1795 GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1798 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1799 string alias, string cmpAlias> {
1800 let isCompare = 1, Defs = [NZCV] in {
1801 // Add/Subtract immediate
1802 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1806 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1811 // Add/Subtract register
1812 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1813 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1815 // Add/Subtract shifted register
1816 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1820 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1825 // Add/Subtract extended register
1826 let AddedComplexity = 1 in {
1827 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1828 arith_extended_reg32<i32>, mnemonic, OpNode> {
1831 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1832 arith_extended_reg32<i64>, mnemonic, OpNode> {
1837 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1838 arith_extendlsl64, mnemonic> {
1839 // UXTX and SXTX only.
1840 let Inst{14-13} = 0b11;
1845 // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1846 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1847 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1848 addsub_shifted_imm32_neg:$imm), 0>;
1849 def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1850 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1851 addsub_shifted_imm64_neg:$imm), 0>;
1854 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1855 WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1856 def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1857 XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1858 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1859 WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1860 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1861 XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1862 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1863 XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1864 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1865 WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1866 def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1867 XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1869 // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1870 def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1871 WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1872 def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1873 XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1875 // Compare shorthands
1876 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1877 WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1878 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1879 XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1880 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1881 WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1882 def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1883 XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1885 // Register/register aliases with no shift when SP is not used.
1886 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1887 GPR32, GPR32, GPR32, 0>;
1888 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1889 GPR64, GPR64, GPR64, 0>;
1891 // Register/register aliases with no shift when the first source register
1893 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1894 GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1895 def : AddSubRegAlias<mnemonic,
1896 !cast<Instruction>(NAME#"Xrx64"),
1897 GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1903 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1905 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1907 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1909 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1910 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1911 Sched<[WriteExtr, ReadExtrHi]> {
1917 let Inst{30-23} = 0b00100111;
1919 let Inst{20-16} = Rm;
1920 let Inst{15-10} = imm;
1925 multiclass ExtractImm<string asm> {
1926 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1928 (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1931 // imm<5> must be zero.
1934 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1936 (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1947 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1948 class BaseBitfieldImm<bits<2> opc,
1949 RegisterClass regtype, Operand imm_type, string asm>
1950 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1951 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1952 Sched<[WriteIS, ReadI]> {
1958 let Inst{30-29} = opc;
1959 let Inst{28-23} = 0b100110;
1960 let Inst{21-16} = immr;
1961 let Inst{15-10} = imms;
1966 multiclass BitfieldImm<bits<2> opc, string asm> {
1967 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1970 // imms<5> and immr<5> must be zero, else ReservedValue().
1974 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1980 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1981 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1982 RegisterClass regtype, Operand imm_type, string asm>
1983 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1985 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1986 Sched<[WriteIS, ReadI]> {
1992 let Inst{30-29} = opc;
1993 let Inst{28-23} = 0b100110;
1994 let Inst{21-16} = immr;
1995 let Inst{15-10} = imms;
2000 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2001 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2004 // imms<5> and immr<5> must be zero, else ReservedValue().
2008 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2018 // Logical (immediate)
2019 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2020 RegisterClass sregtype, Operand imm_type, string asm,
2022 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2023 asm, "\t$Rd, $Rn, $imm", "", pattern>,
2024 Sched<[WriteI, ReadI]> {
2028 let Inst{30-29} = opc;
2029 let Inst{28-23} = 0b100100;
2030 let Inst{22} = imm{12};
2031 let Inst{21-16} = imm{11-6};
2032 let Inst{15-10} = imm{5-0};
2036 let DecoderMethod = "DecodeLogicalImmInstruction";
2039 // Logical (shifted register)
2040 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2041 logical_shifted_reg shifted_regtype, string asm,
2043 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2044 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2045 Sched<[WriteISReg, ReadI, ReadISReg]> {
2046 // The operands are in order to match the 'addr' MI operands, so we
2047 // don't need an encoder method and by-name matching. Just use the default
2048 // in-order handling. Since we're using by-order, make sure the names
2054 let Inst{30-29} = opc;
2055 let Inst{28-24} = 0b01010;
2056 let Inst{23-22} = shift{7-6};
2058 let Inst{20-16} = src2;
2059 let Inst{15-10} = shift{5-0};
2060 let Inst{9-5} = src1;
2061 let Inst{4-0} = dst;
2063 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2066 // Aliases for register+register logical instructions.
2067 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2068 : InstAlias<asm#"\t$dst, $src1, $src2",
2069 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2071 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2073 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2074 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2075 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2076 logical_imm32:$imm))]> {
2078 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2080 let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2081 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2082 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2083 logical_imm64:$imm))]> {
2087 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2088 (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2089 logical_imm32_not:$imm), 0>;
2090 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2091 (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2092 logical_imm64_not:$imm), 0>;
2095 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2097 let isCompare = 1, Defs = [NZCV] in {
2098 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2099 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2101 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2103 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2104 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2107 } // end Defs = [NZCV]
2109 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2110 (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2111 logical_imm32_not:$imm), 0>;
2112 def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2113 (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2114 logical_imm64_not:$imm), 0>;
2117 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2118 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2119 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2120 Sched<[WriteI, ReadI, ReadI]>;
2122 // Split from LogicalImm as not all instructions have both.
2123 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2124 SDPatternOperator OpNode> {
2125 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2126 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2127 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2130 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2131 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2132 logical_shifted_reg32:$Rm))]> {
2135 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2136 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2137 logical_shifted_reg64:$Rm))]> {
2141 def : LogicalRegAlias<mnemonic,
2142 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2143 def : LogicalRegAlias<mnemonic,
2144 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2147 // Split from LogicalReg to allow setting NZCV Defs
2148 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2149 SDPatternOperator OpNode = null_frag> {
2150 let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2151 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2152 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2154 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2155 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2158 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2159 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2164 def : LogicalRegAlias<mnemonic,
2165 !cast<Instruction>(NAME#"Wrs"), GPR32>;
2166 def : LogicalRegAlias<mnemonic,
2167 !cast<Instruction>(NAME#"Xrs"), GPR64>;
2171 // Conditionally set flags
2174 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2175 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2176 string mnemonic, SDNode OpNode>
2177 : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2178 mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2179 [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2180 (i32 imm:$cond), NZCV))]>,
2181 Sched<[WriteI, ReadI]> {
2191 let Inst{29-21} = 0b111010010;
2192 let Inst{20-16} = imm;
2193 let Inst{15-12} = cond;
2194 let Inst{11-10} = 0b10;
2197 let Inst{3-0} = nzcv;
2200 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2201 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2203 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2204 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2205 [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2206 (i32 imm:$cond), NZCV))]>,
2207 Sched<[WriteI, ReadI, ReadI]> {
2217 let Inst{29-21} = 0b111010010;
2218 let Inst{20-16} = Rm;
2219 let Inst{15-12} = cond;
2220 let Inst{11-10} = 0b00;
2223 let Inst{3-0} = nzcv;
2226 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2227 // immediate operand variants
2228 def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2231 def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2234 // register operand variants
2235 def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2238 def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2244 // Conditional select
2247 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2248 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2249 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2251 (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2252 Sched<[WriteI, ReadI, ReadI]> {
2261 let Inst{29-21} = 0b011010100;
2262 let Inst{20-16} = Rm;
2263 let Inst{15-12} = cond;
2264 let Inst{11-10} = op2;
2269 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2270 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2273 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2278 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2280 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2281 asm, "\t$Rd, $Rn, $Rm, $cond", "",
2283 (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2284 (i32 imm:$cond), NZCV))]>,
2285 Sched<[WriteI, ReadI, ReadI]> {
2294 let Inst{29-21} = 0b011010100;
2295 let Inst{20-16} = Rm;
2296 let Inst{15-12} = cond;
2297 let Inst{11-10} = op2;
2302 def inv_cond_XFORM : SDNodeXForm<imm, [{
2303 AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2304 return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2308 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2309 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2312 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2316 def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2317 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2318 (inv_cond_XFORM imm:$cond))>;
2320 def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2321 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2322 (inv_cond_XFORM imm:$cond))>;
2326 // Special Mask Value
2328 def maski8_or_more : Operand<i32>,
2329 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2331 def maski16_or_more : Operand<i32>,
2332 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2340 // (unsigned immediate)
2341 // Indexed for 8-bit registers. offset is in range [0,4095].
2342 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2343 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2344 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2345 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2346 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2348 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2349 let Name = "UImm12Offset" # Scale;
2350 let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2351 let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2352 let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2355 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2356 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2357 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2358 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2359 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2361 class uimm12_scaled<int Scale> : Operand<i64> {
2362 let ParserMatchClass
2363 = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2365 = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2366 let PrintMethod = "printUImm12Offset<" # Scale # ">";
2369 def uimm12s1 : uimm12_scaled<1>;
2370 def uimm12s2 : uimm12_scaled<2>;
2371 def uimm12s4 : uimm12_scaled<4>;
2372 def uimm12s8 : uimm12_scaled<8>;
2373 def uimm12s16 : uimm12_scaled<16>;
2375 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2376 string asm, list<dag> pattern>
2377 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2383 let Inst{31-30} = sz;
2384 let Inst{29-27} = 0b111;
2386 let Inst{25-24} = 0b01;
2387 let Inst{23-22} = opc;
2388 let Inst{21-10} = offset;
2392 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2395 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2396 Operand indextype, string asm, list<dag> pattern> {
2397 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2398 def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2399 (ins GPR64sp:$Rn, indextype:$offset),
2403 def : InstAlias<asm # "\t$Rt, [$Rn]",
2404 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2407 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2408 Operand indextype, string asm, list<dag> pattern> {
2409 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2410 def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2411 (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2415 def : InstAlias<asm # "\t$Rt, [$Rn]",
2416 (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2419 def PrefetchOperand : AsmOperandClass {
2420 let Name = "Prefetch";
2421 let ParserMethod = "tryParsePrefetch";
2423 def prfop : Operand<i32> {
2424 let PrintMethod = "printPrefetchOp";
2425 let ParserMatchClass = PrefetchOperand;
2428 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2429 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2430 : BaseLoadStoreUI<sz, V, opc,
2431 (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2439 // Load literal address: 19-bit immediate. The low two bits of the target
2440 // offset are implied zero and so are not part of the immediate.
2441 def am_ldrlit : Operand<OtherVT> {
2442 let EncoderMethod = "getLoadLiteralOpValue";
2443 let DecoderMethod = "DecodePCRelLabel19";
2444 let PrintMethod = "printAlignedLabel";
2445 let ParserMatchClass = PCRelLabel19Operand;
2448 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2449 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2450 : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2451 asm, "\t$Rt, $label", "", []>,
2455 let Inst{31-30} = opc;
2456 let Inst{29-27} = 0b011;
2458 let Inst{25-24} = 0b00;
2459 let Inst{23-5} = label;
2463 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2464 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2465 : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2466 asm, "\t$Rt, $label", "", pat>,
2470 let Inst{31-30} = opc;
2471 let Inst{29-27} = 0b011;
2473 let Inst{25-24} = 0b00;
2474 let Inst{23-5} = label;
2479 // Load/store register offset
2482 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2483 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2484 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2485 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2486 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2488 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2489 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2490 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2491 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2492 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2494 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2495 let Name = "Mem" # Reg # "Extend" # Width;
2496 let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2497 let RenderMethod = "addMemExtendOperands";
2498 let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2501 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2502 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2503 // the trivial shift.
2504 let RenderMethod = "addMemExtend8Operands";
2506 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2507 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2508 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2509 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2511 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2512 // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2513 // the trivial shift.
2514 let RenderMethod = "addMemExtend8Operands";
2516 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2517 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2518 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2519 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2521 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2523 let ParserMatchClass = ParserClass;
2524 let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2525 let DecoderMethod = "DecodeMemExtend";
2526 let EncoderMethod = "getMemExtendOpValue";
2527 let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2530 def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>;
2531 def ro_Wextend16 : ro_extend<MemWExtend16Operand, "w", 16>;
2532 def ro_Wextend32 : ro_extend<MemWExtend32Operand, "w", 32>;
2533 def ro_Wextend64 : ro_extend<MemWExtend64Operand, "w", 64>;
2534 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2536 def ro_Xextend8 : ro_extend<MemXExtend8Operand, "x", 8>;
2537 def ro_Xextend16 : ro_extend<MemXExtend16Operand, "x", 16>;
2538 def ro_Xextend32 : ro_extend<MemXExtend32Operand, "x", 32>;
2539 def ro_Xextend64 : ro_extend<MemXExtend64Operand, "x", 64>;
2540 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2542 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2543 Operand wextend, Operand xextend> {
2544 // CodeGen-level pattern covering the entire addressing mode.
2545 ComplexPattern Wpat = windex;
2546 ComplexPattern Xpat = xindex;
2548 // Asm-level Operand covering the valid "uxtw #3" style syntax.
2549 Operand Wext = wextend;
2550 Operand Xext = xextend;
2553 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2554 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2555 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2556 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2557 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2560 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2561 string asm, dag ins, dag outs, list<dag> pat>
2562 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2567 let Inst{31-30} = sz;
2568 let Inst{29-27} = 0b111;
2570 let Inst{25-24} = 0b00;
2571 let Inst{23-22} = opc;
2573 let Inst{20-16} = Rm;
2574 let Inst{15} = extend{1}; // sign extend Rm?
2576 let Inst{12} = extend{0}; // do shift?
2577 let Inst{11-10} = 0b10;
2582 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2583 : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2584 (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2586 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2587 string asm, ValueType Ty, SDPatternOperator loadop> {
2588 let AddedComplexity = 10 in
2589 def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2591 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2592 [(set (Ty regtype:$Rt),
2593 (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2594 ro_Wextend8:$extend)))]>,
2595 Sched<[WriteLDIdx, ReadAdrBase]> {
2599 let AddedComplexity = 10 in
2600 def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2602 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2603 [(set (Ty regtype:$Rt),
2604 (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2605 ro_Xextend8:$extend)))]>,
2606 Sched<[WriteLDIdx, ReadAdrBase]> {
2610 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2613 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2614 string asm, ValueType Ty, SDPatternOperator storeop> {
2615 let AddedComplexity = 10 in
2616 def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2617 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2618 [(storeop (Ty regtype:$Rt),
2619 (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2620 ro_Wextend8:$extend))]>,
2621 Sched<[WriteSTIdx, ReadAdrBase]> {
2625 let AddedComplexity = 10 in
2626 def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2627 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2628 [(storeop (Ty regtype:$Rt),
2629 (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2630 ro_Xextend8:$extend))]>,
2631 Sched<[WriteSTIdx, ReadAdrBase]> {
2635 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2638 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2639 string asm, dag ins, dag outs, list<dag> pat>
2640 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2645 let Inst{31-30} = sz;
2646 let Inst{29-27} = 0b111;
2648 let Inst{25-24} = 0b00;
2649 let Inst{23-22} = opc;
2651 let Inst{20-16} = Rm;
2652 let Inst{15} = extend{1}; // sign extend Rm?
2654 let Inst{12} = extend{0}; // do shift?
2655 let Inst{11-10} = 0b10;
2660 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2661 string asm, ValueType Ty, SDPatternOperator loadop> {
2662 let AddedComplexity = 10 in
2663 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2664 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2665 [(set (Ty regtype:$Rt),
2666 (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2667 ro_Wextend16:$extend)))]>,
2668 Sched<[WriteLDIdx, ReadAdrBase]> {
2672 let AddedComplexity = 10 in
2673 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2674 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2675 [(set (Ty regtype:$Rt),
2676 (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2677 ro_Xextend16:$extend)))]>,
2678 Sched<[WriteLDIdx, ReadAdrBase]> {
2682 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2685 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2686 string asm, ValueType Ty, SDPatternOperator storeop> {
2687 let AddedComplexity = 10 in
2688 def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2689 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2690 [(storeop (Ty regtype:$Rt),
2691 (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2692 ro_Wextend16:$extend))]>,
2693 Sched<[WriteSTIdx, ReadAdrBase]> {
2697 let AddedComplexity = 10 in
2698 def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2699 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2700 [(storeop (Ty regtype:$Rt),
2701 (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2702 ro_Xextend16:$extend))]>,
2703 Sched<[WriteSTIdx, ReadAdrBase]> {
2707 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2710 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2711 string asm, dag ins, dag outs, list<dag> pat>
2712 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2717 let Inst{31-30} = sz;
2718 let Inst{29-27} = 0b111;
2720 let Inst{25-24} = 0b00;
2721 let Inst{23-22} = opc;
2723 let Inst{20-16} = Rm;
2724 let Inst{15} = extend{1}; // sign extend Rm?
2726 let Inst{12} = extend{0}; // do shift?
2727 let Inst{11-10} = 0b10;
2732 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2733 string asm, ValueType Ty, SDPatternOperator loadop> {
2734 let AddedComplexity = 10 in
2735 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2736 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2737 [(set (Ty regtype:$Rt),
2738 (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2739 ro_Wextend32:$extend)))]>,
2740 Sched<[WriteLDIdx, ReadAdrBase]> {
2744 let AddedComplexity = 10 in
2745 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2746 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2747 [(set (Ty regtype:$Rt),
2748 (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2749 ro_Xextend32:$extend)))]>,
2750 Sched<[WriteLDIdx, ReadAdrBase]> {
2754 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2757 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2758 string asm, ValueType Ty, SDPatternOperator storeop> {
2759 let AddedComplexity = 10 in
2760 def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2761 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2762 [(storeop (Ty regtype:$Rt),
2763 (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2764 ro_Wextend32:$extend))]>,
2765 Sched<[WriteSTIdx, ReadAdrBase]> {
2769 let AddedComplexity = 10 in
2770 def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2771 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2772 [(storeop (Ty regtype:$Rt),
2773 (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2774 ro_Xextend32:$extend))]>,
2775 Sched<[WriteSTIdx, ReadAdrBase]> {
2779 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2782 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2783 string asm, dag ins, dag outs, list<dag> pat>
2784 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2789 let Inst{31-30} = sz;
2790 let Inst{29-27} = 0b111;
2792 let Inst{25-24} = 0b00;
2793 let Inst{23-22} = opc;
2795 let Inst{20-16} = Rm;
2796 let Inst{15} = extend{1}; // sign extend Rm?
2798 let Inst{12} = extend{0}; // do shift?
2799 let Inst{11-10} = 0b10;
2804 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2805 string asm, ValueType Ty, SDPatternOperator loadop> {
2806 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2807 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2808 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2809 [(set (Ty regtype:$Rt),
2810 (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2811 ro_Wextend64:$extend)))]>,
2812 Sched<[WriteLDIdx, ReadAdrBase]> {
2816 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2817 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2818 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2819 [(set (Ty regtype:$Rt),
2820 (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2821 ro_Xextend64:$extend)))]>,
2822 Sched<[WriteLDIdx, ReadAdrBase]> {
2826 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2829 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2830 string asm, ValueType Ty, SDPatternOperator storeop> {
2831 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2832 def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2833 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2834 [(storeop (Ty regtype:$Rt),
2835 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2836 ro_Wextend64:$extend))]>,
2837 Sched<[WriteSTIdx, ReadAdrBase]> {
2841 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2842 def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2843 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2844 [(storeop (Ty regtype:$Rt),
2845 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2846 ro_Xextend64:$extend))]>,
2847 Sched<[WriteSTIdx, ReadAdrBase]> {
2851 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2854 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2855 string asm, dag ins, dag outs, list<dag> pat>
2856 : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2861 let Inst{31-30} = sz;
2862 let Inst{29-27} = 0b111;
2864 let Inst{25-24} = 0b00;
2865 let Inst{23-22} = opc;
2867 let Inst{20-16} = Rm;
2868 let Inst{15} = extend{1}; // sign extend Rm?
2870 let Inst{12} = extend{0}; // do shift?
2871 let Inst{11-10} = 0b10;
2876 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2877 string asm, ValueType Ty, SDPatternOperator loadop> {
2878 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2879 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2880 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2881 [(set (Ty regtype:$Rt),
2882 (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2883 ro_Wextend128:$extend)))]>,
2884 Sched<[WriteLDIdx, ReadAdrBase]> {
2888 let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2889 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2890 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2891 [(set (Ty regtype:$Rt),
2892 (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2893 ro_Xextend128:$extend)))]>,
2894 Sched<[WriteLDIdx, ReadAdrBase]> {
2898 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2901 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2902 string asm, ValueType Ty, SDPatternOperator storeop> {
2903 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2904 def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2905 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2906 [(storeop (Ty regtype:$Rt),
2907 (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2908 ro_Wextend128:$extend))]>,
2909 Sched<[WriteSTIdx, ReadAdrBase]> {
2913 let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2914 def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2915 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2916 [(storeop (Ty regtype:$Rt),
2917 (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2918 ro_Xextend128:$extend))]>,
2919 Sched<[WriteSTIdx, ReadAdrBase]> {
2923 def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2926 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2927 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2928 string asm, list<dag> pat>
2929 : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2935 let Inst{31-30} = sz;
2936 let Inst{29-27} = 0b111;
2938 let Inst{25-24} = 0b00;
2939 let Inst{23-22} = opc;
2941 let Inst{20-16} = Rm;
2942 let Inst{15} = extend{1}; // sign extend Rm?
2944 let Inst{12} = extend{0}; // do shift?
2945 let Inst{11-10} = 0b10;
2950 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2951 def roW : BasePrefetchRO<sz, V, opc, (outs),
2952 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2953 asm, [(AArch64Prefetch imm:$Rt,
2954 (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2955 ro_Wextend64:$extend))]> {
2959 def roX : BasePrefetchRO<sz, V, opc, (outs),
2960 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2961 asm, [(AArch64Prefetch imm:$Rt,
2962 (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2963 ro_Xextend64:$extend))]> {
2967 def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2968 (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2969 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2973 // Load/store unscaled immediate
2976 def am_unscaled8 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2977 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2978 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2979 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2980 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2982 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2983 string asm, list<dag> pattern>
2984 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2988 let Inst{31-30} = sz;
2989 let Inst{29-27} = 0b111;
2991 let Inst{25-24} = 0b00;
2992 let Inst{23-22} = opc;
2994 let Inst{20-12} = offset;
2995 let Inst{11-10} = 0b00;
2999 let DecoderMethod = "DecodeSignedLdStInstruction";
3002 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3003 string asm, list<dag> pattern> {
3004 let AddedComplexity = 1 in // try this before LoadUI
3005 def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3006 (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3009 def : InstAlias<asm # "\t$Rt, [$Rn]",
3010 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3013 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3014 string asm, list<dag> pattern> {
3015 let AddedComplexity = 1 in // try this before StoreUI
3016 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3017 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3021 def : InstAlias<asm # "\t$Rt, [$Rn]",
3022 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3025 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3027 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3028 def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3029 (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3033 def : InstAlias<asm # "\t$Rt, [$Rn]",
3034 (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3038 // Load/store unscaled immediate, unprivileged
3041 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3042 dag oops, dag iops, string asm>
3043 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3047 let Inst{31-30} = sz;
3048 let Inst{29-27} = 0b111;
3050 let Inst{25-24} = 0b00;
3051 let Inst{23-22} = opc;
3053 let Inst{20-12} = offset;
3054 let Inst{11-10} = 0b10;
3058 let DecoderMethod = "DecodeSignedLdStInstruction";
3061 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3062 RegisterClass regtype, string asm> {
3063 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3064 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3065 (ins GPR64sp:$Rn, simm9:$offset), asm>,
3068 def : InstAlias<asm # "\t$Rt, [$Rn]",
3069 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3072 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3073 RegisterClass regtype, string asm> {
3074 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3075 def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3076 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3080 def : InstAlias<asm # "\t$Rt, [$Rn]",
3081 (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3085 // Load/store pre-indexed
3088 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3089 string asm, string cstr, list<dag> pat>
3090 : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3094 let Inst{31-30} = sz;
3095 let Inst{29-27} = 0b111;
3097 let Inst{25-24} = 0;
3098 let Inst{23-22} = opc;
3100 let Inst{20-12} = offset;
3101 let Inst{11-10} = 0b11;
3105 let DecoderMethod = "DecodeSignedLdStInstruction";
3108 let hasSideEffects = 0 in {
3109 let mayStore = 0, mayLoad = 1 in
3110 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3112 : BaseLoadStorePreIdx<sz, V, opc,
3113 (outs GPR64sp:$wback, regtype:$Rt),
3114 (ins GPR64sp:$Rn, simm9:$offset), asm,
3115 "$Rn = $wback,@earlyclobber $wback", []>,
3116 Sched<[WriteLD, WriteAdr]>;
3118 let mayStore = 1, mayLoad = 0 in
3119 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3120 string asm, SDPatternOperator storeop, ValueType Ty>
3121 : BaseLoadStorePreIdx<sz, V, opc,
3122 (outs GPR64sp:$wback),
3123 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3124 asm, "$Rn = $wback,@earlyclobber $wback",
3125 [(set GPR64sp:$wback,
3126 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3127 Sched<[WriteAdr, WriteST]>;
3128 } // hasSideEffects = 0
3131 // Load/store post-indexed
3134 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3135 string asm, string cstr, list<dag> pat>
3136 : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3140 let Inst{31-30} = sz;
3141 let Inst{29-27} = 0b111;
3143 let Inst{25-24} = 0b00;
3144 let Inst{23-22} = opc;
3146 let Inst{20-12} = offset;
3147 let Inst{11-10} = 0b01;
3151 let DecoderMethod = "DecodeSignedLdStInstruction";
3154 let hasSideEffects = 0 in {
3155 let mayStore = 0, mayLoad = 1 in
3156 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3158 : BaseLoadStorePostIdx<sz, V, opc,
3159 (outs GPR64sp:$wback, regtype:$Rt),
3160 (ins GPR64sp:$Rn, simm9:$offset),
3161 asm, "$Rn = $wback,@earlyclobber $wback", []>,
3162 Sched<[WriteLD, WriteI]>;
3164 let mayStore = 1, mayLoad = 0 in
3165 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3166 string asm, SDPatternOperator storeop, ValueType Ty>
3167 : BaseLoadStorePostIdx<sz, V, opc,
3168 (outs GPR64sp:$wback),
3169 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3170 asm, "$Rn = $wback,@earlyclobber $wback",
3171 [(set GPR64sp:$wback,
3172 (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3173 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3174 } // hasSideEffects = 0
3181 // (indexed, offset)
3183 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3185 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3190 let Inst{31-30} = opc;
3191 let Inst{29-27} = 0b101;
3193 let Inst{25-23} = 0b010;
3195 let Inst{21-15} = offset;
3196 let Inst{14-10} = Rt2;
3200 let DecoderMethod = "DecodePairLdStInstruction";
3203 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3204 Operand indextype, string asm> {
3205 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3206 def i : BaseLoadStorePairOffset<opc, V, 1,
3207 (outs regtype:$Rt, regtype:$Rt2),
3208 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3209 Sched<[WriteLD, WriteLDHi]>;
3211 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3212 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3217 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3218 Operand indextype, string asm> {
3219 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3220 def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3221 (ins regtype:$Rt, regtype:$Rt2,
3222 GPR64sp:$Rn, indextype:$offset),
3226 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3227 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3232 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3234 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3239 let Inst{31-30} = opc;
3240 let Inst{29-27} = 0b101;
3242 let Inst{25-23} = 0b011;
3244 let Inst{21-15} = offset;
3245 let Inst{14-10} = Rt2;
3249 let DecoderMethod = "DecodePairLdStInstruction";
3252 let hasSideEffects = 0 in {
3253 let mayStore = 0, mayLoad = 1 in
3254 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3255 Operand indextype, string asm>
3256 : BaseLoadStorePairPreIdx<opc, V, 1,
3257 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3258 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3259 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3261 let mayStore = 1, mayLoad = 0 in
3262 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3263 Operand indextype, string asm>
3264 : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3265 (ins regtype:$Rt, regtype:$Rt2,
3266 GPR64sp:$Rn, indextype:$offset),
3268 Sched<[WriteAdr, WriteSTP]>;
3269 } // hasSideEffects = 0
3273 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3275 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3280 let Inst{31-30} = opc;
3281 let Inst{29-27} = 0b101;
3283 let Inst{25-23} = 0b001;
3285 let Inst{21-15} = offset;
3286 let Inst{14-10} = Rt2;
3290 let DecoderMethod = "DecodePairLdStInstruction";
3293 let hasSideEffects = 0 in {
3294 let mayStore = 0, mayLoad = 1 in
3295 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3296 Operand idxtype, string asm>
3297 : BaseLoadStorePairPostIdx<opc, V, 1,
3298 (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3299 (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3300 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3302 let mayStore = 1, mayLoad = 0 in
3303 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3304 Operand idxtype, string asm>
3305 : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3306 (ins regtype:$Rt, regtype:$Rt2,
3307 GPR64sp:$Rn, idxtype:$offset),
3309 Sched<[WriteAdr, WriteSTP]>;
3310 } // hasSideEffects = 0
3314 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3316 : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3321 let Inst{31-30} = opc;
3322 let Inst{29-27} = 0b101;
3324 let Inst{25-23} = 0b000;
3326 let Inst{21-15} = offset;
3327 let Inst{14-10} = Rt2;
3331 let DecoderMethod = "DecodePairLdStInstruction";
3334 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3335 Operand indextype, string asm> {
3336 let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3337 def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3338 (outs regtype:$Rt, regtype:$Rt2),
3339 (ins GPR64sp:$Rn, indextype:$offset), asm>,
3340 Sched<[WriteLD, WriteLDHi]>;
3343 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3344 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3348 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3349 Operand indextype, string asm> {
3350 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3351 def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3352 (ins regtype:$Rt, regtype:$Rt2,
3353 GPR64sp:$Rn, indextype:$offset),
3357 def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3358 (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3363 // Load/store exclusive
3366 // True exclusive operations write to and/or read from the system's exclusive
3367 // monitors, which as far as a compiler is concerned can be modelled as a
3368 // random shared memory address. Hence LoadExclusive mayStore.
3370 // Since these instructions have the undefined register bits set to 1 in
3371 // their canonical form, we need a post encoder method to set those bits
3372 // to 1 when encoding these instructions. We do this using the
3373 // fixLoadStoreExclusive function. This function has template parameters:
3375 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3377 // hasRs indicates that the instruction uses the Rs field, so we won't set
3378 // it to 1 (and the same for Rt2). We don't need template parameters for
3379 // the other register fields since Rt and Rn are always used.
3381 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3382 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3383 dag oops, dag iops, string asm, string operands>
3384 : I<oops, iops, asm, operands, "", []> {
3385 let Inst{31-30} = sz;
3386 let Inst{29-24} = 0b001000;
3392 let DecoderMethod = "DecodeExclusiveLdStInstruction";
3395 // Neither Rs nor Rt2 operands.
3396 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3397 dag oops, dag iops, string asm, string operands>
3398 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3401 let Inst{20-16} = 0b11111;
3402 let Unpredictable{20-16} = 0b11111;
3403 let Inst{14-10} = 0b11111;
3404 let Unpredictable{14-10} = 0b11111;
3408 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3411 // Simple load acquires don't set the exclusive monitor
3412 let mayLoad = 1, mayStore = 0 in
3413 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3414 RegisterClass regtype, string asm>
3415 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3416 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3419 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3420 RegisterClass regtype, string asm>
3421 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3422 (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3425 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3426 RegisterClass regtype, string asm>
3427 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3428 (outs regtype:$Rt, regtype:$Rt2),
3429 (ins GPR64sp0:$Rn), asm,
3430 "\t$Rt, $Rt2, [$Rn]">,
3431 Sched<[WriteLD, WriteLDHi]> {
3435 let Inst{14-10} = Rt2;
3439 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3442 // Simple store release operations do not check the exclusive monitor.
3443 let mayLoad = 0, mayStore = 1 in
3444 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3445 RegisterClass regtype, string asm>
3446 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3447 (ins regtype:$Rt, GPR64sp0:$Rn),
3448 asm, "\t$Rt, [$Rn]">,
3451 let mayLoad = 1, mayStore = 1 in
3452 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3453 RegisterClass regtype, string asm>
3454 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3455 (ins regtype:$Rt, GPR64sp0:$Rn),
3456 asm, "\t$Ws, $Rt, [$Rn]">,
3461 let Inst{20-16} = Ws;
3465 let Constraints = "@earlyclobber $Ws";
3466 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3469 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3470 RegisterClass regtype, string asm>
3471 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3473 (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3474 asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3480 let Inst{20-16} = Ws;
3481 let Inst{14-10} = Rt2;
3485 let Constraints = "@earlyclobber $Ws";
3489 // Exception generation
3492 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3493 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3494 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3497 let Inst{31-24} = 0b11010100;
3498 let Inst{23-21} = op1;
3499 let Inst{20-5} = imm;
3500 let Inst{4-2} = 0b000;
3504 let Predicates = [HasFPARMv8] in {
3507 // Floating point to integer conversion
3510 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3511 RegisterClass srcType, RegisterClass dstType,
3512 string asm, list<dag> pattern>
3513 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3514 asm, "\t$Rd, $Rn", "", pattern>,
3515 Sched<[WriteFCvt]> {
3518 let Inst{30-29} = 0b00;
3519 let Inst{28-24} = 0b11110;
3520 let Inst{23-22} = type;
3522 let Inst{20-19} = rmode;
3523 let Inst{18-16} = opcode;
3524 let Inst{15-10} = 0;
3529 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3530 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3531 RegisterClass srcType, RegisterClass dstType,
3532 Operand immType, string asm, list<dag> pattern>
3533 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3534 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3535 Sched<[WriteFCvt]> {
3539 let Inst{30-29} = 0b00;
3540 let Inst{28-24} = 0b11110;
3541 let Inst{23-22} = type;
3543 let Inst{20-19} = rmode;
3544 let Inst{18-16} = opcode;
3545 let Inst{15-10} = scale;
3550 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3551 SDPatternOperator OpN> {
3552 // Unscaled half-precision to 32-bit
3553 def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3554 [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3555 let Inst{31} = 0; // 32-bit GPR flag
3556 let Predicates = [HasFullFP16];
3559 // Unscaled half-precision to 64-bit
3560 def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3561 [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3562 let Inst{31} = 1; // 64-bit GPR flag
3563 let Predicates = [HasFullFP16];
3566 // Unscaled single-precision to 32-bit
3567 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3568 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3569 let Inst{31} = 0; // 32-bit GPR flag
3572 // Unscaled single-precision to 64-bit
3573 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3574 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3575 let Inst{31} = 1; // 64-bit GPR flag
3578 // Unscaled double-precision to 32-bit
3579 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3580 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3581 let Inst{31} = 0; // 32-bit GPR flag
3584 // Unscaled double-precision to 64-bit
3585 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3586 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3587 let Inst{31} = 1; // 64-bit GPR flag
3591 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3592 SDPatternOperator OpN> {
3593 // Scaled half-precision to 32-bit
3594 def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
3595 fixedpoint_f16_i32, asm,
3596 [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
3597 fixedpoint_f16_i32:$scale)))]> {
3598 let Inst{31} = 0; // 32-bit GPR flag
3600 let Predicates = [HasFullFP16];
3603 // Scaled half-precision to 64-bit
3604 def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
3605 fixedpoint_f16_i64, asm,
3606 [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
3607 fixedpoint_f16_i64:$scale)))]> {
3608 let Inst{31} = 1; // 64-bit GPR flag
3609 let Predicates = [HasFullFP16];
3612 // Scaled single-precision to 32-bit
3613 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3614 fixedpoint_f32_i32, asm,
3615 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3616 fixedpoint_f32_i32:$scale)))]> {
3617 let Inst{31} = 0; // 32-bit GPR flag
3621 // Scaled single-precision to 64-bit
3622 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3623 fixedpoint_f32_i64, asm,
3624 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3625 fixedpoint_f32_i64:$scale)))]> {
3626 let Inst{31} = 1; // 64-bit GPR flag
3629 // Scaled double-precision to 32-bit
3630 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3631 fixedpoint_f64_i32, asm,
3632 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3633 fixedpoint_f64_i32:$scale)))]> {
3634 let Inst{31} = 0; // 32-bit GPR flag
3638 // Scaled double-precision to 64-bit
3639 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3640 fixedpoint_f64_i64, asm,
3641 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3642 fixedpoint_f64_i64:$scale)))]> {
3643 let Inst{31} = 1; // 64-bit GPR flag
3648 // Integer to floating point conversion
3651 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3652 class BaseIntegerToFP<bit isUnsigned,
3653 RegisterClass srcType, RegisterClass dstType,
3654 Operand immType, string asm, list<dag> pattern>
3655 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3656 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3657 Sched<[WriteFCvt]> {
3661 let Inst{30-24} = 0b0011110;
3662 let Inst{21-17} = 0b00001;
3663 let Inst{16} = isUnsigned;
3664 let Inst{15-10} = scale;
3669 class BaseIntegerToFPUnscaled<bit isUnsigned,
3670 RegisterClass srcType, RegisterClass dstType,
3671 ValueType dvt, string asm, SDNode node>
3672 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3673 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3674 Sched<[WriteFCvt]> {
3678 let Inst{30-24} = 0b0011110;
3679 let Inst{21-17} = 0b10001;
3680 let Inst{16} = isUnsigned;
3681 let Inst{15-10} = 0b000000;
3686 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3688 def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
3689 let Inst{31} = 0; // 32-bit GPR flag
3690 let Inst{23-22} = 0b11; // 16-bit FPR flag
3691 let Predicates = [HasFullFP16];
3694 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3695 let Inst{31} = 0; // 32-bit GPR flag
3696 let Inst{23-22} = 0b00; // 32-bit FPR flag
3699 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3700 let Inst{31} = 0; // 32-bit GPR flag
3701 let Inst{23-22} = 0b01; // 64-bit FPR flag
3704 def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
3705 let Inst{31} = 1; // 64-bit GPR flag
3706 let Inst{23-22} = 0b11; // 16-bit FPR flag
3707 let Predicates = [HasFullFP16];
3710 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3711 let Inst{31} = 1; // 64-bit GPR flag
3712 let Inst{23-22} = 0b00; // 32-bit FPR flag
3715 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3716 let Inst{31} = 1; // 64-bit GPR flag
3717 let Inst{23-22} = 0b01; // 64-bit FPR flag
3721 def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
3723 (fdiv (node GPR32:$Rn),
3724 fixedpoint_f16_i32:$scale))]> {
3725 let Inst{31} = 0; // 32-bit GPR flag
3726 let Inst{23-22} = 0b11; // 16-bit FPR flag
3728 let Predicates = [HasFullFP16];
3731 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3733 (fdiv (node GPR32:$Rn),
3734 fixedpoint_f32_i32:$scale))]> {
3735 let Inst{31} = 0; // 32-bit GPR flag
3736 let Inst{23-22} = 0b00; // 32-bit FPR flag
3740 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3742 (fdiv (node GPR32:$Rn),
3743 fixedpoint_f64_i32:$scale))]> {
3744 let Inst{31} = 0; // 32-bit GPR flag
3745 let Inst{23-22} = 0b01; // 64-bit FPR flag
3749 def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
3751 (fdiv (node GPR64:$Rn),
3752 fixedpoint_f16_i64:$scale))]> {
3753 let Inst{31} = 1; // 64-bit GPR flag
3754 let Inst{23-22} = 0b11; // 16-bit FPR flag
3755 let Predicates = [HasFullFP16];
3758 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3760 (fdiv (node GPR64:$Rn),
3761 fixedpoint_f32_i64:$scale))]> {
3762 let Inst{31} = 1; // 64-bit GPR flag
3763 let Inst{23-22} = 0b00; // 32-bit FPR flag
3766 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3768 (fdiv (node GPR64:$Rn),
3769 fixedpoint_f64_i64:$scale))]> {
3770 let Inst{31} = 1; // 64-bit GPR flag
3771 let Inst{23-22} = 0b01; // 64-bit FPR flag
3776 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3779 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3780 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3781 RegisterClass srcType, RegisterClass dstType,
3783 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3784 // We use COPY_TO_REGCLASS for these bitconvert operations.
3785 // copyPhysReg() expands the resultant COPY instructions after
3786 // regalloc is done. This gives greater freedom for the allocator
3787 // and related passes (coalescing, copy propagation, et. al.) to
3788 // be more effective.
3789 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3790 Sched<[WriteFCopy]> {
3793 let Inst{30-24} = 0b0011110;
3795 let Inst{20-19} = rmode;
3796 let Inst{18-16} = opcode;
3797 let Inst{15-10} = 0b000000;
3802 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3803 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3804 RegisterClass srcType, RegisterOperand dstType, string asm,
3806 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3807 "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3808 Sched<[WriteFCopy]> {
3811 let Inst{30-23} = 0b00111101;
3813 let Inst{20-19} = rmode;
3814 let Inst{18-16} = opcode;
3815 let Inst{15-10} = 0b000000;
3819 let DecoderMethod = "DecodeFMOVLaneInstruction";
3822 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3823 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3824 RegisterOperand srcType, RegisterClass dstType, string asm,
3826 : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3827 "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3828 Sched<[WriteFCopy]> {
3831 let Inst{30-23} = 0b00111101;
3833 let Inst{20-19} = rmode;
3834 let Inst{18-16} = opcode;
3835 let Inst{15-10} = 0b000000;
3839 let DecoderMethod = "DecodeFMOVLaneInstruction";
3843 multiclass UnscaledConversion<string asm> {
3844 def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
3845 let Inst{31} = 0; // 32-bit GPR flag
3846 let Inst{23-22} = 0b11; // 16-bit FPR flag
3847 let Predicates = [HasFullFP16];
3850 def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
3851 let Inst{31} = 1; // 64-bit GPR flag
3852 let Inst{23-22} = 0b11; // 16-bit FPR flag
3853 let Predicates = [HasFullFP16];
3856 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3857 let Inst{31} = 0; // 32-bit GPR flag
3858 let Inst{23-22} = 0b00; // 32-bit FPR flag
3861 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3862 let Inst{31} = 1; // 64-bit GPR flag
3863 let Inst{23-22} = 0b01; // 64-bit FPR flag
3866 def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
3867 let Inst{31} = 0; // 32-bit GPR flag
3868 let Inst{23-22} = 0b11; // 16-bit FPR flag
3869 let Predicates = [HasFullFP16];
3872 def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
3873 let Inst{31} = 1; // 64-bit GPR flag
3874 let Inst{23-22} = 0b11; // 16-bit FPR flag
3875 let Predicates = [HasFullFP16];
3878 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3879 let Inst{31} = 0; // 32-bit GPR flag
3880 let Inst{23-22} = 0b00; // 32-bit FPR flag
3883 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3884 let Inst{31} = 1; // 64-bit GPR flag
3885 let Inst{23-22} = 0b01; // 64-bit FPR flag
3888 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3894 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3902 // Floating point conversion
3905 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3906 RegisterClass srcType, string asm, list<dag> pattern>
3907 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3908 Sched<[WriteFCvt]> {
3911 let Inst{31-24} = 0b00011110;
3912 let Inst{23-22} = type;
3913 let Inst{21-17} = 0b10001;
3914 let Inst{16-15} = opcode;
3915 let Inst{14-10} = 0b10000;
3920 multiclass FPConversion<string asm> {
3921 // Double-precision to Half-precision
3922 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3923 [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3925 // Double-precision to Single-precision
3926 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3927 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3929 // Half-precision to Double-precision
3930 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3931 [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3933 // Half-precision to Single-precision
3934 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3935 [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3937 // Single-precision to Double-precision
3938 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3939 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3941 // Single-precision to Half-precision
3942 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3943 [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3947 // Single operand floating point data processing
3950 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3951 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3952 ValueType vt, string asm, SDPatternOperator node>
3953 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3954 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3958 let Inst{31-24} = 0b00011110;
3959 let Inst{21-19} = 0b100;
3960 let Inst{18-15} = opcode;
3961 let Inst{14-10} = 0b10000;
3966 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3967 SDPatternOperator node = null_frag> {
3968 def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
3969 let Inst{23-22} = 0b11; // 16-bit size flag
3970 let Predicates = [HasFullFP16];
3973 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3974 let Inst{23-22} = 0b00; // 32-bit size flag
3977 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3978 let Inst{23-22} = 0b01; // 64-bit size flag
3983 // Two operand floating point data processing
3986 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3987 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3988 string asm, list<dag> pat>
3989 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3990 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3995 let Inst{31-24} = 0b00011110;
3997 let Inst{20-16} = Rm;
3998 let Inst{15-12} = opcode;
3999 let Inst{11-10} = 0b10;
4004 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4005 SDPatternOperator node = null_frag> {
4006 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4007 [(set (f16 FPR16:$Rd),
4008 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4009 let Inst{23-22} = 0b11; // 16-bit size flag
4010 let Predicates = [HasFullFP16];
4013 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4014 [(set (f32 FPR32:$Rd),
4015 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4016 let Inst{23-22} = 0b00; // 32-bit size flag
4019 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4020 [(set (f64 FPR64:$Rd),
4021 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4022 let Inst{23-22} = 0b01; // 64-bit size flag
4026 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4027 def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4028 [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4029 let Inst{23-22} = 0b11; // 16-bit size flag
4030 let Predicates = [HasFullFP16];
4033 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4034 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4035 let Inst{23-22} = 0b00; // 32-bit size flag
4038 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4039 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4040 let Inst{23-22} = 0b01; // 64-bit size flag
4046 // Three operand floating point data processing
4049 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4050 RegisterClass regtype, string asm, list<dag> pat>
4051 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4052 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4053 Sched<[WriteFMul]> {
4058 let Inst{31-24} = 0b00011111;
4059 let Inst{21} = isNegated;
4060 let Inst{20-16} = Rm;
4061 let Inst{15} = isSub;
4062 let Inst{14-10} = Ra;
4067 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4068 SDPatternOperator node> {
4069 def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4071 (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4072 let Inst{23-22} = 0b11; // 16-bit size flag
4073 let Predicates = [HasFullFP16];
4076 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4078 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4079 let Inst{23-22} = 0b00; // 32-bit size flag
4082 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4084 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4085 let Inst{23-22} = 0b01; // 64-bit size flag
4090 // Floating point data comparisons
4093 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4094 class BaseOneOperandFPComparison<bit signalAllNans,
4095 RegisterClass regtype, string asm,
4097 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4098 Sched<[WriteFCmp]> {
4100 let Inst{31-24} = 0b00011110;
4103 let Inst{15-10} = 0b001000;
4105 let Inst{4} = signalAllNans;
4106 let Inst{3-0} = 0b1000;
4108 // Rm should be 0b00000 canonically, but we need to accept any value.
4109 let PostEncoderMethod = "fixOneOperandFPComparison";
4112 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4113 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4114 string asm, list<dag> pat>
4115 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4116 Sched<[WriteFCmp]> {
4119 let Inst{31-24} = 0b00011110;
4121 let Inst{20-16} = Rm;
4122 let Inst{15-10} = 0b001000;
4124 let Inst{4} = signalAllNans;
4125 let Inst{3-0} = 0b0000;
4128 multiclass FPComparison<bit signalAllNans, string asm,
4129 SDPatternOperator OpNode = null_frag> {
4130 let Defs = [NZCV] in {
4131 def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4132 [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4133 let Inst{23-22} = 0b11;
4134 let Predicates = [HasFullFP16];
4137 def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4138 [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4139 let Inst{23-22} = 0b11;
4140 let Predicates = [HasFullFP16];
4143 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4144 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4145 let Inst{23-22} = 0b00;
4148 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4149 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4150 let Inst{23-22} = 0b00;
4153 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4154 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4155 let Inst{23-22} = 0b01;
4158 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4159 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4160 let Inst{23-22} = 0b01;
4166 // Floating point conditional comparisons
4169 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4170 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4171 string mnemonic, list<dag> pat>
4172 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4173 mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4174 Sched<[WriteFCmp]> {
4183 let Inst{31-24} = 0b00011110;
4185 let Inst{20-16} = Rm;
4186 let Inst{15-12} = cond;
4187 let Inst{11-10} = 0b01;
4189 let Inst{4} = signalAllNans;
4190 let Inst{3-0} = nzcv;
4193 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4194 SDPatternOperator OpNode = null_frag> {
4195 def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4196 let Inst{23-22} = 0b11;
4197 let Predicates = [HasFullFP16];
4200 def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4201 [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4202 (i32 imm:$cond), NZCV))]> {
4203 let Inst{23-22} = 0b00;
4206 def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4207 [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4208 (i32 imm:$cond), NZCV))]> {
4209 let Inst{23-22} = 0b01;
4214 // Floating point conditional select
4217 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4218 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4219 asm, "\t$Rd, $Rn, $Rm, $cond", "",
4221 (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4222 (i32 imm:$cond), NZCV))]>,
4229 let Inst{31-24} = 0b00011110;
4231 let Inst{20-16} = Rm;
4232 let Inst{15-12} = cond;
4233 let Inst{11-10} = 0b11;
4238 multiclass FPCondSelect<string asm> {
4239 let Uses = [NZCV] in {
4240 def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4241 let Inst{23-22} = 0b11;
4242 let Predicates = [HasFullFP16];
4245 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4246 let Inst{23-22} = 0b00;
4249 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4250 let Inst{23-22} = 0b01;
4256 // Floating move immediate
4259 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4260 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4261 [(set regtype:$Rd, fpimmtype:$imm)]>,
4262 Sched<[WriteFImm]> {
4265 let Inst{31-24} = 0b00011110;
4267 let Inst{20-13} = imm;
4268 let Inst{12-5} = 0b10000000;
4272 multiclass FPMoveImmediate<string asm> {
4273 def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4274 let Inst{23-22} = 0b11;
4275 let Predicates = [HasFullFP16];
4278 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4279 let Inst{23-22} = 0b00;
4282 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4283 let Inst{23-22} = 0b01;
4286 } // end of 'let Predicates = [HasFPARMv8]'
4288 //----------------------------------------------------------------------------
4290 //----------------------------------------------------------------------------
4292 let Predicates = [HasNEON] in {
4294 //----------------------------------------------------------------------------
4295 // AdvSIMD three register vector instructions
4296 //----------------------------------------------------------------------------
4298 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4299 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4300 RegisterOperand regtype, string asm, string kind,
4302 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4303 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4304 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4312 let Inst{28-24} = 0b01110;
4313 let Inst{23-22} = size;
4315 let Inst{20-16} = Rm;
4316 let Inst{15-11} = opcode;
4322 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4323 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4324 RegisterOperand regtype, string asm, string kind,
4326 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4327 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4328 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4336 let Inst{28-24} = 0b01110;
4337 let Inst{23-22} = size;
4339 let Inst{20-16} = Rm;
4340 let Inst{15-11} = opcode;
4346 // All operand sizes distinguished in the encoding.
4347 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4348 SDPatternOperator OpNode> {
4349 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4351 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4352 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4354 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4355 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4357 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4358 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4360 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4361 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4363 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4364 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4366 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4367 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4369 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4372 // As above, but D sized elements unsupported.
4373 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4374 SDPatternOperator OpNode> {
4375 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4377 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4378 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4380 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4381 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4383 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4384 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4386 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4387 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4389 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4390 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4392 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4395 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4396 SDPatternOperator OpNode> {
4397 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4399 [(set (v8i8 V64:$dst),
4400 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4401 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4403 [(set (v16i8 V128:$dst),
4404 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4405 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4407 [(set (v4i16 V64:$dst),
4408 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4409 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4411 [(set (v8i16 V128:$dst),
4412 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4413 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4415 [(set (v2i32 V64:$dst),
4416 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4417 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4419 [(set (v4i32 V128:$dst),
4420 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4423 // As above, but only B sized elements supported.
4424 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4425 SDPatternOperator OpNode> {
4426 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4428 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4429 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4431 [(set (v16i8 V128:$Rd),
4432 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4435 // As above, but only S and D sized floating point elements supported.
4436 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4437 string asm, SDPatternOperator OpNode> {
4438 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4440 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4441 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4443 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4444 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4446 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4449 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4451 SDPatternOperator OpNode> {
4452 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4454 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4455 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4457 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4458 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4460 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4463 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4464 string asm, SDPatternOperator OpNode> {
4465 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4467 [(set (v2f32 V64:$dst),
4468 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4469 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4471 [(set (v4f32 V128:$dst),
4472 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4473 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4475 [(set (v2f64 V128:$dst),
4476 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4479 // As above, but D and B sized elements unsupported.
4480 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4481 SDPatternOperator OpNode> {
4482 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4484 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4485 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4487 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4488 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4490 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4491 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4493 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4496 // Logical three vector ops share opcode bits, and only use B sized elements.
4497 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4498 SDPatternOperator OpNode = null_frag> {
4499 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4501 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4502 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4504 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4506 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4507 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4508 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4509 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4510 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4511 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4513 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4514 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4515 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4516 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4517 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4518 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4521 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4522 string asm, SDPatternOperator OpNode> {
4523 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4525 [(set (v8i8 V64:$dst),
4526 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4527 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4529 [(set (v16i8 V128:$dst),
4530 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4531 (v16i8 V128:$Rm)))]>;
4533 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4535 (!cast<Instruction>(NAME#"v8i8")
4536 V64:$LHS, V64:$MHS, V64:$RHS)>;
4537 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4539 (!cast<Instruction>(NAME#"v8i8")
4540 V64:$LHS, V64:$MHS, V64:$RHS)>;
4541 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4543 (!cast<Instruction>(NAME#"v8i8")
4544 V64:$LHS, V64:$MHS, V64:$RHS)>;
4546 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4547 (v8i16 V128:$RHS))),
4548 (!cast<Instruction>(NAME#"v16i8")
4549 V128:$LHS, V128:$MHS, V128:$RHS)>;
4550 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4551 (v4i32 V128:$RHS))),
4552 (!cast<Instruction>(NAME#"v16i8")
4553 V128:$LHS, V128:$MHS, V128:$RHS)>;
4554 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4555 (v2i64 V128:$RHS))),
4556 (!cast<Instruction>(NAME#"v16i8")
4557 V128:$LHS, V128:$MHS, V128:$RHS)>;
4561 //----------------------------------------------------------------------------
4562 // AdvSIMD two register vector instructions.
4563 //----------------------------------------------------------------------------
4565 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4566 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4567 RegisterOperand regtype, string asm, string dstkind,
4568 string srckind, list<dag> pattern>
4569 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4570 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4571 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4578 let Inst{28-24} = 0b01110;
4579 let Inst{23-22} = size;
4580 let Inst{21-17} = 0b10000;
4581 let Inst{16-12} = opcode;
4582 let Inst{11-10} = 0b10;
4587 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4588 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4589 RegisterOperand regtype, string asm, string dstkind,
4590 string srckind, list<dag> pattern>
4591 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4592 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4593 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4600 let Inst{28-24} = 0b01110;
4601 let Inst{23-22} = size;
4602 let Inst{21-17} = 0b10000;
4603 let Inst{16-12} = opcode;
4604 let Inst{11-10} = 0b10;
4609 // Supports B, H, and S element sizes.
4610 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4611 SDPatternOperator OpNode> {
4612 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4614 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4615 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4616 asm, ".16b", ".16b",
4617 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4618 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4620 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4621 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4623 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4624 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4626 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4627 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4629 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4632 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4633 RegisterOperand regtype, string asm, string dstkind,
4634 string srckind, string amount>
4635 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4636 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4637 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4643 let Inst{29-24} = 0b101110;
4644 let Inst{23-22} = size;
4645 let Inst{21-10} = 0b100001001110;
4650 multiclass SIMDVectorLShiftLongBySizeBHS {
4651 let hasSideEffects = 0 in {
4652 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4653 "shll", ".8h", ".8b", "8">;
4654 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4655 "shll2", ".8h", ".16b", "8">;
4656 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4657 "shll", ".4s", ".4h", "16">;
4658 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4659 "shll2", ".4s", ".8h", "16">;
4660 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4661 "shll", ".2d", ".2s", "32">;
4662 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4663 "shll2", ".2d", ".4s", "32">;
4667 // Supports all element sizes.
4668 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4669 SDPatternOperator OpNode> {
4670 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4672 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4673 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4675 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4676 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4678 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4679 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4681 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4682 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4684 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4685 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4687 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4690 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4691 SDPatternOperator OpNode> {
4692 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4694 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4696 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4698 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4699 (v16i8 V128:$Rn)))]>;
4700 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4702 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4703 (v4i16 V64:$Rn)))]>;
4704 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4706 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4707 (v8i16 V128:$Rn)))]>;
4708 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4710 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4711 (v2i32 V64:$Rn)))]>;
4712 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4714 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4715 (v4i32 V128:$Rn)))]>;
4718 // Supports all element sizes, except 1xD.
4719 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4720 SDPatternOperator OpNode> {
4721 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4723 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4724 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4725 asm, ".16b", ".16b",
4726 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4727 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4729 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4730 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4732 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4733 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4735 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4736 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4738 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4739 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4741 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4744 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4745 SDPatternOperator OpNode = null_frag> {
4746 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4748 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4749 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4750 asm, ".16b", ".16b",
4751 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4752 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4754 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4755 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4757 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4758 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4760 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4761 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4763 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4764 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4766 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4770 // Supports only B element sizes.
4771 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4772 SDPatternOperator OpNode> {
4773 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4775 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4776 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4777 asm, ".16b", ".16b",
4778 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4782 // Supports only B and H element sizes.
4783 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4784 SDPatternOperator OpNode> {
4785 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4787 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4788 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4789 asm, ".16b", ".16b",
4790 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4791 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4793 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4794 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4796 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4799 // Supports only S and D element sizes, uses high bit of the size field
4800 // as an extra opcode bit.
4801 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4802 SDPatternOperator OpNode> {
4803 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4805 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4806 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4808 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4809 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4811 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4814 // Supports only S element size.
4815 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4816 SDPatternOperator OpNode> {
4817 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4819 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4820 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4822 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4826 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4827 SDPatternOperator OpNode> {
4828 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4830 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4831 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4833 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4834 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4836 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4839 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4840 SDPatternOperator OpNode> {
4841 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4843 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4844 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4846 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4847 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4849 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4853 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4854 RegisterOperand inreg, RegisterOperand outreg,
4855 string asm, string outkind, string inkind,
4857 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4858 "{\t$Rd" # outkind # ", $Rn" # inkind #
4859 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4866 let Inst{28-24} = 0b01110;
4867 let Inst{23-22} = size;
4868 let Inst{21-17} = 0b10000;
4869 let Inst{16-12} = opcode;
4870 let Inst{11-10} = 0b10;
4875 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4876 RegisterOperand inreg, RegisterOperand outreg,
4877 string asm, string outkind, string inkind,
4879 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4880 "{\t$Rd" # outkind # ", $Rn" # inkind #
4881 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4888 let Inst{28-24} = 0b01110;
4889 let Inst{23-22} = size;
4890 let Inst{21-17} = 0b10000;
4891 let Inst{16-12} = opcode;
4892 let Inst{11-10} = 0b10;
4897 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4898 SDPatternOperator OpNode> {
4899 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4901 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4902 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4903 asm#"2", ".16b", ".8h", []>;
4904 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4906 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4907 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4908 asm#"2", ".8h", ".4s", []>;
4909 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4911 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4912 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4913 asm#"2", ".4s", ".2d", []>;
4915 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4916 (!cast<Instruction>(NAME # "v16i8")
4917 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4918 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4919 (!cast<Instruction>(NAME # "v8i16")
4920 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4921 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4922 (!cast<Instruction>(NAME # "v4i32")
4923 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4926 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4927 RegisterOperand regtype,
4928 string asm, string kind, string zero,
4929 ValueType dty, ValueType sty, SDNode OpNode>
4930 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4931 "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4932 "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4933 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4940 let Inst{28-24} = 0b01110;
4941 let Inst{23-22} = size;
4942 let Inst{21-17} = 0b10000;
4943 let Inst{16-12} = opcode;
4944 let Inst{11-10} = 0b10;
4949 // Comparisons support all element sizes, except 1xD.
4950 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4952 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4954 v8i8, v8i8, OpNode>;
4955 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4957 v16i8, v16i8, OpNode>;
4958 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4960 v4i16, v4i16, OpNode>;
4961 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4963 v8i16, v8i16, OpNode>;
4964 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4966 v2i32, v2i32, OpNode>;
4967 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4969 v4i32, v4i32, OpNode>;
4970 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4972 v2i64, v2i64, OpNode>;
4975 // FP Comparisons support only S and D element sizes.
4976 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4977 string asm, SDNode OpNode> {
4979 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4981 v2i32, v2f32, OpNode>;
4982 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4984 v4i32, v4f32, OpNode>;
4985 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4987 v2i64, v2f64, OpNode>;
4989 def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
4990 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4991 def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
4992 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4993 def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
4994 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4995 def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
4996 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4997 def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
4998 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4999 def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5000 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5003 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5004 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5005 RegisterOperand outtype, RegisterOperand intype,
5006 string asm, string VdTy, string VnTy,
5008 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5009 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5016 let Inst{28-24} = 0b01110;
5017 let Inst{23-22} = size;
5018 let Inst{21-17} = 0b10000;
5019 let Inst{16-12} = opcode;
5020 let Inst{11-10} = 0b10;
5025 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5026 RegisterOperand outtype, RegisterOperand intype,
5027 string asm, string VdTy, string VnTy,
5029 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5030 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5037 let Inst{28-24} = 0b01110;
5038 let Inst{23-22} = size;
5039 let Inst{21-17} = 0b10000;
5040 let Inst{16-12} = opcode;
5041 let Inst{11-10} = 0b10;
5046 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5047 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5048 asm, ".4s", ".4h", []>;
5049 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5050 asm#"2", ".4s", ".8h", []>;
5051 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5052 asm, ".2d", ".2s", []>;
5053 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5054 asm#"2", ".2d", ".4s", []>;
5057 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5058 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5059 asm, ".4h", ".4s", []>;
5060 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5061 asm#"2", ".8h", ".4s", []>;
5062 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5063 asm, ".2s", ".2d", []>;
5064 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5065 asm#"2", ".4s", ".2d", []>;
5068 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5070 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5072 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5073 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5074 asm#"2", ".4s", ".2d", []>;
5076 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5077 (!cast<Instruction>(NAME # "v4f32")
5078 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5081 //----------------------------------------------------------------------------
5082 // AdvSIMD three register different-size vector instructions.
5083 //----------------------------------------------------------------------------
5085 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5086 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5087 RegisterOperand outtype, RegisterOperand intype1,
5088 RegisterOperand intype2, string asm,
5089 string outkind, string inkind1, string inkind2,
5091 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5092 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5093 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5099 let Inst{30} = size{0};
5101 let Inst{28-24} = 0b01110;
5102 let Inst{23-22} = size{2-1};
5104 let Inst{20-16} = Rm;
5105 let Inst{15-12} = opcode;
5106 let Inst{11-10} = 0b00;
5111 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5112 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5113 RegisterOperand outtype, RegisterOperand intype1,
5114 RegisterOperand intype2, string asm,
5115 string outkind, string inkind1, string inkind2,
5117 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5118 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5119 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5125 let Inst{30} = size{0};
5127 let Inst{28-24} = 0b01110;
5128 let Inst{23-22} = size{2-1};
5130 let Inst{20-16} = Rm;
5131 let Inst{15-12} = opcode;
5132 let Inst{11-10} = 0b00;
5137 // FIXME: TableGen doesn't know how to deal with expanded types that also
5138 // change the element count (in this case, placing the results in
5139 // the high elements of the result register rather than the low
5140 // elements). Until that's fixed, we can't code-gen those.
5141 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5143 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5145 asm, ".8b", ".8h", ".8h",
5146 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5147 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5149 asm#"2", ".16b", ".8h", ".8h",
5151 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5153 asm, ".4h", ".4s", ".4s",
5154 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5155 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5157 asm#"2", ".8h", ".4s", ".4s",
5159 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5161 asm, ".2s", ".2d", ".2d",
5162 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5163 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5165 asm#"2", ".4s", ".2d", ".2d",
5169 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5170 // a version attached to an instruction.
5171 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5173 (!cast<Instruction>(NAME # "v8i16_v16i8")
5174 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5175 V128:$Rn, V128:$Rm)>;
5176 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5178 (!cast<Instruction>(NAME # "v4i32_v8i16")
5179 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5180 V128:$Rn, V128:$Rm)>;
5181 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5183 (!cast<Instruction>(NAME # "v2i64_v4i32")
5184 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5185 V128:$Rn, V128:$Rm)>;
5188 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5190 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5192 asm, ".8h", ".8b", ".8b",
5193 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5194 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5196 asm#"2", ".8h", ".16b", ".16b", []>;
5197 let Predicates = [HasCrypto] in {
5198 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5200 asm, ".1q", ".1d", ".1d", []>;
5201 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5203 asm#"2", ".1q", ".2d", ".2d", []>;
5206 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5207 (v8i8 (extract_high_v16i8 V128:$Rm)))),
5208 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5211 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5212 SDPatternOperator OpNode> {
5213 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5215 asm, ".4s", ".4h", ".4h",
5216 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5217 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5219 asm#"2", ".4s", ".8h", ".8h",
5220 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5221 (extract_high_v8i16 V128:$Rm)))]>;
5222 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5224 asm, ".2d", ".2s", ".2s",
5225 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5226 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5228 asm#"2", ".2d", ".4s", ".4s",
5229 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5230 (extract_high_v4i32 V128:$Rm)))]>;
5233 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5234 SDPatternOperator OpNode = null_frag> {
5235 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5237 asm, ".8h", ".8b", ".8b",
5238 [(set (v8i16 V128:$Rd),
5239 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5240 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5242 asm#"2", ".8h", ".16b", ".16b",
5243 [(set (v8i16 V128:$Rd),
5244 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5245 (extract_high_v16i8 V128:$Rm)))))]>;
5246 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5248 asm, ".4s", ".4h", ".4h",
5249 [(set (v4i32 V128:$Rd),
5250 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5251 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5253 asm#"2", ".4s", ".8h", ".8h",
5254 [(set (v4i32 V128:$Rd),
5255 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5256 (extract_high_v8i16 V128:$Rm)))))]>;
5257 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5259 asm, ".2d", ".2s", ".2s",
5260 [(set (v2i64 V128:$Rd),
5261 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5262 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5264 asm#"2", ".2d", ".4s", ".4s",
5265 [(set (v2i64 V128:$Rd),
5266 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5267 (extract_high_v4i32 V128:$Rm)))))]>;
5270 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5272 SDPatternOperator OpNode> {
5273 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5275 asm, ".8h", ".8b", ".8b",
5276 [(set (v8i16 V128:$dst),
5277 (add (v8i16 V128:$Rd),
5278 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5279 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5281 asm#"2", ".8h", ".16b", ".16b",
5282 [(set (v8i16 V128:$dst),
5283 (add (v8i16 V128:$Rd),
5284 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5285 (extract_high_v16i8 V128:$Rm))))))]>;
5286 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5288 asm, ".4s", ".4h", ".4h",
5289 [(set (v4i32 V128:$dst),
5290 (add (v4i32 V128:$Rd),
5291 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5292 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5294 asm#"2", ".4s", ".8h", ".8h",
5295 [(set (v4i32 V128:$dst),
5296 (add (v4i32 V128:$Rd),
5297 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5298 (extract_high_v8i16 V128:$Rm))))))]>;
5299 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5301 asm, ".2d", ".2s", ".2s",
5302 [(set (v2i64 V128:$dst),
5303 (add (v2i64 V128:$Rd),
5304 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5305 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5307 asm#"2", ".2d", ".4s", ".4s",
5308 [(set (v2i64 V128:$dst),
5309 (add (v2i64 V128:$Rd),
5310 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5311 (extract_high_v4i32 V128:$Rm))))))]>;
5314 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5315 SDPatternOperator OpNode = null_frag> {
5316 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5318 asm, ".8h", ".8b", ".8b",
5319 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5320 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5322 asm#"2", ".8h", ".16b", ".16b",
5323 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5324 (extract_high_v16i8 V128:$Rm)))]>;
5325 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5327 asm, ".4s", ".4h", ".4h",
5328 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5329 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5331 asm#"2", ".4s", ".8h", ".8h",
5332 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5333 (extract_high_v8i16 V128:$Rm)))]>;
5334 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5336 asm, ".2d", ".2s", ".2s",
5337 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5338 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5340 asm#"2", ".2d", ".4s", ".4s",
5341 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5342 (extract_high_v4i32 V128:$Rm)))]>;
5345 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5347 SDPatternOperator OpNode> {
5348 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5350 asm, ".8h", ".8b", ".8b",
5351 [(set (v8i16 V128:$dst),
5352 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5353 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5355 asm#"2", ".8h", ".16b", ".16b",
5356 [(set (v8i16 V128:$dst),
5357 (OpNode (v8i16 V128:$Rd),
5358 (extract_high_v16i8 V128:$Rn),
5359 (extract_high_v16i8 V128:$Rm)))]>;
5360 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5362 asm, ".4s", ".4h", ".4h",
5363 [(set (v4i32 V128:$dst),
5364 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5365 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5367 asm#"2", ".4s", ".8h", ".8h",
5368 [(set (v4i32 V128:$dst),
5369 (OpNode (v4i32 V128:$Rd),
5370 (extract_high_v8i16 V128:$Rn),
5371 (extract_high_v8i16 V128:$Rm)))]>;
5372 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5374 asm, ".2d", ".2s", ".2s",
5375 [(set (v2i64 V128:$dst),
5376 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5377 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5379 asm#"2", ".2d", ".4s", ".4s",
5380 [(set (v2i64 V128:$dst),
5381 (OpNode (v2i64 V128:$Rd),
5382 (extract_high_v4i32 V128:$Rn),
5383 (extract_high_v4i32 V128:$Rm)))]>;
5386 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5387 SDPatternOperator Accum> {
5388 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5390 asm, ".4s", ".4h", ".4h",
5391 [(set (v4i32 V128:$dst),
5392 (Accum (v4i32 V128:$Rd),
5393 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5394 (v4i16 V64:$Rm)))))]>;
5395 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5397 asm#"2", ".4s", ".8h", ".8h",
5398 [(set (v4i32 V128:$dst),
5399 (Accum (v4i32 V128:$Rd),
5400 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5401 (extract_high_v8i16 V128:$Rm)))))]>;
5402 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5404 asm, ".2d", ".2s", ".2s",
5405 [(set (v2i64 V128:$dst),
5406 (Accum (v2i64 V128:$Rd),
5407 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5408 (v2i32 V64:$Rm)))))]>;
5409 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5411 asm#"2", ".2d", ".4s", ".4s",
5412 [(set (v2i64 V128:$dst),
5413 (Accum (v2i64 V128:$Rd),
5414 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5415 (extract_high_v4i32 V128:$Rm)))))]>;
5418 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5419 SDPatternOperator OpNode> {
5420 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5422 asm, ".8h", ".8h", ".8b",
5423 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5424 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5426 asm#"2", ".8h", ".8h", ".16b",
5427 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5428 (extract_high_v16i8 V128:$Rm)))]>;
5429 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5431 asm, ".4s", ".4s", ".4h",
5432 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5433 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5435 asm#"2", ".4s", ".4s", ".8h",
5436 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5437 (extract_high_v8i16 V128:$Rm)))]>;
5438 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5440 asm, ".2d", ".2d", ".2s",
5441 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5442 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5444 asm#"2", ".2d", ".2d", ".4s",
5445 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5446 (extract_high_v4i32 V128:$Rm)))]>;
5449 //----------------------------------------------------------------------------
5450 // AdvSIMD bitwise extract from vector
5451 //----------------------------------------------------------------------------
5453 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5454 string asm, string kind>
5455 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5456 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5457 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5458 [(set (vty regtype:$Rd),
5459 (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5466 let Inst{30} = size;
5467 let Inst{29-21} = 0b101110000;
5468 let Inst{20-16} = Rm;
5470 let Inst{14-11} = imm;
5477 multiclass SIMDBitwiseExtract<string asm> {
5478 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5481 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5484 //----------------------------------------------------------------------------
5485 // AdvSIMD zip vector
5486 //----------------------------------------------------------------------------
5488 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5489 string asm, string kind, SDNode OpNode, ValueType valty>
5490 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5491 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5492 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5493 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5499 let Inst{30} = size{0};
5500 let Inst{29-24} = 0b001110;
5501 let Inst{23-22} = size{2-1};
5503 let Inst{20-16} = Rm;
5505 let Inst{14-12} = opc;
5506 let Inst{11-10} = 0b10;
5511 multiclass SIMDZipVector<bits<3>opc, string asm,
5513 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
5514 asm, ".8b", OpNode, v8i8>;
5515 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
5516 asm, ".16b", OpNode, v16i8>;
5517 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
5518 asm, ".4h", OpNode, v4i16>;
5519 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
5520 asm, ".8h", OpNode, v8i16>;
5521 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
5522 asm, ".2s", OpNode, v2i32>;
5523 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
5524 asm, ".4s", OpNode, v4i32>;
5525 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
5526 asm, ".2d", OpNode, v2i64>;
5528 def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5529 (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5530 def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5531 (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5532 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5533 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5534 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5535 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5536 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5537 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5540 //----------------------------------------------------------------------------
5541 // AdvSIMD three register scalar instructions
5542 //----------------------------------------------------------------------------
5544 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5545 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5546 RegisterClass regtype, string asm,
5548 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5549 "\t$Rd, $Rn, $Rm", "", pattern>,
5554 let Inst{31-30} = 0b01;
5556 let Inst{28-24} = 0b11110;
5557 let Inst{23-22} = size;
5559 let Inst{20-16} = Rm;
5560 let Inst{15-11} = opcode;
5566 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5567 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5568 dag oops, dag iops, string asm,
5570 : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5575 let Inst{31-30} = 0b01;
5577 let Inst{28-24} = 0b11110;
5578 let Inst{23-22} = size;
5580 let Inst{20-16} = Rm;
5581 let Inst{15-11} = opcode;
5587 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5588 SDPatternOperator OpNode> {
5589 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5590 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5593 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5594 SDPatternOperator OpNode> {
5595 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5596 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5597 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5598 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5599 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5601 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5602 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5603 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5604 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5607 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5608 SDPatternOperator OpNode> {
5609 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5610 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5611 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5614 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5615 SDPatternOperator OpNode = null_frag> {
5616 def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5617 (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
5619 def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5620 (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
5624 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5625 SDPatternOperator OpNode = null_frag> {
5626 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5627 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5628 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5629 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5630 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5633 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5634 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5637 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5638 SDPatternOperator OpNode = null_frag> {
5639 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5640 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5641 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5642 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5643 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5646 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5647 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5650 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5651 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5652 : I<oops, iops, asm,
5653 "\t$Rd, $Rn, $Rm", cstr, pat>,
5658 let Inst{31-30} = 0b01;
5660 let Inst{28-24} = 0b11110;
5661 let Inst{23-22} = size;
5663 let Inst{20-16} = Rm;
5664 let Inst{15-11} = opcode;
5670 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5671 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5672 SDPatternOperator OpNode = null_frag> {
5673 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5675 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5676 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5678 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5679 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5682 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5683 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5684 SDPatternOperator OpNode = null_frag> {
5685 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5687 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5688 asm, "$Rd = $dst", []>;
5689 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5691 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5693 [(set (i64 FPR64:$dst),
5694 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5697 //----------------------------------------------------------------------------
5698 // AdvSIMD two register scalar instructions
5699 //----------------------------------------------------------------------------
5701 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5702 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5703 RegisterClass regtype, RegisterClass regtype2,
5704 string asm, list<dag> pat>
5705 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5706 "\t$Rd, $Rn", "", pat>,
5710 let Inst{31-30} = 0b01;
5712 let Inst{28-24} = 0b11110;
5713 let Inst{23-22} = size;
5714 let Inst{21-17} = 0b10000;
5715 let Inst{16-12} = opcode;
5716 let Inst{11-10} = 0b10;
5721 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5722 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5723 RegisterClass regtype, RegisterClass regtype2,
5724 string asm, list<dag> pat>
5725 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5726 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5730 let Inst{31-30} = 0b01;
5732 let Inst{28-24} = 0b11110;
5733 let Inst{23-22} = size;
5734 let Inst{21-17} = 0b10000;
5735 let Inst{16-12} = opcode;
5736 let Inst{11-10} = 0b10;
5742 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5743 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5744 RegisterClass regtype, string asm, string zero>
5745 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5746 "\t$Rd, $Rn, #" # zero, "", []>,
5750 let Inst{31-30} = 0b01;
5752 let Inst{28-24} = 0b11110;
5753 let Inst{23-22} = size;
5754 let Inst{21-17} = 0b10000;
5755 let Inst{16-12} = opcode;
5756 let Inst{11-10} = 0b10;
5761 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5762 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5763 [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5767 let Inst{31-17} = 0b011111100110000;
5768 let Inst{16-12} = opcode;
5769 let Inst{11-10} = 0b10;
5774 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5775 SDPatternOperator OpNode> {
5776 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5778 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5779 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5782 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5783 SDPatternOperator OpNode> {
5784 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5785 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5787 def : InstAlias<asm # "\t$Rd, $Rn, #0",
5788 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5789 def : InstAlias<asm # "\t$Rd, $Rn, #0",
5790 (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5792 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5793 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5796 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5797 SDPatternOperator OpNode = null_frag> {
5798 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5799 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5801 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5802 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5805 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5806 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5807 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5810 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5811 SDPatternOperator OpNode> {
5812 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5813 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5814 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5815 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5818 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5819 SDPatternOperator OpNode = null_frag> {
5820 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5821 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5822 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5823 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5824 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5825 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5826 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5829 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5830 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5833 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5835 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5836 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5837 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5838 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5839 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5840 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5841 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5844 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5845 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5850 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5851 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5852 SDPatternOperator OpNode = null_frag> {
5853 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5854 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5855 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5856 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5859 //----------------------------------------------------------------------------
5860 // AdvSIMD scalar pairwise instructions
5861 //----------------------------------------------------------------------------
5863 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5864 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5865 RegisterOperand regtype, RegisterOperand vectype,
5866 string asm, string kind>
5867 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5868 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5872 let Inst{31-30} = 0b01;
5874 let Inst{28-24} = 0b11110;
5875 let Inst{23-22} = size;
5876 let Inst{21-17} = 0b11000;
5877 let Inst{16-12} = opcode;
5878 let Inst{11-10} = 0b10;
5883 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5884 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5888 multiclass SIMDFPPairwiseScalar<bit U, bit S, bits<5> opc, string asm> {
5889 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5891 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5895 //----------------------------------------------------------------------------
5896 // AdvSIMD across lanes instructions
5897 //----------------------------------------------------------------------------
5899 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5900 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5901 RegisterClass regtype, RegisterOperand vectype,
5902 string asm, string kind, list<dag> pattern>
5903 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5904 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5911 let Inst{28-24} = 0b01110;
5912 let Inst{23-22} = size;
5913 let Inst{21-17} = 0b11000;
5914 let Inst{16-12} = opcode;
5915 let Inst{11-10} = 0b10;
5920 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5922 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5924 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5926 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5928 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5930 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5934 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5935 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5937 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5939 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5941 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5943 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5947 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5949 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5951 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5954 //----------------------------------------------------------------------------
5955 // AdvSIMD INS/DUP instructions
5956 //----------------------------------------------------------------------------
5958 // FIXME: There has got to be a better way to factor these. ugh.
5960 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5961 string operands, string constraints, list<dag> pattern>
5962 : I<outs, ins, asm, operands, constraints, pattern>,
5969 let Inst{28-21} = 0b01110000;
5976 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5977 RegisterOperand vecreg, RegisterClass regtype>
5978 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5979 "{\t$Rd" # size # ", $Rn" #
5980 "|" # size # "\t$Rd, $Rn}", "",
5981 [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5982 let Inst{20-16} = imm5;
5983 let Inst{14-11} = 0b0001;
5986 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5987 ValueType vectype, ValueType insreg,
5988 RegisterOperand vecreg, Operand idxtype,
5989 ValueType elttype, SDNode OpNode>
5990 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5991 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5992 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5993 [(set (vectype vecreg:$Rd),
5994 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5995 let Inst{14-11} = 0b0000;
5998 class SIMDDup64FromElement
5999 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6000 VectorIndexD, i64, AArch64duplane64> {
6003 let Inst{19-16} = 0b1000;
6006 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6007 RegisterOperand vecreg>
6008 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6009 VectorIndexS, i64, AArch64duplane32> {
6011 let Inst{20-19} = idx;
6012 let Inst{18-16} = 0b100;
6015 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6016 RegisterOperand vecreg>
6017 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6018 VectorIndexH, i64, AArch64duplane16> {
6020 let Inst{20-18} = idx;
6021 let Inst{17-16} = 0b10;
6024 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6025 RegisterOperand vecreg>
6026 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6027 VectorIndexB, i64, AArch64duplane8> {
6029 let Inst{20-17} = idx;
6033 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6034 Operand idxtype, string asm, list<dag> pattern>
6035 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6036 "{\t$Rd, $Rn" # size # "$idx" #
6037 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6038 let Inst{14-11} = imm4;
6041 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6043 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6044 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6046 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6047 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6049 class SIMDMovAlias<string asm, string size, Instruction inst,
6050 RegisterClass regtype, Operand idxtype>
6051 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6052 "|" # size # "\t$dst, $src$idx}",
6053 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6056 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6058 let Inst{20-17} = idx;
6061 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6063 let Inst{20-17} = idx;
6066 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6068 let Inst{20-18} = idx;
6069 let Inst{17-16} = 0b10;
6071 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6073 let Inst{20-18} = idx;
6074 let Inst{17-16} = 0b10;
6076 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6078 let Inst{20-19} = idx;
6079 let Inst{18-16} = 0b100;
6084 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6086 let Inst{20-17} = idx;
6089 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6091 let Inst{20-18} = idx;
6092 let Inst{17-16} = 0b10;
6094 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6096 let Inst{20-19} = idx;
6097 let Inst{18-16} = 0b100;
6099 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6102 let Inst{19-16} = 0b1000;
6104 def : SIMDMovAlias<"mov", ".s",
6105 !cast<Instruction>(NAME#"vi32"),
6106 GPR32, VectorIndexS>;
6107 def : SIMDMovAlias<"mov", ".d",
6108 !cast<Instruction>(NAME#"vi64"),
6109 GPR64, VectorIndexD>;
6112 class SIMDInsFromMain<string size, ValueType vectype,
6113 RegisterClass regtype, Operand idxtype>
6114 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6115 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6116 "{\t$Rd" # size # "$idx, $Rn" #
6117 "|" # size # "\t$Rd$idx, $Rn}",
6120 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6121 let Inst{14-11} = 0b0011;
6124 class SIMDInsFromElement<string size, ValueType vectype,
6125 ValueType elttype, Operand idxtype>
6126 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6127 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6128 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6129 "|" # size # "\t$Rd$idx, $Rn$idx2}",
6134 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6137 class SIMDInsMainMovAlias<string size, Instruction inst,
6138 RegisterClass regtype, Operand idxtype>
6139 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6140 "|" # size #"\t$dst$idx, $src}",
6141 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6142 class SIMDInsElementMovAlias<string size, Instruction inst,
6144 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6145 # "|" # size #"\t$dst$idx, $src$idx2}",
6146 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6149 multiclass SIMDIns {
6150 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6152 let Inst{20-17} = idx;
6155 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6157 let Inst{20-18} = idx;
6158 let Inst{17-16} = 0b10;
6160 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6162 let Inst{20-19} = idx;
6163 let Inst{18-16} = 0b100;
6165 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6168 let Inst{19-16} = 0b1000;
6171 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6174 let Inst{20-17} = idx;
6176 let Inst{14-11} = idx2;
6178 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6181 let Inst{20-18} = idx;
6182 let Inst{17-16} = 0b10;
6183 let Inst{14-12} = idx2;
6186 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6189 let Inst{20-19} = idx;
6190 let Inst{18-16} = 0b100;
6191 let Inst{14-13} = idx2;
6192 let Inst{12-11} = {?,?};
6194 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6198 let Inst{19-16} = 0b1000;
6199 let Inst{14} = idx2;
6200 let Inst{13-11} = {?,?,?};
6203 // For all forms of the INS instruction, the "mov" mnemonic is the
6204 // preferred alias. Why they didn't just call the instruction "mov" in
6205 // the first place is a very good question indeed...
6206 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6207 GPR32, VectorIndexB>;
6208 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6209 GPR32, VectorIndexH>;
6210 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6211 GPR32, VectorIndexS>;
6212 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6213 GPR64, VectorIndexD>;
6215 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6217 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6219 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6221 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6225 //----------------------------------------------------------------------------
6227 //----------------------------------------------------------------------------
6229 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6230 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6231 RegisterOperand listtype, string asm, string kind>
6232 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6233 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6240 let Inst{29-21} = 0b001110000;
6241 let Inst{20-16} = Vm;
6243 let Inst{14-13} = len;
6245 let Inst{11-10} = 0b00;
6250 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6251 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6252 RegisterOperand listtype, string asm, string kind>
6253 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6254 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6261 let Inst{29-21} = 0b001110000;
6262 let Inst{20-16} = Vm;
6264 let Inst{14-13} = len;
6266 let Inst{11-10} = 0b00;
6271 class SIMDTableLookupAlias<string asm, Instruction inst,
6272 RegisterOperand vectype, RegisterOperand listtype>
6273 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6274 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6276 multiclass SIMDTableLookup<bit op, string asm> {
6277 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6279 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6281 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6283 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6285 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6287 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6289 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6291 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6294 def : SIMDTableLookupAlias<asm # ".8b",
6295 !cast<Instruction>(NAME#"v8i8One"),
6296 V64, VecListOne128>;
6297 def : SIMDTableLookupAlias<asm # ".8b",
6298 !cast<Instruction>(NAME#"v8i8Two"),
6299 V64, VecListTwo128>;
6300 def : SIMDTableLookupAlias<asm # ".8b",
6301 !cast<Instruction>(NAME#"v8i8Three"),
6302 V64, VecListThree128>;
6303 def : SIMDTableLookupAlias<asm # ".8b",
6304 !cast<Instruction>(NAME#"v8i8Four"),
6305 V64, VecListFour128>;
6306 def : SIMDTableLookupAlias<asm # ".16b",
6307 !cast<Instruction>(NAME#"v16i8One"),
6308 V128, VecListOne128>;
6309 def : SIMDTableLookupAlias<asm # ".16b",
6310 !cast<Instruction>(NAME#"v16i8Two"),
6311 V128, VecListTwo128>;
6312 def : SIMDTableLookupAlias<asm # ".16b",
6313 !cast<Instruction>(NAME#"v16i8Three"),
6314 V128, VecListThree128>;
6315 def : SIMDTableLookupAlias<asm # ".16b",
6316 !cast<Instruction>(NAME#"v16i8Four"),
6317 V128, VecListFour128>;
6320 multiclass SIMDTableLookupTied<bit op, string asm> {
6321 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6323 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6325 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6327 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6329 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6331 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6333 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6335 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6338 def : SIMDTableLookupAlias<asm # ".8b",
6339 !cast<Instruction>(NAME#"v8i8One"),
6340 V64, VecListOne128>;
6341 def : SIMDTableLookupAlias<asm # ".8b",
6342 !cast<Instruction>(NAME#"v8i8Two"),
6343 V64, VecListTwo128>;
6344 def : SIMDTableLookupAlias<asm # ".8b",
6345 !cast<Instruction>(NAME#"v8i8Three"),
6346 V64, VecListThree128>;
6347 def : SIMDTableLookupAlias<asm # ".8b",
6348 !cast<Instruction>(NAME#"v8i8Four"),
6349 V64, VecListFour128>;
6350 def : SIMDTableLookupAlias<asm # ".16b",
6351 !cast<Instruction>(NAME#"v16i8One"),
6352 V128, VecListOne128>;
6353 def : SIMDTableLookupAlias<asm # ".16b",
6354 !cast<Instruction>(NAME#"v16i8Two"),
6355 V128, VecListTwo128>;
6356 def : SIMDTableLookupAlias<asm # ".16b",
6357 !cast<Instruction>(NAME#"v16i8Three"),
6358 V128, VecListThree128>;
6359 def : SIMDTableLookupAlias<asm # ".16b",
6360 !cast<Instruction>(NAME#"v16i8Four"),
6361 V128, VecListFour128>;
6365 //----------------------------------------------------------------------------
6366 // AdvSIMD scalar CPY
6367 //----------------------------------------------------------------------------
6368 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6369 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6370 string kind, Operand idxtype>
6371 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6372 "{\t$dst, $src" # kind # "$idx" #
6373 "|\t$dst, $src$idx}", "", []>,
6377 let Inst{31-21} = 0b01011110000;
6378 let Inst{15-10} = 0b000001;
6379 let Inst{9-5} = src;
6380 let Inst{4-0} = dst;
6383 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6384 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6385 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6386 # "|\t$dst, $src$index}",
6387 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6390 multiclass SIMDScalarCPY<string asm> {
6391 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
6393 let Inst{20-17} = idx;
6396 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6398 let Inst{20-18} = idx;
6399 let Inst{17-16} = 0b10;
6401 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6403 let Inst{20-19} = idx;
6404 let Inst{18-16} = 0b100;
6406 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6409 let Inst{19-16} = 0b1000;
6412 def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6413 VectorIndexD:$idx)))),
6414 (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6416 // 'DUP' mnemonic aliases.
6417 def : SIMDScalarCPYAlias<"dup", ".b",
6418 !cast<Instruction>(NAME#"i8"),
6419 FPR8, V128, VectorIndexB>;
6420 def : SIMDScalarCPYAlias<"dup", ".h",
6421 !cast<Instruction>(NAME#"i16"),
6422 FPR16, V128, VectorIndexH>;
6423 def : SIMDScalarCPYAlias<"dup", ".s",
6424 !cast<Instruction>(NAME#"i32"),
6425 FPR32, V128, VectorIndexS>;
6426 def : SIMDScalarCPYAlias<"dup", ".d",
6427 !cast<Instruction>(NAME#"i64"),
6428 FPR64, V128, VectorIndexD>;
6431 //----------------------------------------------------------------------------
6432 // AdvSIMD modified immediate instructions
6433 //----------------------------------------------------------------------------
6435 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6436 string asm, string op_string,
6437 string cstr, list<dag> pattern>
6438 : I<oops, iops, asm, op_string, cstr, pattern>,
6445 let Inst{28-19} = 0b0111100000;
6446 let Inst{18-16} = imm8{7-5};
6447 let Inst{11-10} = 0b01;
6448 let Inst{9-5} = imm8{4-0};
6452 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6453 Operand immtype, dag opt_shift_iop,
6454 string opt_shift, string asm, string kind,
6456 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6457 !con((ins immtype:$imm8), opt_shift_iop), asm,
6458 "{\t$Rd" # kind # ", $imm8" # opt_shift #
6459 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6461 let DecoderMethod = "DecodeModImmInstruction";
6464 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6465 Operand immtype, dag opt_shift_iop,
6466 string opt_shift, string asm, string kind,
6468 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6469 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6470 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6471 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6472 "$Rd = $dst", pattern> {
6473 let DecoderMethod = "DecodeModImmTiedInstruction";
6476 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6477 RegisterOperand vectype, string asm,
6478 string kind, list<dag> pattern>
6479 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6480 (ins logical_vec_shift:$shift),
6481 "$shift", asm, kind, pattern> {
6483 let Inst{15} = b15_b12{1};
6484 let Inst{14-13} = shift;
6485 let Inst{12} = b15_b12{0};
6488 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6489 RegisterOperand vectype, string asm,
6490 string kind, list<dag> pattern>
6491 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6492 (ins logical_vec_shift:$shift),
6493 "$shift", asm, kind, pattern> {
6495 let Inst{15} = b15_b12{1};
6496 let Inst{14-13} = shift;
6497 let Inst{12} = b15_b12{0};
6501 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6502 RegisterOperand vectype, string asm,
6503 string kind, list<dag> pattern>
6504 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6505 (ins logical_vec_hw_shift:$shift),
6506 "$shift", asm, kind, pattern> {
6508 let Inst{15} = b15_b12{1};
6510 let Inst{13} = shift{0};
6511 let Inst{12} = b15_b12{0};
6514 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6515 RegisterOperand vectype, string asm,
6516 string kind, list<dag> pattern>
6517 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6518 (ins logical_vec_hw_shift:$shift),
6519 "$shift", asm, kind, pattern> {
6521 let Inst{15} = b15_b12{1};
6523 let Inst{13} = shift{0};
6524 let Inst{12} = b15_b12{0};
6527 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6529 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6531 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6534 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6536 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6540 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6541 bits<2> w_cmode, string asm,
6543 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6545 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6547 (i32 imm:$shift)))]>;
6548 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6550 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6552 (i32 imm:$shift)))]>;
6554 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6556 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6558 (i32 imm:$shift)))]>;
6559 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6561 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6563 (i32 imm:$shift)))]>;
6566 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6567 RegisterOperand vectype, string asm,
6568 string kind, list<dag> pattern>
6569 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6570 (ins move_vec_shift:$shift),
6571 "$shift", asm, kind, pattern> {
6573 let Inst{15-13} = cmode{3-1};
6574 let Inst{12} = shift;
6577 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6578 RegisterOperand vectype,
6579 Operand imm_type, string asm,
6580 string kind, list<dag> pattern>
6581 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6582 asm, kind, pattern> {
6583 let Inst{15-12} = cmode;
6586 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6588 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6589 "\t$Rd, $imm8", "", pattern> {
6590 let Inst{15-12} = cmode;
6591 let DecoderMethod = "DecodeModImmInstruction";
6594 //----------------------------------------------------------------------------
6595 // AdvSIMD indexed element
6596 //----------------------------------------------------------------------------
6598 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6599 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6600 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6601 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6602 string apple_kind, string dst_kind, string lhs_kind,
6603 string rhs_kind, list<dag> pattern>
6604 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6606 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6607 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6616 let Inst{28} = Scalar;
6617 let Inst{27-24} = 0b1111;
6618 let Inst{23-22} = size;
6619 // Bit 21 must be set by the derived class.
6620 let Inst{20-16} = Rm;
6621 let Inst{15-12} = opc;
6622 // Bit 11 must be set by the derived class.
6628 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6629 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6630 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6631 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6632 string apple_kind, string dst_kind, string lhs_kind,
6633 string rhs_kind, list<dag> pattern>
6634 : I<(outs dst_reg:$dst),
6635 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6636 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6637 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6646 let Inst{28} = Scalar;
6647 let Inst{27-24} = 0b1111;
6648 let Inst{23-22} = size;
6649 // Bit 21 must be set by the derived class.
6650 let Inst{20-16} = Rm;
6651 let Inst{15-12} = opc;
6652 // Bit 11 must be set by the derived class.
6658 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6659 SDPatternOperator OpNode> {
6660 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6663 asm, ".2s", ".2s", ".2s", ".s",
6664 [(set (v2f32 V64:$Rd),
6665 (OpNode (v2f32 V64:$Rn),
6666 (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6668 let Inst{11} = idx{1};
6669 let Inst{21} = idx{0};
6672 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6675 asm, ".4s", ".4s", ".4s", ".s",
6676 [(set (v4f32 V128:$Rd),
6677 (OpNode (v4f32 V128:$Rn),
6678 (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6680 let Inst{11} = idx{1};
6681 let Inst{21} = idx{0};
6684 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6687 asm, ".2d", ".2d", ".2d", ".d",
6688 [(set (v2f64 V128:$Rd),
6689 (OpNode (v2f64 V128:$Rn),
6690 (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6692 let Inst{11} = idx{0};
6696 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6697 FPR32Op, FPR32Op, V128, VectorIndexS,
6698 asm, ".s", "", "", ".s",
6699 [(set (f32 FPR32Op:$Rd),
6700 (OpNode (f32 FPR32Op:$Rn),
6701 (f32 (vector_extract (v4f32 V128:$Rm),
6702 VectorIndexS:$idx))))]> {
6704 let Inst{11} = idx{1};
6705 let Inst{21} = idx{0};
6708 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6709 FPR64Op, FPR64Op, V128, VectorIndexD,
6710 asm, ".d", "", "", ".d",
6711 [(set (f64 FPR64Op:$Rd),
6712 (OpNode (f64 FPR64Op:$Rn),
6713 (f64 (vector_extract (v2f64 V128:$Rm),
6714 VectorIndexD:$idx))))]> {
6716 let Inst{11} = idx{0};
6721 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6722 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6723 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6724 (AArch64duplane32 (v4f32 V128:$Rm),
6725 VectorIndexS:$idx))),
6726 (!cast<Instruction>(INST # v2i32_indexed)
6727 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6728 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6729 (AArch64dup (f32 FPR32Op:$Rm)))),
6730 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6731 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6734 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6735 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6736 (AArch64duplane32 (v4f32 V128:$Rm),
6737 VectorIndexS:$idx))),
6738 (!cast<Instruction>(INST # "v4i32_indexed")
6739 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6740 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6741 (AArch64dup (f32 FPR32Op:$Rm)))),
6742 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6743 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6745 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6746 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6747 (AArch64duplane64 (v2f64 V128:$Rm),
6748 VectorIndexD:$idx))),
6749 (!cast<Instruction>(INST # "v2i64_indexed")
6750 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6751 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6752 (AArch64dup (f64 FPR64Op:$Rm)))),
6753 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6754 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6756 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6757 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6758 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6759 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6760 V128:$Rm, VectorIndexS:$idx)>;
6761 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6762 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6763 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6764 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6766 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6767 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6768 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6769 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6770 V128:$Rm, VectorIndexD:$idx)>;
6773 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6774 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6776 asm, ".2s", ".2s", ".2s", ".s", []> {
6778 let Inst{11} = idx{1};
6779 let Inst{21} = idx{0};
6782 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6785 asm, ".4s", ".4s", ".4s", ".s", []> {
6787 let Inst{11} = idx{1};
6788 let Inst{21} = idx{0};
6791 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6794 asm, ".2d", ".2d", ".2d", ".d", []> {
6796 let Inst{11} = idx{0};
6801 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6802 FPR32Op, FPR32Op, V128, VectorIndexS,
6803 asm, ".s", "", "", ".s", []> {
6805 let Inst{11} = idx{1};
6806 let Inst{21} = idx{0};
6809 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6810 FPR64Op, FPR64Op, V128, VectorIndexD,
6811 asm, ".d", "", "", ".d", []> {
6813 let Inst{11} = idx{0};
6818 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6819 SDPatternOperator OpNode> {
6820 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6821 V128_lo, VectorIndexH,
6822 asm, ".4h", ".4h", ".4h", ".h",
6823 [(set (v4i16 V64:$Rd),
6824 (OpNode (v4i16 V64:$Rn),
6825 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6827 let Inst{11} = idx{2};
6828 let Inst{21} = idx{1};
6829 let Inst{20} = idx{0};
6832 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6834 V128_lo, VectorIndexH,
6835 asm, ".8h", ".8h", ".8h", ".h",
6836 [(set (v8i16 V128:$Rd),
6837 (OpNode (v8i16 V128:$Rn),
6838 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6840 let Inst{11} = idx{2};
6841 let Inst{21} = idx{1};
6842 let Inst{20} = idx{0};
6845 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6848 asm, ".2s", ".2s", ".2s", ".s",
6849 [(set (v2i32 V64:$Rd),
6850 (OpNode (v2i32 V64:$Rn),
6851 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6853 let Inst{11} = idx{1};
6854 let Inst{21} = idx{0};
6857 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6860 asm, ".4s", ".4s", ".4s", ".s",
6861 [(set (v4i32 V128:$Rd),
6862 (OpNode (v4i32 V128:$Rn),
6863 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6865 let Inst{11} = idx{1};
6866 let Inst{21} = idx{0};
6869 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6870 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6871 asm, ".h", "", "", ".h", []> {
6873 let Inst{11} = idx{2};
6874 let Inst{21} = idx{1};
6875 let Inst{20} = idx{0};
6878 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6879 FPR32Op, FPR32Op, V128, VectorIndexS,
6880 asm, ".s", "", "", ".s",
6881 [(set (i32 FPR32Op:$Rd),
6882 (OpNode FPR32Op:$Rn,
6883 (i32 (vector_extract (v4i32 V128:$Rm),
6884 VectorIndexS:$idx))))]> {
6886 let Inst{11} = idx{1};
6887 let Inst{21} = idx{0};
6891 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6892 SDPatternOperator OpNode> {
6893 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6895 V128_lo, VectorIndexH,
6896 asm, ".4h", ".4h", ".4h", ".h",
6897 [(set (v4i16 V64:$Rd),
6898 (OpNode (v4i16 V64:$Rn),
6899 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6901 let Inst{11} = idx{2};
6902 let Inst{21} = idx{1};
6903 let Inst{20} = idx{0};
6906 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6908 V128_lo, VectorIndexH,
6909 asm, ".8h", ".8h", ".8h", ".h",
6910 [(set (v8i16 V128:$Rd),
6911 (OpNode (v8i16 V128:$Rn),
6912 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6914 let Inst{11} = idx{2};
6915 let Inst{21} = idx{1};
6916 let Inst{20} = idx{0};
6919 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6922 asm, ".2s", ".2s", ".2s", ".s",
6923 [(set (v2i32 V64:$Rd),
6924 (OpNode (v2i32 V64:$Rn),
6925 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6927 let Inst{11} = idx{1};
6928 let Inst{21} = idx{0};
6931 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6934 asm, ".4s", ".4s", ".4s", ".s",
6935 [(set (v4i32 V128:$Rd),
6936 (OpNode (v4i32 V128:$Rn),
6937 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6939 let Inst{11} = idx{1};
6940 let Inst{21} = idx{0};
6944 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6945 SDPatternOperator OpNode> {
6946 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6947 V128_lo, VectorIndexH,
6948 asm, ".4h", ".4h", ".4h", ".h",
6949 [(set (v4i16 V64:$dst),
6950 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6951 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6953 let Inst{11} = idx{2};
6954 let Inst{21} = idx{1};
6955 let Inst{20} = idx{0};
6958 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6960 V128_lo, VectorIndexH,
6961 asm, ".8h", ".8h", ".8h", ".h",
6962 [(set (v8i16 V128:$dst),
6963 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6964 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6966 let Inst{11} = idx{2};
6967 let Inst{21} = idx{1};
6968 let Inst{20} = idx{0};
6971 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6974 asm, ".2s", ".2s", ".2s", ".s",
6975 [(set (v2i32 V64:$dst),
6976 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6977 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6979 let Inst{11} = idx{1};
6980 let Inst{21} = idx{0};
6983 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6986 asm, ".4s", ".4s", ".4s", ".s",
6987 [(set (v4i32 V128:$dst),
6988 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6989 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6991 let Inst{11} = idx{1};
6992 let Inst{21} = idx{0};
6996 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6997 SDPatternOperator OpNode> {
6998 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7000 V128_lo, VectorIndexH,
7001 asm, ".4s", ".4s", ".4h", ".h",
7002 [(set (v4i32 V128:$Rd),
7003 (OpNode (v4i16 V64:$Rn),
7004 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7006 let Inst{11} = idx{2};
7007 let Inst{21} = idx{1};
7008 let Inst{20} = idx{0};
7011 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7013 V128_lo, VectorIndexH,
7014 asm#"2", ".4s", ".4s", ".8h", ".h",
7015 [(set (v4i32 V128:$Rd),
7016 (OpNode (extract_high_v8i16 V128:$Rn),
7017 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7018 VectorIndexH:$idx))))]> {
7021 let Inst{11} = idx{2};
7022 let Inst{21} = idx{1};
7023 let Inst{20} = idx{0};
7026 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7029 asm, ".2d", ".2d", ".2s", ".s",
7030 [(set (v2i64 V128:$Rd),
7031 (OpNode (v2i32 V64:$Rn),
7032 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7034 let Inst{11} = idx{1};
7035 let Inst{21} = idx{0};
7038 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7041 asm#"2", ".2d", ".2d", ".4s", ".s",
7042 [(set (v2i64 V128:$Rd),
7043 (OpNode (extract_high_v4i32 V128:$Rn),
7044 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7045 VectorIndexS:$idx))))]> {
7047 let Inst{11} = idx{1};
7048 let Inst{21} = idx{0};
7051 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7052 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7053 asm, ".h", "", "", ".h", []> {
7055 let Inst{11} = idx{2};
7056 let Inst{21} = idx{1};
7057 let Inst{20} = idx{0};
7060 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7061 FPR64Op, FPR32Op, V128, VectorIndexS,
7062 asm, ".s", "", "", ".s", []> {
7064 let Inst{11} = idx{1};
7065 let Inst{21} = idx{0};
7069 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7070 SDPatternOperator Accum> {
7071 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7073 V128_lo, VectorIndexH,
7074 asm, ".4s", ".4s", ".4h", ".h",
7075 [(set (v4i32 V128:$dst),
7076 (Accum (v4i32 V128:$Rd),
7077 (v4i32 (int_aarch64_neon_sqdmull
7079 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7080 VectorIndexH:$idx))))))]> {
7082 let Inst{11} = idx{2};
7083 let Inst{21} = idx{1};
7084 let Inst{20} = idx{0};
7087 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7088 // intermediate EXTRACT_SUBREG would be untyped.
7089 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7090 (i32 (vector_extract (v4i32
7091 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7092 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7093 VectorIndexH:$idx)))),
7096 (!cast<Instruction>(NAME # v4i16_indexed)
7097 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7098 V128_lo:$Rm, VectorIndexH:$idx),
7101 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7103 V128_lo, VectorIndexH,
7104 asm#"2", ".4s", ".4s", ".8h", ".h",
7105 [(set (v4i32 V128:$dst),
7106 (Accum (v4i32 V128:$Rd),
7107 (v4i32 (int_aarch64_neon_sqdmull
7108 (extract_high_v8i16 V128:$Rn),
7110 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7111 VectorIndexH:$idx))))))]> {
7113 let Inst{11} = idx{2};
7114 let Inst{21} = idx{1};
7115 let Inst{20} = idx{0};
7118 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7121 asm, ".2d", ".2d", ".2s", ".s",
7122 [(set (v2i64 V128:$dst),
7123 (Accum (v2i64 V128:$Rd),
7124 (v2i64 (int_aarch64_neon_sqdmull
7126 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7127 VectorIndexS:$idx))))))]> {
7129 let Inst{11} = idx{1};
7130 let Inst{21} = idx{0};
7133 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7136 asm#"2", ".2d", ".2d", ".4s", ".s",
7137 [(set (v2i64 V128:$dst),
7138 (Accum (v2i64 V128:$Rd),
7139 (v2i64 (int_aarch64_neon_sqdmull
7140 (extract_high_v4i32 V128:$Rn),
7142 (AArch64duplane32 (v4i32 V128:$Rm),
7143 VectorIndexS:$idx))))))]> {
7145 let Inst{11} = idx{1};
7146 let Inst{21} = idx{0};
7149 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7150 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7151 asm, ".h", "", "", ".h", []> {
7153 let Inst{11} = idx{2};
7154 let Inst{21} = idx{1};
7155 let Inst{20} = idx{0};
7159 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7160 FPR64Op, FPR32Op, V128, VectorIndexS,
7161 asm, ".s", "", "", ".s",
7162 [(set (i64 FPR64Op:$dst),
7163 (Accum (i64 FPR64Op:$Rd),
7164 (i64 (int_aarch64_neon_sqdmulls_scalar
7166 (i32 (vector_extract (v4i32 V128:$Rm),
7167 VectorIndexS:$idx))))))]> {
7170 let Inst{11} = idx{1};
7171 let Inst{21} = idx{0};
7175 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7176 SDPatternOperator OpNode> {
7177 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7178 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7180 V128_lo, VectorIndexH,
7181 asm, ".4s", ".4s", ".4h", ".h",
7182 [(set (v4i32 V128:$Rd),
7183 (OpNode (v4i16 V64:$Rn),
7184 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7186 let Inst{11} = idx{2};
7187 let Inst{21} = idx{1};
7188 let Inst{20} = idx{0};
7191 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7193 V128_lo, VectorIndexH,
7194 asm#"2", ".4s", ".4s", ".8h", ".h",
7195 [(set (v4i32 V128:$Rd),
7196 (OpNode (extract_high_v8i16 V128:$Rn),
7197 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7198 VectorIndexH:$idx))))]> {
7201 let Inst{11} = idx{2};
7202 let Inst{21} = idx{1};
7203 let Inst{20} = idx{0};
7206 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7209 asm, ".2d", ".2d", ".2s", ".s",
7210 [(set (v2i64 V128:$Rd),
7211 (OpNode (v2i32 V64:$Rn),
7212 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7214 let Inst{11} = idx{1};
7215 let Inst{21} = idx{0};
7218 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7221 asm#"2", ".2d", ".2d", ".4s", ".s",
7222 [(set (v2i64 V128:$Rd),
7223 (OpNode (extract_high_v4i32 V128:$Rn),
7224 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7225 VectorIndexS:$idx))))]> {
7227 let Inst{11} = idx{1};
7228 let Inst{21} = idx{0};
7233 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7234 SDPatternOperator OpNode> {
7235 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7236 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7238 V128_lo, VectorIndexH,
7239 asm, ".4s", ".4s", ".4h", ".h",
7240 [(set (v4i32 V128:$dst),
7241 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7242 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7244 let Inst{11} = idx{2};
7245 let Inst{21} = idx{1};
7246 let Inst{20} = idx{0};
7249 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7251 V128_lo, VectorIndexH,
7252 asm#"2", ".4s", ".4s", ".8h", ".h",
7253 [(set (v4i32 V128:$dst),
7254 (OpNode (v4i32 V128:$Rd),
7255 (extract_high_v8i16 V128:$Rn),
7256 (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7257 VectorIndexH:$idx))))]> {
7259 let Inst{11} = idx{2};
7260 let Inst{21} = idx{1};
7261 let Inst{20} = idx{0};
7264 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7267 asm, ".2d", ".2d", ".2s", ".s",
7268 [(set (v2i64 V128:$dst),
7269 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7270 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7272 let Inst{11} = idx{1};
7273 let Inst{21} = idx{0};
7276 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7279 asm#"2", ".2d", ".2d", ".4s", ".s",
7280 [(set (v2i64 V128:$dst),
7281 (OpNode (v2i64 V128:$Rd),
7282 (extract_high_v4i32 V128:$Rn),
7283 (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7284 VectorIndexS:$idx))))]> {
7286 let Inst{11} = idx{1};
7287 let Inst{21} = idx{0};
7292 //----------------------------------------------------------------------------
7293 // AdvSIMD scalar shift by immediate
7294 //----------------------------------------------------------------------------
7296 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7297 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7298 RegisterClass regtype1, RegisterClass regtype2,
7299 Operand immtype, string asm, list<dag> pattern>
7300 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7301 asm, "\t$Rd, $Rn, $imm", "", pattern>,
7306 let Inst{31-30} = 0b01;
7308 let Inst{28-23} = 0b111110;
7309 let Inst{22-16} = fixed_imm;
7310 let Inst{15-11} = opc;
7316 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7317 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7318 RegisterClass regtype1, RegisterClass regtype2,
7319 Operand immtype, string asm, list<dag> pattern>
7320 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7321 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7326 let Inst{31-30} = 0b01;
7328 let Inst{28-23} = 0b111110;
7329 let Inst{22-16} = fixed_imm;
7330 let Inst{15-11} = opc;
7337 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7338 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7339 FPR32, FPR32, vecshiftR32, asm, []> {
7340 let Inst{20-16} = imm{4-0};
7343 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7344 FPR64, FPR64, vecshiftR64, asm, []> {
7345 let Inst{21-16} = imm{5-0};
7349 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7350 SDPatternOperator OpNode> {
7351 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7352 FPR64, FPR64, vecshiftR64, asm,
7353 [(set (i64 FPR64:$Rd),
7354 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7355 let Inst{21-16} = imm{5-0};
7358 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7359 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7362 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7363 SDPatternOperator OpNode = null_frag> {
7364 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7365 FPR64, FPR64, vecshiftR64, asm,
7366 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7367 (i32 vecshiftR64:$imm)))]> {
7368 let Inst{21-16} = imm{5-0};
7371 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7372 (i32 vecshiftR64:$imm))),
7373 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7377 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7378 SDPatternOperator OpNode> {
7379 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7380 FPR64, FPR64, vecshiftL64, asm,
7381 [(set (v1i64 FPR64:$Rd),
7382 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7383 let Inst{21-16} = imm{5-0};
7387 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7388 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7389 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7390 FPR64, FPR64, vecshiftL64, asm, []> {
7391 let Inst{21-16} = imm{5-0};
7395 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7396 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7397 SDPatternOperator OpNode = null_frag> {
7398 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7399 FPR8, FPR16, vecshiftR8, asm, []> {
7400 let Inst{18-16} = imm{2-0};
7403 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7404 FPR16, FPR32, vecshiftR16, asm, []> {
7405 let Inst{19-16} = imm{3-0};
7408 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7409 FPR32, FPR64, vecshiftR32, asm,
7410 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7411 let Inst{20-16} = imm{4-0};
7415 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7416 SDPatternOperator OpNode> {
7417 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7418 FPR8, FPR8, vecshiftL8, asm, []> {
7419 let Inst{18-16} = imm{2-0};
7422 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7423 FPR16, FPR16, vecshiftL16, asm, []> {
7424 let Inst{19-16} = imm{3-0};
7427 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7428 FPR32, FPR32, vecshiftL32, asm,
7429 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7430 let Inst{20-16} = imm{4-0};
7433 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7434 FPR64, FPR64, vecshiftL64, asm,
7435 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7436 let Inst{21-16} = imm{5-0};
7439 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7440 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7443 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7444 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7445 FPR8, FPR8, vecshiftR8, asm, []> {
7446 let Inst{18-16} = imm{2-0};
7449 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7450 FPR16, FPR16, vecshiftR16, asm, []> {
7451 let Inst{19-16} = imm{3-0};
7454 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7455 FPR32, FPR32, vecshiftR32, asm, []> {
7456 let Inst{20-16} = imm{4-0};
7459 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7460 FPR64, FPR64, vecshiftR64, asm, []> {
7461 let Inst{21-16} = imm{5-0};
7465 //----------------------------------------------------------------------------
7466 // AdvSIMD vector x indexed element
7467 //----------------------------------------------------------------------------
7469 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7470 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7471 RegisterOperand dst_reg, RegisterOperand src_reg,
7473 string asm, string dst_kind, string src_kind,
7475 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7476 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7477 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7484 let Inst{28-23} = 0b011110;
7485 let Inst{22-16} = fixed_imm;
7486 let Inst{15-11} = opc;
7492 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7493 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7494 RegisterOperand vectype1, RegisterOperand vectype2,
7496 string asm, string dst_kind, string src_kind,
7498 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7499 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7500 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7507 let Inst{28-23} = 0b011110;
7508 let Inst{22-16} = fixed_imm;
7509 let Inst{15-11} = opc;
7515 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7517 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7518 V64, V64, vecshiftR32,
7520 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7522 let Inst{20-16} = imm;
7525 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7526 V128, V128, vecshiftR32,
7528 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7530 let Inst{20-16} = imm;
7533 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7534 V128, V128, vecshiftR64,
7536 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7538 let Inst{21-16} = imm;
7542 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7544 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7545 V64, V64, vecshiftR32,
7547 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7549 let Inst{20-16} = imm;
7552 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7553 V128, V128, vecshiftR32,
7555 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7557 let Inst{20-16} = imm;
7560 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7561 V128, V128, vecshiftR64,
7563 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7565 let Inst{21-16} = imm;
7569 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7570 SDPatternOperator OpNode> {
7571 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7572 V64, V128, vecshiftR16Narrow,
7574 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7576 let Inst{18-16} = imm;
7579 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7580 V128, V128, vecshiftR16Narrow,
7581 asm#"2", ".16b", ".8h", []> {
7583 let Inst{18-16} = imm;
7584 let hasSideEffects = 0;
7587 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7588 V64, V128, vecshiftR32Narrow,
7590 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7592 let Inst{19-16} = imm;
7595 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7596 V128, V128, vecshiftR32Narrow,
7597 asm#"2", ".8h", ".4s", []> {
7599 let Inst{19-16} = imm;
7600 let hasSideEffects = 0;
7603 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7604 V64, V128, vecshiftR64Narrow,
7606 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7608 let Inst{20-16} = imm;
7611 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7612 V128, V128, vecshiftR64Narrow,
7613 asm#"2", ".4s", ".2d", []> {
7615 let Inst{20-16} = imm;
7616 let hasSideEffects = 0;
7619 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7620 // themselves, so put them here instead.
7622 // Patterns involving what's effectively an insert high and a normal
7623 // intrinsic, represented by CONCAT_VECTORS.
7624 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7625 vecshiftR16Narrow:$imm)),
7626 (!cast<Instruction>(NAME # "v16i8_shift")
7627 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7628 V128:$Rn, vecshiftR16Narrow:$imm)>;
7629 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7630 vecshiftR32Narrow:$imm)),
7631 (!cast<Instruction>(NAME # "v8i16_shift")
7632 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7633 V128:$Rn, vecshiftR32Narrow:$imm)>;
7634 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7635 vecshiftR64Narrow:$imm)),
7636 (!cast<Instruction>(NAME # "v4i32_shift")
7637 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7638 V128:$Rn, vecshiftR64Narrow:$imm)>;
7641 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7642 SDPatternOperator OpNode> {
7643 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7644 V64, V64, vecshiftL8,
7646 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7647 (i32 vecshiftL8:$imm)))]> {
7649 let Inst{18-16} = imm;
7652 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7653 V128, V128, vecshiftL8,
7654 asm, ".16b", ".16b",
7655 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7656 (i32 vecshiftL8:$imm)))]> {
7658 let Inst{18-16} = imm;
7661 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7662 V64, V64, vecshiftL16,
7664 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7665 (i32 vecshiftL16:$imm)))]> {
7667 let Inst{19-16} = imm;
7670 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7671 V128, V128, vecshiftL16,
7673 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7674 (i32 vecshiftL16:$imm)))]> {
7676 let Inst{19-16} = imm;
7679 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7680 V64, V64, vecshiftL32,
7682 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7683 (i32 vecshiftL32:$imm)))]> {
7685 let Inst{20-16} = imm;
7688 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7689 V128, V128, vecshiftL32,
7691 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7692 (i32 vecshiftL32:$imm)))]> {
7694 let Inst{20-16} = imm;
7697 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7698 V128, V128, vecshiftL64,
7700 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7701 (i32 vecshiftL64:$imm)))]> {
7703 let Inst{21-16} = imm;
7707 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7708 SDPatternOperator OpNode> {
7709 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7710 V64, V64, vecshiftR8,
7712 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7713 (i32 vecshiftR8:$imm)))]> {
7715 let Inst{18-16} = imm;
7718 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7719 V128, V128, vecshiftR8,
7720 asm, ".16b", ".16b",
7721 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7722 (i32 vecshiftR8:$imm)))]> {
7724 let Inst{18-16} = imm;
7727 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7728 V64, V64, vecshiftR16,
7730 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7731 (i32 vecshiftR16:$imm)))]> {
7733 let Inst{19-16} = imm;
7736 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7737 V128, V128, vecshiftR16,
7739 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7740 (i32 vecshiftR16:$imm)))]> {
7742 let Inst{19-16} = imm;
7745 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7746 V64, V64, vecshiftR32,
7748 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7749 (i32 vecshiftR32:$imm)))]> {
7751 let Inst{20-16} = imm;
7754 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7755 V128, V128, vecshiftR32,
7757 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7758 (i32 vecshiftR32:$imm)))]> {
7760 let Inst{20-16} = imm;
7763 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7764 V128, V128, vecshiftR64,
7766 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7767 (i32 vecshiftR64:$imm)))]> {
7769 let Inst{21-16} = imm;
7773 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7774 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7775 SDPatternOperator OpNode = null_frag> {
7776 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7777 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7778 [(set (v8i8 V64:$dst),
7779 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7780 (i32 vecshiftR8:$imm)))]> {
7782 let Inst{18-16} = imm;
7785 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7786 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7787 [(set (v16i8 V128:$dst),
7788 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7789 (i32 vecshiftR8:$imm)))]> {
7791 let Inst{18-16} = imm;
7794 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7795 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7796 [(set (v4i16 V64:$dst),
7797 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7798 (i32 vecshiftR16:$imm)))]> {
7800 let Inst{19-16} = imm;
7803 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7804 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7805 [(set (v8i16 V128:$dst),
7806 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7807 (i32 vecshiftR16:$imm)))]> {
7809 let Inst{19-16} = imm;
7812 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7813 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7814 [(set (v2i32 V64:$dst),
7815 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7816 (i32 vecshiftR32:$imm)))]> {
7818 let Inst{20-16} = imm;
7821 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7822 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7823 [(set (v4i32 V128:$dst),
7824 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7825 (i32 vecshiftR32:$imm)))]> {
7827 let Inst{20-16} = imm;
7830 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7831 V128, V128, vecshiftR64,
7832 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7833 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7834 (i32 vecshiftR64:$imm)))]> {
7836 let Inst{21-16} = imm;
7840 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7841 SDPatternOperator OpNode = null_frag> {
7842 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7843 V64, V64, vecshiftL8,
7845 [(set (v8i8 V64:$dst),
7846 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7847 (i32 vecshiftL8:$imm)))]> {
7849 let Inst{18-16} = imm;
7852 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7853 V128, V128, vecshiftL8,
7854 asm, ".16b", ".16b",
7855 [(set (v16i8 V128:$dst),
7856 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7857 (i32 vecshiftL8:$imm)))]> {
7859 let Inst{18-16} = imm;
7862 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7863 V64, V64, vecshiftL16,
7865 [(set (v4i16 V64:$dst),
7866 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7867 (i32 vecshiftL16:$imm)))]> {
7869 let Inst{19-16} = imm;
7872 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7873 V128, V128, vecshiftL16,
7875 [(set (v8i16 V128:$dst),
7876 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7877 (i32 vecshiftL16:$imm)))]> {
7879 let Inst{19-16} = imm;
7882 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7883 V64, V64, vecshiftL32,
7885 [(set (v2i32 V64:$dst),
7886 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7887 (i32 vecshiftL32:$imm)))]> {
7889 let Inst{20-16} = imm;
7892 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7893 V128, V128, vecshiftL32,
7895 [(set (v4i32 V128:$dst),
7896 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7897 (i32 vecshiftL32:$imm)))]> {
7899 let Inst{20-16} = imm;
7902 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7903 V128, V128, vecshiftL64,
7905 [(set (v2i64 V128:$dst),
7906 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7907 (i32 vecshiftL64:$imm)))]> {
7909 let Inst{21-16} = imm;
7913 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7914 SDPatternOperator OpNode> {
7915 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7916 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7917 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7919 let Inst{18-16} = imm;
7922 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7923 V128, V128, vecshiftL8,
7924 asm#"2", ".8h", ".16b",
7925 [(set (v8i16 V128:$Rd),
7926 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7928 let Inst{18-16} = imm;
7931 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7932 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7933 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7935 let Inst{19-16} = imm;
7938 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7939 V128, V128, vecshiftL16,
7940 asm#"2", ".4s", ".8h",
7941 [(set (v4i32 V128:$Rd),
7942 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7945 let Inst{19-16} = imm;
7948 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7949 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7950 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7952 let Inst{20-16} = imm;
7955 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7956 V128, V128, vecshiftL32,
7957 asm#"2", ".2d", ".4s",
7958 [(set (v2i64 V128:$Rd),
7959 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7961 let Inst{20-16} = imm;
7967 // Vector load/store
7969 // SIMD ldX/stX no-index memory references don't allow the optional
7970 // ", #0" constant and handle post-indexing explicitly, so we use
7971 // a more specialized parse method for them. Otherwise, it's the same as
7972 // the general GPR64sp handling.
7974 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7975 string asm, dag oops, dag iops, list<dag> pattern>
7976 : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7981 let Inst{29-23} = 0b0011000;
7983 let Inst{21-16} = 0b000000;
7984 let Inst{15-12} = opcode;
7985 let Inst{11-10} = size;
7990 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7991 string asm, dag oops, dag iops>
7992 : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7998 let Inst{29-23} = 0b0011001;
8001 let Inst{20-16} = Xm;
8002 let Inst{15-12} = opcode;
8003 let Inst{11-10} = size;
8008 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8009 // register post-index addressing from the zero register.
8010 multiclass SIMDLdStAliases<string asm, string layout, string Count,
8011 int Offset, int Size> {
8012 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8013 // "ld1\t$Vt, [$Rn], #16"
8014 // may get mapped to
8015 // (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8016 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8017 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8019 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8022 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8023 // "ld1.8b\t$Vt, [$Rn], #16"
8024 // may get mapped to
8025 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8026 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8027 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8029 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8032 // E.g. "ld1.8b { v0, v1 }, [x1]"
8033 // "ld1\t$Vt, [$Rn]"
8034 // may get mapped to
8035 // (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8036 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8037 (!cast<Instruction>(NAME # Count # "v" # layout)
8038 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8041 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8042 // "ld1\t$Vt, [$Rn], $Xm"
8043 // may get mapped to
8044 // (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8045 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8046 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8048 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8049 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8052 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
8053 int Offset64, bits<4> opcode> {
8054 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8055 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8056 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8057 (ins GPR64sp:$Rn), []>;
8058 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8059 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8060 (ins GPR64sp:$Rn), []>;
8061 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8062 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8063 (ins GPR64sp:$Rn), []>;
8064 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8065 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8066 (ins GPR64sp:$Rn), []>;
8067 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8068 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8069 (ins GPR64sp:$Rn), []>;
8070 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8071 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8072 (ins GPR64sp:$Rn), []>;
8073 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8074 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8075 (ins GPR64sp:$Rn), []>;
8078 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8079 (outs GPR64sp:$wback,
8080 !cast<RegisterOperand>(veclist # "16b"):$Vt),
8082 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8083 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8084 (outs GPR64sp:$wback,
8085 !cast<RegisterOperand>(veclist # "8h"):$Vt),
8087 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8088 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8089 (outs GPR64sp:$wback,
8090 !cast<RegisterOperand>(veclist # "4s"):$Vt),
8092 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8093 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8094 (outs GPR64sp:$wback,
8095 !cast<RegisterOperand>(veclist # "2d"):$Vt),
8097 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8098 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8099 (outs GPR64sp:$wback,
8100 !cast<RegisterOperand>(veclist # "8b"):$Vt),
8102 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8103 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8104 (outs GPR64sp:$wback,
8105 !cast<RegisterOperand>(veclist # "4h"):$Vt),
8107 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8108 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8109 (outs GPR64sp:$wback,
8110 !cast<RegisterOperand>(veclist # "2s"):$Vt),
8112 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8115 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8116 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8117 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8118 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8119 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8120 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8121 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8124 // Only ld1/st1 has a v1d version.
8125 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
8126 int Offset64, bits<4> opcode> {
8127 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8128 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8129 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8131 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8132 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8134 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8135 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8137 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8138 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8140 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8141 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8143 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8144 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8146 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8147 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8150 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8151 (outs GPR64sp:$wback),
8152 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8154 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8155 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8156 (outs GPR64sp:$wback),
8157 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8159 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8160 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8161 (outs GPR64sp:$wback),
8162 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8164 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8165 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8166 (outs GPR64sp:$wback),
8167 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8169 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8170 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8171 (outs GPR64sp:$wback),
8172 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8174 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8175 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8176 (outs GPR64sp:$wback),
8177 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8179 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8180 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8181 (outs GPR64sp:$wback),
8182 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8184 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8187 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8188 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8189 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8190 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8191 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8192 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8193 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8196 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8197 int Offset128, int Offset64, bits<4> opcode>
8198 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8200 // LD1 instructions have extra "1d" variants.
8201 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8202 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8203 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8204 (ins GPR64sp:$Rn), []>;
8206 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8207 (outs GPR64sp:$wback,
8208 !cast<RegisterOperand>(veclist # "1d"):$Vt),
8210 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8213 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8216 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8217 int Offset128, int Offset64, bits<4> opcode>
8218 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8220 // ST1 instructions have extra "1d" variants.
8221 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8222 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8223 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8226 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8227 (outs GPR64sp:$wback),
8228 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8230 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8233 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8236 multiclass SIMDLd1Multiple<string asm> {
8237 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
8238 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8239 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8240 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8243 multiclass SIMDSt1Multiple<string asm> {
8244 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
8245 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8246 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8247 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8250 multiclass SIMDLd2Multiple<string asm> {
8251 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8254 multiclass SIMDSt2Multiple<string asm> {
8255 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8258 multiclass SIMDLd3Multiple<string asm> {
8259 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8262 multiclass SIMDSt3Multiple<string asm> {
8263 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8266 multiclass SIMDLd4Multiple<string asm> {
8267 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8270 multiclass SIMDSt4Multiple<string asm> {
8271 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8275 // AdvSIMD Load/store single-element
8278 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8279 string asm, string operands, string cst,
8280 dag oops, dag iops, list<dag> pattern>
8281 : I<oops, iops, asm, operands, cst, pattern> {
8285 let Inst{29-24} = 0b001101;
8288 let Inst{15-13} = opcode;
8293 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8294 string asm, string operands, string cst,
8295 dag oops, dag iops, list<dag> pattern>
8296 : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8300 let Inst{29-24} = 0b001101;
8303 let Inst{15-13} = opcode;
8309 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8310 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8312 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8313 (outs listtype:$Vt), (ins GPR64sp:$Rn),
8317 let Inst{20-16} = 0b00000;
8319 let Inst{11-10} = size;
8321 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8322 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8323 string asm, Operand listtype, Operand GPR64pi>
8324 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8326 (outs GPR64sp:$wback, listtype:$Vt),
8327 (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8331 let Inst{20-16} = Xm;
8333 let Inst{11-10} = size;
8336 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8337 int Offset, int Size> {
8338 // E.g. "ld1r { v0.8b }, [x1], #1"
8339 // "ld1r.8b\t$Vt, [$Rn], #1"
8340 // may get mapped to
8341 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8342 def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8343 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8345 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8348 // E.g. "ld1r.8b { v0 }, [x1], #1"
8349 // "ld1r.8b\t$Vt, [$Rn], #1"
8350 // may get mapped to
8351 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8352 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8353 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8355 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8358 // E.g. "ld1r.8b { v0 }, [x1]"
8359 // "ld1r.8b\t$Vt, [$Rn]"
8360 // may get mapped to
8361 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8362 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8363 (!cast<Instruction>(NAME # "v" # layout)
8364 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8367 // E.g. "ld1r.8b { v0 }, [x1], x2"
8368 // "ld1r.8b\t$Vt, [$Rn], $Xm"
8369 // may get mapped to
8370 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8371 def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8372 (!cast<Instruction>(NAME # "v" # layout # "_POST")
8374 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8375 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8378 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8379 int Offset1, int Offset2, int Offset4, int Offset8> {
8380 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8381 !cast<Operand>("VecList" # Count # "8b")>;
8382 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8383 !cast<Operand>("VecList" # Count #"16b")>;
8384 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8385 !cast<Operand>("VecList" # Count #"4h")>;
8386 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8387 !cast<Operand>("VecList" # Count #"8h")>;
8388 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8389 !cast<Operand>("VecList" # Count #"2s")>;
8390 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8391 !cast<Operand>("VecList" # Count #"4s")>;
8392 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8393 !cast<Operand>("VecList" # Count #"1d")>;
8394 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8395 !cast<Operand>("VecList" # Count #"2d")>;
8397 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8398 !cast<Operand>("VecList" # Count # "8b"),
8399 !cast<Operand>("GPR64pi" # Offset1)>;
8400 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8401 !cast<Operand>("VecList" # Count # "16b"),
8402 !cast<Operand>("GPR64pi" # Offset1)>;
8403 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8404 !cast<Operand>("VecList" # Count # "4h"),
8405 !cast<Operand>("GPR64pi" # Offset2)>;
8406 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8407 !cast<Operand>("VecList" # Count # "8h"),
8408 !cast<Operand>("GPR64pi" # Offset2)>;
8409 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8410 !cast<Operand>("VecList" # Count # "2s"),
8411 !cast<Operand>("GPR64pi" # Offset4)>;
8412 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8413 !cast<Operand>("VecList" # Count # "4s"),
8414 !cast<Operand>("GPR64pi" # Offset4)>;
8415 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8416 !cast<Operand>("VecList" # Count # "1d"),
8417 !cast<Operand>("GPR64pi" # Offset8)>;
8418 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8419 !cast<Operand>("VecList" # Count # "2d"),
8420 !cast<Operand>("GPR64pi" # Offset8)>;
8422 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
8423 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8424 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
8425 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
8426 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
8427 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
8428 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
8429 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
8432 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8433 dag oops, dag iops, list<dag> pattern>
8434 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8436 // idx encoded in Q:S:size fields.
8438 let Inst{30} = idx{3};
8440 let Inst{20-16} = 0b00000;
8441 let Inst{12} = idx{2};
8442 let Inst{11-10} = idx{1-0};
8444 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8445 dag oops, dag iops, list<dag> pattern>
8446 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8447 oops, iops, pattern> {
8448 // idx encoded in Q:S:size fields.
8450 let Inst{30} = idx{3};
8452 let Inst{20-16} = 0b00000;
8453 let Inst{12} = idx{2};
8454 let Inst{11-10} = idx{1-0};
8456 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8458 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8459 "$Rn = $wback", oops, iops, []> {
8460 // idx encoded in Q:S:size fields.
8463 let Inst{30} = idx{3};
8465 let Inst{20-16} = Xm;
8466 let Inst{12} = idx{2};
8467 let Inst{11-10} = idx{1-0};
8469 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8471 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8472 "$Rn = $wback", oops, iops, []> {
8473 // idx encoded in Q:S:size fields.
8476 let Inst{30} = idx{3};
8478 let Inst{20-16} = Xm;
8479 let Inst{12} = idx{2};
8480 let Inst{11-10} = idx{1-0};
8483 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8484 dag oops, dag iops, list<dag> pattern>
8485 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8487 // idx encoded in Q:S:size<1> fields.
8489 let Inst{30} = idx{2};
8491 let Inst{20-16} = 0b00000;
8492 let Inst{12} = idx{1};
8493 let Inst{11} = idx{0};
8494 let Inst{10} = size;
8496 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8497 dag oops, dag iops, list<dag> pattern>
8498 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8499 oops, iops, pattern> {
8500 // idx encoded in Q:S:size<1> fields.
8502 let Inst{30} = idx{2};
8504 let Inst{20-16} = 0b00000;
8505 let Inst{12} = idx{1};
8506 let Inst{11} = idx{0};
8507 let Inst{10} = size;
8510 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8512 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8513 "$Rn = $wback", oops, iops, []> {
8514 // idx encoded in Q:S:size<1> fields.
8517 let Inst{30} = idx{2};
8519 let Inst{20-16} = Xm;
8520 let Inst{12} = idx{1};
8521 let Inst{11} = idx{0};
8522 let Inst{10} = size;
8524 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8526 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8527 "$Rn = $wback", oops, iops, []> {
8528 // idx encoded in Q:S:size<1> fields.
8531 let Inst{30} = idx{2};
8533 let Inst{20-16} = Xm;
8534 let Inst{12} = idx{1};
8535 let Inst{11} = idx{0};
8536 let Inst{10} = size;
8538 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8539 dag oops, dag iops, list<dag> pattern>
8540 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8542 // idx encoded in Q:S fields.
8544 let Inst{30} = idx{1};
8546 let Inst{20-16} = 0b00000;
8547 let Inst{12} = idx{0};
8548 let Inst{11-10} = size;
8550 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8551 dag oops, dag iops, list<dag> pattern>
8552 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8553 oops, iops, pattern> {
8554 // idx encoded in Q:S fields.
8556 let Inst{30} = idx{1};
8558 let Inst{20-16} = 0b00000;
8559 let Inst{12} = idx{0};
8560 let Inst{11-10} = size;
8562 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8563 string asm, dag oops, dag iops>
8564 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8565 "$Rn = $wback", oops, iops, []> {
8566 // idx encoded in Q:S fields.
8569 let Inst{30} = idx{1};
8571 let Inst{20-16} = Xm;
8572 let Inst{12} = idx{0};
8573 let Inst{11-10} = size;
8575 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8576 string asm, dag oops, dag iops>
8577 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8578 "$Rn = $wback", oops, iops, []> {
8579 // idx encoded in Q:S fields.
8582 let Inst{30} = idx{1};
8584 let Inst{20-16} = Xm;
8585 let Inst{12} = idx{0};
8586 let Inst{11-10} = size;
8588 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8589 dag oops, dag iops, list<dag> pattern>
8590 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8592 // idx encoded in Q field.
8596 let Inst{20-16} = 0b00000;
8598 let Inst{11-10} = size;
8600 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8601 dag oops, dag iops, list<dag> pattern>
8602 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8603 oops, iops, pattern> {
8604 // idx encoded in Q field.
8608 let Inst{20-16} = 0b00000;
8610 let Inst{11-10} = size;
8612 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8613 string asm, dag oops, dag iops>
8614 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8615 "$Rn = $wback", oops, iops, []> {
8616 // idx encoded in Q field.
8621 let Inst{20-16} = Xm;
8623 let Inst{11-10} = size;
8625 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8626 string asm, dag oops, dag iops>
8627 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8628 "$Rn = $wback", oops, iops, []> {
8629 // idx encoded in Q field.
8634 let Inst{20-16} = Xm;
8636 let Inst{11-10} = size;
8639 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8640 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8641 RegisterOperand listtype,
8642 RegisterOperand GPR64pi> {
8643 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8644 (outs listtype:$dst),
8645 (ins listtype:$Vt, VectorIndexB:$idx,
8648 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8649 (outs GPR64sp:$wback, listtype:$dst),
8650 (ins listtype:$Vt, VectorIndexB:$idx,
8651 GPR64sp:$Rn, GPR64pi:$Xm)>;
8653 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8654 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8655 RegisterOperand listtype,
8656 RegisterOperand GPR64pi> {
8657 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8658 (outs listtype:$dst),
8659 (ins listtype:$Vt, VectorIndexH:$idx,
8662 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8663 (outs GPR64sp:$wback, listtype:$dst),
8664 (ins listtype:$Vt, VectorIndexH:$idx,
8665 GPR64sp:$Rn, GPR64pi:$Xm)>;
8667 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8668 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8669 RegisterOperand listtype,
8670 RegisterOperand GPR64pi> {
8671 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8672 (outs listtype:$dst),
8673 (ins listtype:$Vt, VectorIndexS:$idx,
8676 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8677 (outs GPR64sp:$wback, listtype:$dst),
8678 (ins listtype:$Vt, VectorIndexS:$idx,
8679 GPR64sp:$Rn, GPR64pi:$Xm)>;
8681 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8682 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8683 RegisterOperand listtype, RegisterOperand GPR64pi> {
8684 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8685 (outs listtype:$dst),
8686 (ins listtype:$Vt, VectorIndexD:$idx,
8689 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8690 (outs GPR64sp:$wback, listtype:$dst),
8691 (ins listtype:$Vt, VectorIndexD:$idx,
8692 GPR64sp:$Rn, GPR64pi:$Xm)>;
8694 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8695 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8696 RegisterOperand listtype, RegisterOperand GPR64pi> {
8697 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8698 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8701 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8702 (outs GPR64sp:$wback),
8703 (ins listtype:$Vt, VectorIndexB:$idx,
8704 GPR64sp:$Rn, GPR64pi:$Xm)>;
8706 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8707 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8708 RegisterOperand listtype, RegisterOperand GPR64pi> {
8709 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8710 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8713 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8714 (outs GPR64sp:$wback),
8715 (ins listtype:$Vt, VectorIndexH:$idx,
8716 GPR64sp:$Rn, GPR64pi:$Xm)>;
8718 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8719 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8720 RegisterOperand listtype, RegisterOperand GPR64pi> {
8721 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8722 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8725 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8726 (outs GPR64sp:$wback),
8727 (ins listtype:$Vt, VectorIndexS:$idx,
8728 GPR64sp:$Rn, GPR64pi:$Xm)>;
8730 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8731 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8732 RegisterOperand listtype, RegisterOperand GPR64pi> {
8733 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8734 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8737 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8738 (outs GPR64sp:$wback),
8739 (ins listtype:$Vt, VectorIndexD:$idx,
8740 GPR64sp:$Rn, GPR64pi:$Xm)>;
8743 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8744 string Count, int Offset, Operand idxtype> {
8745 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8746 // "ld1\t$Vt, [$Rn], #1"
8747 // may get mapped to
8748 // (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8749 def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8750 (!cast<Instruction>(NAME # Type # "_POST")
8752 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8753 idxtype:$idx, XZR), 1>;
8755 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8756 // "ld1.8b\t$Vt, [$Rn], #1"
8757 // may get mapped to
8758 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8759 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8760 (!cast<Instruction>(NAME # Type # "_POST")
8762 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8763 idxtype:$idx, XZR), 0>;
8765 // E.g. "ld1.8b { v0 }[0], [x1]"
8766 // "ld1.8b\t$Vt, [$Rn]"
8767 // may get mapped to
8768 // (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8769 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8770 (!cast<Instruction>(NAME # Type)
8771 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8772 idxtype:$idx, GPR64sp:$Rn), 0>;
8774 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8775 // "ld1.8b\t$Vt, [$Rn], $Xm"
8776 // may get mapped to
8777 // (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8778 def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8779 (!cast<Instruction>(NAME # Type # "_POST")
8781 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8783 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8786 multiclass SIMDLdSt1SingleAliases<string asm> {
8787 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8788 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8789 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8790 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8793 multiclass SIMDLdSt2SingleAliases<string asm> {
8794 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8795 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8796 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8797 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8800 multiclass SIMDLdSt3SingleAliases<string asm> {
8801 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8802 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8803 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8804 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8807 multiclass SIMDLdSt4SingleAliases<string asm> {
8808 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8809 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8810 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8811 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8813 } // end of 'let Predicates = [HasNEON]'
8815 //----------------------------------------------------------------------------
8816 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8817 //----------------------------------------------------------------------------
8819 let Predicates = [HasNEON, HasV8_1a] in {
8821 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8822 RegisterOperand regtype, string asm,
8823 string kind, list<dag> pattern>
8824 : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind,
8828 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8829 SDPatternOperator Accum> {
8830 def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8831 [(set (v4i16 V64:$dst),
8832 (Accum (v4i16 V64:$Rd),
8833 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8834 (v4i16 V64:$Rm)))))]>;
8835 def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8836 [(set (v8i16 V128:$dst),
8837 (Accum (v8i16 V128:$Rd),
8838 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8839 (v8i16 V128:$Rm)))))]>;
8840 def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8841 [(set (v2i32 V64:$dst),
8842 (Accum (v2i32 V64:$Rd),
8843 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8844 (v2i32 V64:$Rm)))))]>;
8845 def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8846 [(set (v4i32 V128:$dst),
8847 (Accum (v4i32 V128:$Rd),
8848 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8849 (v4i32 V128:$Rm)))))]>;
8852 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8853 SDPatternOperator Accum> {
8854 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8855 V64, V64, V128_lo, VectorIndexH,
8856 asm, ".4h", ".4h", ".4h", ".h",
8857 [(set (v4i16 V64:$dst),
8858 (Accum (v4i16 V64:$Rd),
8859 (v4i16 (int_aarch64_neon_sqrdmulh
8861 (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8862 VectorIndexH:$idx))))))]> {
8864 let Inst{11} = idx{2};
8865 let Inst{21} = idx{1};
8866 let Inst{20} = idx{0};
8869 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8870 V128, V128, V128_lo, VectorIndexH,
8871 asm, ".8h", ".8h", ".8h", ".h",
8872 [(set (v8i16 V128:$dst),
8873 (Accum (v8i16 V128:$Rd),
8874 (v8i16 (int_aarch64_neon_sqrdmulh
8876 (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8877 VectorIndexH:$idx))))))]> {
8879 let Inst{11} = idx{2};
8880 let Inst{21} = idx{1};
8881 let Inst{20} = idx{0};
8884 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8885 V64, V64, V128, VectorIndexS,
8886 asm, ".2s", ".2s", ".2s", ".s",
8887 [(set (v2i32 V64:$dst),
8888 (Accum (v2i32 V64:$Rd),
8889 (v2i32 (int_aarch64_neon_sqrdmulh
8891 (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8892 VectorIndexS:$idx))))))]> {
8894 let Inst{11} = idx{1};
8895 let Inst{21} = idx{0};
8898 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8899 // an intermediate EXTRACT_SUBREG would be untyped.
8900 // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
8901 // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8902 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8903 (i32 (vector_extract
8904 (v4i32 (insert_subvector
8906 (v2i32 (int_aarch64_neon_sqrdmulh
8908 (v2i32 (AArch64duplane32
8910 VectorIndexS:$idx)))),
8914 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8915 (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
8920 VectorIndexS:$idx)),
8923 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8924 V128, V128, V128, VectorIndexS,
8925 asm, ".4s", ".4s", ".4s", ".s",
8926 [(set (v4i32 V128:$dst),
8927 (Accum (v4i32 V128:$Rd),
8928 (v4i32 (int_aarch64_neon_sqrdmulh
8930 (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8931 VectorIndexS:$idx))))))]> {
8933 let Inst{11} = idx{1};
8934 let Inst{21} = idx{0};
8937 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8938 // an intermediate EXTRACT_SUBREG would be untyped.
8939 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8940 (i32 (vector_extract
8941 (v4i32 (int_aarch64_neon_sqrdmulh
8943 (v4i32 (AArch64duplane32
8945 VectorIndexS:$idx)))),
8948 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8949 (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
8954 VectorIndexS:$idx)),
8957 def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8958 FPR16Op, FPR16Op, V128_lo,
8959 VectorIndexH, asm, ".h", "", "", ".h",
8962 let Inst{11} = idx{2};
8963 let Inst{21} = idx{1};
8964 let Inst{20} = idx{0};
8967 def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8968 FPR32Op, FPR32Op, V128, VectorIndexS,
8969 asm, ".s", "", "", ".s",
8970 [(set (i32 FPR32Op:$dst),
8971 (Accum (i32 FPR32Op:$Rd),
8972 (i32 (int_aarch64_neon_sqrdmulh
8974 (i32 (vector_extract (v4i32 V128:$Rm),
8975 VectorIndexS:$idx))))))]> {
8977 let Inst{11} = idx{1};
8978 let Inst{21} = idx{0};
8981 } // let Predicates = [HasNeon, HasV8_1a]
8983 //----------------------------------------------------------------------------
8984 // Crypto extensions
8985 //----------------------------------------------------------------------------
8987 let Predicates = [HasCrypto] in {
8988 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8989 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8991 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8995 let Inst{31-16} = 0b0100111000101000;
8996 let Inst{15-12} = opc;
8997 let Inst{11-10} = 0b10;
9002 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9003 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9004 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9006 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9007 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9009 [(set (v16i8 V128:$dst),
9010 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9012 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9013 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9014 dag oops, dag iops, list<dag> pat>
9015 : I<oops, iops, asm,
9016 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9017 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9022 let Inst{31-21} = 0b01011110000;
9023 let Inst{20-16} = Rm;
9025 let Inst{14-12} = opc;
9026 let Inst{11-10} = 0b00;
9031 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9032 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9033 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9034 [(set (v4i32 FPR128:$dst),
9035 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9036 (v4i32 V128:$Rm)))]>;
9038 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9039 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9040 (ins V128:$Rd, V128:$Rn, V128:$Rm),
9041 [(set (v4i32 V128:$dst),
9042 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9043 (v4i32 V128:$Rm)))]>;
9045 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9046 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9047 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9048 [(set (v4i32 FPR128:$dst),
9049 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9050 (v4i32 V128:$Rm)))]>;
9052 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9053 class SHA2OpInst<bits<4> opc, string asm, string kind,
9054 string cstr, dag oops, dag iops,
9056 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9057 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9061 let Inst{31-16} = 0b0101111000101000;
9062 let Inst{15-12} = opc;
9063 let Inst{11-10} = 0b10;
9068 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
9069 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
9070 (ins V128:$Rd, V128:$Rn),
9071 [(set (v4i32 V128:$dst),
9072 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
9074 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
9075 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
9076 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
9077 } // end of 'let Predicates = [HasCrypto]'
9079 //----------------------------------------------------------------------------
9080 // v8.1 atomic instructions extension:
9084 // * LDOPregister<OP>, and aliases STOPregister<OP>
9086 // Instruction encodings:
9088 // 31 30|29 24|23|22|21|20 16|15|14 10|9 5|4 0
9089 // CAS SZ |001000|1 |A |1 |Rs |R |11111 |Rn |Rt
9090 // CASP 0|SZ|001000|0 |A |1 |Rs |R |11111 |Rn |Rt
9091 // SWP SZ |111000|A |R |1 |Rs |1 |OPC|00|Rn |Rt
9092 // LD SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |Rt
9093 // ST SZ |111000|A |R |1 |Rs |0 |OPC|00|Rn |11111
9095 // Instruction syntax:
9097 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9098 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
9099 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
9100 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
9101 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9102 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
9103 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9104 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
9105 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
9106 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
9108 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9109 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
9110 string cstr, list<dag> pattern>
9111 : I<oops, iops, asm, operands, cstr, pattern> {
9119 let Inst{31-30} = Sz;
9120 let Inst{29-24} = 0b001000;
9124 let Inst{20-16} = Rs;
9126 let Inst{14-10} = 0b11111;
9131 class BaseCAS<string order, string size, RegisterClass RC>
9132 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9133 "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
9138 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
9139 let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
9140 let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
9141 let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
9142 let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
9145 class BaseCASP<string order, string size, RegisterOperand RC>
9146 : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9147 "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
9152 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9153 let Sz = 0b00, Acq = Acq, Rel = Rel in
9154 def s : BaseCASP<order, "", WSeqPairClassOperand>;
9155 let Sz = 0b01, Acq = Acq, Rel = Rel in
9156 def d : BaseCASP<order, "", XSeqPairClassOperand>;
9159 let Predicates = [HasV8_1a] in
9160 class BaseSWP<string order, string size, RegisterClass RC>
9161 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9162 "\t$Rs, $Rt, [$Rn]","",[]> {
9167 bits<3> opc = 0b000;
9170 let Inst{31-30} = Sz;
9171 let Inst{29-24} = 0b111000;
9175 let Inst{20-16} = Rs;
9177 let Inst{14-12} = opc;
9178 let Inst{11-10} = 0b00;
9183 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9184 let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9185 let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9186 let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9187 let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9190 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9191 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9192 : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9193 "\t$Rs, $Rt, [$Rn]","",[]> {
9201 let Inst{31-30} = Sz;
9202 let Inst{29-24} = 0b111000;
9206 let Inst{20-16} = Rs;
9208 let Inst{14-12} = opc;
9209 let Inst{11-10} = 0b00;
9214 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
9216 let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
9217 def b : BaseLDOPregister<op, order, "b", GPR32>;
9218 let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
9219 def h : BaseLDOPregister<op, order, "h", GPR32>;
9220 let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
9221 def s : BaseLDOPregister<op, order, "", GPR32>;
9222 let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
9223 def d : BaseLDOPregister<op, order, "", GPR64>;
9226 let Predicates = [HasV8_1a] in
9227 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9229 InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9231 multiclass STOPregister<string asm, string instr> {
9232 def : BaseSTOPregister<asm # "lb", GPR32, WZR,
9233 !cast<Instruction>(instr # "Lb")>;
9234 def : BaseSTOPregister<asm # "lh", GPR32, WZR,
9235 !cast<Instruction>(instr # "Lh")>;
9236 def : BaseSTOPregister<asm # "l", GPR32, WZR,
9237 !cast<Instruction>(instr # "Ls")>;
9238 def : BaseSTOPregister<asm # "l", GPR64, XZR,
9239 !cast<Instruction>(instr # "Ld")>;
9240 def : BaseSTOPregister<asm # "b", GPR32, WZR,
9241 !cast<Instruction>(instr # "b")>;
9242 def : BaseSTOPregister<asm # "h", GPR32, WZR,
9243 !cast<Instruction>(instr # "h")>;
9244 def : BaseSTOPregister<asm, GPR32, WZR,
9245 !cast<Instruction>(instr # "s")>;
9246 def : BaseSTOPregister<asm, GPR64, XZR,
9247 !cast<Instruction>(instr # "d")>;
9250 //----------------------------------------------------------------------------
9251 // Allow the size specifier tokens to be upper case, not just lower.
9252 def : TokenAlias<".8B", ".8b">;
9253 def : TokenAlias<".4H", ".4h">;
9254 def : TokenAlias<".2S", ".2s">;
9255 def : TokenAlias<".1D", ".1d">;
9256 def : TokenAlias<".16B", ".16b">;
9257 def : TokenAlias<".8H", ".8h">;
9258 def : TokenAlias<".4S", ".4s">;
9259 def : TokenAlias<".2D", ".2d">;
9260 def : TokenAlias<".1Q", ".1q">;
9261 def : TokenAlias<".B", ".b">;
9262 def : TokenAlias<".H", ".h">;
9263 def : TokenAlias<".S", ".s">;
9264 def : TokenAlias<".D", ".d">;
9265 def : TokenAlias<".Q", ".q">;