1 //===- ARM64InstrFormats.td - ARM64 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 ARM64 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 // ARM64 Instruction Format
25 class ARM64Inst<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 = "ARM64";
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 : ARM64Inst<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> : ARM64Inst<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";
94 def MovImm64ShifterOperand : AsmOperandClass {
95 let SuperClasses = [ShifterOperand];
96 let Name = "MovImm64Shifter";
99 // Shifter operand for arithmetic register shifted encodings.
100 def ArithmeticShifterOperand : AsmOperandClass {
101 let SuperClasses = [ShifterOperand];
102 let Name = "ArithmeticShifter";
105 // Shifter operand for arithmetic shifted encodings for ADD/SUB instructions.
106 def AddSubShifterOperand : AsmOperandClass {
107 let SuperClasses = [ArithmeticShifterOperand];
108 let Name = "AddSubShifter";
111 // Shifter operand for logical vector 128/64-bit shifted encodings.
112 def LogicalVecShifterOperand : AsmOperandClass {
113 let SuperClasses = [ShifterOperand];
114 let Name = "LogicalVecShifter";
116 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
117 let SuperClasses = [LogicalVecShifterOperand];
118 let Name = "LogicalVecHalfWordShifter";
121 // The "MSL" shifter on the vector MOVI instruction.
122 def MoveVecShifterOperand : AsmOperandClass {
123 let SuperClasses = [ShifterOperand];
124 let Name = "MoveVecShifter";
127 // Extend operand for arithmetic encodings.
128 def ExtendOperand : AsmOperandClass {
130 let DiagnosticType = "AddSubRegExtendLarge";
132 def ExtendOperand64 : AsmOperandClass {
133 let SuperClasses = [ExtendOperand];
134 let Name = "Extend64";
135 let DiagnosticType = "AddSubRegExtendSmall";
137 // 'extend' that's a lsl of a 64-bit register.
138 def ExtendOperandLSL64 : AsmOperandClass {
139 let SuperClasses = [ExtendOperand];
140 let Name = "ExtendLSL64";
141 let DiagnosticType = "AddSubRegExtendLarge";
144 // 8-bit floating-point immediate encodings.
145 def FPImmOperand : AsmOperandClass {
147 let ParserMethod = "tryParseFPImm";
150 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
151 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
152 // are encoded as the eight bit value 'abcdefgh'.
153 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
156 //===----------------------------------------------------------------------===//
157 // Operand Definitions.
160 // ADR[P] instruction labels.
161 def AdrpOperand : AsmOperandClass {
162 let Name = "AdrpLabel";
163 let ParserMethod = "tryParseAdrpLabel";
164 let DiagnosticType = "InvalidLabel";
166 def adrplabel : Operand<i64> {
167 let EncoderMethod = "getAdrLabelOpValue";
168 let PrintMethod = "printAdrpLabel";
169 let ParserMatchClass = AdrpOperand;
172 def AdrOperand : AsmOperandClass {
173 let Name = "AdrLabel";
174 let ParserMethod = "tryParseAdrLabel";
175 let DiagnosticType = "InvalidLabel";
177 def adrlabel : Operand<i64> {
178 let EncoderMethod = "getAdrLabelOpValue";
179 let ParserMatchClass = AdrOperand;
182 // simm9 predicate - True if the immediate is in the range [-256, 255].
183 def SImm9Operand : AsmOperandClass {
185 let DiagnosticType = "InvalidMemoryIndexedSImm9";
187 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
188 let ParserMatchClass = SImm9Operand;
191 // simm7s4 predicate - True if the immediate is a multiple of 4 in the range
193 def SImm7s4Operand : AsmOperandClass {
194 let Name = "SImm7s4";
195 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
197 def simm7s4 : Operand<i32> {
198 let ParserMatchClass = SImm7s4Operand;
199 let PrintMethod = "printImmScale<4>";
202 // simm7s8 predicate - True if the immediate is a multiple of 8 in the range
204 def SImm7s8Operand : AsmOperandClass {
205 let Name = "SImm7s8";
206 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
208 def simm7s8 : Operand<i32> {
209 let ParserMatchClass = SImm7s8Operand;
210 let PrintMethod = "printImmScale<8>";
213 // simm7s16 predicate - True if the immediate is a multiple of 16 in the range
215 def SImm7s16Operand : AsmOperandClass {
216 let Name = "SImm7s16";
217 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
219 def simm7s16 : Operand<i32> {
220 let ParserMatchClass = SImm7s16Operand;
221 let PrintMethod = "printImmScale<16>";
224 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
225 def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
226 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
227 return ((uint32_t)Imm) < 65536;
229 let ParserMatchClass = Imm0_65535Operand;
230 let PrintMethod = "printHexImm";
233 class AsmImmRange<int Low, int High> : AsmOperandClass {
234 let Name = "Imm" # Low # "_" # High;
235 let DiagnosticType = "InvalidImm" # Low # "_" # High;
238 def Imm1_8Operand : AsmImmRange<1, 8>;
239 def Imm1_16Operand : AsmImmRange<1, 16>;
240 def Imm1_32Operand : AsmImmRange<1, 32>;
241 def Imm1_64Operand : AsmImmRange<1, 64>;
243 def MovZSymbolG3AsmOperand : AsmOperandClass {
244 let Name = "MovZSymbolG3";
245 let RenderMethod = "addImmOperands";
248 def movz_symbol_g3 : Operand<i32> {
249 let ParserMatchClass = MovZSymbolG3AsmOperand;
252 def MovZSymbolG2AsmOperand : AsmOperandClass {
253 let Name = "MovZSymbolG2";
254 let RenderMethod = "addImmOperands";
257 def movz_symbol_g2 : Operand<i32> {
258 let ParserMatchClass = MovZSymbolG2AsmOperand;
261 def MovZSymbolG1AsmOperand : AsmOperandClass {
262 let Name = "MovZSymbolG1";
263 let RenderMethod = "addImmOperands";
266 def movz_symbol_g1 : Operand<i32> {
267 let ParserMatchClass = MovZSymbolG1AsmOperand;
270 def MovZSymbolG0AsmOperand : AsmOperandClass {
271 let Name = "MovZSymbolG0";
272 let RenderMethod = "addImmOperands";
275 def movz_symbol_g0 : Operand<i32> {
276 let ParserMatchClass = MovZSymbolG0AsmOperand;
279 def MovKSymbolG3AsmOperand : AsmOperandClass {
280 let Name = "MovKSymbolG3";
281 let RenderMethod = "addImmOperands";
284 def movk_symbol_g3 : Operand<i32> {
285 let ParserMatchClass = MovKSymbolG3AsmOperand;
288 def MovKSymbolG2AsmOperand : AsmOperandClass {
289 let Name = "MovKSymbolG2";
290 let RenderMethod = "addImmOperands";
293 def movk_symbol_g2 : Operand<i32> {
294 let ParserMatchClass = MovKSymbolG2AsmOperand;
297 def MovKSymbolG1AsmOperand : AsmOperandClass {
298 let Name = "MovKSymbolG1";
299 let RenderMethod = "addImmOperands";
302 def movk_symbol_g1 : Operand<i32> {
303 let ParserMatchClass = MovKSymbolG1AsmOperand;
306 def MovKSymbolG0AsmOperand : AsmOperandClass {
307 let Name = "MovKSymbolG0";
308 let RenderMethod = "addImmOperands";
311 def movk_symbol_g0 : Operand<i32> {
312 let ParserMatchClass = MovKSymbolG0AsmOperand;
315 class fixedpoint_i32<ValueType FloatVT>
317 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
318 let EncoderMethod = "getFixedPointScaleOpValue";
319 let DecoderMethod = "DecodeFixedPointScaleImm32";
320 let ParserMatchClass = Imm1_32Operand;
323 class fixedpoint_i64<ValueType FloatVT>
325 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
326 let EncoderMethod = "getFixedPointScaleOpValue";
327 let DecoderMethod = "DecodeFixedPointScaleImm64";
328 let ParserMatchClass = Imm1_64Operand;
331 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
332 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
334 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
335 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
337 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
338 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
340 let EncoderMethod = "getVecShiftR8OpValue";
341 let DecoderMethod = "DecodeVecShiftR8Imm";
342 let ParserMatchClass = Imm1_8Operand;
344 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
345 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
347 let EncoderMethod = "getVecShiftR16OpValue";
348 let DecoderMethod = "DecodeVecShiftR16Imm";
349 let ParserMatchClass = Imm1_16Operand;
351 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
352 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
354 let EncoderMethod = "getVecShiftR16OpValue";
355 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
356 let ParserMatchClass = Imm1_8Operand;
358 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
359 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
361 let EncoderMethod = "getVecShiftR32OpValue";
362 let DecoderMethod = "DecodeVecShiftR32Imm";
363 let ParserMatchClass = Imm1_32Operand;
365 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
366 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
368 let EncoderMethod = "getVecShiftR32OpValue";
369 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
370 let ParserMatchClass = Imm1_16Operand;
372 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
373 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
375 let EncoderMethod = "getVecShiftR64OpValue";
376 let DecoderMethod = "DecodeVecShiftR64Imm";
377 let ParserMatchClass = Imm1_64Operand;
379 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
380 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
382 let EncoderMethod = "getVecShiftR64OpValue";
383 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
384 let ParserMatchClass = Imm1_32Operand;
387 def Imm0_7Operand : AsmImmRange<0, 7>;
388 def Imm0_15Operand : AsmImmRange<0, 15>;
389 def Imm0_31Operand : AsmImmRange<0, 31>;
390 def Imm0_63Operand : AsmImmRange<0, 63>;
392 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
393 return (((uint32_t)Imm) < 8);
395 let EncoderMethod = "getVecShiftL8OpValue";
396 let DecoderMethod = "DecodeVecShiftL8Imm";
397 let ParserMatchClass = Imm0_7Operand;
399 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
400 return (((uint32_t)Imm) < 16);
402 let EncoderMethod = "getVecShiftL16OpValue";
403 let DecoderMethod = "DecodeVecShiftL16Imm";
404 let ParserMatchClass = Imm0_15Operand;
406 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
407 return (((uint32_t)Imm) < 32);
409 let EncoderMethod = "getVecShiftL32OpValue";
410 let DecoderMethod = "DecodeVecShiftL32Imm";
411 let ParserMatchClass = Imm0_31Operand;
413 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
414 return (((uint32_t)Imm) < 64);
416 let EncoderMethod = "getVecShiftL64OpValue";
417 let DecoderMethod = "DecodeVecShiftL64Imm";
418 let ParserMatchClass = Imm0_63Operand;
422 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
423 // instructions for splatting repeating bit patterns across the immediate.
424 def logical_imm32_XFORM : SDNodeXForm<imm, [{
425 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
426 return CurDAG->getTargetConstant(enc, MVT::i32);
428 def logical_imm64_XFORM : SDNodeXForm<imm, [{
429 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
430 return CurDAG->getTargetConstant(enc, MVT::i32);
433 def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
434 def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
435 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
436 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
437 }], logical_imm32_XFORM> {
438 let PrintMethod = "printLogicalImm32";
439 let ParserMatchClass = LogicalImm32Operand;
441 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
442 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
443 }], logical_imm64_XFORM> {
444 let PrintMethod = "printLogicalImm64";
445 let ParserMatchClass = LogicalImm64Operand;
448 // imm0_255 predicate - True if the immediate is in the range [0,255].
449 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
450 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
451 return ((uint32_t)Imm) < 256;
453 let ParserMatchClass = Imm0_255Operand;
454 let PrintMethod = "printHexImm";
457 // imm0_127 predicate - True if the immediate is in the range [0,127]
458 def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
459 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
460 return ((uint32_t)Imm) < 128;
462 let ParserMatchClass = Imm0_127Operand;
463 let PrintMethod = "printHexImm";
466 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
467 // for all shift-amounts.
469 // imm0_63 predicate - True if the immediate is in the range [0,63]
470 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
471 return ((uint64_t)Imm) < 64;
473 let ParserMatchClass = Imm0_63Operand;
476 // imm0_31 predicate - True if the immediate is in the range [0,31]
477 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
478 return ((uint64_t)Imm) < 32;
480 let ParserMatchClass = Imm0_31Operand;
483 // imm0_15 predicate - True if the immediate is in the range [0,15]
484 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
485 return ((uint64_t)Imm) < 16;
487 let ParserMatchClass = Imm0_15Operand;
490 // imm0_7 predicate - True if the immediate is in the range [0,7]
491 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
492 return ((uint64_t)Imm) < 8;
494 let ParserMatchClass = Imm0_7Operand;
497 // An arithmetic shifter operand:
498 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
500 def arith_shift : Operand<i32> {
501 let PrintMethod = "printShifter";
502 let ParserMatchClass = ArithmeticShifterOperand;
505 class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
507 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
508 let PrintMethod = "printShiftedRegister";
509 let MIOperandInfo = (ops regclass, arith_shift);
512 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
513 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
515 // An arithmetic shifter operand:
516 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
518 def logical_shift : Operand<i32> {
519 let PrintMethod = "printShifter";
520 let ParserMatchClass = ShifterOperand;
523 class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
525 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
526 let PrintMethod = "printShiftedRegister";
527 let MIOperandInfo = (ops regclass, logical_shift);
530 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
531 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
533 // A logical vector shifter operand:
534 // {7-6} - shift type: 00 = lsl
535 // {5-0} - imm6: #0, #8, #16, or #24
536 def logical_vec_shift : Operand<i32> {
537 let PrintMethod = "printShifter";
538 let EncoderMethod = "getVecShifterOpValue";
539 let ParserMatchClass = LogicalVecShifterOperand;
542 // A logical vector half-word shifter operand:
543 // {7-6} - shift type: 00 = lsl
544 // {5-0} - imm6: #0 or #8
545 def logical_vec_hw_shift : Operand<i32> {
546 let PrintMethod = "printShifter";
547 let EncoderMethod = "getVecShifterOpValue";
548 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
551 // A vector move shifter operand:
552 // {0} - imm1: #8 or #16
553 def move_vec_shift : Operand<i32> {
554 let PrintMethod = "printShifter";
555 let EncoderMethod = "getMoveVecShifterOpValue";
556 let ParserMatchClass = MoveVecShifterOperand;
559 // An ADD/SUB immediate shifter operand:
560 // {7-6} - shift type: 00 = lsl
561 // {5-0} - imm6: #0 or #12
562 def addsub_shift : Operand<i32> {
563 let ParserMatchClass = AddSubShifterOperand;
566 class addsub_shifted_imm<ValueType Ty>
567 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
568 let PrintMethod = "printAddSubImm";
569 let EncoderMethod = "getAddSubImmOpValue";
570 let MIOperandInfo = (ops i32imm, addsub_shift);
573 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
574 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
576 class neg_addsub_shifted_imm<ValueType Ty>
577 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
578 let PrintMethod = "printAddSubImm";
579 let EncoderMethod = "getAddSubImmOpValue";
580 let MIOperandInfo = (ops i32imm, addsub_shift);
583 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
584 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
586 // An extend operand:
587 // {5-3} - extend type
589 def arith_extend : Operand<i32> {
590 let PrintMethod = "printExtend";
591 let ParserMatchClass = ExtendOperand;
593 def arith_extend64 : Operand<i32> {
594 let PrintMethod = "printExtend";
595 let ParserMatchClass = ExtendOperand64;
598 // 'extend' that's a lsl of a 64-bit register.
599 def arith_extendlsl64 : Operand<i32> {
600 let PrintMethod = "printExtend";
601 let ParserMatchClass = ExtendOperandLSL64;
604 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
605 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
606 let PrintMethod = "printExtendedRegister";
607 let MIOperandInfo = (ops GPR32, arith_extend);
610 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
611 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
612 let PrintMethod = "printExtendedRegister";
613 let MIOperandInfo = (ops GPR32, arith_extend64);
616 // Floating-point immediate.
617 def fpimm32 : Operand<f32>,
618 PatLeaf<(f32 fpimm), [{
619 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
620 }], SDNodeXForm<fpimm, [{
621 APFloat InVal = N->getValueAPF();
622 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
623 return CurDAG->getTargetConstant(enc, MVT::i32);
625 let ParserMatchClass = FPImmOperand;
626 let PrintMethod = "printFPImmOperand";
628 def fpimm64 : Operand<f64>,
629 PatLeaf<(f64 fpimm), [{
630 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
631 }], SDNodeXForm<fpimm, [{
632 APFloat InVal = N->getValueAPF();
633 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
634 return CurDAG->getTargetConstant(enc, MVT::i32);
636 let ParserMatchClass = FPImmOperand;
637 let PrintMethod = "printFPImmOperand";
640 def fpimm8 : Operand<i32> {
641 let ParserMatchClass = FPImmOperand;
642 let PrintMethod = "printFPImmOperand";
645 def fpimm0 : PatLeaf<(fpimm), [{
646 return N->isExactlyValue(+0.0);
649 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
650 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
651 // are encoded as the eight bit value 'abcdefgh'.
652 def simdimmtype10 : Operand<i32>,
653 PatLeaf<(f64 fpimm), [{
654 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
657 }], SDNodeXForm<fpimm, [{
658 APFloat InVal = N->getValueAPF();
659 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
662 return CurDAG->getTargetConstant(enc, MVT::i32);
664 let ParserMatchClass = SIMDImmType10Operand;
665 let PrintMethod = "printSIMDType10Operand";
673 // Base encoding for system instruction operands.
674 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
675 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
676 : I<oops, iops, asm, operands, "", []> {
677 let Inst{31-22} = 0b1101010100;
681 // System instructions which do not have an Rt register.
682 class SimpleSystemI<bit L, dag iops, string asm, string operands>
683 : BaseSystemI<L, (outs), iops, asm, operands> {
684 let Inst{4-0} = 0b11111;
687 // System instructions which have an Rt register.
688 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
689 : BaseSystemI<L, oops, iops, asm, operands>,
695 // Hint instructions that take both a CRm and a 3-bit immediate.
696 class HintI<string mnemonic>
697 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
700 let Inst{20-12} = 0b000110010;
701 let Inst{11-5} = imm;
704 // System instructions taking a single literal operand which encodes into
705 // CRm. op2 differentiates the opcodes.
706 def BarrierAsmOperand : AsmOperandClass {
707 let Name = "Barrier";
708 let ParserMethod = "tryParseBarrierOperand";
710 def barrier_op : Operand<i32> {
711 let PrintMethod = "printBarrierOption";
712 let ParserMatchClass = BarrierAsmOperand;
714 class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
715 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
716 Sched<[WriteBarrier]> {
718 let Inst{20-12} = 0b000110011;
719 let Inst{11-8} = CRm;
723 // MRS/MSR system instructions. These have different operand classes because
724 // a different subset of registers can be accessed through each instruction.
725 def MRSSystemRegisterOperand : AsmOperandClass {
726 let Name = "MRSSystemRegister";
727 let ParserMethod = "tryParseSysReg";
728 let DiagnosticType = "MRS";
730 // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
731 def mrs_sysreg_op : Operand<i32> {
732 let ParserMatchClass = MRSSystemRegisterOperand;
733 let DecoderMethod = "DecodeMRSSystemRegister";
734 let PrintMethod = "printMRSSystemRegister";
737 def MSRSystemRegisterOperand : AsmOperandClass {
738 let Name = "MSRSystemRegister";
739 let ParserMethod = "tryParseSysReg";
740 let DiagnosticType = "MSR";
742 def msr_sysreg_op : Operand<i32> {
743 let ParserMatchClass = MSRSystemRegisterOperand;
744 let DecoderMethod = "DecodeMSRSystemRegister";
745 let PrintMethod = "printMSRSystemRegister";
748 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
749 "mrs", "\t$Rt, $systemreg"> {
752 let Inst{19-5} = systemreg;
755 // FIXME: Some of these def NZCV, others don't. Best way to model that?
756 // Explicitly modeling each of the system register as a register class
757 // would do it, but feels like overkill at this point.
758 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
759 "msr", "\t$systemreg, $Rt"> {
762 let Inst{19-5} = systemreg;
765 def SystemPStateFieldOperand : AsmOperandClass {
766 let Name = "SystemPStateField";
767 let ParserMethod = "tryParseSysReg";
769 def pstatefield_op : Operand<i32> {
770 let ParserMatchClass = SystemPStateFieldOperand;
771 let PrintMethod = "printSystemPStateField";
776 : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
777 "msr", "\t$pstate_field, $imm">,
781 let Inst{20-19} = 0b00;
782 let Inst{18-16} = pstatefield{5-3};
783 let Inst{15-12} = 0b0100;
784 let Inst{11-8} = imm;
785 let Inst{7-5} = pstatefield{2-0};
787 let DecoderMethod = "DecodeSystemPStateInstruction";
790 // SYS and SYSL generic system instructions.
791 def SysCRAsmOperand : AsmOperandClass {
793 let ParserMethod = "tryParseSysCROperand";
796 def sys_cr_op : Operand<i32> {
797 let PrintMethod = "printSysCROperand";
798 let ParserMatchClass = SysCRAsmOperand;
801 class SystemXtI<bit L, string asm>
802 : RtSystemI<L, (outs),
803 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
804 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
809 let Inst{20-19} = 0b01;
810 let Inst{18-16} = op1;
811 let Inst{15-12} = Cn;
816 class SystemLXtI<bit L, string asm>
817 : RtSystemI<L, (outs),
818 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
819 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
824 let Inst{20-19} = 0b01;
825 let Inst{18-16} = op1;
826 let Inst{15-12} = Cn;
832 // Branch (register) instructions:
840 // otherwise UNDEFINED
841 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
842 string operands, list<dag> pattern>
843 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
844 let Inst{31-25} = 0b1101011;
845 let Inst{24-21} = opc;
846 let Inst{20-16} = 0b11111;
847 let Inst{15-10} = 0b000000;
848 let Inst{4-0} = 0b00000;
851 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
852 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
857 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
858 class SpecialReturn<bits<4> opc, string asm>
859 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
860 let Inst{9-5} = 0b11111;
864 // Conditional branch instruction.
866 // Branch condition code.
867 // 4-bit immediate. Pretty-printed as .<cc>
868 def dotCcode : Operand<i32> {
869 let PrintMethod = "printDotCondCode";
872 // Conditional branch target. 19-bit immediate. The low two bits of the target
873 // offset are implied zero and so are not part of the immediate.
874 def PCRelLabel19Operand : AsmOperandClass {
875 let Name = "PCRelLabel19";
877 def am_brcond : Operand<OtherVT> {
878 let EncoderMethod = "getCondBranchTargetOpValue";
879 let DecoderMethod = "DecodePCRelLabel19";
880 let PrintMethod = "printAlignedLabel";
881 let ParserMatchClass = PCRelLabel19Operand;
884 class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
885 "b", "$cond\t$target", "",
886 [(ARM64brcond bb:$target, imm:$cond, NZCV)]>,
889 let isTerminator = 1;
894 let Inst{31-24} = 0b01010100;
895 let Inst{23-5} = target;
897 let Inst{3-0} = cond;
901 // Compare-and-branch instructions.
903 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
904 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
905 asm, "\t$Rt, $target", "",
906 [(node regtype:$Rt, bb:$target)]>,
909 let isTerminator = 1;
913 let Inst{30-25} = 0b011010;
915 let Inst{23-5} = target;
919 multiclass CmpBranch<bit op, string asm, SDNode node> {
920 def W : BaseCmpBranch<GPR32, op, asm, node> {
923 def X : BaseCmpBranch<GPR64, op, asm, node> {
929 // Test-bit-and-branch instructions.
931 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
932 // the target offset are implied zero and so are not part of the immediate.
933 def BranchTarget14Operand : AsmOperandClass {
934 let Name = "BranchTarget14";
936 def am_tbrcond : Operand<OtherVT> {
937 let EncoderMethod = "getTestBranchTargetOpValue";
938 let PrintMethod = "printAlignedLabel";
939 let ParserMatchClass = BranchTarget14Operand;
942 class TestBranch<bit op, string asm, SDNode node>
943 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
944 asm, "\t$Rt, $bit_off, $target", "",
945 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
948 let isTerminator = 1;
954 let Inst{31} = bit_off{5};
955 let Inst{30-25} = 0b011011;
957 let Inst{23-19} = bit_off{4-0};
958 let Inst{18-5} = target;
961 let DecoderMethod = "DecodeTestAndBranch";
965 // Unconditional branch (immediate) instructions.
967 def BranchTarget26Operand : AsmOperandClass {
968 let Name = "BranchTarget26";
970 def am_b_target : Operand<OtherVT> {
971 let EncoderMethod = "getBranchTargetOpValue";
972 let PrintMethod = "printAlignedLabel";
973 let ParserMatchClass = BranchTarget26Operand;
975 def am_bl_target : Operand<i64> {
976 let EncoderMethod = "getBranchTargetOpValue";
977 let PrintMethod = "printAlignedLabel";
978 let ParserMatchClass = BranchTarget26Operand;
981 class BImm<bit op, dag iops, string asm, list<dag> pattern>
982 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
985 let Inst{30-26} = 0b00101;
986 let Inst{25-0} = addr;
988 let DecoderMethod = "DecodeUnconditionalBranch";
991 class BranchImm<bit op, string asm, list<dag> pattern>
992 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
993 class CallImm<bit op, string asm, list<dag> pattern>
994 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
997 // Basic one-operand data processing instructions.
1000 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1001 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1002 SDPatternOperator node>
1003 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1004 [(set regtype:$Rd, (node regtype:$Rn))]>,
1009 let Inst{30-13} = 0b101101011000000000;
1010 let Inst{12-10} = opc;
1015 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1016 multiclass OneOperandData<bits<3> opc, string asm,
1017 SDPatternOperator node = null_frag> {
1018 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1022 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1027 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1028 : BaseOneOperandData<opc, GPR32, asm, node> {
1032 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1033 : BaseOneOperandData<opc, GPR64, asm, node> {
1038 // Basic two-operand data processing instructions.
1040 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1042 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1043 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1049 let Inst{30} = isSub;
1050 let Inst{28-21} = 0b11010000;
1051 let Inst{20-16} = Rm;
1052 let Inst{15-10} = 0;
1057 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1059 : BaseBaseAddSubCarry<isSub, regtype, asm,
1060 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1062 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1064 : BaseBaseAddSubCarry<isSub, regtype, asm,
1065 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1070 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1071 SDNode OpNode, SDNode OpNode_setflags> {
1072 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1076 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1082 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1087 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1094 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1095 SDPatternOperator OpNode>
1096 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1097 asm, "\t$Rd, $Rn, $Rm", "",
1098 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1102 let Inst{30-21} = 0b0011010110;
1103 let Inst{20-16} = Rm;
1104 let Inst{15-14} = 0b00;
1105 let Inst{13-10} = opc;
1110 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1111 SDPatternOperator OpNode>
1112 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1113 let Inst{10} = isSigned;
1116 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1117 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1118 Sched<[WriteID32]> {
1121 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1122 Sched<[WriteID64]> {
1127 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1128 SDPatternOperator OpNode = null_frag>
1129 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1131 let Inst{11-10} = shift_type;
1134 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1135 def Wr : BaseShift<shift_type, GPR32, asm> {
1139 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1143 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1144 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1145 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1147 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1148 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1150 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1151 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1153 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1154 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1157 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1158 : InstAlias<asm#" $dst, $src1, $src2",
1159 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1161 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1162 RegisterClass addtype, string asm,
1164 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1165 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1170 let Inst{30-24} = 0b0011011;
1171 let Inst{23-21} = opc;
1172 let Inst{20-16} = Rm;
1173 let Inst{15} = isSub;
1174 let Inst{14-10} = Ra;
1179 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1180 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1181 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1182 Sched<[WriteIM32]> {
1186 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1187 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1188 Sched<[WriteIM64]> {
1193 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1194 SDNode AccNode, SDNode ExtNode>
1195 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1196 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1197 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1198 Sched<[WriteIM32]> {
1202 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1203 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1204 asm, "\t$Rd, $Rn, $Rm", "",
1205 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1206 Sched<[WriteIM64]> {
1210 let Inst{31-24} = 0b10011011;
1211 let Inst{23-21} = opc;
1212 let Inst{20-16} = Rm;
1217 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1218 // (i.e. all bits 1) but is ignored by the processor.
1219 let PostEncoderMethod = "fixMulHigh";
1222 class MulAccumWAlias<string asm, Instruction inst>
1223 : InstAlias<asm#" $dst, $src1, $src2",
1224 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1225 class MulAccumXAlias<string asm, Instruction inst>
1226 : InstAlias<asm#" $dst, $src1, $src2",
1227 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1228 class WideMulAccumAlias<string asm, Instruction inst>
1229 : InstAlias<asm#" $dst, $src1, $src2",
1230 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1232 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1233 SDPatternOperator OpNode, string asm>
1234 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1235 asm, "\t$Rd, $Rn, $Rm", "",
1236 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1237 Sched<[WriteISReg]> {
1243 let Inst{30-21} = 0b0011010110;
1244 let Inst{20-16} = Rm;
1245 let Inst{15-13} = 0b010;
1247 let Inst{11-10} = sz;
1250 let Predicates = [HasCRC];
1254 // Address generation.
1257 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1258 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1263 let Inst{31} = page;
1264 let Inst{30-29} = label{1-0};
1265 let Inst{28-24} = 0b10000;
1266 let Inst{23-5} = label{20-2};
1269 let DecoderMethod = "DecodeAdrInstruction";
1276 def movimm32_imm : Operand<i32> {
1277 let ParserMatchClass = Imm0_65535Operand;
1278 let EncoderMethod = "getMoveWideImmOpValue";
1279 let PrintMethod = "printHexImm";
1281 def movimm32_shift : Operand<i32> {
1282 let PrintMethod = "printShifter";
1283 let ParserMatchClass = MovImm32ShifterOperand;
1285 def movimm64_shift : Operand<i32> {
1286 let PrintMethod = "printShifter";
1287 let ParserMatchClass = MovImm64ShifterOperand;
1289 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1290 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1292 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1293 asm, "\t$Rd, $imm$shift", "", []>,
1298 let Inst{30-29} = opc;
1299 let Inst{28-23} = 0b100101;
1300 let Inst{22-21} = shift{5-4};
1301 let Inst{20-5} = imm;
1304 let DecoderMethod = "DecodeMoveImmInstruction";
1307 multiclass MoveImmediate<bits<2> opc, string asm> {
1308 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1312 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1317 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1318 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1320 : I<(outs regtype:$Rd),
1321 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1322 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1327 let Inst{30-29} = opc;
1328 let Inst{28-23} = 0b100101;
1329 let Inst{22-21} = shift{5-4};
1330 let Inst{20-5} = imm;
1333 let DecoderMethod = "DecodeMoveImmInstruction";
1336 multiclass InsertImmediate<bits<2> opc, string asm> {
1337 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1341 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1350 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1351 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1352 string asm, SDPatternOperator OpNode>
1353 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1354 asm, "\t$Rd, $Rn, $imm", "",
1355 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1360 let Inst{30} = isSub;
1361 let Inst{29} = setFlags;
1362 let Inst{28-24} = 0b10001;
1363 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1364 let Inst{21-10} = imm{11-0};
1367 let DecoderMethod = "DecodeBaseAddSubImm";
1370 class BaseAddSubRegPseudo<RegisterClass regtype,
1371 SDPatternOperator OpNode>
1372 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1373 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1376 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1377 arith_shifted_reg shifted_regtype, string asm,
1378 SDPatternOperator OpNode>
1379 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1380 asm, "\t$Rd, $Rn, $Rm", "",
1381 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1382 Sched<[WriteISReg]> {
1383 // The operands are in order to match the 'addr' MI operands, so we
1384 // don't need an encoder method and by-name matching. Just use the default
1385 // in-order handling. Since we're using by-order, make sure the names
1391 let Inst{30} = isSub;
1392 let Inst{29} = setFlags;
1393 let Inst{28-24} = 0b01011;
1394 let Inst{23-22} = shift{7-6};
1396 let Inst{20-16} = src2;
1397 let Inst{15-10} = shift{5-0};
1398 let Inst{9-5} = src1;
1399 let Inst{4-0} = dst;
1401 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1404 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1405 RegisterClass src1Regtype, Operand src2Regtype,
1406 string asm, SDPatternOperator OpNode>
1407 : I<(outs dstRegtype:$R1),
1408 (ins src1Regtype:$R2, src2Regtype:$R3),
1409 asm, "\t$R1, $R2, $R3", "",
1410 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1411 Sched<[WriteIEReg]> {
1416 let Inst{30} = isSub;
1417 let Inst{29} = setFlags;
1418 let Inst{28-24} = 0b01011;
1419 let Inst{23-21} = 0b001;
1420 let Inst{20-16} = Rm;
1421 let Inst{15-13} = ext{5-3};
1422 let Inst{12-10} = ext{2-0};
1426 let DecoderMethod = "DecodeAddSubERegInstruction";
1429 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1430 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1431 RegisterClass src1Regtype, RegisterClass src2Regtype,
1432 Operand ext_op, string asm>
1433 : I<(outs dstRegtype:$Rd),
1434 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1435 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1436 Sched<[WriteIEReg]> {
1441 let Inst{30} = isSub;
1442 let Inst{29} = setFlags;
1443 let Inst{28-24} = 0b01011;
1444 let Inst{23-21} = 0b001;
1445 let Inst{20-16} = Rm;
1446 let Inst{15} = ext{5};
1447 let Inst{12-10} = ext{2-0};
1451 let DecoderMethod = "DecodeAddSubERegInstruction";
1454 // Aliases for register+register add/subtract.
1455 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1456 RegisterClass src1Regtype, RegisterClass src2Regtype,
1458 : InstAlias<asm#" $dst, $src1, $src2",
1459 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1462 multiclass AddSub<bit isSub, string mnemonic,
1463 SDPatternOperator OpNode = null_frag> {
1464 let hasSideEffects = 0 in {
1465 // Add/Subtract immediate
1466 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1470 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1475 // Add/Subtract register - Only used for CodeGen
1476 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1477 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1479 // Add/Subtract shifted register
1480 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1484 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1490 // Add/Subtract extended register
1491 let AddedComplexity = 1, hasSideEffects = 0 in {
1492 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1493 arith_extended_reg32<i32>, mnemonic, OpNode> {
1496 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1497 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1502 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1503 arith_extendlsl64, mnemonic> {
1504 // UXTX and SXTX only.
1505 let Inst{14-13} = 0b11;
1509 // Register/register aliases with no shift when SP is not used.
1510 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1511 GPR32, GPR32, GPR32, 0>;
1512 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1513 GPR64, GPR64, GPR64, 0>;
1515 // Register/register aliases with no shift when either the destination or
1516 // first source register is SP. This relies on the shifted register aliases
1517 // above matching first in the case when SP is not used.
1518 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1519 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1520 def : AddSubRegAlias<mnemonic,
1521 !cast<Instruction>(NAME#"Xrx64"),
1522 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1525 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1526 let isCompare = 1, Defs = [NZCV] in {
1527 // Add/Subtract immediate
1528 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1532 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1537 // Add/Subtract register
1538 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1539 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1541 // Add/Subtract shifted register
1542 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1546 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1551 // Add/Subtract extended register
1552 let AddedComplexity = 1 in {
1553 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1554 arith_extended_reg32<i32>, mnemonic, OpNode> {
1557 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1558 arith_extended_reg32<i64>, mnemonic, OpNode> {
1563 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1564 arith_extendlsl64, mnemonic> {
1565 // UXTX and SXTX only.
1566 let Inst{14-13} = 0b11;
1571 // Register/register aliases with no shift when SP is not used.
1572 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1573 GPR32, GPR32, GPR32, 0>;
1574 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1575 GPR64, GPR64, GPR64, 0>;
1577 // Register/register aliases with no shift when the first source register
1578 // is SP. This relies on the shifted register aliases above matching first
1579 // in the case when SP is not used.
1580 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1581 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1582 def : AddSubRegAlias<mnemonic,
1583 !cast<Instruction>(NAME#"Xrx64"),
1584 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1590 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1592 def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1594 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1596 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1597 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1598 Sched<[WriteExtr, ReadExtrHi]> {
1604 let Inst{30-23} = 0b00100111;
1606 let Inst{20-16} = Rm;
1607 let Inst{15-10} = imm;
1612 multiclass ExtractImm<string asm> {
1613 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1615 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1618 // imm<5> must be zero.
1621 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1623 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1634 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1635 class BaseBitfieldImm<bits<2> opc,
1636 RegisterClass regtype, Operand imm_type, string asm>
1637 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1638 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1645 let Inst{30-29} = opc;
1646 let Inst{28-23} = 0b100110;
1647 let Inst{21-16} = immr;
1648 let Inst{15-10} = imms;
1653 multiclass BitfieldImm<bits<2> opc, string asm> {
1654 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1657 // imms<5> and immr<5> must be zero, else ReservedValue().
1661 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1667 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1668 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1669 RegisterClass regtype, Operand imm_type, string asm>
1670 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1672 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1679 let Inst{30-29} = opc;
1680 let Inst{28-23} = 0b100110;
1681 let Inst{21-16} = immr;
1682 let Inst{15-10} = imms;
1687 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1688 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1691 // imms<5> and immr<5> must be zero, else ReservedValue().
1695 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1705 // Logical (immediate)
1706 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1707 RegisterClass sregtype, Operand imm_type, string asm,
1709 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1710 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1715 let Inst{30-29} = opc;
1716 let Inst{28-23} = 0b100100;
1717 let Inst{22} = imm{12};
1718 let Inst{21-16} = imm{11-6};
1719 let Inst{15-10} = imm{5-0};
1723 let DecoderMethod = "DecodeLogicalImmInstruction";
1726 // Logical (shifted register)
1727 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1728 logical_shifted_reg shifted_regtype, string asm,
1730 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1731 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1732 Sched<[WriteISReg]> {
1733 // The operands are in order to match the 'addr' MI operands, so we
1734 // don't need an encoder method and by-name matching. Just use the default
1735 // in-order handling. Since we're using by-order, make sure the names
1741 let Inst{30-29} = opc;
1742 let Inst{28-24} = 0b01010;
1743 let Inst{23-22} = shift{7-6};
1745 let Inst{20-16} = src2;
1746 let Inst{15-10} = shift{5-0};
1747 let Inst{9-5} = src1;
1748 let Inst{4-0} = dst;
1750 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1753 // Aliases for register+register logical instructions.
1754 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1755 : InstAlias<asm#" $dst, $src1, $src2",
1756 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1758 let AddedComplexity = 6 in
1759 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1760 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1761 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1762 logical_imm32:$imm))]> {
1764 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1766 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1767 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1768 logical_imm64:$imm))]> {
1773 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1774 let isCompare = 1, Defs = [NZCV] in {
1775 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1776 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1778 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1780 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1781 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1784 } // end Defs = [NZCV]
1787 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1788 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1789 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1792 // Split from LogicalImm as not all instructions have both.
1793 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1794 SDPatternOperator OpNode> {
1795 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1796 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1798 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1799 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1800 logical_shifted_reg32:$Rm))]> {
1803 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1804 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1805 logical_shifted_reg64:$Rm))]> {
1809 def : LogicalRegAlias<mnemonic,
1810 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1811 def : LogicalRegAlias<mnemonic,
1812 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1815 // Split from LogicalReg to allow setting NZCV Defs
1816 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
1817 SDPatternOperator OpNode = null_frag> {
1818 let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1819 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1820 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1822 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1823 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
1826 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1827 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
1832 def : LogicalRegAlias<mnemonic,
1833 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1834 def : LogicalRegAlias<mnemonic,
1835 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1839 // Conditionally set flags
1843 // 4-bit immediate. Pretty-printed as <cc>
1844 def ccode : Operand<i32> {
1845 let PrintMethod = "printCondCode";
1848 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1849 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1850 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1851 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1862 let Inst{29-21} = 0b111010010;
1863 let Inst{20-16} = imm;
1864 let Inst{15-12} = cond;
1865 let Inst{11-10} = 0b10;
1868 let Inst{3-0} = nzcv;
1871 multiclass CondSetFlagsImm<bit op, string asm> {
1872 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1875 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1880 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1881 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1882 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1883 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1894 let Inst{29-21} = 0b111010010;
1895 let Inst{20-16} = Rm;
1896 let Inst{15-12} = cond;
1897 let Inst{11-10} = 0b00;
1900 let Inst{3-0} = nzcv;
1903 multiclass CondSetFlagsReg<bit op, string asm> {
1904 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1907 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1913 // Conditional select
1916 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1917 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1918 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1920 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
1930 let Inst{29-21} = 0b011010100;
1931 let Inst{20-16} = Rm;
1932 let Inst{15-12} = cond;
1933 let Inst{11-10} = op2;
1938 multiclass CondSelect<bit op, bits<2> op2, string asm> {
1939 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1942 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1947 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1949 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1950 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1952 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1953 (i32 imm:$cond), NZCV))]>,
1963 let Inst{29-21} = 0b011010100;
1964 let Inst{20-16} = Rm;
1965 let Inst{15-12} = cond;
1966 let Inst{11-10} = op2;
1971 def inv_cond_XFORM : SDNodeXForm<imm, [{
1972 ARM64CC::CondCode CC = static_cast<ARM64CC::CondCode>(N->getZExtValue());
1973 return CurDAG->getTargetConstant(ARM64CC::getInvertedCondCode(CC), MVT::i32);
1976 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1977 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1980 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1984 def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
1985 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
1986 (inv_cond_XFORM imm:$cond))>;
1988 def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
1989 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
1990 (inv_cond_XFORM imm:$cond))>;
1994 // Special Mask Value
1996 def maski8_or_more : Operand<i32>,
1997 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1999 def maski16_or_more : Operand<i32>,
2000 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2008 // (unsigned immediate)
2009 // Indexed for 8-bit registers. offset is in range [0,4095].
2010 def MemoryIndexed8Operand : AsmOperandClass {
2011 let Name = "MemoryIndexed8";
2012 let DiagnosticType = "InvalidMemoryIndexed8";
2014 def am_indexed8 : Operand<i64>,
2015 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
2016 let PrintMethod = "printAMIndexed<8>";
2018 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
2019 let ParserMatchClass = MemoryIndexed8Operand;
2020 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2023 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
2024 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
2025 def MemoryIndexed16Operand : AsmOperandClass {
2026 let Name = "MemoryIndexed16";
2027 let DiagnosticType = "InvalidMemoryIndexed16";
2029 def am_indexed16 : Operand<i64>,
2030 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2031 let PrintMethod = "printAMIndexed<16>";
2033 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2034 let ParserMatchClass = MemoryIndexed16Operand;
2035 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2038 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2039 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2040 def MemoryIndexed32Operand : AsmOperandClass {
2041 let Name = "MemoryIndexed32";
2042 let DiagnosticType = "InvalidMemoryIndexed32";
2044 def am_indexed32 : Operand<i64>,
2045 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2046 let PrintMethod = "printAMIndexed<32>";
2048 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2049 let ParserMatchClass = MemoryIndexed32Operand;
2050 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2053 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2054 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2055 def MemoryIndexed64Operand : AsmOperandClass {
2056 let Name = "MemoryIndexed64";
2057 let DiagnosticType = "InvalidMemoryIndexed64";
2059 def am_indexed64 : Operand<i64>,
2060 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2061 let PrintMethod = "printAMIndexed<64>";
2063 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2064 let ParserMatchClass = MemoryIndexed64Operand;
2065 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2068 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2069 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2070 def MemoryIndexed128Operand : AsmOperandClass {
2071 let Name = "MemoryIndexed128";
2072 let DiagnosticType = "InvalidMemoryIndexed128";
2074 def am_indexed128 : Operand<i64>,
2075 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2076 let PrintMethod = "printAMIndexed<128>";
2078 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2079 let ParserMatchClass = MemoryIndexed128Operand;
2080 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2084 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2085 def am_noindex : Operand<i64>,
2086 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2087 let PrintMethod = "printAMNoIndex";
2088 let ParserMatchClass = MemoryNoIndexOperand;
2089 let MIOperandInfo = (ops GPR64sp:$base);
2092 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2093 string asm, list<dag> pattern>
2094 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2098 bits<5> base = addr{4-0};
2099 bits<12> offset = addr{16-5};
2101 let Inst{31-30} = sz;
2102 let Inst{29-27} = 0b111;
2104 let Inst{25-24} = 0b01;
2105 let Inst{23-22} = opc;
2106 let Inst{21-10} = offset;
2107 let Inst{9-5} = base;
2108 let Inst{4-0} = dst;
2110 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2113 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2114 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2115 Operand indextype, string asm, list<dag> pattern>
2116 : BaseLoadStoreUI<sz, V, opc,
2117 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2120 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2121 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2122 Operand indextype, string asm, list<dag> pattern>
2123 : BaseLoadStoreUI<sz, V, opc,
2124 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2127 def PrefetchOperand : AsmOperandClass {
2128 let Name = "Prefetch";
2129 let ParserMethod = "tryParsePrefetch";
2131 def prfop : Operand<i32> {
2132 let PrintMethod = "printPrefetchOp";
2133 let ParserMatchClass = PrefetchOperand;
2136 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2137 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2138 : BaseLoadStoreUI<sz, V, opc,
2139 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2146 // Load literal address: 19-bit immediate. The low two bits of the target
2147 // offset are implied zero and so are not part of the immediate.
2148 def am_ldrlit : Operand<OtherVT> {
2149 let EncoderMethod = "getLoadLiteralOpValue";
2150 let DecoderMethod = "DecodePCRelLabel19";
2151 let PrintMethod = "printAlignedLabel";
2152 let ParserMatchClass = PCRelLabel19Operand;
2155 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2156 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2157 : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2158 asm, "\t$Rt, $label", "", []>,
2162 let Inst{31-30} = opc;
2163 let Inst{29-27} = 0b011;
2165 let Inst{25-24} = 0b00;
2166 let Inst{23-5} = label;
2170 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2171 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2172 : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2173 asm, "\t$Rt, $label", "", pat>,
2177 let Inst{31-30} = opc;
2178 let Inst{29-27} = 0b011;
2180 let Inst{25-24} = 0b00;
2181 let Inst{23-5} = label;
2186 // Load/store register offset
2189 class MemROAsmOperand<int sz> : AsmOperandClass {
2190 let Name = "MemoryRegisterOffset"#sz;
2193 def MemROAsmOperand8 : MemROAsmOperand<8>;
2194 def MemROAsmOperand16 : MemROAsmOperand<16>;
2195 def MemROAsmOperand32 : MemROAsmOperand<32>;
2196 def MemROAsmOperand64 : MemROAsmOperand<64>;
2197 def MemROAsmOperand128 : MemROAsmOperand<128>;
2199 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2200 let PrintMethod = "printMemoryRegOffset<" # sz # ">";
2201 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2204 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2205 let ParserMatchClass = MemROAsmOperand8;
2208 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2209 let ParserMatchClass = MemROAsmOperand16;
2212 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2213 let ParserMatchClass = MemROAsmOperand32;
2216 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2217 let ParserMatchClass = MemROAsmOperand64;
2220 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2221 let ParserMatchClass = MemROAsmOperand128;
2224 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2225 string asm, dag ins, dag outs, list<dag> pat>
2226 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2227 // The operands are in order to match the 'addr' MI operands, so we
2228 // don't need an encoder method and by-name matching. Just use the default
2229 // in-order handling. Since we're using by-order, make sure the names
2235 let Inst{31-30} = sz;
2236 let Inst{29-27} = 0b111;
2238 let Inst{25-24} = 0b00;
2239 let Inst{23-22} = opc;
2241 let Inst{20-16} = offset;
2242 let Inst{15-13} = extend{3-1};
2244 let Inst{12} = extend{0};
2245 let Inst{11-10} = 0b10;
2246 let Inst{9-5} = base;
2247 let Inst{4-0} = dst;
2249 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2252 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2253 string asm, list<dag> pat>
2254 : LoadStore8RO<sz, V, opc, regtype, asm,
2255 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2256 Sched<[WriteLDIdx, ReadAdrBase]>;
2258 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2259 string asm, list<dag> pat>
2260 : LoadStore8RO<sz, V, opc, regtype, asm,
2261 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2262 Sched<[WriteSTIdx, ReadAdrBase]>;
2264 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2265 string asm, dag ins, dag outs, list<dag> pat>
2266 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2267 // The operands are in order to match the 'addr' MI operands, so we
2268 // don't need an encoder method and by-name matching. Just use the default
2269 // in-order handling. Since we're using by-order, make sure the names
2275 let Inst{31-30} = sz;
2276 let Inst{29-27} = 0b111;
2278 let Inst{25-24} = 0b00;
2279 let Inst{23-22} = opc;
2281 let Inst{20-16} = offset;
2282 let Inst{15-13} = extend{3-1};
2284 let Inst{12} = extend{0};
2285 let Inst{11-10} = 0b10;
2286 let Inst{9-5} = base;
2287 let Inst{4-0} = dst;
2289 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2292 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2293 string asm, list<dag> pat>
2294 : LoadStore16RO<sz, V, opc, regtype, asm,
2295 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2296 Sched<[WriteLDIdx, ReadAdrBase]>;
2298 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2299 string asm, list<dag> pat>
2300 : LoadStore16RO<sz, V, opc, regtype, asm,
2301 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2302 Sched<[WriteSTIdx, ReadAdrBase]>;
2304 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2305 string asm, dag ins, dag outs, list<dag> pat>
2306 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2307 // The operands are in order to match the 'addr' MI operands, so we
2308 // don't need an encoder method and by-name matching. Just use the default
2309 // in-order handling. Since we're using by-order, make sure the names
2315 let Inst{31-30} = sz;
2316 let Inst{29-27} = 0b111;
2318 let Inst{25-24} = 0b00;
2319 let Inst{23-22} = opc;
2321 let Inst{20-16} = offset;
2322 let Inst{15-13} = extend{3-1};
2324 let Inst{12} = extend{0};
2325 let Inst{11-10} = 0b10;
2326 let Inst{9-5} = base;
2327 let Inst{4-0} = dst;
2329 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2332 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2333 string asm, list<dag> pat>
2334 : LoadStore32RO<sz, V, opc, regtype, asm,
2335 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2336 Sched<[WriteLDIdx, ReadAdrBase]>;
2338 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2339 string asm, list<dag> pat>
2340 : LoadStore32RO<sz, V, opc, regtype, asm,
2341 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2342 Sched<[WriteSTIdx, ReadAdrBase]>;
2344 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2345 string asm, dag ins, dag outs, list<dag> pat>
2346 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2347 // The operands are in order to match the 'addr' MI operands, so we
2348 // don't need an encoder method and by-name matching. Just use the default
2349 // in-order handling. Since we're using by-order, make sure the names
2355 let Inst{31-30} = sz;
2356 let Inst{29-27} = 0b111;
2358 let Inst{25-24} = 0b00;
2359 let Inst{23-22} = opc;
2361 let Inst{20-16} = offset;
2362 let Inst{15-13} = extend{3-1};
2364 let Inst{12} = extend{0};
2365 let Inst{11-10} = 0b10;
2366 let Inst{9-5} = base;
2367 let Inst{4-0} = dst;
2369 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2372 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2373 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2374 string asm, list<dag> pat>
2375 : LoadStore64RO<sz, V, opc, regtype, asm,
2376 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2377 Sched<[WriteLDIdx, ReadAdrBase]>;
2379 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2380 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2381 string asm, list<dag> pat>
2382 : LoadStore64RO<sz, V, opc, regtype, asm,
2383 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2384 Sched<[WriteSTIdx, ReadAdrBase]>;
2387 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2388 string asm, dag ins, dag outs, list<dag> pat>
2389 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2390 // The operands are in order to match the 'addr' MI operands, so we
2391 // don't need an encoder method and by-name matching. Just use the default
2392 // in-order handling. Since we're using by-order, make sure the names
2398 let Inst{31-30} = sz;
2399 let Inst{29-27} = 0b111;
2401 let Inst{25-24} = 0b00;
2402 let Inst{23-22} = opc;
2404 let Inst{20-16} = offset;
2405 let Inst{15-13} = extend{3-1};
2407 let Inst{12} = extend{0};
2408 let Inst{11-10} = 0b10;
2409 let Inst{9-5} = base;
2410 let Inst{4-0} = dst;
2412 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2415 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2416 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2417 string asm, list<dag> pat>
2418 : LoadStore128RO<sz, V, opc, regtype, asm,
2419 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2420 Sched<[WriteLDIdx, ReadAdrBase]>;
2422 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2423 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2424 string asm, list<dag> pat>
2425 : LoadStore128RO<sz, V, opc, regtype, asm,
2426 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2427 Sched<[WriteSTIdx, ReadAdrBase]>;
2429 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2430 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2431 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2432 "\t$Rt, $addr", "", pat>,
2434 // The operands are in order to match the 'addr' MI operands, so we
2435 // don't need an encoder method and by-name matching. Just use the default
2436 // in-order handling. Since we're using by-order, make sure the names
2442 let Inst{31-30} = sz;
2443 let Inst{29-27} = 0b111;
2445 let Inst{25-24} = 0b00;
2446 let Inst{23-22} = opc;
2448 let Inst{20-16} = offset;
2449 let Inst{15-13} = extend{3-1};
2451 let Inst{12} = extend{0};
2452 let Inst{11-10} = 0b10;
2453 let Inst{9-5} = base;
2454 let Inst{4-0} = dst;
2456 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2460 // Load/store unscaled immediate
2463 def MemoryUnscaledOperand : AsmOperandClass {
2464 let Name = "MemoryUnscaled";
2465 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2467 class am_unscaled_operand : Operand<i64> {
2468 let PrintMethod = "printAMIndexed<8>";
2469 let ParserMatchClass = MemoryUnscaledOperand;
2470 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2472 class am_unscaled_wb_operand : Operand<i64> {
2473 let PrintMethod = "printAMIndexedWB<8>";
2474 let ParserMatchClass = MemoryUnscaledOperand;
2475 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2477 def am_unscaled : am_unscaled_operand;
2478 def am_unscaled_wb: am_unscaled_wb_operand;
2479 def am_unscaled8 : am_unscaled_operand,
2480 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2481 def am_unscaled16 : am_unscaled_operand,
2482 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2483 def am_unscaled32 : am_unscaled_operand,
2484 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2485 def am_unscaled64 : am_unscaled_operand,
2486 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2487 def am_unscaled128 : am_unscaled_operand,
2488 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2490 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2491 string asm, list<dag> pattern>
2492 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2493 // The operands are in order to match the 'addr' MI operands, so we
2494 // don't need an encoder method and by-name matching. Just use the default
2495 // in-order handling. Since we're using by-order, make sure the names
2500 let Inst{31-30} = sz;
2501 let Inst{29-27} = 0b111;
2503 let Inst{25-24} = 0b00;
2504 let Inst{23-22} = opc;
2506 let Inst{20-12} = offset;
2507 let Inst{11-10} = 0b00;
2508 let Inst{9-5} = base;
2509 let Inst{4-0} = dst;
2511 let DecoderMethod = "DecodeSignedLdStInstruction";
2514 let AddedComplexity = 1 in // try this before LoadUI
2515 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2516 Operand amtype, string asm, list<dag> pattern>
2517 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2518 (ins amtype:$addr), asm, pattern>,
2521 let AddedComplexity = 1 in // try this before StoreUI
2522 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2523 Operand amtype, string asm, list<dag> pattern>
2524 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2525 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2528 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2529 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2530 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2531 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2535 // Load/store unscaled immediate, unprivileged
2538 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2539 dag oops, dag iops, string asm>
2540 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2541 // The operands are in order to match the 'addr' MI operands, so we
2542 // don't need an encoder method and by-name matching. Just use the default
2543 // in-order handling. Since we're using by-order, make sure the names
2548 let Inst{31-30} = sz;
2549 let Inst{29-27} = 0b111;
2551 let Inst{25-24} = 0b00;
2552 let Inst{23-22} = opc;
2554 let Inst{20-12} = offset;
2555 let Inst{11-10} = 0b10;
2556 let Inst{9-5} = base;
2557 let Inst{4-0} = dst;
2559 let DecoderMethod = "DecodeSignedLdStInstruction";
2562 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2563 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2565 : BaseLoadStoreUnprivileged<sz, V, opc,
2566 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2570 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2571 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2573 : BaseLoadStoreUnprivileged<sz, V, opc,
2574 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2579 // Load/store pre-indexed
2582 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2583 string asm, string cstr>
2584 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2585 // The operands are in order to match the 'addr' MI operands, so we
2586 // don't need an encoder method and by-name matching. Just use the default
2587 // in-order handling.
2591 let Inst{31-30} = sz;
2592 let Inst{29-27} = 0b111;
2594 let Inst{25-24} = 0;
2595 let Inst{23-22} = opc;
2597 let Inst{20-12} = offset;
2598 let Inst{11-10} = 0b11;
2599 let Inst{9-5} = base;
2600 let Inst{4-0} = dst;
2602 let DecoderMethod = "DecodeSignedLdStInstruction";
2605 let hasSideEffects = 0 in {
2606 let mayStore = 0, mayLoad = 1 in
2607 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2608 // we need the complex addressing mode for the memory reference, but
2609 // we also need the write-back specified as a tied operand to the
2610 // base register. That combination does not play nicely with
2611 // the asm matcher and friends.
2612 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2614 : BaseLoadStorePreIdx<sz, V, opc,
2615 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2616 (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
2617 Sched<[WriteLD, WriteAdr]>;
2619 let mayStore = 1, mayLoad = 0 in
2620 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2622 : BaseLoadStorePreIdx<sz, V, opc,
2623 (outs/* GPR64sp:$wback*/),
2624 (ins regtype:$Rt, am_unscaled_wb:$addr),
2625 asm, ""/*"$addr.base = $wback"*/>,
2626 Sched<[WriteAdr, WriteST]>;
2627 } // hasSideEffects = 0
2629 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2630 // logic finally gets smart enough to strip off tied operands that are just
2631 // for isel convenience, we can get rid of these pseudos and just reference
2632 // the real instructions directly.
2634 // Ironically, also because of the writeback operands, we can't put the
2635 // matcher pattern directly on the instruction, but need to define it
2638 // Loads aren't matched with patterns here at all, but rather in C++
2640 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2641 class LoadPreIdxPseudo<RegisterClass regtype>
2642 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2643 (ins am_noindex:$addr, simm9:$offset), [],
2644 "$addr.base = $wback,@earlyclobber $wback">,
2645 Sched<[WriteLD, WriteAdr]>;
2646 class LoadPostIdxPseudo<RegisterClass regtype>
2647 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2648 (ins am_noindex:$addr, simm9:$offset), [],
2649 "$addr.base = $wback,@earlyclobber $wback">,
2650 Sched<[WriteLD, WriteI]>;
2652 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2653 SDPatternOperator OpNode> {
2654 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2655 def _isel: Pseudo<(outs GPR64sp:$wback),
2656 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2657 "$addr.base = $wback,@earlyclobber $wback">,
2658 Sched<[WriteAdr, WriteST]>;
2660 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2661 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2666 // Load/store post-indexed
2669 // (pre-index) load/stores.
2670 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2671 string asm, string cstr>
2672 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2673 // The operands are in order to match the 'addr' MI operands, so we
2674 // don't need an encoder method and by-name matching. Just use the default
2675 // in-order handling.
2679 let Inst{31-30} = sz;
2680 let Inst{29-27} = 0b111;
2682 let Inst{25-24} = 0b00;
2683 let Inst{23-22} = opc;
2685 let Inst{20-12} = offset;
2686 let Inst{11-10} = 0b01;
2687 let Inst{9-5} = base;
2688 let Inst{4-0} = dst;
2690 let DecoderMethod = "DecodeSignedLdStInstruction";
2693 let hasSideEffects = 0 in {
2694 let mayStore = 0, mayLoad = 1 in
2695 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2696 // we need the complex addressing mode for the memory reference, but
2697 // we also need the write-back specified as a tied operand to the
2698 // base register. That combination does not play nicely with
2699 // the asm matcher and friends.
2700 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2702 : BaseLoadStorePostIdx<sz, V, opc,
2703 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2704 (ins am_noindex:$addr, simm9:$idx),
2705 asm, ""/*"$addr.base = $wback"*/>,
2706 Sched<[WriteLD, WriteI]>;
2708 let mayStore = 1, mayLoad = 0 in
2709 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2711 : BaseLoadStorePostIdx<sz, V, opc,
2712 (outs/* GPR64sp:$wback*/),
2713 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2714 asm, ""/*"$addr.base = $wback"*/>,
2715 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2716 } // hasSideEffects = 0
2718 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2719 // logic finally gets smart enough to strip off tied operands that are just
2720 // for isel convenience, we can get rid of these pseudos and just reference
2721 // the real instructions directly.
2723 // Ironically, also because of the writeback operands, we can't put the
2724 // matcher pattern directly on the instruction, but need to define it
2726 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2727 SDPatternOperator OpNode, Instruction Insn> {
2728 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2729 def _isel: Pseudo<(outs GPR64sp:$wback),
2730 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2731 "$addr.base = $wback,@earlyclobber $wback">,
2732 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2733 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2735 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2736 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2744 // (indexed, offset)
2746 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2748 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2749 // The operands are in order to match the 'addr' MI operands, so we
2750 // don't need an encoder method and by-name matching. Just use the default
2751 // in-order handling. Since we're using by-order, make sure the names
2757 let Inst{31-30} = opc;
2758 let Inst{29-27} = 0b101;
2760 let Inst{25-23} = 0b010;
2762 let Inst{21-15} = offset;
2763 let Inst{14-10} = dst2;
2764 let Inst{9-5} = base;
2765 let Inst{4-0} = dst;
2767 let DecoderMethod = "DecodePairLdStInstruction";
2770 let hasSideEffects = 0 in {
2771 let mayStore = 0, mayLoad = 1 in
2772 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2773 Operand indextype, string asm>
2774 : BaseLoadStorePairOffset<opc, V, 1,
2775 (outs regtype:$Rt, regtype:$Rt2),
2776 (ins indextype:$addr), asm>,
2777 Sched<[WriteLD, WriteLDHi]>;
2779 let mayLoad = 0, mayStore = 1 in
2780 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2781 Operand indextype, string asm>
2782 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2783 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2786 } // hasSideEffects = 0
2790 def MemoryIndexed32SImm7 : AsmOperandClass {
2791 let Name = "MemoryIndexed32SImm7";
2792 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2794 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2795 let PrintMethod = "printAMIndexed<32>";
2796 let ParserMatchClass = MemoryIndexed32SImm7;
2797 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2799 def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2800 let PrintMethod = "printAMIndexedWB<32>";
2801 let ParserMatchClass = MemoryIndexed32SImm7;
2802 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2805 def MemoryIndexed64SImm7 : AsmOperandClass {
2806 let Name = "MemoryIndexed64SImm7";
2807 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2809 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2810 let PrintMethod = "printAMIndexed<64>";
2811 let ParserMatchClass = MemoryIndexed64SImm7;
2812 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2814 def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2815 let PrintMethod = "printAMIndexedWB<64>";
2816 let ParserMatchClass = MemoryIndexed64SImm7;
2817 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2820 def MemoryIndexed128SImm7 : AsmOperandClass {
2821 let Name = "MemoryIndexed128SImm7";
2822 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2824 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2825 let PrintMethod = "printAMIndexed<128>";
2826 let ParserMatchClass = MemoryIndexed128SImm7;
2827 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2829 def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2830 let PrintMethod = "printAMIndexedWB<128>";
2831 let ParserMatchClass = MemoryIndexed128SImm7;
2832 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2835 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2837 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2838 // The operands are in order to match the 'addr' MI operands, so we
2839 // don't need an encoder method and by-name matching. Just use the default
2840 // in-order handling. Since we're using by-order, make sure the names
2846 let Inst{31-30} = opc;
2847 let Inst{29-27} = 0b101;
2849 let Inst{25-23} = 0b011;
2851 let Inst{21-15} = offset;
2852 let Inst{14-10} = dst2;
2853 let Inst{9-5} = base;
2854 let Inst{4-0} = dst;
2856 let DecoderMethod = "DecodePairLdStInstruction";
2859 let hasSideEffects = 0 in {
2860 let mayStore = 0, mayLoad = 1 in
2861 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2862 Operand addrmode, string asm>
2863 : BaseLoadStorePairPreIdx<opc, V, 1,
2864 (outs regtype:$Rt, regtype:$Rt2),
2865 (ins addrmode:$addr), asm>,
2866 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2868 let mayStore = 1, mayLoad = 0 in
2869 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2870 Operand addrmode, string asm>
2871 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2872 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2874 Sched<[WriteAdr, WriteSTP]>;
2875 } // hasSideEffects = 0
2879 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2881 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2882 // The operands are in order to match the 'addr' MI operands, so we
2883 // don't need an encoder method and by-name matching. Just use the default
2884 // in-order handling. Since we're using by-order, make sure the names
2890 let Inst{31-30} = opc;
2891 let Inst{29-27} = 0b101;
2893 let Inst{25-23} = 0b001;
2895 let Inst{21-15} = offset;
2896 let Inst{14-10} = dst2;
2897 let Inst{9-5} = base;
2898 let Inst{4-0} = dst;
2900 let DecoderMethod = "DecodePairLdStInstruction";
2903 let hasSideEffects = 0 in {
2904 let mayStore = 0, mayLoad = 1 in
2905 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2906 Operand idxtype, string asm>
2907 : BaseLoadStorePairPostIdx<opc, V, 1,
2908 (outs regtype:$Rt, regtype:$Rt2),
2909 (ins am_noindex:$addr, idxtype:$idx), asm>,
2910 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2912 let mayStore = 1, mayLoad = 0 in
2913 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2914 Operand idxtype, string asm>
2915 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2916 (ins regtype:$Rt, regtype:$Rt2,
2917 am_noindex:$addr, idxtype:$idx),
2919 Sched<[WriteAdr, WriteSTP]>;
2920 } // hasSideEffects = 0
2924 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2926 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2927 // The operands are in order to match the 'addr' MI operands, so we
2928 // don't need an encoder method and by-name matching. Just use the default
2929 // in-order handling. Since we're using by-order, make sure the names
2935 let Inst{31-30} = opc;
2936 let Inst{29-27} = 0b101;
2938 let Inst{25-23} = 0b000;
2940 let Inst{21-15} = offset;
2941 let Inst{14-10} = dst2;
2942 let Inst{9-5} = base;
2943 let Inst{4-0} = dst;
2945 let DecoderMethod = "DecodePairLdStInstruction";
2948 let hasSideEffects = 0 in {
2949 let mayStore = 0, mayLoad = 1 in
2950 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2951 Operand indextype, string asm>
2952 : BaseLoadStorePairNoAlloc<opc, V, 1,
2953 (outs regtype:$Rt, regtype:$Rt2),
2954 (ins indextype:$addr), asm>,
2955 Sched<[WriteLD, WriteLDHi]>;
2957 let mayStore = 1, mayLoad = 0 in
2958 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2959 Operand indextype, string asm>
2960 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2961 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2964 } // hasSideEffects = 0
2967 // Load/store exclusive
2970 // True exclusive operations write to and/or read from the system's exclusive
2971 // monitors, which as far as a compiler is concerned can be modelled as a
2972 // random shared memory address. Hence LoadExclusive mayStore.
2974 // Since these instructions have the undefined register bits set to 1 in
2975 // their canonical form, we need a post encoder method to set those bits
2976 // to 1 when encoding these instructions. We do this using the
2977 // fixLoadStoreExclusive function. This function has template parameters:
2979 // fixLoadStoreExclusive<int hasRs, int hasRt2>
2981 // hasRs indicates that the instruction uses the Rs field, so we won't set
2982 // it to 1 (and the same for Rt2). We don't need template parameters for
2983 // the other register fields since Rt and Rn are always used.
2985 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2986 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2987 dag oops, dag iops, string asm, string operands>
2988 : I<oops, iops, asm, operands, "", []> {
2989 let Inst{31-30} = sz;
2990 let Inst{29-24} = 0b001000;
2996 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2999 // Neither Rs nor Rt2 operands.
3000 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3001 dag oops, dag iops, string asm, string operands>
3002 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3005 let Inst{9-5} = base;
3006 let Inst{4-0} = reg;
3008 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3011 // Simple load acquires don't set the exclusive monitor
3012 let mayLoad = 1, mayStore = 0 in
3013 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3014 RegisterClass regtype, string asm>
3015 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3016 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3019 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3020 RegisterClass regtype, string asm>
3021 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3022 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3025 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3026 RegisterClass regtype, string asm>
3027 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3028 (outs regtype:$Rt, regtype:$Rt2),
3029 (ins am_noindex:$addr), asm,
3030 "\t$Rt, $Rt2, $addr">,
3031 Sched<[WriteLD, WriteLDHi]> {
3035 let Inst{14-10} = dst2;
3036 let Inst{9-5} = base;
3037 let Inst{4-0} = dst1;
3039 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3042 // Simple store release operations do not check the exclusive monitor.
3043 let mayLoad = 0, mayStore = 1 in
3044 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3045 RegisterClass regtype, string asm>
3046 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3047 (ins regtype:$Rt, am_noindex:$addr),
3048 asm, "\t$Rt, $addr">,
3051 let mayLoad = 1, mayStore = 1 in
3052 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3053 RegisterClass regtype, string asm>
3054 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3055 (ins regtype:$Rt, am_noindex:$addr),
3056 asm, "\t$Ws, $Rt, $addr">,
3061 let Inst{20-16} = status;
3062 let Inst{9-5} = base;
3063 let Inst{4-0} = reg;
3065 let Constraints = "@earlyclobber $Ws";
3066 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3069 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3070 RegisterClass regtype, string asm>
3071 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3073 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3074 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3080 let Inst{20-16} = status;
3081 let Inst{14-10} = dst2;
3082 let Inst{9-5} = base;
3083 let Inst{4-0} = dst1;
3085 let Constraints = "@earlyclobber $Ws";
3089 // Exception generation
3092 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3093 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3094 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3097 let Inst{31-24} = 0b11010100;
3098 let Inst{23-21} = op1;
3099 let Inst{20-5} = imm;
3100 let Inst{4-2} = 0b000;
3104 let Predicates = [HasFPARMv8] in {
3107 // Floating point to integer conversion
3110 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3111 RegisterClass srcType, RegisterClass dstType,
3112 string asm, list<dag> pattern>
3113 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3114 asm, "\t$Rd, $Rn", "", pattern>,
3115 Sched<[WriteFCvt]> {
3118 let Inst{30-29} = 0b00;
3119 let Inst{28-24} = 0b11110;
3120 let Inst{23-22} = type;
3122 let Inst{20-19} = rmode;
3123 let Inst{18-16} = opcode;
3124 let Inst{15-10} = 0;
3129 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3130 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3131 RegisterClass srcType, RegisterClass dstType,
3132 Operand immType, string asm, list<dag> pattern>
3133 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3134 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3135 Sched<[WriteFCvt]> {
3139 let Inst{30-29} = 0b00;
3140 let Inst{28-24} = 0b11110;
3141 let Inst{23-22} = type;
3143 let Inst{20-19} = rmode;
3144 let Inst{18-16} = opcode;
3145 let Inst{15-10} = scale;
3150 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3151 SDPatternOperator OpN> {
3152 // Unscaled single-precision to 32-bit
3153 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3154 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3155 let Inst{31} = 0; // 32-bit GPR flag
3158 // Unscaled single-precision to 64-bit
3159 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3160 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3161 let Inst{31} = 1; // 64-bit GPR flag
3164 // Unscaled double-precision to 32-bit
3165 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3166 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3167 let Inst{31} = 0; // 32-bit GPR flag
3170 // Unscaled double-precision to 64-bit
3171 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3172 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3173 let Inst{31} = 1; // 64-bit GPR flag
3177 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3178 SDPatternOperator OpN> {
3179 // Scaled single-precision to 32-bit
3180 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3181 fixedpoint_f32_i32, asm,
3182 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3183 fixedpoint_f32_i32:$scale)))]> {
3184 let Inst{31} = 0; // 32-bit GPR flag
3188 // Scaled single-precision to 64-bit
3189 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3190 fixedpoint_f32_i64, asm,
3191 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3192 fixedpoint_f32_i64:$scale)))]> {
3193 let Inst{31} = 1; // 64-bit GPR flag
3196 // Scaled double-precision to 32-bit
3197 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3198 fixedpoint_f64_i32, asm,
3199 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3200 fixedpoint_f64_i32:$scale)))]> {
3201 let Inst{31} = 0; // 32-bit GPR flag
3205 // Scaled double-precision to 64-bit
3206 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3207 fixedpoint_f64_i64, asm,
3208 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3209 fixedpoint_f64_i64:$scale)))]> {
3210 let Inst{31} = 1; // 64-bit GPR flag
3215 // Integer to floating point conversion
3218 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3219 class BaseIntegerToFP<bit isUnsigned,
3220 RegisterClass srcType, RegisterClass dstType,
3221 Operand immType, string asm, list<dag> pattern>
3222 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3223 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3224 Sched<[WriteFCvt]> {
3228 let Inst{30-23} = 0b00111100;
3229 let Inst{21-17} = 0b00001;
3230 let Inst{16} = isUnsigned;
3231 let Inst{15-10} = scale;
3236 class BaseIntegerToFPUnscaled<bit isUnsigned,
3237 RegisterClass srcType, RegisterClass dstType,
3238 ValueType dvt, string asm, SDNode node>
3239 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3240 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3241 Sched<[WriteFCvt]> {
3245 let Inst{30-23} = 0b00111100;
3246 let Inst{21-17} = 0b10001;
3247 let Inst{16} = isUnsigned;
3248 let Inst{15-10} = 0b000000;
3253 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3255 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3256 let Inst{31} = 0; // 32-bit GPR flag
3257 let Inst{22} = 0; // 32-bit FPR flag
3260 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3261 let Inst{31} = 0; // 32-bit GPR flag
3262 let Inst{22} = 1; // 64-bit FPR flag
3265 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3266 let Inst{31} = 1; // 64-bit GPR flag
3267 let Inst{22} = 0; // 32-bit FPR flag
3270 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3271 let Inst{31} = 1; // 64-bit GPR flag
3272 let Inst{22} = 1; // 64-bit FPR flag
3276 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3278 (fdiv (node GPR32:$Rn),
3279 fixedpoint_f32_i32:$scale))]> {
3280 let Inst{31} = 0; // 32-bit GPR flag
3281 let Inst{22} = 0; // 32-bit FPR flag
3285 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3287 (fdiv (node GPR32:$Rn),
3288 fixedpoint_f64_i32:$scale))]> {
3289 let Inst{31} = 0; // 32-bit GPR flag
3290 let Inst{22} = 1; // 64-bit FPR flag
3294 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3296 (fdiv (node GPR64:$Rn),
3297 fixedpoint_f32_i64:$scale))]> {
3298 let Inst{31} = 1; // 64-bit GPR flag
3299 let Inst{22} = 0; // 32-bit FPR flag
3302 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3304 (fdiv (node GPR64:$Rn),
3305 fixedpoint_f64_i64:$scale))]> {
3306 let Inst{31} = 1; // 64-bit GPR flag
3307 let Inst{22} = 1; // 64-bit FPR flag
3312 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3315 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3316 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3317 RegisterClass srcType, RegisterClass dstType,
3319 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3320 // We use COPY_TO_REGCLASS for these bitconvert operations.
3321 // copyPhysReg() expands the resultant COPY instructions after
3322 // regalloc is done. This gives greater freedom for the allocator
3323 // and related passes (coalescing, copy propagation, et. al.) to
3324 // be more effective.
3325 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3326 Sched<[WriteFCopy]> {
3329 let Inst{30-23} = 0b00111100;
3331 let Inst{20-19} = rmode;
3332 let Inst{18-16} = opcode;
3333 let Inst{15-10} = 0b000000;
3338 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3339 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3340 RegisterClass srcType, RegisterOperand dstType, string asm,
3342 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3343 "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
3344 Sched<[WriteFCopy]> {
3347 let Inst{30-23} = 0b00111101;
3349 let Inst{20-19} = rmode;
3350 let Inst{18-16} = opcode;
3351 let Inst{15-10} = 0b000000;
3356 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3357 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3358 RegisterOperand srcType, RegisterClass dstType, string asm,
3360 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3361 "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
3362 Sched<[WriteFCopy]> {
3365 let Inst{30-23} = 0b00111101;
3367 let Inst{20-19} = rmode;
3368 let Inst{18-16} = opcode;
3369 let Inst{15-10} = 0b000000;
3376 multiclass UnscaledConversion<string asm> {
3377 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3378 let Inst{31} = 0; // 32-bit GPR flag
3379 let Inst{22} = 0; // 32-bit FPR flag
3382 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3383 let Inst{31} = 1; // 64-bit GPR flag
3384 let Inst{22} = 1; // 64-bit FPR flag
3387 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3388 let Inst{31} = 0; // 32-bit GPR flag
3389 let Inst{22} = 0; // 32-bit FPR flag
3392 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3393 let Inst{31} = 1; // 64-bit GPR flag
3394 let Inst{22} = 1; // 64-bit FPR flag
3397 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3403 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3411 // Floating point conversion
3414 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3415 RegisterClass srcType, string asm, list<dag> pattern>
3416 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3417 Sched<[WriteFCvt]> {
3420 let Inst{31-24} = 0b00011110;
3421 let Inst{23-22} = type;
3422 let Inst{21-17} = 0b10001;
3423 let Inst{16-15} = opcode;
3424 let Inst{14-10} = 0b10000;
3429 multiclass FPConversion<string asm> {
3430 // Double-precision to Half-precision
3431 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3432 [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3434 // Double-precision to Single-precision
3435 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3436 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3438 // Half-precision to Double-precision
3439 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3440 [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3442 // Half-precision to Single-precision
3443 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3444 [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3446 // Single-precision to Double-precision
3447 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3448 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3450 // Single-precision to Half-precision
3451 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3452 [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3456 // Single operand floating point data processing
3459 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3460 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3461 ValueType vt, string asm, SDPatternOperator node>
3462 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3463 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3467 let Inst{31-23} = 0b000111100;
3468 let Inst{21-19} = 0b100;
3469 let Inst{18-15} = opcode;
3470 let Inst{14-10} = 0b10000;
3475 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3476 SDPatternOperator node = null_frag> {
3477 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3478 let Inst{22} = 0; // 32-bit size flag
3481 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3482 let Inst{22} = 1; // 64-bit size flag
3487 // Two operand floating point data processing
3490 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3491 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3492 string asm, list<dag> pat>
3493 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3494 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3499 let Inst{31-23} = 0b000111100;
3501 let Inst{20-16} = Rm;
3502 let Inst{15-12} = opcode;
3503 let Inst{11-10} = 0b10;
3508 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3509 SDPatternOperator node = null_frag> {
3510 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3511 [(set (f32 FPR32:$Rd),
3512 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3513 let Inst{22} = 0; // 32-bit size flag
3516 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3517 [(set (f64 FPR64:$Rd),
3518 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3519 let Inst{22} = 1; // 64-bit size flag
3523 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3524 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3525 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3526 let Inst{22} = 0; // 32-bit size flag
3529 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3530 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3531 let Inst{22} = 1; // 64-bit size flag
3537 // Three operand floating point data processing
3540 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3541 RegisterClass regtype, string asm, list<dag> pat>
3542 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3543 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3544 Sched<[WriteFMul]> {
3549 let Inst{31-23} = 0b000111110;
3550 let Inst{21} = isNegated;
3551 let Inst{20-16} = Rm;
3552 let Inst{15} = isSub;
3553 let Inst{14-10} = Ra;
3558 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3559 SDPatternOperator node> {
3560 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3562 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3563 let Inst{22} = 0; // 32-bit size flag
3566 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3568 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3569 let Inst{22} = 1; // 64-bit size flag
3574 // Floating point data comparisons
3577 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3578 class BaseOneOperandFPComparison<bit signalAllNans,
3579 RegisterClass regtype, string asm,
3581 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3582 Sched<[WriteFCmp]> {
3584 let Inst{31-23} = 0b000111100;
3587 let Inst{15-10} = 0b001000;
3589 let Inst{4} = signalAllNans;
3590 let Inst{3-0} = 0b1000;
3592 // Rm should be 0b00000 canonically, but we need to accept any value.
3593 let PostEncoderMethod = "fixOneOperandFPComparison";
3596 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3597 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3598 string asm, list<dag> pat>
3599 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3600 Sched<[WriteFCmp]> {
3603 let Inst{31-23} = 0b000111100;
3605 let Inst{20-16} = Rm;
3606 let Inst{15-10} = 0b001000;
3608 let Inst{4} = signalAllNans;
3609 let Inst{3-0} = 0b0000;
3612 multiclass FPComparison<bit signalAllNans, string asm,
3613 SDPatternOperator OpNode = null_frag> {
3614 let Defs = [NZCV] in {
3615 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3616 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3620 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3621 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3625 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3626 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3630 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3631 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3638 // Floating point conditional comparisons
3641 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3642 class BaseFPCondComparison<bit signalAllNans,
3643 RegisterClass regtype, string asm>
3644 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3645 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3646 Sched<[WriteFCmp]> {
3652 let Inst{31-23} = 0b000111100;
3654 let Inst{20-16} = Rm;
3655 let Inst{15-12} = cond;
3656 let Inst{11-10} = 0b01;
3658 let Inst{4} = signalAllNans;
3659 let Inst{3-0} = nzcv;
3662 multiclass FPCondComparison<bit signalAllNans, string asm> {
3663 let Defs = [NZCV], Uses = [NZCV] in {
3664 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3668 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3671 } // Defs = [NZCV], Uses = [NZCV]
3675 // Floating point conditional select
3678 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3679 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3680 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3682 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3683 (i32 imm:$cond), NZCV))]>,
3690 let Inst{31-23} = 0b000111100;
3692 let Inst{20-16} = Rm;
3693 let Inst{15-12} = cond;
3694 let Inst{11-10} = 0b11;
3699 multiclass FPCondSelect<string asm> {
3700 let Uses = [NZCV] in {
3701 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3705 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3712 // Floating move immediate
3715 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3716 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3717 [(set regtype:$Rd, fpimmtype:$imm)]>,
3718 Sched<[WriteFImm]> {
3721 let Inst{31-23} = 0b000111100;
3723 let Inst{20-13} = imm;
3724 let Inst{12-5} = 0b10000000;
3728 multiclass FPMoveImmediate<string asm> {
3729 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3733 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3737 } // end of 'let Predicates = [HasFPARMv8]'
3739 //----------------------------------------------------------------------------
3741 //----------------------------------------------------------------------------
3743 class AsmVectorIndex<string Suffix> : AsmOperandClass {
3744 let Name = "VectorIndex" # Suffix;
3745 let DiagnosticType = "InvalidIndex" # Suffix;
3747 def VectorIndexBOperand : AsmVectorIndex<"B">;
3748 def VectorIndexHOperand : AsmVectorIndex<"H">;
3749 def VectorIndexSOperand : AsmVectorIndex<"S">;
3750 def VectorIndexDOperand : AsmVectorIndex<"D">;
3752 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3753 return ((uint64_t)Imm) < 16;
3755 let ParserMatchClass = VectorIndexBOperand;
3756 let PrintMethod = "printVectorIndex";
3757 let MIOperandInfo = (ops i64imm);
3759 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3760 return ((uint64_t)Imm) < 8;
3762 let ParserMatchClass = VectorIndexHOperand;
3763 let PrintMethod = "printVectorIndex";
3764 let MIOperandInfo = (ops i64imm);
3766 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3767 return ((uint64_t)Imm) < 4;
3769 let ParserMatchClass = VectorIndexSOperand;
3770 let PrintMethod = "printVectorIndex";
3771 let MIOperandInfo = (ops i64imm);
3773 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3774 return ((uint64_t)Imm) < 2;
3776 let ParserMatchClass = VectorIndexDOperand;
3777 let PrintMethod = "printVectorIndex";
3778 let MIOperandInfo = (ops i64imm);
3781 def MemorySIMDNoIndexOperand : AsmOperandClass {
3782 let Name = "MemorySIMDNoIndex";
3783 let ParserMethod = "tryParseNoIndexMemory";
3785 def am_simdnoindex : Operand<i64>,
3786 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
3787 let PrintMethod = "printAMNoIndex";
3788 let ParserMatchClass = MemorySIMDNoIndexOperand;
3789 let MIOperandInfo = (ops GPR64sp:$base);
3790 let DecoderMethod = "DecodeGPR64spRegisterClass";
3793 let Predicates = [HasNEON] in {
3795 //----------------------------------------------------------------------------
3796 // AdvSIMD three register vector instructions
3797 //----------------------------------------------------------------------------
3799 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3800 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3801 RegisterOperand regtype, string asm, string kind,
3803 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3804 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3805 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3813 let Inst{28-24} = 0b01110;
3814 let Inst{23-22} = size;
3816 let Inst{20-16} = Rm;
3817 let Inst{15-11} = opcode;
3823 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3824 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3825 RegisterOperand regtype, string asm, string kind,
3827 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3828 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3829 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3837 let Inst{28-24} = 0b01110;
3838 let Inst{23-22} = size;
3840 let Inst{20-16} = Rm;
3841 let Inst{15-11} = opcode;
3847 // All operand sizes distinguished in the encoding.
3848 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3849 SDPatternOperator OpNode> {
3850 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3852 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3853 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3855 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3856 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3858 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3859 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3861 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3862 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3864 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3865 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3867 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3868 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3870 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3873 // As above, but D sized elements unsupported.
3874 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3875 SDPatternOperator OpNode> {
3876 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3878 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3879 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3881 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3882 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3884 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3885 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3887 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3888 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3890 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3891 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3893 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3896 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3897 SDPatternOperator OpNode> {
3898 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3900 [(set (v8i8 V64:$dst),
3901 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3902 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3904 [(set (v16i8 V128:$dst),
3905 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3906 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3908 [(set (v4i16 V64:$dst),
3909 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3910 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3912 [(set (v8i16 V128:$dst),
3913 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3914 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3916 [(set (v2i32 V64:$dst),
3917 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3918 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3920 [(set (v4i32 V128:$dst),
3921 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3924 // As above, but only B sized elements supported.
3925 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3926 SDPatternOperator OpNode> {
3927 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3929 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3930 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3932 [(set (v16i8 V128:$Rd),
3933 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3936 // As above, but only S and D sized floating point elements supported.
3937 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3938 string asm, SDPatternOperator OpNode> {
3939 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3941 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3942 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3944 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3945 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3947 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3950 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3952 SDPatternOperator OpNode> {
3953 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3955 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3956 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3958 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3959 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3961 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3964 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3965 string asm, SDPatternOperator OpNode> {
3966 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3968 [(set (v2f32 V64:$dst),
3969 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3970 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3972 [(set (v4f32 V128:$dst),
3973 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3974 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3976 [(set (v2f64 V128:$dst),
3977 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3980 // As above, but D and B sized elements unsupported.
3981 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3982 SDPatternOperator OpNode> {
3983 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3985 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3986 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3988 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3989 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3991 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3992 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3994 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3997 // Logical three vector ops share opcode bits, and only use B sized elements.
3998 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3999 SDPatternOperator OpNode = null_frag> {
4000 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4002 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4003 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4005 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4007 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4008 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4009 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4010 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4011 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4012 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4014 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4015 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4016 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4017 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4018 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4019 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4022 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4023 string asm, SDPatternOperator OpNode> {
4024 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4026 [(set (v8i8 V64:$dst),
4027 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4028 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4030 [(set (v16i8 V128:$dst),
4031 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4032 (v16i8 V128:$Rm)))]>;
4034 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4036 (!cast<Instruction>(NAME#"v8i8")
4037 V64:$LHS, V64:$MHS, V64:$RHS)>;
4038 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4040 (!cast<Instruction>(NAME#"v8i8")
4041 V64:$LHS, V64:$MHS, V64:$RHS)>;
4042 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4044 (!cast<Instruction>(NAME#"v8i8")
4045 V64:$LHS, V64:$MHS, V64:$RHS)>;
4047 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4048 (v8i16 V128:$RHS))),
4049 (!cast<Instruction>(NAME#"v16i8")
4050 V128:$LHS, V128:$MHS, V128:$RHS)>;
4051 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4052 (v4i32 V128:$RHS))),
4053 (!cast<Instruction>(NAME#"v16i8")
4054 V128:$LHS, V128:$MHS, V128:$RHS)>;
4055 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4056 (v2i64 V128:$RHS))),
4057 (!cast<Instruction>(NAME#"v16i8")
4058 V128:$LHS, V128:$MHS, V128:$RHS)>;
4062 //----------------------------------------------------------------------------
4063 // AdvSIMD two register vector instructions.
4064 //----------------------------------------------------------------------------
4066 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4067 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4068 RegisterOperand regtype, string asm, string dstkind,
4069 string srckind, list<dag> pattern>
4070 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4071 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4072 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4079 let Inst{28-24} = 0b01110;
4080 let Inst{23-22} = size;
4081 let Inst{21-17} = 0b10000;
4082 let Inst{16-12} = opcode;
4083 let Inst{11-10} = 0b10;
4088 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4089 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4090 RegisterOperand regtype, string asm, string dstkind,
4091 string srckind, list<dag> pattern>
4092 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4093 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4094 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4101 let Inst{28-24} = 0b01110;
4102 let Inst{23-22} = size;
4103 let Inst{21-17} = 0b10000;
4104 let Inst{16-12} = opcode;
4105 let Inst{11-10} = 0b10;
4110 // Supports B, H, and S element sizes.
4111 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4112 SDPatternOperator OpNode> {
4113 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4115 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4116 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4117 asm, ".16b", ".16b",
4118 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4119 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4121 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4122 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4124 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4125 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4127 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4128 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4130 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4133 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4134 RegisterOperand regtype, string asm, string dstkind,
4135 string srckind, string amount>
4136 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4137 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4138 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4144 let Inst{29-24} = 0b101110;
4145 let Inst{23-22} = size;
4146 let Inst{21-10} = 0b100001001110;
4151 multiclass SIMDVectorLShiftLongBySizeBHS {
4152 let neverHasSideEffects = 1 in {
4153 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4154 "shll", ".8h", ".8b", "8">;
4155 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4156 "shll2", ".8h", ".16b", "8">;
4157 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4158 "shll", ".4s", ".4h", "16">;
4159 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4160 "shll2", ".4s", ".8h", "16">;
4161 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4162 "shll", ".2d", ".2s", "32">;
4163 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4164 "shll2", ".2d", ".4s", "32">;
4168 // Supports all element sizes.
4169 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4170 SDPatternOperator OpNode> {
4171 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4173 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4174 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4176 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4177 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4179 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4180 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4182 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4183 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4185 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4186 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4188 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4191 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4192 SDPatternOperator OpNode> {
4193 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4195 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4197 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4199 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4200 (v16i8 V128:$Rn)))]>;
4201 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4203 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4204 (v4i16 V64:$Rn)))]>;
4205 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4207 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4208 (v8i16 V128:$Rn)))]>;
4209 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4211 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4212 (v2i32 V64:$Rn)))]>;
4213 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4215 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4216 (v4i32 V128:$Rn)))]>;
4219 // Supports all element sizes, except 1xD.
4220 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4221 SDPatternOperator OpNode> {
4222 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4224 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4225 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4226 asm, ".16b", ".16b",
4227 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4228 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4230 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4231 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4233 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4234 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4236 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4237 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4239 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4240 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4242 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4245 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4246 SDPatternOperator OpNode = null_frag> {
4247 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4249 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4250 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4251 asm, ".16b", ".16b",
4252 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4253 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4255 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4256 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4258 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4259 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4261 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4262 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4264 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4265 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4267 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4271 // Supports only B element sizes.
4272 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4273 SDPatternOperator OpNode> {
4274 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4276 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4277 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4278 asm, ".16b", ".16b",
4279 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4283 // Supports only B and H element sizes.
4284 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4285 SDPatternOperator OpNode> {
4286 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4288 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4289 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4290 asm, ".16b", ".16b",
4291 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4292 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4294 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4295 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4297 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4300 // Supports only S and D element sizes, uses high bit of the size field
4301 // as an extra opcode bit.
4302 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4303 SDPatternOperator OpNode> {
4304 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4306 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4307 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4309 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4310 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4312 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4315 // Supports only S element size.
4316 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4317 SDPatternOperator OpNode> {
4318 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4320 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4321 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4323 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4327 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4328 SDPatternOperator OpNode> {
4329 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4331 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4332 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4334 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4335 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4337 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4340 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4341 SDPatternOperator OpNode> {
4342 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4344 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4345 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4347 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4348 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4350 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4354 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4355 RegisterOperand inreg, RegisterOperand outreg,
4356 string asm, string outkind, string inkind,
4358 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4359 "{\t$Rd" # outkind # ", $Rn" # inkind #
4360 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4367 let Inst{28-24} = 0b01110;
4368 let Inst{23-22} = size;
4369 let Inst{21-17} = 0b10000;
4370 let Inst{16-12} = opcode;
4371 let Inst{11-10} = 0b10;
4376 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4377 RegisterOperand inreg, RegisterOperand outreg,
4378 string asm, string outkind, string inkind,
4380 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4381 "{\t$Rd" # outkind # ", $Rn" # inkind #
4382 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4389 let Inst{28-24} = 0b01110;
4390 let Inst{23-22} = size;
4391 let Inst{21-17} = 0b10000;
4392 let Inst{16-12} = opcode;
4393 let Inst{11-10} = 0b10;
4398 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4399 SDPatternOperator OpNode> {
4400 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4402 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4403 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4404 asm#"2", ".16b", ".8h", []>;
4405 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4407 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4408 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4409 asm#"2", ".8h", ".4s", []>;
4410 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4412 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4413 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4414 asm#"2", ".4s", ".2d", []>;
4416 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4417 (!cast<Instruction>(NAME # "v16i8")
4418 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4419 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4420 (!cast<Instruction>(NAME # "v8i16")
4421 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4422 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4423 (!cast<Instruction>(NAME # "v4i32")
4424 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4427 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4428 RegisterOperand regtype,
4429 string asm, string kind, string zero,
4430 ValueType dty, ValueType sty, SDNode OpNode>
4431 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4432 "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4433 "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4434 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4441 let Inst{28-24} = 0b01110;
4442 let Inst{23-22} = size;
4443 let Inst{21-17} = 0b10000;
4444 let Inst{16-12} = opcode;
4445 let Inst{11-10} = 0b10;
4450 // Comparisons support all element sizes, except 1xD.
4451 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4453 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4455 v8i8, v8i8, OpNode>;
4456 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4458 v16i8, v16i8, OpNode>;
4459 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4461 v4i16, v4i16, OpNode>;
4462 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4464 v8i16, v8i16, OpNode>;
4465 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4467 v2i32, v2i32, OpNode>;
4468 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4470 v4i32, v4i32, OpNode>;
4471 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4473 v2i64, v2i64, OpNode>;
4476 // FP Comparisons support only S and D element sizes.
4477 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4478 string asm, SDNode OpNode> {
4480 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4482 v2i32, v2f32, OpNode>;
4483 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4485 v4i32, v4f32, OpNode>;
4486 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4488 v2i64, v2f64, OpNode>;
4490 def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4491 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4492 def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4493 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4494 def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4495 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4496 def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4497 (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4498 def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4499 (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4500 def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4501 (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4504 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4505 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4506 RegisterOperand outtype, RegisterOperand intype,
4507 string asm, string VdTy, string VnTy,
4509 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4510 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4517 let Inst{28-24} = 0b01110;
4518 let Inst{23-22} = size;
4519 let Inst{21-17} = 0b10000;
4520 let Inst{16-12} = opcode;
4521 let Inst{11-10} = 0b10;
4526 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4527 RegisterOperand outtype, RegisterOperand intype,
4528 string asm, string VdTy, string VnTy,
4530 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4531 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4538 let Inst{28-24} = 0b01110;
4539 let Inst{23-22} = size;
4540 let Inst{21-17} = 0b10000;
4541 let Inst{16-12} = opcode;
4542 let Inst{11-10} = 0b10;
4547 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4548 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4549 asm, ".4s", ".4h", []>;
4550 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4551 asm#"2", ".4s", ".8h", []>;
4552 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4553 asm, ".2d", ".2s", []>;
4554 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4555 asm#"2", ".2d", ".4s", []>;
4558 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4559 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4560 asm, ".4h", ".4s", []>;
4561 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4562 asm#"2", ".8h", ".4s", []>;
4563 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4564 asm, ".2s", ".2d", []>;
4565 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4566 asm#"2", ".4s", ".2d", []>;
4569 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4571 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4573 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4574 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4575 asm#"2", ".4s", ".2d", []>;
4577 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4578 (!cast<Instruction>(NAME # "v4f32")
4579 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4582 //----------------------------------------------------------------------------
4583 // AdvSIMD three register different-size vector instructions.
4584 //----------------------------------------------------------------------------
4586 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4587 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4588 RegisterOperand outtype, RegisterOperand intype1,
4589 RegisterOperand intype2, string asm,
4590 string outkind, string inkind1, string inkind2,
4592 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4593 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4594 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4600 let Inst{30} = size{0};
4602 let Inst{28-24} = 0b01110;
4603 let Inst{23-22} = size{2-1};
4605 let Inst{20-16} = Rm;
4606 let Inst{15-12} = opcode;
4607 let Inst{11-10} = 0b00;
4612 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4613 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4614 RegisterOperand outtype, RegisterOperand intype1,
4615 RegisterOperand intype2, string asm,
4616 string outkind, string inkind1, string inkind2,
4618 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4619 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4620 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4626 let Inst{30} = size{0};
4628 let Inst{28-24} = 0b01110;
4629 let Inst{23-22} = size{2-1};
4631 let Inst{20-16} = Rm;
4632 let Inst{15-12} = opcode;
4633 let Inst{11-10} = 0b00;
4638 // FIXME: TableGen doesn't know how to deal with expanded types that also
4639 // change the element count (in this case, placing the results in
4640 // the high elements of the result register rather than the low
4641 // elements). Until that's fixed, we can't code-gen those.
4642 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4644 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4646 asm, ".8b", ".8h", ".8h",
4647 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4648 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4650 asm#"2", ".16b", ".8h", ".8h",
4652 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4654 asm, ".4h", ".4s", ".4s",
4655 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4656 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4658 asm#"2", ".8h", ".4s", ".4s",
4660 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4662 asm, ".2s", ".2d", ".2d",
4663 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4664 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4666 asm#"2", ".4s", ".2d", ".2d",
4670 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4671 // a version attached to an instruction.
4672 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4674 (!cast<Instruction>(NAME # "v8i16_v16i8")
4675 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4676 V128:$Rn, V128:$Rm)>;
4677 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4679 (!cast<Instruction>(NAME # "v4i32_v8i16")
4680 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4681 V128:$Rn, V128:$Rm)>;
4682 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4684 (!cast<Instruction>(NAME # "v2i64_v4i32")
4685 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4686 V128:$Rn, V128:$Rm)>;
4689 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4691 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4693 asm, ".8h", ".8b", ".8b",
4694 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4695 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4697 asm#"2", ".8h", ".16b", ".16b", []>;
4698 let Predicates = [HasCrypto] in {
4699 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4701 asm, ".1q", ".1d", ".1d", []>;
4702 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4704 asm#"2", ".1q", ".2d", ".2d", []>;
4707 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4708 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4709 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4712 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4713 SDPatternOperator OpNode> {
4714 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4716 asm, ".4s", ".4h", ".4h",
4717 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4718 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4720 asm#"2", ".4s", ".8h", ".8h",
4721 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4722 (extract_high_v8i16 V128:$Rm)))]>;
4723 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4725 asm, ".2d", ".2s", ".2s",
4726 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4727 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4729 asm#"2", ".2d", ".4s", ".4s",
4730 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4731 (extract_high_v4i32 V128:$Rm)))]>;
4734 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4735 SDPatternOperator OpNode = null_frag> {
4736 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4738 asm, ".8h", ".8b", ".8b",
4739 [(set (v8i16 V128:$Rd),
4740 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4741 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4743 asm#"2", ".8h", ".16b", ".16b",
4744 [(set (v8i16 V128:$Rd),
4745 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4746 (extract_high_v16i8 V128:$Rm)))))]>;
4747 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4749 asm, ".4s", ".4h", ".4h",
4750 [(set (v4i32 V128:$Rd),
4751 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4752 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4754 asm#"2", ".4s", ".8h", ".8h",
4755 [(set (v4i32 V128:$Rd),
4756 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4757 (extract_high_v8i16 V128:$Rm)))))]>;
4758 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4760 asm, ".2d", ".2s", ".2s",
4761 [(set (v2i64 V128:$Rd),
4762 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4763 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4765 asm#"2", ".2d", ".4s", ".4s",
4766 [(set (v2i64 V128:$Rd),
4767 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4768 (extract_high_v4i32 V128:$Rm)))))]>;
4771 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4773 SDPatternOperator OpNode> {
4774 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4776 asm, ".8h", ".8b", ".8b",
4777 [(set (v8i16 V128:$dst),
4778 (add (v8i16 V128:$Rd),
4779 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4780 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4782 asm#"2", ".8h", ".16b", ".16b",
4783 [(set (v8i16 V128:$dst),
4784 (add (v8i16 V128:$Rd),
4785 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4786 (extract_high_v16i8 V128:$Rm))))))]>;
4787 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4789 asm, ".4s", ".4h", ".4h",
4790 [(set (v4i32 V128:$dst),
4791 (add (v4i32 V128:$Rd),
4792 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4793 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4795 asm#"2", ".4s", ".8h", ".8h",
4796 [(set (v4i32 V128:$dst),
4797 (add (v4i32 V128:$Rd),
4798 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4799 (extract_high_v8i16 V128:$Rm))))))]>;
4800 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4802 asm, ".2d", ".2s", ".2s",
4803 [(set (v2i64 V128:$dst),
4804 (add (v2i64 V128:$Rd),
4805 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4806 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4808 asm#"2", ".2d", ".4s", ".4s",
4809 [(set (v2i64 V128:$dst),
4810 (add (v2i64 V128:$Rd),
4811 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4812 (extract_high_v4i32 V128:$Rm))))))]>;
4815 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4816 SDPatternOperator OpNode = null_frag> {
4817 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4819 asm, ".8h", ".8b", ".8b",
4820 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4821 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4823 asm#"2", ".8h", ".16b", ".16b",
4824 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4825 (extract_high_v16i8 V128:$Rm)))]>;
4826 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4828 asm, ".4s", ".4h", ".4h",
4829 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4830 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4832 asm#"2", ".4s", ".8h", ".8h",
4833 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4834 (extract_high_v8i16 V128:$Rm)))]>;
4835 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4837 asm, ".2d", ".2s", ".2s",
4838 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4839 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4841 asm#"2", ".2d", ".4s", ".4s",
4842 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4843 (extract_high_v4i32 V128:$Rm)))]>;
4846 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4848 SDPatternOperator OpNode> {
4849 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4851 asm, ".8h", ".8b", ".8b",
4852 [(set (v8i16 V128:$dst),
4853 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4854 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4856 asm#"2", ".8h", ".16b", ".16b",
4857 [(set (v8i16 V128:$dst),
4858 (OpNode (v8i16 V128:$Rd),
4859 (extract_high_v16i8 V128:$Rn),
4860 (extract_high_v16i8 V128:$Rm)))]>;
4861 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4863 asm, ".4s", ".4h", ".4h",
4864 [(set (v4i32 V128:$dst),
4865 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4866 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4868 asm#"2", ".4s", ".8h", ".8h",
4869 [(set (v4i32 V128:$dst),
4870 (OpNode (v4i32 V128:$Rd),
4871 (extract_high_v8i16 V128:$Rn),
4872 (extract_high_v8i16 V128:$Rm)))]>;
4873 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4875 asm, ".2d", ".2s", ".2s",
4876 [(set (v2i64 V128:$dst),
4877 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4878 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4880 asm#"2", ".2d", ".4s", ".4s",
4881 [(set (v2i64 V128:$dst),
4882 (OpNode (v2i64 V128:$Rd),
4883 (extract_high_v4i32 V128:$Rn),
4884 (extract_high_v4i32 V128:$Rm)))]>;
4887 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4888 SDPatternOperator Accum> {
4889 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4891 asm, ".4s", ".4h", ".4h",
4892 [(set (v4i32 V128:$dst),
4893 (Accum (v4i32 V128:$Rd),
4894 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4895 (v4i16 V64:$Rm)))))]>;
4896 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4898 asm#"2", ".4s", ".8h", ".8h",
4899 [(set (v4i32 V128:$dst),
4900 (Accum (v4i32 V128:$Rd),
4901 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4902 (extract_high_v8i16 V128:$Rm)))))]>;
4903 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4905 asm, ".2d", ".2s", ".2s",
4906 [(set (v2i64 V128:$dst),
4907 (Accum (v2i64 V128:$Rd),
4908 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4909 (v2i32 V64:$Rm)))))]>;
4910 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4912 asm#"2", ".2d", ".4s", ".4s",
4913 [(set (v2i64 V128:$dst),
4914 (Accum (v2i64 V128:$Rd),
4915 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4916 (extract_high_v4i32 V128:$Rm)))))]>;
4919 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4920 SDPatternOperator OpNode> {
4921 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4923 asm, ".8h", ".8h", ".8b",
4924 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4925 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4927 asm#"2", ".8h", ".8h", ".16b",
4928 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4929 (extract_high_v16i8 V128:$Rm)))]>;
4930 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4932 asm, ".4s", ".4s", ".4h",
4933 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4934 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4936 asm#"2", ".4s", ".4s", ".8h",
4937 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4938 (extract_high_v8i16 V128:$Rm)))]>;
4939 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4941 asm, ".2d", ".2d", ".2s",
4942 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4943 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4945 asm#"2", ".2d", ".2d", ".4s",
4946 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4947 (extract_high_v4i32 V128:$Rm)))]>;
4950 //----------------------------------------------------------------------------
4951 // AdvSIMD bitwise extract from vector
4952 //----------------------------------------------------------------------------
4954 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4955 string asm, string kind>
4956 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4957 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4958 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4959 [(set (vty regtype:$Rd),
4960 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4967 let Inst{30} = size;
4968 let Inst{29-21} = 0b101110000;
4969 let Inst{20-16} = Rm;
4971 let Inst{14-11} = imm;
4978 multiclass SIMDBitwiseExtract<string asm> {
4979 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4982 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4985 //----------------------------------------------------------------------------
4986 // AdvSIMD zip vector
4987 //----------------------------------------------------------------------------
4989 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4990 string asm, string kind, SDNode OpNode, ValueType valty>
4991 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4992 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4993 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4994 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5000 let Inst{30} = size{0};
5001 let Inst{29-24} = 0b001110;
5002 let Inst{23-22} = size{2-1};
5004 let Inst{20-16} = Rm;
5006 let Inst{14-12} = opc;
5007 let Inst{11-10} = 0b10;
5012 multiclass SIMDZipVector<bits<3>opc, string asm,
5014 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
5015 asm, ".8b", OpNode, v8i8>;
5016 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
5017 asm, ".16b", OpNode, v16i8>;
5018 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
5019 asm, ".4h", OpNode, v4i16>;
5020 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
5021 asm, ".8h", OpNode, v8i16>;
5022 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
5023 asm, ".2s", OpNode, v2i32>;
5024 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
5025 asm, ".4s", OpNode, v4i32>;
5026 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
5027 asm, ".2d", OpNode, v2i64>;
5029 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5030 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5031 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5032 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5033 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5034 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5037 //----------------------------------------------------------------------------
5038 // AdvSIMD three register scalar instructions
5039 //----------------------------------------------------------------------------
5041 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5042 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5043 RegisterClass regtype, string asm,
5045 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5046 "\t$Rd, $Rn, $Rm", "", pattern>,
5051 let Inst{31-30} = 0b01;
5053 let Inst{28-24} = 0b11110;
5054 let Inst{23-22} = size;
5056 let Inst{20-16} = Rm;
5057 let Inst{15-11} = opcode;
5063 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5064 SDPatternOperator OpNode> {
5065 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5066 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5069 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5070 SDPatternOperator OpNode> {
5071 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5072 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5073 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5074 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5075 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5077 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5078 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5079 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5080 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5083 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5084 SDPatternOperator OpNode> {
5085 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5086 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5087 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5090 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5091 SDPatternOperator OpNode = null_frag> {
5092 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5093 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5094 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5095 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5096 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5099 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5100 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5103 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5104 SDPatternOperator OpNode = null_frag> {
5105 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5106 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5107 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5108 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5109 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5112 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5113 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5116 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5117 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5118 : I<oops, iops, asm,
5119 "\t$Rd, $Rn, $Rm", cstr, pat>,
5124 let Inst{31-30} = 0b01;
5126 let Inst{28-24} = 0b11110;
5127 let Inst{23-22} = size;
5129 let Inst{20-16} = Rm;
5130 let Inst{15-11} = opcode;
5136 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5137 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5138 SDPatternOperator OpNode = null_frag> {
5139 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5141 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5142 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5144 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5145 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5148 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5149 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5150 SDPatternOperator OpNode = null_frag> {
5151 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5153 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5154 asm, "$Rd = $dst", []>;
5155 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5157 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5159 [(set (i64 FPR64:$dst),
5160 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5163 //----------------------------------------------------------------------------
5164 // AdvSIMD two register scalar instructions
5165 //----------------------------------------------------------------------------
5167 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5168 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5169 RegisterClass regtype, RegisterClass regtype2,
5170 string asm, list<dag> pat>
5171 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5172 "\t$Rd, $Rn", "", pat>,
5176 let Inst{31-30} = 0b01;
5178 let Inst{28-24} = 0b11110;
5179 let Inst{23-22} = size;
5180 let Inst{21-17} = 0b10000;
5181 let Inst{16-12} = opcode;
5182 let Inst{11-10} = 0b10;
5187 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5188 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5189 RegisterClass regtype, RegisterClass regtype2,
5190 string asm, list<dag> pat>
5191 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5192 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5196 let Inst{31-30} = 0b01;
5198 let Inst{28-24} = 0b11110;
5199 let Inst{23-22} = size;
5200 let Inst{21-17} = 0b10000;
5201 let Inst{16-12} = opcode;
5202 let Inst{11-10} = 0b10;
5208 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5209 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5210 RegisterClass regtype, string asm, string zero>
5211 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5212 "\t$Rd, $Rn, #" # zero, "", []>,
5216 let Inst{31-30} = 0b01;
5218 let Inst{28-24} = 0b11110;
5219 let Inst{23-22} = size;
5220 let Inst{21-17} = 0b10000;
5221 let Inst{16-12} = opcode;
5222 let Inst{11-10} = 0b10;
5227 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5228 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5229 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5233 let Inst{31-17} = 0b011111100110000;
5234 let Inst{16-12} = opcode;
5235 let Inst{11-10} = 0b10;
5240 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5241 SDPatternOperator OpNode> {
5242 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5244 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5245 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5248 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5249 SDPatternOperator OpNode> {
5250 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5251 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5253 def : InstAlias<asm # " $Rd, $Rn, #0",
5254 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn)>;
5255 def : InstAlias<asm # " $Rd, $Rn, #0",
5256 (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn)>;
5258 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5259 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5262 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5263 SDPatternOperator OpNode = null_frag> {
5264 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5265 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5267 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5268 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5271 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5272 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5273 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5276 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5277 SDPatternOperator OpNode> {
5278 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5279 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5280 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5281 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5284 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5285 SDPatternOperator OpNode = null_frag> {
5286 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5287 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5288 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5289 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5290 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5291 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5292 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5295 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5296 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5299 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5301 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5302 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5303 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5304 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5305 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5306 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5307 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5310 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5311 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5316 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5317 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5318 SDPatternOperator OpNode = null_frag> {
5319 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5320 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5321 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5322 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5325 //----------------------------------------------------------------------------
5326 // AdvSIMD scalar pairwise instructions
5327 //----------------------------------------------------------------------------
5329 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5330 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5331 RegisterOperand regtype, RegisterOperand vectype,
5332 string asm, string kind>
5333 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5334 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5338 let Inst{31-30} = 0b01;
5340 let Inst{28-24} = 0b11110;
5341 let Inst{23-22} = size;
5342 let Inst{21-17} = 0b11000;
5343 let Inst{16-12} = opcode;
5344 let Inst{11-10} = 0b10;
5349 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5350 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5354 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5355 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5357 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5361 //----------------------------------------------------------------------------
5362 // AdvSIMD across lanes instructions
5363 //----------------------------------------------------------------------------
5365 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5366 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5367 RegisterClass regtype, RegisterOperand vectype,
5368 string asm, string kind, list<dag> pattern>
5369 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5370 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5377 let Inst{28-24} = 0b01110;
5378 let Inst{23-22} = size;
5379 let Inst{21-17} = 0b11000;
5380 let Inst{16-12} = opcode;
5381 let Inst{11-10} = 0b10;
5386 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5388 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5390 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5392 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5394 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5396 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5400 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5401 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5403 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5405 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5407 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5409 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5413 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5415 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5417 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5420 //----------------------------------------------------------------------------
5421 // AdvSIMD INS/DUP instructions
5422 //----------------------------------------------------------------------------
5424 // FIXME: There has got to be a better way to factor these. ugh.
5426 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5427 string operands, string constraints, list<dag> pattern>
5428 : I<outs, ins, asm, operands, constraints, pattern>,
5435 let Inst{28-21} = 0b01110000;
5442 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5443 RegisterOperand vecreg, RegisterClass regtype>
5444 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5445 "{\t$Rd" # size # ", $Rn" #
5446 "|" # size # "\t$Rd, $Rn}", "",
5447 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5448 let Inst{20-16} = imm5;
5449 let Inst{14-11} = 0b0001;
5452 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5453 ValueType vectype, ValueType insreg,
5454 RegisterOperand vecreg, Operand idxtype,
5455 ValueType elttype, SDNode OpNode>
5456 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5457 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5458 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5459 [(set (vectype vecreg:$Rd),
5460 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5461 let Inst{14-11} = 0b0000;
5464 class SIMDDup64FromElement
5465 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5466 VectorIndexD, i64, ARM64duplane64> {
5469 let Inst{19-16} = 0b1000;
5472 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5473 RegisterOperand vecreg>
5474 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5475 VectorIndexS, i64, ARM64duplane32> {
5477 let Inst{20-19} = idx;
5478 let Inst{18-16} = 0b100;
5481 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5482 RegisterOperand vecreg>
5483 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5484 VectorIndexH, i64, ARM64duplane16> {
5486 let Inst{20-18} = idx;
5487 let Inst{17-16} = 0b10;
5490 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5491 RegisterOperand vecreg>
5492 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5493 VectorIndexB, i64, ARM64duplane8> {
5495 let Inst{20-17} = idx;
5499 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5500 Operand idxtype, string asm, list<dag> pattern>
5501 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5502 "{\t$Rd, $Rn" # size # "$idx" #
5503 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5504 let Inst{14-11} = imm4;
5507 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5509 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5510 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5512 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5513 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5515 class SIMDMovAlias<string asm, string size, Instruction inst,
5516 RegisterClass regtype, Operand idxtype>
5517 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5518 "|" # size # "\t$dst, $src$idx}",
5519 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5522 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5524 let Inst{20-17} = idx;
5527 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5529 let Inst{20-17} = idx;
5532 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5534 let Inst{20-18} = idx;
5535 let Inst{17-16} = 0b10;
5537 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5539 let Inst{20-18} = idx;
5540 let Inst{17-16} = 0b10;
5542 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5544 let Inst{20-19} = idx;
5545 let Inst{18-16} = 0b100;
5550 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5552 let Inst{20-17} = idx;
5555 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5557 let Inst{20-18} = idx;
5558 let Inst{17-16} = 0b10;
5560 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5562 let Inst{20-19} = idx;
5563 let Inst{18-16} = 0b100;
5565 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5568 let Inst{19-16} = 0b1000;
5570 def : SIMDMovAlias<"mov", ".s",
5571 !cast<Instruction>(NAME#"vi32"),
5572 GPR32, VectorIndexS>;
5573 def : SIMDMovAlias<"mov", ".d",
5574 !cast<Instruction>(NAME#"vi64"),
5575 GPR64, VectorIndexD>;
5578 class SIMDInsFromMain<string size, ValueType vectype,
5579 RegisterClass regtype, Operand idxtype>
5580 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5581 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5582 "{\t$Rd" # size # "$idx, $Rn" #
5583 "|" # size # "\t$Rd$idx, $Rn}",
5586 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5587 let Inst{14-11} = 0b0011;
5590 class SIMDInsFromElement<string size, ValueType vectype,
5591 ValueType elttype, Operand idxtype>
5592 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5593 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5594 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5595 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5600 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5603 class SIMDInsMainMovAlias<string size, Instruction inst,
5604 RegisterClass regtype, Operand idxtype>
5605 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5606 "|" # size #"\t$dst$idx, $src}",
5607 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5608 class SIMDInsElementMovAlias<string size, Instruction inst,
5610 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5611 # "|" # size #" $dst$idx, $src$idx2}",
5612 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5615 multiclass SIMDIns {
5616 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5618 let Inst{20-17} = idx;
5621 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5623 let Inst{20-18} = idx;
5624 let Inst{17-16} = 0b10;
5626 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5628 let Inst{20-19} = idx;
5629 let Inst{18-16} = 0b100;
5631 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5634 let Inst{19-16} = 0b1000;
5637 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5640 let Inst{20-17} = idx;
5642 let Inst{14-11} = idx2;
5644 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5647 let Inst{20-18} = idx;
5648 let Inst{17-16} = 0b10;
5649 let Inst{14-12} = idx2;
5652 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5655 let Inst{20-19} = idx;
5656 let Inst{18-16} = 0b100;
5657 let Inst{14-13} = idx2;
5658 let Inst{12-11} = 0;
5660 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5664 let Inst{19-16} = 0b1000;
5665 let Inst{14} = idx2;
5666 let Inst{13-11} = 0;
5669 // For all forms of the INS instruction, the "mov" mnemonic is the
5670 // preferred alias. Why they didn't just call the instruction "mov" in
5671 // the first place is a very good question indeed...
5672 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5673 GPR32, VectorIndexB>;
5674 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5675 GPR32, VectorIndexH>;
5676 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5677 GPR32, VectorIndexS>;
5678 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5679 GPR64, VectorIndexD>;
5681 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5683 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5685 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5687 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5691 //----------------------------------------------------------------------------
5693 //----------------------------------------------------------------------------
5695 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5696 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5697 RegisterOperand listtype, string asm, string kind>
5698 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5699 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5706 let Inst{29-21} = 0b001110000;
5707 let Inst{20-16} = Vm;
5709 let Inst{14-13} = len;
5711 let Inst{11-10} = 0b00;
5716 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5717 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5718 RegisterOperand listtype, string asm, string kind>
5719 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5720 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5727 let Inst{29-21} = 0b001110000;
5728 let Inst{20-16} = Vm;
5730 let Inst{14-13} = len;
5732 let Inst{11-10} = 0b00;
5737 class SIMDTableLookupAlias<string asm, Instruction inst,
5738 RegisterOperand vectype, RegisterOperand listtype>
5739 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5740 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5742 multiclass SIMDTableLookup<bit op, string asm> {
5743 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5745 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5747 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5749 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5751 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5753 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5755 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5757 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5760 def : SIMDTableLookupAlias<asm # ".8b",
5761 !cast<Instruction>(NAME#"v8i8One"),
5762 V64, VecListOne128>;
5763 def : SIMDTableLookupAlias<asm # ".8b",
5764 !cast<Instruction>(NAME#"v8i8Two"),
5765 V64, VecListTwo128>;
5766 def : SIMDTableLookupAlias<asm # ".8b",
5767 !cast<Instruction>(NAME#"v8i8Three"),
5768 V64, VecListThree128>;
5769 def : SIMDTableLookupAlias<asm # ".8b",
5770 !cast<Instruction>(NAME#"v8i8Four"),
5771 V64, VecListFour128>;
5772 def : SIMDTableLookupAlias<asm # ".16b",
5773 !cast<Instruction>(NAME#"v16i8One"),
5774 V128, VecListOne128>;
5775 def : SIMDTableLookupAlias<asm # ".16b",
5776 !cast<Instruction>(NAME#"v16i8Two"),
5777 V128, VecListTwo128>;
5778 def : SIMDTableLookupAlias<asm # ".16b",
5779 !cast<Instruction>(NAME#"v16i8Three"),
5780 V128, VecListThree128>;
5781 def : SIMDTableLookupAlias<asm # ".16b",
5782 !cast<Instruction>(NAME#"v16i8Four"),
5783 V128, VecListFour128>;
5786 multiclass SIMDTableLookupTied<bit op, string asm> {
5787 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5789 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5791 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5793 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5795 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5797 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5799 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5801 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5804 def : SIMDTableLookupAlias<asm # ".8b",
5805 !cast<Instruction>(NAME#"v8i8One"),
5806 V64, VecListOne128>;
5807 def : SIMDTableLookupAlias<asm # ".8b",
5808 !cast<Instruction>(NAME#"v8i8Two"),
5809 V64, VecListTwo128>;
5810 def : SIMDTableLookupAlias<asm # ".8b",
5811 !cast<Instruction>(NAME#"v8i8Three"),
5812 V64, VecListThree128>;
5813 def : SIMDTableLookupAlias<asm # ".8b",
5814 !cast<Instruction>(NAME#"v8i8Four"),
5815 V64, VecListFour128>;
5816 def : SIMDTableLookupAlias<asm # ".16b",
5817 !cast<Instruction>(NAME#"v16i8One"),
5818 V128, VecListOne128>;
5819 def : SIMDTableLookupAlias<asm # ".16b",
5820 !cast<Instruction>(NAME#"v16i8Two"),
5821 V128, VecListTwo128>;
5822 def : SIMDTableLookupAlias<asm # ".16b",
5823 !cast<Instruction>(NAME#"v16i8Three"),
5824 V128, VecListThree128>;
5825 def : SIMDTableLookupAlias<asm # ".16b",
5826 !cast<Instruction>(NAME#"v16i8Four"),
5827 V128, VecListFour128>;
5831 //----------------------------------------------------------------------------
5832 // AdvSIMD scalar CPY
5833 //----------------------------------------------------------------------------
5834 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5835 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5836 string kind, Operand idxtype>
5837 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5838 "{\t$dst, $src" # kind # "$idx" #
5839 "|\t$dst, $src$idx}", "", []>,
5843 let Inst{31-21} = 0b01011110000;
5844 let Inst{15-10} = 0b000001;
5845 let Inst{9-5} = src;
5846 let Inst{4-0} = dst;
5849 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5850 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5851 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5852 # "|\t$dst, $src$index}",
5853 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5856 multiclass SIMDScalarCPY<string asm> {
5857 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5859 let Inst{20-17} = idx;
5862 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5864 let Inst{20-18} = idx;
5865 let Inst{17-16} = 0b10;
5867 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5869 let Inst{20-19} = idx;
5870 let Inst{18-16} = 0b100;
5872 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5875 let Inst{19-16} = 0b1000;
5878 def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
5879 VectorIndexD:$idx)))),
5880 (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
5882 // 'DUP' mnemonic aliases.
5883 def : SIMDScalarCPYAlias<"dup", ".b",
5884 !cast<Instruction>(NAME#"i8"),
5885 FPR8, V128, VectorIndexB>;
5886 def : SIMDScalarCPYAlias<"dup", ".h",
5887 !cast<Instruction>(NAME#"i16"),
5888 FPR16, V128, VectorIndexH>;
5889 def : SIMDScalarCPYAlias<"dup", ".s",
5890 !cast<Instruction>(NAME#"i32"),
5891 FPR32, V128, VectorIndexS>;
5892 def : SIMDScalarCPYAlias<"dup", ".d",
5893 !cast<Instruction>(NAME#"i64"),
5894 FPR64, V128, VectorIndexD>;
5897 //----------------------------------------------------------------------------
5898 // AdvSIMD modified immediate instructions
5899 //----------------------------------------------------------------------------
5901 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5902 string asm, string op_string,
5903 string cstr, list<dag> pattern>
5904 : I<oops, iops, asm, op_string, cstr, pattern>,
5911 let Inst{28-19} = 0b0111100000;
5912 let Inst{18-16} = imm8{7-5};
5913 let Inst{11-10} = 0b01;
5914 let Inst{9-5} = imm8{4-0};
5918 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5919 Operand immtype, dag opt_shift_iop,
5920 string opt_shift, string asm, string kind,
5922 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5923 !con((ins immtype:$imm8), opt_shift_iop), asm,
5924 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5925 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5927 let DecoderMethod = "DecodeModImmInstruction";
5930 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5931 Operand immtype, dag opt_shift_iop,
5932 string opt_shift, string asm, string kind,
5934 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5935 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5936 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5937 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5938 "$Rd = $dst", pattern> {
5939 let DecoderMethod = "DecodeModImmTiedInstruction";
5942 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5943 RegisterOperand vectype, string asm,
5944 string kind, list<dag> pattern>
5945 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5946 (ins logical_vec_shift:$shift),
5947 "$shift", asm, kind, pattern> {
5949 let Inst{15} = b15_b12{1};
5950 let Inst{14-13} = shift;
5951 let Inst{12} = b15_b12{0};
5954 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5955 RegisterOperand vectype, string asm,
5956 string kind, list<dag> pattern>
5957 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5958 (ins logical_vec_shift:$shift),
5959 "$shift", asm, kind, pattern> {
5961 let Inst{15} = b15_b12{1};
5962 let Inst{14-13} = shift;
5963 let Inst{12} = b15_b12{0};
5967 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5968 RegisterOperand vectype, string asm,
5969 string kind, list<dag> pattern>
5970 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5971 (ins logical_vec_hw_shift:$shift),
5972 "$shift", asm, kind, pattern> {
5974 let Inst{15} = b15_b12{1};
5976 let Inst{13} = shift{0};
5977 let Inst{12} = b15_b12{0};
5980 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5981 RegisterOperand vectype, string asm,
5982 string kind, list<dag> pattern>
5983 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5984 (ins logical_vec_hw_shift:$shift),
5985 "$shift", asm, kind, pattern> {
5987 let Inst{15} = b15_b12{1};
5989 let Inst{13} = shift{0};
5990 let Inst{12} = b15_b12{0};
5993 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5995 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5997 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6000 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6002 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6006 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6007 bits<2> w_cmode, string asm,
6009 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6011 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6013 (i32 imm:$shift)))]>;
6014 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6016 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6018 (i32 imm:$shift)))]>;
6020 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6022 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6024 (i32 imm:$shift)))]>;
6025 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6027 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6029 (i32 imm:$shift)))]>;
6032 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6033 RegisterOperand vectype, string asm,
6034 string kind, list<dag> pattern>
6035 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6036 (ins move_vec_shift:$shift),
6037 "$shift", asm, kind, pattern> {
6039 let Inst{15-13} = cmode{3-1};
6040 let Inst{12} = shift;
6043 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6044 RegisterOperand vectype,
6045 Operand imm_type, string asm,
6046 string kind, list<dag> pattern>
6047 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6048 asm, kind, pattern> {
6049 let Inst{15-12} = cmode;
6052 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6054 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6055 "\t$Rd, $imm8", "", pattern> {
6056 let Inst{15-12} = cmode;
6057 let DecoderMethod = "DecodeModImmInstruction";
6060 //----------------------------------------------------------------------------
6061 // AdvSIMD indexed element
6062 //----------------------------------------------------------------------------
6064 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6065 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6066 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6067 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6068 string apple_kind, string dst_kind, string lhs_kind,
6069 string rhs_kind, list<dag> pattern>
6070 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6072 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6073 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6082 let Inst{28} = Scalar;
6083 let Inst{27-24} = 0b1111;
6084 let Inst{23-22} = size;
6085 // Bit 21 must be set by the derived class.
6086 let Inst{20-16} = Rm;
6087 let Inst{15-12} = opc;
6088 // Bit 11 must be set by the derived class.
6094 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6095 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6096 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6097 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6098 string apple_kind, string dst_kind, string lhs_kind,
6099 string rhs_kind, list<dag> pattern>
6100 : I<(outs dst_reg:$dst),
6101 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6102 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6103 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6112 let Inst{28} = Scalar;
6113 let Inst{27-24} = 0b1111;
6114 let Inst{23-22} = size;
6115 // Bit 21 must be set by the derived class.
6116 let Inst{20-16} = Rm;
6117 let Inst{15-12} = opc;
6118 // Bit 11 must be set by the derived class.
6124 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6125 SDPatternOperator OpNode> {
6126 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6129 asm, ".2s", ".2s", ".2s", ".s",
6130 [(set (v2f32 V64:$Rd),
6131 (OpNode (v2f32 V64:$Rn),
6132 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6134 let Inst{11} = idx{1};
6135 let Inst{21} = idx{0};
6138 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6141 asm, ".4s", ".4s", ".4s", ".s",
6142 [(set (v4f32 V128:$Rd),
6143 (OpNode (v4f32 V128:$Rn),
6144 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6146 let Inst{11} = idx{1};
6147 let Inst{21} = idx{0};
6150 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6153 asm, ".2d", ".2d", ".2d", ".d",
6154 [(set (v2f64 V128:$Rd),
6155 (OpNode (v2f64 V128:$Rn),
6156 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6158 let Inst{11} = idx{0};
6162 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6163 FPR32Op, FPR32Op, V128, VectorIndexS,
6164 asm, ".s", "", "", ".s",
6165 [(set (f32 FPR32Op:$Rd),
6166 (OpNode (f32 FPR32Op:$Rn),
6167 (f32 (vector_extract (v4f32 V128:$Rm),
6168 VectorIndexS:$idx))))]> {
6170 let Inst{11} = idx{1};
6171 let Inst{21} = idx{0};
6174 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6175 FPR64Op, FPR64Op, V128, VectorIndexD,
6176 asm, ".d", "", "", ".d",
6177 [(set (f64 FPR64Op:$Rd),
6178 (OpNode (f64 FPR64Op:$Rn),
6179 (f64 (vector_extract (v2f64 V128:$Rm),
6180 VectorIndexD:$idx))))]> {
6182 let Inst{11} = idx{0};
6187 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6188 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6189 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6190 (ARM64duplane32 (v4f32 V128:$Rm),
6191 VectorIndexS:$idx))),
6192 (!cast<Instruction>(INST # v2i32_indexed)
6193 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6194 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6195 (ARM64dup (f32 FPR32Op:$Rm)))),
6196 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6197 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6200 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6201 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6202 (ARM64duplane32 (v4f32 V128:$Rm),
6203 VectorIndexS:$idx))),
6204 (!cast<Instruction>(INST # "v4i32_indexed")
6205 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6206 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6207 (ARM64dup (f32 FPR32Op:$Rm)))),
6208 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6209 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6211 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6212 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6213 (ARM64duplane64 (v2f64 V128:$Rm),
6214 VectorIndexD:$idx))),
6215 (!cast<Instruction>(INST # "v2i64_indexed")
6216 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6217 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6218 (ARM64dup (f64 FPR64Op:$Rm)))),
6219 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6220 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6222 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6223 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6224 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6225 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6226 V128:$Rm, VectorIndexS:$idx)>;
6227 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6228 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6229 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6230 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6232 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6233 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6234 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6235 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6236 V128:$Rm, VectorIndexD:$idx)>;
6239 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6240 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6242 asm, ".2s", ".2s", ".2s", ".s", []> {
6244 let Inst{11} = idx{1};
6245 let Inst{21} = idx{0};
6248 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6251 asm, ".4s", ".4s", ".4s", ".s", []> {
6253 let Inst{11} = idx{1};
6254 let Inst{21} = idx{0};
6257 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6260 asm, ".2d", ".2d", ".2d", ".d", []> {
6262 let Inst{11} = idx{0};
6267 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6268 FPR32Op, FPR32Op, V128, VectorIndexS,
6269 asm, ".s", "", "", ".s", []> {
6271 let Inst{11} = idx{1};
6272 let Inst{21} = idx{0};
6275 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6276 FPR64Op, FPR64Op, V128, VectorIndexD,
6277 asm, ".d", "", "", ".d", []> {
6279 let Inst{11} = idx{0};
6284 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6285 SDPatternOperator OpNode> {
6286 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6287 V128_lo, VectorIndexH,
6288 asm, ".4h", ".4h", ".4h", ".h",
6289 [(set (v4i16 V64:$Rd),
6290 (OpNode (v4i16 V64:$Rn),
6291 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6293 let Inst{11} = idx{2};
6294 let Inst{21} = idx{1};
6295 let Inst{20} = idx{0};
6298 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6300 V128_lo, VectorIndexH,
6301 asm, ".8h", ".8h", ".8h", ".h",
6302 [(set (v8i16 V128:$Rd),
6303 (OpNode (v8i16 V128:$Rn),
6304 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6306 let Inst{11} = idx{2};
6307 let Inst{21} = idx{1};
6308 let Inst{20} = idx{0};
6311 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6314 asm, ".2s", ".2s", ".2s", ".s",
6315 [(set (v2i32 V64:$Rd),
6316 (OpNode (v2i32 V64:$Rn),
6317 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6319 let Inst{11} = idx{1};
6320 let Inst{21} = idx{0};
6323 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6326 asm, ".4s", ".4s", ".4s", ".s",
6327 [(set (v4i32 V128:$Rd),
6328 (OpNode (v4i32 V128:$Rn),
6329 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6331 let Inst{11} = idx{1};
6332 let Inst{21} = idx{0};
6335 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6336 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6337 asm, ".h", "", "", ".h", []> {
6339 let Inst{11} = idx{2};
6340 let Inst{21} = idx{1};
6341 let Inst{20} = idx{0};
6344 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6345 FPR32Op, FPR32Op, V128, VectorIndexS,
6346 asm, ".s", "", "", ".s",
6347 [(set (i32 FPR32Op:$Rd),
6348 (OpNode FPR32Op:$Rn,
6349 (i32 (vector_extract (v4i32 V128:$Rm),
6350 VectorIndexS:$idx))))]> {
6352 let Inst{11} = idx{1};
6353 let Inst{21} = idx{0};
6357 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6358 SDPatternOperator OpNode> {
6359 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6361 V128_lo, VectorIndexH,
6362 asm, ".4h", ".4h", ".4h", ".h",
6363 [(set (v4i16 V64:$Rd),
6364 (OpNode (v4i16 V64:$Rn),
6365 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6367 let Inst{11} = idx{2};
6368 let Inst{21} = idx{1};
6369 let Inst{20} = idx{0};
6372 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6374 V128_lo, VectorIndexH,
6375 asm, ".8h", ".8h", ".8h", ".h",
6376 [(set (v8i16 V128:$Rd),
6377 (OpNode (v8i16 V128:$Rn),
6378 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6380 let Inst{11} = idx{2};
6381 let Inst{21} = idx{1};
6382 let Inst{20} = idx{0};
6385 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6388 asm, ".2s", ".2s", ".2s", ".s",
6389 [(set (v2i32 V64:$Rd),
6390 (OpNode (v2i32 V64:$Rn),
6391 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6393 let Inst{11} = idx{1};
6394 let Inst{21} = idx{0};
6397 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6400 asm, ".4s", ".4s", ".4s", ".s",
6401 [(set (v4i32 V128:$Rd),
6402 (OpNode (v4i32 V128:$Rn),
6403 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6405 let Inst{11} = idx{1};
6406 let Inst{21} = idx{0};
6410 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6411 SDPatternOperator OpNode> {
6412 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6413 V128_lo, VectorIndexH,
6414 asm, ".4h", ".4h", ".4h", ".h",
6415 [(set (v4i16 V64:$dst),
6416 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6417 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6419 let Inst{11} = idx{2};
6420 let Inst{21} = idx{1};
6421 let Inst{20} = idx{0};
6424 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6426 V128_lo, VectorIndexH,
6427 asm, ".8h", ".8h", ".8h", ".h",
6428 [(set (v8i16 V128:$dst),
6429 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6430 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6432 let Inst{11} = idx{2};
6433 let Inst{21} = idx{1};
6434 let Inst{20} = idx{0};
6437 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6440 asm, ".2s", ".2s", ".2s", ".s",
6441 [(set (v2i32 V64:$dst),
6442 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6443 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6445 let Inst{11} = idx{1};
6446 let Inst{21} = idx{0};
6449 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6452 asm, ".4s", ".4s", ".4s", ".s",
6453 [(set (v4i32 V128:$dst),
6454 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6455 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6457 let Inst{11} = idx{1};
6458 let Inst{21} = idx{0};
6462 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6463 SDPatternOperator OpNode> {
6464 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6466 V128_lo, VectorIndexH,
6467 asm, ".4s", ".4s", ".4h", ".h",
6468 [(set (v4i32 V128:$Rd),
6469 (OpNode (v4i16 V64:$Rn),
6470 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6472 let Inst{11} = idx{2};
6473 let Inst{21} = idx{1};
6474 let Inst{20} = idx{0};
6477 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6479 V128_lo, VectorIndexH,
6480 asm#"2", ".4s", ".4s", ".8h", ".h",
6481 [(set (v4i32 V128:$Rd),
6482 (OpNode (extract_high_v8i16 V128:$Rn),
6483 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6484 VectorIndexH:$idx))))]> {
6487 let Inst{11} = idx{2};
6488 let Inst{21} = idx{1};
6489 let Inst{20} = idx{0};
6492 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6495 asm, ".2d", ".2d", ".2s", ".s",
6496 [(set (v2i64 V128:$Rd),
6497 (OpNode (v2i32 V64:$Rn),
6498 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6500 let Inst{11} = idx{1};
6501 let Inst{21} = idx{0};
6504 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6507 asm#"2", ".2d", ".2d", ".4s", ".s",
6508 [(set (v2i64 V128:$Rd),
6509 (OpNode (extract_high_v4i32 V128:$Rn),
6510 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6511 VectorIndexS:$idx))))]> {
6513 let Inst{11} = idx{1};
6514 let Inst{21} = idx{0};
6517 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6518 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6519 asm, ".h", "", "", ".h", []> {
6521 let Inst{11} = idx{2};
6522 let Inst{21} = idx{1};
6523 let Inst{20} = idx{0};
6526 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6527 FPR64Op, FPR32Op, V128, VectorIndexS,
6528 asm, ".s", "", "", ".s", []> {
6530 let Inst{11} = idx{1};
6531 let Inst{21} = idx{0};
6535 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6536 SDPatternOperator Accum> {
6537 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6539 V128_lo, VectorIndexH,
6540 asm, ".4s", ".4s", ".4h", ".h",
6541 [(set (v4i32 V128:$dst),
6542 (Accum (v4i32 V128:$Rd),
6543 (v4i32 (int_arm64_neon_sqdmull
6545 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6546 VectorIndexH:$idx))))))]> {
6548 let Inst{11} = idx{2};
6549 let Inst{21} = idx{1};
6550 let Inst{20} = idx{0};
6553 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6554 // intermediate EXTRACT_SUBREG would be untyped.
6555 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6556 (i32 (vector_extract (v4i32
6557 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6558 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6559 VectorIndexH:$idx)))),
6562 (!cast<Instruction>(NAME # v4i16_indexed)
6563 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6564 V128_lo:$Rm, VectorIndexH:$idx),
6567 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6569 V128_lo, VectorIndexH,
6570 asm#"2", ".4s", ".4s", ".8h", ".h",
6571 [(set (v4i32 V128:$dst),
6572 (Accum (v4i32 V128:$Rd),
6573 (v4i32 (int_arm64_neon_sqdmull
6574 (extract_high_v8i16 V128:$Rn),
6576 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6577 VectorIndexH:$idx))))))]> {
6579 let Inst{11} = idx{2};
6580 let Inst{21} = idx{1};
6581 let Inst{20} = idx{0};
6584 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6587 asm, ".2d", ".2d", ".2s", ".s",
6588 [(set (v2i64 V128:$dst),
6589 (Accum (v2i64 V128:$Rd),
6590 (v2i64 (int_arm64_neon_sqdmull
6592 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6593 VectorIndexS:$idx))))))]> {
6595 let Inst{11} = idx{1};
6596 let Inst{21} = idx{0};
6599 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6602 asm#"2", ".2d", ".2d", ".4s", ".s",
6603 [(set (v2i64 V128:$dst),
6604 (Accum (v2i64 V128:$Rd),
6605 (v2i64 (int_arm64_neon_sqdmull
6606 (extract_high_v4i32 V128:$Rn),
6608 (ARM64duplane32 (v4i32 V128:$Rm),
6609 VectorIndexS:$idx))))))]> {
6611 let Inst{11} = idx{1};
6612 let Inst{21} = idx{0};
6615 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6616 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6617 asm, ".h", "", "", ".h", []> {
6619 let Inst{11} = idx{2};
6620 let Inst{21} = idx{1};
6621 let Inst{20} = idx{0};
6625 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6626 FPR64Op, FPR32Op, V128, VectorIndexS,
6627 asm, ".s", "", "", ".s",
6628 [(set (i64 FPR64Op:$dst),
6629 (Accum (i64 FPR64Op:$Rd),
6630 (i64 (int_arm64_neon_sqdmulls_scalar
6632 (i32 (vector_extract (v4i32 V128:$Rm),
6633 VectorIndexS:$idx))))))]> {
6636 let Inst{11} = idx{1};
6637 let Inst{21} = idx{0};
6641 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6642 SDPatternOperator OpNode> {
6643 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6644 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6646 V128_lo, VectorIndexH,
6647 asm, ".4s", ".4s", ".4h", ".h",
6648 [(set (v4i32 V128:$Rd),
6649 (OpNode (v4i16 V64:$Rn),
6650 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6652 let Inst{11} = idx{2};
6653 let Inst{21} = idx{1};
6654 let Inst{20} = idx{0};
6657 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6659 V128_lo, VectorIndexH,
6660 asm#"2", ".4s", ".4s", ".8h", ".h",
6661 [(set (v4i32 V128:$Rd),
6662 (OpNode (extract_high_v8i16 V128:$Rn),
6663 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6664 VectorIndexH:$idx))))]> {
6667 let Inst{11} = idx{2};
6668 let Inst{21} = idx{1};
6669 let Inst{20} = idx{0};
6672 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6675 asm, ".2d", ".2d", ".2s", ".s",
6676 [(set (v2i64 V128:$Rd),
6677 (OpNode (v2i32 V64:$Rn),
6678 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6680 let Inst{11} = idx{1};
6681 let Inst{21} = idx{0};
6684 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6687 asm#"2", ".2d", ".2d", ".4s", ".s",
6688 [(set (v2i64 V128:$Rd),
6689 (OpNode (extract_high_v4i32 V128:$Rn),
6690 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6691 VectorIndexS:$idx))))]> {
6693 let Inst{11} = idx{1};
6694 let Inst{21} = idx{0};
6699 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6700 SDPatternOperator OpNode> {
6701 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6702 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6704 V128_lo, VectorIndexH,
6705 asm, ".4s", ".4s", ".4h", ".h",
6706 [(set (v4i32 V128:$dst),
6707 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6708 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6710 let Inst{11} = idx{2};
6711 let Inst{21} = idx{1};
6712 let Inst{20} = idx{0};
6715 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6717 V128_lo, VectorIndexH,
6718 asm#"2", ".4s", ".4s", ".8h", ".h",
6719 [(set (v4i32 V128:$dst),
6720 (OpNode (v4i32 V128:$Rd),
6721 (extract_high_v8i16 V128:$Rn),
6722 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6723 VectorIndexH:$idx))))]> {
6725 let Inst{11} = idx{2};
6726 let Inst{21} = idx{1};
6727 let Inst{20} = idx{0};
6730 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6733 asm, ".2d", ".2d", ".2s", ".s",
6734 [(set (v2i64 V128:$dst),
6735 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6736 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6738 let Inst{11} = idx{1};
6739 let Inst{21} = idx{0};
6742 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6745 asm#"2", ".2d", ".2d", ".4s", ".s",
6746 [(set (v2i64 V128:$dst),
6747 (OpNode (v2i64 V128:$Rd),
6748 (extract_high_v4i32 V128:$Rn),
6749 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6750 VectorIndexS:$idx))))]> {
6752 let Inst{11} = idx{1};
6753 let Inst{21} = idx{0};
6758 //----------------------------------------------------------------------------
6759 // AdvSIMD scalar shift by immediate
6760 //----------------------------------------------------------------------------
6762 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6763 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6764 RegisterClass regtype1, RegisterClass regtype2,
6765 Operand immtype, string asm, list<dag> pattern>
6766 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6767 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6772 let Inst{31-30} = 0b01;
6774 let Inst{28-23} = 0b111110;
6775 let Inst{22-16} = fixed_imm;
6776 let Inst{15-11} = opc;
6782 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6783 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6784 RegisterClass regtype1, RegisterClass regtype2,
6785 Operand immtype, string asm, list<dag> pattern>
6786 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6787 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6792 let Inst{31-30} = 0b01;
6794 let Inst{28-23} = 0b111110;
6795 let Inst{22-16} = fixed_imm;
6796 let Inst{15-11} = opc;
6803 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6804 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6805 FPR32, FPR32, vecshiftR32, asm, []> {
6806 let Inst{20-16} = imm{4-0};
6809 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6810 FPR64, FPR64, vecshiftR64, asm, []> {
6811 let Inst{21-16} = imm{5-0};
6815 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6816 SDPatternOperator OpNode> {
6817 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6818 FPR64, FPR64, vecshiftR64, asm,
6819 [(set (i64 FPR64:$Rd),
6820 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6821 let Inst{21-16} = imm{5-0};
6824 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6825 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
6828 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6829 SDPatternOperator OpNode = null_frag> {
6830 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6831 FPR64, FPR64, vecshiftR64, asm,
6832 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6833 (i32 vecshiftR64:$imm)))]> {
6834 let Inst{21-16} = imm{5-0};
6837 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6838 (i32 vecshiftR64:$imm))),
6839 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6843 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6844 SDPatternOperator OpNode> {
6845 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6846 FPR64, FPR64, vecshiftL64, asm,
6847 [(set (v1i64 FPR64:$Rd),
6848 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6849 let Inst{21-16} = imm{5-0};
6853 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6854 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6855 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6856 FPR64, FPR64, vecshiftL64, asm, []> {
6857 let Inst{21-16} = imm{5-0};
6861 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6862 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6863 SDPatternOperator OpNode = null_frag> {
6864 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6865 FPR8, FPR16, vecshiftR8, asm, []> {
6866 let Inst{18-16} = imm{2-0};
6869 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6870 FPR16, FPR32, vecshiftR16, asm, []> {
6871 let Inst{19-16} = imm{3-0};
6874 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6875 FPR32, FPR64, vecshiftR32, asm,
6876 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6877 let Inst{20-16} = imm{4-0};
6881 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6882 SDPatternOperator OpNode> {
6883 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6884 FPR8, FPR8, vecshiftL8, asm, []> {
6885 let Inst{18-16} = imm{2-0};
6888 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6889 FPR16, FPR16, vecshiftL16, asm, []> {
6890 let Inst{19-16} = imm{3-0};
6893 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6894 FPR32, FPR32, vecshiftL32, asm,
6895 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6896 let Inst{20-16} = imm{4-0};
6899 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6900 FPR64, FPR64, vecshiftL64, asm,
6901 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6902 let Inst{21-16} = imm{5-0};
6905 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
6906 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
6909 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6910 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6911 FPR8, FPR8, vecshiftR8, asm, []> {
6912 let Inst{18-16} = imm{2-0};
6915 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6916 FPR16, FPR16, vecshiftR16, asm, []> {
6917 let Inst{19-16} = imm{3-0};
6920 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6921 FPR32, FPR32, vecshiftR32, asm, []> {
6922 let Inst{20-16} = imm{4-0};
6925 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6926 FPR64, FPR64, vecshiftR64, asm, []> {
6927 let Inst{21-16} = imm{5-0};
6931 //----------------------------------------------------------------------------
6932 // AdvSIMD vector x indexed element
6933 //----------------------------------------------------------------------------
6935 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6936 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6937 RegisterOperand dst_reg, RegisterOperand src_reg,
6939 string asm, string dst_kind, string src_kind,
6941 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6942 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6943 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6950 let Inst{28-23} = 0b011110;
6951 let Inst{22-16} = fixed_imm;
6952 let Inst{15-11} = opc;
6958 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6959 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6960 RegisterOperand vectype1, RegisterOperand vectype2,
6962 string asm, string dst_kind, string src_kind,
6964 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6965 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6966 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6973 let Inst{28-23} = 0b011110;
6974 let Inst{22-16} = fixed_imm;
6975 let Inst{15-11} = opc;
6981 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6983 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6984 V64, V64, vecshiftR32,
6986 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6988 let Inst{20-16} = imm;
6991 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6992 V128, V128, vecshiftR32,
6994 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6996 let Inst{20-16} = imm;
6999 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7000 V128, V128, vecshiftR64,
7002 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7004 let Inst{21-16} = imm;
7008 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7010 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7011 V64, V64, vecshiftR32,
7013 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7015 let Inst{20-16} = imm;
7018 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7019 V128, V128, vecshiftR32,
7021 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7023 let Inst{20-16} = imm;
7026 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7027 V128, V128, vecshiftR64,
7029 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7031 let Inst{21-16} = imm;
7035 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7036 SDPatternOperator OpNode> {
7037 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7038 V64, V128, vecshiftR16Narrow,
7040 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7042 let Inst{18-16} = imm;
7045 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7046 V128, V128, vecshiftR16Narrow,
7047 asm#"2", ".16b", ".8h", []> {
7049 let Inst{18-16} = imm;
7050 let hasSideEffects = 0;
7053 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7054 V64, V128, vecshiftR32Narrow,
7056 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7058 let Inst{19-16} = imm;
7061 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7062 V128, V128, vecshiftR32Narrow,
7063 asm#"2", ".8h", ".4s", []> {
7065 let Inst{19-16} = imm;
7066 let hasSideEffects = 0;
7069 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7070 V64, V128, vecshiftR64Narrow,
7072 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7074 let Inst{20-16} = imm;
7077 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7078 V128, V128, vecshiftR64Narrow,
7079 asm#"2", ".4s", ".2d", []> {
7081 let Inst{20-16} = imm;
7082 let hasSideEffects = 0;
7085 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7086 // themselves, so put them here instead.
7088 // Patterns involving what's effectively an insert high and a normal
7089 // intrinsic, represented by CONCAT_VECTORS.
7090 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7091 vecshiftR16Narrow:$imm)),
7092 (!cast<Instruction>(NAME # "v16i8_shift")
7093 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7094 V128:$Rn, vecshiftR16Narrow:$imm)>;
7095 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7096 vecshiftR32Narrow:$imm)),
7097 (!cast<Instruction>(NAME # "v8i16_shift")
7098 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7099 V128:$Rn, vecshiftR32Narrow:$imm)>;
7100 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7101 vecshiftR64Narrow:$imm)),
7102 (!cast<Instruction>(NAME # "v4i32_shift")
7103 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7104 V128:$Rn, vecshiftR64Narrow:$imm)>;
7107 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7108 SDPatternOperator OpNode> {
7109 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7110 V64, V64, vecshiftL8,
7112 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7113 (i32 vecshiftL8:$imm)))]> {
7115 let Inst{18-16} = imm;
7118 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7119 V128, V128, vecshiftL8,
7120 asm, ".16b", ".16b",
7121 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7122 (i32 vecshiftL8:$imm)))]> {
7124 let Inst{18-16} = imm;
7127 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7128 V64, V64, vecshiftL16,
7130 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7131 (i32 vecshiftL16:$imm)))]> {
7133 let Inst{19-16} = imm;
7136 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7137 V128, V128, vecshiftL16,
7139 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7140 (i32 vecshiftL16:$imm)))]> {
7142 let Inst{19-16} = imm;
7145 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7146 V64, V64, vecshiftL32,
7148 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7149 (i32 vecshiftL32:$imm)))]> {
7151 let Inst{20-16} = imm;
7154 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7155 V128, V128, vecshiftL32,
7157 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7158 (i32 vecshiftL32:$imm)))]> {
7160 let Inst{20-16} = imm;
7163 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7164 V128, V128, vecshiftL64,
7166 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7167 (i32 vecshiftL64:$imm)))]> {
7169 let Inst{21-16} = imm;
7173 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7174 SDPatternOperator OpNode> {
7175 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7176 V64, V64, vecshiftR8,
7178 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7179 (i32 vecshiftR8:$imm)))]> {
7181 let Inst{18-16} = imm;
7184 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7185 V128, V128, vecshiftR8,
7186 asm, ".16b", ".16b",
7187 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7188 (i32 vecshiftR8:$imm)))]> {
7190 let Inst{18-16} = imm;
7193 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7194 V64, V64, vecshiftR16,
7196 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7197 (i32 vecshiftR16:$imm)))]> {
7199 let Inst{19-16} = imm;
7202 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7203 V128, V128, vecshiftR16,
7205 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7206 (i32 vecshiftR16:$imm)))]> {
7208 let Inst{19-16} = imm;
7211 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7212 V64, V64, vecshiftR32,
7214 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7215 (i32 vecshiftR32:$imm)))]> {
7217 let Inst{20-16} = imm;
7220 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7221 V128, V128, vecshiftR32,
7223 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7224 (i32 vecshiftR32:$imm)))]> {
7226 let Inst{20-16} = imm;
7229 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7230 V128, V128, vecshiftR64,
7232 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7233 (i32 vecshiftR64:$imm)))]> {
7235 let Inst{21-16} = imm;
7239 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7240 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7241 SDPatternOperator OpNode = null_frag> {
7242 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7243 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7244 [(set (v8i8 V64:$dst),
7245 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7246 (i32 vecshiftR8:$imm)))]> {
7248 let Inst{18-16} = imm;
7251 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7252 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7253 [(set (v16i8 V128:$dst),
7254 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7255 (i32 vecshiftR8:$imm)))]> {
7257 let Inst{18-16} = imm;
7260 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7261 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7262 [(set (v4i16 V64:$dst),
7263 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7264 (i32 vecshiftR16:$imm)))]> {
7266 let Inst{19-16} = imm;
7269 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7270 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7271 [(set (v8i16 V128:$dst),
7272 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7273 (i32 vecshiftR16:$imm)))]> {
7275 let Inst{19-16} = imm;
7278 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7279 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7280 [(set (v2i32 V64:$dst),
7281 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7282 (i32 vecshiftR32:$imm)))]> {
7284 let Inst{20-16} = imm;
7287 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7288 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7289 [(set (v4i32 V128:$dst),
7290 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7291 (i32 vecshiftR32:$imm)))]> {
7293 let Inst{20-16} = imm;
7296 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7297 V128, V128, vecshiftR64,
7298 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7299 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7300 (i32 vecshiftR64:$imm)))]> {
7302 let Inst{21-16} = imm;
7306 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7307 SDPatternOperator OpNode = null_frag> {
7308 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7309 V64, V64, vecshiftL8,
7311 [(set (v8i8 V64:$dst),
7312 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7313 (i32 vecshiftL8:$imm)))]> {
7315 let Inst{18-16} = imm;
7318 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7319 V128, V128, vecshiftL8,
7320 asm, ".16b", ".16b",
7321 [(set (v16i8 V128:$dst),
7322 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7323 (i32 vecshiftL8:$imm)))]> {
7325 let Inst{18-16} = imm;
7328 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7329 V64, V64, vecshiftL16,
7331 [(set (v4i16 V64:$dst),
7332 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7333 (i32 vecshiftL16:$imm)))]> {
7335 let Inst{19-16} = imm;
7338 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7339 V128, V128, vecshiftL16,
7341 [(set (v8i16 V128:$dst),
7342 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7343 (i32 vecshiftL16:$imm)))]> {
7345 let Inst{19-16} = imm;
7348 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7349 V64, V64, vecshiftL32,
7351 [(set (v2i32 V64:$dst),
7352 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7353 (i32 vecshiftL32:$imm)))]> {
7355 let Inst{20-16} = imm;
7358 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7359 V128, V128, vecshiftL32,
7361 [(set (v4i32 V128:$dst),
7362 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7363 (i32 vecshiftL32:$imm)))]> {
7365 let Inst{20-16} = imm;
7368 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7369 V128, V128, vecshiftL64,
7371 [(set (v2i64 V128:$dst),
7372 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7373 (i32 vecshiftL64:$imm)))]> {
7375 let Inst{21-16} = imm;
7379 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7380 SDPatternOperator OpNode> {
7381 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7382 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7383 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7385 let Inst{18-16} = imm;
7388 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7389 V128, V128, vecshiftL8,
7390 asm#"2", ".8h", ".16b",
7391 [(set (v8i16 V128:$Rd),
7392 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7394 let Inst{18-16} = imm;
7397 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7398 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7399 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7401 let Inst{19-16} = imm;
7404 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7405 V128, V128, vecshiftL16,
7406 asm#"2", ".4s", ".8h",
7407 [(set (v4i32 V128:$Rd),
7408 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7411 let Inst{19-16} = imm;
7414 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7415 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7416 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7418 let Inst{20-16} = imm;
7421 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7422 V128, V128, vecshiftL32,
7423 asm#"2", ".2d", ".4s",
7424 [(set (v2i64 V128:$Rd),
7425 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7427 let Inst{20-16} = imm;
7433 // Vector load/store
7435 // SIMD ldX/stX no-index memory references don't allow the optional
7436 // ", #0" constant and handle post-indexing explicitly, so we use
7437 // a more specialized parse method for them. Otherwise, it's the same as
7438 // the general am_noindex handling.
7440 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7441 string asm, dag oops, dag iops, list<dag> pattern>
7442 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7447 let Inst{29-23} = 0b0011000;
7449 let Inst{21-16} = 0b000000;
7450 let Inst{15-12} = opcode;
7451 let Inst{11-10} = size;
7452 let Inst{9-5} = vaddr;
7456 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7457 string asm, dag oops, dag iops>
7458 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "$vaddr = $wback", []> {
7464 let Inst{29-23} = 0b0011001;
7467 let Inst{20-16} = Xm;
7468 let Inst{15-12} = opcode;
7469 let Inst{11-10} = size;
7470 let Inst{9-5} = vaddr;
7474 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7475 // register post-index addressing from the zero register.
7476 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7477 int Offset, int Size> {
7478 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7479 // "ld1\t$Vt, $vaddr, #16"
7480 // may get mapped to
7481 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7482 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7483 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7484 am_simdnoindex:$vaddr,
7485 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7488 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7489 // "ld1.8b\t$Vt, $vaddr, #16"
7490 // may get mapped to
7491 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7492 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7493 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7494 am_simdnoindex:$vaddr,
7495 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7498 // E.g. "ld1.8b { v0, v1 }, [x1]"
7499 // "ld1\t$Vt, $vaddr"
7500 // may get mapped to
7501 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7502 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7503 (!cast<Instruction>(NAME # Count # "v" # layout)
7504 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7505 am_simdnoindex:$vaddr), 0>;
7507 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7508 // "ld1\t$Vt, $vaddr, $Xm"
7509 // may get mapped to
7510 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7511 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7512 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7513 am_simdnoindex:$vaddr,
7514 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7515 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7518 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7519 int Offset64, bits<4> opcode> {
7520 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7521 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7522 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7523 (ins am_simdnoindex:$vaddr), []>;
7524 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7525 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7526 (ins am_simdnoindex:$vaddr), []>;
7527 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7528 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7529 (ins am_simdnoindex:$vaddr), []>;
7530 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7531 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7532 (ins am_simdnoindex:$vaddr), []>;
7533 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7534 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7535 (ins am_simdnoindex:$vaddr), []>;
7536 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7537 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7538 (ins am_simdnoindex:$vaddr), []>;
7539 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7540 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7541 (ins am_simdnoindex:$vaddr), []>;
7544 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7545 (outs am_simdnoindex:$wback,
7546 !cast<RegisterOperand>(veclist # "16b"):$Vt),
7547 (ins am_simdnoindex:$vaddr,
7548 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7549 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7550 (outs am_simdnoindex:$wback,
7551 !cast<RegisterOperand>(veclist # "8h"):$Vt),
7552 (ins am_simdnoindex:$vaddr,
7553 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7554 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7555 (outs am_simdnoindex:$wback,
7556 !cast<RegisterOperand>(veclist # "4s"):$Vt),
7557 (ins am_simdnoindex:$vaddr,
7558 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7559 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7560 (outs am_simdnoindex:$wback,
7561 !cast<RegisterOperand>(veclist # "2d"):$Vt),
7562 (ins am_simdnoindex:$vaddr,
7563 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7564 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7565 (outs am_simdnoindex:$wback,
7566 !cast<RegisterOperand>(veclist # "8b"):$Vt),
7567 (ins am_simdnoindex:$vaddr,
7568 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7569 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7570 (outs am_simdnoindex:$wback,
7571 !cast<RegisterOperand>(veclist # "4h"):$Vt),
7572 (ins am_simdnoindex:$vaddr,
7573 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7574 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7575 (outs am_simdnoindex:$wback,
7576 !cast<RegisterOperand>(veclist # "2s"):$Vt),
7577 (ins am_simdnoindex:$vaddr,
7578 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7581 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7582 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7583 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7584 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7585 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7586 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7587 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7590 // Only ld1/st1 has a v1d version.
7591 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7592 int Offset64, bits<4> opcode> {
7593 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7594 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7595 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7596 am_simdnoindex:$vaddr), []>;
7597 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7598 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7599 am_simdnoindex:$vaddr), []>;
7600 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7601 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7602 am_simdnoindex:$vaddr), []>;
7603 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7604 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7605 am_simdnoindex:$vaddr), []>;
7606 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7607 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7608 am_simdnoindex:$vaddr), []>;
7609 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7610 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7611 am_simdnoindex:$vaddr), []>;
7612 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7613 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7614 am_simdnoindex:$vaddr), []>;
7616 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7617 (outs am_simdnoindex:$wback),
7618 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7619 am_simdnoindex:$vaddr,
7620 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7621 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7622 (outs am_simdnoindex:$wback),
7623 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7624 am_simdnoindex:$vaddr,
7625 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7626 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7627 (outs am_simdnoindex:$wback),
7628 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7629 am_simdnoindex:$vaddr,
7630 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7631 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7632 (outs am_simdnoindex:$wback),
7633 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7634 am_simdnoindex:$vaddr,
7635 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7636 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7637 (outs am_simdnoindex:$wback),
7638 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7639 am_simdnoindex:$vaddr,
7640 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7641 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7642 (outs am_simdnoindex:$wback),
7643 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7644 am_simdnoindex:$vaddr,
7645 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7646 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7647 (outs am_simdnoindex:$wback),
7648 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7649 am_simdnoindex:$vaddr,
7650 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7653 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7654 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7655 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7656 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7657 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7658 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7659 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7662 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7663 int Offset128, int Offset64, bits<4> opcode>
7664 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7666 // LD1 instructions have extra "1d" variants.
7667 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7668 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7669 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7670 (ins am_simdnoindex:$vaddr), []>;
7672 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7673 (outs am_simdnoindex:$wback,
7674 !cast<RegisterOperand>(veclist # "1d"):$Vt),
7675 (ins am_simdnoindex:$vaddr,
7676 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7679 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7682 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7683 int Offset128, int Offset64, bits<4> opcode>
7684 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7686 // ST1 instructions have extra "1d" variants.
7687 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7688 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7689 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7690 am_simdnoindex:$vaddr), []>;
7692 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
7693 (outs am_simdnoindex:$wback),
7694 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7695 am_simdnoindex:$vaddr,
7696 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7699 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7702 multiclass SIMDLd1Multiple<string asm> {
7703 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7704 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7705 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7706 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7709 multiclass SIMDSt1Multiple<string asm> {
7710 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7711 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7712 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7713 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7716 multiclass SIMDLd2Multiple<string asm> {
7717 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7720 multiclass SIMDSt2Multiple<string asm> {
7721 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7724 multiclass SIMDLd3Multiple<string asm> {
7725 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7728 multiclass SIMDSt3Multiple<string asm> {
7729 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7732 multiclass SIMDLd4Multiple<string asm> {
7733 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7736 multiclass SIMDSt4Multiple<string asm> {
7737 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7741 // AdvSIMD Load/store single-element
7744 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7745 string asm, string operands, string cst,
7746 dag oops, dag iops, list<dag> pattern>
7747 : I<oops, iops, asm, operands, cst, pattern> {
7751 let Inst{29-24} = 0b001101;
7754 let Inst{15-13} = opcode;
7755 let Inst{9-5} = vaddr;
7759 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7760 string asm, string operands, string cst,
7761 dag oops, dag iops, list<dag> pattern>
7762 : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
7766 let Inst{29-24} = 0b001101;
7769 let Inst{15-13} = opcode;
7770 let Inst{9-5} = vaddr;
7775 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7776 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7778 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr", "",
7779 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr),
7783 let Inst{20-16} = 0b00000;
7785 let Inst{11-10} = size;
7787 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7788 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7789 string asm, Operand listtype, Operand GPR64pi>
7790 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7792 (outs am_simdnoindex:$wback, listtype:$Vt),
7793 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7797 let Inst{20-16} = Xm;
7799 let Inst{11-10} = size;
7802 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7803 int Offset, int Size> {
7804 // E.g. "ld1r { v0.8b }, [x1], #1"
7805 // "ld1r.8b\t$Vt, $vaddr, #1"
7806 // may get mapped to
7807 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7808 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7809 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7810 am_simdnoindex:$vaddr,
7811 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7814 // E.g. "ld1r.8b { v0 }, [x1], #1"
7815 // "ld1r.8b\t$Vt, $vaddr, #1"
7816 // may get mapped to
7817 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7818 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7819 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7820 am_simdnoindex:$vaddr,
7821 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7824 // E.g. "ld1r.8b { v0 }, [x1]"
7825 // "ld1r.8b\t$Vt, $vaddr"
7826 // may get mapped to
7827 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7828 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7829 (!cast<Instruction>(NAME # "v" # layout)
7830 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7831 am_simdnoindex:$vaddr), 0>;
7833 // E.g. "ld1r.8b { v0 }, [x1], x2"
7834 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7835 // may get mapped to
7836 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7837 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7838 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7839 am_simdnoindex:$vaddr,
7840 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7841 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7844 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7845 int Offset1, int Offset2, int Offset4, int Offset8> {
7846 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7847 !cast<Operand>("VecList" # Count # "8b")>;
7848 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7849 !cast<Operand>("VecList" # Count #"16b")>;
7850 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7851 !cast<Operand>("VecList" # Count #"4h")>;
7852 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7853 !cast<Operand>("VecList" # Count #"8h")>;
7854 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7855 !cast<Operand>("VecList" # Count #"2s")>;
7856 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7857 !cast<Operand>("VecList" # Count #"4s")>;
7858 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7859 !cast<Operand>("VecList" # Count #"1d")>;
7860 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7861 !cast<Operand>("VecList" # Count #"2d")>;
7863 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7864 !cast<Operand>("VecList" # Count # "8b"),
7865 !cast<Operand>("GPR64pi" # Offset1)>;
7866 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7867 !cast<Operand>("VecList" # Count # "16b"),
7868 !cast<Operand>("GPR64pi" # Offset1)>;
7869 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7870 !cast<Operand>("VecList" # Count # "4h"),
7871 !cast<Operand>("GPR64pi" # Offset2)>;
7872 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7873 !cast<Operand>("VecList" # Count # "8h"),
7874 !cast<Operand>("GPR64pi" # Offset2)>;
7875 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7876 !cast<Operand>("VecList" # Count # "2s"),
7877 !cast<Operand>("GPR64pi" # Offset4)>;
7878 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7879 !cast<Operand>("VecList" # Count # "4s"),
7880 !cast<Operand>("GPR64pi" # Offset4)>;
7881 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7882 !cast<Operand>("VecList" # Count # "1d"),
7883 !cast<Operand>("GPR64pi" # Offset8)>;
7884 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7885 !cast<Operand>("VecList" # Count # "2d"),
7886 !cast<Operand>("GPR64pi" # Offset8)>;
7888 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7889 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7890 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7891 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7892 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7893 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7894 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7895 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7898 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7899 dag oops, dag iops, list<dag> pattern>
7900 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
7902 // idx encoded in Q:S:size fields.
7904 let Inst{30} = idx{3};
7906 let Inst{20-16} = 0b00000;
7907 let Inst{12} = idx{2};
7908 let Inst{11-10} = idx{1-0};
7910 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7911 dag oops, dag iops, list<dag> pattern>
7912 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
7913 oops, iops, pattern> {
7914 // idx encoded in Q:S:size fields.
7916 let Inst{30} = idx{3};
7918 let Inst{20-16} = 0b00000;
7919 let Inst{12} = idx{2};
7920 let Inst{11-10} = idx{1-0};
7922 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7924 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7925 "$vaddr = $wback", oops, iops, []> {
7926 // idx encoded in Q:S:size fields.
7929 let Inst{30} = idx{3};
7931 let Inst{20-16} = Xm;
7932 let Inst{12} = idx{2};
7933 let Inst{11-10} = idx{1-0};
7935 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7937 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7938 "$vaddr = $wback", oops, iops, []> {
7939 // idx encoded in Q:S:size fields.
7942 let Inst{30} = idx{3};
7944 let Inst{20-16} = Xm;
7945 let Inst{12} = idx{2};
7946 let Inst{11-10} = idx{1-0};
7949 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7950 dag oops, dag iops, list<dag> pattern>
7951 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
7953 // idx encoded in Q:S:size<1> fields.
7955 let Inst{30} = idx{2};
7957 let Inst{20-16} = 0b00000;
7958 let Inst{12} = idx{1};
7959 let Inst{11} = idx{0};
7960 let Inst{10} = size;
7962 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7963 dag oops, dag iops, list<dag> pattern>
7964 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
7965 oops, iops, pattern> {
7966 // idx encoded in Q:S:size<1> fields.
7968 let Inst{30} = idx{2};
7970 let Inst{20-16} = 0b00000;
7971 let Inst{12} = idx{1};
7972 let Inst{11} = idx{0};
7973 let Inst{10} = size;
7976 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7978 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7979 "$vaddr = $wback", oops, iops, []> {
7980 // idx encoded in Q:S:size<1> fields.
7983 let Inst{30} = idx{2};
7985 let Inst{20-16} = Xm;
7986 let Inst{12} = idx{1};
7987 let Inst{11} = idx{0};
7988 let Inst{10} = size;
7990 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7992 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7993 "$vaddr = $wback", oops, iops, []> {
7994 // idx encoded in Q:S:size<1> fields.
7997 let Inst{30} = idx{2};
7999 let Inst{20-16} = Xm;
8000 let Inst{12} = idx{1};
8001 let Inst{11} = idx{0};
8002 let Inst{10} = size;
8004 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8005 dag oops, dag iops, list<dag> pattern>
8006 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
8008 // idx encoded in Q:S fields.
8010 let Inst{30} = idx{1};
8012 let Inst{20-16} = 0b00000;
8013 let Inst{12} = idx{0};
8014 let Inst{11-10} = size;
8016 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8017 dag oops, dag iops, list<dag> pattern>
8018 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
8019 oops, iops, pattern> {
8020 // idx encoded in Q:S fields.
8022 let Inst{30} = idx{1};
8024 let Inst{20-16} = 0b00000;
8025 let Inst{12} = idx{0};
8026 let Inst{11-10} = size;
8028 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8029 string asm, dag oops, dag iops>
8030 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8031 "$vaddr = $wback", oops, iops, []> {
8032 // idx encoded in Q:S fields.
8035 let Inst{30} = idx{1};
8037 let Inst{20-16} = Xm;
8038 let Inst{12} = idx{0};
8039 let Inst{11-10} = size;
8041 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8042 string asm, dag oops, dag iops>
8043 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8044 "$vaddr = $wback", oops, iops, []> {
8045 // idx encoded in Q:S fields.
8048 let Inst{30} = idx{1};
8050 let Inst{20-16} = Xm;
8051 let Inst{12} = idx{0};
8052 let Inst{11-10} = size;
8054 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8055 dag oops, dag iops, list<dag> pattern>
8056 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
8058 // idx encoded in Q field.
8062 let Inst{20-16} = 0b00000;
8064 let Inst{11-10} = size;
8066 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8067 dag oops, dag iops, list<dag> pattern>
8068 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
8069 oops, iops, pattern> {
8070 // idx encoded in Q field.
8074 let Inst{20-16} = 0b00000;
8076 let Inst{11-10} = size;
8078 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8079 string asm, dag oops, dag iops>
8080 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8081 "$vaddr = $wback", oops, iops, []> {
8082 // idx encoded in Q field.
8087 let Inst{20-16} = Xm;
8089 let Inst{11-10} = size;
8091 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8092 string asm, dag oops, dag iops>
8093 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8094 "$vaddr = $wback", oops, iops, []> {
8095 // idx encoded in Q field.
8100 let Inst{20-16} = Xm;
8102 let Inst{11-10} = size;
8105 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8106 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8107 RegisterOperand listtype,
8108 RegisterOperand GPR64pi> {
8109 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8110 (outs listtype:$dst),
8111 (ins listtype:$Vt, VectorIndexB:$idx,
8112 am_simdnoindex:$vaddr), []>;
8114 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8115 (outs am_simdnoindex:$wback, listtype:$dst),
8116 (ins listtype:$Vt, VectorIndexB:$idx,
8117 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8119 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8120 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8121 RegisterOperand listtype,
8122 RegisterOperand GPR64pi> {
8123 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8124 (outs listtype:$dst),
8125 (ins listtype:$Vt, VectorIndexH:$idx,
8126 am_simdnoindex:$vaddr), []>;
8128 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8129 (outs am_simdnoindex:$wback, listtype:$dst),
8130 (ins listtype:$Vt, VectorIndexH:$idx,
8131 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8133 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8134 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8135 RegisterOperand listtype,
8136 RegisterOperand GPR64pi> {
8137 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8138 (outs listtype:$dst),
8139 (ins listtype:$Vt, VectorIndexS:$idx,
8140 am_simdnoindex:$vaddr), []>;
8142 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8143 (outs am_simdnoindex:$wback, listtype:$dst),
8144 (ins listtype:$Vt, VectorIndexS:$idx,
8145 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8147 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8148 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8149 RegisterOperand listtype, RegisterOperand GPR64pi> {
8150 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8151 (outs listtype:$dst),
8152 (ins listtype:$Vt, VectorIndexD:$idx,
8153 am_simdnoindex:$vaddr), []>;
8155 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8156 (outs am_simdnoindex:$wback, listtype:$dst),
8157 (ins listtype:$Vt, VectorIndexD:$idx,
8158 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8160 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8161 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8162 RegisterOperand listtype, RegisterOperand GPR64pi> {
8163 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8164 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8165 am_simdnoindex:$vaddr), []>;
8167 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8168 (outs am_simdnoindex:$wback),
8169 (ins listtype:$Vt, VectorIndexB:$idx,
8170 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8172 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8173 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8174 RegisterOperand listtype, RegisterOperand GPR64pi> {
8175 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8176 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8177 am_simdnoindex:$vaddr), []>;
8179 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8180 (outs am_simdnoindex:$wback),
8181 (ins listtype:$Vt, VectorIndexH:$idx,
8182 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8184 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8185 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8186 RegisterOperand listtype, RegisterOperand GPR64pi> {
8187 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8188 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8189 am_simdnoindex:$vaddr), []>;
8191 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8192 (outs am_simdnoindex:$wback),
8193 (ins listtype:$Vt, VectorIndexS:$idx,
8194 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8196 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8197 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8198 RegisterOperand listtype, RegisterOperand GPR64pi> {
8199 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8200 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8201 am_simdnoindex:$vaddr), []>;
8203 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8204 (outs am_simdnoindex:$wback),
8205 (ins listtype:$Vt, VectorIndexD:$idx,
8206 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8209 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8210 string Count, int Offset, Operand idxtype> {
8211 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8212 // "ld1\t$Vt, $vaddr, #1"
8213 // may get mapped to
8214 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8215 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8216 (!cast<Instruction>(NAME # Type # "_POST")
8217 am_simdnoindex:$vaddr,
8218 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8219 idxtype:$idx, XZR), 1>;
8221 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8222 // "ld1.8b\t$Vt, $vaddr, #1"
8223 // may get mapped to
8224 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8225 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8226 (!cast<Instruction>(NAME # Type # "_POST")
8227 am_simdnoindex:$vaddr,
8228 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8229 idxtype:$idx, XZR), 0>;
8231 // E.g. "ld1.8b { v0 }[0], [x1]"
8232 // "ld1.8b\t$Vt, $vaddr"
8233 // may get mapped to
8234 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8235 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8236 (!cast<Instruction>(NAME # Type)
8237 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8238 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8240 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8241 // "ld1.8b\t$Vt, $vaddr, $Xm"
8242 // may get mapped to
8243 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8244 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8245 (!cast<Instruction>(NAME # Type # "_POST")
8246 am_simdnoindex:$vaddr,
8247 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8249 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8252 multiclass SIMDLdSt1SingleAliases<string asm> {
8253 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8254 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8255 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8256 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8259 multiclass SIMDLdSt2SingleAliases<string asm> {
8260 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8261 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8262 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8263 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8266 multiclass SIMDLdSt3SingleAliases<string asm> {
8267 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8268 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8269 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8270 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8273 multiclass SIMDLdSt4SingleAliases<string asm> {
8274 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8275 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8276 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8277 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8279 } // end of 'let Predicates = [HasNEON]'
8281 //----------------------------------------------------------------------------
8282 // Crypto extensions
8283 //----------------------------------------------------------------------------
8285 let Predicates = [HasCrypto] in {
8286 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8287 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8289 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8293 let Inst{31-16} = 0b0100111000101000;
8294 let Inst{15-12} = opc;
8295 let Inst{11-10} = 0b10;
8300 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8301 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8302 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8304 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8305 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8307 [(set (v16i8 V128:$dst),
8308 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8310 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8311 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8312 dag oops, dag iops, list<dag> pat>
8313 : I<oops, iops, asm,
8314 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8315 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8320 let Inst{31-21} = 0b01011110000;
8321 let Inst{20-16} = Rm;
8323 let Inst{14-12} = opc;
8324 let Inst{11-10} = 0b00;
8329 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8330 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8331 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8332 [(set (v4i32 FPR128:$dst),
8333 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8334 (v4i32 V128:$Rm)))]>;
8336 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8337 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8338 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8339 [(set (v4i32 V128:$dst),
8340 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8341 (v4i32 V128:$Rm)))]>;
8343 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8344 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8345 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8346 [(set (v4i32 FPR128:$dst),
8347 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8348 (v4i32 V128:$Rm)))]>;
8350 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8351 class SHA2OpInst<bits<4> opc, string asm, string kind,
8352 string cstr, dag oops, dag iops,
8354 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8355 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8359 let Inst{31-16} = 0b0101111000101000;
8360 let Inst{15-12} = opc;
8361 let Inst{11-10} = 0b10;
8366 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8367 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8368 (ins V128:$Rd, V128:$Rn),
8369 [(set (v4i32 V128:$dst),
8370 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8372 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8373 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8374 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8375 } // end of 'let Predicates = [HasCrypto]'
8377 // Allow the size specifier tokens to be upper case, not just lower.
8378 def : TokenAlias<".8B", ".8b">;
8379 def : TokenAlias<".4H", ".4h">;
8380 def : TokenAlias<".2S", ".2s">;
8381 def : TokenAlias<".1D", ".1d">;
8382 def : TokenAlias<".16B", ".16b">;
8383 def : TokenAlias<".8H", ".8h">;
8384 def : TokenAlias<".4S", ".4s">;
8385 def : TokenAlias<".2D", ".2d">;
8386 def : TokenAlias<".1Q", ".1q">;
8387 def : TokenAlias<".B", ".b">;
8388 def : TokenAlias<".H", ".h">;
8389 def : TokenAlias<".S", ".s">;
8390 def : TokenAlias<".D", ".d">;
8391 def : TokenAlias<".Q", ".q">;