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 { let Name = "Extend"; }
129 def ExtendOperand64 : AsmOperandClass {
130 let SuperClasses = [ExtendOperand];
131 let Name = "Extend64";
133 // 'extend' that's a lsl of a 64-bit register.
134 def ExtendOperandLSL64 : AsmOperandClass {
135 let SuperClasses = [ExtendOperand];
136 let Name = "ExtendLSL64";
139 // 8-bit floating-point immediate encodings.
140 def FPImmOperand : AsmOperandClass {
142 let ParserMethod = "tryParseFPImm";
145 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
146 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
147 // are encoded as the eight bit value 'abcdefgh'.
148 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
151 //===----------------------------------------------------------------------===//
152 // Operand Definitions.
155 // ADR[P] instruction labels.
156 def AdrpOperand : AsmOperandClass {
157 let Name = "AdrpLabel";
158 let ParserMethod = "tryParseAdrpLabel";
159 let DiagnosticType = "InvalidLabel";
161 def adrplabel : Operand<i64> {
162 let EncoderMethod = "getAdrLabelOpValue";
163 let PrintMethod = "printAdrpLabel";
164 let ParserMatchClass = AdrpOperand;
167 def AdrOperand : AsmOperandClass {
168 let Name = "AdrLabel";
169 let ParserMethod = "tryParseAdrLabel";
170 let DiagnosticType = "InvalidLabel";
172 def adrlabel : Operand<i64> {
173 let EncoderMethod = "getAdrLabelOpValue";
174 let ParserMatchClass = AdrOperand;
177 // simm9 predicate - True if the immediate is in the range [-256, 255].
178 def SImm9Operand : AsmOperandClass {
180 let DiagnosticType = "InvalidMemoryIndexedSImm9";
182 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
183 let ParserMatchClass = SImm9Operand;
186 // simm7s4 predicate - True if the immediate is a multiple of 4 in the range
188 def SImm7s4Operand : AsmOperandClass {
189 let Name = "SImm7s4";
190 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
192 def simm7s4 : Operand<i32> {
193 let ParserMatchClass = SImm7s4Operand;
194 let PrintMethod = "printImmScale4";
197 // simm7s8 predicate - True if the immediate is a multiple of 8 in the range
199 def SImm7s8Operand : AsmOperandClass {
200 let Name = "SImm7s8";
201 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
203 def simm7s8 : Operand<i32> {
204 let ParserMatchClass = SImm7s8Operand;
205 let PrintMethod = "printImmScale8";
208 // simm7s16 predicate - True if the immediate is a multiple of 16 in the range
210 def SImm7s16Operand : AsmOperandClass {
211 let Name = "SImm7s16";
212 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
214 def simm7s16 : Operand<i32> {
215 let ParserMatchClass = SImm7s16Operand;
216 let PrintMethod = "printImmScale16";
219 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
220 def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
221 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
222 return ((uint32_t)Imm) < 65536;
224 let ParserMatchClass = Imm0_65535Operand;
227 def Imm1_8Operand : AsmOperandClass {
229 let DiagnosticType = "InvalidImm1_8";
231 def Imm1_16Operand : AsmOperandClass {
232 let Name = "Imm1_16";
233 let DiagnosticType = "InvalidImm1_16";
235 def Imm1_32Operand : AsmOperandClass {
236 let Name = "Imm1_32";
237 let DiagnosticType = "InvalidImm1_32";
239 def Imm1_64Operand : AsmOperandClass {
240 let Name = "Imm1_64";
241 let DiagnosticType = "InvalidImm1_64";
244 def MovZSymbolG3AsmOperand : AsmOperandClass {
245 let Name = "MovZSymbolG3";
246 let RenderMethod = "addImmOperands";
249 def movz_symbol_g3 : Operand<i32> {
250 let ParserMatchClass = MovZSymbolG3AsmOperand;
253 def MovZSymbolG2AsmOperand : AsmOperandClass {
254 let Name = "MovZSymbolG2";
255 let RenderMethod = "addImmOperands";
258 def movz_symbol_g2 : Operand<i32> {
259 let ParserMatchClass = MovZSymbolG2AsmOperand;
262 def MovZSymbolG1AsmOperand : AsmOperandClass {
263 let Name = "MovZSymbolG1";
264 let RenderMethod = "addImmOperands";
267 def movz_symbol_g1 : Operand<i32> {
268 let ParserMatchClass = MovZSymbolG1AsmOperand;
271 def MovZSymbolG0AsmOperand : AsmOperandClass {
272 let Name = "MovZSymbolG0";
273 let RenderMethod = "addImmOperands";
276 def movz_symbol_g0 : Operand<i32> {
277 let ParserMatchClass = MovZSymbolG0AsmOperand;
280 def MovKSymbolG2AsmOperand : AsmOperandClass {
281 let Name = "MovKSymbolG2";
282 let RenderMethod = "addImmOperands";
285 def movk_symbol_g2 : Operand<i32> {
286 let ParserMatchClass = MovKSymbolG2AsmOperand;
289 def MovKSymbolG1AsmOperand : AsmOperandClass {
290 let Name = "MovKSymbolG1";
291 let RenderMethod = "addImmOperands";
294 def movk_symbol_g1 : Operand<i32> {
295 let ParserMatchClass = MovKSymbolG1AsmOperand;
298 def MovKSymbolG0AsmOperand : AsmOperandClass {
299 let Name = "MovKSymbolG0";
300 let RenderMethod = "addImmOperands";
303 def movk_symbol_g0 : Operand<i32> {
304 let ParserMatchClass = MovKSymbolG0AsmOperand;
307 class fixedpoint_i32<ValueType FloatVT>
309 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
310 let EncoderMethod = "getFixedPointScaleOpValue";
311 let DecoderMethod = "DecodeFixedPointScaleImm32";
312 let ParserMatchClass = Imm1_32Operand;
315 class fixedpoint_i64<ValueType FloatVT>
317 ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
318 let EncoderMethod = "getFixedPointScaleOpValue";
319 let DecoderMethod = "DecodeFixedPointScaleImm64";
320 let ParserMatchClass = Imm1_64Operand;
323 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
324 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
326 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
327 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
329 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
330 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
332 let EncoderMethod = "getVecShiftR8OpValue";
333 let DecoderMethod = "DecodeVecShiftR8Imm";
334 let ParserMatchClass = Imm1_8Operand;
336 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
337 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
339 let EncoderMethod = "getVecShiftR16OpValue";
340 let DecoderMethod = "DecodeVecShiftR16Imm";
341 let ParserMatchClass = Imm1_16Operand;
343 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
344 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
346 let EncoderMethod = "getVecShiftR16OpValue";
347 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
348 let ParserMatchClass = Imm1_8Operand;
350 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
351 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
353 let EncoderMethod = "getVecShiftR32OpValue";
354 let DecoderMethod = "DecodeVecShiftR32Imm";
355 let ParserMatchClass = Imm1_32Operand;
357 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
358 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
360 let EncoderMethod = "getVecShiftR32OpValue";
361 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
362 let ParserMatchClass = Imm1_16Operand;
364 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
365 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
367 let EncoderMethod = "getVecShiftR64OpValue";
368 let DecoderMethod = "DecodeVecShiftR64Imm";
369 let ParserMatchClass = Imm1_64Operand;
371 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
372 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
374 let EncoderMethod = "getVecShiftR64OpValue";
375 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
376 let ParserMatchClass = Imm1_32Operand;
379 def Imm0_7Operand : AsmOperandClass { let Name = "Imm0_7"; }
380 def Imm0_15Operand : AsmOperandClass { let Name = "Imm0_15"; }
381 def Imm0_31Operand : AsmOperandClass { let Name = "Imm0_31"; }
382 def Imm0_63Operand : AsmOperandClass { let Name = "Imm0_63"; }
384 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
385 return (((uint32_t)Imm) < 8);
387 let EncoderMethod = "getVecShiftL8OpValue";
388 let DecoderMethod = "DecodeVecShiftL8Imm";
389 let ParserMatchClass = Imm0_7Operand;
391 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
392 return (((uint32_t)Imm) < 16);
394 let EncoderMethod = "getVecShiftL16OpValue";
395 let DecoderMethod = "DecodeVecShiftL16Imm";
396 let ParserMatchClass = Imm0_15Operand;
398 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
399 return (((uint32_t)Imm) < 32);
401 let EncoderMethod = "getVecShiftL32OpValue";
402 let DecoderMethod = "DecodeVecShiftL32Imm";
403 let ParserMatchClass = Imm0_31Operand;
405 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
406 return (((uint32_t)Imm) < 64);
408 let EncoderMethod = "getVecShiftL64OpValue";
409 let DecoderMethod = "DecodeVecShiftL64Imm";
410 let ParserMatchClass = Imm0_63Operand;
414 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
415 // instructions for splatting repeating bit patterns across the immediate.
416 def logical_imm32_XFORM : SDNodeXForm<imm, [{
417 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
418 return CurDAG->getTargetConstant(enc, MVT::i32);
420 def logical_imm64_XFORM : SDNodeXForm<imm, [{
421 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
422 return CurDAG->getTargetConstant(enc, MVT::i32);
425 def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
426 def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
427 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
428 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
429 }], logical_imm32_XFORM> {
430 let PrintMethod = "printLogicalImm32";
431 let ParserMatchClass = LogicalImm32Operand;
433 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
434 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
435 }], logical_imm64_XFORM> {
436 let PrintMethod = "printLogicalImm64";
437 let ParserMatchClass = LogicalImm64Operand;
440 // imm0_255 predicate - True if the immediate is in the range [0,255].
441 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
442 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
443 return ((uint32_t)Imm) < 256;
445 let ParserMatchClass = Imm0_255Operand;
448 // imm0_127 predicate - True if the immediate is in the range [0,127]
449 def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
450 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
451 return ((uint32_t)Imm) < 128;
453 let ParserMatchClass = Imm0_127Operand;
456 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
457 // for all shift-amounts.
459 // imm0_63 predicate - True if the immediate is in the range [0,63]
460 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
461 return ((uint64_t)Imm) < 64;
463 let ParserMatchClass = Imm0_63Operand;
466 // imm0_31 predicate - True if the immediate is in the range [0,31]
467 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
468 return ((uint64_t)Imm) < 32;
470 let ParserMatchClass = Imm0_31Operand;
473 // imm0_15 predicate - True if the immediate is in the range [0,15]
474 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
475 return ((uint64_t)Imm) < 16;
477 let ParserMatchClass = Imm0_15Operand;
480 // imm0_7 predicate - True if the immediate is in the range [0,7]
481 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
482 return ((uint64_t)Imm) < 8;
484 let ParserMatchClass = Imm0_7Operand;
487 // An arithmetic shifter operand:
488 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
490 def arith_shift : Operand<i32> {
491 let PrintMethod = "printShifter";
492 let ParserMatchClass = ArithmeticShifterOperand;
495 class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
497 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
498 let PrintMethod = "printShiftedRegister";
499 let MIOperandInfo = (ops regclass, arith_shift);
502 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
503 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
505 // An arithmetic shifter operand:
506 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
508 def logical_shift : Operand<i32> {
509 let PrintMethod = "printShifter";
510 let ParserMatchClass = ShifterOperand;
513 class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
515 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
516 let PrintMethod = "printShiftedRegister";
517 let MIOperandInfo = (ops regclass, logical_shift);
520 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
521 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
523 // A logical vector shifter operand:
524 // {7-6} - shift type: 00 = lsl
525 // {5-0} - imm6: #0, #8, #16, or #24
526 def logical_vec_shift : Operand<i32> {
527 let PrintMethod = "printShifter";
528 let EncoderMethod = "getVecShifterOpValue";
529 let ParserMatchClass = LogicalVecShifterOperand;
532 // A logical vector half-word shifter operand:
533 // {7-6} - shift type: 00 = lsl
534 // {5-0} - imm6: #0 or #8
535 def logical_vec_hw_shift : Operand<i32> {
536 let PrintMethod = "printShifter";
537 let EncoderMethod = "getVecShifterOpValue";
538 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
541 // A vector move shifter operand:
542 // {0} - imm1: #8 or #16
543 def move_vec_shift : Operand<i32> {
544 let PrintMethod = "printShifter";
545 let EncoderMethod = "getMoveVecShifterOpValue";
546 let ParserMatchClass = MoveVecShifterOperand;
549 // An ADD/SUB immediate shifter operand:
550 // {7-6} - shift type: 00 = lsl
551 // {5-0} - imm6: #0 or #12
552 def addsub_shift : Operand<i32> {
553 let ParserMatchClass = AddSubShifterOperand;
556 class addsub_shifted_imm<ValueType Ty>
557 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
558 let PrintMethod = "printAddSubImm";
559 let EncoderMethod = "getAddSubImmOpValue";
560 let MIOperandInfo = (ops i32imm, addsub_shift);
563 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
564 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
566 class neg_addsub_shifted_imm<ValueType Ty>
567 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
568 let PrintMethod = "printAddSubImm";
569 let EncoderMethod = "getAddSubImmOpValue";
570 let MIOperandInfo = (ops i32imm, addsub_shift);
573 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
574 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
576 // An extend operand:
577 // {5-3} - extend type
579 def arith_extend : Operand<i32> {
580 let PrintMethod = "printExtend";
581 let ParserMatchClass = ExtendOperand;
583 def arith_extend64 : Operand<i32> {
584 let PrintMethod = "printExtend";
585 let ParserMatchClass = ExtendOperand64;
588 // 'extend' that's a lsl of a 64-bit register.
589 def arith_extendlsl64 : Operand<i32> {
590 let PrintMethod = "printExtend";
591 let ParserMatchClass = ExtendOperandLSL64;
594 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
595 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
596 let PrintMethod = "printExtendedRegister";
597 let MIOperandInfo = (ops GPR32, arith_extend);
600 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
601 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
602 let PrintMethod = "printExtendedRegister";
603 let MIOperandInfo = (ops GPR32, arith_extend64);
606 // Floating-point immediate.
607 def fpimm32 : Operand<f32>,
608 PatLeaf<(f32 fpimm), [{
609 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
610 }], SDNodeXForm<fpimm, [{
611 APFloat InVal = N->getValueAPF();
612 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
613 return CurDAG->getTargetConstant(enc, MVT::i32);
615 let ParserMatchClass = FPImmOperand;
616 let PrintMethod = "printFPImmOperand";
618 def fpimm64 : Operand<f64>,
619 PatLeaf<(f64 fpimm), [{
620 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
621 }], SDNodeXForm<fpimm, [{
622 APFloat InVal = N->getValueAPF();
623 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
624 return CurDAG->getTargetConstant(enc, MVT::i32);
626 let ParserMatchClass = FPImmOperand;
627 let PrintMethod = "printFPImmOperand";
630 def fpimm8 : Operand<i32> {
631 let ParserMatchClass = FPImmOperand;
632 let PrintMethod = "printFPImmOperand";
635 def fpimm0 : PatLeaf<(fpimm), [{
636 return N->isExactlyValue(+0.0);
639 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
640 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
641 // are encoded as the eight bit value 'abcdefgh'.
642 def simdimmtype10 : Operand<i32>,
643 PatLeaf<(f64 fpimm), [{
644 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
647 }], SDNodeXForm<fpimm, [{
648 APFloat InVal = N->getValueAPF();
649 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
652 return CurDAG->getTargetConstant(enc, MVT::i32);
654 let ParserMatchClass = SIMDImmType10Operand;
655 let PrintMethod = "printSIMDType10Operand";
663 // Base encoding for system instruction operands.
664 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
665 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
666 : I<oops, iops, asm, operands, "", []> {
667 let Inst{31-22} = 0b1101010100;
671 // System instructions which do not have an Rt register.
672 class SimpleSystemI<bit L, dag iops, string asm, string operands>
673 : BaseSystemI<L, (outs), iops, asm, operands> {
674 let Inst{4-0} = 0b11111;
677 // System instructions which have an Rt register.
678 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
679 : BaseSystemI<L, oops, iops, asm, operands>,
685 // Hint instructions that take both a CRm and a 3-bit immediate.
686 class HintI<string mnemonic>
687 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
690 let Inst{20-12} = 0b000110010;
691 let Inst{11-5} = imm;
694 // System instructions taking a single literal operand which encodes into
695 // CRm. op2 differentiates the opcodes.
696 def BarrierAsmOperand : AsmOperandClass {
697 let Name = "Barrier";
698 let ParserMethod = "tryParseBarrierOperand";
700 def barrier_op : Operand<i32> {
701 let PrintMethod = "printBarrierOption";
702 let ParserMatchClass = BarrierAsmOperand;
704 class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
705 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
706 Sched<[WriteBarrier]> {
708 let Inst{20-12} = 0b000110011;
709 let Inst{11-8} = CRm;
713 // MRS/MSR system instructions. These have different operand classes because
714 // a different subset of registers can be accessed through each instruction.
715 def MRSSystemRegisterOperand : AsmOperandClass {
716 let Name = "MRSSystemRegister";
717 let ParserMethod = "tryParseSysReg";
719 // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
720 def mrs_sysreg_op : Operand<i32> {
721 let ParserMatchClass = MRSSystemRegisterOperand;
722 let DecoderMethod = "DecodeMRSSystemRegister";
723 let PrintMethod = "printMRSSystemRegister";
726 def MSRSystemRegisterOperand : AsmOperandClass {
727 let Name = "MSRSystemRegister";
728 let ParserMethod = "tryParseSysReg";
730 def msr_sysreg_op : Operand<i32> {
731 let ParserMatchClass = MSRSystemRegisterOperand;
732 let DecoderMethod = "DecodeMSRSystemRegister";
733 let PrintMethod = "printMSRSystemRegister";
736 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
737 "mrs", "\t$Rt, $systemreg"> {
740 let Inst{19-5} = systemreg;
743 // FIXME: Some of these def CPSR, others don't. Best way to model that?
744 // Explicitly modeling each of the system register as a register class
745 // would do it, but feels like overkill at this point.
746 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
747 "msr", "\t$systemreg, $Rt"> {
750 let Inst{19-5} = systemreg;
753 def SystemCPSRFieldOperand : AsmOperandClass {
754 let Name = "SystemCPSRField";
755 let ParserMethod = "tryParseSysReg";
757 def cpsrfield_op : Operand<i32> {
758 let ParserMatchClass = SystemCPSRFieldOperand;
759 let PrintMethod = "printSystemCPSRField";
763 class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
764 "msr", "\t$cpsr_field, $imm">,
768 let Inst{20-19} = 0b00;
769 let Inst{18-16} = cpsrfield{5-3};
770 let Inst{15-12} = 0b0100;
771 let Inst{11-8} = imm;
772 let Inst{7-5} = cpsrfield{2-0};
774 let DecoderMethod = "DecodeSystemCPSRInstruction";
777 // SYS and SYSL generic system instructions.
778 def SysCRAsmOperand : AsmOperandClass {
780 let ParserMethod = "tryParseSysCROperand";
783 def sys_cr_op : Operand<i32> {
784 let PrintMethod = "printSysCROperand";
785 let ParserMatchClass = SysCRAsmOperand;
788 class SystemXtI<bit L, string asm>
789 : RtSystemI<L, (outs),
790 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
791 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
796 let Inst{20-19} = 0b01;
797 let Inst{18-16} = op1;
798 let Inst{15-12} = Cn;
803 class SystemLXtI<bit L, string asm>
804 : RtSystemI<L, (outs),
805 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
806 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
811 let Inst{20-19} = 0b01;
812 let Inst{18-16} = op1;
813 let Inst{15-12} = Cn;
819 // Branch (register) instructions:
827 // otherwise UNDEFINED
828 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
829 string operands, list<dag> pattern>
830 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
831 let Inst{31-25} = 0b1101011;
832 let Inst{24-21} = opc;
833 let Inst{20-16} = 0b11111;
834 let Inst{15-10} = 0b000000;
835 let Inst{4-0} = 0b00000;
838 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
839 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
844 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
845 class SpecialReturn<bits<4> opc, string asm>
846 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
847 let Inst{9-5} = 0b11111;
851 // Conditional branch instruction.
853 // Branch condition code.
854 // 4-bit immediate. Pretty-printed as .<cc>
855 def dotCcode : Operand<i32> {
856 let PrintMethod = "printDotCondCode";
859 // Conditional branch target. 19-bit immediate. The low two bits of the target
860 // offset are implied zero and so are not part of the immediate.
861 def BranchTarget19Operand : AsmOperandClass {
862 let Name = "BranchTarget19";
864 def am_brcond : Operand<OtherVT> {
865 let EncoderMethod = "getCondBranchTargetOpValue";
866 let DecoderMethod = "DecodeCondBranchTarget";
867 let PrintMethod = "printAlignedBranchTarget";
868 let ParserMatchClass = BranchTarget19Operand;
871 class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
872 "b", "$cond\t$target", "",
873 [(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
876 let isTerminator = 1;
881 let Inst{31-24} = 0b01010100;
882 let Inst{23-5} = target;
884 let Inst{3-0} = cond;
888 // Compare-and-branch instructions.
890 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
891 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
892 asm, "\t$Rt, $target", "",
893 [(node regtype:$Rt, bb:$target)]>,
896 let isTerminator = 1;
900 let Inst{30-25} = 0b011010;
902 let Inst{23-5} = target;
906 multiclass CmpBranch<bit op, string asm, SDNode node> {
907 def W : BaseCmpBranch<GPR32, op, asm, node> {
910 def X : BaseCmpBranch<GPR64, op, asm, node> {
916 // Test-bit-and-branch instructions.
918 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
919 // the target offset are implied zero and so are not part of the immediate.
920 def BranchTarget14Operand : AsmOperandClass {
921 let Name = "BranchTarget14";
923 def am_tbrcond : Operand<OtherVT> {
924 let EncoderMethod = "getTestBranchTargetOpValue";
925 let PrintMethod = "printAlignedBranchTarget";
926 let ParserMatchClass = BranchTarget14Operand;
929 class TestBranch<bit op, string asm, SDNode node>
930 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
931 asm, "\t$Rt, $bit_off, $target", "",
932 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
935 let isTerminator = 1;
941 let Inst{31} = bit_off{5};
942 let Inst{30-25} = 0b011011;
944 let Inst{23-19} = bit_off{4-0};
945 let Inst{18-5} = target;
948 let DecoderMethod = "DecodeTestAndBranch";
952 // Unconditional branch (immediate) instructions.
954 def BranchTarget26Operand : AsmOperandClass {
955 let Name = "BranchTarget26";
957 def am_b_target : Operand<OtherVT> {
958 let EncoderMethod = "getBranchTargetOpValue";
959 let PrintMethod = "printAlignedBranchTarget";
960 let ParserMatchClass = BranchTarget26Operand;
962 def am_bl_target : Operand<i64> {
963 let EncoderMethod = "getBranchTargetOpValue";
964 let PrintMethod = "printAlignedBranchTarget";
965 let ParserMatchClass = BranchTarget26Operand;
968 class BImm<bit op, dag iops, string asm, list<dag> pattern>
969 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
972 let Inst{30-26} = 0b00101;
973 let Inst{25-0} = addr;
975 let DecoderMethod = "DecodeUnconditionalBranch";
978 class BranchImm<bit op, string asm, list<dag> pattern>
979 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
980 class CallImm<bit op, string asm, list<dag> pattern>
981 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
984 // Basic one-operand data processing instructions.
987 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
988 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
989 SDPatternOperator node>
990 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
991 [(set regtype:$Rd, (node regtype:$Rn))]>,
996 let Inst{30-13} = 0b101101011000000000;
997 let Inst{12-10} = opc;
1002 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1003 multiclass OneOperandData<bits<3> opc, string asm,
1004 SDPatternOperator node = null_frag> {
1005 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1009 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1014 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1015 : BaseOneOperandData<opc, GPR32, asm, node> {
1019 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1020 : BaseOneOperandData<opc, GPR64, asm, node> {
1025 // Basic two-operand data processing instructions.
1027 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1029 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1030 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1036 let Inst{30} = isSub;
1037 let Inst{28-21} = 0b11010000;
1038 let Inst{20-16} = Rm;
1039 let Inst{15-10} = 0;
1044 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1046 : BaseBaseAddSubCarry<isSub, regtype, asm,
1047 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
1049 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1051 : BaseBaseAddSubCarry<isSub, regtype, asm,
1052 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
1057 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1058 SDNode OpNode, SDNode OpNode_setflags> {
1059 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1063 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1069 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1074 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1081 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1082 SDPatternOperator OpNode>
1083 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1084 asm, "\t$Rd, $Rn, $Rm", "",
1085 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1089 let Inst{30-21} = 0b0011010110;
1090 let Inst{20-16} = Rm;
1091 let Inst{15-14} = 0b00;
1092 let Inst{13-10} = opc;
1097 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1098 SDPatternOperator OpNode>
1099 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1100 let Inst{10} = isSigned;
1103 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1104 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1105 Sched<[WriteID32]> {
1108 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1109 Sched<[WriteID64]> {
1114 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1115 SDPatternOperator OpNode = null_frag>
1116 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1118 let Inst{11-10} = shift_type;
1121 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1122 def Wr : BaseShift<shift_type, GPR32, asm> {
1126 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1130 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1131 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1132 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1134 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1135 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1137 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1138 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1140 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1141 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1144 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1145 : InstAlias<asm#" $dst, $src1, $src2",
1146 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1148 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1149 RegisterClass addtype, string asm,
1151 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1152 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1157 let Inst{30-24} = 0b0011011;
1158 let Inst{23-21} = opc;
1159 let Inst{20-16} = Rm;
1160 let Inst{15} = isSub;
1161 let Inst{14-10} = Ra;
1166 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1167 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1168 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1169 Sched<[WriteIM32]> {
1173 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1174 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1175 Sched<[WriteIM64]> {
1180 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1181 SDNode AccNode, SDNode ExtNode>
1182 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1183 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1184 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1185 Sched<[WriteIM32]> {
1189 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1190 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1191 asm, "\t$Rd, $Rn, $Rm", "",
1192 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1193 Sched<[WriteIM64]> {
1197 let Inst{31-24} = 0b10011011;
1198 let Inst{23-21} = opc;
1199 let Inst{20-16} = Rm;
1204 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1205 // (i.e. all bits 1) but is ignored by the processor.
1206 let PostEncoderMethod = "fixMulHigh";
1209 class MulAccumWAlias<string asm, Instruction inst>
1210 : InstAlias<asm#" $dst, $src1, $src2",
1211 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1212 class MulAccumXAlias<string asm, Instruction inst>
1213 : InstAlias<asm#" $dst, $src1, $src2",
1214 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1215 class WideMulAccumAlias<string asm, Instruction inst>
1216 : InstAlias<asm#" $dst, $src1, $src2",
1217 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1219 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1220 SDPatternOperator OpNode, string asm>
1221 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1222 asm, "\t$Rd, $Rn, $Rm", "",
1223 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1224 Sched<[WriteISReg]> {
1230 let Inst{30-21} = 0b0011010110;
1231 let Inst{20-16} = Rm;
1232 let Inst{15-13} = 0b010;
1234 let Inst{11-10} = sz;
1240 // Address generation.
1243 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1244 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1249 let Inst{31} = page;
1250 let Inst{30-29} = label{1-0};
1251 let Inst{28-24} = 0b10000;
1252 let Inst{23-5} = label{20-2};
1255 let DecoderMethod = "DecodeAdrInstruction";
1262 def movimm32_imm : Operand<i32> {
1263 let ParserMatchClass = Imm0_65535Operand;
1264 let EncoderMethod = "getMoveWideImmOpValue";
1266 def movimm32_shift : Operand<i32> {
1267 let PrintMethod = "printShifter";
1268 let ParserMatchClass = MovImm32ShifterOperand;
1270 def movimm64_shift : Operand<i32> {
1271 let PrintMethod = "printShifter";
1272 let ParserMatchClass = MovImm64ShifterOperand;
1274 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1275 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1277 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1278 asm, "\t$Rd, $imm$shift", "", []>,
1283 let Inst{30-29} = opc;
1284 let Inst{28-23} = 0b100101;
1285 let Inst{22-21} = shift{5-4};
1286 let Inst{20-5} = imm;
1289 let DecoderMethod = "DecodeMoveImmInstruction";
1292 multiclass MoveImmediate<bits<2> opc, string asm> {
1293 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1297 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1302 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1303 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1305 : I<(outs regtype:$Rd),
1306 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1307 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1312 let Inst{30-29} = opc;
1313 let Inst{28-23} = 0b100101;
1314 let Inst{22-21} = shift{5-4};
1315 let Inst{20-5} = imm;
1318 let DecoderMethod = "DecodeMoveImmInstruction";
1321 multiclass InsertImmediate<bits<2> opc, string asm> {
1322 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1326 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1335 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1336 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1337 string asm, SDPatternOperator OpNode>
1338 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1339 asm, "\t$Rd, $Rn, $imm", "",
1340 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1345 let Inst{30} = isSub;
1346 let Inst{29} = setFlags;
1347 let Inst{28-24} = 0b10001;
1348 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1349 let Inst{21-10} = imm{11-0};
1352 let DecoderMethod = "DecodeBaseAddSubImm";
1355 class BaseAddSubRegPseudo<RegisterClass regtype,
1356 SDPatternOperator OpNode>
1357 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1358 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1361 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1362 arith_shifted_reg shifted_regtype, string asm,
1363 SDPatternOperator OpNode>
1364 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1365 asm, "\t$Rd, $Rn, $Rm", "",
1366 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1367 Sched<[WriteISReg]> {
1368 // The operands are in order to match the 'addr' MI operands, so we
1369 // don't need an encoder method and by-name matching. Just use the default
1370 // in-order handling. Since we're using by-order, make sure the names
1376 let Inst{30} = isSub;
1377 let Inst{29} = setFlags;
1378 let Inst{28-24} = 0b01011;
1379 let Inst{23-22} = shift{7-6};
1381 let Inst{20-16} = src2;
1382 let Inst{15-10} = shift{5-0};
1383 let Inst{9-5} = src1;
1384 let Inst{4-0} = dst;
1386 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1389 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1390 RegisterClass src1Regtype, Operand src2Regtype,
1391 string asm, SDPatternOperator OpNode>
1392 : I<(outs dstRegtype:$R1),
1393 (ins src1Regtype:$R2, src2Regtype:$R3),
1394 asm, "\t$R1, $R2, $R3", "",
1395 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1396 Sched<[WriteIEReg]> {
1401 let Inst{30} = isSub;
1402 let Inst{29} = setFlags;
1403 let Inst{28-24} = 0b01011;
1404 let Inst{23-21} = 0b001;
1405 let Inst{20-16} = Rm;
1406 let Inst{15-13} = ext{5-3};
1407 let Inst{12-10} = ext{2-0};
1411 let DecoderMethod = "DecodeAddSubERegInstruction";
1414 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1415 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1416 RegisterClass src1Regtype, RegisterClass src2Regtype,
1417 Operand ext_op, string asm>
1418 : I<(outs dstRegtype:$Rd),
1419 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1420 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1421 Sched<[WriteIEReg]> {
1426 let Inst{30} = isSub;
1427 let Inst{29} = setFlags;
1428 let Inst{28-24} = 0b01011;
1429 let Inst{23-21} = 0b001;
1430 let Inst{20-16} = Rm;
1431 let Inst{15} = ext{5};
1432 let Inst{12-10} = ext{2-0};
1436 let DecoderMethod = "DecodeAddSubERegInstruction";
1439 // Aliases for register+register add/subtract.
1440 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1441 RegisterClass src1Regtype, RegisterClass src2Regtype,
1443 : InstAlias<asm#" $dst, $src1, $src2",
1444 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1447 multiclass AddSub<bit isSub, string mnemonic,
1448 SDPatternOperator OpNode = null_frag> {
1449 let hasSideEffects = 0 in {
1450 // Add/Subtract immediate
1451 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1455 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1460 // Add/Subtract register - Only used for CodeGen
1461 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1462 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1464 // Add/Subtract shifted register
1465 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1469 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1475 // Add/Subtract extended register
1476 let AddedComplexity = 1, hasSideEffects = 0 in {
1477 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1478 arith_extended_reg32<i32>, mnemonic, OpNode> {
1481 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1482 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1487 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1488 arith_extendlsl64, mnemonic> {
1489 // UXTX and SXTX only.
1490 let Inst{14-13} = 0b11;
1494 // Register/register aliases with no shift when SP is not used.
1495 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1496 GPR32, GPR32, GPR32, 0>;
1497 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1498 GPR64, GPR64, GPR64, 0>;
1500 // Register/register aliases with no shift when either the destination or
1501 // first source register is SP. This relies on the shifted register aliases
1502 // above matching first in the case when SP is not used.
1503 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1504 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1505 def : AddSubRegAlias<mnemonic,
1506 !cast<Instruction>(NAME#"Xrx64"),
1507 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1510 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1511 let isCompare = 1, Defs = [CPSR] in {
1512 // Add/Subtract immediate
1513 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1517 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1522 // Add/Subtract register
1523 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1524 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1526 // Add/Subtract shifted register
1527 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1531 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1536 // Add/Subtract extended register
1537 let AddedComplexity = 1 in {
1538 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1539 arith_extended_reg32<i32>, mnemonic, OpNode> {
1542 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1543 arith_extended_reg32<i64>, mnemonic, OpNode> {
1548 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1549 arith_extendlsl64, mnemonic> {
1550 // UXTX and SXTX only.
1551 let Inst{14-13} = 0b11;
1556 // Register/register aliases with no shift when SP is not used.
1557 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1558 GPR32, GPR32, GPR32, 0>;
1559 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1560 GPR64, GPR64, GPR64, 0>;
1562 // Register/register aliases with no shift when the first source register
1563 // is SP. This relies on the shifted register aliases above matching first
1564 // in the case when SP is not used.
1565 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1566 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1567 def : AddSubRegAlias<mnemonic,
1568 !cast<Instruction>(NAME#"Xrx64"),
1569 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1575 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1577 def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1579 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1581 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1582 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1583 Sched<[WriteExtr, ReadExtrHi]> {
1589 let Inst{30-23} = 0b00100111;
1591 let Inst{20-16} = Rm;
1592 let Inst{15-10} = imm;
1597 multiclass ExtractImm<string asm> {
1598 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1600 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1603 // imm<5> must be zero.
1606 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1608 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1619 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1620 class BaseBitfieldImm<bits<2> opc,
1621 RegisterClass regtype, Operand imm_type, string asm>
1622 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1623 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1630 let Inst{30-29} = opc;
1631 let Inst{28-23} = 0b100110;
1632 let Inst{21-16} = immr;
1633 let Inst{15-10} = imms;
1638 multiclass BitfieldImm<bits<2> opc, string asm> {
1639 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1642 // imms<5> and immr<5> must be zero, else ReservedValue().
1646 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1652 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1653 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1654 RegisterClass regtype, Operand imm_type, string asm>
1655 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1657 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1664 let Inst{30-29} = opc;
1665 let Inst{28-23} = 0b100110;
1666 let Inst{21-16} = immr;
1667 let Inst{15-10} = imms;
1672 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1673 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1676 // imms<5> and immr<5> must be zero, else ReservedValue().
1680 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1690 // Logical (immediate)
1691 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1692 RegisterClass sregtype, Operand imm_type, string asm,
1694 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1695 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1700 let Inst{30-29} = opc;
1701 let Inst{28-23} = 0b100100;
1702 let Inst{22} = imm{12};
1703 let Inst{21-16} = imm{11-6};
1704 let Inst{15-10} = imm{5-0};
1708 let DecoderMethod = "DecodeLogicalImmInstruction";
1711 // Logical (shifted register)
1712 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1713 logical_shifted_reg shifted_regtype, string asm,
1715 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1716 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1717 Sched<[WriteISReg]> {
1718 // The operands are in order to match the 'addr' MI operands, so we
1719 // don't need an encoder method and by-name matching. Just use the default
1720 // in-order handling. Since we're using by-order, make sure the names
1726 let Inst{30-29} = opc;
1727 let Inst{28-24} = 0b01010;
1728 let Inst{23-22} = shift{7-6};
1730 let Inst{20-16} = src2;
1731 let Inst{15-10} = shift{5-0};
1732 let Inst{9-5} = src1;
1733 let Inst{4-0} = dst;
1735 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1738 // Aliases for register+register logical instructions.
1739 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1740 : InstAlias<asm#" $dst, $src1, $src2",
1741 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1743 let AddedComplexity = 6 in
1744 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1745 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1746 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1747 logical_imm32:$imm))]> {
1749 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1751 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1752 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1753 logical_imm64:$imm))]> {
1758 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1759 let isCompare = 1, Defs = [CPSR] in {
1760 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1761 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1763 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1765 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1766 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1769 } // end Defs = [CPSR]
1772 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1773 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1774 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1777 // Split from LogicalImm as not all instructions have both.
1778 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1779 SDPatternOperator OpNode> {
1780 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1781 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1783 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1784 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1785 logical_shifted_reg32:$Rm))]> {
1788 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1789 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1790 logical_shifted_reg64:$Rm))]> {
1794 def : LogicalRegAlias<mnemonic,
1795 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1796 def : LogicalRegAlias<mnemonic,
1797 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1800 // Split from LogicalReg to allow setting CPSR Defs
1801 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1802 let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1803 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1806 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1811 def : LogicalRegAlias<mnemonic,
1812 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1813 def : LogicalRegAlias<mnemonic,
1814 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1818 // Conditionally set flags
1822 // 4-bit immediate. Pretty-printed as <cc>
1823 def ccode : Operand<i32> {
1824 let PrintMethod = "printCondCode";
1827 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1828 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1829 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1830 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1841 let Inst{29-21} = 0b111010010;
1842 let Inst{20-16} = imm;
1843 let Inst{15-12} = cond;
1844 let Inst{11-10} = 0b10;
1847 let Inst{3-0} = nzcv;
1850 multiclass CondSetFlagsImm<bit op, string asm> {
1851 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1854 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1859 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1860 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1861 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1862 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1873 let Inst{29-21} = 0b111010010;
1874 let Inst{20-16} = Rm;
1875 let Inst{15-12} = cond;
1876 let Inst{11-10} = 0b00;
1879 let Inst{3-0} = nzcv;
1882 multiclass CondSetFlagsReg<bit op, string asm> {
1883 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1886 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1892 // Conditional select
1895 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1896 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1897 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1899 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1909 let Inst{29-21} = 0b011010100;
1910 let Inst{20-16} = Rm;
1911 let Inst{15-12} = cond;
1912 let Inst{11-10} = op2;
1917 multiclass CondSelect<bit op, bits<2> op2, string asm> {
1918 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1921 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1926 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1928 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1929 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1931 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1932 (i32 imm:$cond), CPSR))]>,
1942 let Inst{29-21} = 0b011010100;
1943 let Inst{20-16} = Rm;
1944 let Inst{15-12} = cond;
1945 let Inst{11-10} = op2;
1950 def inv_cond_XFORM : SDNodeXForm<imm, [{
1951 ARM64CC::CondCode CC = static_cast<ARM64CC::CondCode>(N->getZExtValue());
1952 return CurDAG->getTargetConstant(ARM64CC::getInvertedCondCode(CC), MVT::i32);
1955 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1956 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1959 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1963 def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), CPSR),
1964 (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
1965 (inv_cond_XFORM imm:$cond))>;
1967 def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), CPSR),
1968 (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
1969 (inv_cond_XFORM imm:$cond))>;
1973 // Special Mask Value
1975 def maski8_or_more : Operand<i32>,
1976 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1978 def maski16_or_more : Operand<i32>,
1979 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1987 // (unsigned immediate)
1988 // Indexed for 8-bit registers. offset is in range [0,4095].
1989 def MemoryIndexed8Operand : AsmOperandClass {
1990 let Name = "MemoryIndexed8";
1991 let DiagnosticType = "InvalidMemoryIndexed8";
1993 def am_indexed8 : Operand<i64>,
1994 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1995 let PrintMethod = "printAMIndexed8";
1997 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1998 let ParserMatchClass = MemoryIndexed8Operand;
1999 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2002 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
2003 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
2004 def MemoryIndexed16Operand : AsmOperandClass {
2005 let Name = "MemoryIndexed16";
2006 let DiagnosticType = "InvalidMemoryIndexed16";
2008 def am_indexed16 : Operand<i64>,
2009 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2010 let PrintMethod = "printAMIndexed16";
2012 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2013 let ParserMatchClass = MemoryIndexed16Operand;
2014 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2017 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2018 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2019 def MemoryIndexed32Operand : AsmOperandClass {
2020 let Name = "MemoryIndexed32";
2021 let DiagnosticType = "InvalidMemoryIndexed32";
2023 def am_indexed32 : Operand<i64>,
2024 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2025 let PrintMethod = "printAMIndexed32";
2027 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2028 let ParserMatchClass = MemoryIndexed32Operand;
2029 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2032 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2033 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2034 def MemoryIndexed64Operand : AsmOperandClass {
2035 let Name = "MemoryIndexed64";
2036 let DiagnosticType = "InvalidMemoryIndexed64";
2038 def am_indexed64 : Operand<i64>,
2039 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2040 let PrintMethod = "printAMIndexed64";
2042 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2043 let ParserMatchClass = MemoryIndexed64Operand;
2044 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2047 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2048 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2049 def MemoryIndexed128Operand : AsmOperandClass {
2050 let Name = "MemoryIndexed128";
2051 let DiagnosticType = "InvalidMemoryIndexed128";
2053 def am_indexed128 : Operand<i64>,
2054 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2055 let PrintMethod = "printAMIndexed128";
2057 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2058 let ParserMatchClass = MemoryIndexed128Operand;
2059 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2063 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2064 def am_noindex : Operand<i64>,
2065 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2066 let PrintMethod = "printAMNoIndex";
2067 let ParserMatchClass = MemoryNoIndexOperand;
2068 let MIOperandInfo = (ops GPR64sp:$base);
2071 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2072 string asm, list<dag> pattern>
2073 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2077 bits<5> base = addr{4-0};
2078 bits<12> offset = addr{16-5};
2080 let Inst{31-30} = sz;
2081 let Inst{29-27} = 0b111;
2083 let Inst{25-24} = 0b01;
2084 let Inst{23-22} = opc;
2085 let Inst{21-10} = offset;
2086 let Inst{9-5} = base;
2087 let Inst{4-0} = dst;
2089 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2092 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2093 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2094 Operand indextype, string asm, list<dag> pattern>
2095 : BaseLoadStoreUI<sz, V, opc,
2096 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2099 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2100 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2101 Operand indextype, string asm, list<dag> pattern>
2102 : BaseLoadStoreUI<sz, V, opc,
2103 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2106 def PrefetchOperand : AsmOperandClass {
2107 let Name = "Prefetch";
2108 let ParserMethod = "tryParsePrefetch";
2110 def prfop : Operand<i32> {
2111 let PrintMethod = "printPrefetchOp";
2112 let ParserMatchClass = PrefetchOperand;
2115 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2116 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2117 : BaseLoadStoreUI<sz, V, opc,
2118 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2125 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2126 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2127 : I<(outs regtype:$Rt), (ins am_brcond:$label),
2128 asm, "\t$Rt, $label", "", []>,
2132 let Inst{31-30} = opc;
2133 let Inst{29-27} = 0b011;
2135 let Inst{25-24} = 0b00;
2136 let Inst{23-5} = label;
2140 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2141 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2142 : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2143 asm, "\t$Rt, $label", "", pat>,
2147 let Inst{31-30} = opc;
2148 let Inst{29-27} = 0b011;
2150 let Inst{25-24} = 0b00;
2151 let Inst{23-5} = label;
2156 // Load/store register offset
2159 class MemROAsmOperand<int sz> : AsmOperandClass {
2160 let Name = "MemoryRegisterOffset"#sz;
2163 def MemROAsmOperand8 : MemROAsmOperand<8>;
2164 def MemROAsmOperand16 : MemROAsmOperand<16>;
2165 def MemROAsmOperand32 : MemROAsmOperand<32>;
2166 def MemROAsmOperand64 : MemROAsmOperand<64>;
2167 def MemROAsmOperand128 : MemROAsmOperand<128>;
2169 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2170 let PrintMethod = "printMemoryRegOffset"#sz;
2171 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2174 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2175 let ParserMatchClass = MemROAsmOperand8;
2178 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2179 let ParserMatchClass = MemROAsmOperand16;
2182 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2183 let ParserMatchClass = MemROAsmOperand32;
2186 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2187 let ParserMatchClass = MemROAsmOperand64;
2190 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2191 let ParserMatchClass = MemROAsmOperand128;
2194 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2195 string asm, dag ins, dag outs, list<dag> pat>
2196 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2197 // The operands are in order to match the 'addr' MI operands, so we
2198 // don't need an encoder method and by-name matching. Just use the default
2199 // in-order handling. Since we're using by-order, make sure the names
2205 let Inst{31-30} = sz;
2206 let Inst{29-27} = 0b111;
2208 let Inst{25-24} = 0b00;
2209 let Inst{23-22} = opc;
2211 let Inst{20-16} = offset;
2212 let Inst{15-13} = extend{3-1};
2214 let Inst{12} = extend{0};
2215 let Inst{11-10} = 0b10;
2216 let Inst{9-5} = base;
2217 let Inst{4-0} = dst;
2219 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2222 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2223 string asm, list<dag> pat>
2224 : LoadStore8RO<sz, V, opc, regtype, asm,
2225 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2226 Sched<[WriteLDIdx, ReadAdrBase]>;
2228 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2229 string asm, list<dag> pat>
2230 : LoadStore8RO<sz, V, opc, regtype, asm,
2231 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2232 Sched<[WriteSTIdx, ReadAdrBase]>;
2234 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2235 string asm, dag ins, dag outs, list<dag> pat>
2236 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2237 // The operands are in order to match the 'addr' MI operands, so we
2238 // don't need an encoder method and by-name matching. Just use the default
2239 // in-order handling. Since we're using by-order, make sure the names
2245 let Inst{31-30} = sz;
2246 let Inst{29-27} = 0b111;
2248 let Inst{25-24} = 0b00;
2249 let Inst{23-22} = opc;
2251 let Inst{20-16} = offset;
2252 let Inst{15-13} = extend{3-1};
2254 let Inst{12} = extend{0};
2255 let Inst{11-10} = 0b10;
2256 let Inst{9-5} = base;
2257 let Inst{4-0} = dst;
2259 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2262 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2263 string asm, list<dag> pat>
2264 : LoadStore16RO<sz, V, opc, regtype, asm,
2265 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2266 Sched<[WriteLDIdx, ReadAdrBase]>;
2268 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2269 string asm, list<dag> pat>
2270 : LoadStore16RO<sz, V, opc, regtype, asm,
2271 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2272 Sched<[WriteSTIdx, ReadAdrBase]>;
2274 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2275 string asm, dag ins, dag outs, list<dag> pat>
2276 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2277 // The operands are in order to match the 'addr' MI operands, so we
2278 // don't need an encoder method and by-name matching. Just use the default
2279 // in-order handling. Since we're using by-order, make sure the names
2285 let Inst{31-30} = sz;
2286 let Inst{29-27} = 0b111;
2288 let Inst{25-24} = 0b00;
2289 let Inst{23-22} = opc;
2291 let Inst{20-16} = offset;
2292 let Inst{15-13} = extend{3-1};
2294 let Inst{12} = extend{0};
2295 let Inst{11-10} = 0b10;
2296 let Inst{9-5} = base;
2297 let Inst{4-0} = dst;
2299 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2302 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2303 string asm, list<dag> pat>
2304 : LoadStore32RO<sz, V, opc, regtype, asm,
2305 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2306 Sched<[WriteLDIdx, ReadAdrBase]>;
2308 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2309 string asm, list<dag> pat>
2310 : LoadStore32RO<sz, V, opc, regtype, asm,
2311 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2312 Sched<[WriteSTIdx, ReadAdrBase]>;
2314 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2315 string asm, dag ins, dag outs, list<dag> pat>
2316 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2317 // The operands are in order to match the 'addr' MI operands, so we
2318 // don't need an encoder method and by-name matching. Just use the default
2319 // in-order handling. Since we're using by-order, make sure the names
2325 let Inst{31-30} = sz;
2326 let Inst{29-27} = 0b111;
2328 let Inst{25-24} = 0b00;
2329 let Inst{23-22} = opc;
2331 let Inst{20-16} = offset;
2332 let Inst{15-13} = extend{3-1};
2334 let Inst{12} = extend{0};
2335 let Inst{11-10} = 0b10;
2336 let Inst{9-5} = base;
2337 let Inst{4-0} = dst;
2339 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2342 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2343 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2344 string asm, list<dag> pat>
2345 : LoadStore64RO<sz, V, opc, regtype, asm,
2346 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2347 Sched<[WriteLDIdx, ReadAdrBase]>;
2349 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2350 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2351 string asm, list<dag> pat>
2352 : LoadStore64RO<sz, V, opc, regtype, asm,
2353 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2354 Sched<[WriteSTIdx, ReadAdrBase]>;
2357 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2358 string asm, dag ins, dag outs, list<dag> pat>
2359 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2360 // The operands are in order to match the 'addr' MI operands, so we
2361 // don't need an encoder method and by-name matching. Just use the default
2362 // in-order handling. Since we're using by-order, make sure the names
2368 let Inst{31-30} = sz;
2369 let Inst{29-27} = 0b111;
2371 let Inst{25-24} = 0b00;
2372 let Inst{23-22} = opc;
2374 let Inst{20-16} = offset;
2375 let Inst{15-13} = extend{3-1};
2377 let Inst{12} = extend{0};
2378 let Inst{11-10} = 0b10;
2379 let Inst{9-5} = base;
2380 let Inst{4-0} = dst;
2382 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2385 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2386 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2387 string asm, list<dag> pat>
2388 : LoadStore128RO<sz, V, opc, regtype, asm,
2389 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2390 Sched<[WriteLDIdx, ReadAdrBase]>;
2392 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2393 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2394 string asm, list<dag> pat>
2395 : LoadStore128RO<sz, V, opc, regtype, asm,
2396 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2397 Sched<[WriteSTIdx, ReadAdrBase]>;
2399 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2400 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2401 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2402 "\t$Rt, $addr", "", pat>,
2404 // The operands are in order to match the 'addr' MI operands, so we
2405 // don't need an encoder method and by-name matching. Just use the default
2406 // in-order handling. Since we're using by-order, make sure the names
2412 let Inst{31-30} = sz;
2413 let Inst{29-27} = 0b111;
2415 let Inst{25-24} = 0b00;
2416 let Inst{23-22} = opc;
2418 let Inst{20-16} = offset;
2419 let Inst{15-13} = extend{3-1};
2421 let Inst{12} = extend{0};
2422 let Inst{11-10} = 0b10;
2423 let Inst{9-5} = base;
2424 let Inst{4-0} = dst;
2426 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2430 // Load/store unscaled immediate
2433 def MemoryUnscaledOperand : AsmOperandClass {
2434 let Name = "MemoryUnscaled";
2435 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2437 class am_unscaled_operand : Operand<i64> {
2438 let PrintMethod = "printAMUnscaled";
2439 let ParserMatchClass = MemoryUnscaledOperand;
2440 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2442 class am_unscaled_wb_operand : Operand<i64> {
2443 let PrintMethod = "printAMUnscaledWB";
2444 let ParserMatchClass = MemoryUnscaledOperand;
2445 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2447 def am_unscaled : am_unscaled_operand;
2448 def am_unscaled_wb: am_unscaled_wb_operand;
2449 def am_unscaled8 : am_unscaled_operand,
2450 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2451 def am_unscaled16 : am_unscaled_operand,
2452 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2453 def am_unscaled32 : am_unscaled_operand,
2454 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2455 def am_unscaled64 : am_unscaled_operand,
2456 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2457 def am_unscaled128 : am_unscaled_operand,
2458 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2460 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2461 string asm, list<dag> pattern>
2462 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2463 // The operands are in order to match the 'addr' MI operands, so we
2464 // don't need an encoder method and by-name matching. Just use the default
2465 // in-order handling. Since we're using by-order, make sure the names
2470 let Inst{31-30} = sz;
2471 let Inst{29-27} = 0b111;
2473 let Inst{25-24} = 0b00;
2474 let Inst{23-22} = opc;
2476 let Inst{20-12} = offset;
2477 let Inst{11-10} = 0b00;
2478 let Inst{9-5} = base;
2479 let Inst{4-0} = dst;
2481 let DecoderMethod = "DecodeSignedLdStInstruction";
2484 let AddedComplexity = 1 in // try this before LoadUI
2485 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2486 Operand amtype, string asm, list<dag> pattern>
2487 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2488 (ins amtype:$addr), asm, pattern>,
2491 let AddedComplexity = 1 in // try this before StoreUI
2492 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2493 Operand amtype, string asm, list<dag> pattern>
2494 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2495 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2498 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2499 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2500 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2501 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2505 // Load/store unscaled immediate, unprivileged
2508 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2509 dag oops, dag iops, string asm>
2510 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2511 // The operands are in order to match the 'addr' MI operands, so we
2512 // don't need an encoder method and by-name matching. Just use the default
2513 // in-order handling. Since we're using by-order, make sure the names
2518 let Inst{31-30} = sz;
2519 let Inst{29-27} = 0b111;
2521 let Inst{25-24} = 0b00;
2522 let Inst{23-22} = opc;
2524 let Inst{20-12} = offset;
2525 let Inst{11-10} = 0b10;
2526 let Inst{9-5} = base;
2527 let Inst{4-0} = dst;
2529 let DecoderMethod = "DecodeSignedLdStInstruction";
2532 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2533 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2535 : BaseLoadStoreUnprivileged<sz, V, opc,
2536 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2540 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2541 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2543 : BaseLoadStoreUnprivileged<sz, V, opc,
2544 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2549 // Load/store pre-indexed
2552 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2553 string asm, string cstr>
2554 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2555 // The operands are in order to match the 'addr' MI operands, so we
2556 // don't need an encoder method and by-name matching. Just use the default
2557 // in-order handling.
2561 let Inst{31-30} = sz;
2562 let Inst{29-27} = 0b111;
2564 let Inst{25-24} = 0;
2565 let Inst{23-22} = opc;
2567 let Inst{20-12} = offset;
2568 let Inst{11-10} = 0b11;
2569 let Inst{9-5} = base;
2570 let Inst{4-0} = dst;
2572 let DecoderMethod = "DecodeSignedLdStInstruction";
2575 let hasSideEffects = 0 in {
2576 let mayStore = 0, mayLoad = 1 in
2577 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2578 // we need the complex addressing mode for the memory reference, but
2579 // we also need the write-back specified as a tied operand to the
2580 // base register. That combination does not play nicely with
2581 // the asm matcher and friends.
2582 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2584 : BaseLoadStorePreIdx<sz, V, opc,
2585 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2586 (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
2587 Sched<[WriteLD, WriteAdr]>;
2589 let mayStore = 1, mayLoad = 0 in
2590 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2592 : BaseLoadStorePreIdx<sz, V, opc,
2593 (outs/* GPR64sp:$wback*/),
2594 (ins regtype:$Rt, am_unscaled_wb:$addr),
2595 asm, ""/*"$addr.base = $wback"*/>,
2596 Sched<[WriteAdr, WriteST]>;
2597 } // hasSideEffects = 0
2599 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2600 // logic finally gets smart enough to strip off tied operands that are just
2601 // for isel convenience, we can get rid of these pseudos and just reference
2602 // the real instructions directly.
2604 // Ironically, also because of the writeback operands, we can't put the
2605 // matcher pattern directly on the instruction, but need to define it
2608 // Loads aren't matched with patterns here at all, but rather in C++
2610 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2611 class LoadPreIdxPseudo<RegisterClass regtype>
2612 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2613 (ins am_noindex:$addr, simm9:$offset), [],
2614 "$addr.base = $wback,@earlyclobber $wback">,
2615 Sched<[WriteLD, WriteAdr]>;
2616 class LoadPostIdxPseudo<RegisterClass regtype>
2617 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2618 (ins am_noindex:$addr, simm9:$offset), [],
2619 "$addr.base = $wback,@earlyclobber $wback">,
2620 Sched<[WriteLD, WriteI]>;
2622 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2623 SDPatternOperator OpNode> {
2624 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2625 def _isel: Pseudo<(outs GPR64sp:$wback),
2626 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2627 "$addr.base = $wback,@earlyclobber $wback">,
2628 Sched<[WriteAdr, WriteST]>;
2630 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2631 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2636 // Load/store post-indexed
2639 // (pre-index) load/stores.
2640 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2641 string asm, string cstr>
2642 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2643 // The operands are in order to match the 'addr' MI operands, so we
2644 // don't need an encoder method and by-name matching. Just use the default
2645 // in-order handling.
2649 let Inst{31-30} = sz;
2650 let Inst{29-27} = 0b111;
2652 let Inst{25-24} = 0b00;
2653 let Inst{23-22} = opc;
2655 let Inst{20-12} = offset;
2656 let Inst{11-10} = 0b01;
2657 let Inst{9-5} = base;
2658 let Inst{4-0} = dst;
2660 let DecoderMethod = "DecodeSignedLdStInstruction";
2663 let hasSideEffects = 0 in {
2664 let mayStore = 0, mayLoad = 1 in
2665 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2666 // we need the complex addressing mode for the memory reference, but
2667 // we also need the write-back specified as a tied operand to the
2668 // base register. That combination does not play nicely with
2669 // the asm matcher and friends.
2670 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2672 : BaseLoadStorePostIdx<sz, V, opc,
2673 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2674 (ins am_noindex:$addr, simm9:$idx),
2675 asm, ""/*"$addr.base = $wback"*/>,
2676 Sched<[WriteLD, WriteI]>;
2678 let mayStore = 1, mayLoad = 0 in
2679 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2681 : BaseLoadStorePostIdx<sz, V, opc,
2682 (outs/* GPR64sp:$wback*/),
2683 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2684 asm, ""/*"$addr.base = $wback"*/>,
2685 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2686 } // hasSideEffects = 0
2688 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2689 // logic finally gets smart enough to strip off tied operands that are just
2690 // for isel convenience, we can get rid of these pseudos and just reference
2691 // the real instructions directly.
2693 // Ironically, also because of the writeback operands, we can't put the
2694 // matcher pattern directly on the instruction, but need to define it
2696 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2697 SDPatternOperator OpNode, Instruction Insn> {
2698 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2699 def _isel: Pseudo<(outs GPR64sp:$wback),
2700 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2701 "$addr.base = $wback,@earlyclobber $wback">,
2702 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2703 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2705 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2706 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2714 // (indexed, offset)
2716 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2718 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2719 // The operands are in order to match the 'addr' MI operands, so we
2720 // don't need an encoder method and by-name matching. Just use the default
2721 // in-order handling. Since we're using by-order, make sure the names
2727 let Inst{31-30} = opc;
2728 let Inst{29-27} = 0b101;
2730 let Inst{25-23} = 0b010;
2732 let Inst{21-15} = offset;
2733 let Inst{14-10} = dst2;
2734 let Inst{9-5} = base;
2735 let Inst{4-0} = dst;
2737 let DecoderMethod = "DecodePairLdStInstruction";
2740 let hasSideEffects = 0 in {
2741 let mayStore = 0, mayLoad = 1 in
2742 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2743 Operand indextype, string asm>
2744 : BaseLoadStorePairOffset<opc, V, 1,
2745 (outs regtype:$Rt, regtype:$Rt2),
2746 (ins indextype:$addr), asm>,
2747 Sched<[WriteLD, WriteLDHi]>;
2749 let mayLoad = 0, mayStore = 1 in
2750 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2751 Operand indextype, string asm>
2752 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2753 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2756 } // hasSideEffects = 0
2760 def MemoryIndexed32SImm7 : AsmOperandClass {
2761 let Name = "MemoryIndexed32SImm7";
2762 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2764 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2765 let PrintMethod = "printAMIndexed32";
2766 let ParserMatchClass = MemoryIndexed32SImm7;
2767 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2769 def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2770 let PrintMethod = "printAMIndexed32WB";
2771 let ParserMatchClass = MemoryIndexed32SImm7;
2772 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2775 def MemoryIndexed64SImm7 : AsmOperandClass {
2776 let Name = "MemoryIndexed64SImm7";
2777 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2779 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2780 let PrintMethod = "printAMIndexed64";
2781 let ParserMatchClass = MemoryIndexed64SImm7;
2782 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2784 def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2785 let PrintMethod = "printAMIndexed64WB";
2786 let ParserMatchClass = MemoryIndexed64SImm7;
2787 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2790 def MemoryIndexed128SImm7 : AsmOperandClass {
2791 let Name = "MemoryIndexed128SImm7";
2792 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2794 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2795 let PrintMethod = "printAMIndexed128";
2796 let ParserMatchClass = MemoryIndexed128SImm7;
2797 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2799 def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2800 let PrintMethod = "printAMIndexed128WB";
2801 let ParserMatchClass = MemoryIndexed128SImm7;
2802 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2805 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2807 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2808 // The operands are in order to match the 'addr' MI operands, so we
2809 // don't need an encoder method and by-name matching. Just use the default
2810 // in-order handling. Since we're using by-order, make sure the names
2816 let Inst{31-30} = opc;
2817 let Inst{29-27} = 0b101;
2819 let Inst{25-23} = 0b011;
2821 let Inst{21-15} = offset;
2822 let Inst{14-10} = dst2;
2823 let Inst{9-5} = base;
2824 let Inst{4-0} = dst;
2826 let DecoderMethod = "DecodePairLdStInstruction";
2829 let hasSideEffects = 0 in {
2830 let mayStore = 0, mayLoad = 1 in
2831 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2832 Operand addrmode, string asm>
2833 : BaseLoadStorePairPreIdx<opc, V, 1,
2834 (outs regtype:$Rt, regtype:$Rt2),
2835 (ins addrmode:$addr), asm>,
2836 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2838 let mayStore = 1, mayLoad = 0 in
2839 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2840 Operand addrmode, string asm>
2841 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2842 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2844 Sched<[WriteAdr, WriteSTP]>;
2845 } // hasSideEffects = 0
2849 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2851 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2852 // The operands are in order to match the 'addr' MI operands, so we
2853 // don't need an encoder method and by-name matching. Just use the default
2854 // in-order handling. Since we're using by-order, make sure the names
2860 let Inst{31-30} = opc;
2861 let Inst{29-27} = 0b101;
2863 let Inst{25-23} = 0b001;
2865 let Inst{21-15} = offset;
2866 let Inst{14-10} = dst2;
2867 let Inst{9-5} = base;
2868 let Inst{4-0} = dst;
2870 let DecoderMethod = "DecodePairLdStInstruction";
2873 let hasSideEffects = 0 in {
2874 let mayStore = 0, mayLoad = 1 in
2875 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2876 Operand idxtype, string asm>
2877 : BaseLoadStorePairPostIdx<opc, V, 1,
2878 (outs regtype:$Rt, regtype:$Rt2),
2879 (ins am_noindex:$addr, idxtype:$idx), asm>,
2880 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2882 let mayStore = 1, mayLoad = 0 in
2883 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2884 Operand idxtype, string asm>
2885 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2886 (ins regtype:$Rt, regtype:$Rt2,
2887 am_noindex:$addr, idxtype:$idx),
2889 Sched<[WriteAdr, WriteSTP]>;
2890 } // hasSideEffects = 0
2894 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2896 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2897 // The operands are in order to match the 'addr' MI operands, so we
2898 // don't need an encoder method and by-name matching. Just use the default
2899 // in-order handling. Since we're using by-order, make sure the names
2905 let Inst{31-30} = opc;
2906 let Inst{29-27} = 0b101;
2908 let Inst{25-23} = 0b000;
2910 let Inst{21-15} = offset;
2911 let Inst{14-10} = dst2;
2912 let Inst{9-5} = base;
2913 let Inst{4-0} = dst;
2915 let DecoderMethod = "DecodePairLdStInstruction";
2918 let hasSideEffects = 0 in {
2919 let mayStore = 0, mayLoad = 1 in
2920 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2921 Operand indextype, string asm>
2922 : BaseLoadStorePairNoAlloc<opc, V, 1,
2923 (outs regtype:$Rt, regtype:$Rt2),
2924 (ins indextype:$addr), asm>,
2925 Sched<[WriteLD, WriteLDHi]>;
2927 let mayStore = 1, mayLoad = 0 in
2928 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2929 Operand indextype, string asm>
2930 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2931 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2934 } // hasSideEffects = 0
2937 // Load/store exclusive
2940 // True exclusive operations write to and/or read from the system's exclusive
2941 // monitors, which as far as a compiler is concerned can be modelled as a
2942 // random shared memory address. Hence LoadExclusive mayStore.
2944 // Since these instructions have the undefined register bits set to 1 in
2945 // their canonical form, we need a post encoder method to set those bits
2946 // to 1 when encoding these instructions. We do this using the
2947 // fixLoadStoreExclusive function. This function has template parameters:
2949 // fixLoadStoreExclusive<int hasRs, int hasRt2>
2951 // hasRs indicates that the instruction uses the Rs field, so we won't set
2952 // it to 1 (and the same for Rt2). We don't need template parameters for
2953 // the other register fields since Rt and Rn are always used.
2955 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2956 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2957 dag oops, dag iops, string asm, string operands>
2958 : I<oops, iops, asm, operands, "", []> {
2959 let Inst{31-30} = sz;
2960 let Inst{29-24} = 0b001000;
2966 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2969 // Neither Rs nor Rt2 operands.
2970 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2971 dag oops, dag iops, string asm, string operands>
2972 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2975 let Inst{9-5} = base;
2976 let Inst{4-0} = reg;
2978 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
2981 // Simple load acquires don't set the exclusive monitor
2982 let mayLoad = 1, mayStore = 0 in
2983 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2984 RegisterClass regtype, string asm>
2985 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2986 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2989 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2990 RegisterClass regtype, string asm>
2991 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2992 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2995 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2996 RegisterClass regtype, string asm>
2997 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2998 (outs regtype:$Rt, regtype:$Rt2),
2999 (ins am_noindex:$addr), asm,
3000 "\t$Rt, $Rt2, $addr">,
3001 Sched<[WriteLD, WriteLDHi]> {
3005 let Inst{14-10} = dst2;
3006 let Inst{9-5} = base;
3007 let Inst{4-0} = dst1;
3009 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3012 // Simple store release operations do not check the exclusive monitor.
3013 let mayLoad = 0, mayStore = 1 in
3014 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3015 RegisterClass regtype, string asm>
3016 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3017 (ins regtype:$Rt, am_noindex:$addr),
3018 asm, "\t$Rt, $addr">,
3021 let mayLoad = 1, mayStore = 1 in
3022 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3023 RegisterClass regtype, string asm>
3024 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3025 (ins regtype:$Rt, am_noindex:$addr),
3026 asm, "\t$Ws, $Rt, $addr">,
3031 let Inst{20-16} = status;
3032 let Inst{9-5} = base;
3033 let Inst{4-0} = reg;
3035 let Constraints = "@earlyclobber $Ws";
3036 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3039 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3040 RegisterClass regtype, string asm>
3041 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3043 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3044 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3050 let Inst{20-16} = status;
3051 let Inst{14-10} = dst2;
3052 let Inst{9-5} = base;
3053 let Inst{4-0} = dst1;
3055 let Constraints = "@earlyclobber $Ws";
3059 // Exception generation
3062 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3063 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3064 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3067 let Inst{31-24} = 0b11010100;
3068 let Inst{23-21} = op1;
3069 let Inst{20-5} = imm;
3070 let Inst{4-2} = 0b000;
3075 // Floating point to integer conversion
3078 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3079 RegisterClass srcType, RegisterClass dstType,
3080 string asm, list<dag> pattern>
3081 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3082 asm, "\t$Rd, $Rn", "", pattern>,
3083 Sched<[WriteFCvt]> {
3086 let Inst{30-29} = 0b00;
3087 let Inst{28-24} = 0b11110;
3088 let Inst{23-22} = type;
3090 let Inst{20-19} = rmode;
3091 let Inst{18-16} = opcode;
3092 let Inst{15-10} = 0;
3097 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3098 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3099 RegisterClass srcType, RegisterClass dstType,
3100 Operand immType, string asm, list<dag> pattern>
3101 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3102 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3103 Sched<[WriteFCvt]> {
3107 let Inst{30-29} = 0b00;
3108 let Inst{28-24} = 0b11110;
3109 let Inst{23-22} = type;
3111 let Inst{20-19} = rmode;
3112 let Inst{18-16} = opcode;
3113 let Inst{15-10} = scale;
3118 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3119 SDPatternOperator OpN> {
3120 // Unscaled single-precision to 32-bit
3121 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3122 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3123 let Inst{31} = 0; // 32-bit GPR flag
3126 // Unscaled single-precision to 64-bit
3127 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3128 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3129 let Inst{31} = 1; // 64-bit GPR flag
3132 // Unscaled double-precision to 32-bit
3133 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3134 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3135 let Inst{31} = 0; // 32-bit GPR flag
3138 // Unscaled double-precision to 64-bit
3139 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3140 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3141 let Inst{31} = 1; // 64-bit GPR flag
3145 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3146 SDPatternOperator OpN> {
3147 // Scaled single-precision to 32-bit
3148 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3149 fixedpoint_f32_i32, asm,
3150 [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3151 fixedpoint_f32_i32:$scale)))]> {
3152 let Inst{31} = 0; // 32-bit GPR flag
3156 // Scaled single-precision to 64-bit
3157 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3158 fixedpoint_f32_i64, asm,
3159 [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3160 fixedpoint_f32_i64:$scale)))]> {
3161 let Inst{31} = 1; // 64-bit GPR flag
3164 // Scaled double-precision to 32-bit
3165 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3166 fixedpoint_f64_i32, asm,
3167 [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3168 fixedpoint_f64_i32:$scale)))]> {
3169 let Inst{31} = 0; // 32-bit GPR flag
3173 // Scaled double-precision to 64-bit
3174 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3175 fixedpoint_f64_i64, asm,
3176 [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3177 fixedpoint_f64_i64:$scale)))]> {
3178 let Inst{31} = 1; // 64-bit GPR flag
3183 // Integer to floating point conversion
3186 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3187 class BaseIntegerToFP<bit isUnsigned,
3188 RegisterClass srcType, RegisterClass dstType,
3189 Operand immType, string asm, list<dag> pattern>
3190 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3191 asm, "\t$Rd, $Rn, $scale", "", pattern>,
3192 Sched<[WriteFCvt]> {
3196 let Inst{30-23} = 0b00111100;
3197 let Inst{21-17} = 0b00001;
3198 let Inst{16} = isUnsigned;
3199 let Inst{15-10} = scale;
3204 class BaseIntegerToFPUnscaled<bit isUnsigned,
3205 RegisterClass srcType, RegisterClass dstType,
3206 ValueType dvt, string asm, SDNode node>
3207 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3208 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3209 Sched<[WriteFCvt]> {
3213 let Inst{30-23} = 0b00111100;
3214 let Inst{21-17} = 0b10001;
3215 let Inst{16} = isUnsigned;
3216 let Inst{15-10} = 0b000000;
3221 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3223 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3224 let Inst{31} = 0; // 32-bit GPR flag
3225 let Inst{22} = 0; // 32-bit FPR flag
3228 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3229 let Inst{31} = 0; // 32-bit GPR flag
3230 let Inst{22} = 1; // 64-bit FPR flag
3233 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3234 let Inst{31} = 1; // 64-bit GPR flag
3235 let Inst{22} = 0; // 32-bit FPR flag
3238 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3239 let Inst{31} = 1; // 64-bit GPR flag
3240 let Inst{22} = 1; // 64-bit FPR flag
3244 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3246 (fdiv (node GPR32:$Rn),
3247 fixedpoint_f32_i32:$scale))]> {
3248 let Inst{31} = 0; // 32-bit GPR flag
3249 let Inst{22} = 0; // 32-bit FPR flag
3253 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3255 (fdiv (node GPR32:$Rn),
3256 fixedpoint_f64_i32:$scale))]> {
3257 let Inst{31} = 0; // 32-bit GPR flag
3258 let Inst{22} = 1; // 64-bit FPR flag
3262 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3264 (fdiv (node GPR64:$Rn),
3265 fixedpoint_f32_i64:$scale))]> {
3266 let Inst{31} = 1; // 64-bit GPR flag
3267 let Inst{22} = 0; // 32-bit FPR flag
3270 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3272 (fdiv (node GPR64:$Rn),
3273 fixedpoint_f64_i64:$scale))]> {
3274 let Inst{31} = 1; // 64-bit GPR flag
3275 let Inst{22} = 1; // 64-bit FPR flag
3280 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3283 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3284 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3285 RegisterClass srcType, RegisterClass dstType,
3287 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3288 // We use COPY_TO_REGCLASS for these bitconvert operations.
3289 // copyPhysReg() expands the resultant COPY instructions after
3290 // regalloc is done. This gives greater freedom for the allocator
3291 // and related passes (coalescing, copy propagation, et. al.) to
3292 // be more effective.
3293 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3294 Sched<[WriteFCopy]> {
3297 let Inst{30-23} = 0b00111100;
3299 let Inst{20-19} = rmode;
3300 let Inst{18-16} = opcode;
3301 let Inst{15-10} = 0b000000;
3306 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3307 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3308 RegisterClass srcType, RegisterOperand dstType, string asm,
3310 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3311 "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
3312 Sched<[WriteFCopy]> {
3315 let Inst{30-23} = 0b00111101;
3317 let Inst{20-19} = rmode;
3318 let Inst{18-16} = opcode;
3319 let Inst{15-10} = 0b000000;
3324 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3325 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3326 RegisterOperand srcType, RegisterClass dstType, string asm,
3328 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3329 "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
3330 Sched<[WriteFCopy]> {
3333 let Inst{30-23} = 0b00111101;
3335 let Inst{20-19} = rmode;
3336 let Inst{18-16} = opcode;
3337 let Inst{15-10} = 0b000000;
3344 multiclass UnscaledConversion<string asm> {
3345 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3346 let Inst{31} = 0; // 32-bit GPR flag
3347 let Inst{22} = 0; // 32-bit FPR flag
3350 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3351 let Inst{31} = 1; // 64-bit GPR flag
3352 let Inst{22} = 1; // 64-bit FPR flag
3355 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3356 let Inst{31} = 0; // 32-bit GPR flag
3357 let Inst{22} = 0; // 32-bit FPR flag
3360 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3361 let Inst{31} = 1; // 64-bit GPR flag
3362 let Inst{22} = 1; // 64-bit FPR flag
3365 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3371 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3379 // Floating point conversion
3382 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3383 RegisterClass srcType, string asm, list<dag> pattern>
3384 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3385 Sched<[WriteFCvt]> {
3388 let Inst{31-24} = 0b00011110;
3389 let Inst{23-22} = type;
3390 let Inst{21-17} = 0b10001;
3391 let Inst{16-15} = opcode;
3392 let Inst{14-10} = 0b10000;
3397 multiclass FPConversion<string asm> {
3398 // Double-precision to Half-precision
3399 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3400 [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3402 // Double-precision to Single-precision
3403 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3404 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3406 // Half-precision to Double-precision
3407 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3408 [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3410 // Half-precision to Single-precision
3411 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3412 [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3414 // Single-precision to Double-precision
3415 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3416 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3418 // Single-precision to Half-precision
3419 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3420 [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3424 // Single operand floating point data processing
3427 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3428 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3429 ValueType vt, string asm, SDPatternOperator node>
3430 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3431 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3435 let Inst{31-23} = 0b000111100;
3436 let Inst{21-19} = 0b100;
3437 let Inst{18-15} = opcode;
3438 let Inst{14-10} = 0b10000;
3443 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3444 SDPatternOperator node = null_frag> {
3445 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3446 let Inst{22} = 0; // 32-bit size flag
3449 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3450 let Inst{22} = 1; // 64-bit size flag
3455 // Two operand floating point data processing
3458 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3459 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3460 string asm, list<dag> pat>
3461 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3462 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3467 let Inst{31-23} = 0b000111100;
3469 let Inst{20-16} = Rm;
3470 let Inst{15-12} = opcode;
3471 let Inst{11-10} = 0b10;
3476 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3477 SDPatternOperator node = null_frag> {
3478 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3479 [(set (f32 FPR32:$Rd),
3480 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3481 let Inst{22} = 0; // 32-bit size flag
3484 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3485 [(set (f64 FPR64:$Rd),
3486 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3487 let Inst{22} = 1; // 64-bit size flag
3491 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3492 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3493 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3494 let Inst{22} = 0; // 32-bit size flag
3497 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3498 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3499 let Inst{22} = 1; // 64-bit size flag
3505 // Three operand floating point data processing
3508 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3509 RegisterClass regtype, string asm, list<dag> pat>
3510 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3511 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3512 Sched<[WriteFMul]> {
3517 let Inst{31-23} = 0b000111110;
3518 let Inst{21} = isNegated;
3519 let Inst{20-16} = Rm;
3520 let Inst{15} = isSub;
3521 let Inst{14-10} = Ra;
3526 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3527 SDPatternOperator node> {
3528 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3530 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3531 let Inst{22} = 0; // 32-bit size flag
3534 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3536 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3537 let Inst{22} = 1; // 64-bit size flag
3542 // Floating point data comparisons
3545 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3546 class BaseOneOperandFPComparison<bit signalAllNans,
3547 RegisterClass regtype, string asm,
3549 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3550 Sched<[WriteFCmp]> {
3552 let Inst{31-23} = 0b000111100;
3555 let Inst{15-10} = 0b001000;
3557 let Inst{4} = signalAllNans;
3558 let Inst{3-0} = 0b1000;
3560 // Rm should be 0b00000 canonically, but we need to accept any value.
3561 let PostEncoderMethod = "fixOneOperandFPComparison";
3564 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3565 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3566 string asm, list<dag> pat>
3567 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3568 Sched<[WriteFCmp]> {
3571 let Inst{31-23} = 0b000111100;
3573 let Inst{20-16} = Rm;
3574 let Inst{15-10} = 0b001000;
3576 let Inst{4} = signalAllNans;
3577 let Inst{3-0} = 0b0000;
3580 multiclass FPComparison<bit signalAllNans, string asm,
3581 SDPatternOperator OpNode = null_frag> {
3582 let Defs = [CPSR] in {
3583 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3584 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3588 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3589 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3593 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3594 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3598 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3599 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3606 // Floating point conditional comparisons
3609 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3610 class BaseFPCondComparison<bit signalAllNans,
3611 RegisterClass regtype, string asm>
3612 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3613 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3614 Sched<[WriteFCmp]> {
3620 let Inst{31-23} = 0b000111100;
3622 let Inst{20-16} = Rm;
3623 let Inst{15-12} = cond;
3624 let Inst{11-10} = 0b01;
3626 let Inst{4} = signalAllNans;
3627 let Inst{3-0} = nzcv;
3630 multiclass FPCondComparison<bit signalAllNans, string asm> {
3631 let Defs = [CPSR], Uses = [CPSR] in {
3632 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3636 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3639 } // Defs = [CPSR], Uses = [CPSR]
3643 // Floating point conditional select
3646 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3647 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3648 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3650 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3651 (i32 imm:$cond), CPSR))]>,
3658 let Inst{31-23} = 0b000111100;
3660 let Inst{20-16} = Rm;
3661 let Inst{15-12} = cond;
3662 let Inst{11-10} = 0b11;
3667 multiclass FPCondSelect<string asm> {
3668 let Uses = [CPSR] in {
3669 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3673 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3680 // Floating move immediate
3683 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3684 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3685 [(set regtype:$Rd, fpimmtype:$imm)]>,
3686 Sched<[WriteFImm]> {
3689 let Inst{31-23} = 0b000111100;
3691 let Inst{20-13} = imm;
3692 let Inst{12-5} = 0b10000000;
3696 multiclass FPMoveImmediate<string asm> {
3697 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3701 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3706 //----------------------------------------------------------------------------
3708 //----------------------------------------------------------------------------
3710 def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3711 def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3712 def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3713 def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3714 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3715 return ((uint64_t)Imm) < 16;
3717 let ParserMatchClass = VectorIndexBOperand;
3718 let PrintMethod = "printVectorIndex";
3719 let MIOperandInfo = (ops i64imm);
3721 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3722 return ((uint64_t)Imm) < 8;
3724 let ParserMatchClass = VectorIndexHOperand;
3725 let PrintMethod = "printVectorIndex";
3726 let MIOperandInfo = (ops i64imm);
3728 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3729 return ((uint64_t)Imm) < 4;
3731 let ParserMatchClass = VectorIndexSOperand;
3732 let PrintMethod = "printVectorIndex";
3733 let MIOperandInfo = (ops i64imm);
3735 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3736 return ((uint64_t)Imm) < 2;
3738 let ParserMatchClass = VectorIndexDOperand;
3739 let PrintMethod = "printVectorIndex";
3740 let MIOperandInfo = (ops i64imm);
3743 //----------------------------------------------------------------------------
3744 // AdvSIMD three register vector instructions
3745 //----------------------------------------------------------------------------
3747 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3748 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3749 RegisterOperand regtype, string asm, string kind,
3751 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3752 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3753 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3761 let Inst{28-24} = 0b01110;
3762 let Inst{23-22} = size;
3764 let Inst{20-16} = Rm;
3765 let Inst{15-11} = opcode;
3771 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3772 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3773 RegisterOperand regtype, string asm, string kind,
3775 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3776 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3777 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3785 let Inst{28-24} = 0b01110;
3786 let Inst{23-22} = size;
3788 let Inst{20-16} = Rm;
3789 let Inst{15-11} = opcode;
3795 // All operand sizes distinguished in the encoding.
3796 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3797 SDPatternOperator OpNode> {
3798 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3800 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3801 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3803 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3804 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3806 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3807 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3809 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3810 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3812 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3813 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3815 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3816 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3818 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3821 // As above, but D sized elements unsupported.
3822 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3823 SDPatternOperator OpNode> {
3824 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3826 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3827 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3829 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3830 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3832 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3833 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3835 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3836 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3838 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3839 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3841 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3844 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3845 SDPatternOperator OpNode> {
3846 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3848 [(set (v8i8 V64:$dst),
3849 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3850 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3852 [(set (v16i8 V128:$dst),
3853 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3854 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3856 [(set (v4i16 V64:$dst),
3857 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3858 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3860 [(set (v8i16 V128:$dst),
3861 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3862 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3864 [(set (v2i32 V64:$dst),
3865 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3866 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3868 [(set (v4i32 V128:$dst),
3869 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3872 // As above, but only B sized elements supported.
3873 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3874 SDPatternOperator OpNode> {
3875 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3877 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3878 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3880 [(set (v16i8 V128:$Rd),
3881 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3884 // As above, but only S and D sized floating point elements supported.
3885 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3886 string asm, SDPatternOperator OpNode> {
3887 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3889 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3890 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3892 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3893 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3895 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3898 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3900 SDPatternOperator OpNode> {
3901 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3903 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3904 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3906 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3907 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3909 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3912 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3913 string asm, SDPatternOperator OpNode> {
3914 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3916 [(set (v2f32 V64:$dst),
3917 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3918 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3920 [(set (v4f32 V128:$dst),
3921 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3922 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3924 [(set (v2f64 V128:$dst),
3925 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3928 // As above, but D and B sized elements unsupported.
3929 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3930 SDPatternOperator OpNode> {
3931 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3933 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3934 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3936 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3937 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3939 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3940 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3942 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3945 // Logical three vector ops share opcode bits, and only use B sized elements.
3946 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3947 SDPatternOperator OpNode = null_frag> {
3948 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3950 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3951 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3953 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3955 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3956 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3957 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3958 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3959 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3960 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3962 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3963 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3964 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3965 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3966 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3967 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3970 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3971 string asm, SDPatternOperator OpNode> {
3972 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3974 [(set (v8i8 V64:$dst),
3975 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3976 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3978 [(set (v16i8 V128:$dst),
3979 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3980 (v16i8 V128:$Rm)))]>;
3982 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3984 (!cast<Instruction>(NAME#"v8i8")
3985 V64:$LHS, V64:$MHS, V64:$RHS)>;
3986 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3988 (!cast<Instruction>(NAME#"v8i8")
3989 V64:$LHS, V64:$MHS, V64:$RHS)>;
3990 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3992 (!cast<Instruction>(NAME#"v8i8")
3993 V64:$LHS, V64:$MHS, V64:$RHS)>;
3995 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3996 (v8i16 V128:$RHS))),
3997 (!cast<Instruction>(NAME#"v16i8")
3998 V128:$LHS, V128:$MHS, V128:$RHS)>;
3999 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4000 (v4i32 V128:$RHS))),
4001 (!cast<Instruction>(NAME#"v16i8")
4002 V128:$LHS, V128:$MHS, V128:$RHS)>;
4003 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4004 (v2i64 V128:$RHS))),
4005 (!cast<Instruction>(NAME#"v16i8")
4006 V128:$LHS, V128:$MHS, V128:$RHS)>;
4010 //----------------------------------------------------------------------------
4011 // AdvSIMD two register vector instructions.
4012 //----------------------------------------------------------------------------
4014 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4015 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4016 RegisterOperand regtype, string asm, string dstkind,
4017 string srckind, list<dag> pattern>
4018 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4019 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4020 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4027 let Inst{28-24} = 0b01110;
4028 let Inst{23-22} = size;
4029 let Inst{21-17} = 0b10000;
4030 let Inst{16-12} = opcode;
4031 let Inst{11-10} = 0b10;
4036 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4037 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4038 RegisterOperand regtype, string asm, string dstkind,
4039 string srckind, list<dag> pattern>
4040 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4041 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4042 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4049 let Inst{28-24} = 0b01110;
4050 let Inst{23-22} = size;
4051 let Inst{21-17} = 0b10000;
4052 let Inst{16-12} = opcode;
4053 let Inst{11-10} = 0b10;
4058 // Supports B, H, and S element sizes.
4059 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4060 SDPatternOperator OpNode> {
4061 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4063 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4064 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4065 asm, ".16b", ".16b",
4066 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4067 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4069 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4070 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4072 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4073 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4075 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4076 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4078 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4081 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4082 RegisterOperand regtype, string asm, string dstkind,
4083 string srckind, string amount>
4084 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4085 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4086 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4092 let Inst{29-24} = 0b101110;
4093 let Inst{23-22} = size;
4094 let Inst{21-10} = 0b100001001110;
4099 multiclass SIMDVectorLShiftLongBySizeBHS {
4100 let neverHasSideEffects = 1 in {
4101 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4102 "shll", ".8h", ".8b", "8">;
4103 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4104 "shll2", ".8h", ".16b", "8">;
4105 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4106 "shll", ".4s", ".4h", "16">;
4107 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4108 "shll2", ".4s", ".8h", "16">;
4109 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4110 "shll", ".2d", ".2s", "32">;
4111 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4112 "shll2", ".2d", ".4s", "32">;
4116 // Supports all element sizes.
4117 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4118 SDPatternOperator OpNode> {
4119 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4121 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4122 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4124 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4125 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4127 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4128 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4130 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4131 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4133 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4134 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4136 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4139 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4140 SDPatternOperator OpNode> {
4141 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4143 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4145 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4147 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4148 (v16i8 V128:$Rn)))]>;
4149 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4151 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4152 (v4i16 V64:$Rn)))]>;
4153 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4155 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4156 (v8i16 V128:$Rn)))]>;
4157 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4159 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4160 (v2i32 V64:$Rn)))]>;
4161 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4163 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4164 (v4i32 V128:$Rn)))]>;
4167 // Supports all element sizes, except 1xD.
4168 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4169 SDPatternOperator OpNode> {
4170 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4172 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4173 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4174 asm, ".16b", ".16b",
4175 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4176 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4178 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4179 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4181 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4182 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4184 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4185 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4187 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4188 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4190 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4193 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4194 SDPatternOperator OpNode = null_frag> {
4195 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4197 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4198 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4199 asm, ".16b", ".16b",
4200 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4201 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4203 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4204 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4206 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4207 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4209 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4210 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4212 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4213 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4215 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4219 // Supports only B element sizes.
4220 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4221 SDPatternOperator OpNode> {
4222 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4224 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4225 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4226 asm, ".16b", ".16b",
4227 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4231 // Supports only B and H element sizes.
4232 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4233 SDPatternOperator OpNode> {
4234 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4236 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4237 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4238 asm, ".16b", ".16b",
4239 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4240 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4242 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4243 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4245 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4248 // Supports only S and D element sizes, uses high bit of the size field
4249 // as an extra opcode bit.
4250 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4251 SDPatternOperator OpNode> {
4252 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4254 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4255 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4257 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4258 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4260 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4263 // Supports only S element size.
4264 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4265 SDPatternOperator OpNode> {
4266 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4268 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4269 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4271 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4275 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4276 SDPatternOperator OpNode> {
4277 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4279 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4280 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4282 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4283 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4285 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4288 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4289 SDPatternOperator OpNode> {
4290 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4292 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4293 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4295 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4296 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4298 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4302 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4303 RegisterOperand inreg, RegisterOperand outreg,
4304 string asm, string outkind, string inkind,
4306 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4307 "{\t$Rd" # outkind # ", $Rn" # inkind #
4308 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4315 let Inst{28-24} = 0b01110;
4316 let Inst{23-22} = size;
4317 let Inst{21-17} = 0b10000;
4318 let Inst{16-12} = opcode;
4319 let Inst{11-10} = 0b10;
4324 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4325 RegisterOperand inreg, RegisterOperand outreg,
4326 string asm, string outkind, string inkind,
4328 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4329 "{\t$Rd" # outkind # ", $Rn" # inkind #
4330 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4337 let Inst{28-24} = 0b01110;
4338 let Inst{23-22} = size;
4339 let Inst{21-17} = 0b10000;
4340 let Inst{16-12} = opcode;
4341 let Inst{11-10} = 0b10;
4346 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4347 SDPatternOperator OpNode> {
4348 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4350 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4351 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4352 asm#"2", ".16b", ".8h", []>;
4353 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4355 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4356 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4357 asm#"2", ".8h", ".4s", []>;
4358 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4360 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4361 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4362 asm#"2", ".4s", ".2d", []>;
4364 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4365 (!cast<Instruction>(NAME # "v16i8")
4366 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4367 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4368 (!cast<Instruction>(NAME # "v8i16")
4369 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4370 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4371 (!cast<Instruction>(NAME # "v4i32")
4372 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4375 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4376 RegisterOperand regtype, string asm, string kind,
4377 ValueType dty, ValueType sty, SDNode OpNode>
4378 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4379 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4380 "|" # kind # "\t$Rd, $Rn, #0}", "",
4381 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4388 let Inst{28-24} = 0b01110;
4389 let Inst{23-22} = size;
4390 let Inst{21-17} = 0b10000;
4391 let Inst{16-12} = opcode;
4392 let Inst{11-10} = 0b10;
4397 // Comparisons support all element sizes, except 1xD.
4398 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4400 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4402 v8i8, v8i8, OpNode>;
4403 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4405 v16i8, v16i8, OpNode>;
4406 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4408 v4i16, v4i16, OpNode>;
4409 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4411 v8i16, v8i16, OpNode>;
4412 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4414 v2i32, v2i32, OpNode>;
4415 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4417 v4i32, v4i32, OpNode>;
4418 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4420 v2i64, v2i64, OpNode>;
4423 // FP Comparisons support only S and D element sizes.
4424 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4425 string asm, SDNode OpNode> {
4426 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4428 v2i32, v2f32, OpNode>;
4429 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4431 v4i32, v4f32, OpNode>;
4432 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4434 v2i64, v2f64, OpNode>;
4437 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4438 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4439 RegisterOperand outtype, RegisterOperand intype,
4440 string asm, string VdTy, string VnTy,
4442 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4443 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4450 let Inst{28-24} = 0b01110;
4451 let Inst{23-22} = size;
4452 let Inst{21-17} = 0b10000;
4453 let Inst{16-12} = opcode;
4454 let Inst{11-10} = 0b10;
4459 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4460 RegisterOperand outtype, RegisterOperand intype,
4461 string asm, string VdTy, string VnTy,
4463 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4464 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4471 let Inst{28-24} = 0b01110;
4472 let Inst{23-22} = size;
4473 let Inst{21-17} = 0b10000;
4474 let Inst{16-12} = opcode;
4475 let Inst{11-10} = 0b10;
4480 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4481 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4482 asm, ".4s", ".4h", []>;
4483 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4484 asm#"2", ".4s", ".8h", []>;
4485 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4486 asm, ".2d", ".2s", []>;
4487 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4488 asm#"2", ".2d", ".4s", []>;
4491 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4492 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4493 asm, ".4h", ".4s", []>;
4494 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4495 asm#"2", ".8h", ".4s", []>;
4496 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4497 asm, ".2s", ".2d", []>;
4498 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4499 asm#"2", ".4s", ".2d", []>;
4502 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4504 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4506 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4507 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4508 asm#"2", ".4s", ".2d", []>;
4510 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4511 (!cast<Instruction>(NAME # "v4f32")
4512 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4515 //----------------------------------------------------------------------------
4516 // AdvSIMD three register different-size vector instructions.
4517 //----------------------------------------------------------------------------
4519 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4520 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4521 RegisterOperand outtype, RegisterOperand intype1,
4522 RegisterOperand intype2, string asm,
4523 string outkind, string inkind1, string inkind2,
4525 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4526 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4527 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4533 let Inst{30} = size{0};
4535 let Inst{28-24} = 0b01110;
4536 let Inst{23-22} = size{2-1};
4538 let Inst{20-16} = Rm;
4539 let Inst{15-12} = opcode;
4540 let Inst{11-10} = 0b00;
4545 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4546 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4547 RegisterOperand outtype, RegisterOperand intype1,
4548 RegisterOperand intype2, string asm,
4549 string outkind, string inkind1, string inkind2,
4551 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4552 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4553 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4559 let Inst{30} = size{0};
4561 let Inst{28-24} = 0b01110;
4562 let Inst{23-22} = size{2-1};
4564 let Inst{20-16} = Rm;
4565 let Inst{15-12} = opcode;
4566 let Inst{11-10} = 0b00;
4571 // FIXME: TableGen doesn't know how to deal with expanded types that also
4572 // change the element count (in this case, placing the results in
4573 // the high elements of the result register rather than the low
4574 // elements). Until that's fixed, we can't code-gen those.
4575 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4577 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4579 asm, ".8b", ".8h", ".8h",
4580 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4581 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4583 asm#"2", ".16b", ".8h", ".8h",
4585 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4587 asm, ".4h", ".4s", ".4s",
4588 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4589 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4591 asm#"2", ".8h", ".4s", ".4s",
4593 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4595 asm, ".2s", ".2d", ".2d",
4596 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4597 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4599 asm#"2", ".4s", ".2d", ".2d",
4603 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4604 // a version attached to an instruction.
4605 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4607 (!cast<Instruction>(NAME # "v8i16_v16i8")
4608 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4609 V128:$Rn, V128:$Rm)>;
4610 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4612 (!cast<Instruction>(NAME # "v4i32_v8i16")
4613 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4614 V128:$Rn, V128:$Rm)>;
4615 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4617 (!cast<Instruction>(NAME # "v2i64_v4i32")
4618 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4619 V128:$Rn, V128:$Rm)>;
4622 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4624 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4626 asm, ".8h", ".8b", ".8b",
4627 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4628 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4630 asm#"2", ".8h", ".16b", ".16b", []>;
4631 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4633 asm, ".1q", ".1d", ".1d", []>;
4634 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4636 asm#"2", ".1q", ".2d", ".2d", []>;
4638 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4639 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4640 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4643 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4644 SDPatternOperator OpNode> {
4645 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4647 asm, ".4s", ".4h", ".4h",
4648 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4649 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4651 asm#"2", ".4s", ".8h", ".8h",
4652 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4653 (extract_high_v8i16 V128:$Rm)))]>;
4654 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4656 asm, ".2d", ".2s", ".2s",
4657 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4658 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4660 asm#"2", ".2d", ".4s", ".4s",
4661 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4662 (extract_high_v4i32 V128:$Rm)))]>;
4665 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4666 SDPatternOperator OpNode = null_frag> {
4667 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4669 asm, ".8h", ".8b", ".8b",
4670 [(set (v8i16 V128:$Rd),
4671 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4672 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4674 asm#"2", ".8h", ".16b", ".16b",
4675 [(set (v8i16 V128:$Rd),
4676 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4677 (extract_high_v16i8 V128:$Rm)))))]>;
4678 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4680 asm, ".4s", ".4h", ".4h",
4681 [(set (v4i32 V128:$Rd),
4682 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4683 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4685 asm#"2", ".4s", ".8h", ".8h",
4686 [(set (v4i32 V128:$Rd),
4687 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4688 (extract_high_v8i16 V128:$Rm)))))]>;
4689 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4691 asm, ".2d", ".2s", ".2s",
4692 [(set (v2i64 V128:$Rd),
4693 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4694 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4696 asm#"2", ".2d", ".4s", ".4s",
4697 [(set (v2i64 V128:$Rd),
4698 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4699 (extract_high_v4i32 V128:$Rm)))))]>;
4702 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4704 SDPatternOperator OpNode> {
4705 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4707 asm, ".8h", ".8b", ".8b",
4708 [(set (v8i16 V128:$dst),
4709 (add (v8i16 V128:$Rd),
4710 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4711 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4713 asm#"2", ".8h", ".16b", ".16b",
4714 [(set (v8i16 V128:$dst),
4715 (add (v8i16 V128:$Rd),
4716 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4717 (extract_high_v16i8 V128:$Rm))))))]>;
4718 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4720 asm, ".4s", ".4h", ".4h",
4721 [(set (v4i32 V128:$dst),
4722 (add (v4i32 V128:$Rd),
4723 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4724 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4726 asm#"2", ".4s", ".8h", ".8h",
4727 [(set (v4i32 V128:$dst),
4728 (add (v4i32 V128:$Rd),
4729 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4730 (extract_high_v8i16 V128:$Rm))))))]>;
4731 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4733 asm, ".2d", ".2s", ".2s",
4734 [(set (v2i64 V128:$dst),
4735 (add (v2i64 V128:$Rd),
4736 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4737 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4739 asm#"2", ".2d", ".4s", ".4s",
4740 [(set (v2i64 V128:$dst),
4741 (add (v2i64 V128:$Rd),
4742 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4743 (extract_high_v4i32 V128:$Rm))))))]>;
4746 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4747 SDPatternOperator OpNode = null_frag> {
4748 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4750 asm, ".8h", ".8b", ".8b",
4751 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4752 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4754 asm#"2", ".8h", ".16b", ".16b",
4755 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4756 (extract_high_v16i8 V128:$Rm)))]>;
4757 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4759 asm, ".4s", ".4h", ".4h",
4760 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4761 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4763 asm#"2", ".4s", ".8h", ".8h",
4764 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4765 (extract_high_v8i16 V128:$Rm)))]>;
4766 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4768 asm, ".2d", ".2s", ".2s",
4769 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4770 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4772 asm#"2", ".2d", ".4s", ".4s",
4773 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4774 (extract_high_v4i32 V128:$Rm)))]>;
4777 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4779 SDPatternOperator OpNode> {
4780 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4782 asm, ".8h", ".8b", ".8b",
4783 [(set (v8i16 V128:$dst),
4784 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4785 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4787 asm#"2", ".8h", ".16b", ".16b",
4788 [(set (v8i16 V128:$dst),
4789 (OpNode (v8i16 V128:$Rd),
4790 (extract_high_v16i8 V128:$Rn),
4791 (extract_high_v16i8 V128:$Rm)))]>;
4792 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4794 asm, ".4s", ".4h", ".4h",
4795 [(set (v4i32 V128:$dst),
4796 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4797 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4799 asm#"2", ".4s", ".8h", ".8h",
4800 [(set (v4i32 V128:$dst),
4801 (OpNode (v4i32 V128:$Rd),
4802 (extract_high_v8i16 V128:$Rn),
4803 (extract_high_v8i16 V128:$Rm)))]>;
4804 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4806 asm, ".2d", ".2s", ".2s",
4807 [(set (v2i64 V128:$dst),
4808 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4809 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4811 asm#"2", ".2d", ".4s", ".4s",
4812 [(set (v2i64 V128:$dst),
4813 (OpNode (v2i64 V128:$Rd),
4814 (extract_high_v4i32 V128:$Rn),
4815 (extract_high_v4i32 V128:$Rm)))]>;
4818 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4819 SDPatternOperator Accum> {
4820 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4822 asm, ".4s", ".4h", ".4h",
4823 [(set (v4i32 V128:$dst),
4824 (Accum (v4i32 V128:$Rd),
4825 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4826 (v4i16 V64:$Rm)))))]>;
4827 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4829 asm#"2", ".4s", ".8h", ".8h",
4830 [(set (v4i32 V128:$dst),
4831 (Accum (v4i32 V128:$Rd),
4832 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4833 (extract_high_v8i16 V128:$Rm)))))]>;
4834 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4836 asm, ".2d", ".2s", ".2s",
4837 [(set (v2i64 V128:$dst),
4838 (Accum (v2i64 V128:$Rd),
4839 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4840 (v2i32 V64:$Rm)))))]>;
4841 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4843 asm#"2", ".2d", ".4s", ".4s",
4844 [(set (v2i64 V128:$dst),
4845 (Accum (v2i64 V128:$Rd),
4846 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4847 (extract_high_v4i32 V128:$Rm)))))]>;
4850 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4851 SDPatternOperator OpNode> {
4852 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4854 asm, ".8h", ".8h", ".8b",
4855 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4856 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4858 asm#"2", ".8h", ".8h", ".16b",
4859 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4860 (extract_high_v16i8 V128:$Rm)))]>;
4861 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4863 asm, ".4s", ".4s", ".4h",
4864 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4865 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4867 asm#"2", ".4s", ".4s", ".8h",
4868 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4869 (extract_high_v8i16 V128:$Rm)))]>;
4870 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4872 asm, ".2d", ".2d", ".2s",
4873 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4874 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4876 asm#"2", ".2d", ".2d", ".4s",
4877 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4878 (extract_high_v4i32 V128:$Rm)))]>;
4881 //----------------------------------------------------------------------------
4882 // AdvSIMD bitwise extract from vector
4883 //----------------------------------------------------------------------------
4885 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4886 string asm, string kind>
4887 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4888 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4889 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4890 [(set (vty regtype:$Rd),
4891 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4898 let Inst{30} = size;
4899 let Inst{29-21} = 0b101110000;
4900 let Inst{20-16} = Rm;
4902 let Inst{14-11} = imm;
4909 multiclass SIMDBitwiseExtract<string asm> {
4910 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4913 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4916 //----------------------------------------------------------------------------
4917 // AdvSIMD zip vector
4918 //----------------------------------------------------------------------------
4920 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4921 string asm, string kind, SDNode OpNode, ValueType valty>
4922 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4923 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4924 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4925 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4931 let Inst{30} = size{0};
4932 let Inst{29-24} = 0b001110;
4933 let Inst{23-22} = size{2-1};
4935 let Inst{20-16} = Rm;
4937 let Inst{14-12} = opc;
4938 let Inst{11-10} = 0b10;
4943 multiclass SIMDZipVector<bits<3>opc, string asm,
4945 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4946 asm, ".8b", OpNode, v8i8>;
4947 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4948 asm, ".16b", OpNode, v16i8>;
4949 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4950 asm, ".4h", OpNode, v4i16>;
4951 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4952 asm, ".8h", OpNode, v8i16>;
4953 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4954 asm, ".2s", OpNode, v2i32>;
4955 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4956 asm, ".4s", OpNode, v4i32>;
4957 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4958 asm, ".2d", OpNode, v2i64>;
4960 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4961 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4962 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4963 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4964 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4965 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4968 //----------------------------------------------------------------------------
4969 // AdvSIMD three register scalar instructions
4970 //----------------------------------------------------------------------------
4972 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4973 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4974 RegisterClass regtype, string asm,
4976 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4977 "\t$Rd, $Rn, $Rm", "", pattern>,
4982 let Inst{31-30} = 0b01;
4984 let Inst{28-24} = 0b11110;
4985 let Inst{23-22} = size;
4987 let Inst{20-16} = Rm;
4988 let Inst{15-11} = opcode;
4994 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4995 SDPatternOperator OpNode> {
4996 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4997 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5000 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5001 SDPatternOperator OpNode> {
5002 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5003 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5004 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5005 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5006 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5008 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5009 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5010 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5011 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5014 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5015 SDPatternOperator OpNode> {
5016 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5017 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5018 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5021 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5022 SDPatternOperator OpNode = null_frag> {
5023 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5024 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5025 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5026 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5027 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5030 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5031 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5034 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5035 SDPatternOperator OpNode = null_frag> {
5036 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5037 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5038 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5039 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5040 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5043 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5044 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5047 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5048 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5049 : I<oops, iops, asm,
5050 "\t$Rd, $Rn, $Rm", cstr, pat>,
5055 let Inst{31-30} = 0b01;
5057 let Inst{28-24} = 0b11110;
5058 let Inst{23-22} = size;
5060 let Inst{20-16} = Rm;
5061 let Inst{15-11} = opcode;
5067 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5068 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5069 SDPatternOperator OpNode = null_frag> {
5070 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5072 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5073 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5075 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5076 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5079 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5080 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5081 SDPatternOperator OpNode = null_frag> {
5082 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5084 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5085 asm, "$Rd = $dst", []>;
5086 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5088 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5090 [(set (i64 FPR64:$dst),
5091 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5094 //----------------------------------------------------------------------------
5095 // AdvSIMD two register scalar instructions
5096 //----------------------------------------------------------------------------
5098 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5099 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5100 RegisterClass regtype, RegisterClass regtype2,
5101 string asm, list<dag> pat>
5102 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5103 "\t$Rd, $Rn", "", pat>,
5107 let Inst{31-30} = 0b01;
5109 let Inst{28-24} = 0b11110;
5110 let Inst{23-22} = size;
5111 let Inst{21-17} = 0b10000;
5112 let Inst{16-12} = opcode;
5113 let Inst{11-10} = 0b10;
5118 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5119 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5120 RegisterClass regtype, RegisterClass regtype2,
5121 string asm, list<dag> pat>
5122 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5123 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5127 let Inst{31-30} = 0b01;
5129 let Inst{28-24} = 0b11110;
5130 let Inst{23-22} = size;
5131 let Inst{21-17} = 0b10000;
5132 let Inst{16-12} = opcode;
5133 let Inst{11-10} = 0b10;
5139 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5140 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5141 RegisterClass regtype, string asm>
5142 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5143 "\t$Rd, $Rn, #0", "", []>,
5147 let Inst{31-30} = 0b01;
5149 let Inst{28-24} = 0b11110;
5150 let Inst{23-22} = size;
5151 let Inst{21-17} = 0b10000;
5152 let Inst{16-12} = opcode;
5153 let Inst{11-10} = 0b10;
5158 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5159 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5160 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5164 let Inst{31-17} = 0b011111100110000;
5165 let Inst{16-12} = opcode;
5166 let Inst{11-10} = 0b10;
5171 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5172 SDPatternOperator OpNode> {
5173 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5175 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5176 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5179 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5180 SDPatternOperator OpNode> {
5181 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5182 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5184 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5185 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5188 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5189 SDPatternOperator OpNode = null_frag> {
5190 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5191 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5193 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5194 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5197 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5198 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5199 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5202 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5203 SDPatternOperator OpNode> {
5204 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5205 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5206 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5207 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5210 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5211 SDPatternOperator OpNode = null_frag> {
5212 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5213 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5214 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5215 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5216 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5217 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5218 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5221 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5222 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5225 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5227 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5228 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5229 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5230 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5231 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5232 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5233 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5236 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5237 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5242 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5243 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5244 SDPatternOperator OpNode = null_frag> {
5245 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5246 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5247 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5248 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5251 //----------------------------------------------------------------------------
5252 // AdvSIMD scalar pairwise instructions
5253 //----------------------------------------------------------------------------
5255 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5256 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5257 RegisterOperand regtype, RegisterOperand vectype,
5258 string asm, string kind>
5259 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5260 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5264 let Inst{31-30} = 0b01;
5266 let Inst{28-24} = 0b11110;
5267 let Inst{23-22} = size;
5268 let Inst{21-17} = 0b11000;
5269 let Inst{16-12} = opcode;
5270 let Inst{11-10} = 0b10;
5275 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5276 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5280 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5281 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5283 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5287 //----------------------------------------------------------------------------
5288 // AdvSIMD across lanes instructions
5289 //----------------------------------------------------------------------------
5291 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5292 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5293 RegisterClass regtype, RegisterOperand vectype,
5294 string asm, string kind, list<dag> pattern>
5295 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5296 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5303 let Inst{28-24} = 0b01110;
5304 let Inst{23-22} = size;
5305 let Inst{21-17} = 0b11000;
5306 let Inst{16-12} = opcode;
5307 let Inst{11-10} = 0b10;
5312 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5314 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5316 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5318 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5320 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5322 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5326 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5327 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5329 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5331 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5333 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5335 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5339 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5341 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5343 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5346 //----------------------------------------------------------------------------
5347 // AdvSIMD INS/DUP instructions
5348 //----------------------------------------------------------------------------
5350 // FIXME: There has got to be a better way to factor these. ugh.
5352 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5353 string operands, string constraints, list<dag> pattern>
5354 : I<outs, ins, asm, operands, constraints, pattern>,
5361 let Inst{28-21} = 0b01110000;
5368 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5369 RegisterOperand vecreg, RegisterClass regtype>
5370 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5371 "{\t$Rd" # size # ", $Rn" #
5372 "|" # size # "\t$Rd, $Rn}", "",
5373 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5374 let Inst{20-16} = imm5;
5375 let Inst{14-11} = 0b0001;
5378 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5379 ValueType vectype, ValueType insreg,
5380 RegisterOperand vecreg, Operand idxtype,
5381 ValueType elttype, SDNode OpNode>
5382 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5383 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5384 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5385 [(set (vectype vecreg:$Rd),
5386 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5387 let Inst{14-11} = 0b0000;
5390 class SIMDDup64FromElement
5391 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5392 VectorIndexD, i64, ARM64duplane64> {
5395 let Inst{19-16} = 0b1000;
5398 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5399 RegisterOperand vecreg>
5400 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5401 VectorIndexS, i64, ARM64duplane32> {
5403 let Inst{20-19} = idx;
5404 let Inst{18-16} = 0b100;
5407 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5408 RegisterOperand vecreg>
5409 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5410 VectorIndexH, i64, ARM64duplane16> {
5412 let Inst{20-18} = idx;
5413 let Inst{17-16} = 0b10;
5416 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5417 RegisterOperand vecreg>
5418 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5419 VectorIndexB, i64, ARM64duplane8> {
5421 let Inst{20-17} = idx;
5425 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5426 Operand idxtype, string asm, list<dag> pattern>
5427 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5428 "{\t$Rd, $Rn" # size # "$idx" #
5429 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5430 let Inst{14-11} = imm4;
5433 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5435 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5436 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5438 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5439 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5441 class SIMDMovAlias<string asm, string size, Instruction inst,
5442 RegisterClass regtype, Operand idxtype>
5443 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5444 "|" # size # "\t$dst, $src$idx}",
5445 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5448 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5450 let Inst{20-17} = idx;
5453 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5455 let Inst{20-17} = idx;
5458 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5460 let Inst{20-18} = idx;
5461 let Inst{17-16} = 0b10;
5463 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5465 let Inst{20-18} = idx;
5466 let Inst{17-16} = 0b10;
5468 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5470 let Inst{20-19} = idx;
5471 let Inst{18-16} = 0b100;
5476 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5478 let Inst{20-17} = idx;
5481 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5483 let Inst{20-18} = idx;
5484 let Inst{17-16} = 0b10;
5486 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5488 let Inst{20-19} = idx;
5489 let Inst{18-16} = 0b100;
5491 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5494 let Inst{19-16} = 0b1000;
5496 def : SIMDMovAlias<"mov", ".s",
5497 !cast<Instruction>(NAME#"vi32"),
5498 GPR32, VectorIndexS>;
5499 def : SIMDMovAlias<"mov", ".d",
5500 !cast<Instruction>(NAME#"vi64"),
5501 GPR64, VectorIndexD>;
5504 class SIMDInsFromMain<string size, ValueType vectype,
5505 RegisterClass regtype, Operand idxtype>
5506 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5507 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5508 "{\t$Rd" # size # "$idx, $Rn" #
5509 "|" # size # "\t$Rd$idx, $Rn}",
5512 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5513 let Inst{14-11} = 0b0011;
5516 class SIMDInsFromElement<string size, ValueType vectype,
5517 ValueType elttype, Operand idxtype>
5518 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5519 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5520 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5521 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5526 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5529 class SIMDInsMainMovAlias<string size, Instruction inst,
5530 RegisterClass regtype, Operand idxtype>
5531 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5532 "|" # size #"\t$dst$idx, $src}",
5533 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5534 class SIMDInsElementMovAlias<string size, Instruction inst,
5536 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5537 # "|" # size #" $dst$idx, $src$idx2}",
5538 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5541 multiclass SIMDIns {
5542 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5544 let Inst{20-17} = idx;
5547 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5549 let Inst{20-18} = idx;
5550 let Inst{17-16} = 0b10;
5552 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5554 let Inst{20-19} = idx;
5555 let Inst{18-16} = 0b100;
5557 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5560 let Inst{19-16} = 0b1000;
5563 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5566 let Inst{20-17} = idx;
5568 let Inst{14-11} = idx2;
5570 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5573 let Inst{20-18} = idx;
5574 let Inst{17-16} = 0b10;
5575 let Inst{14-12} = idx2;
5578 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5581 let Inst{20-19} = idx;
5582 let Inst{18-16} = 0b100;
5583 let Inst{14-13} = idx2;
5584 let Inst{12-11} = 0;
5586 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5590 let Inst{19-16} = 0b1000;
5591 let Inst{14} = idx2;
5592 let Inst{13-11} = 0;
5595 // For all forms of the INS instruction, the "mov" mnemonic is the
5596 // preferred alias. Why they didn't just call the instruction "mov" in
5597 // the first place is a very good question indeed...
5598 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5599 GPR32, VectorIndexB>;
5600 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5601 GPR32, VectorIndexH>;
5602 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5603 GPR32, VectorIndexS>;
5604 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5605 GPR64, VectorIndexD>;
5607 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5609 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5611 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5613 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5617 //----------------------------------------------------------------------------
5619 //----------------------------------------------------------------------------
5621 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5622 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5623 RegisterOperand listtype, string asm, string kind>
5624 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5625 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5632 let Inst{29-21} = 0b001110000;
5633 let Inst{20-16} = Vm;
5635 let Inst{14-13} = len;
5637 let Inst{11-10} = 0b00;
5642 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5643 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5644 RegisterOperand listtype, string asm, string kind>
5645 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5646 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5653 let Inst{29-21} = 0b001110000;
5654 let Inst{20-16} = Vm;
5656 let Inst{14-13} = len;
5658 let Inst{11-10} = 0b00;
5663 class SIMDTableLookupAlias<string asm, Instruction inst,
5664 RegisterOperand vectype, RegisterOperand listtype>
5665 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5666 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5668 multiclass SIMDTableLookup<bit op, string asm> {
5669 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5671 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5673 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5675 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5677 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5679 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5681 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5683 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5686 def : SIMDTableLookupAlias<asm # ".8b",
5687 !cast<Instruction>(NAME#"v8i8One"),
5688 V64, VecListOne128>;
5689 def : SIMDTableLookupAlias<asm # ".8b",
5690 !cast<Instruction>(NAME#"v8i8Two"),
5691 V64, VecListTwo128>;
5692 def : SIMDTableLookupAlias<asm # ".8b",
5693 !cast<Instruction>(NAME#"v8i8Three"),
5694 V64, VecListThree128>;
5695 def : SIMDTableLookupAlias<asm # ".8b",
5696 !cast<Instruction>(NAME#"v8i8Four"),
5697 V64, VecListFour128>;
5698 def : SIMDTableLookupAlias<asm # ".16b",
5699 !cast<Instruction>(NAME#"v16i8One"),
5700 V128, VecListOne128>;
5701 def : SIMDTableLookupAlias<asm # ".16b",
5702 !cast<Instruction>(NAME#"v16i8Two"),
5703 V128, VecListTwo128>;
5704 def : SIMDTableLookupAlias<asm # ".16b",
5705 !cast<Instruction>(NAME#"v16i8Three"),
5706 V128, VecListThree128>;
5707 def : SIMDTableLookupAlias<asm # ".16b",
5708 !cast<Instruction>(NAME#"v16i8Four"),
5709 V128, VecListFour128>;
5712 multiclass SIMDTableLookupTied<bit op, string asm> {
5713 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5715 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5717 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5719 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5721 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5723 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5725 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5727 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5730 def : SIMDTableLookupAlias<asm # ".8b",
5731 !cast<Instruction>(NAME#"v8i8One"),
5732 V64, VecListOne128>;
5733 def : SIMDTableLookupAlias<asm # ".8b",
5734 !cast<Instruction>(NAME#"v8i8Two"),
5735 V64, VecListTwo128>;
5736 def : SIMDTableLookupAlias<asm # ".8b",
5737 !cast<Instruction>(NAME#"v8i8Three"),
5738 V64, VecListThree128>;
5739 def : SIMDTableLookupAlias<asm # ".8b",
5740 !cast<Instruction>(NAME#"v8i8Four"),
5741 V64, VecListFour128>;
5742 def : SIMDTableLookupAlias<asm # ".16b",
5743 !cast<Instruction>(NAME#"v16i8One"),
5744 V128, VecListOne128>;
5745 def : SIMDTableLookupAlias<asm # ".16b",
5746 !cast<Instruction>(NAME#"v16i8Two"),
5747 V128, VecListTwo128>;
5748 def : SIMDTableLookupAlias<asm # ".16b",
5749 !cast<Instruction>(NAME#"v16i8Three"),
5750 V128, VecListThree128>;
5751 def : SIMDTableLookupAlias<asm # ".16b",
5752 !cast<Instruction>(NAME#"v16i8Four"),
5753 V128, VecListFour128>;
5757 //----------------------------------------------------------------------------
5758 // AdvSIMD scalar CPY
5759 //----------------------------------------------------------------------------
5760 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5761 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5762 string kind, Operand idxtype>
5763 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5764 "{\t$dst, $src" # kind # "$idx" #
5765 "|\t$dst, $src$idx}", "", []>,
5769 let Inst{31-21} = 0b01011110000;
5770 let Inst{15-10} = 0b000001;
5771 let Inst{9-5} = src;
5772 let Inst{4-0} = dst;
5775 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5776 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5777 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5778 # "|\t$dst, $src$index}",
5779 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5782 multiclass SIMDScalarCPY<string asm> {
5783 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5785 let Inst{20-17} = idx;
5788 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5790 let Inst{20-18} = idx;
5791 let Inst{17-16} = 0b10;
5793 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5795 let Inst{20-19} = idx;
5796 let Inst{18-16} = 0b100;
5798 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5801 let Inst{19-16} = 0b1000;
5804 // 'DUP' mnemonic aliases.
5805 def : SIMDScalarCPYAlias<"dup", ".b",
5806 !cast<Instruction>(NAME#"i8"),
5807 FPR8, V128, VectorIndexB>;
5808 def : SIMDScalarCPYAlias<"dup", ".h",
5809 !cast<Instruction>(NAME#"i16"),
5810 FPR16, V128, VectorIndexH>;
5811 def : SIMDScalarCPYAlias<"dup", ".s",
5812 !cast<Instruction>(NAME#"i32"),
5813 FPR32, V128, VectorIndexS>;
5814 def : SIMDScalarCPYAlias<"dup", ".d",
5815 !cast<Instruction>(NAME#"i64"),
5816 FPR64, V128, VectorIndexD>;
5819 //----------------------------------------------------------------------------
5820 // AdvSIMD modified immediate instructions
5821 //----------------------------------------------------------------------------
5823 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5824 string asm, string op_string,
5825 string cstr, list<dag> pattern>
5826 : I<oops, iops, asm, op_string, cstr, pattern>,
5833 let Inst{28-19} = 0b0111100000;
5834 let Inst{18-16} = imm8{7-5};
5835 let Inst{11-10} = 0b01;
5836 let Inst{9-5} = imm8{4-0};
5840 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5841 Operand immtype, dag opt_shift_iop,
5842 string opt_shift, string asm, string kind,
5844 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5845 !con((ins immtype:$imm8), opt_shift_iop), asm,
5846 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5847 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5849 let DecoderMethod = "DecodeModImmInstruction";
5852 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5853 Operand immtype, dag opt_shift_iop,
5854 string opt_shift, string asm, string kind,
5856 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5857 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5858 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5859 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5860 "$Rd = $dst", pattern> {
5861 let DecoderMethod = "DecodeModImmTiedInstruction";
5864 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5865 RegisterOperand vectype, string asm,
5866 string kind, list<dag> pattern>
5867 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5868 (ins logical_vec_shift:$shift),
5869 "$shift", asm, kind, pattern> {
5871 let Inst{15} = b15_b12{1};
5872 let Inst{14-13} = shift;
5873 let Inst{12} = b15_b12{0};
5876 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5877 RegisterOperand vectype, string asm,
5878 string kind, list<dag> pattern>
5879 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5880 (ins logical_vec_shift:$shift),
5881 "$shift", asm, kind, pattern> {
5883 let Inst{15} = b15_b12{1};
5884 let Inst{14-13} = shift;
5885 let Inst{12} = b15_b12{0};
5889 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5890 RegisterOperand vectype, string asm,
5891 string kind, list<dag> pattern>
5892 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5893 (ins logical_vec_hw_shift:$shift),
5894 "$shift", asm, kind, pattern> {
5896 let Inst{15} = b15_b12{1};
5898 let Inst{13} = shift{0};
5899 let Inst{12} = b15_b12{0};
5902 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5903 RegisterOperand vectype, string asm,
5904 string kind, list<dag> pattern>
5905 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5906 (ins logical_vec_hw_shift:$shift),
5907 "$shift", asm, kind, pattern> {
5909 let Inst{15} = b15_b12{1};
5911 let Inst{13} = shift{0};
5912 let Inst{12} = b15_b12{0};
5915 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5917 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5919 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5922 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5924 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5928 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5929 bits<2> w_cmode, string asm,
5931 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5933 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5935 (i32 imm:$shift)))]>;
5936 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5938 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5940 (i32 imm:$shift)))]>;
5942 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5944 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5946 (i32 imm:$shift)))]>;
5947 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5949 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5951 (i32 imm:$shift)))]>;
5954 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5955 RegisterOperand vectype, string asm,
5956 string kind, list<dag> pattern>
5957 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5958 (ins move_vec_shift:$shift),
5959 "$shift", asm, kind, pattern> {
5961 let Inst{15-13} = cmode{3-1};
5962 let Inst{12} = shift;
5965 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5966 RegisterOperand vectype,
5967 Operand imm_type, string asm,
5968 string kind, list<dag> pattern>
5969 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5970 asm, kind, pattern> {
5971 let Inst{15-12} = cmode;
5974 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5976 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5977 "\t$Rd, $imm8", "", pattern> {
5978 let Inst{15-12} = cmode;
5979 let DecoderMethod = "DecodeModImmInstruction";
5982 //----------------------------------------------------------------------------
5983 // AdvSIMD indexed element
5984 //----------------------------------------------------------------------------
5986 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5987 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5988 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5989 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5990 string apple_kind, string dst_kind, string lhs_kind,
5991 string rhs_kind, list<dag> pattern>
5992 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5994 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5995 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6004 let Inst{28} = Scalar;
6005 let Inst{27-24} = 0b1111;
6006 let Inst{23-22} = size;
6007 // Bit 21 must be set by the derived class.
6008 let Inst{20-16} = Rm;
6009 let Inst{15-12} = opc;
6010 // Bit 11 must be set by the derived class.
6016 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6017 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6018 RegisterOperand dst_reg, RegisterOperand lhs_reg,
6019 RegisterOperand rhs_reg, Operand vec_idx, string asm,
6020 string apple_kind, string dst_kind, string lhs_kind,
6021 string rhs_kind, list<dag> pattern>
6022 : I<(outs dst_reg:$dst),
6023 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6024 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6025 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6034 let Inst{28} = Scalar;
6035 let Inst{27-24} = 0b1111;
6036 let Inst{23-22} = size;
6037 // Bit 21 must be set by the derived class.
6038 let Inst{20-16} = Rm;
6039 let Inst{15-12} = opc;
6040 // Bit 11 must be set by the derived class.
6046 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6047 SDPatternOperator OpNode> {
6048 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6051 asm, ".2s", ".2s", ".2s", ".s",
6052 [(set (v2f32 V64:$Rd),
6053 (OpNode (v2f32 V64:$Rn),
6054 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6056 let Inst{11} = idx{1};
6057 let Inst{21} = idx{0};
6060 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6063 asm, ".4s", ".4s", ".4s", ".s",
6064 [(set (v4f32 V128:$Rd),
6065 (OpNode (v4f32 V128:$Rn),
6066 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6068 let Inst{11} = idx{1};
6069 let Inst{21} = idx{0};
6072 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6075 asm, ".2d", ".2d", ".2d", ".d",
6076 [(set (v2f64 V128:$Rd),
6077 (OpNode (v2f64 V128:$Rn),
6078 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6080 let Inst{11} = idx{0};
6084 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6085 FPR32Op, FPR32Op, V128, VectorIndexS,
6086 asm, ".s", "", "", ".s",
6087 [(set (f32 FPR32Op:$Rd),
6088 (OpNode (f32 FPR32Op:$Rn),
6089 (f32 (vector_extract (v4f32 V128:$Rm),
6090 VectorIndexS:$idx))))]> {
6092 let Inst{11} = idx{1};
6093 let Inst{21} = idx{0};
6096 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6097 FPR64Op, FPR64Op, V128, VectorIndexD,
6098 asm, ".d", "", "", ".d",
6099 [(set (f64 FPR64Op:$Rd),
6100 (OpNode (f64 FPR64Op:$Rn),
6101 (f64 (vector_extract (v2f64 V128:$Rm),
6102 VectorIndexD:$idx))))]> {
6104 let Inst{11} = idx{0};
6109 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6110 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6111 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6112 (ARM64duplane32 (v4f32 V128:$Rm),
6113 VectorIndexS:$idx))),
6114 (!cast<Instruction>(INST # v2i32_indexed)
6115 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6116 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6117 (ARM64dup (f32 FPR32Op:$Rm)))),
6118 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6119 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6122 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6123 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6124 (ARM64duplane32 (v4f32 V128:$Rm),
6125 VectorIndexS:$idx))),
6126 (!cast<Instruction>(INST # "v4i32_indexed")
6127 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6128 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6129 (ARM64dup (f32 FPR32Op:$Rm)))),
6130 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6131 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6133 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6134 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6135 (ARM64duplane64 (v2f64 V128:$Rm),
6136 VectorIndexD:$idx))),
6137 (!cast<Instruction>(INST # "v2i64_indexed")
6138 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6139 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6140 (ARM64dup (f64 FPR64Op:$Rm)))),
6141 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6142 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6144 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6145 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6146 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6147 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6148 V128:$Rm, VectorIndexS:$idx)>;
6149 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6150 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6151 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6152 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6154 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6155 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6156 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6157 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6158 V128:$Rm, VectorIndexD:$idx)>;
6161 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6162 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6164 asm, ".2s", ".2s", ".2s", ".s", []> {
6166 let Inst{11} = idx{1};
6167 let Inst{21} = idx{0};
6170 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6173 asm, ".4s", ".4s", ".4s", ".s", []> {
6175 let Inst{11} = idx{1};
6176 let Inst{21} = idx{0};
6179 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6182 asm, ".2d", ".2d", ".2d", ".d", []> {
6184 let Inst{11} = idx{0};
6189 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6190 FPR32Op, FPR32Op, V128, VectorIndexS,
6191 asm, ".s", "", "", ".s", []> {
6193 let Inst{11} = idx{1};
6194 let Inst{21} = idx{0};
6197 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6198 FPR64Op, FPR64Op, V128, VectorIndexD,
6199 asm, ".d", "", "", ".d", []> {
6201 let Inst{11} = idx{0};
6206 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6207 SDPatternOperator OpNode> {
6208 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6209 V128_lo, VectorIndexH,
6210 asm, ".4h", ".4h", ".4h", ".h",
6211 [(set (v4i16 V64:$Rd),
6212 (OpNode (v4i16 V64:$Rn),
6213 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6215 let Inst{11} = idx{2};
6216 let Inst{21} = idx{1};
6217 let Inst{20} = idx{0};
6220 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6222 V128_lo, VectorIndexH,
6223 asm, ".8h", ".8h", ".8h", ".h",
6224 [(set (v8i16 V128:$Rd),
6225 (OpNode (v8i16 V128:$Rn),
6226 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6228 let Inst{11} = idx{2};
6229 let Inst{21} = idx{1};
6230 let Inst{20} = idx{0};
6233 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6236 asm, ".2s", ".2s", ".2s", ".s",
6237 [(set (v2i32 V64:$Rd),
6238 (OpNode (v2i32 V64:$Rn),
6239 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6241 let Inst{11} = idx{1};
6242 let Inst{21} = idx{0};
6245 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6248 asm, ".4s", ".4s", ".4s", ".s",
6249 [(set (v4i32 V128:$Rd),
6250 (OpNode (v4i32 V128:$Rn),
6251 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6253 let Inst{11} = idx{1};
6254 let Inst{21} = idx{0};
6257 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6258 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6259 asm, ".h", "", "", ".h", []> {
6261 let Inst{11} = idx{2};
6262 let Inst{21} = idx{1};
6263 let Inst{20} = idx{0};
6266 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6267 FPR32Op, FPR32Op, V128, VectorIndexS,
6268 asm, ".s", "", "", ".s",
6269 [(set (i32 FPR32Op:$Rd),
6270 (OpNode FPR32Op:$Rn,
6271 (i32 (vector_extract (v4i32 V128:$Rm),
6272 VectorIndexS:$idx))))]> {
6274 let Inst{11} = idx{1};
6275 let Inst{21} = idx{0};
6279 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6280 SDPatternOperator OpNode> {
6281 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6283 V128_lo, VectorIndexH,
6284 asm, ".4h", ".4h", ".4h", ".h",
6285 [(set (v4i16 V64:$Rd),
6286 (OpNode (v4i16 V64:$Rn),
6287 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6289 let Inst{11} = idx{2};
6290 let Inst{21} = idx{1};
6291 let Inst{20} = idx{0};
6294 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6296 V128_lo, VectorIndexH,
6297 asm, ".8h", ".8h", ".8h", ".h",
6298 [(set (v8i16 V128:$Rd),
6299 (OpNode (v8i16 V128:$Rn),
6300 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6302 let Inst{11} = idx{2};
6303 let Inst{21} = idx{1};
6304 let Inst{20} = idx{0};
6307 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6310 asm, ".2s", ".2s", ".2s", ".s",
6311 [(set (v2i32 V64:$Rd),
6312 (OpNode (v2i32 V64:$Rn),
6313 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6315 let Inst{11} = idx{1};
6316 let Inst{21} = idx{0};
6319 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6322 asm, ".4s", ".4s", ".4s", ".s",
6323 [(set (v4i32 V128:$Rd),
6324 (OpNode (v4i32 V128:$Rn),
6325 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6327 let Inst{11} = idx{1};
6328 let Inst{21} = idx{0};
6332 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6333 SDPatternOperator OpNode> {
6334 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6335 V128_lo, VectorIndexH,
6336 asm, ".4h", ".4h", ".4h", ".h",
6337 [(set (v4i16 V64:$dst),
6338 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6339 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6341 let Inst{11} = idx{2};
6342 let Inst{21} = idx{1};
6343 let Inst{20} = idx{0};
6346 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6348 V128_lo, VectorIndexH,
6349 asm, ".8h", ".8h", ".8h", ".h",
6350 [(set (v8i16 V128:$dst),
6351 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6352 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6354 let Inst{11} = idx{2};
6355 let Inst{21} = idx{1};
6356 let Inst{20} = idx{0};
6359 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6362 asm, ".2s", ".2s", ".2s", ".s",
6363 [(set (v2i32 V64:$dst),
6364 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6365 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6367 let Inst{11} = idx{1};
6368 let Inst{21} = idx{0};
6371 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6374 asm, ".4s", ".4s", ".4s", ".s",
6375 [(set (v4i32 V128:$dst),
6376 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6377 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6379 let Inst{11} = idx{1};
6380 let Inst{21} = idx{0};
6384 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6385 SDPatternOperator OpNode> {
6386 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6388 V128_lo, VectorIndexH,
6389 asm, ".4s", ".4s", ".4h", ".h",
6390 [(set (v4i32 V128:$Rd),
6391 (OpNode (v4i16 V64:$Rn),
6392 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6394 let Inst{11} = idx{2};
6395 let Inst{21} = idx{1};
6396 let Inst{20} = idx{0};
6399 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6401 V128_lo, VectorIndexH,
6402 asm#"2", ".4s", ".4s", ".8h", ".h",
6403 [(set (v4i32 V128:$Rd),
6404 (OpNode (extract_high_v8i16 V128:$Rn),
6405 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6406 VectorIndexH:$idx))))]> {
6409 let Inst{11} = idx{2};
6410 let Inst{21} = idx{1};
6411 let Inst{20} = idx{0};
6414 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6417 asm, ".2d", ".2d", ".2s", ".s",
6418 [(set (v2i64 V128:$Rd),
6419 (OpNode (v2i32 V64:$Rn),
6420 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6422 let Inst{11} = idx{1};
6423 let Inst{21} = idx{0};
6426 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6429 asm#"2", ".2d", ".2d", ".4s", ".s",
6430 [(set (v2i64 V128:$Rd),
6431 (OpNode (extract_high_v4i32 V128:$Rn),
6432 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6433 VectorIndexS:$idx))))]> {
6435 let Inst{11} = idx{1};
6436 let Inst{21} = idx{0};
6439 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6440 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6441 asm, ".h", "", "", ".h", []> {
6443 let Inst{11} = idx{2};
6444 let Inst{21} = idx{1};
6445 let Inst{20} = idx{0};
6448 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6449 FPR64Op, FPR32Op, V128, VectorIndexS,
6450 asm, ".s", "", "", ".s", []> {
6452 let Inst{11} = idx{1};
6453 let Inst{21} = idx{0};
6457 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6458 SDPatternOperator Accum> {
6459 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6461 V128_lo, VectorIndexH,
6462 asm, ".4s", ".4s", ".4h", ".h",
6463 [(set (v4i32 V128:$dst),
6464 (Accum (v4i32 V128:$Rd),
6465 (v4i32 (int_arm64_neon_sqdmull
6467 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6468 VectorIndexH:$idx))))))]> {
6470 let Inst{11} = idx{2};
6471 let Inst{21} = idx{1};
6472 let Inst{20} = idx{0};
6475 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6476 // intermediate EXTRACT_SUBREG would be untyped.
6477 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6478 (i32 (vector_extract (v4i32
6479 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6480 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6481 VectorIndexH:$idx)))),
6484 (!cast<Instruction>(NAME # v4i16_indexed)
6485 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6486 V128_lo:$Rm, VectorIndexH:$idx),
6489 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6491 V128_lo, VectorIndexH,
6492 asm#"2", ".4s", ".4s", ".8h", ".h",
6493 [(set (v4i32 V128:$dst),
6494 (Accum (v4i32 V128:$Rd),
6495 (v4i32 (int_arm64_neon_sqdmull
6496 (extract_high_v8i16 V128:$Rn),
6498 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6499 VectorIndexH:$idx))))))]> {
6501 let Inst{11} = idx{2};
6502 let Inst{21} = idx{1};
6503 let Inst{20} = idx{0};
6506 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6509 asm, ".2d", ".2d", ".2s", ".s",
6510 [(set (v2i64 V128:$dst),
6511 (Accum (v2i64 V128:$Rd),
6512 (v2i64 (int_arm64_neon_sqdmull
6514 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6515 VectorIndexS:$idx))))))]> {
6517 let Inst{11} = idx{1};
6518 let Inst{21} = idx{0};
6521 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6524 asm#"2", ".2d", ".2d", ".4s", ".s",
6525 [(set (v2i64 V128:$dst),
6526 (Accum (v2i64 V128:$Rd),
6527 (v2i64 (int_arm64_neon_sqdmull
6528 (extract_high_v4i32 V128:$Rn),
6530 (ARM64duplane32 (v4i32 V128:$Rm),
6531 VectorIndexS:$idx))))))]> {
6533 let Inst{11} = idx{1};
6534 let Inst{21} = idx{0};
6537 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6538 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6539 asm, ".h", "", "", ".h", []> {
6541 let Inst{11} = idx{2};
6542 let Inst{21} = idx{1};
6543 let Inst{20} = idx{0};
6547 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6548 FPR64Op, FPR32Op, V128, VectorIndexS,
6549 asm, ".s", "", "", ".s",
6550 [(set (i64 FPR64Op:$dst),
6551 (Accum (i64 FPR64Op:$Rd),
6552 (i64 (int_arm64_neon_sqdmulls_scalar
6554 (i32 (vector_extract (v4i32 V128:$Rm),
6555 VectorIndexS:$idx))))))]> {
6558 let Inst{11} = idx{1};
6559 let Inst{21} = idx{0};
6563 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6564 SDPatternOperator OpNode> {
6565 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6566 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6568 V128_lo, VectorIndexH,
6569 asm, ".4s", ".4s", ".4h", ".h",
6570 [(set (v4i32 V128:$Rd),
6571 (OpNode (v4i16 V64:$Rn),
6572 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6574 let Inst{11} = idx{2};
6575 let Inst{21} = idx{1};
6576 let Inst{20} = idx{0};
6579 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6581 V128_lo, VectorIndexH,
6582 asm#"2", ".4s", ".4s", ".8h", ".h",
6583 [(set (v4i32 V128:$Rd),
6584 (OpNode (extract_high_v8i16 V128:$Rn),
6585 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6586 VectorIndexH:$idx))))]> {
6589 let Inst{11} = idx{2};
6590 let Inst{21} = idx{1};
6591 let Inst{20} = idx{0};
6594 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6597 asm, ".2d", ".2d", ".2s", ".s",
6598 [(set (v2i64 V128:$Rd),
6599 (OpNode (v2i32 V64:$Rn),
6600 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6602 let Inst{11} = idx{1};
6603 let Inst{21} = idx{0};
6606 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6609 asm#"2", ".2d", ".2d", ".4s", ".s",
6610 [(set (v2i64 V128:$Rd),
6611 (OpNode (extract_high_v4i32 V128:$Rn),
6612 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6613 VectorIndexS:$idx))))]> {
6615 let Inst{11} = idx{1};
6616 let Inst{21} = idx{0};
6621 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6622 SDPatternOperator OpNode> {
6623 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6624 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6626 V128_lo, VectorIndexH,
6627 asm, ".4s", ".4s", ".4h", ".h",
6628 [(set (v4i32 V128:$dst),
6629 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6630 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6632 let Inst{11} = idx{2};
6633 let Inst{21} = idx{1};
6634 let Inst{20} = idx{0};
6637 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6639 V128_lo, VectorIndexH,
6640 asm#"2", ".4s", ".4s", ".8h", ".h",
6641 [(set (v4i32 V128:$dst),
6642 (OpNode (v4i32 V128:$Rd),
6643 (extract_high_v8i16 V128:$Rn),
6644 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6645 VectorIndexH:$idx))))]> {
6647 let Inst{11} = idx{2};
6648 let Inst{21} = idx{1};
6649 let Inst{20} = idx{0};
6652 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6655 asm, ".2d", ".2d", ".2s", ".s",
6656 [(set (v2i64 V128:$dst),
6657 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6658 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6660 let Inst{11} = idx{1};
6661 let Inst{21} = idx{0};
6664 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6667 asm#"2", ".2d", ".2d", ".4s", ".s",
6668 [(set (v2i64 V128:$dst),
6669 (OpNode (v2i64 V128:$Rd),
6670 (extract_high_v4i32 V128:$Rn),
6671 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6672 VectorIndexS:$idx))))]> {
6674 let Inst{11} = idx{1};
6675 let Inst{21} = idx{0};
6680 //----------------------------------------------------------------------------
6681 // AdvSIMD scalar shift by immediate
6682 //----------------------------------------------------------------------------
6684 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6685 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6686 RegisterClass regtype1, RegisterClass regtype2,
6687 Operand immtype, string asm, list<dag> pattern>
6688 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6689 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6694 let Inst{31-30} = 0b01;
6696 let Inst{28-23} = 0b111110;
6697 let Inst{22-16} = fixed_imm;
6698 let Inst{15-11} = opc;
6704 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6705 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6706 RegisterClass regtype1, RegisterClass regtype2,
6707 Operand immtype, string asm, list<dag> pattern>
6708 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6709 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6714 let Inst{31-30} = 0b01;
6716 let Inst{28-23} = 0b111110;
6717 let Inst{22-16} = fixed_imm;
6718 let Inst{15-11} = opc;
6725 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6726 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6727 FPR32, FPR32, vecshiftR32, asm, []> {
6728 let Inst{20-16} = imm{4-0};
6731 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6732 FPR64, FPR64, vecshiftR64, asm, []> {
6733 let Inst{21-16} = imm{5-0};
6737 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6738 SDPatternOperator OpNode> {
6739 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6740 FPR64, FPR64, vecshiftR64, asm,
6741 [(set (i64 FPR64:$Rd),
6742 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6743 let Inst{21-16} = imm{5-0};
6746 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6747 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
6750 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6751 SDPatternOperator OpNode = null_frag> {
6752 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6753 FPR64, FPR64, vecshiftR64, asm,
6754 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6755 (i32 vecshiftR64:$imm)))]> {
6756 let Inst{21-16} = imm{5-0};
6759 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6760 (i32 vecshiftR64:$imm))),
6761 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6765 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6766 SDPatternOperator OpNode> {
6767 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6768 FPR64, FPR64, vecshiftL64, asm,
6769 [(set (v1i64 FPR64:$Rd),
6770 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6771 let Inst{21-16} = imm{5-0};
6775 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6776 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6777 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6778 FPR64, FPR64, vecshiftL64, asm, []> {
6779 let Inst{21-16} = imm{5-0};
6783 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6784 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6785 SDPatternOperator OpNode = null_frag> {
6786 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6787 FPR8, FPR16, vecshiftR8, asm, []> {
6788 let Inst{18-16} = imm{2-0};
6791 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6792 FPR16, FPR32, vecshiftR16, asm, []> {
6793 let Inst{19-16} = imm{3-0};
6796 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6797 FPR32, FPR64, vecshiftR32, asm,
6798 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6799 let Inst{20-16} = imm{4-0};
6803 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6804 SDPatternOperator OpNode> {
6805 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6806 FPR8, FPR8, vecshiftL8, asm, []> {
6807 let Inst{18-16} = imm{2-0};
6810 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6811 FPR16, FPR16, vecshiftL16, asm, []> {
6812 let Inst{19-16} = imm{3-0};
6815 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6816 FPR32, FPR32, vecshiftL32, asm,
6817 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6818 let Inst{20-16} = imm{4-0};
6821 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6822 FPR64, FPR64, vecshiftL64, asm,
6823 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6824 (i32 vecshiftL64:$imm)))]> {
6825 let Inst{21-16} = imm{5-0};
6829 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6830 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6831 FPR8, FPR8, vecshiftR8, asm, []> {
6832 let Inst{18-16} = imm{2-0};
6835 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6836 FPR16, FPR16, vecshiftR16, asm, []> {
6837 let Inst{19-16} = imm{3-0};
6840 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6841 FPR32, FPR32, vecshiftR32, asm, []> {
6842 let Inst{20-16} = imm{4-0};
6845 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6846 FPR64, FPR64, vecshiftR64, asm, []> {
6847 let Inst{21-16} = imm{5-0};
6851 //----------------------------------------------------------------------------
6852 // AdvSIMD vector x indexed element
6853 //----------------------------------------------------------------------------
6855 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6856 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6857 RegisterOperand dst_reg, RegisterOperand src_reg,
6859 string asm, string dst_kind, string src_kind,
6861 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6862 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6863 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6870 let Inst{28-23} = 0b011110;
6871 let Inst{22-16} = fixed_imm;
6872 let Inst{15-11} = opc;
6878 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6879 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6880 RegisterOperand vectype1, RegisterOperand vectype2,
6882 string asm, string dst_kind, string src_kind,
6884 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6885 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6886 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6893 let Inst{28-23} = 0b011110;
6894 let Inst{22-16} = fixed_imm;
6895 let Inst{15-11} = opc;
6901 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6903 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6904 V64, V64, vecshiftR32,
6906 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6908 let Inst{20-16} = imm;
6911 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6912 V128, V128, vecshiftR32,
6914 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6916 let Inst{20-16} = imm;
6919 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6920 V128, V128, vecshiftR64,
6922 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6924 let Inst{21-16} = imm;
6928 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6930 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6931 V64, V64, vecshiftR32,
6933 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6935 let Inst{20-16} = imm;
6938 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6939 V128, V128, vecshiftR32,
6941 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6943 let Inst{20-16} = imm;
6946 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6947 V128, V128, vecshiftR64,
6949 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6951 let Inst{21-16} = imm;
6955 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6956 SDPatternOperator OpNode> {
6957 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6958 V64, V128, vecshiftR16Narrow,
6960 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6962 let Inst{18-16} = imm;
6965 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6966 V128, V128, vecshiftR16Narrow,
6967 asm#"2", ".16b", ".8h", []> {
6969 let Inst{18-16} = imm;
6970 let hasSideEffects = 0;
6973 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6974 V64, V128, vecshiftR32Narrow,
6976 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6978 let Inst{19-16} = imm;
6981 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6982 V128, V128, vecshiftR32Narrow,
6983 asm#"2", ".8h", ".4s", []> {
6985 let Inst{19-16} = imm;
6986 let hasSideEffects = 0;
6989 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6990 V64, V128, vecshiftR64Narrow,
6992 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6994 let Inst{20-16} = imm;
6997 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6998 V128, V128, vecshiftR64Narrow,
6999 asm#"2", ".4s", ".2d", []> {
7001 let Inst{20-16} = imm;
7002 let hasSideEffects = 0;
7005 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7006 // themselves, so put them here instead.
7008 // Patterns involving what's effectively an insert high and a normal
7009 // intrinsic, represented by CONCAT_VECTORS.
7010 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7011 vecshiftR16Narrow:$imm)),
7012 (!cast<Instruction>(NAME # "v16i8_shift")
7013 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7014 V128:$Rn, vecshiftR16Narrow:$imm)>;
7015 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7016 vecshiftR32Narrow:$imm)),
7017 (!cast<Instruction>(NAME # "v8i16_shift")
7018 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7019 V128:$Rn, vecshiftR32Narrow:$imm)>;
7020 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7021 vecshiftR64Narrow:$imm)),
7022 (!cast<Instruction>(NAME # "v4i32_shift")
7023 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7024 V128:$Rn, vecshiftR64Narrow:$imm)>;
7027 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7028 SDPatternOperator OpNode> {
7029 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7030 V64, V64, vecshiftL8,
7032 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7033 (i32 vecshiftL8:$imm)))]> {
7035 let Inst{18-16} = imm;
7038 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7039 V128, V128, vecshiftL8,
7040 asm, ".16b", ".16b",
7041 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7042 (i32 vecshiftL8:$imm)))]> {
7044 let Inst{18-16} = imm;
7047 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7048 V64, V64, vecshiftL16,
7050 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7051 (i32 vecshiftL16:$imm)))]> {
7053 let Inst{19-16} = imm;
7056 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7057 V128, V128, vecshiftL16,
7059 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7060 (i32 vecshiftL16:$imm)))]> {
7062 let Inst{19-16} = imm;
7065 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7066 V64, V64, vecshiftL32,
7068 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7069 (i32 vecshiftL32:$imm)))]> {
7071 let Inst{20-16} = imm;
7074 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7075 V128, V128, vecshiftL32,
7077 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7078 (i32 vecshiftL32:$imm)))]> {
7080 let Inst{20-16} = imm;
7083 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7084 V128, V128, vecshiftL64,
7086 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7087 (i32 vecshiftL64:$imm)))]> {
7089 let Inst{21-16} = imm;
7093 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7094 SDPatternOperator OpNode> {
7095 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7096 V64, V64, vecshiftR8,
7098 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7099 (i32 vecshiftR8:$imm)))]> {
7101 let Inst{18-16} = imm;
7104 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7105 V128, V128, vecshiftR8,
7106 asm, ".16b", ".16b",
7107 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7108 (i32 vecshiftR8:$imm)))]> {
7110 let Inst{18-16} = imm;
7113 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7114 V64, V64, vecshiftR16,
7116 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7117 (i32 vecshiftR16:$imm)))]> {
7119 let Inst{19-16} = imm;
7122 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7123 V128, V128, vecshiftR16,
7125 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7126 (i32 vecshiftR16:$imm)))]> {
7128 let Inst{19-16} = imm;
7131 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7132 V64, V64, vecshiftR32,
7134 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7135 (i32 vecshiftR32:$imm)))]> {
7137 let Inst{20-16} = imm;
7140 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7141 V128, V128, vecshiftR32,
7143 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7144 (i32 vecshiftR32:$imm)))]> {
7146 let Inst{20-16} = imm;
7149 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7150 V128, V128, vecshiftR64,
7152 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7153 (i32 vecshiftR64:$imm)))]> {
7155 let Inst{21-16} = imm;
7159 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7160 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7161 SDPatternOperator OpNode = null_frag> {
7162 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7163 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7164 [(set (v8i8 V64:$dst),
7165 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7166 (i32 vecshiftR8:$imm)))]> {
7168 let Inst{18-16} = imm;
7171 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7172 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7173 [(set (v16i8 V128:$dst),
7174 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7175 (i32 vecshiftR8:$imm)))]> {
7177 let Inst{18-16} = imm;
7180 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7181 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7182 [(set (v4i16 V64:$dst),
7183 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7184 (i32 vecshiftR16:$imm)))]> {
7186 let Inst{19-16} = imm;
7189 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7190 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7191 [(set (v8i16 V128:$dst),
7192 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7193 (i32 vecshiftR16:$imm)))]> {
7195 let Inst{19-16} = imm;
7198 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7199 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7200 [(set (v2i32 V64:$dst),
7201 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7202 (i32 vecshiftR32:$imm)))]> {
7204 let Inst{20-16} = imm;
7207 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7208 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7209 [(set (v4i32 V128:$dst),
7210 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7211 (i32 vecshiftR32:$imm)))]> {
7213 let Inst{20-16} = imm;
7216 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7217 V128, V128, vecshiftR64,
7218 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7219 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7220 (i32 vecshiftR64:$imm)))]> {
7222 let Inst{21-16} = imm;
7226 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7227 SDPatternOperator OpNode = null_frag> {
7228 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7229 V64, V64, vecshiftL8,
7231 [(set (v8i8 V64:$dst),
7232 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7233 (i32 vecshiftL8:$imm)))]> {
7235 let Inst{18-16} = imm;
7238 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7239 V128, V128, vecshiftL8,
7240 asm, ".16b", ".16b",
7241 [(set (v16i8 V128:$dst),
7242 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7243 (i32 vecshiftL8:$imm)))]> {
7245 let Inst{18-16} = imm;
7248 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7249 V64, V64, vecshiftL16,
7251 [(set (v4i16 V64:$dst),
7252 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7253 (i32 vecshiftL16:$imm)))]> {
7255 let Inst{19-16} = imm;
7258 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7259 V128, V128, vecshiftL16,
7261 [(set (v8i16 V128:$dst),
7262 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7263 (i32 vecshiftL16:$imm)))]> {
7265 let Inst{19-16} = imm;
7268 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7269 V64, V64, vecshiftL32,
7271 [(set (v2i32 V64:$dst),
7272 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7273 (i32 vecshiftL32:$imm)))]> {
7275 let Inst{20-16} = imm;
7278 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7279 V128, V128, vecshiftL32,
7281 [(set (v4i32 V128:$dst),
7282 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7283 (i32 vecshiftL32:$imm)))]> {
7285 let Inst{20-16} = imm;
7288 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7289 V128, V128, vecshiftL64,
7291 [(set (v2i64 V128:$dst),
7292 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7293 (i32 vecshiftL64:$imm)))]> {
7295 let Inst{21-16} = imm;
7299 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7300 SDPatternOperator OpNode> {
7301 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7302 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7303 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7305 let Inst{18-16} = imm;
7308 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7309 V128, V128, vecshiftL8,
7310 asm#"2", ".8h", ".16b",
7311 [(set (v8i16 V128:$Rd),
7312 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7314 let Inst{18-16} = imm;
7317 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7318 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7319 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7321 let Inst{19-16} = imm;
7324 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7325 V128, V128, vecshiftL16,
7326 asm#"2", ".4s", ".8h",
7327 [(set (v4i32 V128:$Rd),
7328 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7331 let Inst{19-16} = imm;
7334 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7335 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7336 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7338 let Inst{20-16} = imm;
7341 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7342 V128, V128, vecshiftL32,
7343 asm#"2", ".2d", ".4s",
7344 [(set (v2i64 V128:$Rd),
7345 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7347 let Inst{20-16} = imm;
7353 // Vector load/store
7355 // SIMD ldX/stX no-index memory references don't allow the optional
7356 // ", #0" constant and handle post-indexing explicitly, so we use
7357 // a more specialized parse method for them. Otherwise, it's the same as
7358 // the general am_noindex handling.
7359 def MemorySIMDNoIndexOperand : AsmOperandClass {
7360 let Name = "MemorySIMDNoIndex";
7361 let ParserMethod = "tryParseNoIndexMemory";
7363 def am_simdnoindex : Operand<i64>,
7364 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7365 let PrintMethod = "printAMNoIndex";
7366 let ParserMatchClass = MemorySIMDNoIndexOperand;
7367 let MIOperandInfo = (ops GPR64sp:$base);
7368 let DecoderMethod = "DecodeGPR64spRegisterClass";
7371 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7372 string asm, dag oops, dag iops, list<dag> pattern>
7373 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7378 let Inst{29-23} = 0b0011000;
7380 let Inst{21-16} = 0b000000;
7381 let Inst{15-12} = opcode;
7382 let Inst{11-10} = size;
7383 let Inst{9-5} = vaddr;
7387 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7388 string asm, dag oops, dag iops>
7389 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7395 let Inst{29-23} = 0b0011001;
7398 let Inst{20-16} = Xm;
7399 let Inst{15-12} = opcode;
7400 let Inst{11-10} = size;
7401 let Inst{9-5} = vaddr;
7403 let DecoderMethod = "DecodeSIMDLdStPost";
7406 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7407 // register post-index addressing from the zero register.
7408 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7409 int Offset, int Size> {
7410 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7411 // "ld1\t$Vt, $vaddr, #16"
7412 // may get mapped to
7413 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7414 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7415 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7416 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7417 am_simdnoindex:$vaddr, XZR), 1>;
7419 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7420 // "ld1.8b\t$Vt, $vaddr, #16"
7421 // may get mapped to
7422 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7423 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7424 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7425 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7426 am_simdnoindex:$vaddr, XZR), 0>;
7428 // E.g. "ld1.8b { v0, v1 }, [x1]"
7429 // "ld1\t$Vt, $vaddr"
7430 // may get mapped to
7431 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7432 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7433 (!cast<Instruction>(NAME # Count # "v" # layout)
7434 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7435 am_simdnoindex:$vaddr), 0>;
7437 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7438 // "ld1\t$Vt, $vaddr, $Xm"
7439 // may get mapped to
7440 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7441 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7442 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7443 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7444 am_simdnoindex:$vaddr,
7445 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7448 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7449 int Offset64, bits<4> opcode> {
7450 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7451 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7452 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7453 (ins am_simdnoindex:$vaddr), []>;
7454 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7455 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7456 (ins am_simdnoindex:$vaddr), []>;
7457 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7458 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7459 (ins am_simdnoindex:$vaddr), []>;
7460 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7461 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7462 (ins am_simdnoindex:$vaddr), []>;
7463 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7464 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7465 (ins am_simdnoindex:$vaddr), []>;
7466 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7467 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7468 (ins am_simdnoindex:$vaddr), []>;
7469 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7470 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7471 (ins am_simdnoindex:$vaddr), []>;
7474 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7475 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7476 (ins am_simdnoindex:$vaddr,
7477 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7478 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7479 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7480 (ins am_simdnoindex:$vaddr,
7481 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7482 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7483 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7484 (ins am_simdnoindex:$vaddr,
7485 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7486 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7487 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7488 (ins am_simdnoindex:$vaddr,
7489 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7490 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7491 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7492 (ins am_simdnoindex:$vaddr,
7493 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7494 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7495 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7496 (ins am_simdnoindex:$vaddr,
7497 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7498 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7499 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7500 (ins am_simdnoindex:$vaddr,
7501 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7504 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7505 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7506 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7507 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7508 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7509 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7510 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7513 // Only ld1/st1 has a v1d version.
7514 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7515 int Offset64, bits<4> opcode> {
7516 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7517 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7518 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7519 am_simdnoindex:$vaddr), []>;
7520 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7521 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7522 am_simdnoindex:$vaddr), []>;
7523 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7524 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7525 am_simdnoindex:$vaddr), []>;
7526 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7527 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7528 am_simdnoindex:$vaddr), []>;
7529 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7530 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7531 am_simdnoindex:$vaddr), []>;
7532 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7533 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7534 am_simdnoindex:$vaddr), []>;
7535 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7536 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7537 am_simdnoindex:$vaddr), []>;
7539 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7540 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7541 am_simdnoindex:$vaddr,
7542 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7543 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7544 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7545 am_simdnoindex:$vaddr,
7546 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7547 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7548 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7549 am_simdnoindex:$vaddr,
7550 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7551 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7552 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7553 am_simdnoindex:$vaddr,
7554 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7555 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7556 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7557 am_simdnoindex:$vaddr,
7558 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7559 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7560 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7561 am_simdnoindex:$vaddr,
7562 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7563 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7564 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7565 am_simdnoindex:$vaddr,
7566 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7569 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7570 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7571 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7572 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7573 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7574 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7575 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7578 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7579 int Offset128, int Offset64, bits<4> opcode>
7580 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7582 // LD1 instructions have extra "1d" variants.
7583 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7584 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7585 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7586 (ins am_simdnoindex:$vaddr), []>;
7588 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7589 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7590 (ins am_simdnoindex:$vaddr,
7591 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7594 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7597 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7598 int Offset128, int Offset64, bits<4> opcode>
7599 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7601 // ST1 instructions have extra "1d" variants.
7602 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7603 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7604 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7605 am_simdnoindex:$vaddr), []>;
7607 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7608 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7609 am_simdnoindex:$vaddr,
7610 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7613 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7616 multiclass SIMDLd1Multiple<string asm> {
7617 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7618 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7619 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7620 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7623 multiclass SIMDSt1Multiple<string asm> {
7624 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7625 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7626 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7627 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7630 multiclass SIMDLd2Multiple<string asm> {
7631 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7634 multiclass SIMDSt2Multiple<string asm> {
7635 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7638 multiclass SIMDLd3Multiple<string asm> {
7639 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7642 multiclass SIMDSt3Multiple<string asm> {
7643 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7646 multiclass SIMDLd4Multiple<string asm> {
7647 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7650 multiclass SIMDSt4Multiple<string asm> {
7651 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7655 // AdvSIMD Load/store single-element
7658 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7659 string asm, string operands, dag oops, dag iops,
7661 : I<oops, iops, asm, operands, "", pattern> {
7665 let Inst{29-24} = 0b001101;
7668 let Inst{15-13} = opcode;
7669 let Inst{9-5} = vaddr;
7671 let DecoderMethod = "DecodeSIMDLdStSingle";
7674 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7675 string asm, string operands, dag oops, dag iops,
7677 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7681 let Inst{29-24} = 0b001101;
7684 let Inst{15-13} = opcode;
7685 let Inst{9-5} = vaddr;
7687 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7691 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7692 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7694 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7695 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7698 let Inst{20-16} = 0b00000;
7700 let Inst{11-10} = size;
7702 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7703 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7704 string asm, Operand listtype, Operand GPR64pi>
7705 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7706 (outs listtype:$Vt),
7707 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7711 let Inst{20-16} = Xm;
7713 let Inst{11-10} = size;
7716 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7717 int Offset, int Size> {
7718 // E.g. "ld1r { v0.8b }, [x1], #1"
7719 // "ld1r.8b\t$Vt, $vaddr, #1"
7720 // may get mapped to
7721 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7722 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7723 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7724 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7725 am_simdnoindex:$vaddr, XZR), 1>;
7727 // E.g. "ld1r.8b { v0 }, [x1], #1"
7728 // "ld1r.8b\t$Vt, $vaddr, #1"
7729 // may get mapped to
7730 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7731 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7732 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7733 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7734 am_simdnoindex:$vaddr, XZR), 0>;
7736 // E.g. "ld1r.8b { v0 }, [x1]"
7737 // "ld1r.8b\t$Vt, $vaddr"
7738 // may get mapped to
7739 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7740 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7741 (!cast<Instruction>(NAME # "v" # layout)
7742 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7743 am_simdnoindex:$vaddr), 0>;
7745 // E.g. "ld1r.8b { v0 }, [x1], x2"
7746 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7747 // may get mapped to
7748 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7749 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7750 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7751 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7752 am_simdnoindex:$vaddr,
7753 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7756 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7757 int Offset1, int Offset2, int Offset4, int Offset8> {
7758 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7759 !cast<Operand>("VecList" # Count # "8b")>;
7760 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7761 !cast<Operand>("VecList" # Count #"16b")>;
7762 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7763 !cast<Operand>("VecList" # Count #"4h")>;
7764 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7765 !cast<Operand>("VecList" # Count #"8h")>;
7766 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7767 !cast<Operand>("VecList" # Count #"2s")>;
7768 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7769 !cast<Operand>("VecList" # Count #"4s")>;
7770 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7771 !cast<Operand>("VecList" # Count #"1d")>;
7772 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7773 !cast<Operand>("VecList" # Count #"2d")>;
7775 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7776 !cast<Operand>("VecList" # Count # "8b"),
7777 !cast<Operand>("GPR64pi" # Offset1)>;
7778 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7779 !cast<Operand>("VecList" # Count # "16b"),
7780 !cast<Operand>("GPR64pi" # Offset1)>;
7781 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7782 !cast<Operand>("VecList" # Count # "4h"),
7783 !cast<Operand>("GPR64pi" # Offset2)>;
7784 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7785 !cast<Operand>("VecList" # Count # "8h"),
7786 !cast<Operand>("GPR64pi" # Offset2)>;
7787 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7788 !cast<Operand>("VecList" # Count # "2s"),
7789 !cast<Operand>("GPR64pi" # Offset4)>;
7790 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7791 !cast<Operand>("VecList" # Count # "4s"),
7792 !cast<Operand>("GPR64pi" # Offset4)>;
7793 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7794 !cast<Operand>("VecList" # Count # "1d"),
7795 !cast<Operand>("GPR64pi" # Offset8)>;
7796 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7797 !cast<Operand>("VecList" # Count # "2d"),
7798 !cast<Operand>("GPR64pi" # Offset8)>;
7800 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7801 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7802 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7803 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7804 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7805 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7806 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7807 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7810 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7811 dag oops, dag iops, list<dag> pattern>
7812 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7814 // idx encoded in Q:S:size fields.
7816 let Inst{30} = idx{3};
7818 let Inst{20-16} = 0b00000;
7819 let Inst{12} = idx{2};
7820 let Inst{11-10} = idx{1-0};
7822 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7823 dag oops, dag iops, list<dag> pattern>
7824 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7826 // idx encoded in Q:S:size fields.
7828 let Inst{30} = idx{3};
7830 let Inst{20-16} = 0b00000;
7831 let Inst{12} = idx{2};
7832 let Inst{11-10} = idx{1-0};
7834 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7836 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7838 // idx encoded in Q:S:size fields.
7841 let Inst{30} = idx{3};
7843 let Inst{20-16} = Xm;
7844 let Inst{12} = idx{2};
7845 let Inst{11-10} = idx{1-0};
7847 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7849 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7851 // idx encoded in Q:S:size fields.
7854 let Inst{30} = idx{3};
7856 let Inst{20-16} = Xm;
7857 let Inst{12} = idx{2};
7858 let Inst{11-10} = idx{1-0};
7861 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7862 dag oops, dag iops, list<dag> pattern>
7863 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7865 // idx encoded in Q:S:size<1> fields.
7867 let Inst{30} = idx{2};
7869 let Inst{20-16} = 0b00000;
7870 let Inst{12} = idx{1};
7871 let Inst{11} = idx{0};
7872 let Inst{10} = size;
7874 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7875 dag oops, dag iops, list<dag> pattern>
7876 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7878 // idx encoded in Q:S:size<1> fields.
7880 let Inst{30} = idx{2};
7882 let Inst{20-16} = 0b00000;
7883 let Inst{12} = idx{1};
7884 let Inst{11} = idx{0};
7885 let Inst{10} = size;
7888 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7890 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7892 // idx encoded in Q:S:size<1> fields.
7895 let Inst{30} = idx{2};
7897 let Inst{20-16} = Xm;
7898 let Inst{12} = idx{1};
7899 let Inst{11} = idx{0};
7900 let Inst{10} = size;
7902 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7904 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7906 // idx encoded in Q:S:size<1> fields.
7909 let Inst{30} = idx{2};
7911 let Inst{20-16} = Xm;
7912 let Inst{12} = idx{1};
7913 let Inst{11} = idx{0};
7914 let Inst{10} = size;
7916 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7917 dag oops, dag iops, list<dag> pattern>
7918 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7920 // idx encoded in Q:S fields.
7922 let Inst{30} = idx{1};
7924 let Inst{20-16} = 0b00000;
7925 let Inst{12} = idx{0};
7926 let Inst{11-10} = size;
7928 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7929 dag oops, dag iops, list<dag> pattern>
7930 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7932 // idx encoded in Q:S fields.
7934 let Inst{30} = idx{1};
7936 let Inst{20-16} = 0b00000;
7937 let Inst{12} = idx{0};
7938 let Inst{11-10} = size;
7940 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7941 string asm, dag oops, dag iops>
7942 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7944 // idx encoded in Q:S fields.
7947 let Inst{30} = idx{1};
7949 let Inst{20-16} = Xm;
7950 let Inst{12} = idx{0};
7951 let Inst{11-10} = size;
7953 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7954 string asm, dag oops, dag iops>
7955 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7957 // idx encoded in Q:S fields.
7960 let Inst{30} = idx{1};
7962 let Inst{20-16} = Xm;
7963 let Inst{12} = idx{0};
7964 let Inst{11-10} = size;
7966 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7967 dag oops, dag iops, list<dag> pattern>
7968 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7970 // idx encoded in Q field.
7974 let Inst{20-16} = 0b00000;
7976 let Inst{11-10} = size;
7978 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7979 dag oops, dag iops, list<dag> pattern>
7980 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7982 // idx encoded in Q field.
7986 let Inst{20-16} = 0b00000;
7988 let Inst{11-10} = size;
7990 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7991 string asm, dag oops, dag iops>
7992 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7994 // idx encoded in Q field.
7999 let Inst{20-16} = Xm;
8001 let Inst{11-10} = size;
8003 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8004 string asm, dag oops, dag iops>
8005 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8007 // idx encoded in Q field.
8012 let Inst{20-16} = Xm;
8014 let Inst{11-10} = size;
8017 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8018 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8019 RegisterOperand listtype,
8020 RegisterOperand GPR64pi> {
8021 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8022 (outs listtype:$dst),
8023 (ins listtype:$Vt, VectorIndexB:$idx,
8024 am_simdnoindex:$vaddr), []>;
8026 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8027 (outs listtype:$dst),
8028 (ins listtype:$Vt, VectorIndexB:$idx,
8029 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8031 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8032 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8033 RegisterOperand listtype,
8034 RegisterOperand GPR64pi> {
8035 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8036 (outs listtype:$dst),
8037 (ins listtype:$Vt, VectorIndexH:$idx,
8038 am_simdnoindex:$vaddr), []>;
8040 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8041 (outs listtype:$dst),
8042 (ins listtype:$Vt, VectorIndexH:$idx,
8043 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8045 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8046 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8047 RegisterOperand listtype,
8048 RegisterOperand GPR64pi> {
8049 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8050 (outs listtype:$dst),
8051 (ins listtype:$Vt, VectorIndexS:$idx,
8052 am_simdnoindex:$vaddr), []>;
8054 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8055 (outs listtype:$dst),
8056 (ins listtype:$Vt, VectorIndexS:$idx,
8057 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8059 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8060 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8061 RegisterOperand listtype, RegisterOperand GPR64pi> {
8062 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8063 (outs listtype:$dst),
8064 (ins listtype:$Vt, VectorIndexD:$idx,
8065 am_simdnoindex:$vaddr), []>;
8067 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8068 (outs listtype:$dst),
8069 (ins listtype:$Vt, VectorIndexD:$idx,
8070 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8072 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8073 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8074 RegisterOperand listtype, RegisterOperand GPR64pi> {
8075 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8076 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8077 am_simdnoindex:$vaddr), []>;
8079 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8080 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8081 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8083 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8084 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8085 RegisterOperand listtype, RegisterOperand GPR64pi> {
8086 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8087 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8088 am_simdnoindex:$vaddr), []>;
8090 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8091 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8092 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8094 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8095 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8096 RegisterOperand listtype, RegisterOperand GPR64pi> {
8097 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8098 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8099 am_simdnoindex:$vaddr), []>;
8101 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8102 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8103 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8105 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8106 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8107 RegisterOperand listtype, RegisterOperand GPR64pi> {
8108 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8109 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8110 am_simdnoindex:$vaddr), []>;
8112 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8113 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8114 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8117 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8118 string Count, int Offset, Operand idxtype> {
8119 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8120 // "ld1\t$Vt, $vaddr, #1"
8121 // may get mapped to
8122 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8123 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8124 (!cast<Instruction>(NAME # Type # "_POST")
8125 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8126 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8128 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8129 // "ld1.8b\t$Vt, $vaddr, #1"
8130 // may get mapped to
8131 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8132 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8133 (!cast<Instruction>(NAME # Type # "_POST")
8134 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8135 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8137 // E.g. "ld1.8b { v0 }[0], [x1]"
8138 // "ld1.8b\t$Vt, $vaddr"
8139 // may get mapped to
8140 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8141 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8142 (!cast<Instruction>(NAME # Type)
8143 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8144 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8146 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8147 // "ld1.8b\t$Vt, $vaddr, $Xm"
8148 // may get mapped to
8149 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8150 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8151 (!cast<Instruction>(NAME # Type # "_POST")
8152 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8153 idxtype:$idx, am_simdnoindex:$vaddr,
8154 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8157 multiclass SIMDLdSt1SingleAliases<string asm> {
8158 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8159 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8160 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8161 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8164 multiclass SIMDLdSt2SingleAliases<string asm> {
8165 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8166 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8167 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8168 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8171 multiclass SIMDLdSt3SingleAliases<string asm> {
8172 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8173 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8174 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8175 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8178 multiclass SIMDLdSt4SingleAliases<string asm> {
8179 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8180 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8181 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8182 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8185 //----------------------------------------------------------------------------
8186 // Crypto extensions
8187 //----------------------------------------------------------------------------
8189 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8190 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8192 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8196 let Inst{31-16} = 0b0100111000101000;
8197 let Inst{15-12} = opc;
8198 let Inst{11-10} = 0b10;
8203 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8204 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8205 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8207 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8208 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8210 [(set (v16i8 V128:$dst),
8211 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8213 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8214 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8215 dag oops, dag iops, list<dag> pat>
8216 : I<oops, iops, asm,
8217 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8218 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8223 let Inst{31-21} = 0b01011110000;
8224 let Inst{20-16} = Rm;
8226 let Inst{14-12} = opc;
8227 let Inst{11-10} = 0b00;
8232 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8233 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8234 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8235 [(set (v4i32 FPR128:$dst),
8236 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8237 (v4i32 V128:$Rm)))]>;
8239 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8240 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8241 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8242 [(set (v4i32 V128:$dst),
8243 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8244 (v4i32 V128:$Rm)))]>;
8246 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8247 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8248 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8249 [(set (v4i32 FPR128:$dst),
8250 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8251 (v4i32 V128:$Rm)))]>;
8253 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8254 class SHA2OpInst<bits<4> opc, string asm, string kind,
8255 string cstr, dag oops, dag iops,
8257 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8258 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8262 let Inst{31-16} = 0b0101111000101000;
8263 let Inst{15-12} = opc;
8264 let Inst{11-10} = 0b10;
8269 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8270 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8271 (ins V128:$Rd, V128:$Rn),
8272 [(set (v4i32 V128:$dst),
8273 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8275 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8276 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8277 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8279 // Allow the size specifier tokens to be upper case, not just lower.
8280 def : TokenAlias<".8B", ".8b">;
8281 def : TokenAlias<".4H", ".4h">;
8282 def : TokenAlias<".2S", ".2s">;
8283 def : TokenAlias<".1D", ".1d">;
8284 def : TokenAlias<".16B", ".16b">;
8285 def : TokenAlias<".8H", ".8h">;
8286 def : TokenAlias<".4S", ".4s">;
8287 def : TokenAlias<".2D", ".2d">;
8288 def : TokenAlias<".1Q", ".1q">;
8289 def : TokenAlias<".B", ".b">;
8290 def : TokenAlias<".H", ".h">;
8291 def : TokenAlias<".S", ".s">;
8292 def : TokenAlias<".D", ".d">;
8293 def : TokenAlias<".Q", ".q">;