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";
160 def adrplabel : Operand<i64> {
161 let EncoderMethod = "getAdrLabelOpValue";
162 let PrintMethod = "printAdrpLabel";
163 let ParserMatchClass = AdrpOperand;
166 def AdrOperand : AsmOperandClass {
167 let Name = "AdrLabel";
168 let ParserMethod = "tryParseAdrLabel";
170 def adrlabel : Operand<i64> {
171 let EncoderMethod = "getAdrLabelOpValue";
172 let ParserMatchClass = AdrOperand;
175 // simm9 predicate - True if the immediate is in the range [-256, 255].
176 def SImm9Operand : AsmOperandClass {
178 let DiagnosticType = "InvalidMemoryIndexedSImm9";
180 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
181 let ParserMatchClass = SImm9Operand;
184 // simm7s4 predicate - True if the immediate is a multiple of 4 in the range
186 def SImm7s4Operand : AsmOperandClass {
187 let Name = "SImm7s4";
188 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
190 def simm7s4 : Operand<i32> {
191 let ParserMatchClass = SImm7s4Operand;
192 let PrintMethod = "printImmScale4";
195 // simm7s8 predicate - True if the immediate is a multiple of 8 in the range
197 def SImm7s8Operand : AsmOperandClass {
198 let Name = "SImm7s8";
199 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
201 def simm7s8 : Operand<i32> {
202 let ParserMatchClass = SImm7s8Operand;
203 let PrintMethod = "printImmScale8";
206 // simm7s16 predicate - True if the immediate is a multiple of 16 in the range
208 def SImm7s16Operand : AsmOperandClass {
209 let Name = "SImm7s16";
210 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
212 def simm7s16 : Operand<i32> {
213 let ParserMatchClass = SImm7s16Operand;
214 let PrintMethod = "printImmScale16";
217 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
218 def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
219 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
220 return ((uint32_t)Imm) < 65536;
222 let ParserMatchClass = Imm0_65535Operand;
225 def Imm1_8Operand : AsmOperandClass {
227 let DiagnosticType = "InvalidImm1_8";
229 def Imm1_16Operand : AsmOperandClass {
230 let Name = "Imm1_16";
231 let DiagnosticType = "InvalidImm1_16";
233 def Imm1_32Operand : AsmOperandClass {
234 let Name = "Imm1_32";
235 let DiagnosticType = "InvalidImm1_32";
237 def Imm1_64Operand : AsmOperandClass {
238 let Name = "Imm1_64";
239 let DiagnosticType = "InvalidImm1_64";
242 def MovZSymbolG3AsmOperand : AsmOperandClass {
243 let Name = "MovZSymbolG3";
244 let RenderMethod = "addImmOperands";
247 def movz_symbol_g3 : Operand<i32> {
248 let ParserMatchClass = MovZSymbolG3AsmOperand;
251 def MovZSymbolG2AsmOperand : AsmOperandClass {
252 let Name = "MovZSymbolG2";
253 let RenderMethod = "addImmOperands";
256 def movz_symbol_g2 : Operand<i32> {
257 let ParserMatchClass = MovZSymbolG2AsmOperand;
260 def MovZSymbolG1AsmOperand : AsmOperandClass {
261 let Name = "MovZSymbolG1";
262 let RenderMethod = "addImmOperands";
265 def movz_symbol_g1 : Operand<i32> {
266 let ParserMatchClass = MovZSymbolG1AsmOperand;
269 def MovZSymbolG0AsmOperand : AsmOperandClass {
270 let Name = "MovZSymbolG0";
271 let RenderMethod = "addImmOperands";
274 def movz_symbol_g0 : Operand<i32> {
275 let ParserMatchClass = MovZSymbolG0AsmOperand;
278 def MovKSymbolG2AsmOperand : AsmOperandClass {
279 let Name = "MovKSymbolG2";
280 let RenderMethod = "addImmOperands";
283 def movk_symbol_g2 : Operand<i32> {
284 let ParserMatchClass = MovKSymbolG2AsmOperand;
287 def MovKSymbolG1AsmOperand : AsmOperandClass {
288 let Name = "MovKSymbolG1";
289 let RenderMethod = "addImmOperands";
292 def movk_symbol_g1 : Operand<i32> {
293 let ParserMatchClass = MovKSymbolG1AsmOperand;
296 def MovKSymbolG0AsmOperand : AsmOperandClass {
297 let Name = "MovKSymbolG0";
298 let RenderMethod = "addImmOperands";
301 def movk_symbol_g0 : Operand<i32> {
302 let ParserMatchClass = MovKSymbolG0AsmOperand;
305 def fixedpoint32 : Operand<i32> {
306 let EncoderMethod = "getFixedPointScaleOpValue";
307 let DecoderMethod = "DecodeFixedPointScaleImm";
308 let ParserMatchClass = Imm1_32Operand;
310 def fixedpoint64 : Operand<i64> {
311 let EncoderMethod = "getFixedPointScaleOpValue";
312 let DecoderMethod = "DecodeFixedPointScaleImm";
313 let ParserMatchClass = Imm1_64Operand;
316 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
317 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
319 let EncoderMethod = "getVecShiftR8OpValue";
320 let DecoderMethod = "DecodeVecShiftR8Imm";
321 let ParserMatchClass = Imm1_8Operand;
323 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
324 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
326 let EncoderMethod = "getVecShiftR16OpValue";
327 let DecoderMethod = "DecodeVecShiftR16Imm";
328 let ParserMatchClass = Imm1_16Operand;
330 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
331 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
333 let EncoderMethod = "getVecShiftR16OpValue";
334 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
335 let ParserMatchClass = Imm1_8Operand;
337 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
338 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
340 let EncoderMethod = "getVecShiftR32OpValue";
341 let DecoderMethod = "DecodeVecShiftR32Imm";
342 let ParserMatchClass = Imm1_32Operand;
344 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
345 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
347 let EncoderMethod = "getVecShiftR32OpValue";
348 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
349 let ParserMatchClass = Imm1_16Operand;
351 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
352 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
354 let EncoderMethod = "getVecShiftR64OpValue";
355 let DecoderMethod = "DecodeVecShiftR64Imm";
356 let ParserMatchClass = Imm1_64Operand;
358 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
359 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
361 let EncoderMethod = "getVecShiftR64OpValue";
362 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
363 let ParserMatchClass = Imm1_32Operand;
366 def Imm0_7Operand : AsmOperandClass { let Name = "Imm0_7"; }
367 def Imm0_15Operand : AsmOperandClass { let Name = "Imm0_15"; }
368 def Imm0_31Operand : AsmOperandClass { let Name = "Imm0_31"; }
369 def Imm0_63Operand : AsmOperandClass { let Name = "Imm0_63"; }
371 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
372 return (((uint32_t)Imm) < 8);
374 let EncoderMethod = "getVecShiftL8OpValue";
375 let DecoderMethod = "DecodeVecShiftL8Imm";
376 let ParserMatchClass = Imm0_7Operand;
378 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
379 return (((uint32_t)Imm) < 16);
381 let EncoderMethod = "getVecShiftL16OpValue";
382 let DecoderMethod = "DecodeVecShiftL16Imm";
383 let ParserMatchClass = Imm0_15Operand;
385 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
386 return (((uint32_t)Imm) < 32);
388 let EncoderMethod = "getVecShiftL32OpValue";
389 let DecoderMethod = "DecodeVecShiftL32Imm";
390 let ParserMatchClass = Imm0_31Operand;
392 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
393 return (((uint32_t)Imm) < 64);
395 let EncoderMethod = "getVecShiftL64OpValue";
396 let DecoderMethod = "DecodeVecShiftL64Imm";
397 let ParserMatchClass = Imm0_63Operand;
401 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
402 // instructions for splatting repeating bit patterns across the immediate.
403 def logical_imm32_XFORM : SDNodeXForm<imm, [{
404 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
405 return CurDAG->getTargetConstant(enc, MVT::i32);
407 def logical_imm64_XFORM : SDNodeXForm<imm, [{
408 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
409 return CurDAG->getTargetConstant(enc, MVT::i32);
412 def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
413 def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
414 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
415 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
416 }], logical_imm32_XFORM> {
417 let PrintMethod = "printLogicalImm32";
418 let ParserMatchClass = LogicalImm32Operand;
420 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
421 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
422 }], logical_imm64_XFORM> {
423 let PrintMethod = "printLogicalImm64";
424 let ParserMatchClass = LogicalImm64Operand;
427 // imm0_255 predicate - True if the immediate is in the range [0,255].
428 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
429 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
430 return ((uint32_t)Imm) < 256;
432 let ParserMatchClass = Imm0_255Operand;
435 // imm0_127 predicate - True if the immediate is in the range [0,127]
436 def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
437 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
438 return ((uint32_t)Imm) < 128;
440 let ParserMatchClass = Imm0_127Operand;
443 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
444 // for all shift-amounts.
446 // imm0_63 predicate - True if the immediate is in the range [0,63]
447 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
448 return ((uint64_t)Imm) < 64;
450 let ParserMatchClass = Imm0_63Operand;
453 // imm0_31 predicate - True if the immediate is in the range [0,31]
454 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
455 return ((uint64_t)Imm) < 32;
457 let ParserMatchClass = Imm0_31Operand;
460 // imm0_15 predicate - True if the immediate is in the range [0,15]
461 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
462 return ((uint64_t)Imm) < 16;
464 let ParserMatchClass = Imm0_15Operand;
467 // imm0_7 predicate - True if the immediate is in the range [0,7]
468 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
469 return ((uint64_t)Imm) < 8;
471 let ParserMatchClass = Imm0_7Operand;
474 // An arithmetic shifter operand:
475 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
477 def arith_shift : Operand<i32> {
478 let PrintMethod = "printShifter";
479 let ParserMatchClass = ArithmeticShifterOperand;
482 class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
484 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
485 let PrintMethod = "printShiftedRegister";
486 let MIOperandInfo = (ops regclass, arith_shift);
489 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
490 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
492 // An arithmetic shifter operand:
493 // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
495 def logical_shift : Operand<i32> {
496 let PrintMethod = "printShifter";
497 let ParserMatchClass = ShifterOperand;
500 class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
502 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
503 let PrintMethod = "printShiftedRegister";
504 let MIOperandInfo = (ops regclass, logical_shift);
507 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
508 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
510 // A logical vector shifter operand:
511 // {7-6} - shift type: 00 = lsl
512 // {5-0} - imm6: #0, #8, #16, or #24
513 def logical_vec_shift : Operand<i32> {
514 let PrintMethod = "printShifter";
515 let EncoderMethod = "getVecShifterOpValue";
516 let ParserMatchClass = LogicalVecShifterOperand;
519 // A logical vector half-word shifter operand:
520 // {7-6} - shift type: 00 = lsl
521 // {5-0} - imm6: #0 or #8
522 def logical_vec_hw_shift : Operand<i32> {
523 let PrintMethod = "printShifter";
524 let EncoderMethod = "getVecShifterOpValue";
525 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
528 // A vector move shifter operand:
529 // {0} - imm1: #8 or #16
530 def move_vec_shift : Operand<i32> {
531 let PrintMethod = "printShifter";
532 let EncoderMethod = "getMoveVecShifterOpValue";
533 let ParserMatchClass = MoveVecShifterOperand;
536 // An ADD/SUB immediate shifter operand:
537 // {7-6} - shift type: 00 = lsl
538 // {5-0} - imm6: #0 or #12
539 def addsub_shift : Operand<i32> {
540 let ParserMatchClass = AddSubShifterOperand;
543 class addsub_shifted_imm<ValueType Ty>
544 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
545 let PrintMethod = "printAddSubImm";
546 let EncoderMethod = "getAddSubImmOpValue";
547 let MIOperandInfo = (ops i32imm, addsub_shift);
550 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
551 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
553 class neg_addsub_shifted_imm<ValueType Ty>
554 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
555 let PrintMethod = "printAddSubImm";
556 let EncoderMethod = "getAddSubImmOpValue";
557 let MIOperandInfo = (ops i32imm, addsub_shift);
560 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
561 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
563 // An extend operand:
564 // {5-3} - extend type
566 def arith_extend : Operand<i32> {
567 let PrintMethod = "printExtend";
568 let ParserMatchClass = ExtendOperand;
570 def arith_extend64 : Operand<i32> {
571 let PrintMethod = "printExtend";
572 let ParserMatchClass = ExtendOperand64;
575 // 'extend' that's a lsl of a 64-bit register.
576 def arith_extendlsl64 : Operand<i32> {
577 let PrintMethod = "printExtend";
578 let ParserMatchClass = ExtendOperandLSL64;
581 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
582 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
583 let PrintMethod = "printExtendedRegister";
584 let MIOperandInfo = (ops GPR32, arith_extend);
587 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
588 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
589 let PrintMethod = "printExtendedRegister";
590 let MIOperandInfo = (ops GPR32, arith_extend64);
593 // Floating-point immediate.
594 def fpimm32 : Operand<f32>,
595 PatLeaf<(f32 fpimm), [{
596 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
597 }], SDNodeXForm<fpimm, [{
598 APFloat InVal = N->getValueAPF();
599 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
600 return CurDAG->getTargetConstant(enc, MVT::i32);
602 let ParserMatchClass = FPImmOperand;
603 let PrintMethod = "printFPImmOperand";
605 def fpimm64 : Operand<f64>,
606 PatLeaf<(f64 fpimm), [{
607 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
608 }], SDNodeXForm<fpimm, [{
609 APFloat InVal = N->getValueAPF();
610 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
611 return CurDAG->getTargetConstant(enc, MVT::i32);
613 let ParserMatchClass = FPImmOperand;
614 let PrintMethod = "printFPImmOperand";
617 def fpimm8 : Operand<i32> {
618 let ParserMatchClass = FPImmOperand;
619 let PrintMethod = "printFPImmOperand";
622 def fpimm0 : PatLeaf<(fpimm), [{
623 return N->isExactlyValue(+0.0);
626 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
627 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
628 // are encoded as the eight bit value 'abcdefgh'.
629 def simdimmtype10 : Operand<i32>,
630 PatLeaf<(f64 fpimm), [{
631 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
634 }], SDNodeXForm<fpimm, [{
635 APFloat InVal = N->getValueAPF();
636 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
639 return CurDAG->getTargetConstant(enc, MVT::i32);
641 let ParserMatchClass = SIMDImmType10Operand;
642 let PrintMethod = "printSIMDType10Operand";
650 // Base encoding for system instruction operands.
651 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
652 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
653 : I<oops, iops, asm, operands, "", []> {
654 let Inst{31-22} = 0b1101010100;
658 // System instructions which do not have an Rt register.
659 class SimpleSystemI<bit L, dag iops, string asm, string operands>
660 : BaseSystemI<L, (outs), iops, asm, operands> {
661 let Inst{4-0} = 0b11111;
664 // System instructions which have an Rt register.
665 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
666 : BaseSystemI<L, oops, iops, asm, operands>,
672 // Hint instructions that take both a CRm and a 3-bit immediate.
673 class HintI<string mnemonic>
674 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
677 let Inst{20-12} = 0b000110010;
678 let Inst{11-5} = imm;
681 // System instructions taking a single literal operand which encodes into
682 // CRm. op2 differentiates the opcodes.
683 def BarrierAsmOperand : AsmOperandClass {
684 let Name = "Barrier";
685 let ParserMethod = "tryParseBarrierOperand";
687 def barrier_op : Operand<i32> {
688 let PrintMethod = "printBarrierOption";
689 let ParserMatchClass = BarrierAsmOperand;
691 class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
692 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
693 Sched<[WriteBarrier]> {
695 let Inst{20-12} = 0b000110011;
696 let Inst{11-8} = CRm;
700 // MRS/MSR system instructions. These have different operand classes because
701 // a different subset of registers can be accessed through each instruction.
702 def MRSSystemRegisterOperand : AsmOperandClass {
703 let Name = "MRSSystemRegister";
704 let ParserMethod = "tryParseMRSSystemRegister";
705 let RenderMethod = "addSystemRegisterOperands";
706 let PredicateMethod = "isSystemRegister";
708 // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
709 def mrs_sysreg_op : Operand<i32> {
710 let ParserMatchClass = MRSSystemRegisterOperand;
711 let DecoderMethod = "DecodeMRSSystemRegister";
712 let PrintMethod = "printMRSSystemRegister";
715 def MSRSystemRegisterOperand : AsmOperandClass {
716 let Name = "MSRSystemRegister";
717 let ParserMethod = "tryParseMSRSystemRegister";
718 let RenderMethod = "addSystemRegisterOperands";
719 let PredicateMethod = "isSystemRegister";
721 def msr_sysreg_op : Operand<i32> {
722 let ParserMatchClass = MSRSystemRegisterOperand;
723 let DecoderMethod = "DecodeMSRSystemRegister";
724 let PrintMethod = "printMSRSystemRegister";
727 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
728 "mrs", "\t$Rt, $systemreg"> {
731 let Inst{19-5} = systemreg;
734 // FIXME: Some of these def CPSR, others don't. Best way to model that?
735 // Explicitly modeling each of the system register as a register class
736 // would do it, but feels like overkill at this point.
737 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
738 "msr", "\t$systemreg, $Rt"> {
741 let Inst{19-5} = systemreg;
744 def SystemCPSRFieldOperand : AsmOperandClass {
745 let Name = "SystemCPSRField";
746 let ParserMethod = "tryParseCPSRField";
748 def cpsrfield_op : Operand<i32> {
749 let ParserMatchClass = SystemCPSRFieldOperand;
750 let PrintMethod = "printSystemCPSRField";
754 class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
755 "msr", "\t$cpsr_field, $imm">,
759 let Inst{20-19} = 0b00;
760 let Inst{18-16} = cpsrfield{5-3};
761 let Inst{15-12} = 0b0100;
762 let Inst{11-8} = imm;
763 let Inst{7-5} = cpsrfield{2-0};
765 let DecoderMethod = "DecodeSystemCPSRInstruction";
768 // SYS and SYSL generic system instructions.
769 def SysCRAsmOperand : AsmOperandClass {
771 let ParserMethod = "tryParseSysCROperand";
774 def sys_cr_op : Operand<i32> {
775 let PrintMethod = "printSysCROperand";
776 let ParserMatchClass = SysCRAsmOperand;
779 class SystemI<bit L, string asm>
781 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
782 asm, "\t$op1, $Cn, $Cm, $op2">,
788 let Inst{20-19} = 0b01;
789 let Inst{18-16} = op1;
790 let Inst{15-12} = Cn;
795 class SystemXtI<bit L, string asm>
796 : RtSystemI<L, (outs),
797 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
798 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
803 let Inst{20-19} = 0b01;
804 let Inst{18-16} = op1;
805 let Inst{15-12} = Cn;
810 class SystemLXtI<bit L, string asm>
811 : RtSystemI<L, (outs),
812 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
813 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
818 let Inst{20-19} = 0b01;
819 let Inst{18-16} = op1;
820 let Inst{15-12} = Cn;
826 // Branch (register) instructions:
834 // otherwise UNDEFINED
835 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
836 string operands, list<dag> pattern>
837 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
838 let Inst{31-25} = 0b1101011;
839 let Inst{24-21} = opc;
840 let Inst{20-16} = 0b11111;
841 let Inst{15-10} = 0b000000;
842 let Inst{4-0} = 0b00000;
845 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
846 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
851 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
852 class SpecialReturn<bits<4> opc, string asm>
853 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
854 let Inst{9-5} = 0b11111;
858 // Conditional branch instruction.
860 // Branch condition code.
861 // 4-bit immediate. Pretty-printed as .<cc>
862 def dotCcode : Operand<i32> {
863 let PrintMethod = "printDotCondCode";
866 // Conditional branch target. 19-bit immediate. The low two bits of the target
867 // offset are implied zero and so are not part of the immediate.
868 def BranchTarget19Operand : AsmOperandClass {
869 let Name = "BranchTarget19";
871 def am_brcond : Operand<OtherVT> {
872 let EncoderMethod = "getCondBranchTargetOpValue";
873 let DecoderMethod = "DecodeCondBranchTarget";
874 let PrintMethod = "printAlignedBranchTarget";
875 let ParserMatchClass = BranchTarget19Operand;
878 class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
879 "b", "$cond\t$target", "",
880 [(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
883 let isTerminator = 1;
888 let Inst{31-24} = 0b01010100;
889 let Inst{23-5} = target;
891 let Inst{3-0} = cond;
895 // Compare-and-branch instructions.
897 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
898 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
899 asm, "\t$Rt, $target", "",
900 [(node regtype:$Rt, bb:$target)]>,
903 let isTerminator = 1;
907 let Inst{30-25} = 0b011010;
909 let Inst{23-5} = target;
913 multiclass CmpBranch<bit op, string asm, SDNode node> {
914 def W : BaseCmpBranch<GPR32, op, asm, node> {
917 def X : BaseCmpBranch<GPR64, op, asm, node> {
923 // Test-bit-and-branch instructions.
925 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
926 // the target offset are implied zero and so are not part of the immediate.
927 def BranchTarget14Operand : AsmOperandClass {
928 let Name = "BranchTarget14";
930 def am_tbrcond : Operand<OtherVT> {
931 let EncoderMethod = "getTestBranchTargetOpValue";
932 let PrintMethod = "printAlignedBranchTarget";
933 let ParserMatchClass = BranchTarget14Operand;
936 class TestBranch<bit op, string asm, SDNode node>
937 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
938 asm, "\t$Rt, $bit_off, $target", "",
939 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
942 let isTerminator = 1;
948 let Inst{31} = bit_off{5};
949 let Inst{30-25} = 0b011011;
951 let Inst{23-19} = bit_off{4-0};
952 let Inst{18-5} = target;
955 let DecoderMethod = "DecodeTestAndBranch";
959 // Unconditional branch (immediate) instructions.
961 def BranchTarget26Operand : AsmOperandClass {
962 let Name = "BranchTarget26";
964 def am_b_target : Operand<OtherVT> {
965 let EncoderMethod = "getBranchTargetOpValue";
966 let PrintMethod = "printAlignedBranchTarget";
967 let ParserMatchClass = BranchTarget26Operand;
969 def am_bl_target : Operand<i64> {
970 let EncoderMethod = "getBranchTargetOpValue";
971 let PrintMethod = "printAlignedBranchTarget";
972 let ParserMatchClass = BranchTarget26Operand;
975 class BImm<bit op, dag iops, string asm, list<dag> pattern>
976 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
979 let Inst{30-26} = 0b00101;
980 let Inst{25-0} = addr;
982 let DecoderMethod = "DecodeUnconditionalBranch";
985 class BranchImm<bit op, string asm, list<dag> pattern>
986 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
987 class CallImm<bit op, string asm, list<dag> pattern>
988 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
991 // Basic one-operand data processing instructions.
994 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
995 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
996 SDPatternOperator node>
997 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
998 [(set regtype:$Rd, (node regtype:$Rn))]>,
1003 let Inst{30-13} = 0b101101011000000000;
1004 let Inst{12-10} = opc;
1009 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1010 multiclass OneOperandData<bits<3> opc, string asm,
1011 SDPatternOperator node = null_frag> {
1012 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1016 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1021 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1022 : BaseOneOperandData<opc, GPR32, asm, node> {
1026 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1027 : BaseOneOperandData<opc, GPR64, asm, node> {
1032 // Basic two-operand data processing instructions.
1034 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1036 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1037 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1043 let Inst{30} = isSub;
1044 let Inst{28-21} = 0b11010000;
1045 let Inst{20-16} = Rm;
1046 let Inst{15-10} = 0;
1051 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1053 : BaseBaseAddSubCarry<isSub, regtype, asm,
1054 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
1056 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1058 : BaseBaseAddSubCarry<isSub, regtype, asm,
1059 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
1064 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1065 SDNode OpNode, SDNode OpNode_setflags> {
1066 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1070 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1076 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1081 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1088 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1089 SDPatternOperator OpNode>
1090 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1091 asm, "\t$Rd, $Rn, $Rm", "",
1092 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1096 let Inst{30-21} = 0b0011010110;
1097 let Inst{20-16} = Rm;
1098 let Inst{15-14} = 0b00;
1099 let Inst{13-10} = opc;
1104 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1105 SDPatternOperator OpNode>
1106 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1107 let Inst{10} = isSigned;
1110 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1111 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1112 Sched<[WriteID32]> {
1115 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1116 Sched<[WriteID64]> {
1121 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1122 SDPatternOperator OpNode = null_frag>
1123 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1125 let Inst{11-10} = shift_type;
1128 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1129 def Wr : BaseShift<shift_type, GPR32, asm> {
1133 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1137 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1138 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1139 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1141 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1142 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1144 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1145 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1147 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1148 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1151 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1152 : InstAlias<asm#" $dst, $src1, $src2",
1153 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1155 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1156 RegisterClass addtype, string asm,
1158 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1159 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1164 let Inst{30-24} = 0b0011011;
1165 let Inst{23-21} = opc;
1166 let Inst{20-16} = Rm;
1167 let Inst{15} = isSub;
1168 let Inst{14-10} = Ra;
1173 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1174 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1175 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1176 Sched<[WriteIM32]> {
1180 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1181 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1182 Sched<[WriteIM64]> {
1187 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1188 SDNode AccNode, SDNode ExtNode>
1189 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1190 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1191 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1192 Sched<[WriteIM32]> {
1196 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1197 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1198 asm, "\t$Rd, $Rn, $Rm", "",
1199 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1200 Sched<[WriteIM64]> {
1204 let Inst{31-24} = 0b10011011;
1205 let Inst{23-21} = opc;
1206 let Inst{20-16} = Rm;
1207 let Inst{15-10} = 0b011111;
1212 class MulAccumWAlias<string asm, Instruction inst>
1213 : InstAlias<asm#" $dst, $src1, $src2",
1214 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1215 class MulAccumXAlias<string asm, Instruction inst>
1216 : InstAlias<asm#" $dst, $src1, $src2",
1217 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1218 class WideMulAccumAlias<string asm, Instruction inst>
1219 : InstAlias<asm#" $dst, $src1, $src2",
1220 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1222 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1223 SDPatternOperator OpNode, string asm>
1224 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1225 asm, "\t$Rd, $Rn, $Rm", "",
1226 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1227 Sched<[WriteISReg]> {
1233 let Inst{30-21} = 0b0011010110;
1234 let Inst{20-16} = Rm;
1235 let Inst{15-13} = 0b010;
1237 let Inst{11-10} = sz;
1243 // Address generation.
1246 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1247 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1252 let Inst{31} = page;
1253 let Inst{30-29} = label{1-0};
1254 let Inst{28-24} = 0b10000;
1255 let Inst{23-5} = label{20-2};
1258 let DecoderMethod = "DecodeAdrInstruction";
1265 def movimm32_imm : Operand<i32> {
1266 let ParserMatchClass = Imm0_65535Operand;
1267 let EncoderMethod = "getMoveWideImmOpValue";
1269 def movimm32_shift : Operand<i32> {
1270 let PrintMethod = "printShifter";
1271 let ParserMatchClass = MovImm32ShifterOperand;
1273 def movimm64_shift : Operand<i32> {
1274 let PrintMethod = "printShifter";
1275 let ParserMatchClass = MovImm64ShifterOperand;
1277 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1278 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1280 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1281 asm, "\t$Rd, $imm$shift", "", []>,
1286 let Inst{30-29} = opc;
1287 let Inst{28-23} = 0b100101;
1288 let Inst{22-21} = shift{5-4};
1289 let Inst{20-5} = imm;
1292 let DecoderMethod = "DecodeMoveImmInstruction";
1295 multiclass MoveImmediate<bits<2> opc, string asm> {
1296 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1300 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1305 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1306 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1308 : I<(outs regtype:$Rd),
1309 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1310 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1315 let Inst{30-29} = opc;
1316 let Inst{28-23} = 0b100101;
1317 let Inst{22-21} = shift{5-4};
1318 let Inst{20-5} = imm;
1321 let DecoderMethod = "DecodeMoveImmInstruction";
1324 multiclass InsertImmediate<bits<2> opc, string asm> {
1325 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1329 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1338 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1339 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1340 string asm, SDPatternOperator OpNode>
1341 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1342 asm, "\t$Rd, $Rn, $imm", "",
1343 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1348 let Inst{30} = isSub;
1349 let Inst{29} = setFlags;
1350 let Inst{28-24} = 0b10001;
1351 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1352 let Inst{21-10} = imm{11-0};
1355 let DecoderMethod = "DecodeBaseAddSubImm";
1358 class BaseAddSubRegPseudo<RegisterClass regtype,
1359 SDPatternOperator OpNode>
1360 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1361 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1364 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1365 arith_shifted_reg shifted_regtype, string asm,
1366 SDPatternOperator OpNode>
1367 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1368 asm, "\t$Rd, $Rn, $Rm", "",
1369 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1370 Sched<[WriteISReg]> {
1371 // The operands are in order to match the 'addr' MI operands, so we
1372 // don't need an encoder method and by-name matching. Just use the default
1373 // in-order handling. Since we're using by-order, make sure the names
1379 let Inst{30} = isSub;
1380 let Inst{29} = setFlags;
1381 let Inst{28-24} = 0b01011;
1382 let Inst{23-22} = shift{7-6};
1384 let Inst{20-16} = src2;
1385 let Inst{15-10} = shift{5-0};
1386 let Inst{9-5} = src1;
1387 let Inst{4-0} = dst;
1389 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1392 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1393 RegisterClass src1Regtype, Operand src2Regtype,
1394 string asm, SDPatternOperator OpNode>
1395 : I<(outs dstRegtype:$R1),
1396 (ins src1Regtype:$R2, src2Regtype:$R3),
1397 asm, "\t$R1, $R2, $R3", "",
1398 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1399 Sched<[WriteIEReg]> {
1404 let Inst{30} = isSub;
1405 let Inst{29} = setFlags;
1406 let Inst{28-24} = 0b01011;
1407 let Inst{23-21} = 0b001;
1408 let Inst{20-16} = Rm;
1409 let Inst{15-13} = ext{5-3};
1410 let Inst{12-10} = ext{2-0};
1414 let DecoderMethod = "DecodeAddSubERegInstruction";
1417 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1418 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1419 RegisterClass src1Regtype, RegisterClass src2Regtype,
1420 Operand ext_op, string asm>
1421 : I<(outs dstRegtype:$Rd),
1422 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1423 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1424 Sched<[WriteIEReg]> {
1429 let Inst{30} = isSub;
1430 let Inst{29} = setFlags;
1431 let Inst{28-24} = 0b01011;
1432 let Inst{23-21} = 0b001;
1433 let Inst{20-16} = Rm;
1434 let Inst{15} = ext{5};
1435 let Inst{12-10} = ext{2-0};
1439 let DecoderMethod = "DecodeAddSubERegInstruction";
1442 // Aliases for register+register add/subtract.
1443 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1444 RegisterClass src1Regtype, RegisterClass src2Regtype,
1446 : InstAlias<asm#" $dst, $src1, $src2",
1447 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1450 multiclass AddSub<bit isSub, string mnemonic,
1451 SDPatternOperator OpNode = null_frag> {
1452 let hasSideEffects = 0 in {
1453 // Add/Subtract immediate
1454 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1458 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1463 // Add/Subtract register - Only used for CodeGen
1464 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1465 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1467 // Add/Subtract shifted register
1468 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1472 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1478 // Add/Subtract extended register
1479 let AddedComplexity = 1, hasSideEffects = 0 in {
1480 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1481 arith_extended_reg32<i32>, mnemonic, OpNode> {
1484 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1485 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1490 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1491 arith_extendlsl64, mnemonic> {
1492 // UXTX and SXTX only.
1493 let Inst{14-13} = 0b11;
1497 // Register/register aliases with no shift when SP is not used.
1498 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1499 GPR32, GPR32, GPR32, 0>;
1500 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1501 GPR64, GPR64, GPR64, 0>;
1503 // Register/register aliases with no shift when either the destination or
1504 // first source register is SP. This relies on the shifted register aliases
1505 // above matching first in the case when SP is not used.
1506 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1507 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1508 def : AddSubRegAlias<mnemonic,
1509 !cast<Instruction>(NAME#"Xrx64"),
1510 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1513 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1514 let isCompare = 1, Defs = [CPSR] in {
1515 // Add/Subtract immediate
1516 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1520 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1525 // Add/Subtract register
1526 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1527 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1529 // Add/Subtract shifted register
1530 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1534 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1539 // Add/Subtract extended register
1540 let AddedComplexity = 1 in {
1541 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1542 arith_extended_reg32<i32>, mnemonic, OpNode> {
1545 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1546 arith_extended_reg32<i64>, mnemonic, OpNode> {
1551 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1552 arith_extendlsl64, mnemonic> {
1553 // UXTX and SXTX only.
1554 let Inst{14-13} = 0b11;
1559 // Register/register aliases with no shift when SP is not used.
1560 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1561 GPR32, GPR32, GPR32, 0>;
1562 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1563 GPR64, GPR64, GPR64, 0>;
1565 // Register/register aliases with no shift when the first source register
1566 // is SP. This relies on the shifted register aliases above matching first
1567 // in the case when SP is not used.
1568 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1569 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1570 def : AddSubRegAlias<mnemonic,
1571 !cast<Instruction>(NAME#"Xrx64"),
1572 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1578 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1580 def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1582 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1584 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1585 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1586 Sched<[WriteExtr, ReadExtrHi]> {
1592 let Inst{30-23} = 0b00100111;
1594 let Inst{20-16} = Rm;
1595 let Inst{15-10} = imm;
1600 multiclass ExtractImm<string asm> {
1601 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1603 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1607 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1609 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1620 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1621 class BaseBitfieldImm<bits<2> opc,
1622 RegisterClass regtype, Operand imm_type, string asm>
1623 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1624 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1631 let Inst{30-29} = opc;
1632 let Inst{28-23} = 0b100110;
1633 let Inst{21-16} = immr;
1634 let Inst{15-10} = imms;
1639 multiclass BitfieldImm<bits<2> opc, string asm> {
1640 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1644 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1650 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1651 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1652 RegisterClass regtype, Operand imm_type, string asm>
1653 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1655 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1662 let Inst{30-29} = opc;
1663 let Inst{28-23} = 0b100110;
1664 let Inst{21-16} = immr;
1665 let Inst{15-10} = imms;
1670 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1671 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1675 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1685 // Logical (immediate)
1686 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1687 RegisterClass sregtype, Operand imm_type, string asm,
1689 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1690 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1695 let Inst{30-29} = opc;
1696 let Inst{28-23} = 0b100100;
1697 let Inst{22} = imm{12};
1698 let Inst{21-16} = imm{11-6};
1699 let Inst{15-10} = imm{5-0};
1703 let DecoderMethod = "DecodeLogicalImmInstruction";
1706 // Logical (shifted register)
1707 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1708 logical_shifted_reg shifted_regtype, string asm,
1710 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1711 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1712 Sched<[WriteISReg]> {
1713 // The operands are in order to match the 'addr' MI operands, so we
1714 // don't need an encoder method and by-name matching. Just use the default
1715 // in-order handling. Since we're using by-order, make sure the names
1721 let Inst{30-29} = opc;
1722 let Inst{28-24} = 0b01010;
1723 let Inst{23-22} = shift{7-6};
1725 let Inst{20-16} = src2;
1726 let Inst{15-10} = shift{5-0};
1727 let Inst{9-5} = src1;
1728 let Inst{4-0} = dst;
1730 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1733 // Aliases for register+register logical instructions.
1734 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1735 : InstAlias<asm#" $dst, $src1, $src2",
1736 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1738 let AddedComplexity = 6 in
1739 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1740 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1741 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1742 logical_imm32:$imm))]> {
1744 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1746 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1747 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1748 logical_imm64:$imm))]> {
1753 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1754 let isCompare = 1, Defs = [CPSR] in {
1755 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1756 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1758 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1760 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1761 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1764 } // end Defs = [CPSR]
1767 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1768 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1769 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1772 // Split from LogicalImm as not all instructions have both.
1773 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1774 SDPatternOperator OpNode> {
1775 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1776 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1778 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1779 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1780 logical_shifted_reg32:$Rm))]> {
1783 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1784 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1785 logical_shifted_reg64:$Rm))]> {
1789 def : LogicalRegAlias<mnemonic,
1790 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1791 def : LogicalRegAlias<mnemonic,
1792 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1795 // Split from LogicalReg to allow setting CPSR Defs
1796 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1797 let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1798 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1801 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1806 def : LogicalRegAlias<mnemonic,
1807 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1808 def : LogicalRegAlias<mnemonic,
1809 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1813 // Conditionally set flags
1817 // 4-bit immediate. Pretty-printed as <cc>
1818 def ccode : Operand<i32> {
1819 let PrintMethod = "printCondCode";
1822 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1823 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1824 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1825 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1836 let Inst{29-21} = 0b111010010;
1837 let Inst{20-16} = imm;
1838 let Inst{15-12} = cond;
1839 let Inst{11-10} = 0b10;
1842 let Inst{3-0} = nzcv;
1845 multiclass CondSetFlagsImm<bit op, string asm> {
1846 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1849 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1854 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1855 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1856 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1857 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1868 let Inst{29-21} = 0b111010010;
1869 let Inst{20-16} = Rm;
1870 let Inst{15-12} = cond;
1871 let Inst{11-10} = 0b00;
1874 let Inst{3-0} = nzcv;
1877 multiclass CondSetFlagsReg<bit op, string asm> {
1878 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1881 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1887 // Conditional select
1890 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1891 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1892 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1894 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1904 let Inst{29-21} = 0b011010100;
1905 let Inst{20-16} = Rm;
1906 let Inst{15-12} = cond;
1907 let Inst{11-10} = op2;
1912 multiclass CondSelect<bit op, bits<2> op2, string asm> {
1913 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1916 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1921 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1923 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1924 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1926 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1927 (i32 imm:$cond), CPSR))]>,
1937 let Inst{29-21} = 0b011010100;
1938 let Inst{20-16} = Rm;
1939 let Inst{15-12} = cond;
1940 let Inst{11-10} = op2;
1945 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1946 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1949 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1955 // Special Mask Value
1957 def maski8_or_more : Operand<i32>,
1958 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1960 def maski16_or_more : Operand<i32>,
1961 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1969 // (unsigned immediate)
1970 // Indexed for 8-bit registers. offset is in range [0,4095].
1971 def MemoryIndexed8Operand : AsmOperandClass {
1972 let Name = "MemoryIndexed8";
1973 let DiagnosticType = "InvalidMemoryIndexed8";
1975 def am_indexed8 : Operand<i64>,
1976 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1977 let PrintMethod = "printAMIndexed8";
1979 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1980 let ParserMatchClass = MemoryIndexed8Operand;
1981 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1984 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
1985 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
1986 def MemoryIndexed16Operand : AsmOperandClass {
1987 let Name = "MemoryIndexed16";
1988 let DiagnosticType = "InvalidMemoryIndexed16";
1990 def am_indexed16 : Operand<i64>,
1991 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
1992 let PrintMethod = "printAMIndexed16";
1994 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
1995 let ParserMatchClass = MemoryIndexed16Operand;
1996 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1999 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2000 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2001 def MemoryIndexed32Operand : AsmOperandClass {
2002 let Name = "MemoryIndexed32";
2003 let DiagnosticType = "InvalidMemoryIndexed32";
2005 def am_indexed32 : Operand<i64>,
2006 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2007 let PrintMethod = "printAMIndexed32";
2009 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2010 let ParserMatchClass = MemoryIndexed32Operand;
2011 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2014 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2015 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2016 def MemoryIndexed64Operand : AsmOperandClass {
2017 let Name = "MemoryIndexed64";
2018 let DiagnosticType = "InvalidMemoryIndexed64";
2020 def am_indexed64 : Operand<i64>,
2021 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2022 let PrintMethod = "printAMIndexed64";
2024 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2025 let ParserMatchClass = MemoryIndexed64Operand;
2026 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2029 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2030 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2031 def MemoryIndexed128Operand : AsmOperandClass {
2032 let Name = "MemoryIndexed128";
2033 let DiagnosticType = "InvalidMemoryIndexed128";
2035 def am_indexed128 : Operand<i64>,
2036 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2037 let PrintMethod = "printAMIndexed128";
2039 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2040 let ParserMatchClass = MemoryIndexed128Operand;
2041 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2045 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2046 def am_noindex : Operand<i64>,
2047 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2048 let PrintMethod = "printAMNoIndex";
2049 let ParserMatchClass = MemoryNoIndexOperand;
2050 let MIOperandInfo = (ops GPR64sp:$base);
2053 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2054 string asm, list<dag> pattern>
2055 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2059 bits<5> base = addr{4-0};
2060 bits<12> offset = addr{16-5};
2062 let Inst{31-30} = sz;
2063 let Inst{29-27} = 0b111;
2065 let Inst{25-24} = 0b01;
2066 let Inst{23-22} = opc;
2067 let Inst{21-10} = offset;
2068 let Inst{9-5} = base;
2069 let Inst{4-0} = dst;
2071 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2074 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2075 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2076 Operand indextype, string asm, list<dag> pattern>
2077 : BaseLoadStoreUI<sz, V, opc,
2078 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2081 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2082 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2083 Operand indextype, string asm, list<dag> pattern>
2084 : BaseLoadStoreUI<sz, V, opc,
2085 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2088 def PrefetchOperand : AsmOperandClass {
2089 let Name = "Prefetch";
2090 let ParserMethod = "tryParsePrefetch";
2092 def prfop : Operand<i32> {
2093 let PrintMethod = "printPrefetchOp";
2094 let ParserMatchClass = PrefetchOperand;
2097 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2098 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2099 : BaseLoadStoreUI<sz, V, opc,
2100 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2107 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2108 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2109 : I<(outs regtype:$Rt), (ins am_brcond:$label),
2110 asm, "\t$Rt, $label", "", []>,
2114 let Inst{31-30} = opc;
2115 let Inst{29-27} = 0b011;
2117 let Inst{25-24} = 0b00;
2118 let Inst{23-5} = label;
2122 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2123 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2124 : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2125 asm, "\t$Rt, $label", "", pat>,
2129 let Inst{31-30} = opc;
2130 let Inst{29-27} = 0b011;
2132 let Inst{25-24} = 0b00;
2133 let Inst{23-5} = label;
2138 // Load/store register offset
2141 class MemROAsmOperand<int sz> : AsmOperandClass {
2142 let Name = "MemoryRegisterOffset"#sz;
2145 def MemROAsmOperand8 : MemROAsmOperand<8>;
2146 def MemROAsmOperand16 : MemROAsmOperand<16>;
2147 def MemROAsmOperand32 : MemROAsmOperand<32>;
2148 def MemROAsmOperand64 : MemROAsmOperand<64>;
2149 def MemROAsmOperand128 : MemROAsmOperand<128>;
2151 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2152 let PrintMethod = "printMemoryRegOffset"#sz;
2153 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2156 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2157 let ParserMatchClass = MemROAsmOperand8;
2160 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2161 let ParserMatchClass = MemROAsmOperand16;
2164 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2165 let ParserMatchClass = MemROAsmOperand32;
2168 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2169 let ParserMatchClass = MemROAsmOperand64;
2172 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2173 let ParserMatchClass = MemROAsmOperand128;
2176 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2177 string asm, dag ins, dag outs, list<dag> pat>
2178 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2179 // The operands are in order to match the 'addr' MI operands, so we
2180 // don't need an encoder method and by-name matching. Just use the default
2181 // in-order handling. Since we're using by-order, make sure the names
2187 let Inst{31-30} = sz;
2188 let Inst{29-27} = 0b111;
2190 let Inst{25-24} = 0b00;
2191 let Inst{23-22} = opc;
2193 let Inst{20-16} = offset;
2194 let Inst{15-13} = extend{3-1};
2196 let Inst{12} = extend{0};
2197 let Inst{11-10} = 0b10;
2198 let Inst{9-5} = base;
2199 let Inst{4-0} = dst;
2201 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2204 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2205 string asm, list<dag> pat>
2206 : LoadStore8RO<sz, V, opc, regtype, asm,
2207 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2208 Sched<[WriteLDIdx, ReadAdrBase]>;
2210 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2211 string asm, list<dag> pat>
2212 : LoadStore8RO<sz, V, opc, regtype, asm,
2213 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2214 Sched<[WriteSTIdx, ReadAdrBase]>;
2216 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2217 string asm, dag ins, dag outs, list<dag> pat>
2218 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2219 // The operands are in order to match the 'addr' MI operands, so we
2220 // don't need an encoder method and by-name matching. Just use the default
2221 // in-order handling. Since we're using by-order, make sure the names
2227 let Inst{31-30} = sz;
2228 let Inst{29-27} = 0b111;
2230 let Inst{25-24} = 0b00;
2231 let Inst{23-22} = opc;
2233 let Inst{20-16} = offset;
2234 let Inst{15-13} = extend{3-1};
2236 let Inst{12} = extend{0};
2237 let Inst{11-10} = 0b10;
2238 let Inst{9-5} = base;
2239 let Inst{4-0} = dst;
2241 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2244 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2245 string asm, list<dag> pat>
2246 : LoadStore16RO<sz, V, opc, regtype, asm,
2247 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2248 Sched<[WriteLDIdx, ReadAdrBase]>;
2250 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2251 string asm, list<dag> pat>
2252 : LoadStore16RO<sz, V, opc, regtype, asm,
2253 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2254 Sched<[WriteSTIdx, ReadAdrBase]>;
2256 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2257 string asm, dag ins, dag outs, list<dag> pat>
2258 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2259 // The operands are in order to match the 'addr' MI operands, so we
2260 // don't need an encoder method and by-name matching. Just use the default
2261 // in-order handling. Since we're using by-order, make sure the names
2267 let Inst{31-30} = sz;
2268 let Inst{29-27} = 0b111;
2270 let Inst{25-24} = 0b00;
2271 let Inst{23-22} = opc;
2273 let Inst{20-16} = offset;
2274 let Inst{15-13} = extend{3-1};
2276 let Inst{12} = extend{0};
2277 let Inst{11-10} = 0b10;
2278 let Inst{9-5} = base;
2279 let Inst{4-0} = dst;
2281 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2284 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2285 string asm, list<dag> pat>
2286 : LoadStore32RO<sz, V, opc, regtype, asm,
2287 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2288 Sched<[WriteLDIdx, ReadAdrBase]>;
2290 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2291 string asm, list<dag> pat>
2292 : LoadStore32RO<sz, V, opc, regtype, asm,
2293 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2294 Sched<[WriteSTIdx, ReadAdrBase]>;
2296 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2297 string asm, dag ins, dag outs, list<dag> pat>
2298 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2299 // The operands are in order to match the 'addr' MI operands, so we
2300 // don't need an encoder method and by-name matching. Just use the default
2301 // in-order handling. Since we're using by-order, make sure the names
2307 let Inst{31-30} = sz;
2308 let Inst{29-27} = 0b111;
2310 let Inst{25-24} = 0b00;
2311 let Inst{23-22} = opc;
2313 let Inst{20-16} = offset;
2314 let Inst{15-13} = extend{3-1};
2316 let Inst{12} = extend{0};
2317 let Inst{11-10} = 0b10;
2318 let Inst{9-5} = base;
2319 let Inst{4-0} = dst;
2321 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2324 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2325 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2326 string asm, list<dag> pat>
2327 : LoadStore64RO<sz, V, opc, regtype, asm,
2328 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2329 Sched<[WriteLDIdx, ReadAdrBase]>;
2331 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2332 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2333 string asm, list<dag> pat>
2334 : LoadStore64RO<sz, V, opc, regtype, asm,
2335 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2336 Sched<[WriteSTIdx, ReadAdrBase]>;
2339 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2340 string asm, dag ins, dag outs, list<dag> pat>
2341 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2342 // The operands are in order to match the 'addr' MI operands, so we
2343 // don't need an encoder method and by-name matching. Just use the default
2344 // in-order handling. Since we're using by-order, make sure the names
2350 let Inst{31-30} = sz;
2351 let Inst{29-27} = 0b111;
2353 let Inst{25-24} = 0b00;
2354 let Inst{23-22} = opc;
2356 let Inst{20-16} = offset;
2357 let Inst{15-13} = extend{3-1};
2359 let Inst{12} = extend{0};
2360 let Inst{11-10} = 0b10;
2361 let Inst{9-5} = base;
2362 let Inst{4-0} = dst;
2364 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2367 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2368 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2369 string asm, list<dag> pat>
2370 : LoadStore128RO<sz, V, opc, regtype, asm,
2371 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2372 Sched<[WriteLDIdx, ReadAdrBase]>;
2374 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2375 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2376 string asm, list<dag> pat>
2377 : LoadStore128RO<sz, V, opc, regtype, asm,
2378 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2379 Sched<[WriteSTIdx, ReadAdrBase]>;
2381 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2382 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2383 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2384 "\t$Rt, $addr", "", pat>,
2386 // The operands are in order to match the 'addr' MI operands, so we
2387 // don't need an encoder method and by-name matching. Just use the default
2388 // in-order handling. Since we're using by-order, make sure the names
2394 let Inst{31-30} = sz;
2395 let Inst{29-27} = 0b111;
2397 let Inst{25-24} = 0b00;
2398 let Inst{23-22} = opc;
2400 let Inst{20-16} = offset;
2401 let Inst{15-13} = extend{3-1};
2403 let Inst{12} = extend{0};
2404 let Inst{11-10} = 0b10;
2405 let Inst{9-5} = base;
2406 let Inst{4-0} = dst;
2408 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2412 // Load/store unscaled immediate
2415 def MemoryUnscaledOperand : AsmOperandClass {
2416 let Name = "MemoryUnscaled";
2417 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2419 class am_unscaled_operand : Operand<i64> {
2420 let PrintMethod = "printAMUnscaled";
2421 let ParserMatchClass = MemoryUnscaledOperand;
2422 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2424 def am_unscaled : am_unscaled_operand;
2425 def am_unscaled8 : am_unscaled_operand,
2426 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2427 def am_unscaled16 : am_unscaled_operand,
2428 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2429 def am_unscaled32 : am_unscaled_operand,
2430 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2431 def am_unscaled64 : am_unscaled_operand,
2432 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2433 def am_unscaled128 : am_unscaled_operand,
2434 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2436 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2437 string asm, list<dag> pattern>
2438 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2439 // The operands are in order to match the 'addr' MI operands, so we
2440 // don't need an encoder method and by-name matching. Just use the default
2441 // in-order handling. Since we're using by-order, make sure the names
2446 let Inst{31-30} = sz;
2447 let Inst{29-27} = 0b111;
2449 let Inst{25-24} = 0b00;
2450 let Inst{23-22} = opc;
2452 let Inst{20-12} = offset;
2453 let Inst{11-10} = 0b00;
2454 let Inst{9-5} = base;
2455 let Inst{4-0} = dst;
2457 let DecoderMethod = "DecodeSignedLdStInstruction";
2460 let AddedComplexity = 1 in // try this before LoadUI
2461 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2462 Operand amtype, string asm, list<dag> pattern>
2463 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2464 (ins amtype:$addr), asm, pattern>,
2467 let AddedComplexity = 1 in // try this before StoreUI
2468 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2469 Operand amtype, string asm, list<dag> pattern>
2470 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2471 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2474 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2475 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2476 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2477 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2481 // Load/store unscaled immediate, unprivileged
2484 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2485 dag oops, dag iops, string asm>
2486 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2487 // The operands are in order to match the 'addr' MI operands, so we
2488 // don't need an encoder method and by-name matching. Just use the default
2489 // in-order handling. Since we're using by-order, make sure the names
2494 let Inst{31-30} = sz;
2495 let Inst{29-27} = 0b111;
2497 let Inst{25-24} = 0b00;
2498 let Inst{23-22} = opc;
2500 let Inst{20-12} = offset;
2501 let Inst{11-10} = 0b10;
2502 let Inst{9-5} = base;
2503 let Inst{4-0} = dst;
2505 let DecoderMethod = "DecodeSignedLdStInstruction";
2508 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2509 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2511 : BaseLoadStoreUnprivileged<sz, V, opc,
2512 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2516 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2517 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2519 : BaseLoadStoreUnprivileged<sz, V, opc,
2520 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2525 // Load/store pre-indexed
2528 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2529 string asm, string cstr>
2530 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2531 // The operands are in order to match the 'addr' MI operands, so we
2532 // don't need an encoder method and by-name matching. Just use the default
2533 // in-order handling.
2537 let Inst{31-30} = sz;
2538 let Inst{29-27} = 0b111;
2540 let Inst{25-24} = 0;
2541 let Inst{23-22} = opc;
2543 let Inst{20-12} = offset;
2544 let Inst{11-10} = 0b11;
2545 let Inst{9-5} = base;
2546 let Inst{4-0} = dst;
2548 let DecoderMethod = "DecodeSignedLdStInstruction";
2551 let hasSideEffects = 0 in {
2552 let mayStore = 0, mayLoad = 1 in
2553 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2554 // we need the complex addressing mode for the memory reference, but
2555 // we also need the write-back specified as a tied operand to the
2556 // base register. That combination does not play nicely with
2557 // the asm matcher and friends.
2558 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2560 : BaseLoadStorePreIdx<sz, V, opc,
2561 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2562 (ins am_unscaled:$addr), asm, ""/*"$addr.base = $wback"*/>,
2563 Sched<[WriteLD, WriteAdr]>;
2565 let mayStore = 1, mayLoad = 0 in
2566 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2568 : BaseLoadStorePreIdx<sz, V, opc,
2569 (outs/* GPR64sp:$wback*/),
2570 (ins regtype:$Rt, am_unscaled:$addr),
2571 asm, ""/*"$addr.base = $wback"*/>,
2572 Sched<[WriteAdr, WriteST]>;
2573 } // hasSideEffects = 0
2575 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2576 // logic finally gets smart enough to strip off tied operands that are just
2577 // for isel convenience, we can get rid of these pseudos and just reference
2578 // the real instructions directly.
2580 // Ironically, also because of the writeback operands, we can't put the
2581 // matcher pattern directly on the instruction, but need to define it
2584 // Loads aren't matched with patterns here at all, but rather in C++
2586 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2587 class LoadPreIdxPseudo<RegisterClass regtype>
2588 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2589 (ins am_noindex:$addr, simm9:$offset), [],
2590 "$addr.base = $wback,@earlyclobber $wback">,
2591 Sched<[WriteLD, WriteAdr]>;
2592 class LoadPostIdxPseudo<RegisterClass regtype>
2593 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2594 (ins am_noindex:$addr, simm9:$offset), [],
2595 "$addr.base = $wback,@earlyclobber $wback">,
2596 Sched<[WriteLD, WriteI]>;
2598 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2599 SDPatternOperator OpNode> {
2600 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2601 def _isel: Pseudo<(outs GPR64sp:$wback),
2602 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2603 "$addr.base = $wback,@earlyclobber $wback">,
2604 Sched<[WriteAdr, WriteST]>;
2606 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2607 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2612 // Load/store post-indexed
2615 // (pre-index) load/stores.
2616 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2617 string asm, string cstr>
2618 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2619 // The operands are in order to match the 'addr' MI operands, so we
2620 // don't need an encoder method and by-name matching. Just use the default
2621 // in-order handling.
2625 let Inst{31-30} = sz;
2626 let Inst{29-27} = 0b111;
2628 let Inst{25-24} = 0b00;
2629 let Inst{23-22} = opc;
2631 let Inst{20-12} = offset;
2632 let Inst{11-10} = 0b01;
2633 let Inst{9-5} = base;
2634 let Inst{4-0} = dst;
2636 let DecoderMethod = "DecodeSignedLdStInstruction";
2639 let hasSideEffects = 0 in {
2640 let mayStore = 0, mayLoad = 1 in
2641 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2642 // we need the complex addressing mode for the memory reference, but
2643 // we also need the write-back specified as a tied operand to the
2644 // base register. That combination does not play nicely with
2645 // the asm matcher and friends.
2646 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2648 : BaseLoadStorePostIdx<sz, V, opc,
2649 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2650 (ins am_noindex:$addr, simm9:$idx),
2651 asm, ""/*"$addr.base = $wback"*/>,
2652 Sched<[WriteLD, WriteI]>;
2654 let mayStore = 1, mayLoad = 0 in
2655 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2657 : BaseLoadStorePostIdx<sz, V, opc,
2658 (outs/* GPR64sp:$wback*/),
2659 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2660 asm, ""/*"$addr.base = $wback"*/>,
2661 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2662 } // hasSideEffects = 0
2664 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2665 // logic finally gets smart enough to strip off tied operands that are just
2666 // for isel convenience, we can get rid of these pseudos and just reference
2667 // the real instructions directly.
2669 // Ironically, also because of the writeback operands, we can't put the
2670 // matcher pattern directly on the instruction, but need to define it
2672 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2673 SDPatternOperator OpNode, Instruction Insn> {
2674 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2675 def _isel: Pseudo<(outs GPR64sp:$wback),
2676 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2677 "$addr.base = $wback,@earlyclobber $wback">,
2678 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2679 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2681 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2682 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2690 // (indexed, offset)
2692 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2694 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2695 // The operands are in order to match the 'addr' MI operands, so we
2696 // don't need an encoder method and by-name matching. Just use the default
2697 // in-order handling. Since we're using by-order, make sure the names
2703 let Inst{31-30} = opc;
2704 let Inst{29-27} = 0b101;
2706 let Inst{25-23} = 0b010;
2708 let Inst{21-15} = offset;
2709 let Inst{14-10} = dst2;
2710 let Inst{9-5} = base;
2711 let Inst{4-0} = dst;
2713 let DecoderMethod = "DecodePairLdStInstruction";
2716 let hasSideEffects = 0 in {
2717 let mayStore = 0, mayLoad = 1 in
2718 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2719 Operand indextype, string asm>
2720 : BaseLoadStorePairOffset<opc, V, 1,
2721 (outs regtype:$Rt, regtype:$Rt2),
2722 (ins indextype:$addr), asm>,
2723 Sched<[WriteLD, WriteLDHi]>;
2725 let mayLoad = 0, mayStore = 1 in
2726 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2727 Operand indextype, string asm>
2728 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2729 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2732 } // hasSideEffects = 0
2736 def MemoryIndexed32SImm7 : AsmOperandClass {
2737 let Name = "MemoryIndexed32SImm7";
2738 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2740 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2741 let PrintMethod = "printAMIndexed32";
2742 let ParserMatchClass = MemoryIndexed32SImm7;
2743 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2746 def MemoryIndexed64SImm7 : AsmOperandClass {
2747 let Name = "MemoryIndexed64SImm7";
2748 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2750 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2751 let PrintMethod = "printAMIndexed64";
2752 let ParserMatchClass = MemoryIndexed64SImm7;
2753 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2756 def MemoryIndexed128SImm7 : AsmOperandClass {
2757 let Name = "MemoryIndexed128SImm7";
2758 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2760 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2761 let PrintMethod = "printAMIndexed128";
2762 let ParserMatchClass = MemoryIndexed128SImm7;
2763 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2766 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2768 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2769 // The operands are in order to match the 'addr' MI operands, so we
2770 // don't need an encoder method and by-name matching. Just use the default
2771 // in-order handling. Since we're using by-order, make sure the names
2777 let Inst{31-30} = opc;
2778 let Inst{29-27} = 0b101;
2780 let Inst{25-23} = 0b011;
2782 let Inst{21-15} = offset;
2783 let Inst{14-10} = dst2;
2784 let Inst{9-5} = base;
2785 let Inst{4-0} = dst;
2787 let DecoderMethod = "DecodePairLdStInstruction";
2790 let hasSideEffects = 0 in {
2791 let mayStore = 0, mayLoad = 1 in
2792 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2793 Operand addrmode, string asm>
2794 : BaseLoadStorePairPreIdx<opc, V, 1,
2795 (outs regtype:$Rt, regtype:$Rt2),
2796 (ins addrmode:$addr), asm>,
2797 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2799 let mayStore = 1, mayLoad = 0 in
2800 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2801 Operand addrmode, string asm>
2802 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2803 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2805 Sched<[WriteAdr, WriteSTP]>;
2806 } // hasSideEffects = 0
2810 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2812 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2813 // The operands are in order to match the 'addr' MI operands, so we
2814 // don't need an encoder method and by-name matching. Just use the default
2815 // in-order handling. Since we're using by-order, make sure the names
2821 let Inst{31-30} = opc;
2822 let Inst{29-27} = 0b101;
2824 let Inst{25-23} = 0b001;
2826 let Inst{21-15} = offset;
2827 let Inst{14-10} = dst2;
2828 let Inst{9-5} = base;
2829 let Inst{4-0} = dst;
2831 let DecoderMethod = "DecodePairLdStInstruction";
2834 let hasSideEffects = 0 in {
2835 let mayStore = 0, mayLoad = 1 in
2836 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2837 Operand idxtype, string asm>
2838 : BaseLoadStorePairPostIdx<opc, V, 1,
2839 (outs regtype:$Rt, regtype:$Rt2),
2840 (ins am_noindex:$addr, idxtype:$idx), asm>,
2841 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2843 let mayStore = 1, mayLoad = 0 in
2844 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2845 Operand idxtype, string asm>
2846 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2847 (ins regtype:$Rt, regtype:$Rt2,
2848 am_noindex:$addr, idxtype:$idx),
2850 Sched<[WriteAdr, WriteSTP]>;
2851 } // hasSideEffects = 0
2855 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2857 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2858 // The operands are in order to match the 'addr' MI operands, so we
2859 // don't need an encoder method and by-name matching. Just use the default
2860 // in-order handling. Since we're using by-order, make sure the names
2866 let Inst{31-30} = opc;
2867 let Inst{29-27} = 0b101;
2869 let Inst{25-23} = 0b000;
2871 let Inst{21-15} = offset;
2872 let Inst{14-10} = dst2;
2873 let Inst{9-5} = base;
2874 let Inst{4-0} = dst;
2876 let DecoderMethod = "DecodePairLdStInstruction";
2879 let hasSideEffects = 0 in {
2880 let mayStore = 0, mayLoad = 1 in
2881 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2882 Operand indextype, string asm>
2883 : BaseLoadStorePairNoAlloc<opc, V, 1,
2884 (outs regtype:$Rt, regtype:$Rt2),
2885 (ins indextype:$addr), asm>,
2886 Sched<[WriteLD, WriteLDHi]>;
2888 let mayStore = 1, mayLoad = 0 in
2889 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2890 Operand indextype, string asm>
2891 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2892 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2895 } // hasSideEffects = 0
2898 // Load/store exclusive
2901 // True exclusive operations write to and/or read from the system's exclusive
2902 // monitors, which as far as a compiler is concerned can be modelled as a
2903 // random shared memory address. Hence LoadExclusive mayStore.
2905 // Since these instructions have the undefined register bits set to 1 in
2906 // their canonical form, we need a post encoder method to set those bits
2907 // to 1 when encoding these instructions. We do this using the
2908 // fixLoadStoreExclusive function. This function has template parameters:
2910 // fixLoadStoreExclusive<int hasRs, int hasRt2>
2912 // hasRs indicates that the instruction uses the Rs field, so we won't set
2913 // it to 1 (and the same for Rt2). We don't need template parameters for
2914 // the other register fields since Rt and Rn are always used.
2916 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2917 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2918 dag oops, dag iops, string asm, string operands>
2919 : I<oops, iops, asm, operands, "", []> {
2920 let Inst{31-30} = sz;
2921 let Inst{29-24} = 0b001000;
2927 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2930 // Neither Rs nor Rt2 operands.
2931 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2932 dag oops, dag iops, string asm, string operands>
2933 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2936 let Inst{9-5} = base;
2937 let Inst{4-0} = reg;
2939 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
2942 // Simple load acquires don't set the exclusive monitor
2943 let mayLoad = 1, mayStore = 0 in
2944 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2945 RegisterClass regtype, string asm>
2946 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2947 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2950 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2951 RegisterClass regtype, string asm>
2952 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2953 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2956 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2957 RegisterClass regtype, string asm>
2958 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2959 (outs regtype:$Rt, regtype:$Rt2),
2960 (ins am_noindex:$addr), asm,
2961 "\t$Rt, $Rt2, $addr">,
2962 Sched<[WriteLD, WriteLDHi]> {
2966 let Inst{14-10} = dst2;
2967 let Inst{9-5} = base;
2968 let Inst{4-0} = dst1;
2970 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
2973 // Simple store release operations do not check the exclusive monitor.
2974 let mayLoad = 0, mayStore = 1 in
2975 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2976 RegisterClass regtype, string asm>
2977 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
2978 (ins regtype:$Rt, am_noindex:$addr),
2979 asm, "\t$Rt, $addr">,
2982 let mayLoad = 1, mayStore = 1 in
2983 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2984 RegisterClass regtype, string asm>
2985 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
2986 (ins regtype:$Rt, am_noindex:$addr),
2987 asm, "\t$Ws, $Rt, $addr">,
2992 let Inst{20-16} = status;
2993 let Inst{9-5} = base;
2994 let Inst{4-0} = reg;
2996 let Constraints = "@earlyclobber $Ws";
2997 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3000 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3001 RegisterClass regtype, string asm>
3002 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3004 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3005 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3011 let Inst{20-16} = status;
3012 let Inst{14-10} = dst2;
3013 let Inst{9-5} = base;
3014 let Inst{4-0} = dst1;
3016 let Constraints = "@earlyclobber $Ws";
3020 // Exception generation
3023 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3024 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3025 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3028 let Inst{31-24} = 0b11010100;
3029 let Inst{23-21} = op1;
3030 let Inst{20-5} = imm;
3031 let Inst{4-2} = 0b000;
3036 // Floating point to integer conversion
3039 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3040 RegisterClass srcType, RegisterClass dstType,
3041 string asm, list<dag> pattern>
3042 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3043 asm, "\t$Rd, $Rn", "", pattern>,
3044 Sched<[WriteFCvt]> {
3048 let Inst{28-24} = 0b11110;
3049 let Inst{23-22} = type;
3051 let Inst{20-19} = rmode;
3052 let Inst{18-16} = opcode;
3053 let Inst{15-10} = 0;
3058 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3059 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3060 RegisterClass srcType, RegisterClass dstType,
3061 Operand immType, string asm>
3062 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3063 asm, "\t$Rd, $Rn, $scale", "", []>,
3064 Sched<[WriteFCvt]> {
3069 let Inst{28-24} = 0b11110;
3070 let Inst{23-22} = type;
3072 let Inst{20-19} = rmode;
3073 let Inst{18-16} = opcode;
3074 let Inst{15-10} = scale;
3079 multiclass FPToInteger<bits<2> rmode, bits<3> opcode, string asm, SDPatternOperator OpN> {
3080 // Unscaled single-precision to 32-bit
3081 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3082 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3083 let Inst{31} = 0; // 32-bit GPR flag
3086 // Unscaled single-precision to 64-bit
3087 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3088 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3089 let Inst{31} = 1; // 64-bit GPR flag
3092 // Unscaled double-precision to 32-bit
3093 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3094 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3095 let Inst{31} = 0; // 32-bit GPR flag
3098 // Unscaled double-precision to 64-bit
3099 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3100 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3101 let Inst{31} = 1; // 64-bit GPR flag
3104 // Scaled single-precision to 32-bit
3105 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3106 fixedpoint32, asm> {
3107 let Inst{31} = 0; // 32-bit GPR flag
3110 // Scaled single-precision to 64-bit
3111 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3112 fixedpoint64, asm> {
3113 let Inst{31} = 1; // 64-bit GPR flag
3116 // Scaled double-precision to 32-bit
3117 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3118 fixedpoint32, asm> {
3119 let Inst{31} = 0; // 32-bit GPR flag
3122 // Scaled double-precision to 64-bit
3123 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3124 fixedpoint64, asm> {
3125 let Inst{31} = 1; // 64-bit GPR flag
3130 // Integer to floating point conversion
3133 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3134 class BaseIntegerToFP<bit isUnsigned,
3135 RegisterClass srcType, RegisterClass dstType,
3136 Operand immType, string asm>
3137 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3138 asm, "\t$Rd, $Rn, $scale", "", []>,
3139 Sched<[WriteFCvt]> {
3143 let Inst{30-23} = 0b00111100;
3144 let Inst{21-17} = 0b00001;
3145 let Inst{16} = isUnsigned;
3146 let Inst{15-10} = scale;
3151 class BaseIntegerToFPUnscaled<bit isUnsigned,
3152 RegisterClass srcType, RegisterClass dstType,
3153 ValueType dvt, string asm, SDNode node>
3154 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3155 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3156 Sched<[WriteFCvt]> {
3160 let Inst{30-23} = 0b00111100;
3161 let Inst{21-17} = 0b10001;
3162 let Inst{16} = isUnsigned;
3163 let Inst{15-10} = 0b000000;
3168 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3170 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3171 let Inst{31} = 0; // 32-bit GPR flag
3172 let Inst{22} = 0; // 32-bit FPR flag
3175 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3176 let Inst{31} = 0; // 32-bit GPR flag
3177 let Inst{22} = 1; // 64-bit FPR flag
3180 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3181 let Inst{31} = 1; // 64-bit GPR flag
3182 let Inst{22} = 0; // 32-bit FPR flag
3185 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3186 let Inst{31} = 1; // 64-bit GPR flag
3187 let Inst{22} = 1; // 64-bit FPR flag
3191 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint32, asm> {
3192 let Inst{31} = 0; // 32-bit GPR flag
3193 let Inst{22} = 0; // 32-bit FPR flag
3196 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint32, asm> {
3197 let Inst{31} = 0; // 32-bit GPR flag
3198 let Inst{22} = 1; // 64-bit FPR flag
3201 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint64, asm> {
3202 let Inst{31} = 1; // 64-bit GPR flag
3203 let Inst{22} = 0; // 32-bit FPR flag
3206 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint64, asm> {
3207 let Inst{31} = 1; // 64-bit GPR flag
3208 let Inst{22} = 1; // 64-bit FPR flag
3213 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3216 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3217 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3218 RegisterClass srcType, RegisterClass dstType,
3220 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3221 // We use COPY_TO_REGCLASS for these bitconvert operations.
3222 // copyPhysReg() expands the resultant COPY instructions after
3223 // regalloc is done. This gives greater freedom for the allocator
3224 // and related passes (coalescing, copy propagation, et. al.) to
3225 // be more effective.
3226 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3227 Sched<[WriteFCopy]> {
3230 let Inst{30-23} = 0b00111100;
3232 let Inst{20-19} = rmode;
3233 let Inst{18-16} = opcode;
3234 let Inst{15-10} = 0b000000;
3239 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3240 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3241 RegisterClass srcType, RegisterOperand dstType, string asm>
3242 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd[1], $Rn", "", []>,
3243 Sched<[WriteFCopy]> {
3246 let Inst{30-23} = 0b00111101;
3248 let Inst{20-19} = rmode;
3249 let Inst{18-16} = opcode;
3250 let Inst{15-10} = 0b000000;
3255 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3256 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3257 RegisterOperand srcType, RegisterClass dstType, string asm>
3258 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn[1]", "", []>,
3259 Sched<[WriteFCopy]> {
3262 let Inst{30-23} = 0b00111101;
3264 let Inst{20-19} = rmode;
3265 let Inst{18-16} = opcode;
3266 let Inst{15-10} = 0b000000;
3273 multiclass UnscaledConversion<string asm> {
3274 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3275 let Inst{31} = 0; // 32-bit GPR flag
3276 let Inst{22} = 0; // 32-bit FPR flag
3279 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3280 let Inst{31} = 1; // 64-bit GPR flag
3281 let Inst{22} = 1; // 64-bit FPR flag
3284 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3285 let Inst{31} = 0; // 32-bit GPR flag
3286 let Inst{22} = 0; // 32-bit FPR flag
3289 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3290 let Inst{31} = 1; // 64-bit GPR flag
3291 let Inst{22} = 1; // 64-bit FPR flag
3294 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3300 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3306 def : InstAlias<asm#"$Vd.d[1], $Rn",
3307 (!cast<Instruction>(NAME#XDHighr) V128:$Vd, GPR64:$Rn), 0>;
3308 def : InstAlias<asm#"$Rd, $Vn.d[1]",
3309 (!cast<Instruction>(NAME#DXHighr) GPR64:$Rd, V128:$Vn), 0>;
3313 // Floating point conversion
3316 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3317 RegisterClass srcType, string asm, list<dag> pattern>
3318 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3319 Sched<[WriteFCvt]> {
3322 let Inst{31-24} = 0b00011110;
3323 let Inst{23-22} = type;
3324 let Inst{21-17} = 0b10001;
3325 let Inst{16-15} = opcode;
3326 let Inst{14-10} = 0b10000;
3331 multiclass FPConversion<string asm> {
3332 // Double-precision to Half-precision
3333 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3334 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, []>;
3336 // Double-precision to Single-precision
3337 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3338 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3340 // Half-precision to Double-precision
3341 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3342 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, []>;
3344 // Half-precision to Single-precision
3345 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3346 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, []>;
3348 // Single-precision to Double-precision
3349 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3350 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3352 // Single-precision to Half-precision
3353 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3354 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, []>;
3358 // Single operand floating point data processing
3361 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3362 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3363 ValueType vt, string asm, SDPatternOperator node>
3364 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3365 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3369 let Inst{31-23} = 0b000111100;
3370 let Inst{21-19} = 0b100;
3371 let Inst{18-15} = opcode;
3372 let Inst{14-10} = 0b10000;
3377 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3378 SDPatternOperator node = null_frag> {
3379 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3380 let Inst{22} = 0; // 32-bit size flag
3383 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3384 let Inst{22} = 1; // 64-bit size flag
3389 // Two operand floating point data processing
3392 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3393 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3394 string asm, list<dag> pat>
3395 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3396 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3401 let Inst{31-23} = 0b000111100;
3403 let Inst{20-16} = Rm;
3404 let Inst{15-12} = opcode;
3405 let Inst{11-10} = 0b10;
3410 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3411 SDPatternOperator node = null_frag> {
3412 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3413 [(set (f32 FPR32:$Rd),
3414 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3415 let Inst{22} = 0; // 32-bit size flag
3418 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3419 [(set (f64 FPR64:$Rd),
3420 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3421 let Inst{22} = 1; // 64-bit size flag
3425 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3426 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3427 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3428 let Inst{22} = 0; // 32-bit size flag
3431 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3432 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3433 let Inst{22} = 1; // 64-bit size flag
3439 // Three operand floating point data processing
3442 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3443 RegisterClass regtype, string asm, list<dag> pat>
3444 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3445 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3446 Sched<[WriteFMul]> {
3451 let Inst{31-23} = 0b000111110;
3452 let Inst{21} = isNegated;
3453 let Inst{20-16} = Rm;
3454 let Inst{15} = isSub;
3455 let Inst{14-10} = Ra;
3460 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3461 SDPatternOperator node> {
3462 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3464 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3465 let Inst{22} = 0; // 32-bit size flag
3468 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3470 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3471 let Inst{22} = 1; // 64-bit size flag
3476 // Floating point data comparisons
3479 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3480 class BaseOneOperandFPComparison<bit signalAllNans,
3481 RegisterClass regtype, string asm,
3483 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3484 Sched<[WriteFCmp]> {
3486 let Inst{31-23} = 0b000111100;
3489 let Inst{20-16} = 0b00000;
3490 let Inst{15-10} = 0b001000;
3492 let Inst{4} = signalAllNans;
3493 let Inst{3-0} = 0b1000;
3496 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3497 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3498 string asm, list<dag> pat>
3499 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3500 Sched<[WriteFCmp]> {
3503 let Inst{31-23} = 0b000111100;
3505 let Inst{20-16} = Rm;
3506 let Inst{15-10} = 0b001000;
3508 let Inst{4} = signalAllNans;
3509 let Inst{3-0} = 0b0000;
3512 multiclass FPComparison<bit signalAllNans, string asm,
3513 SDPatternOperator OpNode = null_frag> {
3514 let Defs = [CPSR] in {
3515 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3516 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3520 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3521 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3525 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3526 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3530 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3531 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3538 // Floating point conditional comparisons
3541 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3542 class BaseFPCondComparison<bit signalAllNans,
3543 RegisterClass regtype, string asm>
3544 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3545 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3546 Sched<[WriteFCmp]> {
3552 let Inst{31-23} = 0b000111100;
3554 let Inst{20-16} = Rm;
3555 let Inst{15-12} = cond;
3556 let Inst{11-10} = 0b01;
3558 let Inst{4} = signalAllNans;
3559 let Inst{3-0} = nzcv;
3562 multiclass FPCondComparison<bit signalAllNans, string asm> {
3563 let Defs = [CPSR], Uses = [CPSR] in {
3564 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3568 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3571 } // Defs = [CPSR], Uses = [CPSR]
3575 // Floating point conditional select
3578 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3579 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3580 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3582 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3583 (i32 imm:$cond), CPSR))]>,
3590 let Inst{31-23} = 0b000111100;
3592 let Inst{20-16} = Rm;
3593 let Inst{15-12} = cond;
3594 let Inst{11-10} = 0b11;
3599 multiclass FPCondSelect<string asm> {
3600 let Uses = [CPSR] in {
3601 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3605 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3612 // Floating move immediate
3615 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3616 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3617 [(set regtype:$Rd, fpimmtype:$imm)]>,
3618 Sched<[WriteFImm]> {
3621 let Inst{31-23} = 0b000111100;
3623 let Inst{20-13} = imm;
3624 let Inst{12-5} = 0b10000000;
3628 multiclass FPMoveImmediate<string asm> {
3629 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3633 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3638 //----------------------------------------------------------------------------
3640 //----------------------------------------------------------------------------
3642 def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3643 def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3644 def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3645 def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3646 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3647 return ((uint64_t)Imm) < 16;
3649 let ParserMatchClass = VectorIndexBOperand;
3650 let PrintMethod = "printVectorIndex";
3651 let MIOperandInfo = (ops i64imm);
3653 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3654 return ((uint64_t)Imm) < 8;
3656 let ParserMatchClass = VectorIndexHOperand;
3657 let PrintMethod = "printVectorIndex";
3658 let MIOperandInfo = (ops i64imm);
3660 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3661 return ((uint64_t)Imm) < 4;
3663 let ParserMatchClass = VectorIndexSOperand;
3664 let PrintMethod = "printVectorIndex";
3665 let MIOperandInfo = (ops i64imm);
3667 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3668 return ((uint64_t)Imm) < 2;
3670 let ParserMatchClass = VectorIndexDOperand;
3671 let PrintMethod = "printVectorIndex";
3672 let MIOperandInfo = (ops i64imm);
3675 //----------------------------------------------------------------------------
3676 // AdvSIMD three register vector instructions
3677 //----------------------------------------------------------------------------
3679 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3680 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3681 RegisterOperand regtype, string asm, string kind,
3683 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3684 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3685 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3693 let Inst{28-24} = 0b01110;
3694 let Inst{23-22} = size;
3696 let Inst{20-16} = Rm;
3697 let Inst{15-11} = opcode;
3703 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3704 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3705 RegisterOperand regtype, string asm, string kind,
3707 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3708 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3709 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3717 let Inst{28-24} = 0b01110;
3718 let Inst{23-22} = size;
3720 let Inst{20-16} = Rm;
3721 let Inst{15-11} = opcode;
3727 // All operand sizes distinguished in the encoding.
3728 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3729 SDPatternOperator OpNode> {
3730 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3732 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3733 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3735 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3736 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3738 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3739 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3741 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3742 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3744 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3745 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3747 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3748 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3750 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3753 // As above, but D sized elements unsupported.
3754 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3755 SDPatternOperator OpNode> {
3756 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3758 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3759 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3761 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3762 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3764 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3765 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3767 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3768 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3770 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3771 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3773 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3776 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3777 SDPatternOperator OpNode> {
3778 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3780 [(set (v8i8 V64:$dst),
3781 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3782 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3784 [(set (v16i8 V128:$dst),
3785 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3786 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3788 [(set (v4i16 V64:$dst),
3789 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3790 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3792 [(set (v8i16 V128:$dst),
3793 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3794 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3796 [(set (v2i32 V64:$dst),
3797 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3798 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3800 [(set (v4i32 V128:$dst),
3801 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3804 // As above, but only B sized elements supported.
3805 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3806 SDPatternOperator OpNode> {
3807 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3809 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3810 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3812 [(set (v16i8 V128:$Rd),
3813 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3816 // As above, but only S and D sized floating point elements supported.
3817 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3818 string asm, SDPatternOperator OpNode> {
3819 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3821 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3822 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3824 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3825 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3827 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3830 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3832 SDPatternOperator OpNode> {
3833 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3835 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3836 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3838 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3839 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3841 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3844 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3845 string asm, SDPatternOperator OpNode> {
3846 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3848 [(set (v2f32 V64:$dst),
3849 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3850 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3852 [(set (v4f32 V128:$dst),
3853 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3854 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3856 [(set (v2f64 V128:$dst),
3857 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3860 // As above, but D and B sized elements unsupported.
3861 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3862 SDPatternOperator OpNode> {
3863 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3865 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3866 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3868 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3869 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3871 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3872 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3874 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3877 // Logical three vector ops share opcode bits, and only use B sized elements.
3878 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3879 SDPatternOperator OpNode = null_frag> {
3880 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3882 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3883 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3885 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3887 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3888 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3889 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3890 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3891 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3892 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3894 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3895 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3896 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3897 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3898 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3899 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3902 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3903 string asm, SDPatternOperator OpNode> {
3904 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3906 [(set (v8i8 V64:$dst),
3907 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3908 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3910 [(set (v16i8 V128:$dst),
3911 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3912 (v16i8 V128:$Rm)))]>;
3914 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3916 (!cast<Instruction>(NAME#"v8i8")
3917 V64:$LHS, V64:$MHS, V64:$RHS)>;
3918 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3920 (!cast<Instruction>(NAME#"v8i8")
3921 V64:$LHS, V64:$MHS, V64:$RHS)>;
3922 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3924 (!cast<Instruction>(NAME#"v8i8")
3925 V64:$LHS, V64:$MHS, V64:$RHS)>;
3927 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3928 (v8i16 V128:$RHS))),
3929 (!cast<Instruction>(NAME#"v16i8")
3930 V128:$LHS, V128:$MHS, V128:$RHS)>;
3931 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
3932 (v4i32 V128:$RHS))),
3933 (!cast<Instruction>(NAME#"v16i8")
3934 V128:$LHS, V128:$MHS, V128:$RHS)>;
3935 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
3936 (v2i64 V128:$RHS))),
3937 (!cast<Instruction>(NAME#"v16i8")
3938 V128:$LHS, V128:$MHS, V128:$RHS)>;
3942 //----------------------------------------------------------------------------
3943 // AdvSIMD two register vector instructions.
3944 //----------------------------------------------------------------------------
3946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3947 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3948 RegisterOperand regtype, string asm, string dstkind,
3949 string srckind, list<dag> pattern>
3950 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
3951 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3952 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
3959 let Inst{28-24} = 0b01110;
3960 let Inst{23-22} = size;
3961 let Inst{21-17} = 0b10000;
3962 let Inst{16-12} = opcode;
3963 let Inst{11-10} = 0b10;
3968 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3969 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3970 RegisterOperand regtype, string asm, string dstkind,
3971 string srckind, list<dag> pattern>
3972 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
3973 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3974 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
3981 let Inst{28-24} = 0b01110;
3982 let Inst{23-22} = size;
3983 let Inst{21-17} = 0b10000;
3984 let Inst{16-12} = opcode;
3985 let Inst{11-10} = 0b10;
3990 // Supports B, H, and S element sizes.
3991 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
3992 SDPatternOperator OpNode> {
3993 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
3995 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
3996 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
3997 asm, ".16b", ".16b",
3998 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
3999 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4001 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4002 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4004 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4005 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4007 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4008 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4010 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4013 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4014 RegisterOperand regtype, string asm, string dstkind,
4015 string srckind, string amount>
4016 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4017 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4018 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4024 let Inst{29-24} = 0b101110;
4025 let Inst{23-22} = size;
4026 let Inst{21-10} = 0b100001001110;
4031 multiclass SIMDVectorLShiftLongBySizeBHS {
4032 let neverHasSideEffects = 1 in {
4033 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4034 "shll", ".8h", ".8b", "8">;
4035 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4036 "shll2", ".8h", ".16b", "8">;
4037 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4038 "shll", ".4s", ".4h", "16">;
4039 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4040 "shll2", ".4s", ".8h", "16">;
4041 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4042 "shll", ".2d", ".2s", "32">;
4043 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4044 "shll2", ".2d", ".4s", "32">;
4048 // Supports all element sizes.
4049 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4050 SDPatternOperator OpNode> {
4051 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4053 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4054 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4056 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4057 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4059 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4060 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4062 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4063 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4065 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4066 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4068 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4071 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4072 SDPatternOperator OpNode> {
4073 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4075 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4077 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4079 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4080 (v16i8 V128:$Rn)))]>;
4081 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4083 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4084 (v4i16 V64:$Rn)))]>;
4085 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4087 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4088 (v8i16 V128:$Rn)))]>;
4089 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4091 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4092 (v2i32 V64:$Rn)))]>;
4093 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4095 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4096 (v4i32 V128:$Rn)))]>;
4099 // Supports all element sizes, except 1xD.
4100 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4101 SDPatternOperator OpNode> {
4102 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4104 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4105 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4106 asm, ".16b", ".16b",
4107 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4108 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4110 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4111 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4113 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4114 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4116 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4117 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4119 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4120 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4122 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4125 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4126 SDPatternOperator OpNode = null_frag> {
4127 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4129 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4130 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4131 asm, ".16b", ".16b",
4132 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4133 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4135 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4136 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4138 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4139 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4141 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4142 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4144 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4145 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4147 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4151 // Supports only B element sizes.
4152 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4153 SDPatternOperator OpNode> {
4154 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4156 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4157 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4158 asm, ".16b", ".16b",
4159 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4163 // Supports only B and H element sizes.
4164 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4165 SDPatternOperator OpNode> {
4166 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4168 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4169 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4170 asm, ".16b", ".16b",
4171 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4172 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4174 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4175 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4177 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4180 // Supports only S and D element sizes, uses high bit of the size field
4181 // as an extra opcode bit.
4182 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4183 SDPatternOperator OpNode> {
4184 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4186 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4187 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4189 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4190 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4192 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4195 // Supports only S element size.
4196 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4197 SDPatternOperator OpNode> {
4198 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4200 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4201 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4203 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4207 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4208 SDPatternOperator OpNode> {
4209 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4211 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4212 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4214 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4215 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4217 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4220 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4221 SDPatternOperator OpNode> {
4222 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4224 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4225 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4227 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4228 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4230 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4234 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4235 RegisterOperand inreg, RegisterOperand outreg,
4236 string asm, string outkind, string inkind,
4238 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4239 "{\t$Rd" # outkind # ", $Rn" # inkind #
4240 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4247 let Inst{28-24} = 0b01110;
4248 let Inst{23-22} = size;
4249 let Inst{21-17} = 0b10000;
4250 let Inst{16-12} = opcode;
4251 let Inst{11-10} = 0b10;
4256 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4257 RegisterOperand inreg, RegisterOperand outreg,
4258 string asm, string outkind, string inkind,
4260 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4261 "{\t$Rd" # outkind # ", $Rn" # inkind #
4262 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4269 let Inst{28-24} = 0b01110;
4270 let Inst{23-22} = size;
4271 let Inst{21-17} = 0b10000;
4272 let Inst{16-12} = opcode;
4273 let Inst{11-10} = 0b10;
4278 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4279 SDPatternOperator OpNode> {
4280 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4282 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4283 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4284 asm#"2", ".16b", ".8h", []>;
4285 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4287 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4288 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4289 asm#"2", ".8h", ".4s", []>;
4290 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4292 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4293 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4294 asm#"2", ".4s", ".2d", []>;
4296 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4297 (!cast<Instruction>(NAME # "v16i8")
4298 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4299 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4300 (!cast<Instruction>(NAME # "v8i16")
4301 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4302 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4303 (!cast<Instruction>(NAME # "v4i32")
4304 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4307 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4308 RegisterOperand regtype, string asm, string kind,
4309 ValueType dty, ValueType sty, SDNode OpNode>
4310 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4311 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4312 "|" # kind # "\t$Rd, $Rn, #0}", "",
4313 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4320 let Inst{28-24} = 0b01110;
4321 let Inst{23-22} = size;
4322 let Inst{21-17} = 0b10000;
4323 let Inst{16-12} = opcode;
4324 let Inst{11-10} = 0b10;
4329 // Comparisons support all element sizes, except 1xD.
4330 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4332 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4334 v8i8, v8i8, OpNode>;
4335 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4337 v16i8, v16i8, OpNode>;
4338 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4340 v4i16, v4i16, OpNode>;
4341 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4343 v8i16, v8i16, OpNode>;
4344 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4346 v2i32, v2i32, OpNode>;
4347 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4349 v4i32, v4i32, OpNode>;
4350 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4352 v2i64, v2i64, OpNode>;
4355 // FP Comparisons support only S and D element sizes.
4356 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4357 string asm, SDNode OpNode> {
4358 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4360 v2i32, v2f32, OpNode>;
4361 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4363 v4i32, v4f32, OpNode>;
4364 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4366 v2i64, v2f64, OpNode>;
4369 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4370 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4371 RegisterOperand outtype, RegisterOperand intype,
4372 string asm, string VdTy, string VnTy,
4374 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4375 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4382 let Inst{28-24} = 0b01110;
4383 let Inst{23-22} = size;
4384 let Inst{21-17} = 0b10000;
4385 let Inst{16-12} = opcode;
4386 let Inst{11-10} = 0b10;
4391 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4392 RegisterOperand outtype, RegisterOperand intype,
4393 string asm, string VdTy, string VnTy,
4395 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4396 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4403 let Inst{28-24} = 0b01110;
4404 let Inst{23-22} = size;
4405 let Inst{21-17} = 0b10000;
4406 let Inst{16-12} = opcode;
4407 let Inst{11-10} = 0b10;
4412 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4413 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4414 asm, ".4s", ".4h", []>;
4415 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4416 asm#"2", ".4s", ".8h", []>;
4417 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4418 asm, ".2d", ".2s", []>;
4419 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4420 asm#"2", ".2d", ".4s", []>;
4423 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4424 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4425 asm, ".4h", ".4s", []>;
4426 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4427 asm#"2", ".8h", ".4s", []>;
4428 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4429 asm, ".2s", ".2d", []>;
4430 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4431 asm#"2", ".4s", ".2d", []>;
4434 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4436 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4438 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4439 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4440 asm#"2", ".4s", ".2d", []>;
4442 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4443 (!cast<Instruction>(NAME # "v4f32")
4444 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4447 //----------------------------------------------------------------------------
4448 // AdvSIMD three register different-size vector instructions.
4449 //----------------------------------------------------------------------------
4451 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4452 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4453 RegisterOperand outtype, RegisterOperand intype1,
4454 RegisterOperand intype2, string asm,
4455 string outkind, string inkind1, string inkind2,
4457 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4458 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4459 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4465 let Inst{30} = size{0};
4467 let Inst{28-24} = 0b01110;
4468 let Inst{23-22} = size{2-1};
4470 let Inst{20-16} = Rm;
4471 let Inst{15-12} = opcode;
4472 let Inst{11-10} = 0b00;
4477 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4478 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4479 RegisterOperand outtype, RegisterOperand intype1,
4480 RegisterOperand intype2, string asm,
4481 string outkind, string inkind1, string inkind2,
4483 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4484 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4485 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4491 let Inst{30} = size{0};
4493 let Inst{28-24} = 0b01110;
4494 let Inst{23-22} = size{2-1};
4496 let Inst{20-16} = Rm;
4497 let Inst{15-12} = opcode;
4498 let Inst{11-10} = 0b00;
4503 // FIXME: TableGen doesn't know how to deal with expanded types that also
4504 // change the element count (in this case, placing the results in
4505 // the high elements of the result register rather than the low
4506 // elements). Until that's fixed, we can't code-gen those.
4507 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4509 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4511 asm, ".8b", ".8h", ".8h",
4512 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4513 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4515 asm#"2", ".16b", ".8h", ".8h",
4517 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4519 asm, ".4h", ".4s", ".4s",
4520 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4521 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4523 asm#"2", ".8h", ".4s", ".4s",
4525 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4527 asm, ".2s", ".2d", ".2d",
4528 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4529 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4531 asm#"2", ".4s", ".2d", ".2d",
4535 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4536 // a version attached to an instruction.
4537 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4539 (!cast<Instruction>(NAME # "v8i16_v16i8")
4540 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4541 V128:$Rn, V128:$Rm)>;
4542 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4544 (!cast<Instruction>(NAME # "v4i32_v8i16")
4545 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4546 V128:$Rn, V128:$Rm)>;
4547 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4549 (!cast<Instruction>(NAME # "v2i64_v4i32")
4550 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4551 V128:$Rn, V128:$Rm)>;
4554 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4556 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4558 asm, ".8h", ".8b", ".8b",
4559 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4560 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4562 asm#"2", ".8h", ".16b", ".16b", []>;
4563 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4565 asm, ".1q", ".1d", ".1d", []>;
4566 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4568 asm#"2", ".1q", ".2d", ".2d", []>;
4570 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4571 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4572 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4575 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4576 SDPatternOperator OpNode> {
4577 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4579 asm, ".4s", ".4h", ".4h",
4580 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4581 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4583 asm#"2", ".4s", ".8h", ".8h",
4584 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4585 (extract_high_v8i16 V128:$Rm)))]>;
4586 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4588 asm, ".2d", ".2s", ".2s",
4589 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4590 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4592 asm#"2", ".2d", ".4s", ".4s",
4593 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4594 (extract_high_v4i32 V128:$Rm)))]>;
4597 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4598 SDPatternOperator OpNode = null_frag> {
4599 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4601 asm, ".8h", ".8b", ".8b",
4602 [(set (v8i16 V128:$Rd),
4603 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4604 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4606 asm#"2", ".8h", ".16b", ".16b",
4607 [(set (v8i16 V128:$Rd),
4608 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4609 (extract_high_v16i8 V128:$Rm)))))]>;
4610 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4612 asm, ".4s", ".4h", ".4h",
4613 [(set (v4i32 V128:$Rd),
4614 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4615 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4617 asm#"2", ".4s", ".8h", ".8h",
4618 [(set (v4i32 V128:$Rd),
4619 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4620 (extract_high_v8i16 V128:$Rm)))))]>;
4621 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4623 asm, ".2d", ".2s", ".2s",
4624 [(set (v2i64 V128:$Rd),
4625 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4626 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4628 asm#"2", ".2d", ".4s", ".4s",
4629 [(set (v2i64 V128:$Rd),
4630 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4631 (extract_high_v4i32 V128:$Rm)))))]>;
4634 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4636 SDPatternOperator OpNode> {
4637 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4639 asm, ".8h", ".8b", ".8b",
4640 [(set (v8i16 V128:$dst),
4641 (add (v8i16 V128:$Rd),
4642 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4643 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4645 asm#"2", ".8h", ".16b", ".16b",
4646 [(set (v8i16 V128:$dst),
4647 (add (v8i16 V128:$Rd),
4648 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4649 (extract_high_v16i8 V128:$Rm))))))]>;
4650 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4652 asm, ".4s", ".4h", ".4h",
4653 [(set (v4i32 V128:$dst),
4654 (add (v4i32 V128:$Rd),
4655 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4656 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4658 asm#"2", ".4s", ".8h", ".8h",
4659 [(set (v4i32 V128:$dst),
4660 (add (v4i32 V128:$Rd),
4661 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4662 (extract_high_v8i16 V128:$Rm))))))]>;
4663 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4665 asm, ".2d", ".2s", ".2s",
4666 [(set (v2i64 V128:$dst),
4667 (add (v2i64 V128:$Rd),
4668 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4669 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4671 asm#"2", ".2d", ".4s", ".4s",
4672 [(set (v2i64 V128:$dst),
4673 (add (v2i64 V128:$Rd),
4674 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4675 (extract_high_v4i32 V128:$Rm))))))]>;
4678 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4679 SDPatternOperator OpNode = null_frag> {
4680 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4682 asm, ".8h", ".8b", ".8b",
4683 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4684 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4686 asm#"2", ".8h", ".16b", ".16b",
4687 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4688 (extract_high_v16i8 V128:$Rm)))]>;
4689 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4691 asm, ".4s", ".4h", ".4h",
4692 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4693 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4695 asm#"2", ".4s", ".8h", ".8h",
4696 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4697 (extract_high_v8i16 V128:$Rm)))]>;
4698 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4700 asm, ".2d", ".2s", ".2s",
4701 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4702 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4704 asm#"2", ".2d", ".4s", ".4s",
4705 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4706 (extract_high_v4i32 V128:$Rm)))]>;
4709 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4711 SDPatternOperator OpNode> {
4712 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4714 asm, ".8h", ".8b", ".8b",
4715 [(set (v8i16 V128:$dst),
4716 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4717 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4719 asm#"2", ".8h", ".16b", ".16b",
4720 [(set (v8i16 V128:$dst),
4721 (OpNode (v8i16 V128:$Rd),
4722 (extract_high_v16i8 V128:$Rn),
4723 (extract_high_v16i8 V128:$Rm)))]>;
4724 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4726 asm, ".4s", ".4h", ".4h",
4727 [(set (v4i32 V128:$dst),
4728 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4729 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4731 asm#"2", ".4s", ".8h", ".8h",
4732 [(set (v4i32 V128:$dst),
4733 (OpNode (v4i32 V128:$Rd),
4734 (extract_high_v8i16 V128:$Rn),
4735 (extract_high_v8i16 V128:$Rm)))]>;
4736 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4738 asm, ".2d", ".2s", ".2s",
4739 [(set (v2i64 V128:$dst),
4740 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4741 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4743 asm#"2", ".2d", ".4s", ".4s",
4744 [(set (v2i64 V128:$dst),
4745 (OpNode (v2i64 V128:$Rd),
4746 (extract_high_v4i32 V128:$Rn),
4747 (extract_high_v4i32 V128:$Rm)))]>;
4750 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4751 SDPatternOperator Accum> {
4752 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4754 asm, ".4s", ".4h", ".4h",
4755 [(set (v4i32 V128:$dst),
4756 (Accum (v4i32 V128:$Rd),
4757 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4758 (v4i16 V64:$Rm)))))]>;
4759 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4761 asm#"2", ".4s", ".8h", ".8h",
4762 [(set (v4i32 V128:$dst),
4763 (Accum (v4i32 V128:$Rd),
4764 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4765 (extract_high_v8i16 V128:$Rm)))))]>;
4766 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4768 asm, ".2d", ".2s", ".2s",
4769 [(set (v2i64 V128:$dst),
4770 (Accum (v2i64 V128:$Rd),
4771 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4772 (v2i32 V64:$Rm)))))]>;
4773 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4775 asm#"2", ".2d", ".4s", ".4s",
4776 [(set (v2i64 V128:$dst),
4777 (Accum (v2i64 V128:$Rd),
4778 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4779 (extract_high_v4i32 V128:$Rm)))))]>;
4782 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4783 SDPatternOperator OpNode> {
4784 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4786 asm, ".8h", ".8h", ".8b",
4787 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4788 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4790 asm#"2", ".8h", ".8h", ".16b",
4791 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4792 (extract_high_v16i8 V128:$Rm)))]>;
4793 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4795 asm, ".4s", ".4s", ".4h",
4796 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4797 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4799 asm#"2", ".4s", ".4s", ".8h",
4800 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4801 (extract_high_v8i16 V128:$Rm)))]>;
4802 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4804 asm, ".2d", ".2d", ".2s",
4805 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4806 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4808 asm#"2", ".2d", ".2d", ".4s",
4809 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4810 (extract_high_v4i32 V128:$Rm)))]>;
4813 //----------------------------------------------------------------------------
4814 // AdvSIMD bitwise extract from vector
4815 //----------------------------------------------------------------------------
4817 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4818 string asm, string kind>
4819 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4820 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4821 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4822 [(set (vty regtype:$Rd),
4823 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4830 let Inst{30} = size;
4831 let Inst{29-21} = 0b101110000;
4832 let Inst{20-16} = Rm;
4834 let Inst{14-11} = imm;
4841 multiclass SIMDBitwiseExtract<string asm> {
4842 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b">;
4843 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4846 //----------------------------------------------------------------------------
4847 // AdvSIMD zip vector
4848 //----------------------------------------------------------------------------
4850 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4851 string asm, string kind, SDNode OpNode, ValueType valty>
4852 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4853 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4854 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4855 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4861 let Inst{30} = size{0};
4862 let Inst{29-24} = 0b001110;
4863 let Inst{23-22} = size{2-1};
4865 let Inst{20-16} = Rm;
4867 let Inst{14-12} = opc;
4868 let Inst{11-10} = 0b10;
4873 multiclass SIMDZipVector<bits<3>opc, string asm,
4875 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4876 asm, ".8b", OpNode, v8i8>;
4877 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4878 asm, ".16b", OpNode, v16i8>;
4879 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4880 asm, ".4h", OpNode, v4i16>;
4881 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4882 asm, ".8h", OpNode, v8i16>;
4883 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4884 asm, ".2s", OpNode, v2i32>;
4885 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4886 asm, ".4s", OpNode, v4i32>;
4887 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4888 asm, ".2d", OpNode, v2i64>;
4890 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4891 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4892 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4893 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4894 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4895 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4898 //----------------------------------------------------------------------------
4899 // AdvSIMD three register scalar instructions
4900 //----------------------------------------------------------------------------
4902 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4903 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4904 RegisterClass regtype, string asm,
4906 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4907 "\t$Rd, $Rn, $Rm", "", pattern>,
4912 let Inst{31-30} = 0b01;
4914 let Inst{28-24} = 0b11110;
4915 let Inst{23-22} = size;
4917 let Inst{20-16} = Rm;
4918 let Inst{15-11} = opcode;
4924 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4925 SDPatternOperator OpNode> {
4926 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4927 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4930 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
4931 SDPatternOperator OpNode> {
4932 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4933 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4934 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
4935 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4936 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
4938 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
4939 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
4940 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
4941 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
4944 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
4945 SDPatternOperator OpNode> {
4946 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
4947 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4948 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4951 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
4952 SDPatternOperator OpNode = null_frag> {
4953 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4954 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4955 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4956 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4957 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4960 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4961 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4964 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
4965 SDPatternOperator OpNode = null_frag> {
4966 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4967 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4968 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4969 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4970 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
4973 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4974 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4977 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
4978 dag oops, dag iops, string asm, string cstr, list<dag> pat>
4979 : I<oops, iops, asm,
4980 "\t$Rd, $Rn, $Rm", cstr, pat>,
4985 let Inst{31-30} = 0b01;
4987 let Inst{28-24} = 0b11110;
4988 let Inst{23-22} = size;
4990 let Inst{20-16} = Rm;
4991 let Inst{15-11} = opcode;
4997 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4998 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
4999 SDPatternOperator OpNode = null_frag> {
5000 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5002 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5003 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5005 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5006 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5009 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5010 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5011 SDPatternOperator OpNode = null_frag> {
5012 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5014 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5015 asm, "$Rd = $dst", []>;
5016 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5018 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5020 [(set (i64 FPR64:$dst),
5021 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5024 //----------------------------------------------------------------------------
5025 // AdvSIMD two register scalar instructions
5026 //----------------------------------------------------------------------------
5028 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5029 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5030 RegisterClass regtype, RegisterClass regtype2,
5031 string asm, list<dag> pat>
5032 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5033 "\t$Rd, $Rn", "", pat>,
5037 let Inst{31-30} = 0b01;
5039 let Inst{28-24} = 0b11110;
5040 let Inst{23-22} = size;
5041 let Inst{21-17} = 0b10000;
5042 let Inst{16-12} = opcode;
5043 let Inst{11-10} = 0b10;
5048 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5049 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5050 RegisterClass regtype, RegisterClass regtype2,
5051 string asm, list<dag> pat>
5052 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5053 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5057 let Inst{31-30} = 0b01;
5059 let Inst{28-24} = 0b11110;
5060 let Inst{23-22} = size;
5061 let Inst{21-17} = 0b10000;
5062 let Inst{16-12} = opcode;
5063 let Inst{11-10} = 0b10;
5069 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5070 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5071 RegisterClass regtype, string asm>
5072 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5073 "\t$Rd, $Rn, #0", "", []>,
5077 let Inst{31-30} = 0b01;
5079 let Inst{28-24} = 0b11110;
5080 let Inst{23-22} = size;
5081 let Inst{21-17} = 0b10000;
5082 let Inst{16-12} = opcode;
5083 let Inst{11-10} = 0b10;
5088 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5089 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5090 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5094 let Inst{31-17} = 0b011111100110000;
5095 let Inst{16-12} = opcode;
5096 let Inst{11-10} = 0b10;
5101 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5102 SDPatternOperator OpNode> {
5103 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5105 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5106 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5109 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5110 SDPatternOperator OpNode> {
5111 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5112 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5114 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5115 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5118 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5119 SDPatternOperator OpNode = null_frag> {
5120 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5121 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5123 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5124 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5127 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5128 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5129 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5132 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5133 SDPatternOperator OpNode> {
5134 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5135 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5136 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5137 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5140 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5141 SDPatternOperator OpNode = null_frag> {
5142 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5143 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5144 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5145 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5146 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5147 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5148 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5151 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5152 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5155 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5157 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5158 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5159 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5160 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5161 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5162 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5163 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5166 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5167 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5172 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5173 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5174 SDPatternOperator OpNode = null_frag> {
5175 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5176 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5177 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5178 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5181 //----------------------------------------------------------------------------
5182 // AdvSIMD scalar pairwise instructions
5183 //----------------------------------------------------------------------------
5185 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5186 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5187 RegisterOperand regtype, RegisterOperand vectype,
5188 string asm, string kind>
5189 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5190 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5194 let Inst{31-30} = 0b01;
5196 let Inst{28-24} = 0b11110;
5197 let Inst{23-22} = size;
5198 let Inst{21-17} = 0b11000;
5199 let Inst{16-12} = opcode;
5200 let Inst{11-10} = 0b10;
5205 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5206 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5210 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5211 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5213 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5217 //----------------------------------------------------------------------------
5218 // AdvSIMD across lanes instructions
5219 //----------------------------------------------------------------------------
5221 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5222 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5223 RegisterClass regtype, RegisterOperand vectype,
5224 string asm, string kind, list<dag> pattern>
5225 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5226 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5233 let Inst{28-24} = 0b01110;
5234 let Inst{23-22} = size;
5235 let Inst{21-17} = 0b11000;
5236 let Inst{16-12} = opcode;
5237 let Inst{11-10} = 0b10;
5242 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5244 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5246 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5248 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5250 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5252 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5256 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5257 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5259 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5261 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5263 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5265 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5269 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5271 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5273 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5276 //----------------------------------------------------------------------------
5277 // AdvSIMD INS/DUP instructions
5278 //----------------------------------------------------------------------------
5280 // FIXME: There has got to be a better way to factor these. ugh.
5282 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5283 string operands, string constraints, list<dag> pattern>
5284 : I<outs, ins, asm, operands, constraints, pattern>,
5291 let Inst{28-21} = 0b01110000;
5298 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5299 RegisterOperand vecreg, RegisterClass regtype>
5300 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5301 "{\t$Rd" # size # ", $Rn" #
5302 "|" # size # "\t$Rd, $Rn}", "",
5303 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5304 let Inst{20-16} = imm5;
5305 let Inst{14-11} = 0b0001;
5308 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5309 ValueType vectype, ValueType insreg,
5310 RegisterOperand vecreg, Operand idxtype,
5311 ValueType elttype, SDNode OpNode>
5312 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5313 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5314 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5315 [(set (vectype vecreg:$Rd),
5316 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5317 let Inst{14-11} = 0b0000;
5320 class SIMDDup64FromElement
5321 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5322 VectorIndexD, i64, ARM64duplane64> {
5325 let Inst{19-16} = 0b1000;
5328 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5329 RegisterOperand vecreg>
5330 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5331 VectorIndexS, i64, ARM64duplane32> {
5333 let Inst{20-19} = idx;
5334 let Inst{18-16} = 0b100;
5337 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5338 RegisterOperand vecreg>
5339 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5340 VectorIndexH, i64, ARM64duplane16> {
5342 let Inst{20-18} = idx;
5343 let Inst{17-16} = 0b10;
5346 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5347 RegisterOperand vecreg>
5348 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5349 VectorIndexB, i64, ARM64duplane8> {
5351 let Inst{20-17} = idx;
5355 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5356 Operand idxtype, string asm, list<dag> pattern>
5357 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5358 "{\t$Rd, $Rn" # size # "$idx" #
5359 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5360 let Inst{14-11} = imm4;
5363 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5365 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5366 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5368 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5369 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5371 class SIMDMovAlias<string asm, string size, Instruction inst,
5372 RegisterClass regtype, Operand idxtype>
5373 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5374 "|" # size # "\t$dst, $src$idx}",
5375 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5378 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5380 let Inst{20-17} = idx;
5383 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5385 let Inst{20-17} = idx;
5388 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5390 let Inst{20-18} = idx;
5391 let Inst{17-16} = 0b10;
5393 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5395 let Inst{20-18} = idx;
5396 let Inst{17-16} = 0b10;
5398 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5400 let Inst{20-19} = idx;
5401 let Inst{18-16} = 0b100;
5406 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5408 let Inst{20-17} = idx;
5411 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5413 let Inst{20-18} = idx;
5414 let Inst{17-16} = 0b10;
5416 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5418 let Inst{20-19} = idx;
5419 let Inst{18-16} = 0b100;
5421 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5424 let Inst{19-16} = 0b1000;
5426 def : SIMDMovAlias<"mov", ".s",
5427 !cast<Instruction>(NAME#"vi32"),
5428 GPR32, VectorIndexS>;
5429 def : SIMDMovAlias<"mov", ".d",
5430 !cast<Instruction>(NAME#"vi64"),
5431 GPR64, VectorIndexD>;
5434 class SIMDInsFromMain<string size, ValueType vectype,
5435 RegisterClass regtype, Operand idxtype>
5436 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5437 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5438 "{\t$Rd" # size # "$idx, $Rn" #
5439 "|" # size # "\t$Rd$idx, $Rn}",
5442 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5443 let Inst{14-11} = 0b0011;
5446 class SIMDInsFromElement<string size, ValueType vectype,
5447 ValueType elttype, Operand idxtype>
5448 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5449 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5450 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5451 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5456 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5459 class SIMDInsMainMovAlias<string size, Instruction inst,
5460 RegisterClass regtype, Operand idxtype>
5461 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5462 "|" # size #"\t$dst$idx, $src}",
5463 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5464 class SIMDInsElementMovAlias<string size, Instruction inst,
5466 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5467 # "|" # size #" $dst$idx, $src$idx2}",
5468 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5471 multiclass SIMDIns {
5472 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5474 let Inst{20-17} = idx;
5477 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5479 let Inst{20-18} = idx;
5480 let Inst{17-16} = 0b10;
5482 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5484 let Inst{20-19} = idx;
5485 let Inst{18-16} = 0b100;
5487 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5490 let Inst{19-16} = 0b1000;
5493 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5496 let Inst{20-17} = idx;
5498 let Inst{14-11} = idx2;
5500 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5503 let Inst{20-18} = idx;
5504 let Inst{17-16} = 0b10;
5505 let Inst{14-12} = idx2;
5508 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5511 let Inst{20-19} = idx;
5512 let Inst{18-16} = 0b100;
5513 let Inst{14-13} = idx2;
5514 let Inst{12-11} = 0;
5516 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5520 let Inst{19-16} = 0b1000;
5521 let Inst{14} = idx2;
5522 let Inst{13-11} = 0;
5525 // For all forms of the INS instruction, the "mov" mnemonic is the
5526 // preferred alias. Why they didn't just call the instruction "mov" in
5527 // the first place is a very good question indeed...
5528 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5529 GPR32, VectorIndexB>;
5530 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5531 GPR32, VectorIndexH>;
5532 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5533 GPR32, VectorIndexS>;
5534 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5535 GPR64, VectorIndexD>;
5537 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5539 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5541 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5543 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5547 //----------------------------------------------------------------------------
5549 //----------------------------------------------------------------------------
5551 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5552 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5553 RegisterOperand listtype, string asm, string kind>
5554 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5555 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5562 let Inst{29-21} = 0b001110000;
5563 let Inst{20-16} = Vm;
5565 let Inst{14-13} = len;
5567 let Inst{11-10} = 0b00;
5572 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5573 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5574 RegisterOperand listtype, string asm, string kind>
5575 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5576 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5583 let Inst{29-21} = 0b001110000;
5584 let Inst{20-16} = Vm;
5586 let Inst{14-13} = len;
5588 let Inst{11-10} = 0b00;
5593 class SIMDTableLookupAlias<string asm, Instruction inst,
5594 RegisterOperand vectype, RegisterOperand listtype>
5595 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5596 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5598 multiclass SIMDTableLookup<bit op, string asm> {
5599 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5601 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5603 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5605 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5607 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5609 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5611 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5613 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5616 def : SIMDTableLookupAlias<asm # ".8b",
5617 !cast<Instruction>(NAME#"v8i8One"),
5618 V64, VecListOne128>;
5619 def : SIMDTableLookupAlias<asm # ".8b",
5620 !cast<Instruction>(NAME#"v8i8Two"),
5621 V64, VecListTwo128>;
5622 def : SIMDTableLookupAlias<asm # ".8b",
5623 !cast<Instruction>(NAME#"v8i8Three"),
5624 V64, VecListThree128>;
5625 def : SIMDTableLookupAlias<asm # ".8b",
5626 !cast<Instruction>(NAME#"v8i8Four"),
5627 V64, VecListFour128>;
5628 def : SIMDTableLookupAlias<asm # ".16b",
5629 !cast<Instruction>(NAME#"v16i8One"),
5630 V128, VecListOne128>;
5631 def : SIMDTableLookupAlias<asm # ".16b",
5632 !cast<Instruction>(NAME#"v16i8Two"),
5633 V128, VecListTwo128>;
5634 def : SIMDTableLookupAlias<asm # ".16b",
5635 !cast<Instruction>(NAME#"v16i8Three"),
5636 V128, VecListThree128>;
5637 def : SIMDTableLookupAlias<asm # ".16b",
5638 !cast<Instruction>(NAME#"v16i8Four"),
5639 V128, VecListFour128>;
5642 multiclass SIMDTableLookupTied<bit op, string asm> {
5643 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5645 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5647 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5649 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5651 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5653 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5655 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5657 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5660 def : SIMDTableLookupAlias<asm # ".8b",
5661 !cast<Instruction>(NAME#"v8i8One"),
5662 V64, VecListOne128>;
5663 def : SIMDTableLookupAlias<asm # ".8b",
5664 !cast<Instruction>(NAME#"v8i8Two"),
5665 V64, VecListTwo128>;
5666 def : SIMDTableLookupAlias<asm # ".8b",
5667 !cast<Instruction>(NAME#"v8i8Three"),
5668 V64, VecListThree128>;
5669 def : SIMDTableLookupAlias<asm # ".8b",
5670 !cast<Instruction>(NAME#"v8i8Four"),
5671 V64, VecListFour128>;
5672 def : SIMDTableLookupAlias<asm # ".16b",
5673 !cast<Instruction>(NAME#"v16i8One"),
5674 V128, VecListOne128>;
5675 def : SIMDTableLookupAlias<asm # ".16b",
5676 !cast<Instruction>(NAME#"v16i8Two"),
5677 V128, VecListTwo128>;
5678 def : SIMDTableLookupAlias<asm # ".16b",
5679 !cast<Instruction>(NAME#"v16i8Three"),
5680 V128, VecListThree128>;
5681 def : SIMDTableLookupAlias<asm # ".16b",
5682 !cast<Instruction>(NAME#"v16i8Four"),
5683 V128, VecListFour128>;
5687 //----------------------------------------------------------------------------
5688 // AdvSIMD scalar CPY
5689 //----------------------------------------------------------------------------
5690 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5691 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5692 string kind, Operand idxtype>
5693 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5694 "{\t$dst, $src" # kind # "$idx" #
5695 "|\t$dst, $src$idx}", "", []>,
5699 let Inst{31-21} = 0b01011110000;
5700 let Inst{15-10} = 0b000001;
5701 let Inst{9-5} = src;
5702 let Inst{4-0} = dst;
5705 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5706 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5707 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5708 # "|\t$dst, $src$index}",
5709 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5712 multiclass SIMDScalarCPY<string asm> {
5713 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5715 let Inst{20-17} = idx;
5718 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5720 let Inst{20-18} = idx;
5721 let Inst{17-16} = 0b10;
5723 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5725 let Inst{20-19} = idx;
5726 let Inst{18-16} = 0b100;
5728 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5731 let Inst{19-16} = 0b1000;
5734 // 'DUP' mnemonic aliases.
5735 def : SIMDScalarCPYAlias<"dup", ".b",
5736 !cast<Instruction>(NAME#"i8"),
5737 FPR8, V128, VectorIndexB>;
5738 def : SIMDScalarCPYAlias<"dup", ".h",
5739 !cast<Instruction>(NAME#"i16"),
5740 FPR16, V128, VectorIndexH>;
5741 def : SIMDScalarCPYAlias<"dup", ".s",
5742 !cast<Instruction>(NAME#"i32"),
5743 FPR32, V128, VectorIndexS>;
5744 def : SIMDScalarCPYAlias<"dup", ".d",
5745 !cast<Instruction>(NAME#"i64"),
5746 FPR64, V128, VectorIndexD>;
5749 //----------------------------------------------------------------------------
5750 // AdvSIMD modified immediate instructions
5751 //----------------------------------------------------------------------------
5753 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5754 string asm, string op_string,
5755 string cstr, list<dag> pattern>
5756 : I<oops, iops, asm, op_string, cstr, pattern>,
5763 let Inst{28-19} = 0b0111100000;
5764 let Inst{18-16} = imm8{7-5};
5765 let Inst{11-10} = 0b01;
5766 let Inst{9-5} = imm8{4-0};
5770 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5771 Operand immtype, dag opt_shift_iop,
5772 string opt_shift, string asm, string kind,
5774 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5775 !con((ins immtype:$imm8), opt_shift_iop), asm,
5776 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5777 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5779 let DecoderMethod = "DecodeModImmInstruction";
5782 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5783 Operand immtype, dag opt_shift_iop,
5784 string opt_shift, string asm, string kind,
5786 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5787 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5788 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5789 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5790 "$Rd = $dst", pattern> {
5791 let DecoderMethod = "DecodeModImmTiedInstruction";
5794 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5795 RegisterOperand vectype, string asm,
5796 string kind, list<dag> pattern>
5797 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5798 (ins logical_vec_shift:$shift),
5799 "$shift", asm, kind, pattern> {
5801 let Inst{15} = b15_b12{1};
5802 let Inst{14-13} = shift;
5803 let Inst{12} = b15_b12{0};
5806 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5807 RegisterOperand vectype, string asm,
5808 string kind, list<dag> pattern>
5809 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5810 (ins logical_vec_shift:$shift),
5811 "$shift", asm, kind, pattern> {
5813 let Inst{15} = b15_b12{1};
5814 let Inst{14-13} = shift;
5815 let Inst{12} = b15_b12{0};
5819 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5820 RegisterOperand vectype, string asm,
5821 string kind, list<dag> pattern>
5822 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5823 (ins logical_vec_hw_shift:$shift),
5824 "$shift", asm, kind, pattern> {
5826 let Inst{15} = b15_b12{1};
5828 let Inst{13} = shift{0};
5829 let Inst{12} = b15_b12{0};
5832 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5833 RegisterOperand vectype, string asm,
5834 string kind, list<dag> pattern>
5835 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5836 (ins logical_vec_hw_shift:$shift),
5837 "$shift", asm, kind, pattern> {
5839 let Inst{15} = b15_b12{1};
5841 let Inst{13} = shift{0};
5842 let Inst{12} = b15_b12{0};
5845 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5847 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5849 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5852 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5854 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5858 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5859 bits<2> w_cmode, string asm,
5861 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5863 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5865 (i32 imm:$shift)))]>;
5866 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5868 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5870 (i32 imm:$shift)))]>;
5872 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5874 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5876 (i32 imm:$shift)))]>;
5877 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5879 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5881 (i32 imm:$shift)))]>;
5884 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5885 RegisterOperand vectype, string asm,
5886 string kind, list<dag> pattern>
5887 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5888 (ins move_vec_shift:$shift),
5889 "$shift", asm, kind, pattern> {
5891 let Inst{15-13} = cmode{3-1};
5892 let Inst{12} = shift;
5895 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5896 RegisterOperand vectype,
5897 Operand imm_type, string asm,
5898 string kind, list<dag> pattern>
5899 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5900 asm, kind, pattern> {
5901 let Inst{15-12} = cmode;
5904 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5906 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5907 "\t$Rd, $imm8", "", pattern> {
5908 let Inst{15-12} = cmode;
5909 let DecoderMethod = "DecodeModImmInstruction";
5912 //----------------------------------------------------------------------------
5913 // AdvSIMD indexed element
5914 //----------------------------------------------------------------------------
5916 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5917 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5918 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5919 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5920 string apple_kind, string dst_kind, string lhs_kind,
5921 string rhs_kind, list<dag> pattern>
5922 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5924 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5925 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5934 let Inst{28} = Scalar;
5935 let Inst{27-24} = 0b1111;
5936 let Inst{23-22} = size;
5937 // Bit 21 must be set by the derived class.
5938 let Inst{20-16} = Rm;
5939 let Inst{15-12} = opc;
5940 // Bit 11 must be set by the derived class.
5946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5947 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5948 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5949 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5950 string apple_kind, string dst_kind, string lhs_kind,
5951 string rhs_kind, list<dag> pattern>
5952 : I<(outs dst_reg:$dst),
5953 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5954 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5955 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5964 let Inst{28} = Scalar;
5965 let Inst{27-24} = 0b1111;
5966 let Inst{23-22} = size;
5967 // Bit 21 must be set by the derived class.
5968 let Inst{20-16} = Rm;
5969 let Inst{15-12} = opc;
5970 // Bit 11 must be set by the derived class.
5976 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
5977 SDPatternOperator OpNode> {
5978 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
5981 asm, ".2s", ".2s", ".2s", ".s",
5982 [(set (v2f32 V64:$Rd),
5983 (OpNode (v2f32 V64:$Rn),
5984 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5986 let Inst{11} = idx{1};
5987 let Inst{21} = idx{0};
5990 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
5993 asm, ".4s", ".4s", ".4s", ".s",
5994 [(set (v4f32 V128:$Rd),
5995 (OpNode (v4f32 V128:$Rn),
5996 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5998 let Inst{11} = idx{1};
5999 let Inst{21} = idx{0};
6002 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6005 asm, ".2d", ".2d", ".2d", ".d",
6006 [(set (v2f64 V128:$Rd),
6007 (OpNode (v2f64 V128:$Rn),
6008 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6010 let Inst{11} = idx{0};
6014 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6015 FPR32Op, FPR32Op, V128, VectorIndexS,
6016 asm, ".s", "", "", ".s",
6017 [(set (f32 FPR32Op:$Rd),
6018 (OpNode (f32 FPR32Op:$Rn),
6019 (f32 (vector_extract (v4f32 V128:$Rm),
6020 VectorIndexS:$idx))))]> {
6022 let Inst{11} = idx{1};
6023 let Inst{21} = idx{0};
6026 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6027 FPR64Op, FPR64Op, V128, VectorIndexD,
6028 asm, ".d", "", "", ".d",
6029 [(set (f64 FPR64Op:$Rd),
6030 (OpNode (f64 FPR64Op:$Rn),
6031 (f64 (vector_extract (v2f64 V128:$Rm),
6032 VectorIndexD:$idx))))]> {
6034 let Inst{11} = idx{0};
6039 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6040 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6041 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6042 (ARM64duplane32 (v4f32 V128:$Rm),
6043 VectorIndexS:$idx))),
6044 (!cast<Instruction>(INST # v2i32_indexed)
6045 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6046 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6047 (ARM64dup (f32 FPR32Op:$Rm)))),
6048 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6049 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6052 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6053 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6054 (ARM64duplane32 (v4f32 V128:$Rm),
6055 VectorIndexS:$idx))),
6056 (!cast<Instruction>(INST # "v4i32_indexed")
6057 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6058 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6059 (ARM64dup (f32 FPR32Op:$Rm)))),
6060 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6061 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6063 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6064 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6065 (ARM64duplane64 (v2f64 V128:$Rm),
6066 VectorIndexD:$idx))),
6067 (!cast<Instruction>(INST # "v2i64_indexed")
6068 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6069 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6070 (ARM64dup (f64 FPR64Op:$Rm)))),
6071 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6072 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6074 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6075 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6076 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6077 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6078 V128:$Rm, VectorIndexS:$idx)>;
6079 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6080 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6081 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6082 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6084 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6085 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6086 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6087 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6088 V128:$Rm, VectorIndexD:$idx)>;
6091 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6092 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6094 asm, ".2s", ".2s", ".2s", ".s", []> {
6096 let Inst{11} = idx{1};
6097 let Inst{21} = idx{0};
6100 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6103 asm, ".4s", ".4s", ".4s", ".s", []> {
6105 let Inst{11} = idx{1};
6106 let Inst{21} = idx{0};
6109 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6112 asm, ".2d", ".2d", ".2d", ".d", []> {
6114 let Inst{11} = idx{0};
6119 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6120 FPR32Op, FPR32Op, V128, VectorIndexS,
6121 asm, ".s", "", "", ".s", []> {
6123 let Inst{11} = idx{1};
6124 let Inst{21} = idx{0};
6127 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6128 FPR64Op, FPR64Op, V128, VectorIndexD,
6129 asm, ".d", "", "", ".d", []> {
6131 let Inst{11} = idx{0};
6136 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6137 SDPatternOperator OpNode> {
6138 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6139 V128_lo, VectorIndexH,
6140 asm, ".4h", ".4h", ".4h", ".h",
6141 [(set (v4i16 V64:$Rd),
6142 (OpNode (v4i16 V64:$Rn),
6143 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6145 let Inst{11} = idx{2};
6146 let Inst{21} = idx{1};
6147 let Inst{20} = idx{0};
6150 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6152 V128_lo, VectorIndexH,
6153 asm, ".8h", ".8h", ".8h", ".h",
6154 [(set (v8i16 V128:$Rd),
6155 (OpNode (v8i16 V128:$Rn),
6156 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6158 let Inst{11} = idx{2};
6159 let Inst{21} = idx{1};
6160 let Inst{20} = idx{0};
6163 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6166 asm, ".2s", ".2s", ".2s", ".s",
6167 [(set (v2i32 V64:$Rd),
6168 (OpNode (v2i32 V64:$Rn),
6169 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6171 let Inst{11} = idx{1};
6172 let Inst{21} = idx{0};
6175 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6178 asm, ".4s", ".4s", ".4s", ".s",
6179 [(set (v4i32 V128:$Rd),
6180 (OpNode (v4i32 V128:$Rn),
6181 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6183 let Inst{11} = idx{1};
6184 let Inst{21} = idx{0};
6187 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6188 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6189 asm, ".h", "", "", ".h", []> {
6191 let Inst{11} = idx{2};
6192 let Inst{21} = idx{1};
6193 let Inst{20} = idx{0};
6196 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6197 FPR32Op, FPR32Op, V128, VectorIndexS,
6198 asm, ".s", "", "", ".s",
6199 [(set (i32 FPR32Op:$Rd),
6200 (OpNode FPR32Op:$Rn,
6201 (i32 (vector_extract (v4i32 V128:$Rm),
6202 VectorIndexS:$idx))))]> {
6204 let Inst{11} = idx{1};
6205 let Inst{21} = idx{0};
6209 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6210 SDPatternOperator OpNode> {
6211 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6213 V128_lo, VectorIndexH,
6214 asm, ".4h", ".4h", ".4h", ".h",
6215 [(set (v4i16 V64:$Rd),
6216 (OpNode (v4i16 V64:$Rn),
6217 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6219 let Inst{11} = idx{2};
6220 let Inst{21} = idx{1};
6221 let Inst{20} = idx{0};
6224 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6226 V128_lo, VectorIndexH,
6227 asm, ".8h", ".8h", ".8h", ".h",
6228 [(set (v8i16 V128:$Rd),
6229 (OpNode (v8i16 V128:$Rn),
6230 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6232 let Inst{11} = idx{2};
6233 let Inst{21} = idx{1};
6234 let Inst{20} = idx{0};
6237 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6240 asm, ".2s", ".2s", ".2s", ".s",
6241 [(set (v2i32 V64:$Rd),
6242 (OpNode (v2i32 V64:$Rn),
6243 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6245 let Inst{11} = idx{1};
6246 let Inst{21} = idx{0};
6249 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6252 asm, ".4s", ".4s", ".4s", ".s",
6253 [(set (v4i32 V128:$Rd),
6254 (OpNode (v4i32 V128:$Rn),
6255 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6257 let Inst{11} = idx{1};
6258 let Inst{21} = idx{0};
6262 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6263 SDPatternOperator OpNode> {
6264 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6265 V128_lo, VectorIndexH,
6266 asm, ".4h", ".4h", ".4h", ".h",
6267 [(set (v4i16 V64:$dst),
6268 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6269 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6271 let Inst{11} = idx{2};
6272 let Inst{21} = idx{1};
6273 let Inst{20} = idx{0};
6276 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6278 V128_lo, VectorIndexH,
6279 asm, ".8h", ".8h", ".8h", ".h",
6280 [(set (v8i16 V128:$dst),
6281 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6282 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6284 let Inst{11} = idx{2};
6285 let Inst{21} = idx{1};
6286 let Inst{20} = idx{0};
6289 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6292 asm, ".2s", ".2s", ".2s", ".s",
6293 [(set (v2i32 V64:$dst),
6294 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6295 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6297 let Inst{11} = idx{1};
6298 let Inst{21} = idx{0};
6301 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6304 asm, ".4s", ".4s", ".4s", ".s",
6305 [(set (v4i32 V128:$dst),
6306 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6307 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6309 let Inst{11} = idx{1};
6310 let Inst{21} = idx{0};
6314 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6315 SDPatternOperator OpNode> {
6316 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6318 V128_lo, VectorIndexH,
6319 asm, ".4s", ".4s", ".4h", ".h",
6320 [(set (v4i32 V128:$Rd),
6321 (OpNode (v4i16 V64:$Rn),
6322 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6324 let Inst{11} = idx{2};
6325 let Inst{21} = idx{1};
6326 let Inst{20} = idx{0};
6329 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6331 V128_lo, VectorIndexH,
6332 asm#"2", ".4s", ".4s", ".8h", ".h",
6333 [(set (v4i32 V128:$Rd),
6334 (OpNode (extract_high_v8i16 V128:$Rn),
6335 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6336 VectorIndexH:$idx))))]> {
6339 let Inst{11} = idx{2};
6340 let Inst{21} = idx{1};
6341 let Inst{20} = idx{0};
6344 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6347 asm, ".2d", ".2d", ".2s", ".s",
6348 [(set (v2i64 V128:$Rd),
6349 (OpNode (v2i32 V64:$Rn),
6350 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6352 let Inst{11} = idx{1};
6353 let Inst{21} = idx{0};
6356 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6359 asm#"2", ".2d", ".2d", ".4s", ".s",
6360 [(set (v2i64 V128:$Rd),
6361 (OpNode (extract_high_v4i32 V128:$Rn),
6362 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6363 VectorIndexS:$idx))))]> {
6365 let Inst{11} = idx{1};
6366 let Inst{21} = idx{0};
6369 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6370 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6371 asm, ".h", "", "", ".h", []> {
6373 let Inst{11} = idx{2};
6374 let Inst{21} = idx{1};
6375 let Inst{20} = idx{0};
6378 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6379 FPR64Op, FPR32Op, V128, VectorIndexS,
6380 asm, ".s", "", "", ".s", []> {
6382 let Inst{11} = idx{1};
6383 let Inst{21} = idx{0};
6387 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6388 SDPatternOperator Accum> {
6389 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6391 V128_lo, VectorIndexH,
6392 asm, ".4s", ".4s", ".4h", ".h",
6393 [(set (v4i32 V128:$dst),
6394 (Accum (v4i32 V128:$Rd),
6395 (v4i32 (int_arm64_neon_sqdmull
6397 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6398 VectorIndexH:$idx))))))]> {
6400 let Inst{11} = idx{2};
6401 let Inst{21} = idx{1};
6402 let Inst{20} = idx{0};
6405 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6406 // intermediate EXTRACT_SUBREG would be untyped.
6407 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6408 (i32 (vector_extract (v4i32
6409 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6410 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6411 VectorIndexH:$idx)))),
6414 (!cast<Instruction>(NAME # v4i16_indexed)
6415 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6416 V128_lo:$Rm, VectorIndexH:$idx),
6419 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6421 V128_lo, VectorIndexH,
6422 asm#"2", ".4s", ".4s", ".8h", ".h",
6423 [(set (v4i32 V128:$dst),
6424 (Accum (v4i32 V128:$Rd),
6425 (v4i32 (int_arm64_neon_sqdmull
6426 (extract_high_v8i16 V128:$Rn),
6428 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6429 VectorIndexH:$idx))))))]> {
6431 let Inst{11} = idx{2};
6432 let Inst{21} = idx{1};
6433 let Inst{20} = idx{0};
6436 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6439 asm, ".2d", ".2d", ".2s", ".s",
6440 [(set (v2i64 V128:$dst),
6441 (Accum (v2i64 V128:$Rd),
6442 (v2i64 (int_arm64_neon_sqdmull
6444 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6445 VectorIndexS:$idx))))))]> {
6447 let Inst{11} = idx{1};
6448 let Inst{21} = idx{0};
6451 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6454 asm#"2", ".2d", ".2d", ".4s", ".s",
6455 [(set (v2i64 V128:$dst),
6456 (Accum (v2i64 V128:$Rd),
6457 (v2i64 (int_arm64_neon_sqdmull
6458 (extract_high_v4i32 V128:$Rn),
6460 (ARM64duplane32 (v4i32 V128:$Rm),
6461 VectorIndexS:$idx))))))]> {
6463 let Inst{11} = idx{1};
6464 let Inst{21} = idx{0};
6467 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6468 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6469 asm, ".h", "", "", ".h", []> {
6471 let Inst{11} = idx{2};
6472 let Inst{21} = idx{1};
6473 let Inst{20} = idx{0};
6477 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6478 FPR64Op, FPR32Op, V128, VectorIndexS,
6479 asm, ".s", "", "", ".s",
6480 [(set (i64 FPR64Op:$dst),
6481 (Accum (i64 FPR64Op:$Rd),
6482 (i64 (int_arm64_neon_sqdmulls_scalar
6484 (i32 (vector_extract (v4i32 V128:$Rm),
6485 VectorIndexS:$idx))))))]> {
6488 let Inst{11} = idx{1};
6489 let Inst{21} = idx{0};
6493 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6494 SDPatternOperator OpNode> {
6495 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6496 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6498 V128_lo, VectorIndexH,
6499 asm, ".4s", ".4s", ".4h", ".h",
6500 [(set (v4i32 V128:$Rd),
6501 (OpNode (v4i16 V64:$Rn),
6502 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6504 let Inst{11} = idx{2};
6505 let Inst{21} = idx{1};
6506 let Inst{20} = idx{0};
6509 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6511 V128_lo, VectorIndexH,
6512 asm#"2", ".4s", ".4s", ".8h", ".h",
6513 [(set (v4i32 V128:$Rd),
6514 (OpNode (extract_high_v8i16 V128:$Rn),
6515 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6516 VectorIndexH:$idx))))]> {
6519 let Inst{11} = idx{2};
6520 let Inst{21} = idx{1};
6521 let Inst{20} = idx{0};
6524 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6527 asm, ".2d", ".2d", ".2s", ".s",
6528 [(set (v2i64 V128:$Rd),
6529 (OpNode (v2i32 V64:$Rn),
6530 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6532 let Inst{11} = idx{1};
6533 let Inst{21} = idx{0};
6536 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6539 asm#"2", ".2d", ".2d", ".4s", ".s",
6540 [(set (v2i64 V128:$Rd),
6541 (OpNode (extract_high_v4i32 V128:$Rn),
6542 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6543 VectorIndexS:$idx))))]> {
6545 let Inst{11} = idx{1};
6546 let Inst{21} = idx{0};
6551 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6552 SDPatternOperator OpNode> {
6553 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6554 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6556 V128_lo, VectorIndexH,
6557 asm, ".4s", ".4s", ".4h", ".h",
6558 [(set (v4i32 V128:$dst),
6559 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6560 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6562 let Inst{11} = idx{2};
6563 let Inst{21} = idx{1};
6564 let Inst{20} = idx{0};
6567 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6569 V128_lo, VectorIndexH,
6570 asm#"2", ".4s", ".4s", ".8h", ".h",
6571 [(set (v4i32 V128:$dst),
6572 (OpNode (v4i32 V128:$Rd),
6573 (extract_high_v8i16 V128:$Rn),
6574 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6575 VectorIndexH:$idx))))]> {
6577 let Inst{11} = idx{2};
6578 let Inst{21} = idx{1};
6579 let Inst{20} = idx{0};
6582 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6585 asm, ".2d", ".2d", ".2s", ".s",
6586 [(set (v2i64 V128:$dst),
6587 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6588 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6590 let Inst{11} = idx{1};
6591 let Inst{21} = idx{0};
6594 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6597 asm#"2", ".2d", ".2d", ".4s", ".s",
6598 [(set (v2i64 V128:$dst),
6599 (OpNode (v2i64 V128:$Rd),
6600 (extract_high_v4i32 V128:$Rn),
6601 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6602 VectorIndexS:$idx))))]> {
6604 let Inst{11} = idx{1};
6605 let Inst{21} = idx{0};
6610 //----------------------------------------------------------------------------
6611 // AdvSIMD scalar shift by immediate
6612 //----------------------------------------------------------------------------
6614 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6615 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6616 RegisterClass regtype1, RegisterClass regtype2,
6617 Operand immtype, string asm, list<dag> pattern>
6618 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6619 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6624 let Inst{31-30} = 0b01;
6626 let Inst{28-23} = 0b111110;
6627 let Inst{22-16} = fixed_imm;
6628 let Inst{15-11} = opc;
6634 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6635 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6636 RegisterClass regtype1, RegisterClass regtype2,
6637 Operand immtype, string asm, list<dag> pattern>
6638 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6639 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6644 let Inst{31-30} = 0b01;
6646 let Inst{28-23} = 0b111110;
6647 let Inst{22-16} = fixed_imm;
6648 let Inst{15-11} = opc;
6655 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6656 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6657 FPR32, FPR32, vecshiftR32, asm, []> {
6658 let Inst{20-16} = imm{4-0};
6661 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6662 FPR64, FPR64, vecshiftR64, asm, []> {
6663 let Inst{21-16} = imm{5-0};
6667 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6668 SDPatternOperator OpNode> {
6669 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6670 FPR64, FPR64, vecshiftR64, asm,
6671 [(set (i64 FPR64:$Rd),
6672 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6673 let Inst{21-16} = imm{5-0};
6676 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6677 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
6680 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6681 SDPatternOperator OpNode = null_frag> {
6682 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6683 FPR64, FPR64, vecshiftR64, asm,
6684 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6685 (i32 vecshiftR64:$imm)))]> {
6686 let Inst{21-16} = imm{5-0};
6689 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6690 (i32 vecshiftR64:$imm))),
6691 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6695 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6696 SDPatternOperator OpNode> {
6697 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6698 FPR64, FPR64, vecshiftL64, asm,
6699 [(set (v1i64 FPR64:$Rd),
6700 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6701 let Inst{21-16} = imm{5-0};
6705 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6706 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6707 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6708 FPR64, FPR64, vecshiftL64, asm, []> {
6709 let Inst{21-16} = imm{5-0};
6713 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6714 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6715 SDPatternOperator OpNode = null_frag> {
6716 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6717 FPR8, FPR16, vecshiftR8, asm, []> {
6718 let Inst{18-16} = imm{2-0};
6721 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6722 FPR16, FPR32, vecshiftR16, asm, []> {
6723 let Inst{19-16} = imm{3-0};
6726 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6727 FPR32, FPR64, vecshiftR32, asm,
6728 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6729 let Inst{20-16} = imm{4-0};
6733 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6734 SDPatternOperator OpNode> {
6735 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6736 FPR8, FPR8, vecshiftL8, asm, []> {
6737 let Inst{18-16} = imm{2-0};
6740 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6741 FPR16, FPR16, vecshiftL16, asm, []> {
6742 let Inst{19-16} = imm{3-0};
6745 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6746 FPR32, FPR32, vecshiftL32, asm,
6747 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6748 let Inst{20-16} = imm{4-0};
6751 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6752 FPR64, FPR64, vecshiftL64, asm,
6753 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6754 (i32 vecshiftL64:$imm)))]> {
6755 let Inst{21-16} = imm{5-0};
6759 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6760 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6761 FPR8, FPR8, vecshiftR8, asm, []> {
6762 let Inst{18-16} = imm{2-0};
6765 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6766 FPR16, FPR16, vecshiftR16, asm, []> {
6767 let Inst{19-16} = imm{3-0};
6770 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6771 FPR32, FPR32, vecshiftR32, asm, []> {
6772 let Inst{20-16} = imm{4-0};
6775 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6776 FPR64, FPR64, vecshiftR64, asm, []> {
6777 let Inst{21-16} = imm{5-0};
6781 //----------------------------------------------------------------------------
6782 // AdvSIMD vector x indexed element
6783 //----------------------------------------------------------------------------
6785 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6786 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6787 RegisterOperand dst_reg, RegisterOperand src_reg,
6789 string asm, string dst_kind, string src_kind,
6791 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6792 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6793 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6800 let Inst{28-23} = 0b011110;
6801 let Inst{22-16} = fixed_imm;
6802 let Inst{15-11} = opc;
6808 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6809 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6810 RegisterOperand vectype1, RegisterOperand vectype2,
6812 string asm, string dst_kind, string src_kind,
6814 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6815 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6816 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6823 let Inst{28-23} = 0b011110;
6824 let Inst{22-16} = fixed_imm;
6825 let Inst{15-11} = opc;
6831 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6833 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6834 V64, V64, vecshiftR32,
6836 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6838 let Inst{20-16} = imm;
6841 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6842 V128, V128, vecshiftR32,
6844 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6846 let Inst{20-16} = imm;
6849 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6850 V128, V128, vecshiftR64,
6852 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6854 let Inst{21-16} = imm;
6858 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6860 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6861 V64, V64, vecshiftR32,
6863 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6865 let Inst{20-16} = imm;
6868 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6869 V128, V128, vecshiftR32,
6871 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6873 let Inst{20-16} = imm;
6876 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6877 V128, V128, vecshiftR64,
6879 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6881 let Inst{21-16} = imm;
6885 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6886 SDPatternOperator OpNode> {
6887 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6888 V64, V128, vecshiftR16Narrow,
6890 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6892 let Inst{18-16} = imm;
6895 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6896 V128, V128, vecshiftR16Narrow,
6897 asm#"2", ".16b", ".8h", []> {
6899 let Inst{18-16} = imm;
6900 let hasSideEffects = 0;
6903 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6904 V64, V128, vecshiftR32Narrow,
6906 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6908 let Inst{19-16} = imm;
6911 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6912 V128, V128, vecshiftR32Narrow,
6913 asm#"2", ".8h", ".4s", []> {
6915 let Inst{19-16} = imm;
6916 let hasSideEffects = 0;
6919 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6920 V64, V128, vecshiftR64Narrow,
6922 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6924 let Inst{20-16} = imm;
6927 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6928 V128, V128, vecshiftR64Narrow,
6929 asm#"2", ".4s", ".2d", []> {
6931 let Inst{20-16} = imm;
6932 let hasSideEffects = 0;
6935 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6936 // themselves, so put them here instead.
6938 // Patterns involving what's effectively an insert high and a normal
6939 // intrinsic, represented by CONCAT_VECTORS.
6940 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6941 vecshiftR16Narrow:$imm)),
6942 (!cast<Instruction>(NAME # "v16i8_shift")
6943 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6944 V128:$Rn, vecshiftR16Narrow:$imm)>;
6945 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6946 vecshiftR32Narrow:$imm)),
6947 (!cast<Instruction>(NAME # "v8i16_shift")
6948 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6949 V128:$Rn, vecshiftR32Narrow:$imm)>;
6950 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6951 vecshiftR64Narrow:$imm)),
6952 (!cast<Instruction>(NAME # "v4i32_shift")
6953 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6954 V128:$Rn, vecshiftR64Narrow:$imm)>;
6957 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
6958 SDPatternOperator OpNode> {
6959 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6960 V64, V64, vecshiftL8,
6962 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6963 (i32 vecshiftL8:$imm)))]> {
6965 let Inst{18-16} = imm;
6968 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
6969 V128, V128, vecshiftL8,
6970 asm, ".16b", ".16b",
6971 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
6972 (i32 vecshiftL8:$imm)))]> {
6974 let Inst{18-16} = imm;
6977 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6978 V64, V64, vecshiftL16,
6980 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
6981 (i32 vecshiftL16:$imm)))]> {
6983 let Inst{19-16} = imm;
6986 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
6987 V128, V128, vecshiftL16,
6989 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6990 (i32 vecshiftL16:$imm)))]> {
6992 let Inst{19-16} = imm;
6995 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6996 V64, V64, vecshiftL32,
6998 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
6999 (i32 vecshiftL32:$imm)))]> {
7001 let Inst{20-16} = imm;
7004 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7005 V128, V128, vecshiftL32,
7007 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7008 (i32 vecshiftL32:$imm)))]> {
7010 let Inst{20-16} = imm;
7013 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7014 V128, V128, vecshiftL64,
7016 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7017 (i32 vecshiftL64:$imm)))]> {
7019 let Inst{21-16} = imm;
7023 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7024 SDPatternOperator OpNode> {
7025 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7026 V64, V64, vecshiftR8,
7028 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7029 (i32 vecshiftR8:$imm)))]> {
7031 let Inst{18-16} = imm;
7034 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7035 V128, V128, vecshiftR8,
7036 asm, ".16b", ".16b",
7037 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7038 (i32 vecshiftR8:$imm)))]> {
7040 let Inst{18-16} = imm;
7043 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7044 V64, V64, vecshiftR16,
7046 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7047 (i32 vecshiftR16:$imm)))]> {
7049 let Inst{19-16} = imm;
7052 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7053 V128, V128, vecshiftR16,
7055 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7056 (i32 vecshiftR16:$imm)))]> {
7058 let Inst{19-16} = imm;
7061 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7062 V64, V64, vecshiftR32,
7064 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7065 (i32 vecshiftR32:$imm)))]> {
7067 let Inst{20-16} = imm;
7070 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7071 V128, V128, vecshiftR32,
7073 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7074 (i32 vecshiftR32:$imm)))]> {
7076 let Inst{20-16} = imm;
7079 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7080 V128, V128, vecshiftR64,
7082 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7083 (i32 vecshiftR64:$imm)))]> {
7085 let Inst{21-16} = imm;
7089 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7090 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7091 SDPatternOperator OpNode = null_frag> {
7092 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7093 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7094 [(set (v8i8 V64:$dst),
7095 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7096 (i32 vecshiftR8:$imm)))]> {
7098 let Inst{18-16} = imm;
7101 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7102 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7103 [(set (v16i8 V128:$dst),
7104 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7105 (i32 vecshiftR8:$imm)))]> {
7107 let Inst{18-16} = imm;
7110 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7111 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7112 [(set (v4i16 V64:$dst),
7113 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7114 (i32 vecshiftR16:$imm)))]> {
7116 let Inst{19-16} = imm;
7119 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7120 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7121 [(set (v8i16 V128:$dst),
7122 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7123 (i32 vecshiftR16:$imm)))]> {
7125 let Inst{19-16} = imm;
7128 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7129 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7130 [(set (v2i32 V64:$dst),
7131 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7132 (i32 vecshiftR32:$imm)))]> {
7134 let Inst{20-16} = imm;
7137 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7138 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7139 [(set (v4i32 V128:$dst),
7140 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7141 (i32 vecshiftR32:$imm)))]> {
7143 let Inst{20-16} = imm;
7146 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7147 V128, V128, vecshiftR64,
7148 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7149 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7150 (i32 vecshiftR64:$imm)))]> {
7152 let Inst{21-16} = imm;
7156 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7157 SDPatternOperator OpNode = null_frag> {
7158 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7159 V64, V64, vecshiftL8,
7161 [(set (v8i8 V64:$dst),
7162 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7163 (i32 vecshiftL8:$imm)))]> {
7165 let Inst{18-16} = imm;
7168 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7169 V128, V128, vecshiftL8,
7170 asm, ".16b", ".16b",
7171 [(set (v16i8 V128:$dst),
7172 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7173 (i32 vecshiftL8:$imm)))]> {
7175 let Inst{18-16} = imm;
7178 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7179 V64, V64, vecshiftL16,
7181 [(set (v4i16 V64:$dst),
7182 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7183 (i32 vecshiftL16:$imm)))]> {
7185 let Inst{19-16} = imm;
7188 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7189 V128, V128, vecshiftL16,
7191 [(set (v8i16 V128:$dst),
7192 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7193 (i32 vecshiftL16:$imm)))]> {
7195 let Inst{19-16} = imm;
7198 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7199 V64, V64, vecshiftL32,
7201 [(set (v2i32 V64:$dst),
7202 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7203 (i32 vecshiftL32:$imm)))]> {
7205 let Inst{20-16} = imm;
7208 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7209 V128, V128, vecshiftL32,
7211 [(set (v4i32 V128:$dst),
7212 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7213 (i32 vecshiftL32:$imm)))]> {
7215 let Inst{20-16} = imm;
7218 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7219 V128, V128, vecshiftL64,
7221 [(set (v2i64 V128:$dst),
7222 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7223 (i32 vecshiftL64:$imm)))]> {
7225 let Inst{21-16} = imm;
7229 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7230 SDPatternOperator OpNode> {
7231 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7232 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7233 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7235 let Inst{18-16} = imm;
7238 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7239 V128, V128, vecshiftL8,
7240 asm#"2", ".8h", ".16b",
7241 [(set (v8i16 V128:$Rd),
7242 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7244 let Inst{18-16} = imm;
7247 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7248 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7249 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7251 let Inst{19-16} = imm;
7254 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7255 V128, V128, vecshiftL16,
7256 asm#"2", ".4s", ".8h",
7257 [(set (v4i32 V128:$Rd),
7258 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7261 let Inst{19-16} = imm;
7264 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7265 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7266 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7268 let Inst{20-16} = imm;
7271 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7272 V128, V128, vecshiftL32,
7273 asm#"2", ".2d", ".4s",
7274 [(set (v2i64 V128:$Rd),
7275 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7277 let Inst{20-16} = imm;
7283 // Vector load/store
7285 // SIMD ldX/stX no-index memory references don't allow the optional
7286 // ", #0" constant and handle post-indexing explicitly, so we use
7287 // a more specialized parse method for them. Otherwise, it's the same as
7288 // the general am_noindex handling.
7289 def MemorySIMDNoIndexOperand : AsmOperandClass {
7290 let Name = "MemorySIMDNoIndex";
7291 let ParserMethod = "tryParseNoIndexMemory";
7293 def am_simdnoindex : Operand<i64>,
7294 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7295 let PrintMethod = "printAMNoIndex";
7296 let ParserMatchClass = MemorySIMDNoIndexOperand;
7297 let MIOperandInfo = (ops GPR64sp:$base);
7298 let DecoderMethod = "DecodeGPR64spRegisterClass";
7301 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7302 string asm, dag oops, dag iops, list<dag> pattern>
7303 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7308 let Inst{29-23} = 0b0011000;
7310 let Inst{21-16} = 0b000000;
7311 let Inst{15-12} = opcode;
7312 let Inst{11-10} = size;
7313 let Inst{9-5} = vaddr;
7317 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7318 string asm, dag oops, dag iops>
7319 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7325 let Inst{29-23} = 0b0011001;
7328 let Inst{20-16} = Xm;
7329 let Inst{15-12} = opcode;
7330 let Inst{11-10} = size;
7331 let Inst{9-5} = vaddr;
7333 let DecoderMethod = "DecodeSIMDLdStPost";
7336 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7337 // register post-index addressing from the zero register.
7338 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7339 int Offset, int Size> {
7340 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7341 // "ld1\t$Vt, $vaddr, #16"
7342 // may get mapped to
7343 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7344 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7345 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7346 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7347 am_simdnoindex:$vaddr, XZR), 1>;
7349 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7350 // "ld1.8b\t$Vt, $vaddr, #16"
7351 // may get mapped to
7352 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7353 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7354 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7355 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7356 am_simdnoindex:$vaddr, XZR), 0>;
7358 // E.g. "ld1.8b { v0, v1 }, [x1]"
7359 // "ld1\t$Vt, $vaddr"
7360 // may get mapped to
7361 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7362 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7363 (!cast<Instruction>(NAME # Count # "v" # layout)
7364 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7365 am_simdnoindex:$vaddr), 0>;
7367 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7368 // "ld1\t$Vt, $vaddr, $Xm"
7369 // may get mapped to
7370 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7371 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7372 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7373 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7374 am_simdnoindex:$vaddr,
7375 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7378 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7379 int Offset64, bits<4> opcode> {
7380 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7381 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7382 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7383 (ins am_simdnoindex:$vaddr), []>;
7384 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7385 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7386 (ins am_simdnoindex:$vaddr), []>;
7387 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7388 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7389 (ins am_simdnoindex:$vaddr), []>;
7390 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7391 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7392 (ins am_simdnoindex:$vaddr), []>;
7393 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7394 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7395 (ins am_simdnoindex:$vaddr), []>;
7396 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7397 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7398 (ins am_simdnoindex:$vaddr), []>;
7399 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7400 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7401 (ins am_simdnoindex:$vaddr), []>;
7404 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7405 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7406 (ins am_simdnoindex:$vaddr,
7407 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7408 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7409 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7410 (ins am_simdnoindex:$vaddr,
7411 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7412 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7413 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7414 (ins am_simdnoindex:$vaddr,
7415 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7416 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7417 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7418 (ins am_simdnoindex:$vaddr,
7419 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7420 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7421 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7422 (ins am_simdnoindex:$vaddr,
7423 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7424 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7425 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7426 (ins am_simdnoindex:$vaddr,
7427 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7428 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7429 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7430 (ins am_simdnoindex:$vaddr,
7431 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7434 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7435 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7436 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7437 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7438 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7439 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7440 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7443 // Only ld1/st1 has a v1d version.
7444 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7445 int Offset64, bits<4> opcode> {
7446 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7447 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7448 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7449 am_simdnoindex:$vaddr), []>;
7450 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7451 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7452 am_simdnoindex:$vaddr), []>;
7453 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7454 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7455 am_simdnoindex:$vaddr), []>;
7456 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7457 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7458 am_simdnoindex:$vaddr), []>;
7459 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7460 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7461 am_simdnoindex:$vaddr), []>;
7462 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7463 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7464 am_simdnoindex:$vaddr), []>;
7465 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7466 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7467 am_simdnoindex:$vaddr), []>;
7469 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7470 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7471 am_simdnoindex:$vaddr,
7472 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7473 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7474 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7475 am_simdnoindex:$vaddr,
7476 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7477 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7478 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7479 am_simdnoindex:$vaddr,
7480 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7481 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7482 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7483 am_simdnoindex:$vaddr,
7484 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7485 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7486 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7487 am_simdnoindex:$vaddr,
7488 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7489 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7490 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7491 am_simdnoindex:$vaddr,
7492 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7493 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7494 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7495 am_simdnoindex:$vaddr,
7496 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7499 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7500 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7501 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7502 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7503 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7504 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7505 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7508 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7509 int Offset128, int Offset64, bits<4> opcode>
7510 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7512 // LD1 instructions have extra "1d" variants.
7513 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7514 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7515 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7516 (ins am_simdnoindex:$vaddr), []>;
7518 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7519 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7520 (ins am_simdnoindex:$vaddr,
7521 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7524 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7527 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7528 int Offset128, int Offset64, bits<4> opcode>
7529 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7531 // ST1 instructions have extra "1d" variants.
7532 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7533 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7534 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7535 am_simdnoindex:$vaddr), []>;
7537 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7538 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7539 am_simdnoindex:$vaddr,
7540 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7543 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7546 multiclass SIMDLd1Multiple<string asm> {
7547 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7548 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7549 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7550 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7553 multiclass SIMDSt1Multiple<string asm> {
7554 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7555 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7556 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7557 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7560 multiclass SIMDLd2Multiple<string asm> {
7561 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7564 multiclass SIMDSt2Multiple<string asm> {
7565 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7568 multiclass SIMDLd3Multiple<string asm> {
7569 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7572 multiclass SIMDSt3Multiple<string asm> {
7573 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7576 multiclass SIMDLd4Multiple<string asm> {
7577 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7580 multiclass SIMDSt4Multiple<string asm> {
7581 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7585 // AdvSIMD Load/store single-element
7588 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7589 string asm, string operands, dag oops, dag iops,
7591 : I<oops, iops, asm, operands, "", pattern> {
7595 let Inst{29-24} = 0b001101;
7598 let Inst{15-13} = opcode;
7599 let Inst{9-5} = vaddr;
7601 let DecoderMethod = "DecodeSIMDLdStSingle";
7604 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7605 string asm, string operands, dag oops, dag iops,
7607 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7611 let Inst{29-24} = 0b001101;
7614 let Inst{15-13} = opcode;
7615 let Inst{9-5} = vaddr;
7617 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7621 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7622 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7624 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7625 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7628 let Inst{20-16} = 0b00000;
7630 let Inst{11-10} = size;
7632 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7633 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7634 string asm, Operand listtype, Operand GPR64pi>
7635 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7636 (outs listtype:$Vt),
7637 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7641 let Inst{20-16} = Xm;
7643 let Inst{11-10} = size;
7646 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7647 int Offset, int Size> {
7648 // E.g. "ld1r { v0.8b }, [x1], #1"
7649 // "ld1r.8b\t$Vt, $vaddr, #1"
7650 // may get mapped to
7651 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7652 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7653 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7654 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7655 am_simdnoindex:$vaddr, XZR), 1>;
7657 // E.g. "ld1r.8b { v0 }, [x1], #1"
7658 // "ld1r.8b\t$Vt, $vaddr, #1"
7659 // may get mapped to
7660 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7661 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7662 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7663 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7664 am_simdnoindex:$vaddr, XZR), 0>;
7666 // E.g. "ld1r.8b { v0 }, [x1]"
7667 // "ld1r.8b\t$Vt, $vaddr"
7668 // may get mapped to
7669 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7670 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7671 (!cast<Instruction>(NAME # "v" # layout)
7672 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7673 am_simdnoindex:$vaddr), 0>;
7675 // E.g. "ld1r.8b { v0 }, [x1], x2"
7676 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7677 // may get mapped to
7678 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7679 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7680 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7681 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7682 am_simdnoindex:$vaddr,
7683 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7686 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7687 int Offset1, int Offset2, int Offset4, int Offset8> {
7688 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7689 !cast<Operand>("VecList" # Count # "8b")>;
7690 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7691 !cast<Operand>("VecList" # Count #"16b")>;
7692 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7693 !cast<Operand>("VecList" # Count #"4h")>;
7694 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7695 !cast<Operand>("VecList" # Count #"8h")>;
7696 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7697 !cast<Operand>("VecList" # Count #"2s")>;
7698 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7699 !cast<Operand>("VecList" # Count #"4s")>;
7700 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7701 !cast<Operand>("VecList" # Count #"1d")>;
7702 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7703 !cast<Operand>("VecList" # Count #"2d")>;
7705 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7706 !cast<Operand>("VecList" # Count # "8b"),
7707 !cast<Operand>("GPR64pi" # Offset1)>;
7708 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7709 !cast<Operand>("VecList" # Count # "16b"),
7710 !cast<Operand>("GPR64pi" # Offset1)>;
7711 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7712 !cast<Operand>("VecList" # Count # "4h"),
7713 !cast<Operand>("GPR64pi" # Offset2)>;
7714 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7715 !cast<Operand>("VecList" # Count # "8h"),
7716 !cast<Operand>("GPR64pi" # Offset2)>;
7717 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7718 !cast<Operand>("VecList" # Count # "2s"),
7719 !cast<Operand>("GPR64pi" # Offset4)>;
7720 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7721 !cast<Operand>("VecList" # Count # "4s"),
7722 !cast<Operand>("GPR64pi" # Offset4)>;
7723 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7724 !cast<Operand>("VecList" # Count # "1d"),
7725 !cast<Operand>("GPR64pi" # Offset8)>;
7726 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7727 !cast<Operand>("VecList" # Count # "2d"),
7728 !cast<Operand>("GPR64pi" # Offset8)>;
7730 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7731 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7732 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7733 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7734 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7735 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7736 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7737 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7740 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7741 dag oops, dag iops, list<dag> pattern>
7742 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7744 // idx encoded in Q:S:size fields.
7746 let Inst{30} = idx{3};
7748 let Inst{20-16} = 0b00000;
7749 let Inst{12} = idx{2};
7750 let Inst{11-10} = idx{1-0};
7752 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7753 dag oops, dag iops, list<dag> pattern>
7754 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7756 // idx encoded in Q:S:size fields.
7758 let Inst{30} = idx{3};
7760 let Inst{20-16} = 0b00000;
7761 let Inst{12} = idx{2};
7762 let Inst{11-10} = idx{1-0};
7764 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7766 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7768 // idx encoded in Q:S:size fields.
7771 let Inst{30} = idx{3};
7773 let Inst{20-16} = Xm;
7774 let Inst{12} = idx{2};
7775 let Inst{11-10} = idx{1-0};
7777 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7779 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7781 // idx encoded in Q:S:size fields.
7784 let Inst{30} = idx{3};
7786 let Inst{20-16} = Xm;
7787 let Inst{12} = idx{2};
7788 let Inst{11-10} = idx{1-0};
7791 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7792 dag oops, dag iops, list<dag> pattern>
7793 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7795 // idx encoded in Q:S:size<1> fields.
7797 let Inst{30} = idx{2};
7799 let Inst{20-16} = 0b00000;
7800 let Inst{12} = idx{1};
7801 let Inst{11} = idx{0};
7802 let Inst{10} = size;
7804 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7805 dag oops, dag iops, list<dag> pattern>
7806 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7808 // idx encoded in Q:S:size<1> fields.
7810 let Inst{30} = idx{2};
7812 let Inst{20-16} = 0b00000;
7813 let Inst{12} = idx{1};
7814 let Inst{11} = idx{0};
7815 let Inst{10} = size;
7818 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7820 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7822 // idx encoded in Q:S:size<1> fields.
7825 let Inst{30} = idx{2};
7827 let Inst{20-16} = Xm;
7828 let Inst{12} = idx{1};
7829 let Inst{11} = idx{0};
7830 let Inst{10} = size;
7832 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7834 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7836 // idx encoded in Q:S:size<1> fields.
7839 let Inst{30} = idx{2};
7841 let Inst{20-16} = Xm;
7842 let Inst{12} = idx{1};
7843 let Inst{11} = idx{0};
7844 let Inst{10} = size;
7846 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7847 dag oops, dag iops, list<dag> pattern>
7848 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7850 // idx encoded in Q:S fields.
7852 let Inst{30} = idx{1};
7854 let Inst{20-16} = 0b00000;
7855 let Inst{12} = idx{0};
7856 let Inst{11-10} = size;
7858 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7859 dag oops, dag iops, list<dag> pattern>
7860 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7862 // idx encoded in Q:S fields.
7864 let Inst{30} = idx{1};
7866 let Inst{20-16} = 0b00000;
7867 let Inst{12} = idx{0};
7868 let Inst{11-10} = size;
7870 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7871 string asm, dag oops, dag iops>
7872 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7874 // idx encoded in Q:S fields.
7877 let Inst{30} = idx{1};
7879 let Inst{20-16} = Xm;
7880 let Inst{12} = idx{0};
7881 let Inst{11-10} = size;
7883 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7884 string asm, dag oops, dag iops>
7885 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7887 // idx encoded in Q:S fields.
7890 let Inst{30} = idx{1};
7892 let Inst{20-16} = Xm;
7893 let Inst{12} = idx{0};
7894 let Inst{11-10} = size;
7896 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7897 dag oops, dag iops, list<dag> pattern>
7898 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7900 // idx encoded in Q field.
7904 let Inst{20-16} = 0b00000;
7906 let Inst{11-10} = size;
7908 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7909 dag oops, dag iops, list<dag> pattern>
7910 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7912 // idx encoded in Q field.
7916 let Inst{20-16} = 0b00000;
7918 let Inst{11-10} = size;
7920 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7921 string asm, dag oops, dag iops>
7922 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7924 // idx encoded in Q field.
7929 let Inst{20-16} = Xm;
7931 let Inst{11-10} = size;
7933 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7934 string asm, dag oops, dag iops>
7935 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7937 // idx encoded in Q field.
7942 let Inst{20-16} = Xm;
7944 let Inst{11-10} = size;
7947 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7948 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7949 RegisterOperand listtype,
7950 RegisterOperand GPR64pi> {
7951 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7952 (outs listtype:$dst),
7953 (ins listtype:$Vt, VectorIndexB:$idx,
7954 am_simdnoindex:$vaddr), []>;
7956 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
7957 (outs listtype:$dst),
7958 (ins listtype:$Vt, VectorIndexB:$idx,
7959 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7961 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7962 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
7963 RegisterOperand listtype,
7964 RegisterOperand GPR64pi> {
7965 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
7966 (outs listtype:$dst),
7967 (ins listtype:$Vt, VectorIndexH:$idx,
7968 am_simdnoindex:$vaddr), []>;
7970 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
7971 (outs listtype:$dst),
7972 (ins listtype:$Vt, VectorIndexH:$idx,
7973 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7975 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7976 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
7977 RegisterOperand listtype,
7978 RegisterOperand GPR64pi> {
7979 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
7980 (outs listtype:$dst),
7981 (ins listtype:$Vt, VectorIndexS:$idx,
7982 am_simdnoindex:$vaddr), []>;
7984 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
7985 (outs listtype:$dst),
7986 (ins listtype:$Vt, VectorIndexS:$idx,
7987 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7989 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7990 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
7991 RegisterOperand listtype, RegisterOperand GPR64pi> {
7992 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
7993 (outs listtype:$dst),
7994 (ins listtype:$Vt, VectorIndexD:$idx,
7995 am_simdnoindex:$vaddr), []>;
7997 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
7998 (outs listtype:$dst),
7999 (ins listtype:$Vt, VectorIndexD:$idx,
8000 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8002 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8003 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8004 RegisterOperand listtype, RegisterOperand GPR64pi> {
8005 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8006 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8007 am_simdnoindex:$vaddr), []>;
8009 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8010 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8011 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8013 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8014 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8015 RegisterOperand listtype, RegisterOperand GPR64pi> {
8016 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8017 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8018 am_simdnoindex:$vaddr), []>;
8020 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8021 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8022 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8024 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8025 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8026 RegisterOperand listtype, RegisterOperand GPR64pi> {
8027 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8028 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8029 am_simdnoindex:$vaddr), []>;
8031 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8032 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8033 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8035 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8036 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8037 RegisterOperand listtype, RegisterOperand GPR64pi> {
8038 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8039 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8040 am_simdnoindex:$vaddr), []>;
8042 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8043 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8044 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8047 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8048 string Count, int Offset, Operand idxtype> {
8049 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8050 // "ld1\t$Vt, $vaddr, #1"
8051 // may get mapped to
8052 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8053 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8054 (!cast<Instruction>(NAME # Type # "_POST")
8055 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8056 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8058 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8059 // "ld1.8b\t$Vt, $vaddr, #1"
8060 // may get mapped to
8061 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8062 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8063 (!cast<Instruction>(NAME # Type # "_POST")
8064 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8065 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8067 // E.g. "ld1.8b { v0 }[0], [x1]"
8068 // "ld1.8b\t$Vt, $vaddr"
8069 // may get mapped to
8070 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8071 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8072 (!cast<Instruction>(NAME # Type)
8073 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8074 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8076 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8077 // "ld1.8b\t$Vt, $vaddr, $Xm"
8078 // may get mapped to
8079 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8080 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8081 (!cast<Instruction>(NAME # Type # "_POST")
8082 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8083 idxtype:$idx, am_simdnoindex:$vaddr,
8084 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8087 multiclass SIMDLdSt1SingleAliases<string asm> {
8088 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8089 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8090 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8091 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8094 multiclass SIMDLdSt2SingleAliases<string asm> {
8095 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8096 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8097 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8098 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8101 multiclass SIMDLdSt3SingleAliases<string asm> {
8102 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8103 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8104 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8105 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8108 multiclass SIMDLdSt4SingleAliases<string asm> {
8109 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8110 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8111 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8112 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8115 //----------------------------------------------------------------------------
8116 // Crypto extensions
8117 //----------------------------------------------------------------------------
8119 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8120 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8122 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8126 let Inst{31-16} = 0b0100111000101000;
8127 let Inst{15-12} = opc;
8128 let Inst{11-10} = 0b10;
8133 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8134 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8135 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8137 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8138 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8140 [(set (v16i8 V128:$dst),
8141 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8143 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8144 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8145 dag oops, dag iops, list<dag> pat>
8146 : I<oops, iops, asm,
8147 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8148 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8153 let Inst{31-21} = 0b01011110000;
8154 let Inst{20-16} = Rm;
8156 let Inst{14-12} = opc;
8157 let Inst{11-10} = 0b00;
8162 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8163 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8164 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8165 [(set (v4i32 FPR128:$dst),
8166 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8167 (v4i32 V128:$Rm)))]>;
8169 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8170 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8171 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8172 [(set (v4i32 V128:$dst),
8173 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8174 (v4i32 V128:$Rm)))]>;
8176 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8177 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8178 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8179 [(set (v4i32 FPR128:$dst),
8180 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8181 (v4i32 V128:$Rm)))]>;
8183 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8184 class SHA2OpInst<bits<4> opc, string asm, string kind,
8185 string cstr, dag oops, dag iops,
8187 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8188 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8192 let Inst{31-16} = 0b0101111000101000;
8193 let Inst{15-12} = opc;
8194 let Inst{11-10} = 0b10;
8199 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8200 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8201 (ins V128:$Rd, V128:$Rn),
8202 [(set (v4i32 V128:$dst),
8203 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8205 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8206 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8207 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8209 // Allow the size specifier tokens to be upper case, not just lower.
8210 def : TokenAlias<".8B", ".8b">;
8211 def : TokenAlias<".4H", ".4h">;
8212 def : TokenAlias<".2S", ".2s">;
8213 def : TokenAlias<".1D", ".1d">;
8214 def : TokenAlias<".16B", ".16b">;
8215 def : TokenAlias<".8H", ".8h">;
8216 def : TokenAlias<".4S", ".4s">;
8217 def : TokenAlias<".2D", ".2d">;
8218 def : TokenAlias<".1Q", ".1q">;
8219 def : TokenAlias<".B", ".b">;
8220 def : TokenAlias<".H", ".h">;
8221 def : TokenAlias<".S", ".s">;
8222 def : TokenAlias<".D", ".d">;
8223 def : TokenAlias<".Q", ".q">;