xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 2fb4f839f3fc72ce2bab12f9ba4760f97f73e97f)
1//===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
13// Format specifies the encoding used by the instruction.  This is part of the
14// ad-hoc solution used to emit machine instruction encodings by our machine
15// code emitter.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
40
41class FalseLanesEnum<bits<2> val> {
42  bits<2> Value = val;
43}
44def FalseLanesNone  : FalseLanesEnum<0>;
45def FalseLanesZero  : FalseLanesEnum<1>;
46def FalseLanesUndef : FalseLanesEnum<2>;
47
48// AArch64 Instruction Format
49class AArch64Inst<Format f, string cstr> : Instruction {
50  field bits<32> Inst; // Instruction encoding.
51  // Mask of bits that cause an encoding to be UNPREDICTABLE.
52  // If a bit is set, then if the corresponding bit in the
53  // target encoding differs from its value in the "Inst" field,
54  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
55  field bits<32> Unpredictable = 0;
56  // SoftFail is the generic name for this field, but we alias it so
57  // as to make it more obvious what it means in ARM-land.
58  field bits<32> SoftFail = Unpredictable;
59  let Namespace   = "AArch64";
60  Format F        = f;
61  bits<2> Form    = F.Value;
62
63  // Defaults
64  bit isWhile = 0;
65  bit isPTestLike = 0;
66  FalseLanesEnum FalseLanes = FalseLanesNone;
67  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
68  ElementSizeEnum ElementSize = ElementSizeNone;
69
70  let TSFlags{10}  = isPTestLike;
71  let TSFlags{9}   = isWhile;
72  let TSFlags{8-7} = FalseLanes.Value;
73  let TSFlags{6-3} = DestructiveInstType.Value;
74  let TSFlags{2-0} = ElementSize.Value;
75
76  let Pattern     = [];
77  let Constraints = cstr;
78}
79
80class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
81  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
82
83// Pseudo instructions (don't have encoding information)
84class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
85    : AArch64Inst<PseudoFrm, cstr> {
86  dag OutOperandList = oops;
87  dag InOperandList  = iops;
88  let Pattern        = pattern;
89  let isCodeGenOnly  = 1;
90  let isPseudo       = 1;
91}
92
93// Real instructions (have encoding information)
94class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
95  let Pattern = pattern;
96  let Size = 4;
97}
98
99// Normal instructions
100class I<dag oops, dag iops, string asm, string operands, string cstr,
101        list<dag> pattern>
102    : EncodedI<cstr, pattern> {
103  dag OutOperandList = oops;
104  dag InOperandList  = iops;
105  let AsmString      = !strconcat(asm, operands);
106}
107
108class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
109class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
110class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
111
112// Helper fragment for an extract of the high portion of a 128-bit vector.
113def extract_high_v16i8 :
114   UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
115def extract_high_v8i16 :
116   UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
117def extract_high_v4i32 :
118   UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
119def extract_high_v2i64 :
120   UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
121
122//===----------------------------------------------------------------------===//
123// Asm Operand Classes.
124//
125
126// Shifter operand for arithmetic shifted encodings.
127def ShifterOperand : AsmOperandClass {
128  let Name = "Shifter";
129}
130
131// Shifter operand for mov immediate encodings.
132def MovImm32ShifterOperand : AsmOperandClass {
133  let SuperClasses = [ShifterOperand];
134  let Name = "MovImm32Shifter";
135  let RenderMethod = "addShifterOperands";
136  let DiagnosticType = "InvalidMovImm32Shift";
137}
138def MovImm64ShifterOperand : AsmOperandClass {
139  let SuperClasses = [ShifterOperand];
140  let Name = "MovImm64Shifter";
141  let RenderMethod = "addShifterOperands";
142  let DiagnosticType = "InvalidMovImm64Shift";
143}
144
145// Shifter operand for arithmetic register shifted encodings.
146class ArithmeticShifterOperand<int width> : AsmOperandClass {
147  let SuperClasses = [ShifterOperand];
148  let Name = "ArithmeticShifter" # width;
149  let PredicateMethod = "isArithmeticShifter<" # width # ">";
150  let RenderMethod = "addShifterOperands";
151  let DiagnosticType = "AddSubRegShift" # width;
152}
153
154def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
155def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
156
157// Shifter operand for logical register shifted encodings.
158class LogicalShifterOperand<int width> : AsmOperandClass {
159  let SuperClasses = [ShifterOperand];
160  let Name = "LogicalShifter" # width;
161  let PredicateMethod = "isLogicalShifter<" # width # ">";
162  let RenderMethod = "addShifterOperands";
163  let DiagnosticType = "AddSubRegShift" # width;
164}
165
166def LogicalShifterOperand32 : LogicalShifterOperand<32>;
167def LogicalShifterOperand64 : LogicalShifterOperand<64>;
168
169// Shifter operand for logical vector 128/64-bit shifted encodings.
170def LogicalVecShifterOperand : AsmOperandClass {
171  let SuperClasses = [ShifterOperand];
172  let Name = "LogicalVecShifter";
173  let RenderMethod = "addShifterOperands";
174}
175def LogicalVecHalfWordShifterOperand : AsmOperandClass {
176  let SuperClasses = [LogicalVecShifterOperand];
177  let Name = "LogicalVecHalfWordShifter";
178  let RenderMethod = "addShifterOperands";
179}
180
181// The "MSL" shifter on the vector MOVI instruction.
182def MoveVecShifterOperand : AsmOperandClass {
183  let SuperClasses = [ShifterOperand];
184  let Name = "MoveVecShifter";
185  let RenderMethod = "addShifterOperands";
186}
187
188// Extend operand for arithmetic encodings.
189def ExtendOperand : AsmOperandClass {
190  let Name = "Extend";
191  let DiagnosticType = "AddSubRegExtendLarge";
192}
193def ExtendOperand64 : AsmOperandClass {
194  let SuperClasses = [ExtendOperand];
195  let Name = "Extend64";
196  let DiagnosticType = "AddSubRegExtendSmall";
197}
198// 'extend' that's a lsl of a 64-bit register.
199def ExtendOperandLSL64 : AsmOperandClass {
200  let SuperClasses = [ExtendOperand];
201  let Name = "ExtendLSL64";
202  let RenderMethod = "addExtend64Operands";
203  let DiagnosticType = "AddSubRegExtendLarge";
204}
205
206// 8-bit floating-point immediate encodings.
207def FPImmOperand : AsmOperandClass {
208  let Name = "FPImm";
209  let ParserMethod = "tryParseFPImm<true>";
210  let DiagnosticType = "InvalidFPImm";
211}
212
213def CondCode : AsmOperandClass {
214  let Name = "CondCode";
215  let DiagnosticType = "InvalidCondCode";
216}
217
218// A 32-bit register pasrsed as 64-bit
219def GPR32as64Operand : AsmOperandClass {
220  let Name = "GPR32as64";
221  let ParserMethod =
222      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
223}
224def GPR32as64 : RegisterOperand<GPR32> {
225  let ParserMatchClass = GPR32as64Operand;
226}
227
228// A 64-bit register pasrsed as 32-bit
229def GPR64as32Operand : AsmOperandClass {
230  let Name = "GPR64as32";
231  let ParserMethod =
232      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
233}
234def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
235  let ParserMatchClass = GPR64as32Operand;
236}
237
238// 8-bit immediate for AdvSIMD where 64-bit values of the form:
239// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
240// are encoded as the eight bit value 'abcdefgh'.
241def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
242
243class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
244  let Name = "UImm" # Width # "s" # Scale;
245  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
246  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
247  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
248}
249
250class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
251  let Name = "SImm" # Width # "s" # Scale;
252  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
253  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
254  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
255}
256
257//===----------------------------------------------------------------------===//
258// Operand Definitions.
259//
260
261// ADR[P] instruction labels.
262def AdrpOperand : AsmOperandClass {
263  let Name = "AdrpLabel";
264  let ParserMethod = "tryParseAdrpLabel";
265  let DiagnosticType = "InvalidLabel";
266}
267def adrplabel : Operand<i64> {
268  let EncoderMethod = "getAdrLabelOpValue";
269  let PrintMethod = "printAdrpLabel";
270  let ParserMatchClass = AdrpOperand;
271  let OperandType = "OPERAND_PCREL";
272}
273
274def AdrOperand : AsmOperandClass {
275  let Name = "AdrLabel";
276  let ParserMethod = "tryParseAdrLabel";
277  let DiagnosticType = "InvalidLabel";
278}
279def adrlabel : Operand<i64> {
280  let EncoderMethod = "getAdrLabelOpValue";
281  let ParserMatchClass = AdrOperand;
282}
283
284class SImmOperand<int width> : AsmOperandClass {
285  let Name = "SImm" # width;
286  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
287  let RenderMethod = "addImmOperands";
288  let PredicateMethod = "isSImm<" # width # ">";
289}
290
291
292class AsmImmRange<int Low, int High> : AsmOperandClass {
293  let Name = "Imm" # Low # "_" # High;
294  let DiagnosticType = "InvalidImm" # Low # "_" # High;
295  let RenderMethod = "addImmOperands";
296  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
297}
298
299// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
300def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
301def simm10Scaled : Operand<i64> {
302  let ParserMatchClass = SImm10s8Operand;
303  let DecoderMethod = "DecodeSImm<10>";
304  let PrintMethod = "printImmScale<8>";
305}
306
307def simm9s16 : Operand<i64> {
308  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
309  let DecoderMethod = "DecodeSImm<9>";
310  let PrintMethod = "printImmScale<16>";
311}
312
313// uimm6 predicate - True if the immediate is in the range [0, 63].
314def UImm6Operand : AsmOperandClass {
315  let Name = "UImm6";
316  let DiagnosticType = "InvalidImm0_63";
317}
318
319def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
320  let ParserMatchClass = UImm6Operand;
321}
322
323def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
324  let ParserMatchClass = AsmImmRange<0, 65535>;
325}
326
327def SImm9Operand : SImmOperand<9>;
328def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
329  let ParserMatchClass = SImm9Operand;
330  let DecoderMethod = "DecodeSImm<9>";
331}
332
333def SImm8Operand : SImmOperand<8>;
334def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
335  let ParserMatchClass = SImm8Operand;
336  let DecoderMethod = "DecodeSImm<8>";
337}
338
339def SImm6Operand : SImmOperand<6>;
340def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
341  let ParserMatchClass = SImm6Operand;
342  let DecoderMethod = "DecodeSImm<6>";
343}
344
345def SImm5Operand : SImmOperand<5>;
346def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
347  let ParserMatchClass = SImm5Operand;
348  let DecoderMethod = "DecodeSImm<5>";
349}
350
351def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
352  let ParserMatchClass = SImm5Operand;
353  let DecoderMethod = "DecodeSImm<5>";
354}
355
356def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
357  let ParserMatchClass = SImm5Operand;
358  let DecoderMethod = "DecodeSImm<5>";
359  let PrintMethod = "printSImm<8>";
360}
361
362def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
363  let ParserMatchClass = SImm5Operand;
364  let DecoderMethod = "DecodeSImm<5>";
365  let PrintMethod = "printSImm<16>";
366}
367
368// simm7sN predicate - True if the immediate is a multiple of N in the range
369// [-64 * N, 63 * N].
370
371def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
372def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
373def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
374
375def simm7s4 : Operand<i32> {
376  let ParserMatchClass = SImm7s4Operand;
377  let PrintMethod = "printImmScale<4>";
378}
379
380def simm7s8 : Operand<i32> {
381  let ParserMatchClass = SImm7s8Operand;
382  let PrintMethod = "printImmScale<8>";
383}
384
385def simm7s16 : Operand<i32> {
386  let ParserMatchClass = SImm7s16Operand;
387  let PrintMethod = "printImmScale<16>";
388}
389
390def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
391
392def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
393def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
394def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
395def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
396def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
397
398def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
399def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
400
401def UImmS1XForm : SDNodeXForm<imm, [{
402  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
403}]>;
404def UImmS2XForm : SDNodeXForm<imm, [{
405  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
406}]>;
407def UImmS4XForm : SDNodeXForm<imm, [{
408  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
409}]>;
410def UImmS8XForm : SDNodeXForm<imm, [{
411  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
412}]>;
413
414// uimm5sN predicate - True if the immediate is a multiple of N in the range
415// [0 * N, 32 * N].
416def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
417def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
418def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
419
420def uimm5s2 : Operand<i64>, ImmLeaf<i64,
421                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
422                UImmS2XForm> {
423  let ParserMatchClass = UImm5s2Operand;
424  let PrintMethod = "printImmScale<2>";
425}
426def uimm5s4 : Operand<i64>, ImmLeaf<i64,
427                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
428                UImmS4XForm> {
429  let ParserMatchClass = UImm5s4Operand;
430  let PrintMethod = "printImmScale<4>";
431}
432def uimm5s8 : Operand<i64>, ImmLeaf<i64,
433                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
434                UImmS8XForm> {
435  let ParserMatchClass = UImm5s8Operand;
436  let PrintMethod = "printImmScale<8>";
437}
438
439// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
440// instead of ImmLeaf (Constant)
441def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
442                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
443                UImmS2XForm> {
444  let ParserMatchClass = UImm5s2Operand;
445  let PrintMethod = "printImmScale<2>";
446}
447def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
448                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
449                UImmS4XForm> {
450  let ParserMatchClass = UImm5s4Operand;
451  let PrintMethod = "printImmScale<4>";
452}
453def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
454                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
455                UImmS8XForm> {
456  let ParserMatchClass = UImm5s8Operand;
457  let PrintMethod = "printImmScale<8>";
458}
459
460// uimm6sN predicate - True if the immediate is a multiple of N in the range
461// [0 * N, 64 * N].
462def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
463def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
464def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
465def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
466def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
467
468def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
469  let ParserMatchClass = UImm6s1Operand;
470}
471def uimm6s2 : Operand<i64>, ImmLeaf<i64,
472[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
473  let PrintMethod = "printImmScale<2>";
474  let ParserMatchClass = UImm6s2Operand;
475}
476def uimm6s4 : Operand<i64>, ImmLeaf<i64,
477[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
478  let PrintMethod = "printImmScale<4>";
479  let ParserMatchClass = UImm6s4Operand;
480}
481def uimm6s8 : Operand<i64>, ImmLeaf<i64,
482[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
483  let PrintMethod = "printImmScale<8>";
484  let ParserMatchClass = UImm6s8Operand;
485}
486def uimm6s16 : Operand<i64>, ImmLeaf<i64,
487[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
488  let PrintMethod = "printImmScale<16>";
489  let ParserMatchClass = UImm6s16Operand;
490}
491
492def SImmS2XForm : SDNodeXForm<imm, [{
493  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
494}]>;
495def SImmS3XForm : SDNodeXForm<imm, [{
496  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
497}]>;
498def SImmS4XForm : SDNodeXForm<imm, [{
499  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
500}]>;
501def SImmS16XForm : SDNodeXForm<imm, [{
502  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
503}]>;
504def SImmS32XForm : SDNodeXForm<imm, [{
505  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
506}]>;
507
508// simm6sN predicate - True if the immediate is a multiple of N in the range
509// [-32 * N, 31 * N].
510def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
511def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
512  let ParserMatchClass = SImm6s1Operand;
513  let DecoderMethod = "DecodeSImm<6>";
514}
515
516// simm4sN predicate - True if the immediate is a multiple of N in the range
517// [ -8* N, 7 * N].
518def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
519def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
520def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
521def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
522def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
523def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
524
525def simm4s1 : Operand<i64>, ImmLeaf<i64,
526[{ return Imm >=-8  && Imm <= 7; }]> {
527  let ParserMatchClass = SImm4s1Operand;
528  let DecoderMethod = "DecodeSImm<4>";
529}
530
531def simm4s2 : Operand<i64>, ImmLeaf<i64,
532[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
533  let PrintMethod = "printImmScale<2>";
534  let ParserMatchClass = SImm4s2Operand;
535  let DecoderMethod = "DecodeSImm<4>";
536}
537
538def simm4s3 : Operand<i64>, ImmLeaf<i64,
539[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
540  let PrintMethod = "printImmScale<3>";
541  let ParserMatchClass = SImm4s3Operand;
542  let DecoderMethod = "DecodeSImm<4>";
543}
544
545def simm4s4 : Operand<i64>, ImmLeaf<i64,
546[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
547  let PrintMethod = "printImmScale<4>";
548  let ParserMatchClass = SImm4s4Operand;
549  let DecoderMethod = "DecodeSImm<4>";
550}
551def simm4s16 : Operand<i64>, ImmLeaf<i64,
552[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
553  let PrintMethod = "printImmScale<16>";
554  let ParserMatchClass = SImm4s16Operand;
555  let DecoderMethod = "DecodeSImm<4>";
556}
557def simm4s32 : Operand<i64>, ImmLeaf<i64,
558[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
559  let PrintMethod = "printImmScale<32>";
560  let ParserMatchClass = SImm4s32Operand;
561  let DecoderMethod = "DecodeSImm<4>";
562}
563
564def Imm1_8Operand : AsmImmRange<1, 8>;
565def Imm1_16Operand : AsmImmRange<1, 16>;
566def Imm1_32Operand : AsmImmRange<1, 32>;
567def Imm1_64Operand : AsmImmRange<1, 64>;
568
569class BranchTarget<int N> : AsmOperandClass {
570  let Name = "BranchTarget" # N;
571  let DiagnosticType = "InvalidLabel";
572  let PredicateMethod = "isBranchTarget<" # N # ">";
573}
574
575class PCRelLabel<int N> : BranchTarget<N> {
576  let Name = "PCRelLabel" # N;
577}
578
579def BranchTarget14Operand : BranchTarget<14>;
580def BranchTarget26Operand : BranchTarget<26>;
581def PCRelLabel19Operand   : PCRelLabel<19>;
582
583def MovWSymbolG3AsmOperand : AsmOperandClass {
584  let Name = "MovWSymbolG3";
585  let RenderMethod = "addImmOperands";
586}
587
588def movw_symbol_g3 : Operand<i32> {
589  let ParserMatchClass = MovWSymbolG3AsmOperand;
590}
591
592def MovWSymbolG2AsmOperand : AsmOperandClass {
593  let Name = "MovWSymbolG2";
594  let RenderMethod = "addImmOperands";
595}
596
597def movw_symbol_g2 : Operand<i32> {
598  let ParserMatchClass = MovWSymbolG2AsmOperand;
599}
600
601def MovWSymbolG1AsmOperand : AsmOperandClass {
602  let Name = "MovWSymbolG1";
603  let RenderMethod = "addImmOperands";
604}
605
606def movw_symbol_g1 : Operand<i32> {
607  let ParserMatchClass = MovWSymbolG1AsmOperand;
608}
609
610def MovWSymbolG0AsmOperand : AsmOperandClass {
611  let Name = "MovWSymbolG0";
612  let RenderMethod = "addImmOperands";
613}
614
615def movw_symbol_g0 : Operand<i32> {
616  let ParserMatchClass = MovWSymbolG0AsmOperand;
617}
618
619class fixedpoint_i32<ValueType FloatVT>
620  : Operand<FloatVT>,
621    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
622  let EncoderMethod = "getFixedPointScaleOpValue";
623  let DecoderMethod = "DecodeFixedPointScaleImm32";
624  let ParserMatchClass = Imm1_32Operand;
625}
626
627class fixedpoint_i64<ValueType FloatVT>
628  : Operand<FloatVT>,
629    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
630  let EncoderMethod = "getFixedPointScaleOpValue";
631  let DecoderMethod = "DecodeFixedPointScaleImm64";
632  let ParserMatchClass = Imm1_64Operand;
633}
634
635def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
636def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
637def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
638
639def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
640def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
641def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
642
643def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
644  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
645}]> {
646  let EncoderMethod = "getVecShiftR8OpValue";
647  let DecoderMethod = "DecodeVecShiftR8Imm";
648  let ParserMatchClass = Imm1_8Operand;
649}
650def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
651  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
652}]> {
653  let EncoderMethod = "getVecShiftR16OpValue";
654  let DecoderMethod = "DecodeVecShiftR16Imm";
655  let ParserMatchClass = Imm1_16Operand;
656}
657def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
658  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
659}]> {
660  let EncoderMethod = "getVecShiftR16OpValue";
661  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
662  let ParserMatchClass = Imm1_8Operand;
663}
664def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
665  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
666}]> {
667  let EncoderMethod = "getVecShiftR32OpValue";
668  let DecoderMethod = "DecodeVecShiftR32Imm";
669  let ParserMatchClass = Imm1_32Operand;
670}
671def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
672  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
673}]> {
674  let EncoderMethod = "getVecShiftR32OpValue";
675  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
676  let ParserMatchClass = Imm1_16Operand;
677}
678def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
679  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
680}]> {
681  let EncoderMethod = "getVecShiftR64OpValue";
682  let DecoderMethod = "DecodeVecShiftR64Imm";
683  let ParserMatchClass = Imm1_64Operand;
684}
685def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
686  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
687}]> {
688  let EncoderMethod = "getVecShiftR64OpValue";
689  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
690  let ParserMatchClass = Imm1_32Operand;
691}
692
693// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
694// (ImmLeaf)
695def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
696  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
697}]> {
698  let EncoderMethod = "getVecShiftR8OpValue";
699  let DecoderMethod = "DecodeVecShiftR8Imm";
700  let ParserMatchClass = Imm1_8Operand;
701}
702def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
703  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
704}]> {
705  let EncoderMethod = "getVecShiftR16OpValue";
706  let DecoderMethod = "DecodeVecShiftR16Imm";
707  let ParserMatchClass = Imm1_16Operand;
708}
709def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
710  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
711}]> {
712  let EncoderMethod = "getVecShiftR32OpValue";
713  let DecoderMethod = "DecodeVecShiftR32Imm";
714  let ParserMatchClass = Imm1_32Operand;
715}
716def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
717  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
718}]> {
719  let EncoderMethod = "getVecShiftR64OpValue";
720  let DecoderMethod = "DecodeVecShiftR64Imm";
721  let ParserMatchClass = Imm1_64Operand;
722}
723
724def Imm0_0Operand : AsmImmRange<0, 0>;
725def Imm0_1Operand : AsmImmRange<0, 1>;
726def Imm0_3Operand : AsmImmRange<0, 3>;
727def Imm0_7Operand : AsmImmRange<0, 7>;
728def Imm0_15Operand : AsmImmRange<0, 15>;
729def Imm0_31Operand : AsmImmRange<0, 31>;
730def Imm0_63Operand : AsmImmRange<0, 63>;
731
732def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
733  return (((uint32_t)Imm) < 8);
734}]> {
735  let EncoderMethod = "getVecShiftL8OpValue";
736  let DecoderMethod = "DecodeVecShiftL8Imm";
737  let ParserMatchClass = Imm0_7Operand;
738}
739def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
740  return (((uint32_t)Imm) < 16);
741}]> {
742  let EncoderMethod = "getVecShiftL16OpValue";
743  let DecoderMethod = "DecodeVecShiftL16Imm";
744  let ParserMatchClass = Imm0_15Operand;
745}
746def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
747  return (((uint32_t)Imm) < 32);
748}]> {
749  let EncoderMethod = "getVecShiftL32OpValue";
750  let DecoderMethod = "DecodeVecShiftL32Imm";
751  let ParserMatchClass = Imm0_31Operand;
752}
753def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
754  return (((uint32_t)Imm) < 64);
755}]> {
756  let EncoderMethod = "getVecShiftL64OpValue";
757  let DecoderMethod = "DecodeVecShiftL64Imm";
758  let ParserMatchClass = Imm0_63Operand;
759}
760
761// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
762// (ImmLeaf)
763def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
764  return (((uint32_t)Imm) < 8);
765}]> {
766  let EncoderMethod = "getVecShiftL8OpValue";
767  let DecoderMethod = "DecodeVecShiftL8Imm";
768  let ParserMatchClass = Imm0_7Operand;
769}
770def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
771  return (((uint32_t)Imm) < 16);
772}]> {
773  let EncoderMethod = "getVecShiftL16OpValue";
774  let DecoderMethod = "DecodeVecShiftL16Imm";
775  let ParserMatchClass = Imm0_15Operand;
776}
777def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
778  return (((uint32_t)Imm) < 32);
779}]> {
780  let EncoderMethod = "getVecShiftL32OpValue";
781  let DecoderMethod = "DecodeVecShiftL32Imm";
782  let ParserMatchClass = Imm0_31Operand;
783}
784def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
785  return (((uint32_t)Imm) < 64);
786}]> {
787  let EncoderMethod = "getVecShiftL64OpValue";
788  let DecoderMethod = "DecodeVecShiftL64Imm";
789  let ParserMatchClass = Imm0_63Operand;
790}
791
792// Crazy immediate formats used by 32-bit and 64-bit logical immediate
793// instructions for splatting repeating bit patterns across the immediate.
794def logical_imm32_XFORM : SDNodeXForm<imm, [{
795  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
796  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
797}]>;
798def logical_imm64_XFORM : SDNodeXForm<imm, [{
799  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
800  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
801}]>;
802
803def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
804  GISDNodeXFormEquiv<logical_imm32_XFORM>;
805def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
806  GISDNodeXFormEquiv<logical_imm64_XFORM>;
807
808let DiagnosticType = "LogicalSecondSource" in {
809  def LogicalImm32Operand : AsmOperandClass {
810    let Name = "LogicalImm32";
811    let PredicateMethod = "isLogicalImm<int32_t>";
812    let RenderMethod = "addLogicalImmOperands<int32_t>";
813  }
814  def LogicalImm64Operand : AsmOperandClass {
815    let Name = "LogicalImm64";
816    let PredicateMethod = "isLogicalImm<int64_t>";
817    let RenderMethod = "addLogicalImmOperands<int64_t>";
818  }
819  def LogicalImm32NotOperand : AsmOperandClass {
820    let Name = "LogicalImm32Not";
821    let PredicateMethod = "isLogicalImm<int32_t>";
822    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
823  }
824  def LogicalImm64NotOperand : AsmOperandClass {
825    let Name = "LogicalImm64Not";
826    let PredicateMethod = "isLogicalImm<int64_t>";
827    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
828  }
829}
830def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
831  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
832}], logical_imm32_XFORM> {
833  let PrintMethod = "printLogicalImm<int32_t>";
834  let ParserMatchClass = LogicalImm32Operand;
835}
836def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
837  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
838}], logical_imm64_XFORM> {
839  let PrintMethod = "printLogicalImm<int64_t>";
840  let ParserMatchClass = LogicalImm64Operand;
841}
842def logical_imm32_not : Operand<i32> {
843  let ParserMatchClass = LogicalImm32NotOperand;
844}
845def logical_imm64_not : Operand<i64> {
846  let ParserMatchClass = LogicalImm64NotOperand;
847}
848
849// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
850let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
851def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
852  return ((uint32_t)Imm) < 65536;
853}]>;
854
855def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
856  return ((uint64_t)Imm) < 65536;
857}]>;
858}
859
860// imm0_255 predicate - True if the immediate is in the range [0,255].
861def Imm0_255Operand : AsmImmRange<0,255>;
862
863def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
864  return ((uint32_t)Imm) < 256;
865}]> {
866  let ParserMatchClass = Imm0_255Operand;
867  let PrintMethod = "printImm";
868}
869
870// imm0_127 predicate - True if the immediate is in the range [0,127]
871def Imm0_127Operand : AsmImmRange<0, 127>;
872def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
873  return ((uint32_t)Imm) < 128;
874}]> {
875  let ParserMatchClass = Imm0_127Operand;
876  let PrintMethod = "printImm";
877}
878
879def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
880  return ((uint64_t)Imm) < 128;
881}]> {
882  let ParserMatchClass = Imm0_127Operand;
883  let PrintMethod = "printImm";
884}
885
886// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
887// for all shift-amounts.
888
889// imm0_63 predicate - True if the immediate is in the range [0,63]
890def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
891  return ((uint64_t)Imm) < 64;
892}]> {
893  let ParserMatchClass = Imm0_63Operand;
894}
895
896def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
897  return ((uint64_t)Imm) < 64;
898}]> {
899  let ParserMatchClass = Imm0_63Operand;
900}
901
902// imm0_31 predicate - True if the immediate is in the range [0,31]
903def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
904  return ((uint64_t)Imm) < 32;
905}]> {
906  let ParserMatchClass = Imm0_31Operand;
907}
908
909// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
910// instead of Constant (ImmLeaf)
911def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
912  return ((uint64_t)Imm) < 32;
913}]> {
914  let ParserMatchClass = Imm0_31Operand;
915}
916
917// True if the 32-bit immediate is in the range [0,31]
918def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
919  return ((uint64_t)Imm) < 32;
920}]> {
921  let ParserMatchClass = Imm0_31Operand;
922}
923
924// imm0_1 predicate - True if the immediate is in the range [0,1]
925def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
926  return ((uint64_t)Imm) < 2;
927}]> {
928  let ParserMatchClass = Imm0_1Operand;
929}
930
931// timm0_1 - as above, but use TargetConstant (TImmLeaf)
932def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
933  return ((uint64_t)Imm) < 2;
934}]> {
935  let ParserMatchClass = Imm0_1Operand;
936}
937
938// imm0_15 predicate - True if the immediate is in the range [0,15]
939def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
940  return ((uint64_t)Imm) < 16;
941}]> {
942  let ParserMatchClass = Imm0_15Operand;
943}
944
945// imm0_7 predicate - True if the immediate is in the range [0,7]
946def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
947  return ((uint64_t)Imm) < 8;
948}]> {
949  let ParserMatchClass = Imm0_7Operand;
950}
951
952// imm0_3 predicate - True if the immediate is in the range [0,3]
953def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
954  return ((uint64_t)Imm) < 4;
955}]> {
956  let ParserMatchClass = Imm0_3Operand;
957}
958
959// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
960def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
961  return ((uint32_t)Imm) < 8;
962}]> {
963  let ParserMatchClass = Imm0_7Operand;
964}
965
966// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
967def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
968  return ((uint32_t)Imm) < 16;
969}]> {
970  let ParserMatchClass = Imm0_15Operand;
971}
972
973// An arithmetic shifter operand:
974//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
975//  {5-0} - imm6
976class arith_shift<ValueType Ty, int width> : Operand<Ty> {
977  let PrintMethod = "printShifter";
978  let ParserMatchClass = !cast<AsmOperandClass>(
979                         "ArithmeticShifterOperand" # width);
980}
981
982def arith_shift32 : arith_shift<i32, 32>;
983def arith_shift64 : arith_shift<i64, 64>;
984
985class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
986    : Operand<Ty>,
987      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
988  let PrintMethod = "printShiftedRegister";
989  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
990}
991
992def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
993def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
994
995def gi_arith_shifted_reg32 :
996  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
997  GIComplexPatternEquiv<arith_shifted_reg32>;
998
999def gi_arith_shifted_reg64 :
1000  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1001  GIComplexPatternEquiv<arith_shifted_reg64>;
1002
1003// An arithmetic shifter operand:
1004//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1005//  {5-0} - imm6
1006class logical_shift<int width> : Operand<i32> {
1007  let PrintMethod = "printShifter";
1008  let ParserMatchClass = !cast<AsmOperandClass>(
1009                         "LogicalShifterOperand" # width);
1010}
1011
1012def logical_shift32 : logical_shift<32>;
1013def logical_shift64 : logical_shift<64>;
1014
1015class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1016    : Operand<Ty>,
1017      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1018  let PrintMethod = "printShiftedRegister";
1019  let MIOperandInfo = (ops regclass, shiftop);
1020}
1021
1022def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1023def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1024
1025def gi_logical_shifted_reg32 :
1026  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1027  GIComplexPatternEquiv<logical_shifted_reg32>;
1028
1029def gi_logical_shifted_reg64 :
1030  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1031  GIComplexPatternEquiv<logical_shifted_reg64>;
1032
1033// A logical vector shifter operand:
1034//  {7-6} - shift type: 00 = lsl
1035//  {5-0} - imm6: #0, #8, #16, or #24
1036def logical_vec_shift : Operand<i32> {
1037  let PrintMethod = "printShifter";
1038  let EncoderMethod = "getVecShifterOpValue";
1039  let ParserMatchClass = LogicalVecShifterOperand;
1040}
1041
1042// A logical vector half-word shifter operand:
1043//  {7-6} - shift type: 00 = lsl
1044//  {5-0} - imm6: #0 or #8
1045def logical_vec_hw_shift : Operand<i32> {
1046  let PrintMethod = "printShifter";
1047  let EncoderMethod = "getVecShifterOpValue";
1048  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1049}
1050
1051// A vector move shifter operand:
1052//  {0} - imm1: #8 or #16
1053def move_vec_shift : Operand<i32> {
1054  let PrintMethod = "printShifter";
1055  let EncoderMethod = "getMoveVecShifterOpValue";
1056  let ParserMatchClass = MoveVecShifterOperand;
1057}
1058
1059let DiagnosticType = "AddSubSecondSource" in {
1060  def AddSubImmOperand : AsmOperandClass {
1061    let Name = "AddSubImm";
1062    let ParserMethod = "tryParseImmWithOptionalShift";
1063    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1064  }
1065  def AddSubImmNegOperand : AsmOperandClass {
1066    let Name = "AddSubImmNeg";
1067    let ParserMethod = "tryParseImmWithOptionalShift";
1068    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1069  }
1070}
1071// An ADD/SUB immediate shifter operand:
1072//  second operand:
1073//  {7-6} - shift type: 00 = lsl
1074//  {5-0} - imm6: #0 or #12
1075class addsub_shifted_imm<ValueType Ty>
1076    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1077  let PrintMethod = "printAddSubImm";
1078  let EncoderMethod = "getAddSubImmOpValue";
1079  let ParserMatchClass = AddSubImmOperand;
1080  let MIOperandInfo = (ops i32imm, i32imm);
1081}
1082
1083class addsub_shifted_imm_neg<ValueType Ty>
1084    : Operand<Ty> {
1085  let EncoderMethod = "getAddSubImmOpValue";
1086  let ParserMatchClass = AddSubImmNegOperand;
1087  let MIOperandInfo = (ops i32imm, i32imm);
1088}
1089
1090def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1091def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1092def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1093def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1094
1095def gi_addsub_shifted_imm32 :
1096    GIComplexOperandMatcher<s32, "selectArithImmed">,
1097    GIComplexPatternEquiv<addsub_shifted_imm32>;
1098
1099def gi_addsub_shifted_imm64 :
1100    GIComplexOperandMatcher<s64, "selectArithImmed">,
1101    GIComplexPatternEquiv<addsub_shifted_imm64>;
1102
1103class neg_addsub_shifted_imm<ValueType Ty>
1104    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1105  let PrintMethod = "printAddSubImm";
1106  let EncoderMethod = "getAddSubImmOpValue";
1107  let ParserMatchClass = AddSubImmOperand;
1108  let MIOperandInfo = (ops i32imm, i32imm);
1109}
1110
1111def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1112def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1113
1114def gi_neg_addsub_shifted_imm32 :
1115    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1116    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1117
1118def gi_neg_addsub_shifted_imm64 :
1119    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1120    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1121
1122// An extend operand:
1123//  {5-3} - extend type
1124//  {2-0} - imm3
1125def arith_extend : Operand<i32> {
1126  let PrintMethod = "printArithExtend";
1127  let ParserMatchClass = ExtendOperand;
1128}
1129def arith_extend64 : Operand<i32> {
1130  let PrintMethod = "printArithExtend";
1131  let ParserMatchClass = ExtendOperand64;
1132}
1133
1134// 'extend' that's a lsl of a 64-bit register.
1135def arith_extendlsl64 : Operand<i32> {
1136  let PrintMethod = "printArithExtend";
1137  let ParserMatchClass = ExtendOperandLSL64;
1138}
1139
1140class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1141                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1142  let PrintMethod = "printExtendedRegister";
1143  let MIOperandInfo = (ops GPR32, arith_extend);
1144}
1145
1146class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1147                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1148  let PrintMethod = "printExtendedRegister";
1149  let MIOperandInfo = (ops GPR32, arith_extend64);
1150}
1151
1152def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1153def gi_arith_extended_reg32_i32 :
1154    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1155    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1156
1157def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1158def gi_arith_extended_reg32_i64 :
1159    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1160    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1161
1162def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1163def gi_arith_extended_reg32to64_i64 :
1164    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1165    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1166
1167// Floating-point immediate.
1168
1169def fpimm16XForm : SDNodeXForm<fpimm, [{
1170      APFloat InVal = N->getValueAPF();
1171      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1172      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1173    }]>;
1174
1175def fpimm32XForm : SDNodeXForm<fpimm, [{
1176      APFloat InVal = N->getValueAPF();
1177      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1178      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1179    }]>;
1180
1181def fpimm64XForm : SDNodeXForm<fpimm, [{
1182      APFloat InVal = N->getValueAPF();
1183      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1184      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1185    }]>;
1186
1187def fpimm16 : Operand<f16>,
1188              FPImmLeaf<f16, [{
1189      return AArch64_AM::getFP16Imm(Imm) != -1;
1190    }], fpimm16XForm> {
1191  let ParserMatchClass = FPImmOperand;
1192  let PrintMethod = "printFPImmOperand";
1193}
1194
1195def fpimm32 : Operand<f32>,
1196              FPImmLeaf<f32, [{
1197      return AArch64_AM::getFP32Imm(Imm) != -1;
1198    }], fpimm32XForm> {
1199  let ParserMatchClass = FPImmOperand;
1200  let PrintMethod = "printFPImmOperand";
1201}
1202def fpimm64 : Operand<f64>,
1203              FPImmLeaf<f64, [{
1204      return AArch64_AM::getFP64Imm(Imm) != -1;
1205    }], fpimm64XForm> {
1206  let ParserMatchClass = FPImmOperand;
1207  let PrintMethod = "printFPImmOperand";
1208}
1209
1210def fpimm8 : Operand<i32> {
1211  let ParserMatchClass = FPImmOperand;
1212  let PrintMethod = "printFPImmOperand";
1213}
1214
1215def fpimm0 : FPImmLeaf<fAny, [{
1216  return Imm.isExactlyValue(+0.0);
1217}]>;
1218
1219def fpimm_half : FPImmLeaf<fAny, [{
1220  return Imm.isExactlyValue(+0.5);
1221}]>;
1222
1223def fpimm_one : FPImmLeaf<fAny, [{
1224  return Imm.isExactlyValue(+1.0);
1225}]>;
1226
1227def fpimm_two : FPImmLeaf<fAny, [{
1228  return Imm.isExactlyValue(+2.0);
1229}]>;
1230
1231def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1232  GISDNodeXFormEquiv<fpimm16XForm>;
1233def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1234  GISDNodeXFormEquiv<fpimm32XForm>;
1235def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1236  GISDNodeXFormEquiv<fpimm64XForm>;
1237
1238// Vector lane operands
1239class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1240  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1241  let DiagnosticType = "Invalid" # Name;
1242  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1243  let RenderMethod = "addVectorIndexOperands";
1244}
1245
1246class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1247    : Operand<ty> {
1248  let ParserMatchClass = mc;
1249  let PrintMethod = "printVectorIndex";
1250}
1251
1252multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1253  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1254  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1255}
1256
1257def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1258def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1259def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1260def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1261def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1262def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1263
1264defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1265                                [{ return ((uint64_t)Imm) == 0; }]>;
1266defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1267                                [{ return ((uint64_t)Imm) == 1; }]>;
1268defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1269                                [{ return ((uint64_t)Imm) < 16; }]>;
1270defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1271                                [{ return ((uint64_t)Imm) < 8; }]>;
1272defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1273                                [{ return ((uint64_t)Imm) < 4; }]>;
1274defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1275                                [{ return ((uint64_t)Imm) < 2; }]>;
1276
1277defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1278                                   [{ return ((uint64_t)Imm) == 1; }]>;
1279defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1280                                   [{ return ((uint64_t)Imm) < 16; }]>;
1281defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1282                                   [{ return ((uint64_t)Imm) < 8; }]>;
1283defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1284                                   [{ return ((uint64_t)Imm) < 4; }]>;
1285defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1286                                   [{ return ((uint64_t)Imm) < 2; }]>;
1287
1288def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1289def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1290def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1291def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1292def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1293
1294defm sve_elm_idx_extdup_b
1295  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1296                [{ return ((uint64_t)Imm) < 64; }]>;
1297defm sve_elm_idx_extdup_h
1298  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1299                [{ return ((uint64_t)Imm) < 32; }]>;
1300defm sve_elm_idx_extdup_s
1301  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1302                [{ return ((uint64_t)Imm) < 16; }]>;
1303defm sve_elm_idx_extdup_d
1304  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1305                [{ return ((uint64_t)Imm) < 8; }]>;
1306defm sve_elm_idx_extdup_q
1307  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1308                [{ return ((uint64_t)Imm) < 4; }]>;
1309
1310def sme_elm_idx0_0 : Operand<i64>, ImmLeaf<i64, [{
1311  return ((uint64_t)Imm) == 0;
1312}]> {
1313  let ParserMatchClass = Imm0_0Operand;
1314  let PrintMethod = "printMatrixIndex";
1315}
1316def sme_elm_idx0_1 : Operand<i64>, ImmLeaf<i64, [{
1317  return ((uint64_t)Imm) <= 1;
1318}]> {
1319  let ParserMatchClass = Imm0_1Operand;
1320  let PrintMethod = "printMatrixIndex";
1321}
1322def sme_elm_idx0_3 : Operand<i64>, ImmLeaf<i64, [{
1323  return ((uint64_t)Imm) <= 3;
1324}]> {
1325  let ParserMatchClass = Imm0_3Operand;
1326  let PrintMethod = "printMatrixIndex";
1327}
1328def sme_elm_idx0_7 : Operand<i64>, ImmLeaf<i64, [{
1329  return ((uint64_t)Imm) <= 7;
1330}]> {
1331  let ParserMatchClass = Imm0_7Operand;
1332  let PrintMethod = "printMatrixIndex";
1333}
1334def sme_elm_idx0_15 : Operand<i64>, ImmLeaf<i64, [{
1335  return ((uint64_t)Imm) <= 15;
1336}]> {
1337  let ParserMatchClass = Imm0_15Operand;
1338  let PrintMethod = "printMatrixIndex";
1339}
1340
1341// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1342// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1343// are encoded as the eight bit value 'abcdefgh'.
1344def simdimmtype10 : Operand<i32>,
1345                    FPImmLeaf<f64, [{
1346      return AArch64_AM::isAdvSIMDModImmType10(
1347                 Imm.bitcastToAPInt().getZExtValue());
1348    }], SDNodeXForm<fpimm, [{
1349      APFloat InVal = N->getValueAPF();
1350      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1351                                                           .bitcastToAPInt()
1352                                                           .getZExtValue());
1353      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1354    }]>> {
1355  let ParserMatchClass = SIMDImmType10Operand;
1356  let PrintMethod = "printSIMDType10Operand";
1357}
1358
1359
1360//---
1361// System management
1362//---
1363
1364// Base encoding for system instruction operands.
1365let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1366class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1367                  list<dag> pattern = []>
1368    : I<oops, iops, asm, operands, "", pattern> {
1369  let Inst{31-22} = 0b1101010100;
1370  let Inst{21}    = L;
1371}
1372
1373// System instructions which do not have an Rt register.
1374class SimpleSystemI<bit L, dag iops, string asm, string operands,
1375                    list<dag> pattern = []>
1376    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1377  let Inst{4-0} = 0b11111;
1378}
1379
1380// System instructions which have an Rt register.
1381class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1382                list<dag> pattern = []>
1383    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1384      Sched<[WriteSys]> {
1385  bits<5> Rt;
1386  let Inst{4-0} = Rt;
1387}
1388
1389// System instructions for transactional memory extension
1390class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1391                    string asm, string operands, list<dag> pattern>
1392    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1393      Sched<[WriteSys]> {
1394  let Inst{20-12} = 0b000110011;
1395  let Inst{11-8} = CRm;
1396  let Inst{7-5} = op2;
1397  let DecoderMethod = "";
1398
1399  let mayLoad = 1;
1400  let mayStore = 1;
1401}
1402
1403// System instructions for transactional memory - single input operand
1404class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1405    : TMBaseSystemI<0b1, CRm, 0b011,
1406                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1407  bits<5> Rt;
1408  let Inst{4-0} = Rt;
1409}
1410
1411// System instructions that pass a register argument
1412// This class assumes the register is for input rather than output.
1413class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1414                      list<dag> pattern = []>
1415    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1416  let Inst{20-12} = 0b000110001;
1417  let Inst{11-8} = CRm;
1418  let Inst{7-5} = Op2;
1419}
1420
1421// System instructions for transactional memory - no operand
1422class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1423    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1424  let Inst{4-0} = 0b11111;
1425}
1426
1427// System instructions for exit from transactions
1428class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1429    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1430      Sched<[WriteSys]> {
1431  bits<16> imm;
1432  let Inst{31-24} = 0b11010100;
1433  let Inst{23-21} = op1;
1434  let Inst{20-5}  = imm;
1435  let Inst{4-0}   = 0b00000;
1436}
1437
1438// Hint instructions that take both a CRm and a 3-bit immediate.
1439// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1440// model patterns with sufficiently fine granularity
1441let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1442  class HintI<string mnemonic>
1443      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1444                      [(int_aarch64_hint imm0_127:$imm)]>,
1445        Sched<[WriteHint]> {
1446    bits <7> imm;
1447    let Inst{20-12} = 0b000110010;
1448    let Inst{11-5} = imm;
1449  }
1450
1451// System instructions taking a single literal operand which encodes into
1452// CRm. op2 differentiates the opcodes.
1453def BarrierAsmOperand : AsmOperandClass {
1454  let Name = "Barrier";
1455  let ParserMethod = "tryParseBarrierOperand";
1456}
1457def barrier_op : Operand<i32> {
1458  let PrintMethod = "printBarrierOption";
1459  let ParserMatchClass = BarrierAsmOperand;
1460}
1461def BarriernXSAsmOperand : AsmOperandClass {
1462  let Name = "BarriernXS";
1463  let ParserMethod = "tryParseBarriernXSOperand";
1464}
1465def barrier_nxs_op : Operand<i32> {
1466  let PrintMethod = "printBarriernXSOption";
1467  let ParserMatchClass = BarriernXSAsmOperand;
1468}
1469class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1470                 list<dag> pattern = []>
1471    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1472      Sched<[WriteBarrier]> {
1473  bits<4> CRm;
1474  let Inst{20-12} = 0b000110011;
1475  let Inst{11-8} = CRm;
1476  let Inst{7-5} = opc;
1477}
1478
1479class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1480    : SimpleSystemI<0, (ins), asm, "", pattern>,
1481      Sched<[]> {
1482  bits<4> CRm;
1483  let CRm = 0b0011;
1484  let Inst{31-12} = 0b11010101000000110010;
1485  let Inst{11-8} = CRm;
1486  let Inst{7-5} = op2;
1487  let Inst{4-0} = 0b11111;
1488}
1489
1490// MRS/MSR system instructions. These have different operand classes because
1491// a different subset of registers can be accessed through each instruction.
1492def MRSSystemRegisterOperand : AsmOperandClass {
1493  let Name = "MRSSystemRegister";
1494  let ParserMethod = "tryParseSysReg";
1495  let DiagnosticType = "MRS";
1496}
1497// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1498def mrs_sysreg_op : Operand<i32> {
1499  let ParserMatchClass = MRSSystemRegisterOperand;
1500  let DecoderMethod = "DecodeMRSSystemRegister";
1501  let PrintMethod = "printMRSSystemRegister";
1502}
1503
1504def MSRSystemRegisterOperand : AsmOperandClass {
1505  let Name = "MSRSystemRegister";
1506  let ParserMethod = "tryParseSysReg";
1507  let DiagnosticType = "MSR";
1508}
1509def msr_sysreg_op : Operand<i32> {
1510  let ParserMatchClass = MSRSystemRegisterOperand;
1511  let DecoderMethod = "DecodeMSRSystemRegister";
1512  let PrintMethod = "printMSRSystemRegister";
1513}
1514
1515def PSBHintOperand : AsmOperandClass {
1516  let Name = "PSBHint";
1517  let ParserMethod = "tryParsePSBHint";
1518}
1519def psbhint_op : Operand<i32> {
1520  let ParserMatchClass = PSBHintOperand;
1521  let PrintMethod = "printPSBHintOp";
1522  let MCOperandPredicate = [{
1523    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1524    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1525    if (!MCOp.isImm())
1526      return false;
1527    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1528  }];
1529}
1530
1531def BTIHintOperand : AsmOperandClass {
1532  let Name = "BTIHint";
1533  let ParserMethod = "tryParseBTIHint";
1534}
1535def btihint_op : Operand<i32> {
1536  let ParserMatchClass = BTIHintOperand;
1537  let PrintMethod = "printBTIHintOp";
1538  let MCOperandPredicate = [{
1539    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1540    if (!MCOp.isImm())
1541      return false;
1542    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1543  }];
1544}
1545
1546class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1547                       "mrs", "\t$Rt, $systemreg"> {
1548  bits<16> systemreg;
1549  let Inst{20-5} = systemreg;
1550  let DecoderNamespace = "Fallback";
1551  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1552  // require doing this. The alternative was to explicitly model each one, but
1553  // it feels like it is unnecessary because it seems there are no negative
1554  // consequences setting these flags for all.
1555  let Defs = [NZCV];
1556}
1557
1558// FIXME: Some of these def NZCV, others don't. Best way to model that?
1559// Explicitly modeling each of the system register as a register class
1560// would do it, but feels like overkill at this point.
1561class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1562                       "msr", "\t$systemreg, $Rt"> {
1563  bits<16> systemreg;
1564  let Inst{20-5} = systemreg;
1565  let DecoderNamespace = "Fallback";
1566}
1567
1568def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1569  let Name = "SystemPStateFieldWithImm0_15";
1570  let ParserMethod = "tryParseSysReg";
1571}
1572def pstatefield4_op : Operand<i32> {
1573  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1574  let PrintMethod = "printSystemPStateField";
1575}
1576
1577// Instructions to modify PSTATE, no input reg
1578let Defs = [NZCV] in
1579class PstateWriteSimple<dag iops, string asm, string operands>
1580  : SimpleSystemI<0, iops, asm, operands> {
1581
1582  let Inst{20-19} = 0b00;
1583  let Inst{15-12} = 0b0100;
1584}
1585
1586class MSRpstateImm0_15
1587  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1588                  "\t$pstatefield, $imm">,
1589    Sched<[WriteSys]> {
1590
1591  bits<6> pstatefield;
1592  bits<4> imm;
1593  let Inst{18-16} = pstatefield{5-3};
1594  let Inst{11-8} = imm;
1595  let Inst{7-5} = pstatefield{2-0};
1596
1597  let DecoderMethod = "DecodeSystemPStateInstruction";
1598  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1599  // Fail the decoder should attempt to decode the instruction as MSRI.
1600  let hasCompleteDecoder = 0;
1601}
1602
1603def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1604  let Name = "SystemPStateFieldWithImm0_1";
1605  let ParserMethod = "tryParseSysReg";
1606}
1607def pstatefield1_op : Operand<i32> {
1608  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1609  let PrintMethod = "printSystemPStateField";
1610}
1611
1612class MSRpstateImm0_1
1613  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1614                 "\t$pstatefield, $imm">,
1615    Sched<[WriteSys]> {
1616
1617  bits<6> pstatefield;
1618  bit imm;
1619  let Inst{18-16} = pstatefield{5-3};
1620  let Inst{11-9} = 0b000;
1621  let Inst{8} = imm;
1622  let Inst{7-5} = pstatefield{2-0};
1623
1624  let DecoderMethod = "DecodeSystemPStateInstruction";
1625  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1626  // Fail the decoder should attempt to decode the instruction as MSRI.
1627  let hasCompleteDecoder = 0;
1628}
1629
1630// SYS and SYSL generic system instructions.
1631def SysCRAsmOperand : AsmOperandClass {
1632  let Name = "SysCR";
1633  let ParserMethod = "tryParseSysCROperand";
1634}
1635
1636def sys_cr_op : Operand<i32> {
1637  let PrintMethod = "printSysCROperand";
1638  let ParserMatchClass = SysCRAsmOperand;
1639}
1640
1641class SystemXtI<bit L, string asm>
1642  : RtSystemI<L, (outs),
1643       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1644       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1645  bits<3> op1;
1646  bits<4> Cn;
1647  bits<4> Cm;
1648  bits<3> op2;
1649  let Inst{20-19} = 0b01;
1650  let Inst{18-16} = op1;
1651  let Inst{15-12} = Cn;
1652  let Inst{11-8}  = Cm;
1653  let Inst{7-5}   = op2;
1654}
1655
1656class SystemLXtI<bit L, string asm>
1657  : RtSystemI<L, (outs),
1658       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1659       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1660  bits<3> op1;
1661  bits<4> Cn;
1662  bits<4> Cm;
1663  bits<3> op2;
1664  let Inst{20-19} = 0b01;
1665  let Inst{18-16} = op1;
1666  let Inst{15-12} = Cn;
1667  let Inst{11-8}  = Cm;
1668  let Inst{7-5}   = op2;
1669}
1670
1671
1672// Branch (register) instructions:
1673//
1674//  case opc of
1675//    0001 blr
1676//    0000 br
1677//    0101 dret
1678//    0100 eret
1679//    0010 ret
1680//    otherwise UNDEFINED
1681class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1682                    string operands, list<dag> pattern>
1683    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1684  let Inst{31-25} = 0b1101011;
1685  let Inst{24-21} = opc;
1686  let Inst{20-16} = 0b11111;
1687  let Inst{15-10} = 0b000000;
1688  let Inst{4-0}   = 0b00000;
1689}
1690
1691class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1692    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1693  bits<5> Rn;
1694  let Inst{9-5} = Rn;
1695}
1696
1697let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1698class SpecialReturn<bits<4> opc, string asm>
1699    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1700  let Inst{9-5} = 0b11111;
1701}
1702
1703let mayLoad = 1 in
1704class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1705  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1706  Sched<[]> {
1707  bits<5> Rn;
1708  bits<5> Rt;
1709  let Inst{31-30} = sz;
1710  let Inst{29-10} = 0b11100010111111110000;
1711  let Inst{9-5} = Rn;
1712  let Inst{4-0} = Rt;
1713}
1714
1715class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1716               list<dag> pattern>
1717  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1718  let isAuthenticated = 1;
1719  let Inst{31-25} = 0b1101011;
1720  let Inst{20-11} = 0b1111100001;
1721  let Inst{10} = M;
1722  let Inst{4-0} = 0b11111;
1723}
1724
1725class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1726  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1727  bits<5> Rn;
1728  bits<5> Rm;
1729  let Inst{24-22} = 0b100;
1730  let Inst{21} = op;
1731  let Inst{9-5} = Rn;
1732  let Inst{4-0} = Rm;
1733}
1734
1735class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1736  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1737  bits<5> Rn;
1738  let Inst{24} = 0;
1739  let Inst{23-21} = opc;
1740  let Inst{9-5} = Rn;
1741}
1742
1743let Uses = [LR,SP] in
1744class AuthReturn<bits<3> op, bits<1> M, string asm>
1745  : AuthBase<M, (outs), (ins), asm, "", []> {
1746  let Inst{24} = 0;
1747  let Inst{23-21} = op;
1748  let Inst{9-0} = 0b1111111111;
1749}
1750
1751let mayLoad = 1 in
1752class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1753                   string operands, string cstr>
1754  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1755  bits<10> offset;
1756  bits<5> Rn;
1757  bits<5> Rt;
1758  let isAuthenticated = 1;
1759  let Inst{31-24} = 0b11111000;
1760  let Inst{23} = M;
1761  let Inst{22} = offset{9};
1762  let Inst{21} = 1;
1763  let Inst{20-12} = offset{8-0};
1764  let Inst{11} = W;
1765  let Inst{10} = 1;
1766  let Inst{9-5} = Rn;
1767  let Inst{4-0} = Rt;
1768
1769  let DecoderMethod = "DecodeAuthLoadInstruction";
1770}
1771
1772multiclass AuthLoad<bit M, string asm, Operand opr> {
1773  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1774                               (ins GPR64sp:$Rn, opr:$offset),
1775                               asm, "\t$Rt, [$Rn, $offset]", "">;
1776  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1777                               (ins GPR64sp:$Rn, opr:$offset),
1778                               asm, "\t$Rt, [$Rn, $offset]!",
1779                               "$Rn = $wback,@earlyclobber $wback">;
1780
1781  def : InstAlias<asm # "\t$Rt, [$Rn]",
1782                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1783
1784  def : InstAlias<asm # "\t$Rt, [$wback]!",
1785                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1786}
1787
1788//---
1789// Conditional branch instruction.
1790//---
1791
1792// Condition code.
1793// 4-bit immediate. Pretty-printed as <cc>
1794def ccode : Operand<i32> {
1795  let PrintMethod = "printCondCode";
1796  let ParserMatchClass = CondCode;
1797}
1798def inv_ccode : Operand<i32> {
1799  // AL and NV are invalid in the aliases which use inv_ccode
1800  let PrintMethod = "printInverseCondCode";
1801  let ParserMatchClass = CondCode;
1802  let MCOperandPredicate = [{
1803    return MCOp.isImm() &&
1804           MCOp.getImm() != AArch64CC::AL &&
1805           MCOp.getImm() != AArch64CC::NV;
1806  }];
1807}
1808
1809// Conditional branch target. 19-bit immediate. The low two bits of the target
1810// offset are implied zero and so are not part of the immediate.
1811def am_brcond : Operand<OtherVT> {
1812  let EncoderMethod = "getCondBranchTargetOpValue";
1813  let DecoderMethod = "DecodePCRelLabel19";
1814  let PrintMethod = "printAlignedLabel";
1815  let ParserMatchClass = PCRelLabel19Operand;
1816  let OperandType = "OPERAND_PCREL";
1817}
1818
1819class BranchCond<bit bit4, string mnemonic>
1820   : I<(outs), (ins ccode:$cond, am_brcond:$target),
1821       mnemonic, ".$cond\t$target", "",
1822       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
1823  let isBranch = 1;
1824  let isTerminator = 1;
1825  let Uses = [NZCV];
1826
1827  bits<4> cond;
1828  bits<19> target;
1829  let Inst{31-24} = 0b01010100;
1830  let Inst{23-5} = target;
1831  let Inst{4} = bit4;
1832  let Inst{3-0} = cond;
1833}
1834
1835//---
1836// Compare-and-branch instructions.
1837//---
1838class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1839    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1840         asm, "\t$Rt, $target", "",
1841         [(node regtype:$Rt, bb:$target)]>,
1842      Sched<[WriteBr]> {
1843  let isBranch = 1;
1844  let isTerminator = 1;
1845
1846  bits<5> Rt;
1847  bits<19> target;
1848  let Inst{30-25} = 0b011010;
1849  let Inst{24}    = op;
1850  let Inst{23-5}  = target;
1851  let Inst{4-0}   = Rt;
1852}
1853
1854multiclass CmpBranch<bit op, string asm, SDNode node> {
1855  def W : BaseCmpBranch<GPR32, op, asm, node> {
1856    let Inst{31} = 0;
1857  }
1858  def X : BaseCmpBranch<GPR64, op, asm, node> {
1859    let Inst{31} = 1;
1860  }
1861}
1862
1863//---
1864// Test-bit-and-branch instructions.
1865//---
1866// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1867// the target offset are implied zero and so are not part of the immediate.
1868def am_tbrcond : Operand<OtherVT> {
1869  let EncoderMethod = "getTestBranchTargetOpValue";
1870  let PrintMethod = "printAlignedLabel";
1871  let ParserMatchClass = BranchTarget14Operand;
1872  let OperandType = "OPERAND_PCREL";
1873}
1874
1875// AsmOperand classes to emit (or not) special diagnostics
1876def TBZImm0_31Operand : AsmOperandClass {
1877  let Name = "TBZImm0_31";
1878  let PredicateMethod = "isImmInRange<0,31>";
1879  let RenderMethod = "addImmOperands";
1880}
1881def TBZImm32_63Operand : AsmOperandClass {
1882  let Name = "Imm32_63";
1883  let PredicateMethod = "isImmInRange<32,63>";
1884  let DiagnosticType = "InvalidImm0_63";
1885  let RenderMethod = "addImmOperands";
1886}
1887
1888class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1889  return (((uint32_t)Imm) < 32);
1890}]> {
1891  let ParserMatchClass = matcher;
1892}
1893
1894def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1895def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1896
1897def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1898  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1899}]> {
1900  let ParserMatchClass = TBZImm32_63Operand;
1901}
1902
1903class BaseTestBranch<RegisterClass regtype, Operand immtype,
1904                     bit op, string asm, SDNode node>
1905    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1906       asm, "\t$Rt, $bit_off, $target", "",
1907       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1908      Sched<[WriteBr]> {
1909  let isBranch = 1;
1910  let isTerminator = 1;
1911
1912  bits<5> Rt;
1913  bits<6> bit_off;
1914  bits<14> target;
1915
1916  let Inst{30-25} = 0b011011;
1917  let Inst{24}    = op;
1918  let Inst{23-19} = bit_off{4-0};
1919  let Inst{18-5}  = target;
1920  let Inst{4-0}   = Rt;
1921
1922  let DecoderMethod = "DecodeTestAndBranch";
1923}
1924
1925multiclass TestBranch<bit op, string asm, SDNode node> {
1926  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1927    let Inst{31} = 0;
1928  }
1929
1930  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1931    let Inst{31} = 1;
1932  }
1933
1934  // Alias X-reg with 0-31 imm to W-Reg.
1935  def : InstAlias<asm # "\t$Rd, $imm, $target",
1936                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1937                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1938  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1939            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1940            tbz_imm0_31_diag:$imm, bb:$target)>;
1941}
1942
1943//---
1944// Unconditional branch (immediate) instructions.
1945//---
1946def am_b_target : Operand<OtherVT> {
1947  let EncoderMethod = "getBranchTargetOpValue";
1948  let PrintMethod = "printAlignedLabel";
1949  let ParserMatchClass = BranchTarget26Operand;
1950  let OperandType = "OPERAND_PCREL";
1951}
1952def am_bl_target : Operand<i64> {
1953  let EncoderMethod = "getBranchTargetOpValue";
1954  let PrintMethod = "printAlignedLabel";
1955  let ParserMatchClass = BranchTarget26Operand;
1956  let OperandType = "OPERAND_PCREL";
1957}
1958
1959class BImm<bit op, dag iops, string asm, list<dag> pattern>
1960    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1961  bits<26> addr;
1962  let Inst{31}    = op;
1963  let Inst{30-26} = 0b00101;
1964  let Inst{25-0}  = addr;
1965
1966  let DecoderMethod = "DecodeUnconditionalBranch";
1967}
1968
1969class BranchImm<bit op, string asm, list<dag> pattern>
1970    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1971class CallImm<bit op, string asm, list<dag> pattern>
1972    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1973
1974//---
1975// Basic one-operand data processing instructions.
1976//---
1977
1978let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1979class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1980                         SDPatternOperator node>
1981  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1982      [(set regtype:$Rd, (node regtype:$Rn))]>,
1983    Sched<[WriteI, ReadI]> {
1984  bits<5> Rd;
1985  bits<5> Rn;
1986
1987  let Inst{30-13} = 0b101101011000000000;
1988  let Inst{12-10} = opc;
1989  let Inst{9-5}   = Rn;
1990  let Inst{4-0}   = Rd;
1991}
1992
1993let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1994multiclass OneOperandData<bits<3> opc, string asm,
1995                          SDPatternOperator node = null_frag> {
1996  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1997    let Inst{31} = 0;
1998  }
1999
2000  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
2001    let Inst{31} = 1;
2002  }
2003}
2004
2005class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
2006    : BaseOneOperandData<opc, GPR32, asm, node> {
2007  let Inst{31} = 0;
2008}
2009
2010class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
2011    : BaseOneOperandData<opc, GPR64, asm, node> {
2012  let Inst{31} = 1;
2013}
2014
2015class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2016                      SDPatternOperator op>
2017  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2018      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2019    Sched<[WriteI, ReadI]> {
2020  bits<5> Rd;
2021  bits<5> Rn;
2022  let Inst{31-15} = 0b11011010110000010;
2023  let Inst{14-12} = opcode_prefix;
2024  let Inst{11-10} = opcode;
2025  let Inst{9-5} = Rn;
2026  let Inst{4-0} = Rd;
2027}
2028
2029class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2030                   SDPatternOperator op>
2031  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2032      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2033    Sched<[]> {
2034  bits<5> Rd;
2035  let Inst{31-15} = 0b11011010110000010;
2036  let Inst{14-12} = opcode_prefix;
2037  let Inst{11-10} = opcode;
2038  let Inst{9-5} = 0b11111;
2039  let Inst{4-0} = Rd;
2040}
2041
2042class SignAuthTwoOperand<bits<4> opc, string asm,
2043                         SDPatternOperator OpNode>
2044  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2045      asm, "\t$Rd, $Rn, $Rm", "",
2046      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2047    Sched<[WriteI, ReadI, ReadI]> {
2048  bits<5> Rd;
2049  bits<5> Rn;
2050  bits<5> Rm;
2051  let Inst{31-21} = 0b10011010110;
2052  let Inst{20-16} = Rm;
2053  let Inst{15-14} = 0b00;
2054  let Inst{13-10} = opc;
2055  let Inst{9-5}   = Rn;
2056  let Inst{4-0}   = Rd;
2057}
2058
2059class ClearAuth<bits<1> data, string asm>
2060  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2061  bits<5> Rd;
2062  let Inst{31-11} = 0b110110101100000101000;
2063  let Inst{10} = data;
2064  let Inst{9-5} = 0b11111;
2065  let Inst{4-0} = Rd;
2066}
2067
2068// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2069class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2070    : I<(outs), iops, asm, ops, "", []>,
2071      Sched<[WriteI, ReadI, ReadI]> {
2072  let Uses = [NZCV];
2073  let Defs = [NZCV];
2074  bits<5> Rn;
2075  let Inst{31}    = sf;
2076  let Inst{30-15} = 0b0111010000000000;
2077  let Inst{14}    = sz;
2078  let Inst{13-10} = 0b0010;
2079  let Inst{9-5}   = Rn;
2080  let Inst{4-0}   = 0b01101;
2081}
2082
2083class FlagRotate<dag iops, string asm, string ops>
2084    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2085  bits<6> imm;
2086  bits<4> mask;
2087  let Inst{20-15} = imm;
2088  let Inst{13-10} = 0b0001;
2089  let Inst{4}     = 0b0;
2090  let Inst{3-0}   = mask;
2091}
2092
2093//---
2094// Basic two-operand data processing instructions.
2095//---
2096class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2097                          list<dag> pattern>
2098    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2099        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2100      Sched<[WriteI, ReadI, ReadI]> {
2101  let Uses = [NZCV];
2102  bits<5> Rd;
2103  bits<5> Rn;
2104  bits<5> Rm;
2105  let Inst{30}    = isSub;
2106  let Inst{28-21} = 0b11010000;
2107  let Inst{20-16} = Rm;
2108  let Inst{15-10} = 0;
2109  let Inst{9-5}   = Rn;
2110  let Inst{4-0}   = Rd;
2111}
2112
2113class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2114                      SDNode OpNode>
2115    : BaseBaseAddSubCarry<isSub, regtype, asm,
2116        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2117
2118class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2119                              SDNode OpNode>
2120    : BaseBaseAddSubCarry<isSub, regtype, asm,
2121        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2122         (implicit NZCV)]> {
2123  let Defs = [NZCV];
2124}
2125
2126multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2127                       SDNode OpNode, SDNode OpNode_setflags> {
2128  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2129    let Inst{31} = 0;
2130    let Inst{29} = 0;
2131  }
2132  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2133    let Inst{31} = 1;
2134    let Inst{29} = 0;
2135  }
2136
2137  // Sets flags.
2138  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2139                                    OpNode_setflags> {
2140    let Inst{31} = 0;
2141    let Inst{29} = 1;
2142  }
2143  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2144                                    OpNode_setflags> {
2145    let Inst{31} = 1;
2146    let Inst{29} = 1;
2147  }
2148}
2149
2150class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2151                     SDPatternOperator OpNode,
2152                     RegisterClass in1regtype = regtype,
2153                     RegisterClass in2regtype = regtype>
2154  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2155      asm, "\t$Rd, $Rn, $Rm", "",
2156      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2157  bits<5> Rd;
2158  bits<5> Rn;
2159  bits<5> Rm;
2160  let Inst{30-21} = 0b0011010110;
2161  let Inst{20-16} = Rm;
2162  let Inst{15-14} = 0b00;
2163  let Inst{13-10} = opc;
2164  let Inst{9-5}   = Rn;
2165  let Inst{4-0}   = Rd;
2166}
2167
2168class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2169              SDPatternOperator OpNode>
2170    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2171  let Inst{10}    = isSigned;
2172}
2173
2174multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2175  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2176           Sched<[WriteID32, ReadID, ReadID]> {
2177    let Inst{31} = 0;
2178  }
2179  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2180           Sched<[WriteID64, ReadID, ReadID]> {
2181    let Inst{31} = 1;
2182  }
2183}
2184
2185class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2186                SDPatternOperator OpNode = null_frag>
2187  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2188    Sched<[WriteIS, ReadI]> {
2189  let Inst{11-10} = shift_type;
2190}
2191
2192multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2193  def Wr : BaseShift<shift_type, GPR32, asm> {
2194    let Inst{31} = 0;
2195  }
2196
2197  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2198    let Inst{31} = 1;
2199  }
2200
2201  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2202            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2203                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2204
2205  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2206            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2207
2208  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2209            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2210
2211  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2212            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2213
2214  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2215            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2216                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2217
2218  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2219            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2220                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2221}
2222
2223class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2224    : InstAlias<asm#"\t$dst, $src1, $src2",
2225                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2226
2227class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2228                       RegisterClass addtype, string asm,
2229                       list<dag> pattern>
2230  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2231      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2232  bits<5> Rd;
2233  bits<5> Rn;
2234  bits<5> Rm;
2235  bits<5> Ra;
2236  let Inst{30-24} = 0b0011011;
2237  let Inst{23-21} = opc;
2238  let Inst{20-16} = Rm;
2239  let Inst{15}    = isSub;
2240  let Inst{14-10} = Ra;
2241  let Inst{9-5}   = Rn;
2242  let Inst{4-0}   = Rd;
2243}
2244
2245multiclass MulAccum<bit isSub, string asm> {
2246  // MADD/MSUB generation is decided by MachineCombiner.cpp
2247  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2248      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2249    let Inst{31} = 0;
2250  }
2251
2252  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2253      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2254    let Inst{31} = 1;
2255  }
2256}
2257
2258class WideMulAccum<bit isSub, bits<3> opc, string asm,
2259                   SDNode AccNode, SDNode ExtNode>
2260  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2261    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2262                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2263    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2264  let Inst{31} = 1;
2265}
2266
2267class MulHi<bits<3> opc, string asm, SDNode OpNode>
2268  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2269      asm, "\t$Rd, $Rn, $Rm", "",
2270      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2271    Sched<[WriteIM64, ReadIM, ReadIM]> {
2272  bits<5> Rd;
2273  bits<5> Rn;
2274  bits<5> Rm;
2275  let Inst{31-24} = 0b10011011;
2276  let Inst{23-21} = opc;
2277  let Inst{20-16} = Rm;
2278  let Inst{15}    = 0;
2279  let Inst{9-5}   = Rn;
2280  let Inst{4-0}   = Rd;
2281
2282  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2283  // (i.e. all bits 1) but is ignored by the processor.
2284  let PostEncoderMethod = "fixMulHigh";
2285}
2286
2287class MulAccumWAlias<string asm, Instruction inst>
2288    : InstAlias<asm#"\t$dst, $src1, $src2",
2289                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2290class MulAccumXAlias<string asm, Instruction inst>
2291    : InstAlias<asm#"\t$dst, $src1, $src2",
2292                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2293class WideMulAccumAlias<string asm, Instruction inst>
2294    : InstAlias<asm#"\t$dst, $src1, $src2",
2295                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2296
2297class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2298              SDPatternOperator OpNode, string asm>
2299  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2300      asm, "\t$Rd, $Rn, $Rm", "",
2301      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2302    Sched<[WriteISReg, ReadI, ReadISReg]> {
2303  bits<5> Rd;
2304  bits<5> Rn;
2305  bits<5> Rm;
2306
2307  let Inst{31} = sf;
2308  let Inst{30-21} = 0b0011010110;
2309  let Inst{20-16} = Rm;
2310  let Inst{15-13} = 0b010;
2311  let Inst{12} = C;
2312  let Inst{11-10} = sz;
2313  let Inst{9-5} = Rn;
2314  let Inst{4-0} = Rd;
2315  let Predicates = [HasCRC];
2316}
2317
2318//---
2319// Address generation.
2320//---
2321
2322class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2323    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2324        pattern>,
2325      Sched<[WriteI]> {
2326  bits<5>  Xd;
2327  bits<21> label;
2328  let Inst{31}    = page;
2329  let Inst{30-29} = label{1-0};
2330  let Inst{28-24} = 0b10000;
2331  let Inst{23-5}  = label{20-2};
2332  let Inst{4-0}   = Xd;
2333
2334  let DecoderMethod = "DecodeAdrInstruction";
2335}
2336
2337//---
2338// Move immediate.
2339//---
2340
2341def movimm32_imm : Operand<i32> {
2342  let ParserMatchClass = AsmImmRange<0, 65535>;
2343  let EncoderMethod = "getMoveWideImmOpValue";
2344  let PrintMethod = "printImm";
2345}
2346def movimm32_shift : Operand<i32> {
2347  let PrintMethod = "printShifter";
2348  let ParserMatchClass = MovImm32ShifterOperand;
2349}
2350def movimm64_shift : Operand<i32> {
2351  let PrintMethod = "printShifter";
2352  let ParserMatchClass = MovImm64ShifterOperand;
2353}
2354
2355let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2356class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2357                        string asm>
2358  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2359       asm, "\t$Rd, $imm$shift", "", []>,
2360    Sched<[WriteImm]> {
2361  bits<5> Rd;
2362  bits<16> imm;
2363  bits<6> shift;
2364  let Inst{30-29} = opc;
2365  let Inst{28-23} = 0b100101;
2366  let Inst{22-21} = shift{5-4};
2367  let Inst{20-5}  = imm;
2368  let Inst{4-0}   = Rd;
2369
2370  let DecoderMethod = "DecodeMoveImmInstruction";
2371}
2372
2373multiclass MoveImmediate<bits<2> opc, string asm> {
2374  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2375    let Inst{31} = 0;
2376  }
2377
2378  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2379    let Inst{31} = 1;
2380  }
2381}
2382
2383let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2384class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2385                          string asm>
2386  : I<(outs regtype:$Rd),
2387      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2388       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2389    Sched<[WriteI, ReadI]> {
2390  bits<5> Rd;
2391  bits<16> imm;
2392  bits<6> shift;
2393  let Inst{30-29} = opc;
2394  let Inst{28-23} = 0b100101;
2395  let Inst{22-21} = shift{5-4};
2396  let Inst{20-5}  = imm;
2397  let Inst{4-0}   = Rd;
2398
2399  let DecoderMethod = "DecodeMoveImmInstruction";
2400}
2401
2402multiclass InsertImmediate<bits<2> opc, string asm> {
2403  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2404    let Inst{31} = 0;
2405  }
2406
2407  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2408    let Inst{31} = 1;
2409  }
2410}
2411
2412//---
2413// Add/Subtract
2414//---
2415
2416class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2417                    string asm_inst, string asm_ops,
2418                    dag inputs, dag pattern>
2419    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2420      Sched<[WriteI, ReadI]> {
2421  bits<5>  Rd;
2422  bits<5>  Rn;
2423  let Inst{30}    = isSub;
2424  let Inst{29}    = setFlags;
2425  let Inst{28-24} = 0b10001;
2426  let Inst{9-5}   = Rn;
2427  let Inst{4-0}   = Rd;
2428}
2429
2430class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2431                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2432                     string asm_inst, SDPatternOperator OpNode>
2433    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2434                    (ins srcRegtype:$Rn, immtype:$imm),
2435                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2436  bits<14> imm;
2437  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2438  let Inst{21-10} = imm{11-0};
2439  let DecoderMethod = "DecodeAddSubImmShift";
2440}
2441
2442class BaseAddSubRegPseudo<RegisterClass regtype,
2443                          SDPatternOperator OpNode>
2444    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2445             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2446      Sched<[WriteI, ReadI, ReadI]>;
2447
2448class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2449                     arith_shifted_reg shifted_regtype, string asm,
2450                     SDPatternOperator OpNode>
2451    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2452        asm, "\t$Rd, $Rn, $Rm", "",
2453        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2454      Sched<[WriteISReg, ReadI, ReadISReg]> {
2455  // The operands are in order to match the 'addr' MI operands, so we
2456  // don't need an encoder method and by-name matching. Just use the default
2457  // in-order handling. Since we're using by-order, make sure the names
2458  // do not match.
2459  bits<5> dst;
2460  bits<5> src1;
2461  bits<5> src2;
2462  bits<8> shift;
2463  let Inst{30}    = isSub;
2464  let Inst{29}    = setFlags;
2465  let Inst{28-24} = 0b01011;
2466  let Inst{23-22} = shift{7-6};
2467  let Inst{21}    = 0;
2468  let Inst{20-16} = src2;
2469  let Inst{15-10} = shift{5-0};
2470  let Inst{9-5}   = src1;
2471  let Inst{4-0}   = dst;
2472
2473  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2474}
2475
2476class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2477                     RegisterClass src1Regtype, Operand src2Regtype,
2478                     string asm, SDPatternOperator OpNode>
2479    : I<(outs dstRegtype:$R1),
2480        (ins src1Regtype:$R2, src2Regtype:$R3),
2481        asm, "\t$R1, $R2, $R3", "",
2482        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2483      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2484  bits<5> Rd;
2485  bits<5> Rn;
2486  bits<5> Rm;
2487  bits<6> ext;
2488  let Inst{30}    = isSub;
2489  let Inst{29}    = setFlags;
2490  let Inst{28-24} = 0b01011;
2491  let Inst{23-21} = 0b001;
2492  let Inst{20-16} = Rm;
2493  let Inst{15-13} = ext{5-3};
2494  let Inst{12-10} = ext{2-0};
2495  let Inst{9-5}   = Rn;
2496  let Inst{4-0}   = Rd;
2497
2498  let DecoderMethod = "DecodeAddSubERegInstruction";
2499}
2500
2501let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2502class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2503                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2504                       Operand ext_op, string asm>
2505    : I<(outs dstRegtype:$Rd),
2506        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2507        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2508      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2509  bits<5> Rd;
2510  bits<5> Rn;
2511  bits<5> Rm;
2512  bits<6> ext;
2513  let Inst{30}    = isSub;
2514  let Inst{29}    = setFlags;
2515  let Inst{28-24} = 0b01011;
2516  let Inst{23-21} = 0b001;
2517  let Inst{20-16} = Rm;
2518  let Inst{15}    = ext{5};
2519  let Inst{12-10} = ext{2-0};
2520  let Inst{9-5}   = Rn;
2521  let Inst{4-0}   = Rd;
2522
2523  let DecoderMethod = "DecodeAddSubERegInstruction";
2524}
2525
2526// Aliases for register+register add/subtract.
2527class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2528                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2529                     int shiftExt>
2530    : InstAlias<asm#"\t$dst, $src1, $src2",
2531                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2532                      shiftExt)>;
2533
2534multiclass AddSub<bit isSub, string mnemonic, string alias,
2535                  SDPatternOperator OpNode = null_frag> {
2536  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2537  // Add/Subtract immediate
2538  // Increase the weight of the immediate variant to try to match it before
2539  // the extended register variant.
2540  // We used to match the register variant before the immediate when the
2541  // register argument could be implicitly zero-extended.
2542  let AddedComplexity = 6 in
2543  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2544                           mnemonic, OpNode> {
2545    let Inst{31} = 0;
2546  }
2547  let AddedComplexity = 6 in
2548  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2549                           mnemonic, OpNode> {
2550    let Inst{31} = 1;
2551  }
2552
2553  // Add/Subtract register - Only used for CodeGen
2554  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2555  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2556
2557  // Add/Subtract shifted register
2558  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2559                           OpNode> {
2560    let Inst{31} = 0;
2561  }
2562  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2563                           OpNode> {
2564    let Inst{31} = 1;
2565  }
2566  }
2567
2568  // Add/Subtract extended register
2569  let AddedComplexity = 1, hasSideEffects = 0 in {
2570  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2571                           arith_extended_reg32_i32, mnemonic, OpNode> {
2572    let Inst{31} = 0;
2573  }
2574  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2575                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2576    let Inst{31} = 1;
2577  }
2578  }
2579
2580  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2581                               arith_extendlsl64, mnemonic> {
2582    // UXTX and SXTX only.
2583    let Inst{14-13} = 0b11;
2584    let Inst{31} = 1;
2585  }
2586
2587  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2588  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2589                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2590                      addsub_shifted_imm32_neg:$imm), 0>;
2591  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2592                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2593                       addsub_shifted_imm64_neg:$imm), 0>;
2594
2595  // Register/register aliases with no shift when SP is not used.
2596  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2597                       GPR32, GPR32, GPR32, 0>;
2598  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2599                       GPR64, GPR64, GPR64, 0>;
2600
2601  // Register/register aliases with no shift when either the destination or
2602  // first source register is SP.
2603  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2604                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2605  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2606                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2607  def : AddSubRegAlias<mnemonic,
2608                       !cast<Instruction>(NAME#"Xrx64"),
2609                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2610  def : AddSubRegAlias<mnemonic,
2611                       !cast<Instruction>(NAME#"Xrx64"),
2612                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2613}
2614
2615multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2616                   string alias, string cmpAlias> {
2617  let isCompare = 1, Defs = [NZCV] in {
2618  // Add/Subtract immediate
2619  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2620                           mnemonic, OpNode> {
2621    let Inst{31} = 0;
2622  }
2623  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2624                           mnemonic, OpNode> {
2625    let Inst{31} = 1;
2626  }
2627
2628  // Add/Subtract register
2629  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2630  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2631
2632  // Add/Subtract shifted register
2633  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2634                           OpNode> {
2635    let Inst{31} = 0;
2636  }
2637  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2638                           OpNode> {
2639    let Inst{31} = 1;
2640  }
2641
2642  // Add/Subtract extended register
2643  let AddedComplexity = 1 in {
2644  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2645                           arith_extended_reg32_i32, mnemonic, OpNode> {
2646    let Inst{31} = 0;
2647  }
2648  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2649                           arith_extended_reg32_i64, mnemonic, OpNode> {
2650    let Inst{31} = 1;
2651  }
2652  }
2653
2654  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2655                               arith_extendlsl64, mnemonic> {
2656    // UXTX and SXTX only.
2657    let Inst{14-13} = 0b11;
2658    let Inst{31} = 1;
2659  }
2660  } // Defs = [NZCV]
2661
2662  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2663  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2664                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2665                      addsub_shifted_imm32_neg:$imm), 0>;
2666  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2667                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2668                       addsub_shifted_imm64_neg:$imm), 0>;
2669
2670  // Compare aliases
2671  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2672                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2673  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2674                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2675  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2676                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2677  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2678                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2679  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2680                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2681  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2682                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2683  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2684                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2685
2686  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2687  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2688                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2689  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2690                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2691
2692  // Compare shorthands
2693  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2694                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2695  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2696                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2697  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2698                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2699  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2700                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2701
2702  // Register/register aliases with no shift when SP is not used.
2703  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2704                       GPR32, GPR32, GPR32, 0>;
2705  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2706                       GPR64, GPR64, GPR64, 0>;
2707
2708  // Register/register aliases with no shift when the first source register
2709  // is SP.
2710  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2711                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2712  def : AddSubRegAlias<mnemonic,
2713                       !cast<Instruction>(NAME#"Xrx64"),
2714                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2715}
2716
2717class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2718      : BaseAddSubImm<
2719          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2720          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2721          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2722  bits<6> imm6;
2723  bits<4> imm4;
2724  let Inst{31} = 1;
2725  let Inst{23-22} = 0b10;
2726  let Inst{21-16} = imm6;
2727  let Inst{15-14} = 0b00;
2728  let Inst{13-10} = imm4;
2729  let Unpredictable{15-14} = 0b11;
2730}
2731
2732class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2733      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2734  let Inst{31} = 1;
2735  let Inst{29} = setsFlags;
2736}
2737
2738//---
2739// Extract
2740//---
2741def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2742                                      SDTCisPtrTy<3>]>;
2743def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2744
2745class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2746                     list<dag> patterns>
2747    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2748         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2749      Sched<[WriteExtr, ReadExtrHi]> {
2750  bits<5> Rd;
2751  bits<5> Rn;
2752  bits<5> Rm;
2753  bits<6> imm;
2754
2755  let Inst{30-23} = 0b00100111;
2756  let Inst{21}    = 0;
2757  let Inst{20-16} = Rm;
2758  let Inst{15-10} = imm;
2759  let Inst{9-5}   = Rn;
2760  let Inst{4-0}   = Rd;
2761}
2762
2763multiclass ExtractImm<string asm> {
2764  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2765                      [(set GPR32:$Rd,
2766                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2767    let Inst{31} = 0;
2768    let Inst{22} = 0;
2769    // imm<5> must be zero.
2770    let imm{5}   = 0;
2771  }
2772  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2773                      [(set GPR64:$Rd,
2774                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2775
2776    let Inst{31} = 1;
2777    let Inst{22} = 1;
2778  }
2779}
2780
2781//---
2782// Bitfield
2783//---
2784
2785let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2786class BaseBitfieldImm<bits<2> opc,
2787                      RegisterClass regtype, Operand imm_type, string asm>
2788    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2789         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2790      Sched<[WriteIS, ReadI]> {
2791  bits<5> Rd;
2792  bits<5> Rn;
2793  bits<6> immr;
2794  bits<6> imms;
2795
2796  let Inst{30-29} = opc;
2797  let Inst{28-23} = 0b100110;
2798  let Inst{21-16} = immr;
2799  let Inst{15-10} = imms;
2800  let Inst{9-5}   = Rn;
2801  let Inst{4-0}   = Rd;
2802}
2803
2804multiclass BitfieldImm<bits<2> opc, string asm> {
2805  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2806    let Inst{31} = 0;
2807    let Inst{22} = 0;
2808    // imms<5> and immr<5> must be zero, else ReservedValue().
2809    let Inst{21} = 0;
2810    let Inst{15} = 0;
2811  }
2812  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2813    let Inst{31} = 1;
2814    let Inst{22} = 1;
2815  }
2816}
2817
2818let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2819class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2820                      RegisterClass regtype, Operand imm_type, string asm>
2821    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2822                             imm_type:$imms),
2823         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2824      Sched<[WriteIS, ReadI]> {
2825  bits<5> Rd;
2826  bits<5> Rn;
2827  bits<6> immr;
2828  bits<6> imms;
2829
2830  let Inst{30-29} = opc;
2831  let Inst{28-23} = 0b100110;
2832  let Inst{21-16} = immr;
2833  let Inst{15-10} = imms;
2834  let Inst{9-5}   = Rn;
2835  let Inst{4-0}   = Rd;
2836}
2837
2838multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2839  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2840    let Inst{31} = 0;
2841    let Inst{22} = 0;
2842    // imms<5> and immr<5> must be zero, else ReservedValue().
2843    let Inst{21} = 0;
2844    let Inst{15} = 0;
2845  }
2846  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2847    let Inst{31} = 1;
2848    let Inst{22} = 1;
2849  }
2850}
2851
2852//---
2853// Logical
2854//---
2855
2856// Logical (immediate)
2857class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2858                     RegisterClass sregtype, Operand imm_type, string asm,
2859                     list<dag> pattern>
2860    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2861         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2862      Sched<[WriteI, ReadI]> {
2863  bits<5>  Rd;
2864  bits<5>  Rn;
2865  bits<13> imm;
2866  let Inst{30-29} = opc;
2867  let Inst{28-23} = 0b100100;
2868  let Inst{22}    = imm{12};
2869  let Inst{21-16} = imm{11-6};
2870  let Inst{15-10} = imm{5-0};
2871  let Inst{9-5}   = Rn;
2872  let Inst{4-0}   = Rd;
2873
2874  let DecoderMethod = "DecodeLogicalImmInstruction";
2875}
2876
2877// Logical (shifted register)
2878class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2879                      logical_shifted_reg shifted_regtype, string asm,
2880                      list<dag> pattern>
2881    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2882        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2883      Sched<[WriteISReg, ReadI, ReadISReg]> {
2884  // The operands are in order to match the 'addr' MI operands, so we
2885  // don't need an encoder method and by-name matching. Just use the default
2886  // in-order handling. Since we're using by-order, make sure the names
2887  // do not match.
2888  bits<5> dst;
2889  bits<5> src1;
2890  bits<5> src2;
2891  bits<8> shift;
2892  let Inst{30-29} = opc;
2893  let Inst{28-24} = 0b01010;
2894  let Inst{23-22} = shift{7-6};
2895  let Inst{21}    = N;
2896  let Inst{20-16} = src2;
2897  let Inst{15-10} = shift{5-0};
2898  let Inst{9-5}   = src1;
2899  let Inst{4-0}   = dst;
2900
2901  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2902}
2903
2904// Aliases for register+register logical instructions.
2905class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2906    : InstAlias<asm#"\t$dst, $src1, $src2",
2907                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2908
2909multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2910                      string Alias> {
2911  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2912  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2913                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2914                                               logical_imm32:$imm))]> {
2915    let Inst{31} = 0;
2916    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2917  }
2918  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2919  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2920                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2921                                               logical_imm64:$imm))]> {
2922    let Inst{31} = 1;
2923  }
2924
2925  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2926                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2927                      logical_imm32_not:$imm), 0>;
2928  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2929                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2930                       logical_imm64_not:$imm), 0>;
2931}
2932
2933multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2934                       string Alias> {
2935  let isCompare = 1, Defs = [NZCV] in {
2936  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2937      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2938    let Inst{31} = 0;
2939    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2940  }
2941  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2942      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2943    let Inst{31} = 1;
2944  }
2945  } // end Defs = [NZCV]
2946
2947  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2948                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2949                      logical_imm32_not:$imm), 0>;
2950  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2951                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2952                       logical_imm64_not:$imm), 0>;
2953}
2954
2955class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2956    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2957             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2958      Sched<[WriteI, ReadI, ReadI]>;
2959
2960// Split from LogicalImm as not all instructions have both.
2961multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2962                      SDPatternOperator OpNode> {
2963  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2964  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2965  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2966  }
2967
2968  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2969                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2970                                                 logical_shifted_reg32:$Rm))]> {
2971    let Inst{31} = 0;
2972  }
2973  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2974                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2975                                                 logical_shifted_reg64:$Rm))]> {
2976    let Inst{31} = 1;
2977  }
2978
2979  def : LogicalRegAlias<mnemonic,
2980                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2981  def : LogicalRegAlias<mnemonic,
2982                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2983}
2984
2985// Split from LogicalReg to allow setting NZCV Defs
2986multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2987                       SDPatternOperator OpNode = null_frag> {
2988  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2989  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2990  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2991
2992  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2993            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2994    let Inst{31} = 0;
2995  }
2996  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2997            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2998    let Inst{31} = 1;
2999  }
3000  } // Defs = [NZCV]
3001
3002  def : LogicalRegAlias<mnemonic,
3003                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3004  def : LogicalRegAlias<mnemonic,
3005                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3006}
3007
3008//---
3009// Conditionally set flags
3010//---
3011
3012let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3013class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3014                            string mnemonic, SDNode OpNode>
3015    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3016         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3017         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3018                             (i32 imm:$cond), NZCV))]>,
3019      Sched<[WriteI, ReadI]> {
3020  let Uses = [NZCV];
3021  let Defs = [NZCV];
3022
3023  bits<5> Rn;
3024  bits<5> imm;
3025  bits<4> nzcv;
3026  bits<4> cond;
3027
3028  let Inst{30}    = op;
3029  let Inst{29-21} = 0b111010010;
3030  let Inst{20-16} = imm;
3031  let Inst{15-12} = cond;
3032  let Inst{11-10} = 0b10;
3033  let Inst{9-5}   = Rn;
3034  let Inst{4}     = 0b0;
3035  let Inst{3-0}   = nzcv;
3036}
3037
3038let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3039class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3040                            SDNode OpNode>
3041    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3042         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3043         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3044                             (i32 imm:$cond), NZCV))]>,
3045      Sched<[WriteI, ReadI, ReadI]> {
3046  let Uses = [NZCV];
3047  let Defs = [NZCV];
3048
3049  bits<5> Rn;
3050  bits<5> Rm;
3051  bits<4> nzcv;
3052  bits<4> cond;
3053
3054  let Inst{30}    = op;
3055  let Inst{29-21} = 0b111010010;
3056  let Inst{20-16} = Rm;
3057  let Inst{15-12} = cond;
3058  let Inst{11-10} = 0b00;
3059  let Inst{9-5}   = Rn;
3060  let Inst{4}     = 0b0;
3061  let Inst{3-0}   = nzcv;
3062}
3063
3064multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3065  // immediate operand variants
3066  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3067    let Inst{31} = 0;
3068  }
3069  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3070    let Inst{31} = 1;
3071  }
3072  // register operand variants
3073  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3074    let Inst{31} = 0;
3075  }
3076  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3077    let Inst{31} = 1;
3078  }
3079}
3080
3081//---
3082// Conditional select
3083//---
3084
3085class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3086    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3087         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3088         [(set regtype:$Rd,
3089               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3090      Sched<[WriteI, ReadI, ReadI]> {
3091  let Uses = [NZCV];
3092
3093  bits<5> Rd;
3094  bits<5> Rn;
3095  bits<5> Rm;
3096  bits<4> cond;
3097
3098  let Inst{30}    = op;
3099  let Inst{29-21} = 0b011010100;
3100  let Inst{20-16} = Rm;
3101  let Inst{15-12} = cond;
3102  let Inst{11-10} = op2;
3103  let Inst{9-5}   = Rn;
3104  let Inst{4-0}   = Rd;
3105}
3106
3107multiclass CondSelect<bit op, bits<2> op2, string asm> {
3108  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3109    let Inst{31} = 0;
3110  }
3111  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3112    let Inst{31} = 1;
3113  }
3114}
3115
3116class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3117                       PatFrag frag>
3118    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3119         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3120         [(set regtype:$Rd,
3121               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3122               (i32 imm:$cond), NZCV))]>,
3123      Sched<[WriteI, ReadI, ReadI]> {
3124  let Uses = [NZCV];
3125
3126  bits<5> Rd;
3127  bits<5> Rn;
3128  bits<5> Rm;
3129  bits<4> cond;
3130
3131  let Inst{30}    = op;
3132  let Inst{29-21} = 0b011010100;
3133  let Inst{20-16} = Rm;
3134  let Inst{15-12} = cond;
3135  let Inst{11-10} = op2;
3136  let Inst{9-5}   = Rn;
3137  let Inst{4-0}   = Rd;
3138}
3139
3140def inv_cond_XFORM : SDNodeXForm<imm, [{
3141  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3142  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3143                                   MVT::i32);
3144}]>;
3145
3146multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3147  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3148    let Inst{31} = 0;
3149  }
3150  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3151    let Inst{31} = 1;
3152  }
3153
3154  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3155            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3156                                           (inv_cond_XFORM imm:$cond))>;
3157
3158  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3159            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3160                                           (inv_cond_XFORM imm:$cond))>;
3161}
3162
3163//---
3164// Special Mask Value
3165//---
3166def maski8_or_more : Operand<i32>,
3167  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3168}
3169def maski16_or_more : Operand<i32>,
3170  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3171}
3172
3173
3174//---
3175// Load/store
3176//---
3177
3178// (unsigned immediate)
3179// Indexed for 8-bit registers. offset is in range [0,4095].
3180def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3181def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3182def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3183def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3184def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3185
3186// (unsigned immediate)
3187// Indexed for 8-bit registers. offset is in range [0,63].
3188def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3189def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3190def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3191def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3192
3193def gi_am_indexed8 :
3194    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3195    GIComplexPatternEquiv<am_indexed8>;
3196def gi_am_indexed16 :
3197    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3198    GIComplexPatternEquiv<am_indexed16>;
3199def gi_am_indexed32 :
3200    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3201    GIComplexPatternEquiv<am_indexed32>;
3202def gi_am_indexed64 :
3203    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3204    GIComplexPatternEquiv<am_indexed64>;
3205def gi_am_indexed128 :
3206    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3207    GIComplexPatternEquiv<am_indexed128>;
3208
3209class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3210  let Name = "UImm12Offset" # Scale;
3211  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3212  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3213  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3214}
3215
3216def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3217def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3218def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3219def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3220def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3221
3222class uimm12_scaled<int Scale> : Operand<i64> {
3223  let ParserMatchClass
3224   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3225  let EncoderMethod
3226   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3227  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3228}
3229
3230def uimm12s1 : uimm12_scaled<1>;
3231def uimm12s2 : uimm12_scaled<2>;
3232def uimm12s4 : uimm12_scaled<4>;
3233def uimm12s8 : uimm12_scaled<8>;
3234def uimm12s16 : uimm12_scaled<16>;
3235
3236class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3237                      string asm, list<dag> pattern>
3238    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3239  bits<5> Rt;
3240
3241  bits<5> Rn;
3242  bits<12> offset;
3243
3244  let Inst{31-30} = sz;
3245  let Inst{29-27} = 0b111;
3246  let Inst{26}    = V;
3247  let Inst{25-24} = 0b01;
3248  let Inst{23-22} = opc;
3249  let Inst{21-10} = offset;
3250  let Inst{9-5}   = Rn;
3251  let Inst{4-0}   = Rt;
3252
3253  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3254}
3255
3256multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3257                  Operand indextype, string asm, list<dag> pattern> {
3258  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3259  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3260                           (ins GPR64sp:$Rn, indextype:$offset),
3261                           asm, pattern>,
3262           Sched<[WriteLD]>;
3263
3264  def : InstAlias<asm # "\t$Rt, [$Rn]",
3265                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3266}
3267
3268multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3269             Operand indextype, string asm, list<dag> pattern> {
3270  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3271  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3272                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3273                           asm, pattern>,
3274           Sched<[WriteST]>;
3275
3276  def : InstAlias<asm # "\t$Rt, [$Rn]",
3277                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3278}
3279
3280// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3281// substitute zero-registers automatically.
3282//
3283// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3284//       into StoreUI.
3285multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3286             Operand indextype, string asm, list<dag> pattern> {
3287  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3288  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3289                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3290                           asm, pattern>,
3291           Sched<[WriteST]>;
3292
3293  def : InstAlias<asm # "\t$Rt, [$Rn]",
3294                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3295}
3296
3297def PrefetchOperand : AsmOperandClass {
3298  let Name = "Prefetch";
3299  let ParserMethod = "tryParsePrefetch";
3300}
3301def prfop : Operand<i32> {
3302  let PrintMethod = "printPrefetchOp";
3303  let ParserMatchClass = PrefetchOperand;
3304}
3305
3306let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3307class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3308    : BaseLoadStoreUI<sz, V, opc,
3309                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3310                      asm, pat>,
3311      Sched<[WriteLD]>;
3312
3313//---
3314// Load literal
3315//---
3316
3317// Load literal address: 19-bit immediate. The low two bits of the target
3318// offset are implied zero and so are not part of the immediate.
3319def am_ldrlit : Operand<iPTR> {
3320  let EncoderMethod = "getLoadLiteralOpValue";
3321  let DecoderMethod = "DecodePCRelLabel19";
3322  let PrintMethod = "printAlignedLabel";
3323  let ParserMatchClass = PCRelLabel19Operand;
3324  let OperandType = "OPERAND_PCREL";
3325}
3326
3327let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3328class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3329    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3330        asm, "\t$Rt, $label", "", pat>,
3331      Sched<[WriteLD]> {
3332  bits<5> Rt;
3333  bits<19> label;
3334  let Inst{31-30} = opc;
3335  let Inst{29-27} = 0b011;
3336  let Inst{26}    = V;
3337  let Inst{25-24} = 0b00;
3338  let Inst{23-5}  = label;
3339  let Inst{4-0}   = Rt;
3340}
3341
3342let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3343class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3344    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3345        asm, "\t$Rt, $label", "", pat>,
3346      Sched<[WriteLD]> {
3347  bits<5> Rt;
3348  bits<19> label;
3349  let Inst{31-30} = opc;
3350  let Inst{29-27} = 0b011;
3351  let Inst{26}    = V;
3352  let Inst{25-24} = 0b00;
3353  let Inst{23-5}  = label;
3354  let Inst{4-0}   = Rt;
3355}
3356
3357//---
3358// Load/store register offset
3359//---
3360
3361def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3362def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3363def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3364def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3365def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3366
3367def gi_ro_Xindexed8 :
3368    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3369    GIComplexPatternEquiv<ro_Xindexed8>;
3370def gi_ro_Xindexed16 :
3371    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3372    GIComplexPatternEquiv<ro_Xindexed16>;
3373def gi_ro_Xindexed32 :
3374    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3375    GIComplexPatternEquiv<ro_Xindexed32>;
3376def gi_ro_Xindexed64 :
3377    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3378    GIComplexPatternEquiv<ro_Xindexed64>;
3379def gi_ro_Xindexed128 :
3380    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3381    GIComplexPatternEquiv<ro_Xindexed128>;
3382
3383def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3384def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3385def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3386def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3387def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3388
3389def gi_ro_Windexed8 :
3390    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3391    GIComplexPatternEquiv<ro_Windexed8>;
3392def gi_ro_Windexed16 :
3393    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3394    GIComplexPatternEquiv<ro_Windexed16>;
3395def gi_ro_Windexed32 :
3396    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3397    GIComplexPatternEquiv<ro_Windexed32>;
3398def gi_ro_Windexed64 :
3399    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3400    GIComplexPatternEquiv<ro_Windexed64>;
3401def gi_ro_Windexed128 :
3402    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3403    GIComplexPatternEquiv<ro_Windexed128>;
3404
3405class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3406  let Name = "Mem" # Reg # "Extend" # Width;
3407  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3408  let RenderMethod = "addMemExtendOperands";
3409  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3410}
3411
3412def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3413  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3414  // the trivial shift.
3415  let RenderMethod = "addMemExtend8Operands";
3416}
3417def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3418def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3419def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3420def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3421
3422def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3423  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3424  // the trivial shift.
3425  let RenderMethod = "addMemExtend8Operands";
3426}
3427def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3428def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3429def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3430def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3431
3432class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3433        : Operand<i32> {
3434  let ParserMatchClass = ParserClass;
3435  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3436  let DecoderMethod = "DecodeMemExtend";
3437  let EncoderMethod = "getMemExtendOpValue";
3438  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3439}
3440
3441def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3442def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3443def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3444def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3445def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3446
3447def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3448def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3449def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3450def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3451def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3452
3453class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3454                  Operand wextend, Operand xextend>  {
3455  // CodeGen-level pattern covering the entire addressing mode.
3456  ComplexPattern Wpat = windex;
3457  ComplexPattern Xpat = xindex;
3458
3459  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3460  Operand Wext = wextend;
3461  Operand Xext = xextend;
3462}
3463
3464def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3465def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3466def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3467def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3468def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3469                       ro_Xextend128>;
3470
3471class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3472                   dag outs, list<dag> pat>
3473    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3474  bits<5> Rt;
3475  bits<5> Rn;
3476  bits<5> Rm;
3477  bits<2> extend;
3478  let Inst{31-30} = sz;
3479  let Inst{29-27} = 0b111;
3480  let Inst{26}    = V;
3481  let Inst{25-24} = 0b00;
3482  let Inst{23-22} = opc;
3483  let Inst{21}    = 1;
3484  let Inst{20-16} = Rm;
3485  let Inst{15}    = extend{1}; // sign extend Rm?
3486  let Inst{14}    = 1;
3487  let Inst{12}    = extend{0}; // do shift?
3488  let Inst{11-10} = 0b10;
3489  let Inst{9-5}   = Rn;
3490  let Inst{4-0}   = Rt;
3491}
3492
3493class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3494  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3495              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3496
3497multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3498                   string asm, ValueType Ty, SDPatternOperator loadop> {
3499  let AddedComplexity = 10 in
3500  def roW : LoadStore8RO<sz, V, opc, asm,
3501                 (outs regtype:$Rt),
3502                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3503                 [(set (Ty regtype:$Rt),
3504                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3505                                             ro_Wextend8:$extend)))]>,
3506           Sched<[WriteLDIdx, ReadAdrBase]> {
3507    let Inst{13} = 0b0;
3508  }
3509
3510  let AddedComplexity = 10 in
3511  def roX : LoadStore8RO<sz, V, opc, asm,
3512                 (outs regtype:$Rt),
3513                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3514                 [(set (Ty regtype:$Rt),
3515                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3516                                             ro_Xextend8:$extend)))]>,
3517           Sched<[WriteLDIdx, ReadAdrBase]> {
3518    let Inst{13} = 0b1;
3519  }
3520
3521  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3522}
3523
3524multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3525                    string asm, ValueType Ty, SDPatternOperator storeop> {
3526  let AddedComplexity = 10 in
3527  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3528                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3529                 [(storeop (Ty regtype:$Rt),
3530                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3531                                         ro_Wextend8:$extend))]>,
3532            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3533    let Inst{13} = 0b0;
3534  }
3535
3536  let AddedComplexity = 10 in
3537  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3538                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3539                 [(storeop (Ty regtype:$Rt),
3540                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3541                                         ro_Xextend8:$extend))]>,
3542            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3543    let Inst{13} = 0b1;
3544  }
3545
3546  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3547}
3548
3549class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3550                    dag outs, list<dag> pat>
3551    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3552  bits<5> Rt;
3553  bits<5> Rn;
3554  bits<5> Rm;
3555  bits<2> extend;
3556  let Inst{31-30} = sz;
3557  let Inst{29-27} = 0b111;
3558  let Inst{26}    = V;
3559  let Inst{25-24} = 0b00;
3560  let Inst{23-22} = opc;
3561  let Inst{21}    = 1;
3562  let Inst{20-16} = Rm;
3563  let Inst{15}    = extend{1}; // sign extend Rm?
3564  let Inst{14}    = 1;
3565  let Inst{12}    = extend{0}; // do shift?
3566  let Inst{11-10} = 0b10;
3567  let Inst{9-5}   = Rn;
3568  let Inst{4-0}   = Rt;
3569}
3570
3571multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3572                    string asm, ValueType Ty, SDPatternOperator loadop> {
3573  let AddedComplexity = 10 in
3574  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3575                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3576                 [(set (Ty regtype:$Rt),
3577                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3578                                              ro_Wextend16:$extend)))]>,
3579            Sched<[WriteLDIdx, ReadAdrBase]> {
3580    let Inst{13} = 0b0;
3581  }
3582
3583  let AddedComplexity = 10 in
3584  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3585                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3586                 [(set (Ty regtype:$Rt),
3587                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3588                                             ro_Xextend16:$extend)))]>,
3589            Sched<[WriteLDIdx, ReadAdrBase]> {
3590    let Inst{13} = 0b1;
3591  }
3592
3593  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3594}
3595
3596multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3597                     string asm, ValueType Ty, SDPatternOperator storeop> {
3598  let AddedComplexity = 10 in
3599  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3600                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3601                [(storeop (Ty regtype:$Rt),
3602                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3603                                         ro_Wextend16:$extend))]>,
3604           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3605    let Inst{13} = 0b0;
3606  }
3607
3608  let AddedComplexity = 10 in
3609  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3610                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3611                [(storeop (Ty regtype:$Rt),
3612                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3613                                         ro_Xextend16:$extend))]>,
3614           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3615    let Inst{13} = 0b1;
3616  }
3617
3618  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3619}
3620
3621class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3622                    dag outs, list<dag> pat>
3623    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3624  bits<5> Rt;
3625  bits<5> Rn;
3626  bits<5> Rm;
3627  bits<2> extend;
3628  let Inst{31-30} = sz;
3629  let Inst{29-27} = 0b111;
3630  let Inst{26}    = V;
3631  let Inst{25-24} = 0b00;
3632  let Inst{23-22} = opc;
3633  let Inst{21}    = 1;
3634  let Inst{20-16} = Rm;
3635  let Inst{15}    = extend{1}; // sign extend Rm?
3636  let Inst{14}    = 1;
3637  let Inst{12}    = extend{0}; // do shift?
3638  let Inst{11-10} = 0b10;
3639  let Inst{9-5}   = Rn;
3640  let Inst{4-0}   = Rt;
3641}
3642
3643multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3644                    string asm, ValueType Ty, SDPatternOperator loadop> {
3645  let AddedComplexity = 10 in
3646  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3647                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3648                 [(set (Ty regtype:$Rt),
3649                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3650                                              ro_Wextend32:$extend)))]>,
3651           Sched<[WriteLDIdx, ReadAdrBase]> {
3652    let Inst{13} = 0b0;
3653  }
3654
3655  let AddedComplexity = 10 in
3656  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3657                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3658                 [(set (Ty regtype:$Rt),
3659                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3660                                              ro_Xextend32:$extend)))]>,
3661           Sched<[WriteLDIdx, ReadAdrBase]> {
3662    let Inst{13} = 0b1;
3663  }
3664
3665  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3666}
3667
3668multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3669                     string asm, ValueType Ty, SDPatternOperator storeop> {
3670  let AddedComplexity = 10 in
3671  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3672                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3673                [(storeop (Ty regtype:$Rt),
3674                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3675                                         ro_Wextend32:$extend))]>,
3676            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3677    let Inst{13} = 0b0;
3678  }
3679
3680  let AddedComplexity = 10 in
3681  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3682                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3683                [(storeop (Ty regtype:$Rt),
3684                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3685                                        ro_Xextend32:$extend))]>,
3686            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3687    let Inst{13} = 0b1;
3688  }
3689
3690  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3691}
3692
3693class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3694                    dag outs, list<dag> pat>
3695    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3696  bits<5> Rt;
3697  bits<5> Rn;
3698  bits<5> Rm;
3699  bits<2> extend;
3700  let Inst{31-30} = sz;
3701  let Inst{29-27} = 0b111;
3702  let Inst{26}    = V;
3703  let Inst{25-24} = 0b00;
3704  let Inst{23-22} = opc;
3705  let Inst{21}    = 1;
3706  let Inst{20-16} = Rm;
3707  let Inst{15}    = extend{1}; // sign extend Rm?
3708  let Inst{14}    = 1;
3709  let Inst{12}    = extend{0}; // do shift?
3710  let Inst{11-10} = 0b10;
3711  let Inst{9-5}   = Rn;
3712  let Inst{4-0}   = Rt;
3713}
3714
3715multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3716                    string asm, ValueType Ty, SDPatternOperator loadop> {
3717  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3718  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3719                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3720                [(set (Ty regtype:$Rt),
3721                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3722                                             ro_Wextend64:$extend)))]>,
3723           Sched<[WriteLDIdx, ReadAdrBase]> {
3724    let Inst{13} = 0b0;
3725  }
3726
3727  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3728  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3729                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3730                 [(set (Ty regtype:$Rt),
3731                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3732                                              ro_Xextend64:$extend)))]>,
3733           Sched<[WriteLDIdx, ReadAdrBase]> {
3734    let Inst{13} = 0b1;
3735  }
3736
3737  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3738}
3739
3740multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3741                     string asm, ValueType Ty, SDPatternOperator storeop> {
3742  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3743  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3744                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3745                [(storeop (Ty regtype:$Rt),
3746                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3747                                         ro_Wextend64:$extend))]>,
3748            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3749    let Inst{13} = 0b0;
3750  }
3751
3752  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3753  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3754                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3755                [(storeop (Ty regtype:$Rt),
3756                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3757                                         ro_Xextend64:$extend))]>,
3758            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3759    let Inst{13} = 0b1;
3760  }
3761
3762  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3763}
3764
3765class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3766                     dag outs, list<dag> pat>
3767    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3768  bits<5> Rt;
3769  bits<5> Rn;
3770  bits<5> Rm;
3771  bits<2> extend;
3772  let Inst{31-30} = sz;
3773  let Inst{29-27} = 0b111;
3774  let Inst{26}    = V;
3775  let Inst{25-24} = 0b00;
3776  let Inst{23-22} = opc;
3777  let Inst{21}    = 1;
3778  let Inst{20-16} = Rm;
3779  let Inst{15}    = extend{1}; // sign extend Rm?
3780  let Inst{14}    = 1;
3781  let Inst{12}    = extend{0}; // do shift?
3782  let Inst{11-10} = 0b10;
3783  let Inst{9-5}   = Rn;
3784  let Inst{4-0}   = Rt;
3785}
3786
3787multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3788                     string asm, ValueType Ty, SDPatternOperator loadop> {
3789  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3790  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3791                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3792                 [(set (Ty regtype:$Rt),
3793                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3794                                               ro_Wextend128:$extend)))]>,
3795            Sched<[WriteLDIdx, ReadAdrBase]> {
3796    let Inst{13} = 0b0;
3797  }
3798
3799  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3800  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3801                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3802                 [(set (Ty regtype:$Rt),
3803                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3804                                               ro_Xextend128:$extend)))]>,
3805            Sched<[WriteLDIdx, ReadAdrBase]> {
3806    let Inst{13} = 0b1;
3807  }
3808
3809  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3810}
3811
3812multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3813                      string asm> {
3814  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3815  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
3816               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3817                []>,
3818            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3819    let Inst{13} = 0b0;
3820  }
3821
3822  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3823  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
3824               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3825                []>,
3826            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3827    let Inst{13} = 0b1;
3828  }
3829
3830  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3831}
3832
3833let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3834class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3835                     string asm, list<dag> pat>
3836    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3837      Sched<[WriteLD]> {
3838  bits<5> Rt;
3839  bits<5> Rn;
3840  bits<5> Rm;
3841  bits<2> extend;
3842  let Inst{31-30} = sz;
3843  let Inst{29-27} = 0b111;
3844  let Inst{26}    = V;
3845  let Inst{25-24} = 0b00;
3846  let Inst{23-22} = opc;
3847  let Inst{21}    = 1;
3848  let Inst{20-16} = Rm;
3849  let Inst{15}    = extend{1}; // sign extend Rm?
3850  let Inst{14}    = 1;
3851  let Inst{12}    = extend{0}; // do shift?
3852  let Inst{11-10} = 0b10;
3853  let Inst{9-5}   = Rn;
3854  let Inst{4-0}   = Rt;
3855}
3856
3857multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3858  def roW : BasePrefetchRO<sz, V, opc, (outs),
3859                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3860                asm, [(AArch64Prefetch imm:$Rt,
3861                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3862                                                    ro_Wextend64:$extend))]> {
3863    let Inst{13} = 0b0;
3864  }
3865
3866  def roX : BasePrefetchRO<sz, V, opc, (outs),
3867                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3868                asm,  [(AArch64Prefetch imm:$Rt,
3869                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3870                                                     ro_Xextend64:$extend))]> {
3871    let Inst{13} = 0b1;
3872  }
3873
3874  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3875               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3876                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3877}
3878
3879//---
3880// Load/store unscaled immediate
3881//---
3882
3883def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
3884def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
3885def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
3886def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
3887def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
3888
3889def gi_am_unscaled8 :
3890    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3891    GIComplexPatternEquiv<am_unscaled8>;
3892def gi_am_unscaled16 :
3893    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3894    GIComplexPatternEquiv<am_unscaled16>;
3895def gi_am_unscaled32 :
3896    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3897    GIComplexPatternEquiv<am_unscaled32>;
3898def gi_am_unscaled64 :
3899    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3900    GIComplexPatternEquiv<am_unscaled64>;
3901def gi_am_unscaled128 :
3902    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3903    GIComplexPatternEquiv<am_unscaled128>;
3904
3905
3906class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3907                           string asm, list<dag> pattern>
3908    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3909  bits<5> Rt;
3910  bits<5> Rn;
3911  bits<9> offset;
3912  let Inst{31-30} = sz;
3913  let Inst{29-27} = 0b111;
3914  let Inst{26}    = V;
3915  let Inst{25-24} = 0b00;
3916  let Inst{23-22} = opc;
3917  let Inst{21}    = 0;
3918  let Inst{20-12} = offset;
3919  let Inst{11-10} = 0b00;
3920  let Inst{9-5}   = Rn;
3921  let Inst{4-0}   = Rt;
3922
3923  let DecoderMethod = "DecodeSignedLdStInstruction";
3924}
3925
3926// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3927multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3928                              DAGOperand regtype > {
3929  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3930                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3931          Sched<[WriteST]> {
3932    let Inst{29} = 0;
3933    let Inst{24} = 1;
3934  }
3935  def : InstAlias<asm # "\t$Rt, [$Rn]",
3936                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3937}
3938
3939multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3940                               DAGOperand regtype > {
3941  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3942                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3943                               asm, []>,
3944          Sched<[WriteST]> {
3945    let Inst{29} = 0;
3946    let Inst{24} = 1;
3947  }
3948  def : InstAlias<asm # "\t$Rt, [$Rn]",
3949                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3950}
3951
3952multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3953                   string asm, list<dag> pattern> {
3954  let AddedComplexity = 1 in // try this before LoadUI
3955  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3956                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3957          Sched<[WriteLD]>;
3958
3959  def : InstAlias<asm # "\t$Rt, [$Rn]",
3960                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3961}
3962
3963multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3964                         string asm, list<dag> pattern> {
3965  let AddedComplexity = 1 in // try this before StoreUI
3966  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3967                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3968                               asm, pattern>,
3969          Sched<[WriteST]>;
3970
3971  def : InstAlias<asm # "\t$Rt, [$Rn]",
3972                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3973}
3974
3975multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3976                            list<dag> pat> {
3977  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3978  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3979                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3980                               asm, pat>,
3981          Sched<[WriteLD]>;
3982
3983  def : InstAlias<asm # "\t$Rt, [$Rn]",
3984                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3985}
3986
3987//---
3988// Load/store unscaled immediate, unprivileged
3989//---
3990
3991class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3992                                dag oops, dag iops, string asm>
3993    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3994  bits<5> Rt;
3995  bits<5> Rn;
3996  bits<9> offset;
3997  let Inst{31-30} = sz;
3998  let Inst{29-27} = 0b111;
3999  let Inst{26}    = V;
4000  let Inst{25-24} = 0b00;
4001  let Inst{23-22} = opc;
4002  let Inst{21}    = 0;
4003  let Inst{20-12} = offset;
4004  let Inst{11-10} = 0b10;
4005  let Inst{9-5}   = Rn;
4006  let Inst{4-0}   = Rt;
4007
4008  let DecoderMethod = "DecodeSignedLdStInstruction";
4009}
4010
4011multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4012                            RegisterClass regtype, string asm> {
4013  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4014  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4015                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4016          Sched<[WriteLD]>;
4017
4018  def : InstAlias<asm # "\t$Rt, [$Rn]",
4019                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4020}
4021
4022multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4023                             RegisterClass regtype, string asm> {
4024  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4025  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4026                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4027                                 asm>,
4028          Sched<[WriteST]>;
4029
4030  def : InstAlias<asm # "\t$Rt, [$Rn]",
4031                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4032}
4033
4034//---
4035// Load/store pre-indexed
4036//---
4037
4038class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4039                          string asm, string cstr, list<dag> pat>
4040    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4041  bits<5> Rt;
4042  bits<5> Rn;
4043  bits<9> offset;
4044  let Inst{31-30} = sz;
4045  let Inst{29-27} = 0b111;
4046  let Inst{26}    = V;
4047  let Inst{25-24} = 0;
4048  let Inst{23-22} = opc;
4049  let Inst{21}    = 0;
4050  let Inst{20-12} = offset;
4051  let Inst{11-10} = 0b11;
4052  let Inst{9-5}   = Rn;
4053  let Inst{4-0}   = Rt;
4054
4055  let DecoderMethod = "DecodeSignedLdStInstruction";
4056}
4057
4058let hasSideEffects = 0 in {
4059let mayStore = 0, mayLoad = 1 in
4060class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4061             string asm>
4062    : BaseLoadStorePreIdx<sz, V, opc,
4063                     (outs GPR64sp:$wback, regtype:$Rt),
4064                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4065                     "$Rn = $wback,@earlyclobber $wback", []>,
4066      Sched<[WriteAdr, WriteLD]>;
4067
4068let mayStore = 1, mayLoad = 0 in
4069class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4070                  string asm, SDPatternOperator storeop, ValueType Ty>
4071    : BaseLoadStorePreIdx<sz, V, opc,
4072                      (outs GPR64sp:$wback),
4073                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4074                      asm, "$Rn = $wback,@earlyclobber $wback",
4075      [(set GPR64sp:$wback,
4076            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4077      Sched<[WriteAdr, WriteST]>;
4078} // hasSideEffects = 0
4079
4080//---
4081// Load/store post-indexed
4082//---
4083
4084class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4085                          string asm, string cstr, list<dag> pat>
4086    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4087  bits<5> Rt;
4088  bits<5> Rn;
4089  bits<9> offset;
4090  let Inst{31-30} = sz;
4091  let Inst{29-27} = 0b111;
4092  let Inst{26}    = V;
4093  let Inst{25-24} = 0b00;
4094  let Inst{23-22} = opc;
4095  let Inst{21}    = 0b0;
4096  let Inst{20-12} = offset;
4097  let Inst{11-10} = 0b01;
4098  let Inst{9-5}   = Rn;
4099  let Inst{4-0}   = Rt;
4100
4101  let DecoderMethod = "DecodeSignedLdStInstruction";
4102}
4103
4104let hasSideEffects = 0 in {
4105let mayStore = 0, mayLoad = 1 in
4106class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4107             string asm>
4108    : BaseLoadStorePostIdx<sz, V, opc,
4109                      (outs GPR64sp:$wback, regtype:$Rt),
4110                      (ins GPR64sp:$Rn, simm9:$offset),
4111                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4112      Sched<[WriteAdr, WriteLD]>;
4113
4114let mayStore = 1, mayLoad = 0 in
4115class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4116                   string asm, SDPatternOperator storeop, ValueType Ty>
4117    : BaseLoadStorePostIdx<sz, V, opc,
4118                      (outs GPR64sp:$wback),
4119                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4120                       asm, "$Rn = $wback,@earlyclobber $wback",
4121      [(set GPR64sp:$wback,
4122            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4123    Sched<[WriteAdr, WriteST]>;
4124} // hasSideEffects = 0
4125
4126
4127//---
4128// Load/store pair
4129//---
4130
4131// (indexed, offset)
4132
4133class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4134                              string asm>
4135    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4136  bits<5> Rt;
4137  bits<5> Rt2;
4138  bits<5> Rn;
4139  bits<7> offset;
4140  let Inst{31-30} = opc;
4141  let Inst{29-27} = 0b101;
4142  let Inst{26}    = V;
4143  let Inst{25-23} = 0b010;
4144  let Inst{22}    = L;
4145  let Inst{21-15} = offset;
4146  let Inst{14-10} = Rt2;
4147  let Inst{9-5}   = Rn;
4148  let Inst{4-0}   = Rt;
4149
4150  let DecoderMethod = "DecodePairLdStInstruction";
4151}
4152
4153multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4154                          Operand indextype, string asm> {
4155  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4156  def i : BaseLoadStorePairOffset<opc, V, 1,
4157                                  (outs regtype:$Rt, regtype:$Rt2),
4158                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4159          Sched<[WriteLD, WriteLDHi]>;
4160
4161  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4162                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4163                                                  GPR64sp:$Rn, 0)>;
4164}
4165
4166
4167multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4168                           Operand indextype, string asm> {
4169  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4170  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4171                                  (ins regtype:$Rt, regtype:$Rt2,
4172                                       GPR64sp:$Rn, indextype:$offset),
4173                                  asm>,
4174          Sched<[WriteSTP]>;
4175
4176  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4177                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4178                                                  GPR64sp:$Rn, 0)>;
4179}
4180
4181// (pre-indexed)
4182class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4183                              string asm>
4184    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4185  bits<5> Rt;
4186  bits<5> Rt2;
4187  bits<5> Rn;
4188  bits<7> offset;
4189  let Inst{31-30} = opc;
4190  let Inst{29-27} = 0b101;
4191  let Inst{26}    = V;
4192  let Inst{25-23} = 0b011;
4193  let Inst{22}    = L;
4194  let Inst{21-15} = offset;
4195  let Inst{14-10} = Rt2;
4196  let Inst{9-5}   = Rn;
4197  let Inst{4-0}   = Rt;
4198
4199  let DecoderMethod = "DecodePairLdStInstruction";
4200}
4201
4202let hasSideEffects = 0 in {
4203let mayStore = 0, mayLoad = 1 in
4204class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4205                     Operand indextype, string asm>
4206    : BaseLoadStorePairPreIdx<opc, V, 1,
4207                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4208                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4209      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4210
4211let mayStore = 1, mayLoad = 0 in
4212class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4213                      Operand indextype, string asm>
4214    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4215                             (ins regtype:$Rt, regtype:$Rt2,
4216                                  GPR64sp:$Rn, indextype:$offset),
4217                             asm>,
4218      Sched<[WriteAdr, WriteSTP]>;
4219} // hasSideEffects = 0
4220
4221// (post-indexed)
4222
4223class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4224                              string asm>
4225    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4226  bits<5> Rt;
4227  bits<5> Rt2;
4228  bits<5> Rn;
4229  bits<7> offset;
4230  let Inst{31-30} = opc;
4231  let Inst{29-27} = 0b101;
4232  let Inst{26}    = V;
4233  let Inst{25-23} = 0b001;
4234  let Inst{22}    = L;
4235  let Inst{21-15} = offset;
4236  let Inst{14-10} = Rt2;
4237  let Inst{9-5}   = Rn;
4238  let Inst{4-0}   = Rt;
4239
4240  let DecoderMethod = "DecodePairLdStInstruction";
4241}
4242
4243let hasSideEffects = 0 in {
4244let mayStore = 0, mayLoad = 1 in
4245class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4246                      Operand idxtype, string asm>
4247    : BaseLoadStorePairPostIdx<opc, V, 1,
4248                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4249                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4250      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4251
4252let mayStore = 1, mayLoad = 0 in
4253class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4254                       Operand idxtype, string asm>
4255    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4256                             (ins regtype:$Rt, regtype:$Rt2,
4257                                  GPR64sp:$Rn, idxtype:$offset),
4258                             asm>,
4259      Sched<[WriteAdr, WriteSTP]>;
4260} // hasSideEffects = 0
4261
4262//  (no-allocate)
4263
4264class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4265                              string asm>
4266    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4267  bits<5> Rt;
4268  bits<5> Rt2;
4269  bits<5> Rn;
4270  bits<7> offset;
4271  let Inst{31-30} = opc;
4272  let Inst{29-27} = 0b101;
4273  let Inst{26}    = V;
4274  let Inst{25-23} = 0b000;
4275  let Inst{22}    = L;
4276  let Inst{21-15} = offset;
4277  let Inst{14-10} = Rt2;
4278  let Inst{9-5}   = Rn;
4279  let Inst{4-0}   = Rt;
4280
4281  let DecoderMethod = "DecodePairLdStInstruction";
4282}
4283
4284multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4285                           Operand indextype, string asm> {
4286  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4287  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4288                                   (outs regtype:$Rt, regtype:$Rt2),
4289                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4290          Sched<[WriteLD, WriteLDHi]>;
4291
4292
4293  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4294                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4295                                                  GPR64sp:$Rn, 0)>;
4296}
4297
4298multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4299                      Operand indextype, string asm> {
4300  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4301  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4302                                   (ins regtype:$Rt, regtype:$Rt2,
4303                                        GPR64sp:$Rn, indextype:$offset),
4304                                   asm>,
4305          Sched<[WriteSTP]>;
4306
4307  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4308                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4309                                                  GPR64sp:$Rn, 0)>;
4310}
4311
4312//---
4313// Load/store exclusive
4314//---
4315
4316// True exclusive operations write to and/or read from the system's exclusive
4317// monitors, which as far as a compiler is concerned can be modelled as a
4318// random shared memory address. Hence LoadExclusive mayStore.
4319//
4320// Since these instructions have the undefined register bits set to 1 in
4321// their canonical form, we need a post encoder method to set those bits
4322// to 1 when encoding these instructions. We do this using the
4323// fixLoadStoreExclusive function. This function has template parameters:
4324//
4325// fixLoadStoreExclusive<int hasRs, int hasRt2>
4326//
4327// hasRs indicates that the instruction uses the Rs field, so we won't set
4328// it to 1 (and the same for Rt2). We don't need template parameters for
4329// the other register fields since Rt and Rn are always used.
4330//
4331let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4332class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4333                             dag oops, dag iops, string asm, string operands>
4334    : I<oops, iops, asm, operands, "", []> {
4335  let Inst{31-30} = sz;
4336  let Inst{29-24} = 0b001000;
4337  let Inst{23}    = o2;
4338  let Inst{22}    = L;
4339  let Inst{21}    = o1;
4340  let Inst{15}    = o0;
4341
4342  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4343}
4344
4345// Neither Rs nor Rt2 operands.
4346class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4347                               dag oops, dag iops, string asm, string operands>
4348    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4349  bits<5> Rt;
4350  bits<5> Rn;
4351  let Inst{20-16} = 0b11111;
4352  let Unpredictable{20-16} = 0b11111;
4353  let Inst{14-10} = 0b11111;
4354  let Unpredictable{14-10} = 0b11111;
4355  let Inst{9-5} = Rn;
4356  let Inst{4-0} = Rt;
4357
4358  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4359}
4360
4361// Simple load acquires don't set the exclusive monitor
4362let mayLoad = 1, mayStore = 0 in
4363class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4364                  RegisterClass regtype, string asm>
4365    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4366                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4367      Sched<[WriteLD]>;
4368
4369class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4370                    RegisterClass regtype, string asm>
4371    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4372                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4373      Sched<[WriteLD]>;
4374
4375class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4376                       RegisterClass regtype, string asm>
4377    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4378                             (outs regtype:$Rt, regtype:$Rt2),
4379                             (ins GPR64sp0:$Rn), asm,
4380                             "\t$Rt, $Rt2, [$Rn]">,
4381      Sched<[WriteLD, WriteLDHi]> {
4382  bits<5> Rt;
4383  bits<5> Rt2;
4384  bits<5> Rn;
4385  let Inst{14-10} = Rt2;
4386  let Inst{9-5} = Rn;
4387  let Inst{4-0} = Rt;
4388
4389  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4390}
4391
4392// Simple store release operations do not check the exclusive monitor.
4393let mayLoad = 0, mayStore = 1 in
4394class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4395                   RegisterClass regtype, string asm>
4396    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4397                               (ins regtype:$Rt, GPR64sp0:$Rn),
4398                               asm, "\t$Rt, [$Rn]">,
4399      Sched<[WriteST]>;
4400
4401let mayLoad = 1, mayStore = 1 in
4402class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4403                     RegisterClass regtype, string asm>
4404    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4405                             (ins regtype:$Rt, GPR64sp0:$Rn),
4406                             asm, "\t$Ws, $Rt, [$Rn]">,
4407      Sched<[WriteSTX]> {
4408  bits<5> Ws;
4409  bits<5> Rt;
4410  bits<5> Rn;
4411  let Inst{20-16} = Ws;
4412  let Inst{9-5} = Rn;
4413  let Inst{4-0} = Rt;
4414
4415  let Constraints = "@earlyclobber $Ws";
4416  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4417}
4418
4419class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4420                         RegisterClass regtype, string asm>
4421    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4422                             (outs GPR32:$Ws),
4423                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4424                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4425      Sched<[WriteSTX]> {
4426  bits<5> Ws;
4427  bits<5> Rt;
4428  bits<5> Rt2;
4429  bits<5> Rn;
4430  let Inst{20-16} = Ws;
4431  let Inst{14-10} = Rt2;
4432  let Inst{9-5} = Rn;
4433  let Inst{4-0} = Rt;
4434
4435  let Constraints = "@earlyclobber $Ws";
4436}
4437
4438// Armv8.5-A Memory Tagging Extension
4439class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4440                 string asm_opnds, string cstr, dag oops, dag iops>
4441    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4442      Sched<[]> {
4443  bits<5> Rn;
4444
4445  let Inst{31-24} = 0b11011001;
4446  let Inst{23-22} = opc1;
4447  let Inst{21}    = 1;
4448  // Inst{20-12} defined by subclass
4449  let Inst{11-10} = opc2;
4450  let Inst{9-5}   = Rn;
4451  // Inst{4-0} defined by subclass
4452}
4453
4454class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4455                   dag oops, dag iops>
4456    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4457                  "", oops, iops> {
4458  bits<5> Rt;
4459
4460  let Inst{20-12} = 0b000000000;
4461  let Inst{4-0}   = Rt;
4462
4463  let mayLoad = Load;
4464}
4465
4466class MemTagLoad<string asm_insn, string asm_opnds>
4467    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4468                 (outs GPR64:$wback),
4469                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4470  bits<5> Rt;
4471  bits<9> offset;
4472
4473  let Inst{20-12} = offset;
4474  let Inst{4-0}   = Rt;
4475
4476  let mayLoad = 1;
4477}
4478
4479class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4480                     string asm_opnds, string cstr, dag oops, dag iops>
4481    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4482  bits<5> Rt;
4483  bits<9> offset;
4484
4485  let Inst{20-12} = offset;
4486  let Inst{4-0}   = Rt;
4487
4488  let mayStore = 1;
4489}
4490
4491multiclass MemTagStore<bits<2> opc1, string insn> {
4492  def Offset :
4493    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4494                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4495  def PreIndex :
4496    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4497                    "$Rn = $wback",
4498                    (outs GPR64sp:$wback),
4499                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4500  def PostIndex :
4501    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4502                    "$Rn = $wback",
4503                    (outs GPR64sp:$wback),
4504                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4505
4506  def : InstAlias<insn # "\t$Rt, [$Rn]",
4507                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4508}
4509
4510//---
4511// Exception generation
4512//---
4513
4514let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4515class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4516    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", []>,
4517      Sched<[WriteSys]> {
4518  bits<16> imm;
4519  let Inst{31-24} = 0b11010100;
4520  let Inst{23-21} = op1;
4521  let Inst{20-5}  = imm;
4522  let Inst{4-2}   = 0b000;
4523  let Inst{1-0}   = ll;
4524}
4525
4526//---
4527// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4528//--
4529let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4530class UDFType<bits<16> opc, string asm>
4531  : I<(outs), (ins uimm16:$imm),
4532       asm, "\t$imm", "", []>,
4533    Sched<[]> {
4534  bits<16> imm;
4535  let Inst{31-16} = opc;
4536  let Inst{15-0} = imm;
4537}
4538}
4539let Predicates = [HasFPARMv8] in {
4540
4541//---
4542// Floating point to integer conversion
4543//---
4544
4545class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4546                      RegisterClass srcType, RegisterClass dstType,
4547                      string asm, list<dag> pattern>
4548    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4549         asm, "\t$Rd, $Rn", "", pattern>,
4550      Sched<[WriteFCvt]> {
4551  bits<5> Rd;
4552  bits<5> Rn;
4553  let Inst{30-29} = 0b00;
4554  let Inst{28-24} = 0b11110;
4555  let Inst{23-22} = type;
4556  let Inst{21}    = 1;
4557  let Inst{20-19} = rmode;
4558  let Inst{18-16} = opcode;
4559  let Inst{15-10} = 0;
4560  let Inst{9-5}   = Rn;
4561  let Inst{4-0}   = Rd;
4562}
4563
4564let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4565class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4566                      RegisterClass srcType, RegisterClass dstType,
4567                      Operand immType, string asm, list<dag> pattern>
4568    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4569         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4570      Sched<[WriteFCvt]> {
4571  bits<5> Rd;
4572  bits<5> Rn;
4573  bits<6> scale;
4574  let Inst{30-29} = 0b00;
4575  let Inst{28-24} = 0b11110;
4576  let Inst{23-22} = type;
4577  let Inst{21}    = 0;
4578  let Inst{20-19} = rmode;
4579  let Inst{18-16} = opcode;
4580  let Inst{15-10} = scale;
4581  let Inst{9-5}   = Rn;
4582  let Inst{4-0}   = Rd;
4583}
4584
4585multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4586           SDPatternOperator OpN> {
4587  // Unscaled half-precision to 32-bit
4588  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4589                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4590    let Inst{31} = 0; // 32-bit GPR flag
4591    let Predicates = [HasFullFP16];
4592  }
4593
4594  // Unscaled half-precision to 64-bit
4595  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4596                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4597    let Inst{31} = 1; // 64-bit GPR flag
4598    let Predicates = [HasFullFP16];
4599  }
4600
4601  // Unscaled single-precision to 32-bit
4602  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4603                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4604    let Inst{31} = 0; // 32-bit GPR flag
4605  }
4606
4607  // Unscaled single-precision to 64-bit
4608  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4609                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4610    let Inst{31} = 1; // 64-bit GPR flag
4611  }
4612
4613  // Unscaled double-precision to 32-bit
4614  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4615                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4616    let Inst{31} = 0; // 32-bit GPR flag
4617  }
4618
4619  // Unscaled double-precision to 64-bit
4620  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4621                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4622    let Inst{31} = 1; // 64-bit GPR flag
4623  }
4624}
4625
4626multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4627                             SDPatternOperator OpN> {
4628  // Scaled half-precision to 32-bit
4629  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4630                              fixedpoint_f16_i32, asm,
4631              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4632                                          fixedpoint_f16_i32:$scale)))]> {
4633    let Inst{31} = 0; // 32-bit GPR flag
4634    let scale{5} = 1;
4635    let Predicates = [HasFullFP16];
4636  }
4637
4638  // Scaled half-precision to 64-bit
4639  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4640                              fixedpoint_f16_i64, asm,
4641              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4642                                          fixedpoint_f16_i64:$scale)))]> {
4643    let Inst{31} = 1; // 64-bit GPR flag
4644    let Predicates = [HasFullFP16];
4645  }
4646
4647  // Scaled single-precision to 32-bit
4648  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4649                              fixedpoint_f32_i32, asm,
4650              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4651                                          fixedpoint_f32_i32:$scale)))]> {
4652    let Inst{31} = 0; // 32-bit GPR flag
4653    let scale{5} = 1;
4654  }
4655
4656  // Scaled single-precision to 64-bit
4657  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4658                              fixedpoint_f32_i64, asm,
4659              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4660                                          fixedpoint_f32_i64:$scale)))]> {
4661    let Inst{31} = 1; // 64-bit GPR flag
4662  }
4663
4664  // Scaled double-precision to 32-bit
4665  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4666                              fixedpoint_f64_i32, asm,
4667              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4668                                          fixedpoint_f64_i32:$scale)))]> {
4669    let Inst{31} = 0; // 32-bit GPR flag
4670    let scale{5} = 1;
4671  }
4672
4673  // Scaled double-precision to 64-bit
4674  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4675                              fixedpoint_f64_i64, asm,
4676              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4677                                          fixedpoint_f64_i64:$scale)))]> {
4678    let Inst{31} = 1; // 64-bit GPR flag
4679  }
4680}
4681
4682//---
4683// Integer to floating point conversion
4684//---
4685
4686let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4687class BaseIntegerToFP<bit isUnsigned,
4688                      RegisterClass srcType, RegisterClass dstType,
4689                      Operand immType, string asm, list<dag> pattern>
4690    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4691         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4692      Sched<[WriteFCvt]> {
4693  bits<5> Rd;
4694  bits<5> Rn;
4695  bits<6> scale;
4696  let Inst{30-24} = 0b0011110;
4697  let Inst{21-17} = 0b00001;
4698  let Inst{16}    = isUnsigned;
4699  let Inst{15-10} = scale;
4700  let Inst{9-5}   = Rn;
4701  let Inst{4-0}   = Rd;
4702}
4703
4704class BaseIntegerToFPUnscaled<bit isUnsigned,
4705                      RegisterClass srcType, RegisterClass dstType,
4706                      ValueType dvt, string asm, SDPatternOperator node>
4707    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4708         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4709      Sched<[WriteFCvt]> {
4710  bits<5> Rd;
4711  bits<5> Rn;
4712  bits<6> scale;
4713  let Inst{30-24} = 0b0011110;
4714  let Inst{21-17} = 0b10001;
4715  let Inst{16}    = isUnsigned;
4716  let Inst{15-10} = 0b000000;
4717  let Inst{9-5}   = Rn;
4718  let Inst{4-0}   = Rd;
4719}
4720
4721multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4722  // Unscaled
4723  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4724    let Inst{31} = 0; // 32-bit GPR flag
4725    let Inst{23-22} = 0b11; // 16-bit FPR flag
4726    let Predicates = [HasFullFP16];
4727  }
4728
4729  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4730    let Inst{31} = 0; // 32-bit GPR flag
4731    let Inst{23-22} = 0b00; // 32-bit FPR flag
4732  }
4733
4734  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4735    let Inst{31} = 0; // 32-bit GPR flag
4736    let Inst{23-22} = 0b01; // 64-bit FPR flag
4737  }
4738
4739  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4740    let Inst{31} = 1; // 64-bit GPR flag
4741    let Inst{23-22} = 0b11; // 16-bit FPR flag
4742    let Predicates = [HasFullFP16];
4743  }
4744
4745  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4746    let Inst{31} = 1; // 64-bit GPR flag
4747    let Inst{23-22} = 0b00; // 32-bit FPR flag
4748  }
4749
4750  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4751    let Inst{31} = 1; // 64-bit GPR flag
4752    let Inst{23-22} = 0b01; // 64-bit FPR flag
4753  }
4754
4755  // Scaled
4756  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4757                             [(set (f16 FPR16:$Rd),
4758                                   (fdiv (node GPR32:$Rn),
4759                                         fixedpoint_f16_i32:$scale))]> {
4760    let Inst{31} = 0; // 32-bit GPR flag
4761    let Inst{23-22} = 0b11; // 16-bit FPR flag
4762    let scale{5} = 1;
4763    let Predicates = [HasFullFP16];
4764  }
4765
4766  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4767                             [(set FPR32:$Rd,
4768                                   (fdiv (node GPR32:$Rn),
4769                                         fixedpoint_f32_i32:$scale))]> {
4770    let Inst{31} = 0; // 32-bit GPR flag
4771    let Inst{23-22} = 0b00; // 32-bit FPR flag
4772    let scale{5} = 1;
4773  }
4774
4775  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4776                             [(set FPR64:$Rd,
4777                                   (fdiv (node GPR32:$Rn),
4778                                         fixedpoint_f64_i32:$scale))]> {
4779    let Inst{31} = 0; // 32-bit GPR flag
4780    let Inst{23-22} = 0b01; // 64-bit FPR flag
4781    let scale{5} = 1;
4782  }
4783
4784  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4785                             [(set (f16 FPR16:$Rd),
4786                                   (fdiv (node GPR64:$Rn),
4787                                         fixedpoint_f16_i64:$scale))]> {
4788    let Inst{31} = 1; // 64-bit GPR flag
4789    let Inst{23-22} = 0b11; // 16-bit FPR flag
4790    let Predicates = [HasFullFP16];
4791  }
4792
4793  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4794                             [(set FPR32:$Rd,
4795                                   (fdiv (node GPR64:$Rn),
4796                                         fixedpoint_f32_i64:$scale))]> {
4797    let Inst{31} = 1; // 64-bit GPR flag
4798    let Inst{23-22} = 0b00; // 32-bit FPR flag
4799  }
4800
4801  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4802                             [(set FPR64:$Rd,
4803                                   (fdiv (node GPR64:$Rn),
4804                                         fixedpoint_f64_i64:$scale))]> {
4805    let Inst{31} = 1; // 64-bit GPR flag
4806    let Inst{23-22} = 0b01; // 64-bit FPR flag
4807  }
4808}
4809
4810//---
4811// Unscaled integer <-> floating point conversion (i.e. FMOV)
4812//---
4813
4814let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4815class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4816                      RegisterClass srcType, RegisterClass dstType,
4817                      string asm>
4818    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4819        // We use COPY_TO_REGCLASS for these bitconvert operations.
4820        // copyPhysReg() expands the resultant COPY instructions after
4821        // regalloc is done. This gives greater freedom for the allocator
4822        // and related passes (coalescing, copy propagation, et. al.) to
4823        // be more effective.
4824        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4825      Sched<[WriteFCopy]> {
4826  bits<5> Rd;
4827  bits<5> Rn;
4828  let Inst{30-24} = 0b0011110;
4829  let Inst{21}    = 1;
4830  let Inst{20-19} = rmode;
4831  let Inst{18-16} = opcode;
4832  let Inst{15-10} = 0b000000;
4833  let Inst{9-5}   = Rn;
4834  let Inst{4-0}   = Rd;
4835}
4836
4837let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4838class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4839                     RegisterClass srcType, RegisterOperand dstType, string asm,
4840                     string kind>
4841    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4842        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4843      Sched<[WriteFCopy]> {
4844  bits<5> Rd;
4845  bits<5> Rn;
4846  let Inst{30-23} = 0b00111101;
4847  let Inst{21}    = 1;
4848  let Inst{20-19} = rmode;
4849  let Inst{18-16} = opcode;
4850  let Inst{15-10} = 0b000000;
4851  let Inst{9-5}   = Rn;
4852  let Inst{4-0}   = Rd;
4853
4854  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4855}
4856
4857let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4858class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4859                     RegisterOperand srcType, RegisterClass dstType, string asm,
4860                     string kind>
4861    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4862        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4863      Sched<[WriteFCopy]> {
4864  bits<5> Rd;
4865  bits<5> Rn;
4866  let Inst{30-23} = 0b00111101;
4867  let Inst{21}    = 1;
4868  let Inst{20-19} = rmode;
4869  let Inst{18-16} = opcode;
4870  let Inst{15-10} = 0b000000;
4871  let Inst{9-5}   = Rn;
4872  let Inst{4-0}   = Rd;
4873
4874  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4875}
4876
4877
4878multiclass UnscaledConversion<string asm> {
4879  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4880    let Inst{31} = 0; // 32-bit GPR flag
4881    let Inst{23-22} = 0b11; // 16-bit FPR flag
4882    let Predicates = [HasFullFP16];
4883  }
4884
4885  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4886    let Inst{31} = 1; // 64-bit GPR flag
4887    let Inst{23-22} = 0b11; // 16-bit FPR flag
4888    let Predicates = [HasFullFP16];
4889  }
4890
4891  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4892    let Inst{31} = 0; // 32-bit GPR flag
4893    let Inst{23-22} = 0b00; // 32-bit FPR flag
4894  }
4895
4896  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4897    let Inst{31} = 1; // 64-bit GPR flag
4898    let Inst{23-22} = 0b01; // 64-bit FPR flag
4899  }
4900
4901  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4902    let Inst{31} = 0; // 32-bit GPR flag
4903    let Inst{23-22} = 0b11; // 16-bit FPR flag
4904    let Predicates = [HasFullFP16];
4905  }
4906
4907  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4908    let Inst{31} = 1; // 64-bit GPR flag
4909    let Inst{23-22} = 0b11; // 16-bit FPR flag
4910    let Predicates = [HasFullFP16];
4911  }
4912
4913  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4914    let Inst{31} = 0; // 32-bit GPR flag
4915    let Inst{23-22} = 0b00; // 32-bit FPR flag
4916  }
4917
4918  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4919    let Inst{31} = 1; // 64-bit GPR flag
4920    let Inst{23-22} = 0b01; // 64-bit FPR flag
4921  }
4922
4923  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4924                                             asm, ".d"> {
4925    let Inst{31} = 1;
4926    let Inst{22} = 0;
4927  }
4928
4929  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4930                                               asm, ".d"> {
4931    let Inst{31} = 1;
4932    let Inst{22} = 0;
4933  }
4934}
4935
4936//---
4937// Floating point conversion
4938//---
4939
4940class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4941                       RegisterClass srcType, string asm, list<dag> pattern>
4942    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4943      Sched<[WriteFCvt]> {
4944  bits<5> Rd;
4945  bits<5> Rn;
4946  let Inst{31-24} = 0b00011110;
4947  let Inst{23-22} = type;
4948  let Inst{21-17} = 0b10001;
4949  let Inst{16-15} = opcode;
4950  let Inst{14-10} = 0b10000;
4951  let Inst{9-5}   = Rn;
4952  let Inst{4-0}   = Rd;
4953}
4954
4955multiclass FPConversion<string asm> {
4956  // Double-precision to Half-precision
4957  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4958                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4959
4960  // Double-precision to Single-precision
4961  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4962                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4963
4964  // Half-precision to Double-precision
4965  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4966                             [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4967
4968  // Half-precision to Single-precision
4969  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4970                             [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4971
4972  // Single-precision to Double-precision
4973  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4974                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4975
4976  // Single-precision to Half-precision
4977  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4978                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4979}
4980
4981//---
4982// Single operand floating point data processing
4983//---
4984
4985let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4986class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4987                              ValueType vt, string asm, SDPatternOperator node>
4988    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4989         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4990      Sched<[WriteF]> {
4991  bits<5> Rd;
4992  bits<5> Rn;
4993  let Inst{31-24} = 0b00011110;
4994  let Inst{21}    = 0b1;
4995  let Inst{20-15} = opcode;
4996  let Inst{14-10} = 0b10000;
4997  let Inst{9-5}   = Rn;
4998  let Inst{4-0}   = Rd;
4999}
5000
5001multiclass SingleOperandFPData<bits<4> opcode, string asm,
5002                               SDPatternOperator node = null_frag> {
5003
5004  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5005    let Inst{23-22} = 0b11; // 16-bit size flag
5006    let Predicates = [HasFullFP16];
5007  }
5008
5009  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5010    let Inst{23-22} = 0b00; // 32-bit size flag
5011  }
5012
5013  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5014    let Inst{23-22} = 0b01; // 64-bit size flag
5015  }
5016}
5017
5018multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5019                  SDPatternOperator node = null_frag>{
5020
5021  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5022    let Inst{23-22} = 0b00; // 32-bit registers
5023  }
5024
5025  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5026    let Inst{23-22} = 0b01; // 64-bit registers
5027  }
5028}
5029
5030// FRInt[32|64][Z|N] instructions
5031multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5032      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5033
5034//---
5035// Two operand floating point data processing
5036//---
5037
5038let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5039class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5040                           string asm, list<dag> pat>
5041    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5042         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5043      Sched<[WriteF]> {
5044  bits<5> Rd;
5045  bits<5> Rn;
5046  bits<5> Rm;
5047  let Inst{31-24} = 0b00011110;
5048  let Inst{21}    = 1;
5049  let Inst{20-16} = Rm;
5050  let Inst{15-12} = opcode;
5051  let Inst{11-10} = 0b10;
5052  let Inst{9-5}   = Rn;
5053  let Inst{4-0}   = Rd;
5054}
5055
5056multiclass TwoOperandFPData<bits<4> opcode, string asm,
5057                            SDPatternOperator node = null_frag> {
5058  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5059                         [(set (f16 FPR16:$Rd),
5060                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5061    let Inst{23-22} = 0b11; // 16-bit size flag
5062    let Predicates = [HasFullFP16];
5063  }
5064
5065  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5066                         [(set (f32 FPR32:$Rd),
5067                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5068    let Inst{23-22} = 0b00; // 32-bit size flag
5069  }
5070
5071  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5072                         [(set (f64 FPR64:$Rd),
5073                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5074    let Inst{23-22} = 0b01; // 64-bit size flag
5075  }
5076}
5077
5078multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
5079  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5080                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5081    let Inst{23-22} = 0b11; // 16-bit size flag
5082    let Predicates = [HasFullFP16];
5083  }
5084
5085  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5086                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5087    let Inst{23-22} = 0b00; // 32-bit size flag
5088  }
5089
5090  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5091                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5092    let Inst{23-22} = 0b01; // 64-bit size flag
5093  }
5094}
5095
5096
5097//---
5098// Three operand floating point data processing
5099//---
5100
5101class BaseThreeOperandFPData<bit isNegated, bit isSub,
5102                             RegisterClass regtype, string asm, list<dag> pat>
5103    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5104         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5105      Sched<[WriteFMul]> {
5106  bits<5> Rd;
5107  bits<5> Rn;
5108  bits<5> Rm;
5109  bits<5> Ra;
5110  let Inst{31-24} = 0b00011111;
5111  let Inst{21}    = isNegated;
5112  let Inst{20-16} = Rm;
5113  let Inst{15}    = isSub;
5114  let Inst{14-10} = Ra;
5115  let Inst{9-5}   = Rn;
5116  let Inst{4-0}   = Rd;
5117}
5118
5119multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5120                              SDPatternOperator node> {
5121  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5122            [(set (f16 FPR16:$Rd),
5123                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5124    let Inst{23-22} = 0b11; // 16-bit size flag
5125    let Predicates = [HasFullFP16];
5126  }
5127
5128  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5129            [(set FPR32:$Rd,
5130                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5131    let Inst{23-22} = 0b00; // 32-bit size flag
5132  }
5133
5134  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5135            [(set FPR64:$Rd,
5136                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5137    let Inst{23-22} = 0b01; // 64-bit size flag
5138  }
5139}
5140
5141//---
5142// Floating point data comparisons
5143//---
5144
5145let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5146class BaseOneOperandFPComparison<bit signalAllNans,
5147                                 RegisterClass regtype, string asm,
5148                                 list<dag> pat>
5149    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5150      Sched<[WriteFCmp]> {
5151  bits<5> Rn;
5152  let Inst{31-24} = 0b00011110;
5153  let Inst{21}    = 1;
5154
5155  let Inst{15-10} = 0b001000;
5156  let Inst{9-5}   = Rn;
5157  let Inst{4}     = signalAllNans;
5158  let Inst{3-0}   = 0b1000;
5159
5160  // Rm should be 0b00000 canonically, but we need to accept any value.
5161  let PostEncoderMethod = "fixOneOperandFPComparison";
5162}
5163
5164let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5165class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5166                                string asm, list<dag> pat>
5167    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5168      Sched<[WriteFCmp]> {
5169  bits<5> Rm;
5170  bits<5> Rn;
5171  let Inst{31-24} = 0b00011110;
5172  let Inst{21}    = 1;
5173  let Inst{20-16} = Rm;
5174  let Inst{15-10} = 0b001000;
5175  let Inst{9-5}   = Rn;
5176  let Inst{4}     = signalAllNans;
5177  let Inst{3-0}   = 0b0000;
5178}
5179
5180multiclass FPComparison<bit signalAllNans, string asm,
5181                        SDPatternOperator OpNode = null_frag> {
5182  let Defs = [NZCV] in {
5183  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5184      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5185    let Inst{23-22} = 0b11;
5186    let Predicates = [HasFullFP16];
5187  }
5188
5189  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5190      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5191    let Inst{23-22} = 0b11;
5192    let Predicates = [HasFullFP16];
5193  }
5194
5195  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5196      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5197    let Inst{23-22} = 0b00;
5198  }
5199
5200  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5201      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5202    let Inst{23-22} = 0b00;
5203  }
5204
5205  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5206      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5207    let Inst{23-22} = 0b01;
5208  }
5209
5210  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5211      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5212    let Inst{23-22} = 0b01;
5213  }
5214  } // Defs = [NZCV]
5215}
5216
5217//---
5218// Floating point conditional comparisons
5219//---
5220
5221let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5222class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5223                           string mnemonic, list<dag> pat>
5224    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5225         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5226      Sched<[WriteFCmp]> {
5227  let Uses = [NZCV];
5228  let Defs = [NZCV];
5229
5230  bits<5> Rn;
5231  bits<5> Rm;
5232  bits<4> nzcv;
5233  bits<4> cond;
5234
5235  let Inst{31-24} = 0b00011110;
5236  let Inst{21}    = 1;
5237  let Inst{20-16} = Rm;
5238  let Inst{15-12} = cond;
5239  let Inst{11-10} = 0b01;
5240  let Inst{9-5}   = Rn;
5241  let Inst{4}     = signalAllNans;
5242  let Inst{3-0}   = nzcv;
5243}
5244
5245multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5246                            SDPatternOperator OpNode = null_frag> {
5247  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5248      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5249                          (i32 imm:$cond), NZCV))]> {
5250    let Inst{23-22} = 0b11;
5251    let Predicates = [HasFullFP16];
5252  }
5253
5254  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5255      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5256                          (i32 imm:$cond), NZCV))]> {
5257    let Inst{23-22} = 0b00;
5258  }
5259
5260  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5261      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5262                          (i32 imm:$cond), NZCV))]> {
5263    let Inst{23-22} = 0b01;
5264  }
5265}
5266
5267//---
5268// Floating point conditional select
5269//---
5270
5271class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5272    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5273         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5274         [(set regtype:$Rd,
5275               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5276                          (i32 imm:$cond), NZCV))]>,
5277      Sched<[WriteF]> {
5278  bits<5> Rd;
5279  bits<5> Rn;
5280  bits<5> Rm;
5281  bits<4> cond;
5282
5283  let Inst{31-24} = 0b00011110;
5284  let Inst{21}    = 1;
5285  let Inst{20-16} = Rm;
5286  let Inst{15-12} = cond;
5287  let Inst{11-10} = 0b11;
5288  let Inst{9-5}   = Rn;
5289  let Inst{4-0}   = Rd;
5290}
5291
5292multiclass FPCondSelect<string asm> {
5293  let Uses = [NZCV] in {
5294  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5295    let Inst{23-22} = 0b11;
5296    let Predicates = [HasFullFP16];
5297  }
5298
5299  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5300    let Inst{23-22} = 0b00;
5301  }
5302
5303  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5304    let Inst{23-22} = 0b01;
5305  }
5306  } // Uses = [NZCV]
5307}
5308
5309//---
5310// Floating move immediate
5311//---
5312
5313class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5314  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5315      [(set regtype:$Rd, fpimmtype:$imm)]>,
5316    Sched<[WriteFImm]> {
5317  bits<5> Rd;
5318  bits<8> imm;
5319  let Inst{31-24} = 0b00011110;
5320  let Inst{21}    = 1;
5321  let Inst{20-13} = imm;
5322  let Inst{12-5}  = 0b10000000;
5323  let Inst{4-0}   = Rd;
5324}
5325
5326multiclass FPMoveImmediate<string asm> {
5327  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5328    let Inst{23-22} = 0b11;
5329    let Predicates = [HasFullFP16];
5330  }
5331
5332  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5333    let Inst{23-22} = 0b00;
5334  }
5335
5336  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5337    let Inst{23-22} = 0b01;
5338  }
5339}
5340} // end of 'let Predicates = [HasFPARMv8]'
5341
5342//----------------------------------------------------------------------------
5343// AdvSIMD
5344//----------------------------------------------------------------------------
5345
5346let Predicates = [HasNEON] in {
5347
5348//----------------------------------------------------------------------------
5349// AdvSIMD three register vector instructions
5350//----------------------------------------------------------------------------
5351
5352let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5353class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5354                        RegisterOperand regtype, string asm, string kind,
5355                        list<dag> pattern>
5356  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5357      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5358      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5359    Sched<[!if(Q, WriteVq, WriteVd)]> {
5360  bits<5> Rd;
5361  bits<5> Rn;
5362  bits<5> Rm;
5363  let Inst{31}    = 0;
5364  let Inst{30}    = Q;
5365  let Inst{29}    = U;
5366  let Inst{28-24} = 0b01110;
5367  let Inst{23-21} = size;
5368  let Inst{20-16} = Rm;
5369  let Inst{15-11} = opcode;
5370  let Inst{10}    = 1;
5371  let Inst{9-5}   = Rn;
5372  let Inst{4-0}   = Rd;
5373}
5374
5375let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5376class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5377                        RegisterOperand regtype, string asm, string kind,
5378                        list<dag> pattern>
5379  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5380      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5381      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5382    Sched<[!if(Q, WriteVq, WriteVd)]> {
5383  bits<5> Rd;
5384  bits<5> Rn;
5385  bits<5> Rm;
5386  let Inst{31}    = 0;
5387  let Inst{30}    = Q;
5388  let Inst{29}    = U;
5389  let Inst{28-24} = 0b01110;
5390  let Inst{23-21} = size;
5391  let Inst{20-16} = Rm;
5392  let Inst{15-11} = opcode;
5393  let Inst{10}    = 1;
5394  let Inst{9-5}   = Rn;
5395  let Inst{4-0}   = Rd;
5396}
5397
5398let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5399class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5400  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5401    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5402
5403multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5404  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5405             [(set (v8i8 V64:$dst),
5406                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5407  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5408             [(set (v16i8 V128:$dst),
5409                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5410                           (v16i8 V128:$Rm)))]>;
5411
5412  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5413                           (v4i16 V64:$RHS))),
5414          (!cast<Instruction>(NAME#"v8i8")
5415            V64:$LHS, V64:$MHS, V64:$RHS)>;
5416  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5417                           (v2i32 V64:$RHS))),
5418          (!cast<Instruction>(NAME#"v8i8")
5419            V64:$LHS, V64:$MHS, V64:$RHS)>;
5420  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5421                           (v1i64 V64:$RHS))),
5422          (!cast<Instruction>(NAME#"v8i8")
5423            V64:$LHS, V64:$MHS, V64:$RHS)>;
5424
5425  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5426                           (v8i16 V128:$RHS))),
5427      (!cast<Instruction>(NAME#"v16i8")
5428        V128:$LHS, V128:$MHS, V128:$RHS)>;
5429  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5430                           (v4i32 V128:$RHS))),
5431      (!cast<Instruction>(NAME#"v16i8")
5432        V128:$LHS, V128:$MHS, V128:$RHS)>;
5433  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5434                           (v2i64 V128:$RHS))),
5435      (!cast<Instruction>(NAME#"v16i8")
5436        V128:$LHS, V128:$MHS, V128:$RHS)>;
5437}
5438
5439// All operand sizes distinguished in the encoding.
5440multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5441                               SDPatternOperator OpNode> {
5442  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5443                                      asm, ".8b",
5444         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5445  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5446                                      asm, ".16b",
5447         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5448  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5449                                      asm, ".4h",
5450         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5451  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5452                                      asm, ".8h",
5453         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5454  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5455                                      asm, ".2s",
5456         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5457  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5458                                      asm, ".4s",
5459         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5460  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5461                                      asm, ".2d",
5462         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5463}
5464
5465multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5466  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5467          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5468  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5469          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5470  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5471          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5472
5473  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5474          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5475  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5476          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5477  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5478          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5479  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5480          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5481}
5482
5483// As above, but D sized elements unsupported.
5484multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5485                                  SDPatternOperator OpNode> {
5486  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5487                                      asm, ".8b",
5488        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5489  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5490                                      asm, ".16b",
5491        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5492  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5493                                      asm, ".4h",
5494        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5495  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5496                                      asm, ".8h",
5497        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5498  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5499                                      asm, ".2s",
5500        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5501  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5502                                      asm, ".4s",
5503        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5504}
5505
5506multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5507                                  SDPatternOperator OpNode> {
5508  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5509                                      asm, ".8b",
5510      [(set (v8i8 V64:$dst),
5511            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5512  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5513                                      asm, ".16b",
5514      [(set (v16i8 V128:$dst),
5515            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5516  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5517                                      asm, ".4h",
5518      [(set (v4i16 V64:$dst),
5519            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5520  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5521                                      asm, ".8h",
5522      [(set (v8i16 V128:$dst),
5523            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5524  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5525                                      asm, ".2s",
5526      [(set (v2i32 V64:$dst),
5527            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5528  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5529                                      asm, ".4s",
5530      [(set (v4i32 V128:$dst),
5531            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5532}
5533
5534// As above, but only B sized elements supported.
5535multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5536                                SDPatternOperator OpNode> {
5537  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5538                                      asm, ".8b",
5539    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5540  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5541                                      asm, ".16b",
5542    [(set (v16i8 V128:$Rd),
5543          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5544}
5545
5546// As above, but only floating point elements supported.
5547multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5548                                 string asm, SDPatternOperator OpNode> {
5549  let Predicates = [HasNEON, HasFullFP16] in {
5550  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5551                                      asm, ".4h",
5552        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5553  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5554                                      asm, ".8h",
5555        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5556  } // Predicates = [HasNEON, HasFullFP16]
5557  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5558                                      asm, ".2s",
5559        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5560  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5561                                      asm, ".4s",
5562        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5563  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5564                                      asm, ".2d",
5565        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5566}
5567
5568multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5569                                    string asm,
5570                                    SDPatternOperator OpNode> {
5571  let Predicates = [HasNEON, HasFullFP16] in {
5572  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5573                                      asm, ".4h",
5574        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5575  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5576                                      asm, ".8h",
5577        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5578  } // Predicates = [HasNEON, HasFullFP16]
5579  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5580                                      asm, ".2s",
5581        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5582  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5583                                      asm, ".4s",
5584        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5585  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5586                                      asm, ".2d",
5587        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5588}
5589
5590multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5591                                 string asm, SDPatternOperator OpNode> {
5592  let Predicates = [HasNEON, HasFullFP16] in {
5593  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5594                                      asm, ".4h",
5595     [(set (v4f16 V64:$dst),
5596           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5597  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5598                                      asm, ".8h",
5599     [(set (v8f16 V128:$dst),
5600           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5601  } // Predicates = [HasNEON, HasFullFP16]
5602  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5603                                      asm, ".2s",
5604     [(set (v2f32 V64:$dst),
5605           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5606  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5607                                      asm, ".4s",
5608     [(set (v4f32 V128:$dst),
5609           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5610  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5611                                      asm, ".2d",
5612     [(set (v2f64 V128:$dst),
5613           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5614}
5615
5616// As above, but D and B sized elements unsupported.
5617multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5618                                SDPatternOperator OpNode> {
5619  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5620                                      asm, ".4h",
5621        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5622  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5623                                      asm, ".8h",
5624        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5625  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5626                                      asm, ".2s",
5627        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5628  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5629                                      asm, ".4s",
5630        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5631}
5632
5633// Logical three vector ops share opcode bits, and only use B sized elements.
5634multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5635                                  SDPatternOperator OpNode = null_frag> {
5636  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5637                                     asm, ".8b",
5638                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5639  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5640                                     asm, ".16b",
5641                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5642
5643  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5644          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5645  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5646          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5647  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5648          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5649
5650  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5651      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5652  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5653      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5654  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5655      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5656}
5657
5658multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5659                                  string asm, SDPatternOperator OpNode = null_frag> {
5660  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5661                                     asm, ".8b",
5662             [(set (v8i8 V64:$dst),
5663                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5664  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5665                                     asm, ".16b",
5666             [(set (v16i8 V128:$dst),
5667                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5668                           (v16i8 V128:$Rm)))]>;
5669
5670  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5671                           (v4i16 V64:$RHS))),
5672          (!cast<Instruction>(NAME#"v8i8")
5673            V64:$LHS, V64:$MHS, V64:$RHS)>;
5674  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5675                           (v2i32 V64:$RHS))),
5676          (!cast<Instruction>(NAME#"v8i8")
5677            V64:$LHS, V64:$MHS, V64:$RHS)>;
5678  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5679                           (v1i64 V64:$RHS))),
5680          (!cast<Instruction>(NAME#"v8i8")
5681            V64:$LHS, V64:$MHS, V64:$RHS)>;
5682
5683  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5684                           (v8i16 V128:$RHS))),
5685      (!cast<Instruction>(NAME#"v16i8")
5686        V128:$LHS, V128:$MHS, V128:$RHS)>;
5687  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5688                           (v4i32 V128:$RHS))),
5689      (!cast<Instruction>(NAME#"v16i8")
5690        V128:$LHS, V128:$MHS, V128:$RHS)>;
5691  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5692                           (v2i64 V128:$RHS))),
5693      (!cast<Instruction>(NAME#"v16i8")
5694        V128:$LHS, V128:$MHS, V128:$RHS)>;
5695}
5696
5697// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5698// bytes from S-sized elements.
5699class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5700                                 string kind2, RegisterOperand RegType,
5701                                 ValueType AccumType, ValueType InputType,
5702                                 SDPatternOperator OpNode> :
5703        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5704        [(set (AccumType RegType:$dst),
5705              (OpNode (AccumType RegType:$Rd),
5706                      (InputType RegType:$Rn),
5707                      (InputType RegType:$Rm)))]> {
5708  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5709}
5710
5711multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5712  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5713                                         v2i32, v8i8, OpNode>;
5714  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5715                                         v4i32, v16i8, OpNode>;
5716}
5717
5718// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5719// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5720// 8H to 4S, when Q=1).
5721class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5722                                 string kind2, RegisterOperand RegType,
5723                                 ValueType AccumType, ValueType InputType,
5724                                 SDPatternOperator OpNode> :
5725        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5726		[(set (AccumType RegType:$dst),
5727              (OpNode (AccumType RegType:$Rd),
5728                      (InputType RegType:$Rn),
5729                      (InputType RegType:$Rm)))]> {
5730  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5731  let Inst{13} = b13;
5732}
5733
5734multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5735                                  SDPatternOperator OpNode> {
5736  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5737                                         v2f32, v4f16, OpNode>;
5738  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5739                                         v4f32, v8f16, OpNode>;
5740}
5741
5742
5743//----------------------------------------------------------------------------
5744// AdvSIMD two register vector instructions.
5745//----------------------------------------------------------------------------
5746
5747let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5748class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5749                            bits<2> size2, RegisterOperand regtype, string asm,
5750                            string dstkind, string srckind, list<dag> pattern>
5751  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5752      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5753      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5754    Sched<[!if(Q, WriteVq, WriteVd)]> {
5755  bits<5> Rd;
5756  bits<5> Rn;
5757  let Inst{31}    = 0;
5758  let Inst{30}    = Q;
5759  let Inst{29}    = U;
5760  let Inst{28-24} = 0b01110;
5761  let Inst{23-22} = size;
5762  let Inst{21} = 0b1;
5763  let Inst{20-19} = size2;
5764  let Inst{18-17} = 0b00;
5765  let Inst{16-12} = opcode;
5766  let Inst{11-10} = 0b10;
5767  let Inst{9-5}   = Rn;
5768  let Inst{4-0}   = Rd;
5769}
5770
5771let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5772class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5773                                bits<2> size2, RegisterOperand regtype,
5774                                string asm, string dstkind, string srckind,
5775                                list<dag> pattern>
5776  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5777      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5778      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5779    Sched<[!if(Q, WriteVq, WriteVd)]> {
5780  bits<5> Rd;
5781  bits<5> Rn;
5782  let Inst{31}    = 0;
5783  let Inst{30}    = Q;
5784  let Inst{29}    = U;
5785  let Inst{28-24} = 0b01110;
5786  let Inst{23-22} = size;
5787  let Inst{21} = 0b1;
5788  let Inst{20-19} = size2;
5789  let Inst{18-17} = 0b00;
5790  let Inst{16-12} = opcode;
5791  let Inst{11-10} = 0b10;
5792  let Inst{9-5}   = Rn;
5793  let Inst{4-0}   = Rd;
5794}
5795
5796// Supports B, H, and S element sizes.
5797multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5798                            SDPatternOperator OpNode> {
5799  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5800                                      asm, ".8b", ".8b",
5801                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5802  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5803                                      asm, ".16b", ".16b",
5804                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5805  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5806                                      asm, ".4h", ".4h",
5807                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5808  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5809                                      asm, ".8h", ".8h",
5810                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5811  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5812                                      asm, ".2s", ".2s",
5813                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5814  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5815                                      asm, ".4s", ".4s",
5816                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5817}
5818
5819class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5820                            RegisterOperand regtype, string asm, string dstkind,
5821                            string srckind, string amount>
5822  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5823      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5824      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5825    Sched<[WriteVq]> {
5826  bits<5> Rd;
5827  bits<5> Rn;
5828  let Inst{31}    = 0;
5829  let Inst{30}    = Q;
5830  let Inst{29-24} = 0b101110;
5831  let Inst{23-22} = size;
5832  let Inst{21-10} = 0b100001001110;
5833  let Inst{9-5}   = Rn;
5834  let Inst{4-0}   = Rd;
5835}
5836
5837multiclass SIMDVectorLShiftLongBySizeBHS {
5838  let hasSideEffects = 0 in {
5839  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5840                                             "shll", ".8h",  ".8b", "8">;
5841  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5842                                             "shll2", ".8h", ".16b", "8">;
5843  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5844                                             "shll", ".4s",  ".4h", "16">;
5845  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5846                                             "shll2", ".4s", ".8h", "16">;
5847  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5848                                             "shll", ".2d",  ".2s", "32">;
5849  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5850                                             "shll2", ".2d", ".4s", "32">;
5851  }
5852}
5853
5854// Supports all element sizes.
5855multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5856                             SDPatternOperator OpNode> {
5857  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5858                                      asm, ".4h", ".8b",
5859               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5860  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5861                                      asm, ".8h", ".16b",
5862               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5863  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5864                                      asm, ".2s", ".4h",
5865               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5866  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5867                                      asm, ".4s", ".8h",
5868               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5869  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5870                                      asm, ".1d", ".2s",
5871               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5872  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5873                                      asm, ".2d", ".4s",
5874               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5875}
5876
5877multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5878                                 SDPatternOperator OpNode> {
5879  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5880                                          asm, ".4h", ".8b",
5881      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5882                                      (v8i8 V64:$Rn)))]>;
5883  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5884                                          asm, ".8h", ".16b",
5885      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5886                                      (v16i8 V128:$Rn)))]>;
5887  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5888                                          asm, ".2s", ".4h",
5889      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5890                                      (v4i16 V64:$Rn)))]>;
5891  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5892                                          asm, ".4s", ".8h",
5893      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5894                                      (v8i16 V128:$Rn)))]>;
5895  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5896                                          asm, ".1d", ".2s",
5897      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5898                                      (v2i32 V64:$Rn)))]>;
5899  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5900                                          asm, ".2d", ".4s",
5901      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5902                                      (v4i32 V128:$Rn)))]>;
5903}
5904
5905// Supports all element sizes, except 1xD.
5906multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5907                                  SDPatternOperator OpNode> {
5908  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5909                                    asm, ".8b", ".8b",
5910    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5911  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5912                                    asm, ".16b", ".16b",
5913    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5914  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5915                                    asm, ".4h", ".4h",
5916    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5917  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5918                                    asm, ".8h", ".8h",
5919    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5920  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5921                                    asm, ".2s", ".2s",
5922    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5923  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5924                                    asm, ".4s", ".4s",
5925    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5926  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5927                                    asm, ".2d", ".2d",
5928    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5929}
5930
5931multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5932                             SDPatternOperator OpNode = null_frag> {
5933  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5934                                asm, ".8b", ".8b",
5935    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5936  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5937                                asm, ".16b", ".16b",
5938    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5939  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5940                                asm, ".4h", ".4h",
5941    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5942  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5943                                asm, ".8h", ".8h",
5944    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5945  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5946                                asm, ".2s", ".2s",
5947    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5948  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5949                                asm, ".4s", ".4s",
5950    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5951  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5952                                asm, ".2d", ".2d",
5953    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5954}
5955
5956
5957// Supports only B element sizes.
5958multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5959                          SDPatternOperator OpNode> {
5960  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5961                                asm, ".8b", ".8b",
5962                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5963  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5964                                asm, ".16b", ".16b",
5965                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5966
5967}
5968
5969// Supports only B and H element sizes.
5970multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5971                                SDPatternOperator OpNode> {
5972  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5973                                asm, ".8b", ".8b",
5974                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5975  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5976                                asm, ".16b", ".16b",
5977                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5978  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5979                                asm, ".4h", ".4h",
5980                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5981  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5982                                asm, ".8h", ".8h",
5983                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5984}
5985
5986// Supports H, S and D element sizes, uses high bit of the size field
5987// as an extra opcode bit.
5988multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5989                           SDPatternOperator OpNode> {
5990  let Predicates = [HasNEON, HasFullFP16] in {
5991  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5992                                asm, ".4h", ".4h",
5993                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5994  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5995                                asm, ".8h", ".8h",
5996                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5997  } // Predicates = [HasNEON, HasFullFP16]
5998  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5999                                asm, ".2s", ".2s",
6000                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6001  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6002                                asm, ".4s", ".4s",
6003                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6004  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6005                                asm, ".2d", ".2d",
6006                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6007}
6008
6009// Supports only S and D element sizes
6010multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6011                           SDPatternOperator OpNode = null_frag> {
6012
6013  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6014                                asm, ".2s", ".2s",
6015                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6016  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6017                                asm, ".4s", ".4s",
6018                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6019  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6020                                asm, ".2d", ".2d",
6021                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6022}
6023
6024multiclass FRIntNNTVector<bit U, bit op, string asm,
6025                          SDPatternOperator OpNode = null_frag> :
6026           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6027
6028// Supports only S element size.
6029multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6030                           SDPatternOperator OpNode> {
6031  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6032                                asm, ".2s", ".2s",
6033                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6034  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6035                                asm, ".4s", ".4s",
6036                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6037}
6038
6039
6040multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6041                           SDPatternOperator OpNode> {
6042  let Predicates = [HasNEON, HasFullFP16] in {
6043  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6044                                asm, ".4h", ".4h",
6045                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6046  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6047                                asm, ".8h", ".8h",
6048                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6049  } // Predicates = [HasNEON, HasFullFP16]
6050  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6051                                asm, ".2s", ".2s",
6052                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6053  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6054                                asm, ".4s", ".4s",
6055                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6056  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6057                                asm, ".2d", ".2d",
6058                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6059}
6060
6061multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6062                           SDPatternOperator OpNode> {
6063  let Predicates = [HasNEON, HasFullFP16] in {
6064  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6065                                asm, ".4h", ".4h",
6066                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6067  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6068                                asm, ".8h", ".8h",
6069                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6070  } // Predicates = [HasNEON, HasFullFP16]
6071  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6072                                asm, ".2s", ".2s",
6073                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6074  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6075                                asm, ".4s", ".4s",
6076                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6077  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6078                                asm, ".2d", ".2d",
6079                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6080}
6081
6082let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6083class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6084                           RegisterOperand inreg, RegisterOperand outreg,
6085                           string asm, string outkind, string inkind,
6086                           list<dag> pattern>
6087  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6088      "{\t$Rd" # outkind # ", $Rn" # inkind #
6089      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6090    Sched<[WriteVq]> {
6091  bits<5> Rd;
6092  bits<5> Rn;
6093  let Inst{31}    = 0;
6094  let Inst{30}    = Q;
6095  let Inst{29}    = U;
6096  let Inst{28-24} = 0b01110;
6097  let Inst{23-22} = size;
6098  let Inst{21-17} = 0b10000;
6099  let Inst{16-12} = opcode;
6100  let Inst{11-10} = 0b10;
6101  let Inst{9-5}   = Rn;
6102  let Inst{4-0}   = Rd;
6103}
6104
6105let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6106class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6107                           RegisterOperand inreg, RegisterOperand outreg,
6108                           string asm, string outkind, string inkind,
6109                           list<dag> pattern>
6110  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6111      "{\t$Rd" # outkind # ", $Rn" # inkind #
6112      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6113    Sched<[WriteVq]> {
6114  bits<5> Rd;
6115  bits<5> Rn;
6116  let Inst{31}    = 0;
6117  let Inst{30}    = Q;
6118  let Inst{29}    = U;
6119  let Inst{28-24} = 0b01110;
6120  let Inst{23-22} = size;
6121  let Inst{21-17} = 0b10000;
6122  let Inst{16-12} = opcode;
6123  let Inst{11-10} = 0b10;
6124  let Inst{9-5}   = Rn;
6125  let Inst{4-0}   = Rd;
6126}
6127
6128multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6129                              SDPatternOperator OpNode> {
6130  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6131                                      asm, ".8b", ".8h",
6132        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6133  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6134                                      asm#"2", ".16b", ".8h", []>;
6135  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6136                                      asm, ".4h", ".4s",
6137        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6138  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6139                                      asm#"2", ".8h", ".4s", []>;
6140  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6141                                      asm, ".2s", ".2d",
6142        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6143  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6144                                      asm#"2", ".4s", ".2d", []>;
6145
6146  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6147            (!cast<Instruction>(NAME # "v16i8")
6148                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6149  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6150            (!cast<Instruction>(NAME # "v8i16")
6151                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6152  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6153            (!cast<Instruction>(NAME # "v4i32")
6154                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6155}
6156
6157class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6158                           bits<5> opcode, RegisterOperand regtype, string asm,
6159                           string kind, string zero, ValueType dty,
6160                           ValueType sty, SDNode OpNode>
6161  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6162      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6163      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6164      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6165    Sched<[!if(Q, WriteVq, WriteVd)]> {
6166  bits<5> Rd;
6167  bits<5> Rn;
6168  let Inst{31}    = 0;
6169  let Inst{30}    = Q;
6170  let Inst{29}    = U;
6171  let Inst{28-24} = 0b01110;
6172  let Inst{23-22} = size;
6173  let Inst{21} = 0b1;
6174  let Inst{20-19} = size2;
6175  let Inst{18-17} = 0b00;
6176  let Inst{16-12} = opcode;
6177  let Inst{11-10} = 0b10;
6178  let Inst{9-5}   = Rn;
6179  let Inst{4-0}   = Rd;
6180}
6181
6182// Comparisons support all element sizes, except 1xD.
6183multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6184                            SDNode OpNode> {
6185  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6186                                     asm, ".8b", "0",
6187                                     v8i8, v8i8, OpNode>;
6188  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6189                                     asm, ".16b", "0",
6190                                     v16i8, v16i8, OpNode>;
6191  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6192                                     asm, ".4h", "0",
6193                                     v4i16, v4i16, OpNode>;
6194  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6195                                     asm, ".8h", "0",
6196                                     v8i16, v8i16, OpNode>;
6197  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6198                                     asm, ".2s", "0",
6199                                     v2i32, v2i32, OpNode>;
6200  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6201                                     asm, ".4s", "0",
6202                                     v4i32, v4i32, OpNode>;
6203  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6204                                     asm, ".2d", "0",
6205                                     v2i64, v2i64, OpNode>;
6206}
6207
6208// FP Comparisons support only S and D element sizes (and H for v8.2a).
6209multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6210                              string asm, SDNode OpNode> {
6211
6212  let Predicates = [HasNEON, HasFullFP16] in {
6213  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6214                                     asm, ".4h", "0.0",
6215                                     v4i16, v4f16, OpNode>;
6216  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6217                                     asm, ".8h", "0.0",
6218                                     v8i16, v8f16, OpNode>;
6219  } // Predicates = [HasNEON, HasFullFP16]
6220  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6221                                     asm, ".2s", "0.0",
6222                                     v2i32, v2f32, OpNode>;
6223  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6224                                     asm, ".4s", "0.0",
6225                                     v4i32, v4f32, OpNode>;
6226  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6227                                     asm, ".2d", "0.0",
6228                                     v2i64, v2f64, OpNode>;
6229
6230  let Predicates = [HasNEON, HasFullFP16] in {
6231  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6232                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6233  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6234                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6235  }
6236  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6237                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6238  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6239                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6240  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6241                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6242  let Predicates = [HasNEON, HasFullFP16] in {
6243  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6244                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6245  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6246                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6247  }
6248  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6249                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6250  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6251                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6252  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6253                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6254}
6255
6256let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6257class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6258                             RegisterOperand outtype, RegisterOperand intype,
6259                             string asm, string VdTy, string VnTy,
6260                             list<dag> pattern>
6261  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6262      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6263    Sched<[WriteVq]> {
6264  bits<5> Rd;
6265  bits<5> Rn;
6266  let Inst{31}    = 0;
6267  let Inst{30}    = Q;
6268  let Inst{29}    = U;
6269  let Inst{28-24} = 0b01110;
6270  let Inst{23-22} = size;
6271  let Inst{21-17} = 0b10000;
6272  let Inst{16-12} = opcode;
6273  let Inst{11-10} = 0b10;
6274  let Inst{9-5}   = Rn;
6275  let Inst{4-0}   = Rd;
6276}
6277
6278let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6279class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6280                             RegisterOperand outtype, RegisterOperand intype,
6281                             string asm, string VdTy, string VnTy,
6282                             list<dag> pattern>
6283  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6284      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6285    Sched<[WriteVq]> {
6286  bits<5> Rd;
6287  bits<5> Rn;
6288  let Inst{31}    = 0;
6289  let Inst{30}    = Q;
6290  let Inst{29}    = U;
6291  let Inst{28-24} = 0b01110;
6292  let Inst{23-22} = size;
6293  let Inst{21-17} = 0b10000;
6294  let Inst{16-12} = opcode;
6295  let Inst{11-10} = 0b10;
6296  let Inst{9-5}   = Rn;
6297  let Inst{4-0}   = Rd;
6298}
6299
6300multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6301  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6302                                    asm, ".4s", ".4h", []>;
6303  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6304                                    asm#"2", ".4s", ".8h", []>;
6305  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6306                                    asm, ".2d", ".2s", []>;
6307  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6308                                    asm#"2", ".2d", ".4s", []>;
6309}
6310
6311multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6312  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6313                                    asm, ".4h", ".4s", []>;
6314  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6315                                    asm#"2", ".8h", ".4s", []>;
6316  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6317                                    asm, ".2s", ".2d", []>;
6318  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6319                                    asm#"2", ".4s", ".2d", []>;
6320}
6321
6322multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6323                                     Intrinsic OpNode> {
6324  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6325                                     asm, ".2s", ".2d",
6326                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6327  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6328                                    asm#"2", ".4s", ".2d", []>;
6329
6330  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6331            (!cast<Instruction>(NAME # "v4f32")
6332                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6333}
6334
6335//----------------------------------------------------------------------------
6336// AdvSIMD three register different-size vector instructions.
6337//----------------------------------------------------------------------------
6338
6339let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6340class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6341                      RegisterOperand outtype, RegisterOperand intype1,
6342                      RegisterOperand intype2, string asm,
6343                      string outkind, string inkind1, string inkind2,
6344                      list<dag> pattern>
6345  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6346      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6347      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6348    Sched<[WriteVq]> {
6349  bits<5> Rd;
6350  bits<5> Rn;
6351  bits<5> Rm;
6352  let Inst{31}    = 0;
6353  let Inst{30}    = size{0};
6354  let Inst{29}    = U;
6355  let Inst{28-24} = 0b01110;
6356  let Inst{23-22} = size{2-1};
6357  let Inst{21}    = 1;
6358  let Inst{20-16} = Rm;
6359  let Inst{15-12} = opcode;
6360  let Inst{11-10} = 0b00;
6361  let Inst{9-5}   = Rn;
6362  let Inst{4-0}   = Rd;
6363}
6364
6365let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6366class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6367                      RegisterOperand outtype, RegisterOperand intype1,
6368                      RegisterOperand intype2, string asm,
6369                      string outkind, string inkind1, string inkind2,
6370                      list<dag> pattern>
6371  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6372      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6373      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6374    Sched<[WriteVq]> {
6375  bits<5> Rd;
6376  bits<5> Rn;
6377  bits<5> Rm;
6378  let Inst{31}    = 0;
6379  let Inst{30}    = size{0};
6380  let Inst{29}    = U;
6381  let Inst{28-24} = 0b01110;
6382  let Inst{23-22} = size{2-1};
6383  let Inst{21}    = 1;
6384  let Inst{20-16} = Rm;
6385  let Inst{15-12} = opcode;
6386  let Inst{11-10} = 0b00;
6387  let Inst{9-5}   = Rn;
6388  let Inst{4-0}   = Rd;
6389}
6390
6391// FIXME: TableGen doesn't know how to deal with expanded types that also
6392//        change the element count (in this case, placing the results in
6393//        the high elements of the result register rather than the low
6394//        elements). Until that's fixed, we can't code-gen those.
6395multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6396                                    Intrinsic IntOp> {
6397  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6398                                                  V64, V128, V128,
6399                                                  asm, ".8b", ".8h", ".8h",
6400     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6401  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6402                                                  V128, V128, V128,
6403                                                  asm#"2", ".16b", ".8h", ".8h",
6404     []>;
6405  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6406                                                  V64, V128, V128,
6407                                                  asm, ".4h", ".4s", ".4s",
6408     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6409  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6410                                                  V128, V128, V128,
6411                                                  asm#"2", ".8h", ".4s", ".4s",
6412     []>;
6413  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6414                                                  V64, V128, V128,
6415                                                  asm, ".2s", ".2d", ".2d",
6416     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6417  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6418                                                  V128, V128, V128,
6419                                                  asm#"2", ".4s", ".2d", ".2d",
6420     []>;
6421
6422
6423  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6424  // a version attached to an instruction.
6425  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6426                                                   (v8i16 V128:$Rm))),
6427            (!cast<Instruction>(NAME # "v8i16_v16i8")
6428                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6429                V128:$Rn, V128:$Rm)>;
6430  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6431                                                    (v4i32 V128:$Rm))),
6432            (!cast<Instruction>(NAME # "v4i32_v8i16")
6433                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6434                V128:$Rn, V128:$Rm)>;
6435  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6436                                                    (v2i64 V128:$Rm))),
6437            (!cast<Instruction>(NAME # "v2i64_v4i32")
6438                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6439                V128:$Rn, V128:$Rm)>;
6440}
6441
6442multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6443                                      Intrinsic IntOp> {
6444  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6445                                            V128, V64, V64,
6446                                            asm, ".8h", ".8b", ".8b",
6447      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6448  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6449                                            V128, V128, V128,
6450                                            asm#"2", ".8h", ".16b", ".16b", []>;
6451  let Predicates = [HasAES] in {
6452    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6453                                              V128, V64, V64,
6454                                              asm, ".1q", ".1d", ".1d", []>;
6455    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6456                                              V128, V128, V128,
6457                                              asm#"2", ".1q", ".2d", ".2d", []>;
6458  }
6459
6460  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6461                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6462      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6463}
6464
6465multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6466                                 SDPatternOperator OpNode> {
6467  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6468                                                  V128, V64, V64,
6469                                                  asm, ".4s", ".4h", ".4h",
6470      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6471  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6472                                                  V128, V128, V128,
6473                                                  asm#"2", ".4s", ".8h", ".8h",
6474      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6475                                      (extract_high_v8i16 V128:$Rm)))]>;
6476  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6477                                                  V128, V64, V64,
6478                                                  asm, ".2d", ".2s", ".2s",
6479      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6480  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6481                                                  V128, V128, V128,
6482                                                  asm#"2", ".2d", ".4s", ".4s",
6483      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6484                                      (extract_high_v4i32 V128:$Rm)))]>;
6485}
6486
6487multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6488                                  SDPatternOperator OpNode = null_frag> {
6489  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6490                                                  V128, V64, V64,
6491                                                  asm, ".8h", ".8b", ".8b",
6492      [(set (v8i16 V128:$Rd),
6493            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6494  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6495                                                 V128, V128, V128,
6496                                                 asm#"2", ".8h", ".16b", ".16b",
6497      [(set (v8i16 V128:$Rd),
6498            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6499                                (extract_high_v16i8 V128:$Rm)))))]>;
6500  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6501                                                  V128, V64, V64,
6502                                                  asm, ".4s", ".4h", ".4h",
6503      [(set (v4i32 V128:$Rd),
6504            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6505  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6506                                                  V128, V128, V128,
6507                                                  asm#"2", ".4s", ".8h", ".8h",
6508      [(set (v4i32 V128:$Rd),
6509            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6510                                  (extract_high_v8i16 V128:$Rm)))))]>;
6511  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6512                                                  V128, V64, V64,
6513                                                  asm, ".2d", ".2s", ".2s",
6514      [(set (v2i64 V128:$Rd),
6515            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6516  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6517                                                  V128, V128, V128,
6518                                                  asm#"2", ".2d", ".4s", ".4s",
6519      [(set (v2i64 V128:$Rd),
6520            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6521                                 (extract_high_v4i32 V128:$Rm)))))]>;
6522}
6523
6524multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6525                                          string asm,
6526                                          SDPatternOperator OpNode> {
6527  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6528                                                  V128, V64, V64,
6529                                                  asm, ".8h", ".8b", ".8b",
6530    [(set (v8i16 V128:$dst),
6531          (add (v8i16 V128:$Rd),
6532               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6533  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6534                                                 V128, V128, V128,
6535                                                 asm#"2", ".8h", ".16b", ".16b",
6536    [(set (v8i16 V128:$dst),
6537          (add (v8i16 V128:$Rd),
6538               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6539                                   (extract_high_v16i8 V128:$Rm))))))]>;
6540  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6541                                                  V128, V64, V64,
6542                                                  asm, ".4s", ".4h", ".4h",
6543    [(set (v4i32 V128:$dst),
6544          (add (v4i32 V128:$Rd),
6545               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6546  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6547                                                  V128, V128, V128,
6548                                                  asm#"2", ".4s", ".8h", ".8h",
6549    [(set (v4i32 V128:$dst),
6550          (add (v4i32 V128:$Rd),
6551               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6552                                    (extract_high_v8i16 V128:$Rm))))))]>;
6553  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6554                                                  V128, V64, V64,
6555                                                  asm, ".2d", ".2s", ".2s",
6556    [(set (v2i64 V128:$dst),
6557          (add (v2i64 V128:$Rd),
6558               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6559  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6560                                                  V128, V128, V128,
6561                                                  asm#"2", ".2d", ".4s", ".4s",
6562    [(set (v2i64 V128:$dst),
6563          (add (v2i64 V128:$Rd),
6564               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6565                                    (extract_high_v4i32 V128:$Rm))))))]>;
6566}
6567
6568multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6569                                  SDPatternOperator OpNode = null_frag> {
6570  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6571                                                  V128, V64, V64,
6572                                                  asm, ".8h", ".8b", ".8b",
6573      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6574  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6575                                                 V128, V128, V128,
6576                                                 asm#"2", ".8h", ".16b", ".16b",
6577      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6578                                      (extract_high_v16i8 V128:$Rm)))]>;
6579  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6580                                                  V128, V64, V64,
6581                                                  asm, ".4s", ".4h", ".4h",
6582      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6583  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6584                                                  V128, V128, V128,
6585                                                  asm#"2", ".4s", ".8h", ".8h",
6586      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6587                                      (extract_high_v8i16 V128:$Rm)))]>;
6588  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6589                                                  V128, V64, V64,
6590                                                  asm, ".2d", ".2s", ".2s",
6591      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6592  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6593                                                  V128, V128, V128,
6594                                                  asm#"2", ".2d", ".4s", ".4s",
6595      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6596                                      (extract_high_v4i32 V128:$Rm)))]>;
6597}
6598
6599multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6600                                      string asm,
6601                                      SDPatternOperator OpNode> {
6602  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6603                                                  V128, V64, V64,
6604                                                  asm, ".8h", ".8b", ".8b",
6605    [(set (v8i16 V128:$dst),
6606          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6607  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6608                                                 V128, V128, V128,
6609                                                 asm#"2", ".8h", ".16b", ".16b",
6610    [(set (v8i16 V128:$dst),
6611          (OpNode (v8i16 V128:$Rd),
6612                  (extract_high_v16i8 V128:$Rn),
6613                  (extract_high_v16i8 V128:$Rm)))]>;
6614  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6615                                                  V128, V64, V64,
6616                                                  asm, ".4s", ".4h", ".4h",
6617    [(set (v4i32 V128:$dst),
6618          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6619  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6620                                                  V128, V128, V128,
6621                                                  asm#"2", ".4s", ".8h", ".8h",
6622    [(set (v4i32 V128:$dst),
6623          (OpNode (v4i32 V128:$Rd),
6624                  (extract_high_v8i16 V128:$Rn),
6625                  (extract_high_v8i16 V128:$Rm)))]>;
6626  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6627                                                  V128, V64, V64,
6628                                                  asm, ".2d", ".2s", ".2s",
6629    [(set (v2i64 V128:$dst),
6630          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6631  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6632                                                  V128, V128, V128,
6633                                                  asm#"2", ".2d", ".4s", ".4s",
6634    [(set (v2i64 V128:$dst),
6635          (OpNode (v2i64 V128:$Rd),
6636                  (extract_high_v4i32 V128:$Rn),
6637                  (extract_high_v4i32 V128:$Rm)))]>;
6638}
6639
6640multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6641                                           SDPatternOperator Accum> {
6642  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6643                                                  V128, V64, V64,
6644                                                  asm, ".4s", ".4h", ".4h",
6645    [(set (v4i32 V128:$dst),
6646          (Accum (v4i32 V128:$Rd),
6647                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6648                                                (v4i16 V64:$Rm)))))]>;
6649  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6650                                                  V128, V128, V128,
6651                                                  asm#"2", ".4s", ".8h", ".8h",
6652    [(set (v4i32 V128:$dst),
6653          (Accum (v4i32 V128:$Rd),
6654                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6655                                            (extract_high_v8i16 V128:$Rm)))))]>;
6656  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6657                                                  V128, V64, V64,
6658                                                  asm, ".2d", ".2s", ".2s",
6659    [(set (v2i64 V128:$dst),
6660          (Accum (v2i64 V128:$Rd),
6661                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6662                                                (v2i32 V64:$Rm)))))]>;
6663  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6664                                                  V128, V128, V128,
6665                                                  asm#"2", ".2d", ".4s", ".4s",
6666    [(set (v2i64 V128:$dst),
6667          (Accum (v2i64 V128:$Rd),
6668                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6669                                            (extract_high_v4i32 V128:$Rm)))))]>;
6670}
6671
6672multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6673                                  SDPatternOperator OpNode> {
6674  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6675                                                  V128, V128, V64,
6676                                                  asm, ".8h", ".8h", ".8b",
6677       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6678  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6679                                                  V128, V128, V128,
6680                                                  asm#"2", ".8h", ".8h", ".16b",
6681       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6682                                       (extract_high_v16i8 V128:$Rm)))]>;
6683  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6684                                                  V128, V128, V64,
6685                                                  asm, ".4s", ".4s", ".4h",
6686       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6687  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6688                                                  V128, V128, V128,
6689                                                  asm#"2", ".4s", ".4s", ".8h",
6690       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6691                                       (extract_high_v8i16 V128:$Rm)))]>;
6692  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6693                                                  V128, V128, V64,
6694                                                  asm, ".2d", ".2d", ".2s",
6695       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6696  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6697                                                  V128, V128, V128,
6698                                                  asm#"2", ".2d", ".2d", ".4s",
6699       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6700                                       (extract_high_v4i32 V128:$Rm)))]>;
6701}
6702
6703//----------------------------------------------------------------------------
6704// AdvSIMD bitwise extract from vector
6705//----------------------------------------------------------------------------
6706
6707class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6708                             string asm, string kind>
6709  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6710      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6711      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6712      [(set (vty regtype:$Rd),
6713            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6714    Sched<[!if(size, WriteVq, WriteVd)]> {
6715  bits<5> Rd;
6716  bits<5> Rn;
6717  bits<5> Rm;
6718  bits<4> imm;
6719  let Inst{31}    = 0;
6720  let Inst{30}    = size;
6721  let Inst{29-21} = 0b101110000;
6722  let Inst{20-16} = Rm;
6723  let Inst{15}    = 0;
6724  let Inst{14-11} = imm;
6725  let Inst{10}    = 0;
6726  let Inst{9-5}   = Rn;
6727  let Inst{4-0}   = Rd;
6728}
6729
6730
6731multiclass SIMDBitwiseExtract<string asm> {
6732  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6733    let imm{3} = 0;
6734  }
6735  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6736}
6737
6738//----------------------------------------------------------------------------
6739// AdvSIMD zip vector
6740//----------------------------------------------------------------------------
6741
6742class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6743                        string asm, string kind, SDNode OpNode, ValueType valty>
6744  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6745      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6746      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6747      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6748    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
6749  bits<5> Rd;
6750  bits<5> Rn;
6751  bits<5> Rm;
6752  let Inst{31}    = 0;
6753  let Inst{30}    = size{0};
6754  let Inst{29-24} = 0b001110;
6755  let Inst{23-22} = size{2-1};
6756  let Inst{21}    = 0;
6757  let Inst{20-16} = Rm;
6758  let Inst{15}    = 0;
6759  let Inst{14-12} = opc;
6760  let Inst{11-10} = 0b10;
6761  let Inst{9-5}   = Rn;
6762  let Inst{4-0}   = Rd;
6763}
6764
6765multiclass SIMDZipVector<bits<3>opc, string asm,
6766                         SDNode OpNode> {
6767  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6768      asm, ".8b", OpNode, v8i8>;
6769  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6770      asm, ".16b", OpNode, v16i8>;
6771  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6772      asm, ".4h", OpNode, v4i16>;
6773  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6774      asm, ".8h", OpNode, v8i16>;
6775  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6776      asm, ".2s", OpNode, v2i32>;
6777  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6778      asm, ".4s", OpNode, v4i32>;
6779  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6780      asm, ".2d", OpNode, v2i64>;
6781
6782  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6783        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6784  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6785        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6786  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6787        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6788  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6789        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6790  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6791        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6792}
6793
6794//----------------------------------------------------------------------------
6795// AdvSIMD three register scalar instructions
6796//----------------------------------------------------------------------------
6797
6798let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6799class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6800                        RegisterClass regtype, string asm,
6801                        list<dag> pattern>
6802  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6803      "\t$Rd, $Rn, $Rm", "", pattern>,
6804    Sched<[WriteVd]> {
6805  bits<5> Rd;
6806  bits<5> Rn;
6807  bits<5> Rm;
6808  let Inst{31-30} = 0b01;
6809  let Inst{29}    = U;
6810  let Inst{28-24} = 0b11110;
6811  let Inst{23-21} = size;
6812  let Inst{20-16} = Rm;
6813  let Inst{15-11} = opcode;
6814  let Inst{10}    = 1;
6815  let Inst{9-5}   = Rn;
6816  let Inst{4-0}   = Rd;
6817}
6818
6819let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6820class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6821                        dag oops, dag iops, string asm,
6822            list<dag> pattern>
6823  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6824    Sched<[WriteVd]> {
6825  bits<5> Rd;
6826  bits<5> Rn;
6827  bits<5> Rm;
6828  let Inst{31-30} = 0b01;
6829  let Inst{29}    = U;
6830  let Inst{28-24} = 0b11110;
6831  let Inst{23-22} = size;
6832  let Inst{21}    = R;
6833  let Inst{20-16} = Rm;
6834  let Inst{15-11} = opcode;
6835  let Inst{10}    = 1;
6836  let Inst{9-5}   = Rn;
6837  let Inst{4-0}   = Rd;
6838}
6839
6840multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6841                            SDPatternOperator OpNode> {
6842  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6843    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6844}
6845
6846multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6847                               SDPatternOperator OpNode> {
6848  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6849    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6850  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6851  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6852  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6853
6854  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6855            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6856  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6857            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6858}
6859
6860multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6861                             SDPatternOperator OpNode> {
6862  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6863                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6864  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6865}
6866
6867multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
6868  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6869                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6870                                     asm, []>;
6871  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6872                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6873                                     asm, []>;
6874}
6875
6876multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6877                             SDPatternOperator OpNode = null_frag,
6878                             Predicate pred = HasNEON> {
6879  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6880    let Predicates = [pred] in {
6881    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6882      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6883    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6884      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6885    }
6886    let Predicates = [pred, HasFullFP16] in {
6887    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6888      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6889    }
6890  }
6891
6892  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6893            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6894}
6895
6896multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6897                                SDPatternOperator OpNode = null_frag> {
6898  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6899    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6900      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6901    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6902      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6903    let Predicates = [HasNEON, HasFullFP16] in {
6904    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6905      []>;
6906    } // Predicates = [HasNEON, HasFullFP16]
6907  }
6908
6909  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6910            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6911}
6912
6913class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6914              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6915  : I<oops, iops, asm,
6916      "\t$Rd, $Rn, $Rm", cstr, pat>,
6917    Sched<[WriteVd]> {
6918  bits<5> Rd;
6919  bits<5> Rn;
6920  bits<5> Rm;
6921  let Inst{31-30} = 0b01;
6922  let Inst{29}    = U;
6923  let Inst{28-24} = 0b11110;
6924  let Inst{23-22} = size;
6925  let Inst{21}    = 1;
6926  let Inst{20-16} = Rm;
6927  let Inst{15-11} = opcode;
6928  let Inst{10}    = 0;
6929  let Inst{9-5}   = Rn;
6930  let Inst{4-0}   = Rd;
6931}
6932
6933let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6934multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6935                                  SDPatternOperator OpNode = null_frag> {
6936  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6937                                      (outs FPR32:$Rd),
6938                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6939  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6940                                      (outs FPR64:$Rd),
6941                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6942            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6943}
6944
6945let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6946multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6947                                  SDPatternOperator OpNode = null_frag> {
6948  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6949                                      (outs FPR32:$dst),
6950                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6951                                      asm, "$Rd = $dst", []>;
6952  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6953                                      (outs FPR64:$dst),
6954                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6955                                      asm, "$Rd = $dst",
6956            [(set (i64 FPR64:$dst),
6957                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6958}
6959
6960//----------------------------------------------------------------------------
6961// AdvSIMD two register scalar instructions
6962//----------------------------------------------------------------------------
6963
6964let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6965class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6966                        RegisterClass regtype, RegisterClass regtype2,
6967                        string asm, list<dag> pat>
6968  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6969      "\t$Rd, $Rn", "", pat>,
6970    Sched<[WriteVd]> {
6971  bits<5> Rd;
6972  bits<5> Rn;
6973  let Inst{31-30} = 0b01;
6974  let Inst{29}    = U;
6975  let Inst{28-24} = 0b11110;
6976  let Inst{23-22} = size;
6977  let Inst{21} = 0b1;
6978  let Inst{20-19} = size2;
6979  let Inst{18-17} = 0b00;
6980  let Inst{16-12} = opcode;
6981  let Inst{11-10} = 0b10;
6982  let Inst{9-5}   = Rn;
6983  let Inst{4-0}   = Rd;
6984}
6985
6986let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6987class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6988                        RegisterClass regtype, RegisterClass regtype2,
6989                        string asm, list<dag> pat>
6990  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6991      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6992    Sched<[WriteVd]> {
6993  bits<5> Rd;
6994  bits<5> Rn;
6995  let Inst{31-30} = 0b01;
6996  let Inst{29}    = U;
6997  let Inst{28-24} = 0b11110;
6998  let Inst{23-22} = size;
6999  let Inst{21-17} = 0b10000;
7000  let Inst{16-12} = opcode;
7001  let Inst{11-10} = 0b10;
7002  let Inst{9-5}   = Rn;
7003  let Inst{4-0}   = Rd;
7004}
7005
7006
7007let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7008class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7009                        RegisterClass regtype, string asm, string zero>
7010  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7011      "\t$Rd, $Rn, #" # zero, "", []>,
7012    Sched<[WriteVd]> {
7013  bits<5> Rd;
7014  bits<5> Rn;
7015  let Inst{31-30} = 0b01;
7016  let Inst{29}    = U;
7017  let Inst{28-24} = 0b11110;
7018  let Inst{23-22} = size;
7019  let Inst{21} = 0b1;
7020  let Inst{20-19} = size2;
7021  let Inst{18-17} = 0b00;
7022  let Inst{16-12} = opcode;
7023  let Inst{11-10} = 0b10;
7024  let Inst{9-5}   = Rn;
7025  let Inst{4-0}   = Rd;
7026}
7027
7028class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7029  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7030     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7031    Sched<[WriteVd]> {
7032  bits<5> Rd;
7033  bits<5> Rn;
7034  let Inst{31-17} = 0b011111100110000;
7035  let Inst{16-12} = opcode;
7036  let Inst{11-10} = 0b10;
7037  let Inst{9-5}   = Rn;
7038  let Inst{4-0}   = Rd;
7039}
7040
7041multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7042                             SDPatternOperator OpNode> {
7043  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7044
7045  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7046            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7047}
7048
7049multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7050                              SDPatternOperator OpNode> {
7051  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7052  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7053  let Predicates = [HasNEON, HasFullFP16] in {
7054  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7055  }
7056
7057  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7058                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7059  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7060                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7061  let Predicates = [HasNEON, HasFullFP16] in {
7062  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7063                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7064  }
7065
7066  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7067            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7068}
7069
7070multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7071                          SDPatternOperator OpNode = null_frag> {
7072  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7073    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7074
7075  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7076            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7077}
7078
7079multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7080                           Predicate pred = HasNEON> {
7081  let Predicates = [pred] in {
7082  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7083  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7084  }
7085  let Predicates = [pred, HasFullFP16] in {
7086  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7087  }
7088}
7089
7090multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7091                              SDPatternOperator OpNode> {
7092  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7093                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7094  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7095                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7096  let Predicates = [HasNEON, HasFullFP16] in {
7097  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7098                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7099  }
7100}
7101
7102multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7103                             SDPatternOperator OpNode = null_frag> {
7104  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7105    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7106           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7107    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7108           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7109    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7110    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7111  }
7112
7113  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7114            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7115}
7116
7117multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7118                                 Intrinsic OpNode> {
7119  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7120    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7121        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7122    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7123        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7124    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7125    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7126  }
7127
7128  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7129            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7130}
7131
7132
7133
7134let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7135multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7136                                 SDPatternOperator OpNode = null_frag> {
7137  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7138        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7139  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7140  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7141}
7142
7143//----------------------------------------------------------------------------
7144// AdvSIMD scalar pairwise instructions
7145//----------------------------------------------------------------------------
7146
7147let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7148class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7149                        RegisterOperand regtype, RegisterOperand vectype,
7150                        string asm, string kind>
7151  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7152      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7153    Sched<[WriteVd]> {
7154  bits<5> Rd;
7155  bits<5> Rn;
7156  let Inst{31-30} = 0b01;
7157  let Inst{29}    = U;
7158  let Inst{28-24} = 0b11110;
7159  let Inst{23-22} = size;
7160  let Inst{21-17} = 0b11000;
7161  let Inst{16-12} = opcode;
7162  let Inst{11-10} = 0b10;
7163  let Inst{9-5}   = Rn;
7164  let Inst{4-0}   = Rd;
7165}
7166
7167multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7168  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7169                                      asm, ".2d">;
7170}
7171
7172multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7173  let Predicates = [HasNEON, HasFullFP16] in {
7174  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7175                                      asm, ".2h">;
7176  }
7177  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7178                                      asm, ".2s">;
7179  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7180                                      asm, ".2d">;
7181}
7182
7183//----------------------------------------------------------------------------
7184// AdvSIMD across lanes instructions
7185//----------------------------------------------------------------------------
7186
7187let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7188class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7189                          RegisterClass regtype, RegisterOperand vectype,
7190                          string asm, string kind, list<dag> pattern>
7191  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7192      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7193    Sched<[!if(Q, WriteVq, WriteVd)]> {
7194  bits<5> Rd;
7195  bits<5> Rn;
7196  let Inst{31}    = 0;
7197  let Inst{30}    = Q;
7198  let Inst{29}    = U;
7199  let Inst{28-24} = 0b01110;
7200  let Inst{23-22} = size;
7201  let Inst{21-17} = 0b11000;
7202  let Inst{16-12} = opcode;
7203  let Inst{11-10} = 0b10;
7204  let Inst{9-5}   = Rn;
7205  let Inst{4-0}   = Rd;
7206}
7207
7208multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7209                              string asm> {
7210  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7211                                   asm, ".8b", []>;
7212  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7213                                   asm, ".16b", []>;
7214  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7215                                   asm, ".4h", []>;
7216  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7217                                   asm, ".8h", []>;
7218  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7219                                   asm, ".4s", []>;
7220}
7221
7222multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7223  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7224                                   asm, ".8b", []>;
7225  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7226                                   asm, ".16b", []>;
7227  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7228                                   asm, ".4h", []>;
7229  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7230                                   asm, ".8h", []>;
7231  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7232                                   asm, ".4s", []>;
7233}
7234
7235multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7236                            Intrinsic intOp> {
7237  let Predicates = [HasNEON, HasFullFP16] in {
7238  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7239                                   asm, ".4h",
7240        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7241  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7242                                   asm, ".8h",
7243        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7244  } // Predicates = [HasNEON, HasFullFP16]
7245  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7246                                   asm, ".4s",
7247        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7248}
7249
7250//----------------------------------------------------------------------------
7251// AdvSIMD INS/DUP instructions
7252//----------------------------------------------------------------------------
7253
7254// FIXME: There has got to be a better way to factor these. ugh.
7255
7256class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7257                     string operands, string constraints, list<dag> pattern>
7258  : I<outs, ins, asm, operands, constraints, pattern>,
7259    Sched<[!if(Q, WriteVq, WriteVd)]> {
7260  bits<5> Rd;
7261  bits<5> Rn;
7262  let Inst{31} = 0;
7263  let Inst{30} = Q;
7264  let Inst{29} = op;
7265  let Inst{28-21} = 0b01110000;
7266  let Inst{15} = 0;
7267  let Inst{10} = 1;
7268  let Inst{9-5} = Rn;
7269  let Inst{4-0} = Rd;
7270}
7271
7272class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7273                      RegisterOperand vecreg, RegisterClass regtype>
7274  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7275                   "{\t$Rd" # size # ", $Rn" #
7276                   "|" # size # "\t$Rd, $Rn}", "",
7277                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7278  let Inst{20-16} = imm5;
7279  let Inst{14-11} = 0b0001;
7280}
7281
7282class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7283                         ValueType vectype, ValueType insreg,
7284                         RegisterOperand vecreg, Operand idxtype,
7285                         SDNode OpNode>
7286  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7287                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7288                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7289                 [(set (vectype vecreg:$Rd),
7290                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7291  let Inst{14-11} = 0b0000;
7292}
7293
7294class SIMDDup64FromElement
7295  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7296                       VectorIndexD, AArch64duplane64> {
7297  bits<1> idx;
7298  let Inst{20} = idx;
7299  let Inst{19-16} = 0b1000;
7300}
7301
7302class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7303                           RegisterOperand vecreg>
7304  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7305                       VectorIndexS, AArch64duplane32> {
7306  bits<2> idx;
7307  let Inst{20-19} = idx;
7308  let Inst{18-16} = 0b100;
7309}
7310
7311class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7312                           RegisterOperand vecreg>
7313  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7314                       VectorIndexH, AArch64duplane16> {
7315  bits<3> idx;
7316  let Inst{20-18} = idx;
7317  let Inst{17-16} = 0b10;
7318}
7319
7320class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7321                          RegisterOperand vecreg>
7322  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7323                       VectorIndexB, AArch64duplane8> {
7324  bits<4> idx;
7325  let Inst{20-17} = idx;
7326  let Inst{16} = 1;
7327}
7328
7329class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7330                  Operand idxtype, string asm, list<dag> pattern>
7331  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7332                   "{\t$Rd, $Rn" # size # "$idx" #
7333                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7334  let Inst{14-11} = imm4;
7335}
7336
7337class SIMDSMov<bit Q, string size, RegisterClass regtype,
7338               Operand idxtype>
7339  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7340class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7341               Operand idxtype>
7342  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7343      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7344
7345class SIMDMovAlias<string asm, string size, Instruction inst,
7346                   RegisterClass regtype, Operand idxtype>
7347    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7348                    "|" # size # "\t$dst, $src$idx}",
7349                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7350
7351multiclass SMov {
7352  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7353  // streaming mode.
7354  let Predicates = [HasNEONorStreamingSVE] in {
7355    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7356      let Inst{20-16} = 0b00001;
7357    }
7358    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7359      let Inst{20-16} = 0b00001;
7360    }
7361    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7362      let Inst{20-16} = 0b00010;
7363    }
7364    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7365      let Inst{20-16} = 0b00010;
7366    }
7367    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7368      let Inst{20-16} = 0b00100;
7369    }
7370  }
7371  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7372    bits<4> idx;
7373    let Inst{20-17} = idx;
7374    let Inst{16} = 1;
7375  }
7376  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7377    bits<4> idx;
7378    let Inst{20-17} = idx;
7379    let Inst{16} = 1;
7380  }
7381  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7382    bits<3> idx;
7383    let Inst{20-18} = idx;
7384    let Inst{17-16} = 0b10;
7385  }
7386  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7387    bits<3> idx;
7388    let Inst{20-18} = idx;
7389    let Inst{17-16} = 0b10;
7390  }
7391  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7392    bits<2> idx;
7393    let Inst{20-19} = idx;
7394    let Inst{18-16} = 0b100;
7395  }
7396}
7397
7398multiclass UMov {
7399  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7400  // streaming mode.
7401  let Predicates = [HasNEONorStreamingSVE] in {
7402    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7403      let Inst{20-16} = 0b00001;
7404    }
7405    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7406      let Inst{20-16} = 0b00010;
7407    }
7408    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7409      let Inst{20-16} = 0b00100;
7410    }
7411    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7412      let Inst{20-16} = 0b01000;
7413    }
7414    def : SIMDMovAlias<"mov", ".s",
7415                       !cast<Instruction>(NAME # vi32_idx0),
7416                       GPR32, VectorIndex0>;
7417    def : SIMDMovAlias<"mov", ".d",
7418                       !cast<Instruction>(NAME # vi64_idx0),
7419                       GPR64, VectorIndex0>;
7420  }
7421  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7422    bits<4> idx;
7423    let Inst{20-17} = idx;
7424    let Inst{16} = 1;
7425  }
7426  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7427    bits<3> idx;
7428    let Inst{20-18} = idx;
7429    let Inst{17-16} = 0b10;
7430  }
7431  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7432    bits<2> idx;
7433    let Inst{20-19} = idx;
7434    let Inst{18-16} = 0b100;
7435  }
7436  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7437    bits<1> idx;
7438    let Inst{20} = idx;
7439    let Inst{19-16} = 0b1000;
7440  }
7441  def : SIMDMovAlias<"mov", ".s",
7442                     !cast<Instruction>(NAME#"vi32"),
7443                     GPR32, VectorIndexS>;
7444  def : SIMDMovAlias<"mov", ".d",
7445                     !cast<Instruction>(NAME#"vi64"),
7446                     GPR64, VectorIndexD>;
7447}
7448
7449class SIMDInsFromMain<string size, ValueType vectype,
7450                      RegisterClass regtype, Operand idxtype>
7451  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7452                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7453                   "{\t$Rd" # size # "$idx, $Rn" #
7454                   "|" # size # "\t$Rd$idx, $Rn}",
7455                   "$Rd = $dst",
7456            [(set V128:$dst,
7457              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7458  let Inst{14-11} = 0b0011;
7459}
7460
7461class SIMDInsFromElement<string size, ValueType vectype,
7462                         ValueType elttype, Operand idxtype>
7463  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7464                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7465                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7466                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7467                   "$Rd = $dst",
7468         [(set V128:$dst,
7469               (vector_insert
7470                 (vectype V128:$Rd),
7471                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7472                 idxtype:$idx))]>;
7473
7474class SIMDInsMainMovAlias<string size, Instruction inst,
7475                          RegisterClass regtype, Operand idxtype>
7476    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7477                        "|" # size #"\t$dst$idx, $src}",
7478                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7479class SIMDInsElementMovAlias<string size, Instruction inst,
7480                             Operand idxtype>
7481    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7482                      # "|" # size #"\t$dst$idx, $src$idx2}",
7483                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7484
7485
7486multiclass SIMDIns {
7487  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7488    bits<4> idx;
7489    let Inst{20-17} = idx;
7490    let Inst{16} = 1;
7491  }
7492  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7493    bits<3> idx;
7494    let Inst{20-18} = idx;
7495    let Inst{17-16} = 0b10;
7496  }
7497  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7498    bits<2> idx;
7499    let Inst{20-19} = idx;
7500    let Inst{18-16} = 0b100;
7501  }
7502  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7503    bits<1> idx;
7504    let Inst{20} = idx;
7505    let Inst{19-16} = 0b1000;
7506  }
7507
7508  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7509    bits<4> idx;
7510    bits<4> idx2;
7511    let Inst{20-17} = idx;
7512    let Inst{16} = 1;
7513    let Inst{14-11} = idx2;
7514  }
7515  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7516    bits<3> idx;
7517    bits<3> idx2;
7518    let Inst{20-18} = idx;
7519    let Inst{17-16} = 0b10;
7520    let Inst{14-12} = idx2;
7521    let Inst{11} = {?};
7522  }
7523  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7524    bits<2> idx;
7525    bits<2> idx2;
7526    let Inst{20-19} = idx;
7527    let Inst{18-16} = 0b100;
7528    let Inst{14-13} = idx2;
7529    let Inst{12-11} = {?,?};
7530  }
7531  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7532    bits<1> idx;
7533    bits<1> idx2;
7534    let Inst{20} = idx;
7535    let Inst{19-16} = 0b1000;
7536    let Inst{14} = idx2;
7537    let Inst{13-11} = {?,?,?};
7538  }
7539
7540  // For all forms of the INS instruction, the "mov" mnemonic is the
7541  // preferred alias. Why they didn't just call the instruction "mov" in
7542  // the first place is a very good question indeed...
7543  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7544                         GPR32, VectorIndexB>;
7545  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7546                         GPR32, VectorIndexH>;
7547  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7548                         GPR32, VectorIndexS>;
7549  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7550                         GPR64, VectorIndexD>;
7551
7552  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7553                         VectorIndexB>;
7554  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7555                         VectorIndexH>;
7556  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7557                         VectorIndexS>;
7558  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7559                         VectorIndexD>;
7560}
7561
7562//----------------------------------------------------------------------------
7563// AdvSIMD TBL/TBX
7564//----------------------------------------------------------------------------
7565
7566let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7567class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7568                          RegisterOperand listtype, string asm, string kind>
7569  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7570       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7571    Sched<[!if(Q, WriteVq, WriteVd)]> {
7572  bits<5> Vd;
7573  bits<5> Vn;
7574  bits<5> Vm;
7575  let Inst{31}    = 0;
7576  let Inst{30}    = Q;
7577  let Inst{29-21} = 0b001110000;
7578  let Inst{20-16} = Vm;
7579  let Inst{15}    = 0;
7580  let Inst{14-13} = len;
7581  let Inst{12}    = op;
7582  let Inst{11-10} = 0b00;
7583  let Inst{9-5}   = Vn;
7584  let Inst{4-0}   = Vd;
7585}
7586
7587let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7588class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7589                          RegisterOperand listtype, string asm, string kind>
7590  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7591       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7592    Sched<[!if(Q, WriteVq, WriteVd)]> {
7593  bits<5> Vd;
7594  bits<5> Vn;
7595  bits<5> Vm;
7596  let Inst{31}    = 0;
7597  let Inst{30}    = Q;
7598  let Inst{29-21} = 0b001110000;
7599  let Inst{20-16} = Vm;
7600  let Inst{15}    = 0;
7601  let Inst{14-13} = len;
7602  let Inst{12}    = op;
7603  let Inst{11-10} = 0b00;
7604  let Inst{9-5}   = Vn;
7605  let Inst{4-0}   = Vd;
7606}
7607
7608class SIMDTableLookupAlias<string asm, Instruction inst,
7609                          RegisterOperand vectype, RegisterOperand listtype>
7610    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7611                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7612
7613multiclass SIMDTableLookup<bit op, string asm> {
7614  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7615                                      asm, ".8b">;
7616  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7617                                      asm, ".8b">;
7618  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7619                                      asm, ".8b">;
7620  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7621                                      asm, ".8b">;
7622  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7623                                      asm, ".16b">;
7624  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7625                                      asm, ".16b">;
7626  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7627                                      asm, ".16b">;
7628  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7629                                      asm, ".16b">;
7630
7631  def : SIMDTableLookupAlias<asm # ".8b",
7632                         !cast<Instruction>(NAME#"v8i8One"),
7633                         V64, VecListOne128>;
7634  def : SIMDTableLookupAlias<asm # ".8b",
7635                         !cast<Instruction>(NAME#"v8i8Two"),
7636                         V64, VecListTwo128>;
7637  def : SIMDTableLookupAlias<asm # ".8b",
7638                         !cast<Instruction>(NAME#"v8i8Three"),
7639                         V64, VecListThree128>;
7640  def : SIMDTableLookupAlias<asm # ".8b",
7641                         !cast<Instruction>(NAME#"v8i8Four"),
7642                         V64, VecListFour128>;
7643  def : SIMDTableLookupAlias<asm # ".16b",
7644                         !cast<Instruction>(NAME#"v16i8One"),
7645                         V128, VecListOne128>;
7646  def : SIMDTableLookupAlias<asm # ".16b",
7647                         !cast<Instruction>(NAME#"v16i8Two"),
7648                         V128, VecListTwo128>;
7649  def : SIMDTableLookupAlias<asm # ".16b",
7650                         !cast<Instruction>(NAME#"v16i8Three"),
7651                         V128, VecListThree128>;
7652  def : SIMDTableLookupAlias<asm # ".16b",
7653                         !cast<Instruction>(NAME#"v16i8Four"),
7654                         V128, VecListFour128>;
7655}
7656
7657multiclass SIMDTableLookupTied<bit op, string asm> {
7658  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7659                                      asm, ".8b">;
7660  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7661                                      asm, ".8b">;
7662  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7663                                      asm, ".8b">;
7664  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7665                                      asm, ".8b">;
7666  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7667                                      asm, ".16b">;
7668  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7669                                      asm, ".16b">;
7670  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7671                                      asm, ".16b">;
7672  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7673                                      asm, ".16b">;
7674
7675  def : SIMDTableLookupAlias<asm # ".8b",
7676                         !cast<Instruction>(NAME#"v8i8One"),
7677                         V64, VecListOne128>;
7678  def : SIMDTableLookupAlias<asm # ".8b",
7679                         !cast<Instruction>(NAME#"v8i8Two"),
7680                         V64, VecListTwo128>;
7681  def : SIMDTableLookupAlias<asm # ".8b",
7682                         !cast<Instruction>(NAME#"v8i8Three"),
7683                         V64, VecListThree128>;
7684  def : SIMDTableLookupAlias<asm # ".8b",
7685                         !cast<Instruction>(NAME#"v8i8Four"),
7686                         V64, VecListFour128>;
7687  def : SIMDTableLookupAlias<asm # ".16b",
7688                         !cast<Instruction>(NAME#"v16i8One"),
7689                         V128, VecListOne128>;
7690  def : SIMDTableLookupAlias<asm # ".16b",
7691                         !cast<Instruction>(NAME#"v16i8Two"),
7692                         V128, VecListTwo128>;
7693  def : SIMDTableLookupAlias<asm # ".16b",
7694                         !cast<Instruction>(NAME#"v16i8Three"),
7695                         V128, VecListThree128>;
7696  def : SIMDTableLookupAlias<asm # ".16b",
7697                         !cast<Instruction>(NAME#"v16i8Four"),
7698                         V128, VecListFour128>;
7699}
7700
7701
7702//----------------------------------------------------------------------------
7703// AdvSIMD scalar DUP
7704//----------------------------------------------------------------------------
7705let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7706class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7707                        string asm, string kind, Operand idxtype>
7708  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7709       "{\t$dst, $src" # kind # "$idx" #
7710       "|\t$dst, $src$idx}", "", []>,
7711    Sched<[WriteVd]> {
7712  bits<5> dst;
7713  bits<5> src;
7714  let Inst{31-21} = 0b01011110000;
7715  let Inst{15-10} = 0b000001;
7716  let Inst{9-5}   = src;
7717  let Inst{4-0}   = dst;
7718}
7719
7720class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7721      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7722    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7723                    # "|\t$dst, $src$index}",
7724                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7725
7726
7727multiclass SIMDScalarDUP<string asm> {
7728  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
7729    bits<4> idx;
7730    let Inst{20-17} = idx;
7731    let Inst{16} = 1;
7732  }
7733  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
7734    bits<3> idx;
7735    let Inst{20-18} = idx;
7736    let Inst{17-16} = 0b10;
7737  }
7738  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
7739    bits<2> idx;
7740    let Inst{20-19} = idx;
7741    let Inst{18-16} = 0b100;
7742  }
7743  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
7744    bits<1> idx;
7745    let Inst{20} = idx;
7746    let Inst{19-16} = 0b1000;
7747  }
7748
7749  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7750                                                          VectorIndexD:$idx)))),
7751            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7752
7753  // 'DUP' mnemonic aliases.
7754  def : SIMDScalarDUPAlias<"dup", ".b",
7755                           !cast<Instruction>(NAME#"i8"),
7756                           FPR8, V128, VectorIndexB>;
7757  def : SIMDScalarDUPAlias<"dup", ".h",
7758                           !cast<Instruction>(NAME#"i16"),
7759                           FPR16, V128, VectorIndexH>;
7760  def : SIMDScalarDUPAlias<"dup", ".s",
7761                           !cast<Instruction>(NAME#"i32"),
7762                           FPR32, V128, VectorIndexS>;
7763  def : SIMDScalarDUPAlias<"dup", ".d",
7764                           !cast<Instruction>(NAME#"i64"),
7765                           FPR64, V128, VectorIndexD>;
7766}
7767
7768//----------------------------------------------------------------------------
7769// AdvSIMD modified immediate instructions
7770//----------------------------------------------------------------------------
7771
7772class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7773                          string asm, string op_string,
7774                          string cstr, list<dag> pattern>
7775  : I<oops, iops, asm, op_string, cstr, pattern>,
7776    Sched<[!if(Q, WriteVq, WriteVd)]> {
7777  bits<5> Rd;
7778  bits<8> imm8;
7779  let Inst{31}    = 0;
7780  let Inst{30}    = Q;
7781  let Inst{29}    = op;
7782  let Inst{28-19} = 0b0111100000;
7783  let Inst{18-16} = imm8{7-5};
7784  let Inst{11} = op2;
7785  let Inst{10} = 1;
7786  let Inst{9-5}   = imm8{4-0};
7787  let Inst{4-0}   = Rd;
7788}
7789
7790class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7791                                Operand immtype, dag opt_shift_iop,
7792                                string opt_shift, string asm, string kind,
7793                                list<dag> pattern>
7794  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7795                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7796                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7797                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7798                        "", pattern> {
7799  let DecoderMethod = "DecodeModImmInstruction";
7800}
7801
7802class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7803                                Operand immtype, dag opt_shift_iop,
7804                                string opt_shift, string asm, string kind,
7805                                list<dag> pattern>
7806  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7807                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7808                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7809                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7810                        "$Rd = $dst", pattern> {
7811  let DecoderMethod = "DecodeModImmTiedInstruction";
7812}
7813
7814class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7815                                     RegisterOperand vectype, string asm,
7816                                     string kind, list<dag> pattern>
7817  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7818                              (ins logical_vec_shift:$shift),
7819                              "$shift", asm, kind, pattern> {
7820  bits<2> shift;
7821  let Inst{15}    = b15_b12{1};
7822  let Inst{14-13} = shift;
7823  let Inst{12}    = b15_b12{0};
7824}
7825
7826class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7827                                     RegisterOperand vectype, string asm,
7828                                     string kind, list<dag> pattern>
7829  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7830                              (ins logical_vec_shift:$shift),
7831                              "$shift", asm, kind, pattern> {
7832  bits<2> shift;
7833  let Inst{15}    = b15_b12{1};
7834  let Inst{14-13} = shift;
7835  let Inst{12}    = b15_b12{0};
7836}
7837
7838
7839class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7840                                         RegisterOperand vectype, string asm,
7841                                         string kind, list<dag> pattern>
7842  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7843                              (ins logical_vec_hw_shift:$shift),
7844                              "$shift", asm, kind, pattern> {
7845  bits<2> shift;
7846  let Inst{15} = b15_b12{1};
7847  let Inst{14} = 0;
7848  let Inst{13} = shift{0};
7849  let Inst{12} = b15_b12{0};
7850}
7851
7852class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7853                                         RegisterOperand vectype, string asm,
7854                                         string kind, list<dag> pattern>
7855  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7856                              (ins logical_vec_hw_shift:$shift),
7857                              "$shift", asm, kind, pattern> {
7858  bits<2> shift;
7859  let Inst{15} = b15_b12{1};
7860  let Inst{14} = 0;
7861  let Inst{13} = shift{0};
7862  let Inst{12} = b15_b12{0};
7863}
7864
7865multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7866                                      string asm> {
7867  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7868                                                 asm, ".4h", []>;
7869  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7870                                                 asm, ".8h", []>;
7871
7872  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7873                                             asm, ".2s", []>;
7874  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7875                                             asm, ".4s", []>;
7876}
7877
7878multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7879                                      bits<2> w_cmode, string asm,
7880                                      SDNode OpNode> {
7881  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7882                                                 asm, ".4h",
7883             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7884                                             imm0_255:$imm8,
7885                                             (i32 imm:$shift)))]>;
7886  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7887                                                 asm, ".8h",
7888             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7889                                              imm0_255:$imm8,
7890                                              (i32 imm:$shift)))]>;
7891
7892  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7893                                             asm, ".2s",
7894             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7895                                             imm0_255:$imm8,
7896                                             (i32 imm:$shift)))]>;
7897  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7898                                             asm, ".4s",
7899             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7900                                              imm0_255:$imm8,
7901                                              (i32 imm:$shift)))]>;
7902}
7903
7904class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7905                             RegisterOperand vectype, string asm,
7906                             string kind, list<dag> pattern>
7907  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7908                              (ins move_vec_shift:$shift),
7909                              "$shift", asm, kind, pattern> {
7910  bits<1> shift;
7911  let Inst{15-13} = cmode{3-1};
7912  let Inst{12}    = shift;
7913}
7914
7915class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7916                                   RegisterOperand vectype,
7917                                   Operand imm_type, string asm,
7918                                   string kind, list<dag> pattern>
7919  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7920                              asm, kind, pattern> {
7921  let Inst{15-12} = cmode;
7922}
7923
7924class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7925                                   list<dag> pattern>
7926  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7927                        "\t$Rd, $imm8", "", pattern> {
7928  let Inst{15-12} = cmode;
7929  let DecoderMethod = "DecodeModImmInstruction";
7930}
7931
7932//----------------------------------------------------------------------------
7933// AdvSIMD indexed element
7934//----------------------------------------------------------------------------
7935
7936let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7937class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7938                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7939                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7940                      string apple_kind, string dst_kind, string lhs_kind,
7941                      string rhs_kind, list<dag> pattern>
7942  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7943      asm,
7944      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7945      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7946    Sched<[WriteVd]> {
7947  bits<5> Rd;
7948  bits<5> Rn;
7949  bits<5> Rm;
7950
7951  let Inst{31}    = 0;
7952  let Inst{30}    = Q;
7953  let Inst{29}    = U;
7954  let Inst{28}    = Scalar;
7955  let Inst{27-24} = 0b1111;
7956  let Inst{23-22} = size;
7957  // Bit 21 must be set by the derived class.
7958  let Inst{20-16} = Rm;
7959  let Inst{15-12} = opc;
7960  // Bit 11 must be set by the derived class.
7961  let Inst{10}    = 0;
7962  let Inst{9-5}   = Rn;
7963  let Inst{4-0}   = Rd;
7964}
7965
7966let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7967class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7968                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7969                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7970                      string apple_kind, string dst_kind, string lhs_kind,
7971                      string rhs_kind, list<dag> pattern>
7972  : I<(outs dst_reg:$dst),
7973      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7974      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7975      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7976    Sched<[WriteVd]> {
7977  bits<5> Rd;
7978  bits<5> Rn;
7979  bits<5> Rm;
7980
7981  let Inst{31}    = 0;
7982  let Inst{30}    = Q;
7983  let Inst{29}    = U;
7984  let Inst{28}    = Scalar;
7985  let Inst{27-24} = 0b1111;
7986  let Inst{23-22} = size;
7987  // Bit 21 must be set by the derived class.
7988  let Inst{20-16} = Rm;
7989  let Inst{15-12} = opc;
7990  // Bit 11 must be set by the derived class.
7991  let Inst{10}    = 0;
7992  let Inst{9-5}   = Rn;
7993  let Inst{4-0}   = Rd;
7994}
7995
7996
7997//----------------------------------------------------------------------------
7998// Armv8.6 BFloat16 Extension
7999//----------------------------------------------------------------------------
8000let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8001
8002class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8003                                   string kind2, RegisterOperand RegType,
8004                                   ValueType AccumType, ValueType InputType>
8005  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8006                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8007                                            (InputType RegType:$Rn),
8008                                            (InputType RegType:$Rm)))]> {
8009  let AsmString = !strconcat(asm,
8010                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8011                               ", $Rm" # kind2 # "}");
8012}
8013
8014multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8015  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8016                                           v2f32, v4bf16>;
8017  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8018                                           v4f32, v8bf16>;
8019}
8020
8021class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8022                                      string dst_kind, string lhs_kind,
8023                                      string rhs_kind,
8024                                      RegisterOperand RegType,
8025                                      ValueType AccumType,
8026                                      ValueType InputType>
8027  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8028                        RegType, RegType, V128, VectorIndexS,
8029                        asm, "", dst_kind, lhs_kind, rhs_kind,
8030        [(set (AccumType RegType:$dst),
8031              (AccumType (int_aarch64_neon_bfdot
8032                                 (AccumType RegType:$Rd),
8033                                 (InputType RegType:$Rn),
8034                                 (InputType (bitconvert (AccumType
8035                                    (AArch64duplane32 (v4f32 V128:$Rm),
8036                                        VectorIndexS:$idx)))))))]> {
8037
8038  bits<2> idx;
8039  let Inst{21}    = idx{0};  // L
8040  let Inst{11}    = idx{1};  // H
8041}
8042
8043multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8044
8045  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8046                                               ".2h", V64, v2f32, v4bf16>;
8047  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8048                                              ".2h", V128, v4f32, v8bf16>;
8049}
8050
8051class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8052  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8053              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8054                                               (v8bf16 V128:$Rn),
8055                                               (v8bf16 V128:$Rm)))]> {
8056  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8057}
8058
8059class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8060  : I<(outs V128:$dst),
8061      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8062      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8063          [(set (v4f32 V128:$dst),
8064                (v4f32 (OpNode (v4f32 V128:$Rd),
8065                               (v8bf16 V128:$Rn),
8066                               (v8bf16
8067                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8068                                      VectorIndexH:$idx)))))]>,
8069    Sched<[WriteVq]> {
8070  bits<5> Rd;
8071  bits<5> Rn;
8072  bits<4> Rm;
8073  bits<3> idx;
8074
8075  let Inst{31}    = 0;
8076  let Inst{30}    = Q;
8077  let Inst{29-22} = 0b00111111;
8078  let Inst{21-20} = idx{1-0};
8079  let Inst{19-16} = Rm;
8080  let Inst{15-12} = 0b1111;
8081  let Inst{11}    = idx{2};   // H
8082  let Inst{10}    = 0;
8083  let Inst{9-5}   = Rn;
8084  let Inst{4-0}   = Rd;
8085}
8086
8087class SIMDThreeSameVectorBF16MatrixMul<string asm>
8088  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8089                                V128, asm, ".4s",
8090                          [(set (v4f32 V128:$dst),
8091                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8092                                                         (v8bf16 V128:$Rn),
8093                                                         (v8bf16 V128:$Rm)))]> {
8094  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8095                                    ", $Rm", ".8h", "}");
8096}
8097
8098class SIMD_BFCVTN
8099  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8100                           "bfcvtn", ".4h", ".4s",
8101    [(set (v8bf16 V128:$Rd),
8102          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8103
8104class SIMD_BFCVTN2
8105  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8106                           "bfcvtn2", ".8h", ".4s",
8107    [(set (v8bf16 V128:$dst),
8108          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8109
8110class BF16ToSinglePrecision<string asm>
8111  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8112    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8113    Sched<[WriteFCvt]> {
8114  bits<5> Rd;
8115  bits<5> Rn;
8116  let Inst{31-10} = 0b0001111001100011010000;
8117  let Inst{9-5}   = Rn;
8118  let Inst{4-0}   = Rd;
8119}
8120} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8121
8122//----------------------------------------------------------------------------
8123// Armv8.6 Matrix Multiply Extension
8124//----------------------------------------------------------------------------
8125
8126class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8127  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8128              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8129                                               (v16i8 V128:$Rn),
8130                                               (v16i8 V128:$Rm)))]> {
8131  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8132}
8133
8134//----------------------------------------------------------------------------
8135// ARMv8.2-A Dot Product Instructions (Indexed)
8136class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8137                                      string dst_kind, string lhs_kind, string rhs_kind,
8138                                      RegisterOperand RegType,
8139                                      ValueType AccumType, ValueType InputType,
8140                                      SDPatternOperator OpNode> :
8141        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8142                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8143        [(set (AccumType RegType:$dst),
8144              (AccumType (OpNode (AccumType RegType:$Rd),
8145                                 (InputType RegType:$Rn),
8146                                 (InputType (bitconvert (AccumType
8147                                    (AArch64duplane32 (v4i32 V128:$Rm),
8148                                        VectorIndexS:$idx)))))))]> {
8149  bits<2> idx;
8150  let Inst{21}    = idx{0};  // L
8151  let Inst{11}    = idx{1};  // H
8152}
8153
8154multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8155                                       SDPatternOperator OpNode> {
8156  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8157                                              V64, v2i32, v8i8, OpNode>;
8158  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8159                                              V128, v4i32, v16i8, OpNode>;
8160}
8161
8162// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8163class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8164                                      string dst_kind, string lhs_kind,
8165                                      string rhs_kind, RegisterOperand RegType,
8166                                      ValueType AccumType, ValueType InputType,
8167                                      SDPatternOperator OpNode> :
8168        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8169                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8170          [(set (AccumType RegType:$dst),
8171                (AccumType (OpNode (AccumType RegType:$Rd),
8172                                   (InputType RegType:$Rn),
8173                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8174                                                VectorIndexH:$idx)))))]> {
8175  // idx = H:L:M
8176  bits<3> idx;
8177  let Inst{11} = idx{2}; // H
8178  let Inst{21} = idx{1}; // L
8179  let Inst{20} = idx{0}; // M
8180}
8181
8182multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8183                                       SDPatternOperator OpNode> {
8184  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8185                                              V64, v2f32, v4f16, OpNode>;
8186  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8187                                              V128, v4f32, v8f16, OpNode>;
8188}
8189
8190multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8191                         SDPatternOperator OpNode> {
8192  let Predicates = [HasNEON, HasFullFP16] in {
8193  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8194                                      V64, V64,
8195                                      V128_lo, VectorIndexH,
8196                                      asm, ".4h", ".4h", ".4h", ".h",
8197    [(set (v4f16 V64:$Rd),
8198        (OpNode (v4f16 V64:$Rn),
8199         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8200    bits<3> idx;
8201    let Inst{11} = idx{2};
8202    let Inst{21} = idx{1};
8203    let Inst{20} = idx{0};
8204  }
8205
8206  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8207                                      V128, V128,
8208                                      V128_lo, VectorIndexH,
8209                                      asm, ".8h", ".8h", ".8h", ".h",
8210    [(set (v8f16 V128:$Rd),
8211        (OpNode (v8f16 V128:$Rn),
8212         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8213    bits<3> idx;
8214    let Inst{11} = idx{2};
8215    let Inst{21} = idx{1};
8216    let Inst{20} = idx{0};
8217  }
8218  } // Predicates = [HasNEON, HasFullFP16]
8219
8220  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8221                                      V64, V64,
8222                                      V128, VectorIndexS,
8223                                      asm, ".2s", ".2s", ".2s", ".s",
8224    [(set (v2f32 V64:$Rd),
8225        (OpNode (v2f32 V64:$Rn),
8226         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8227    bits<2> idx;
8228    let Inst{11} = idx{1};
8229    let Inst{21} = idx{0};
8230  }
8231
8232  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8233                                      V128, V128,
8234                                      V128, VectorIndexS,
8235                                      asm, ".4s", ".4s", ".4s", ".s",
8236    [(set (v4f32 V128:$Rd),
8237        (OpNode (v4f32 V128:$Rn),
8238         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8239    bits<2> idx;
8240    let Inst{11} = idx{1};
8241    let Inst{21} = idx{0};
8242  }
8243
8244  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8245                                      V128, V128,
8246                                      V128, VectorIndexD,
8247                                      asm, ".2d", ".2d", ".2d", ".d",
8248    [(set (v2f64 V128:$Rd),
8249        (OpNode (v2f64 V128:$Rn),
8250         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8251    bits<1> idx;
8252    let Inst{11} = idx{0};
8253    let Inst{21} = 0;
8254  }
8255
8256  let Predicates = [HasNEON, HasFullFP16] in {
8257  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8258                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8259                                      asm, ".h", "", "", ".h",
8260    [(set (f16 FPR16Op:$Rd),
8261          (OpNode (f16 FPR16Op:$Rn),
8262                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8263                                       VectorIndexH:$idx))))]> {
8264    bits<3> idx;
8265    let Inst{11} = idx{2};
8266    let Inst{21} = idx{1};
8267    let Inst{20} = idx{0};
8268  }
8269  } // Predicates = [HasNEON, HasFullFP16]
8270
8271  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8272                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8273                                      asm, ".s", "", "", ".s",
8274    [(set (f32 FPR32Op:$Rd),
8275          (OpNode (f32 FPR32Op:$Rn),
8276                  (f32 (vector_extract (v4f32 V128:$Rm),
8277                                       VectorIndexS:$idx))))]> {
8278    bits<2> idx;
8279    let Inst{11} = idx{1};
8280    let Inst{21} = idx{0};
8281  }
8282
8283  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8284                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8285                                      asm, ".d", "", "", ".d",
8286    [(set (f64 FPR64Op:$Rd),
8287          (OpNode (f64 FPR64Op:$Rn),
8288                  (f64 (vector_extract (v2f64 V128:$Rm),
8289                                       VectorIndexD:$idx))))]> {
8290    bits<1> idx;
8291    let Inst{11} = idx{0};
8292    let Inst{21} = 0;
8293  }
8294}
8295
8296multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8297  let Predicates = [HasNEON, HasFullFP16] in {
8298  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8299  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8300                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8301                                           VectorIndexH:$idx))),
8302            (!cast<Instruction>(INST # "v8i16_indexed")
8303                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8304  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8305                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8306            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8307                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8308
8309  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8310                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8311                                           VectorIndexH:$idx))),
8312            (!cast<Instruction>(INST # "v4i16_indexed")
8313                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8314  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8315                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8316            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8317                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8318
8319  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8320                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8321            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8322                V128_lo:$Rm, VectorIndexH:$idx)>;
8323  } // Predicates = [HasNEON, HasFullFP16]
8324
8325  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8326  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8327                           (AArch64duplane32 (v4f32 V128:$Rm),
8328                                           VectorIndexS:$idx))),
8329            (!cast<Instruction>(INST # v2i32_indexed)
8330                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8331  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8332                           (AArch64dup (f32 FPR32Op:$Rm)))),
8333            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8334                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8335
8336
8337  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8338  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8339                           (AArch64duplane32 (v4f32 V128:$Rm),
8340                                           VectorIndexS:$idx))),
8341            (!cast<Instruction>(INST # "v4i32_indexed")
8342                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8343  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8344                           (AArch64dup (f32 FPR32Op:$Rm)))),
8345            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8346                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8347
8348  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8349  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8350                           (AArch64duplane64 (v2f64 V128:$Rm),
8351                                           VectorIndexD:$idx))),
8352            (!cast<Instruction>(INST # "v2i64_indexed")
8353                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8354  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8355                           (AArch64dup (f64 FPR64Op:$Rm)))),
8356            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8357                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8358
8359  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8360  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8361                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8362            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8363                V128:$Rm, VectorIndexS:$idx)>;
8364
8365  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8366  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8367                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8368            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8369                V128:$Rm, VectorIndexD:$idx)>;
8370}
8371
8372multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8373  let Predicates = [HasNEON, HasFullFP16] in {
8374  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8375                                          V128_lo, VectorIndexH,
8376                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8377    bits<3> idx;
8378    let Inst{11} = idx{2};
8379    let Inst{21} = idx{1};
8380    let Inst{20} = idx{0};
8381  }
8382
8383  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8384                                          V128, V128,
8385                                          V128_lo, VectorIndexH,
8386                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8387    bits<3> idx;
8388    let Inst{11} = idx{2};
8389    let Inst{21} = idx{1};
8390    let Inst{20} = idx{0};
8391  }
8392  } // Predicates = [HasNEON, HasFullFP16]
8393
8394  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8395                                          V128, VectorIndexS,
8396                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8397    bits<2> idx;
8398    let Inst{11} = idx{1};
8399    let Inst{21} = idx{0};
8400  }
8401
8402  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8403                                      V128, V128,
8404                                      V128, VectorIndexS,
8405                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8406    bits<2> idx;
8407    let Inst{11} = idx{1};
8408    let Inst{21} = idx{0};
8409  }
8410
8411  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8412                                      V128, V128,
8413                                      V128, VectorIndexD,
8414                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8415    bits<1> idx;
8416    let Inst{11} = idx{0};
8417    let Inst{21} = 0;
8418  }
8419
8420  let Predicates = [HasNEON, HasFullFP16] in {
8421  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8422                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8423                                      asm, ".h", "", "", ".h", []> {
8424    bits<3> idx;
8425    let Inst{11} = idx{2};
8426    let Inst{21} = idx{1};
8427    let Inst{20} = idx{0};
8428  }
8429  } // Predicates = [HasNEON, HasFullFP16]
8430
8431  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8432                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8433                                      asm, ".s", "", "", ".s", []> {
8434    bits<2> idx;
8435    let Inst{11} = idx{1};
8436    let Inst{21} = idx{0};
8437  }
8438
8439  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8440                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8441                                      asm, ".d", "", "", ".d", []> {
8442    bits<1> idx;
8443    let Inst{11} = idx{0};
8444    let Inst{21} = 0;
8445  }
8446}
8447
8448multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8449                                 SDPatternOperator OpNodeLaneQ> {
8450
8451  def : Pat<(v4i16 (OpNodeLane
8452                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8453                     VectorIndexS32b:$idx)),
8454            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8455              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8456              (UImmS1XForm $idx))>;
8457
8458  def : Pat<(v4i16 (OpNodeLaneQ
8459                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8460                     VectorIndexH32b:$idx)),
8461            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8462              (UImmS1XForm $idx))>;
8463
8464  def : Pat<(v8i16 (OpNodeLane
8465                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8466                     VectorIndexS32b:$idx)),
8467            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8468              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8469              (UImmS1XForm $idx))>;
8470
8471  def : Pat<(v8i16 (OpNodeLaneQ
8472                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8473                     VectorIndexH32b:$idx)),
8474            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8475              (UImmS1XForm $idx))>;
8476
8477  def : Pat<(v2i32 (OpNodeLane
8478                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8479                     VectorIndexD32b:$idx)),
8480            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8481              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8482              (UImmS1XForm $idx))>;
8483
8484  def : Pat<(v2i32 (OpNodeLaneQ
8485                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8486                     VectorIndexS32b:$idx)),
8487            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8488              (UImmS1XForm $idx))>;
8489
8490  def : Pat<(v4i32 (OpNodeLane
8491                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8492                     VectorIndexD32b:$idx)),
8493            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8494              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8495              (UImmS1XForm $idx))>;
8496
8497  def : Pat<(v4i32 (OpNodeLaneQ
8498                     (v4i32 V128:$Rn),
8499                     (v4i32 V128:$Rm),
8500                     VectorIndexS32b:$idx)),
8501            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8502              (UImmS1XForm $idx))>;
8503
8504}
8505
8506multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8507                         SDPatternOperator OpNode> {
8508  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8509                                      V128_lo, VectorIndexH,
8510                                      asm, ".4h", ".4h", ".4h", ".h",
8511    [(set (v4i16 V64:$Rd),
8512        (OpNode (v4i16 V64:$Rn),
8513         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8514    bits<3> idx;
8515    let Inst{11} = idx{2};
8516    let Inst{21} = idx{1};
8517    let Inst{20} = idx{0};
8518  }
8519
8520  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8521                                      V128, V128,
8522                                      V128_lo, VectorIndexH,
8523                                      asm, ".8h", ".8h", ".8h", ".h",
8524    [(set (v8i16 V128:$Rd),
8525       (OpNode (v8i16 V128:$Rn),
8526         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8527    bits<3> idx;
8528    let Inst{11} = idx{2};
8529    let Inst{21} = idx{1};
8530    let Inst{20} = idx{0};
8531  }
8532
8533  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8534                                      V64, V64,
8535                                      V128, VectorIndexS,
8536                                      asm, ".2s", ".2s", ".2s",  ".s",
8537    [(set (v2i32 V64:$Rd),
8538       (OpNode (v2i32 V64:$Rn),
8539          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8540    bits<2> idx;
8541    let Inst{11} = idx{1};
8542    let Inst{21} = idx{0};
8543  }
8544
8545  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8546                                      V128, V128,
8547                                      V128, VectorIndexS,
8548                                      asm, ".4s", ".4s", ".4s", ".s",
8549    [(set (v4i32 V128:$Rd),
8550       (OpNode (v4i32 V128:$Rn),
8551          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8552    bits<2> idx;
8553    let Inst{11} = idx{1};
8554    let Inst{21} = idx{0};
8555  }
8556
8557  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8558                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8559                                      asm, ".h", "", "", ".h", []> {
8560    bits<3> idx;
8561    let Inst{11} = idx{2};
8562    let Inst{21} = idx{1};
8563    let Inst{20} = idx{0};
8564  }
8565
8566  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8567                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8568                                      asm, ".s", "", "", ".s",
8569      [(set (i32 FPR32Op:$Rd),
8570            (OpNode FPR32Op:$Rn,
8571                    (i32 (vector_extract (v4i32 V128:$Rm),
8572                                         VectorIndexS:$idx))))]> {
8573    bits<2> idx;
8574    let Inst{11} = idx{1};
8575    let Inst{21} = idx{0};
8576  }
8577}
8578
8579multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8580                               SDPatternOperator OpNode> {
8581  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8582                                      V64, V64,
8583                                      V128_lo, VectorIndexH,
8584                                      asm, ".4h", ".4h", ".4h", ".h",
8585    [(set (v4i16 V64:$Rd),
8586        (OpNode (v4i16 V64:$Rn),
8587         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8588    bits<3> idx;
8589    let Inst{11} = idx{2};
8590    let Inst{21} = idx{1};
8591    let Inst{20} = idx{0};
8592  }
8593
8594  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8595                                      V128, V128,
8596                                      V128_lo, VectorIndexH,
8597                                      asm, ".8h", ".8h", ".8h", ".h",
8598    [(set (v8i16 V128:$Rd),
8599       (OpNode (v8i16 V128:$Rn),
8600         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8601    bits<3> idx;
8602    let Inst{11} = idx{2};
8603    let Inst{21} = idx{1};
8604    let Inst{20} = idx{0};
8605  }
8606
8607  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8608                                      V64, V64,
8609                                      V128, VectorIndexS,
8610                                      asm, ".2s", ".2s", ".2s", ".s",
8611    [(set (v2i32 V64:$Rd),
8612       (OpNode (v2i32 V64:$Rn),
8613          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8614    bits<2> idx;
8615    let Inst{11} = idx{1};
8616    let Inst{21} = idx{0};
8617  }
8618
8619  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8620                                      V128, V128,
8621                                      V128, VectorIndexS,
8622                                      asm, ".4s", ".4s", ".4s", ".s",
8623    [(set (v4i32 V128:$Rd),
8624       (OpNode (v4i32 V128:$Rn),
8625          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8626    bits<2> idx;
8627    let Inst{11} = idx{1};
8628    let Inst{21} = idx{0};
8629  }
8630}
8631
8632multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8633                                   SDPatternOperator OpNode> {
8634  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8635                                          V128_lo, VectorIndexH,
8636                                          asm, ".4h", ".4h", ".4h", ".h",
8637    [(set (v4i16 V64:$dst),
8638        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8639         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8640    bits<3> idx;
8641    let Inst{11} = idx{2};
8642    let Inst{21} = idx{1};
8643    let Inst{20} = idx{0};
8644  }
8645
8646  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8647                                      V128, V128,
8648                                      V128_lo, VectorIndexH,
8649                                      asm, ".8h", ".8h", ".8h", ".h",
8650    [(set (v8i16 V128:$dst),
8651       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8652         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8653    bits<3> idx;
8654    let Inst{11} = idx{2};
8655    let Inst{21} = idx{1};
8656    let Inst{20} = idx{0};
8657  }
8658
8659  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8660                                      V64, V64,
8661                                      V128, VectorIndexS,
8662                                      asm, ".2s", ".2s", ".2s", ".s",
8663    [(set (v2i32 V64:$dst),
8664       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8665          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8666    bits<2> idx;
8667    let Inst{11} = idx{1};
8668    let Inst{21} = idx{0};
8669  }
8670
8671  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8672                                      V128, V128,
8673                                      V128, VectorIndexS,
8674                                      asm, ".4s", ".4s", ".4s", ".s",
8675    [(set (v4i32 V128:$dst),
8676       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8677          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8678    bits<2> idx;
8679    let Inst{11} = idx{1};
8680    let Inst{21} = idx{0};
8681  }
8682}
8683
8684multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8685                             SDPatternOperator OpNode> {
8686  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8687                                      V128, V64,
8688                                      V128_lo, VectorIndexH,
8689                                      asm, ".4s", ".4s", ".4h", ".h",
8690    [(set (v4i32 V128:$Rd),
8691        (OpNode (v4i16 V64:$Rn),
8692         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8693    bits<3> idx;
8694    let Inst{11} = idx{2};
8695    let Inst{21} = idx{1};
8696    let Inst{20} = idx{0};
8697  }
8698
8699  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8700                                      V128, V128,
8701                                      V128_lo, VectorIndexH,
8702                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8703    [(set (v4i32 V128:$Rd),
8704          (OpNode (extract_high_v8i16 V128:$Rn),
8705                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8706                                                      VectorIndexH:$idx))))]> {
8707
8708    bits<3> idx;
8709    let Inst{11} = idx{2};
8710    let Inst{21} = idx{1};
8711    let Inst{20} = idx{0};
8712  }
8713
8714  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8715                                      V128, V64,
8716                                      V128, VectorIndexS,
8717                                      asm, ".2d", ".2d", ".2s", ".s",
8718    [(set (v2i64 V128:$Rd),
8719        (OpNode (v2i32 V64:$Rn),
8720         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8721    bits<2> idx;
8722    let Inst{11} = idx{1};
8723    let Inst{21} = idx{0};
8724  }
8725
8726  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8727                                      V128, V128,
8728                                      V128, VectorIndexS,
8729                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8730    [(set (v2i64 V128:$Rd),
8731          (OpNode (extract_high_v4i32 V128:$Rn),
8732                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8733                                                      VectorIndexS:$idx))))]> {
8734    bits<2> idx;
8735    let Inst{11} = idx{1};
8736    let Inst{21} = idx{0};
8737  }
8738
8739  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8740                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8741                                      asm, ".h", "", "", ".h", []> {
8742    bits<3> idx;
8743    let Inst{11} = idx{2};
8744    let Inst{21} = idx{1};
8745    let Inst{20} = idx{0};
8746  }
8747
8748  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8749                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8750                                      asm, ".s", "", "", ".s", []> {
8751    bits<2> idx;
8752    let Inst{11} = idx{1};
8753    let Inst{21} = idx{0};
8754  }
8755}
8756
8757multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8758                                       SDPatternOperator Accum> {
8759  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8760                                      V128, V64,
8761                                      V128_lo, VectorIndexH,
8762                                      asm, ".4s", ".4s", ".4h", ".h",
8763    [(set (v4i32 V128:$dst),
8764          (Accum (v4i32 V128:$Rd),
8765                 (v4i32 (int_aarch64_neon_sqdmull
8766                             (v4i16 V64:$Rn),
8767                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8768                                                    VectorIndexH:$idx))))))]> {
8769    bits<3> idx;
8770    let Inst{11} = idx{2};
8771    let Inst{21} = idx{1};
8772    let Inst{20} = idx{0};
8773  }
8774
8775  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8776  // intermediate EXTRACT_SUBREG would be untyped.
8777  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8778                (i32 (vector_extract (v4i32
8779                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8780                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8781                                                    VectorIndexH:$idx)))),
8782                         (i64 0))))),
8783            (EXTRACT_SUBREG
8784                (!cast<Instruction>(NAME # v4i16_indexed)
8785                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8786                    V128_lo:$Rm, VectorIndexH:$idx),
8787                ssub)>;
8788
8789  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8790                                      V128, V128,
8791                                      V128_lo, VectorIndexH,
8792                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8793    [(set (v4i32 V128:$dst),
8794          (Accum (v4i32 V128:$Rd),
8795                 (v4i32 (int_aarch64_neon_sqdmull
8796                            (extract_high_v8i16 V128:$Rn),
8797                            (extract_high_v8i16
8798                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8799                                                VectorIndexH:$idx))))))]> {
8800    bits<3> idx;
8801    let Inst{11} = idx{2};
8802    let Inst{21} = idx{1};
8803    let Inst{20} = idx{0};
8804  }
8805
8806  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8807                                      V128, V64,
8808                                      V128, VectorIndexS,
8809                                      asm, ".2d", ".2d", ".2s", ".s",
8810    [(set (v2i64 V128:$dst),
8811        (Accum (v2i64 V128:$Rd),
8812               (v2i64 (int_aarch64_neon_sqdmull
8813                          (v2i32 V64:$Rn),
8814                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8815                                                 VectorIndexS:$idx))))))]> {
8816    bits<2> idx;
8817    let Inst{11} = idx{1};
8818    let Inst{21} = idx{0};
8819  }
8820
8821  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8822                                      V128, V128,
8823                                      V128, VectorIndexS,
8824                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8825    [(set (v2i64 V128:$dst),
8826          (Accum (v2i64 V128:$Rd),
8827                 (v2i64 (int_aarch64_neon_sqdmull
8828                            (extract_high_v4i32 V128:$Rn),
8829                            (extract_high_v4i32
8830                                (AArch64duplane32 (v4i32 V128:$Rm),
8831                                                VectorIndexS:$idx))))))]> {
8832    bits<2> idx;
8833    let Inst{11} = idx{1};
8834    let Inst{21} = idx{0};
8835  }
8836
8837  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8838                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8839                                      asm, ".h", "", "", ".h", []> {
8840    bits<3> idx;
8841    let Inst{11} = idx{2};
8842    let Inst{21} = idx{1};
8843    let Inst{20} = idx{0};
8844  }
8845
8846
8847  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8848                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8849                                      asm, ".s", "", "", ".s",
8850    [(set (i64 FPR64Op:$dst),
8851          (Accum (i64 FPR64Op:$Rd),
8852                 (i64 (int_aarch64_neon_sqdmulls_scalar
8853                            (i32 FPR32Op:$Rn),
8854                            (i32 (vector_extract (v4i32 V128:$Rm),
8855                                                 VectorIndexS:$idx))))))]> {
8856
8857    bits<2> idx;
8858    let Inst{11} = idx{1};
8859    let Inst{21} = idx{0};
8860  }
8861}
8862
8863multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8864                                   SDPatternOperator OpNode> {
8865  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8866  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8867                                      V128, V64,
8868                                      V128_lo, VectorIndexH,
8869                                      asm, ".4s", ".4s", ".4h", ".h",
8870    [(set (v4i32 V128:$Rd),
8871        (OpNode (v4i16 V64:$Rn),
8872         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8873    bits<3> idx;
8874    let Inst{11} = idx{2};
8875    let Inst{21} = idx{1};
8876    let Inst{20} = idx{0};
8877  }
8878
8879  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8880                                      V128, V128,
8881                                      V128_lo, VectorIndexH,
8882                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8883    [(set (v4i32 V128:$Rd),
8884          (OpNode (extract_high_v8i16 V128:$Rn),
8885                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8886                                                      VectorIndexH:$idx))))]> {
8887
8888    bits<3> idx;
8889    let Inst{11} = idx{2};
8890    let Inst{21} = idx{1};
8891    let Inst{20} = idx{0};
8892  }
8893
8894  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8895                                      V128, V64,
8896                                      V128, VectorIndexS,
8897                                      asm, ".2d", ".2d", ".2s", ".s",
8898    [(set (v2i64 V128:$Rd),
8899        (OpNode (v2i32 V64:$Rn),
8900         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8901    bits<2> idx;
8902    let Inst{11} = idx{1};
8903    let Inst{21} = idx{0};
8904  }
8905
8906  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8907                                      V128, V128,
8908                                      V128, VectorIndexS,
8909                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8910    [(set (v2i64 V128:$Rd),
8911          (OpNode (extract_high_v4i32 V128:$Rn),
8912                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8913                                                      VectorIndexS:$idx))))]> {
8914    bits<2> idx;
8915    let Inst{11} = idx{1};
8916    let Inst{21} = idx{0};
8917  }
8918  }
8919}
8920
8921multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8922                                       SDPatternOperator OpNode> {
8923  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8924  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8925                                      V128, V64,
8926                                      V128_lo, VectorIndexH,
8927                                      asm, ".4s", ".4s", ".4h", ".h",
8928    [(set (v4i32 V128:$dst),
8929        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8930         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8931    bits<3> idx;
8932    let Inst{11} = idx{2};
8933    let Inst{21} = idx{1};
8934    let Inst{20} = idx{0};
8935  }
8936
8937  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8938                                      V128, V128,
8939                                      V128_lo, VectorIndexH,
8940                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8941    [(set (v4i32 V128:$dst),
8942          (OpNode (v4i32 V128:$Rd),
8943                  (extract_high_v8i16 V128:$Rn),
8944                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8945                                                      VectorIndexH:$idx))))]> {
8946    bits<3> idx;
8947    let Inst{11} = idx{2};
8948    let Inst{21} = idx{1};
8949    let Inst{20} = idx{0};
8950  }
8951
8952  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8953                                      V128, V64,
8954                                      V128, VectorIndexS,
8955                                      asm, ".2d", ".2d", ".2s", ".s",
8956    [(set (v2i64 V128:$dst),
8957        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8958         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8959    bits<2> idx;
8960    let Inst{11} = idx{1};
8961    let Inst{21} = idx{0};
8962  }
8963
8964  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8965                                      V128, V128,
8966                                      V128, VectorIndexS,
8967                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8968    [(set (v2i64 V128:$dst),
8969          (OpNode (v2i64 V128:$Rd),
8970                  (extract_high_v4i32 V128:$Rn),
8971                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8972                                                      VectorIndexS:$idx))))]> {
8973    bits<2> idx;
8974    let Inst{11} = idx{1};
8975    let Inst{21} = idx{0};
8976  }
8977  }
8978}
8979
8980//----------------------------------------------------------------------------
8981// AdvSIMD scalar shift by immediate
8982//----------------------------------------------------------------------------
8983
8984let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8985class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8986                     RegisterClass regtype1, RegisterClass regtype2,
8987                     Operand immtype, string asm, list<dag> pattern>
8988  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8989      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8990    Sched<[WriteVd]> {
8991  bits<5> Rd;
8992  bits<5> Rn;
8993  bits<7> imm;
8994  let Inst{31-30} = 0b01;
8995  let Inst{29}    = U;
8996  let Inst{28-23} = 0b111110;
8997  let Inst{22-16} = fixed_imm;
8998  let Inst{15-11} = opc;
8999  let Inst{10}    = 1;
9000  let Inst{9-5} = Rn;
9001  let Inst{4-0} = Rd;
9002}
9003
9004let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9005class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9006                     RegisterClass regtype1, RegisterClass regtype2,
9007                     Operand immtype, string asm, list<dag> pattern>
9008  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9009      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9010    Sched<[WriteVd]> {
9011  bits<5> Rd;
9012  bits<5> Rn;
9013  bits<7> imm;
9014  let Inst{31-30} = 0b01;
9015  let Inst{29}    = U;
9016  let Inst{28-23} = 0b111110;
9017  let Inst{22-16} = fixed_imm;
9018  let Inst{15-11} = opc;
9019  let Inst{10}    = 1;
9020  let Inst{9-5} = Rn;
9021  let Inst{4-0} = Rd;
9022}
9023
9024
9025multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9026  let Predicates = [HasNEON, HasFullFP16] in {
9027  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9028                              FPR16, FPR16, vecshiftR16, asm, []> {
9029    let Inst{19-16} = imm{3-0};
9030  }
9031  } // Predicates = [HasNEON, HasFullFP16]
9032  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9033                              FPR32, FPR32, vecshiftR32, asm, []> {
9034    let Inst{20-16} = imm{4-0};
9035  }
9036  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9037                              FPR64, FPR64, vecshiftR64, asm, []> {
9038    let Inst{21-16} = imm{5-0};
9039  }
9040}
9041
9042multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9043                             SDPatternOperator OpNode> {
9044  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9045                              FPR64, FPR64, vecshiftR64, asm,
9046  [(set (i64 FPR64:$Rd),
9047     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9048    let Inst{21-16} = imm{5-0};
9049  }
9050
9051  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9052            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9053}
9054
9055multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9056                                 SDPatternOperator OpNode = null_frag> {
9057  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9058                              FPR64, FPR64, vecshiftR64, asm,
9059  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9060                                                   (i32 vecshiftR64:$imm)))]> {
9061    let Inst{21-16} = imm{5-0};
9062  }
9063
9064  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9065                           (i32 vecshiftR64:$imm))),
9066            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9067                                            vecshiftR64:$imm)>;
9068}
9069
9070multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9071                             SDPatternOperator OpNode> {
9072  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9073                              FPR64, FPR64, vecshiftL64, asm,
9074    [(set (i64 FPR64:$Rd),
9075       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9076    let Inst{21-16} = imm{5-0};
9077  }
9078
9079  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9080            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9081}
9082
9083let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9084multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9085  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9086                              FPR64, FPR64, vecshiftL64, asm, []> {
9087    let Inst{21-16} = imm{5-0};
9088  }
9089}
9090
9091let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9092multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9093                               SDPatternOperator OpNode = null_frag> {
9094  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9095                              FPR8, FPR16, vecshiftR8, asm, []> {
9096    let Inst{18-16} = imm{2-0};
9097  }
9098
9099  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9100                              FPR16, FPR32, vecshiftR16, asm, []> {
9101    let Inst{19-16} = imm{3-0};
9102  }
9103
9104  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9105                              FPR32, FPR64, vecshiftR32, asm,
9106    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9107    let Inst{20-16} = imm{4-0};
9108  }
9109}
9110
9111multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9112                                SDPatternOperator OpNode> {
9113  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9114                              FPR8, FPR8, vecshiftL8, asm, []> {
9115    let Inst{18-16} = imm{2-0};
9116  }
9117
9118  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9119                              FPR16, FPR16, vecshiftL16, asm, []> {
9120    let Inst{19-16} = imm{3-0};
9121  }
9122
9123  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9124                              FPR32, FPR32, vecshiftL32, asm,
9125    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9126    let Inst{20-16} = imm{4-0};
9127  }
9128
9129  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9130                              FPR64, FPR64, vecshiftL64, asm,
9131    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9132    let Inst{21-16} = imm{5-0};
9133  }
9134
9135  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9136            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9137}
9138
9139multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9140  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9141                              FPR8, FPR8, vecshiftR8, asm, []> {
9142    let Inst{18-16} = imm{2-0};
9143  }
9144
9145  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9146                              FPR16, FPR16, vecshiftR16, asm, []> {
9147    let Inst{19-16} = imm{3-0};
9148  }
9149
9150  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9151                              FPR32, FPR32, vecshiftR32, asm, []> {
9152    let Inst{20-16} = imm{4-0};
9153  }
9154
9155  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9156                              FPR64, FPR64, vecshiftR64, asm, []> {
9157    let Inst{21-16} = imm{5-0};
9158  }
9159}
9160
9161//----------------------------------------------------------------------------
9162// AdvSIMD vector x indexed element
9163//----------------------------------------------------------------------------
9164
9165let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9166class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9167                     RegisterOperand dst_reg, RegisterOperand src_reg,
9168                     Operand immtype,
9169                     string asm, string dst_kind, string src_kind,
9170                     list<dag> pattern>
9171  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9172      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9173           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9174    Sched<[!if(Q, WriteVq, WriteVd)]> {
9175  bits<5> Rd;
9176  bits<5> Rn;
9177  let Inst{31}    = 0;
9178  let Inst{30}    = Q;
9179  let Inst{29}    = U;
9180  let Inst{28-23} = 0b011110;
9181  let Inst{22-16} = fixed_imm;
9182  let Inst{15-11} = opc;
9183  let Inst{10}    = 1;
9184  let Inst{9-5}   = Rn;
9185  let Inst{4-0}   = Rd;
9186}
9187
9188let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9189class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9190                     RegisterOperand vectype1, RegisterOperand vectype2,
9191                     Operand immtype,
9192                     string asm, string dst_kind, string src_kind,
9193                     list<dag> pattern>
9194  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9195      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9196           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9197    Sched<[!if(Q, WriteVq, WriteVd)]> {
9198  bits<5> Rd;
9199  bits<5> Rn;
9200  let Inst{31}    = 0;
9201  let Inst{30}    = Q;
9202  let Inst{29}    = U;
9203  let Inst{28-23} = 0b011110;
9204  let Inst{22-16} = fixed_imm;
9205  let Inst{15-11} = opc;
9206  let Inst{10}    = 1;
9207  let Inst{9-5}   = Rn;
9208  let Inst{4-0}   = Rd;
9209}
9210
9211multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9212                              Intrinsic OpNode> {
9213  let Predicates = [HasNEON, HasFullFP16] in {
9214  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9215                                  V64, V64, vecshiftR16,
9216                                  asm, ".4h", ".4h",
9217      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9218    bits<4> imm;
9219    let Inst{19-16} = imm;
9220  }
9221
9222  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9223                                  V128, V128, vecshiftR16,
9224                                  asm, ".8h", ".8h",
9225      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9226    bits<4> imm;
9227    let Inst{19-16} = imm;
9228  }
9229  } // Predicates = [HasNEON, HasFullFP16]
9230  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9231                                  V64, V64, vecshiftR32,
9232                                  asm, ".2s", ".2s",
9233      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9234    bits<5> imm;
9235    let Inst{20-16} = imm;
9236  }
9237
9238  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9239                                  V128, V128, vecshiftR32,
9240                                  asm, ".4s", ".4s",
9241      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9242    bits<5> imm;
9243    let Inst{20-16} = imm;
9244  }
9245
9246  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9247                                  V128, V128, vecshiftR64,
9248                                  asm, ".2d", ".2d",
9249      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9250    bits<6> imm;
9251    let Inst{21-16} = imm;
9252  }
9253}
9254
9255multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9256                                  Intrinsic OpNode> {
9257  let Predicates = [HasNEON, HasFullFP16] in {
9258  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9259                                  V64, V64, vecshiftR16,
9260                                  asm, ".4h", ".4h",
9261      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9262    bits<4> imm;
9263    let Inst{19-16} = imm;
9264  }
9265
9266  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9267                                  V128, V128, vecshiftR16,
9268                                  asm, ".8h", ".8h",
9269      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9270    bits<4> imm;
9271    let Inst{19-16} = imm;
9272  }
9273  } // Predicates = [HasNEON, HasFullFP16]
9274
9275  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9276                                  V64, V64, vecshiftR32,
9277                                  asm, ".2s", ".2s",
9278      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9279    bits<5> imm;
9280    let Inst{20-16} = imm;
9281  }
9282
9283  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9284                                  V128, V128, vecshiftR32,
9285                                  asm, ".4s", ".4s",
9286      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9287    bits<5> imm;
9288    let Inst{20-16} = imm;
9289  }
9290
9291  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9292                                  V128, V128, vecshiftR64,
9293                                  asm, ".2d", ".2d",
9294      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9295    bits<6> imm;
9296    let Inst{21-16} = imm;
9297  }
9298}
9299
9300multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9301                                     SDPatternOperator OpNode> {
9302  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9303                                  V64, V128, vecshiftR16Narrow,
9304                                  asm, ".8b", ".8h",
9305      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9306    bits<3> imm;
9307    let Inst{18-16} = imm;
9308  }
9309
9310  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9311                                  V128, V128, vecshiftR16Narrow,
9312                                  asm#"2", ".16b", ".8h", []> {
9313    bits<3> imm;
9314    let Inst{18-16} = imm;
9315    let hasSideEffects = 0;
9316  }
9317
9318  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9319                                  V64, V128, vecshiftR32Narrow,
9320                                  asm, ".4h", ".4s",
9321      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9322    bits<4> imm;
9323    let Inst{19-16} = imm;
9324  }
9325
9326  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9327                                  V128, V128, vecshiftR32Narrow,
9328                                  asm#"2", ".8h", ".4s", []> {
9329    bits<4> imm;
9330    let Inst{19-16} = imm;
9331    let hasSideEffects = 0;
9332  }
9333
9334  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9335                                  V64, V128, vecshiftR64Narrow,
9336                                  asm, ".2s", ".2d",
9337      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9338    bits<5> imm;
9339    let Inst{20-16} = imm;
9340  }
9341
9342  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9343                                  V128, V128, vecshiftR64Narrow,
9344                                  asm#"2", ".4s", ".2d", []> {
9345    bits<5> imm;
9346    let Inst{20-16} = imm;
9347    let hasSideEffects = 0;
9348  }
9349
9350  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9351  // themselves, so put them here instead.
9352
9353  // Patterns involving what's effectively an insert high and a normal
9354  // intrinsic, represented by CONCAT_VECTORS.
9355  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9356                                                   vecshiftR16Narrow:$imm)),
9357            (!cast<Instruction>(NAME # "v16i8_shift")
9358                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9359                V128:$Rn, vecshiftR16Narrow:$imm)>;
9360  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9361                                                     vecshiftR32Narrow:$imm)),
9362            (!cast<Instruction>(NAME # "v8i16_shift")
9363                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9364                V128:$Rn, vecshiftR32Narrow:$imm)>;
9365  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9366                                                     vecshiftR64Narrow:$imm)),
9367            (!cast<Instruction>(NAME # "v4i32_shift")
9368                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9369                V128:$Rn, vecshiftR64Narrow:$imm)>;
9370}
9371
9372multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9373                                SDPatternOperator OpNode> {
9374  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9375                                  V64, V64, vecshiftL8,
9376                                  asm, ".8b", ".8b",
9377                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9378                       (i32 vecshiftL8:$imm)))]> {
9379    bits<3> imm;
9380    let Inst{18-16} = imm;
9381  }
9382
9383  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9384                                  V128, V128, vecshiftL8,
9385                                  asm, ".16b", ".16b",
9386             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9387                   (i32 vecshiftL8:$imm)))]> {
9388    bits<3> imm;
9389    let Inst{18-16} = imm;
9390  }
9391
9392  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9393                                  V64, V64, vecshiftL16,
9394                                  asm, ".4h", ".4h",
9395              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9396                    (i32 vecshiftL16:$imm)))]> {
9397    bits<4> imm;
9398    let Inst{19-16} = imm;
9399  }
9400
9401  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9402                                  V128, V128, vecshiftL16,
9403                                  asm, ".8h", ".8h",
9404            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9405                  (i32 vecshiftL16:$imm)))]> {
9406    bits<4> imm;
9407    let Inst{19-16} = imm;
9408  }
9409
9410  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9411                                  V64, V64, vecshiftL32,
9412                                  asm, ".2s", ".2s",
9413              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9414                    (i32 vecshiftL32:$imm)))]> {
9415    bits<5> imm;
9416    let Inst{20-16} = imm;
9417  }
9418
9419  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9420                                  V128, V128, vecshiftL32,
9421                                  asm, ".4s", ".4s",
9422            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9423                  (i32 vecshiftL32:$imm)))]> {
9424    bits<5> imm;
9425    let Inst{20-16} = imm;
9426  }
9427
9428  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9429                                  V128, V128, vecshiftL64,
9430                                  asm, ".2d", ".2d",
9431            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9432                  (i32 vecshiftL64:$imm)))]> {
9433    bits<6> imm;
9434    let Inst{21-16} = imm;
9435  }
9436}
9437
9438multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9439                                SDPatternOperator OpNode> {
9440  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9441                                  V64, V64, vecshiftR8,
9442                                  asm, ".8b", ".8b",
9443                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9444                       (i32 vecshiftR8:$imm)))]> {
9445    bits<3> imm;
9446    let Inst{18-16} = imm;
9447  }
9448
9449  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9450                                  V128, V128, vecshiftR8,
9451                                  asm, ".16b", ".16b",
9452             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9453                   (i32 vecshiftR8:$imm)))]> {
9454    bits<3> imm;
9455    let Inst{18-16} = imm;
9456  }
9457
9458  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9459                                  V64, V64, vecshiftR16,
9460                                  asm, ".4h", ".4h",
9461              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9462                    (i32 vecshiftR16:$imm)))]> {
9463    bits<4> imm;
9464    let Inst{19-16} = imm;
9465  }
9466
9467  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9468                                  V128, V128, vecshiftR16,
9469                                  asm, ".8h", ".8h",
9470            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9471                  (i32 vecshiftR16:$imm)))]> {
9472    bits<4> imm;
9473    let Inst{19-16} = imm;
9474  }
9475
9476  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9477                                  V64, V64, vecshiftR32,
9478                                  asm, ".2s", ".2s",
9479              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9480                    (i32 vecshiftR32:$imm)))]> {
9481    bits<5> imm;
9482    let Inst{20-16} = imm;
9483  }
9484
9485  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9486                                  V128, V128, vecshiftR32,
9487                                  asm, ".4s", ".4s",
9488            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9489                  (i32 vecshiftR32:$imm)))]> {
9490    bits<5> imm;
9491    let Inst{20-16} = imm;
9492  }
9493
9494  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9495                                  V128, V128, vecshiftR64,
9496                                  asm, ".2d", ".2d",
9497            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9498                  (i32 vecshiftR64:$imm)))]> {
9499    bits<6> imm;
9500    let Inst{21-16} = imm;
9501  }
9502}
9503
9504let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9505multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9506                                    SDPatternOperator OpNode = null_frag> {
9507  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9508                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9509                 [(set (v8i8 V64:$dst),
9510                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9511                           (i32 vecshiftR8:$imm)))]> {
9512    bits<3> imm;
9513    let Inst{18-16} = imm;
9514  }
9515
9516  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9517                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9518             [(set (v16i8 V128:$dst),
9519               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9520                       (i32 vecshiftR8:$imm)))]> {
9521    bits<3> imm;
9522    let Inst{18-16} = imm;
9523  }
9524
9525  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9526                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9527              [(set (v4i16 V64:$dst),
9528                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9529                        (i32 vecshiftR16:$imm)))]> {
9530    bits<4> imm;
9531    let Inst{19-16} = imm;
9532  }
9533
9534  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9535                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9536            [(set (v8i16 V128:$dst),
9537              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9538                      (i32 vecshiftR16:$imm)))]> {
9539    bits<4> imm;
9540    let Inst{19-16} = imm;
9541  }
9542
9543  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9544                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9545              [(set (v2i32 V64:$dst),
9546                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9547                        (i32 vecshiftR32:$imm)))]> {
9548    bits<5> imm;
9549    let Inst{20-16} = imm;
9550  }
9551
9552  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9553                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9554            [(set (v4i32 V128:$dst),
9555              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9556                      (i32 vecshiftR32:$imm)))]> {
9557    bits<5> imm;
9558    let Inst{20-16} = imm;
9559  }
9560
9561  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9562                                  V128, V128, vecshiftR64,
9563                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9564              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9565                      (i32 vecshiftR64:$imm)))]> {
9566    bits<6> imm;
9567    let Inst{21-16} = imm;
9568  }
9569}
9570
9571multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9572                                    SDPatternOperator OpNode = null_frag> {
9573  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9574                                  V64, V64, vecshiftL8,
9575                                  asm, ".8b", ".8b",
9576                    [(set (v8i8 V64:$dst),
9577                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9578                                  (i32 vecshiftL8:$imm)))]> {
9579    bits<3> imm;
9580    let Inst{18-16} = imm;
9581  }
9582
9583  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9584                                  V128, V128, vecshiftL8,
9585                                  asm, ".16b", ".16b",
9586                    [(set (v16i8 V128:$dst),
9587                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9588                                  (i32 vecshiftL8:$imm)))]> {
9589    bits<3> imm;
9590    let Inst{18-16} = imm;
9591  }
9592
9593  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9594                                  V64, V64, vecshiftL16,
9595                                  asm, ".4h", ".4h",
9596                    [(set (v4i16 V64:$dst),
9597                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9598                                   (i32 vecshiftL16:$imm)))]> {
9599    bits<4> imm;
9600    let Inst{19-16} = imm;
9601  }
9602
9603  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9604                                  V128, V128, vecshiftL16,
9605                                  asm, ".8h", ".8h",
9606                    [(set (v8i16 V128:$dst),
9607                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9608                                  (i32 vecshiftL16:$imm)))]> {
9609    bits<4> imm;
9610    let Inst{19-16} = imm;
9611  }
9612
9613  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9614                                  V64, V64, vecshiftL32,
9615                                  asm, ".2s", ".2s",
9616                    [(set (v2i32 V64:$dst),
9617                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9618                                  (i32 vecshiftL32:$imm)))]> {
9619    bits<5> imm;
9620    let Inst{20-16} = imm;
9621  }
9622
9623  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9624                                  V128, V128, vecshiftL32,
9625                                  asm, ".4s", ".4s",
9626                    [(set (v4i32 V128:$dst),
9627                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9628                                  (i32 vecshiftL32:$imm)))]> {
9629    bits<5> imm;
9630    let Inst{20-16} = imm;
9631  }
9632
9633  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9634                                  V128, V128, vecshiftL64,
9635                                  asm, ".2d", ".2d",
9636                    [(set (v2i64 V128:$dst),
9637                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9638                                  (i32 vecshiftL64:$imm)))]> {
9639    bits<6> imm;
9640    let Inst{21-16} = imm;
9641  }
9642}
9643
9644multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9645                                   SDPatternOperator OpNode> {
9646  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9647                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9648      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9649    bits<3> imm;
9650    let Inst{18-16} = imm;
9651  }
9652
9653  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9654                                  V128, V128, vecshiftL8,
9655                                  asm#"2", ".8h", ".16b",
9656      [(set (v8i16 V128:$Rd),
9657            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9658    bits<3> imm;
9659    let Inst{18-16} = imm;
9660  }
9661
9662  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9663                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9664      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9665    bits<4> imm;
9666    let Inst{19-16} = imm;
9667  }
9668
9669  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9670                                  V128, V128, vecshiftL16,
9671                                  asm#"2", ".4s", ".8h",
9672      [(set (v4i32 V128:$Rd),
9673            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9674
9675    bits<4> imm;
9676    let Inst{19-16} = imm;
9677  }
9678
9679  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9680                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9681      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9682    bits<5> imm;
9683    let Inst{20-16} = imm;
9684  }
9685
9686  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9687                                  V128, V128, vecshiftL32,
9688                                  asm#"2", ".2d", ".4s",
9689      [(set (v2i64 V128:$Rd),
9690            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9691    bits<5> imm;
9692    let Inst{20-16} = imm;
9693  }
9694}
9695
9696
9697//---
9698// Vector load/store
9699//---
9700// SIMD ldX/stX no-index memory references don't allow the optional
9701// ", #0" constant and handle post-indexing explicitly, so we use
9702// a more specialized parse method for them. Otherwise, it's the same as
9703// the general GPR64sp handling.
9704
9705class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9706                   string asm, dag oops, dag iops, list<dag> pattern>
9707  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9708  bits<5> Vt;
9709  bits<5> Rn;
9710  let Inst{31} = 0;
9711  let Inst{30} = Q;
9712  let Inst{29-23} = 0b0011000;
9713  let Inst{22} = L;
9714  let Inst{21-16} = 0b000000;
9715  let Inst{15-12} = opcode;
9716  let Inst{11-10} = size;
9717  let Inst{9-5} = Rn;
9718  let Inst{4-0} = Vt;
9719}
9720
9721class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9722                       string asm, dag oops, dag iops>
9723  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9724  bits<5> Vt;
9725  bits<5> Rn;
9726  bits<5> Xm;
9727  let Inst{31} = 0;
9728  let Inst{30} = Q;
9729  let Inst{29-23} = 0b0011001;
9730  let Inst{22} = L;
9731  let Inst{21} = 0;
9732  let Inst{20-16} = Xm;
9733  let Inst{15-12} = opcode;
9734  let Inst{11-10} = size;
9735  let Inst{9-5} = Rn;
9736  let Inst{4-0} = Vt;
9737}
9738
9739// The immediate form of AdvSIMD post-indexed addressing is encoded with
9740// register post-index addressing from the zero register.
9741multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9742                           int Offset, int Size> {
9743  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9744  //      "ld1\t$Vt, [$Rn], #16"
9745  // may get mapped to
9746  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9747  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9748                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9749                      GPR64sp:$Rn,
9750                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9751                      XZR), 1>;
9752
9753  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9754  //      "ld1.8b\t$Vt, [$Rn], #16"
9755  // may get mapped to
9756  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9757  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9758                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9759                      GPR64sp:$Rn,
9760                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9761                      XZR), 0>;
9762
9763  // E.g. "ld1.8b { v0, v1 }, [x1]"
9764  //      "ld1\t$Vt, [$Rn]"
9765  // may get mapped to
9766  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9767  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9768                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9769                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9770                      GPR64sp:$Rn), 0>;
9771
9772  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9773  //      "ld1\t$Vt, [$Rn], $Xm"
9774  // may get mapped to
9775  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9776  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9777                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9778                      GPR64sp:$Rn,
9779                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9780                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9781}
9782
9783multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9784                       int Offset128, int Offset64, bits<4> opcode> {
9785  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9786    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9787                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9788                           (ins GPR64sp:$Rn), []>;
9789    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9790                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9791                           (ins GPR64sp:$Rn), []>;
9792    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9793                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9794                           (ins GPR64sp:$Rn), []>;
9795    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9796                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9797                           (ins GPR64sp:$Rn), []>;
9798    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9799                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9800                           (ins GPR64sp:$Rn), []>;
9801    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9802                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9803                           (ins GPR64sp:$Rn), []>;
9804    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9805                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9806                           (ins GPR64sp:$Rn), []>;
9807
9808
9809    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9810                       (outs GPR64sp:$wback,
9811                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9812                       (ins GPR64sp:$Rn,
9813                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9814    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9815                       (outs GPR64sp:$wback,
9816                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9817                       (ins GPR64sp:$Rn,
9818                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9819    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9820                       (outs GPR64sp:$wback,
9821                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9822                       (ins GPR64sp:$Rn,
9823                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9824    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9825                       (outs GPR64sp:$wback,
9826                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9827                       (ins GPR64sp:$Rn,
9828                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9829    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9830                       (outs GPR64sp:$wback,
9831                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9832                       (ins GPR64sp:$Rn,
9833                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9834    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9835                       (outs GPR64sp:$wback,
9836                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9837                       (ins GPR64sp:$Rn,
9838                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9839    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9840                       (outs GPR64sp:$wback,
9841                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9842                       (ins GPR64sp:$Rn,
9843                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9844  }
9845
9846  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9847  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9848  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9849  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9850  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9851  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9852  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9853}
9854
9855// Only ld1/st1 has a v1d version.
9856multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9857                       int Offset128, int Offset64, bits<4> opcode> {
9858  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9859    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9860                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9861                                 GPR64sp:$Rn), []>;
9862    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9863                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9864                                GPR64sp:$Rn), []>;
9865    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9866                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9867                                GPR64sp:$Rn), []>;
9868    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9869                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9870                                GPR64sp:$Rn), []>;
9871    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9872                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9873                                GPR64sp:$Rn), []>;
9874    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9875                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9876                                GPR64sp:$Rn), []>;
9877    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9878                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9879                                GPR64sp:$Rn), []>;
9880
9881    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9882                       (outs GPR64sp:$wback),
9883                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9884                            GPR64sp:$Rn,
9885                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9886    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9887                       (outs GPR64sp:$wback),
9888                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9889                            GPR64sp:$Rn,
9890                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9891    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9892                       (outs GPR64sp:$wback),
9893                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9894                            GPR64sp:$Rn,
9895                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9896    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9897                       (outs GPR64sp:$wback),
9898                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9899                            GPR64sp:$Rn,
9900                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9901    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9902                       (outs GPR64sp:$wback),
9903                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9904                            GPR64sp:$Rn,
9905                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9906    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9907                       (outs GPR64sp:$wback),
9908                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9909                            GPR64sp:$Rn,
9910                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9911    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9912                       (outs GPR64sp:$wback),
9913                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9914                            GPR64sp:$Rn,
9915                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9916  }
9917
9918  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9919  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9920  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9921  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9922  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9923  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9924  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9925}
9926
9927multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9928                       int Offset128, int Offset64, bits<4> opcode>
9929  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9930
9931  // LD1 instructions have extra "1d" variants.
9932  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9933    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9934                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9935                           (ins GPR64sp:$Rn), []>;
9936
9937    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9938                       (outs GPR64sp:$wback,
9939                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9940                       (ins GPR64sp:$Rn,
9941                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9942  }
9943
9944  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9945}
9946
9947multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9948                       int Offset128, int Offset64, bits<4> opcode>
9949  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9950
9951  // ST1 instructions have extra "1d" variants.
9952  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9953    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9954                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9955                                GPR64sp:$Rn), []>;
9956
9957    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9958                       (outs GPR64sp:$wback),
9959                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9960                            GPR64sp:$Rn,
9961                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9962  }
9963
9964  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9965}
9966
9967multiclass SIMDLd1Multiple<string asm> {
9968  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9969  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9970  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9971  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9972}
9973
9974multiclass SIMDSt1Multiple<string asm> {
9975  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9976  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9977  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9978  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9979}
9980
9981multiclass SIMDLd2Multiple<string asm> {
9982  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9983}
9984
9985multiclass SIMDSt2Multiple<string asm> {
9986  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9987}
9988
9989multiclass SIMDLd3Multiple<string asm> {
9990  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9991}
9992
9993multiclass SIMDSt3Multiple<string asm> {
9994  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9995}
9996
9997multiclass SIMDLd4Multiple<string asm> {
9998  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9999}
10000
10001multiclass SIMDSt4Multiple<string asm> {
10002  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10003}
10004
10005//---
10006// AdvSIMD Load/store single-element
10007//---
10008
10009class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10010                         string asm, string operands, string cst,
10011                         dag oops, dag iops, list<dag> pattern>
10012  : I<oops, iops, asm, operands, cst, pattern> {
10013  bits<5> Vt;
10014  bits<5> Rn;
10015  let Inst{31} = 0;
10016  let Inst{29-24} = 0b001101;
10017  let Inst{22} = L;
10018  let Inst{21} = R;
10019  let Inst{15-13} = opcode;
10020  let Inst{9-5} = Rn;
10021  let Inst{4-0} = Vt;
10022}
10023
10024class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10025                         string asm, string operands, string cst,
10026                         dag oops, dag iops, list<dag> pattern>
10027  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10028  bits<5> Vt;
10029  bits<5> Rn;
10030  let Inst{31} = 0;
10031  let Inst{29-24} = 0b001101;
10032  let Inst{22} = L;
10033  let Inst{21} = R;
10034  let Inst{15-13} = opcode;
10035  let Inst{9-5} = Rn;
10036  let Inst{4-0} = Vt;
10037}
10038
10039
10040let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10041class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10042                  DAGOperand listtype>
10043  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10044                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10045                       []> {
10046  let Inst{30} = Q;
10047  let Inst{23} = 0;
10048  let Inst{20-16} = 0b00000;
10049  let Inst{12} = S;
10050  let Inst{11-10} = size;
10051}
10052let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10053class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10054                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10055  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10056                       "$Rn = $wback",
10057                       (outs GPR64sp:$wback, listtype:$Vt),
10058                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10059  bits<5> Xm;
10060  let Inst{30} = Q;
10061  let Inst{23} = 1;
10062  let Inst{20-16} = Xm;
10063  let Inst{12} = S;
10064  let Inst{11-10} = size;
10065}
10066
10067multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10068                          int Offset, int Size> {
10069  // E.g. "ld1r { v0.8b }, [x1], #1"
10070  //      "ld1r.8b\t$Vt, [$Rn], #1"
10071  // may get mapped to
10072  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10073  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10074                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10075                      GPR64sp:$Rn,
10076                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10077                      XZR), 1>;
10078
10079  // E.g. "ld1r.8b { v0 }, [x1], #1"
10080  //      "ld1r.8b\t$Vt, [$Rn], #1"
10081  // may get mapped to
10082  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10083  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10084                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10085                      GPR64sp:$Rn,
10086                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10087                      XZR), 0>;
10088
10089  // E.g. "ld1r.8b { v0 }, [x1]"
10090  //      "ld1r.8b\t$Vt, [$Rn]"
10091  // may get mapped to
10092  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10093  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10094                  (!cast<Instruction>(BaseName # "v" # layout)
10095                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10096                      GPR64sp:$Rn), 0>;
10097
10098  // E.g. "ld1r.8b { v0 }, [x1], x2"
10099  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10100  // may get mapped to
10101  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10102  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10103                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10104                      GPR64sp:$Rn,
10105                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10106                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10107}
10108
10109multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10110  int Offset1, int Offset2, int Offset4, int Offset8> {
10111  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10112                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10113  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10114                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10115  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10116                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10117  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10118                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10119  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10120                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10121  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10122                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10123  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10124                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10125  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10126                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10127
10128  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10129                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10130                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10131  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10132                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10133                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10134  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10135                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10136                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10137  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10138                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10139                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10140  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10141                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10142                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10143  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10144                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10145                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10146  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10147                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10148                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10149  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10150                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10151                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10152
10153  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10154  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10155  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10156  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10157  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10158  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10159  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10160  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10161}
10162
10163class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10164                      dag oops, dag iops, list<dag> pattern>
10165  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10166                       pattern> {
10167  // idx encoded in Q:S:size fields.
10168  bits<4> idx;
10169  let Inst{30} = idx{3};
10170  let Inst{23} = 0;
10171  let Inst{20-16} = 0b00000;
10172  let Inst{12} = idx{2};
10173  let Inst{11-10} = idx{1-0};
10174}
10175class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10176                      dag oops, dag iops, list<dag> pattern>
10177  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10178                           oops, iops, pattern> {
10179  // idx encoded in Q:S:size fields.
10180  bits<4> idx;
10181  let Inst{30} = idx{3};
10182  let Inst{23} = 0;
10183  let Inst{20-16} = 0b00000;
10184  let Inst{12} = idx{2};
10185  let Inst{11-10} = idx{1-0};
10186}
10187class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10188                          dag oops, dag iops>
10189  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10190                       "$Rn = $wback", oops, iops, []> {
10191  // idx encoded in Q:S:size fields.
10192  bits<4> idx;
10193  bits<5> Xm;
10194  let Inst{30} = idx{3};
10195  let Inst{23} = 1;
10196  let Inst{20-16} = Xm;
10197  let Inst{12} = idx{2};
10198  let Inst{11-10} = idx{1-0};
10199}
10200class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10201                          dag oops, dag iops>
10202  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10203                           "$Rn = $wback", oops, iops, []> {
10204  // idx encoded in Q:S:size fields.
10205  bits<4> idx;
10206  bits<5> Xm;
10207  let Inst{30} = idx{3};
10208  let Inst{23} = 1;
10209  let Inst{20-16} = Xm;
10210  let Inst{12} = idx{2};
10211  let Inst{11-10} = idx{1-0};
10212}
10213
10214class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10215                      dag oops, dag iops, list<dag> pattern>
10216  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10217                       pattern> {
10218  // idx encoded in Q:S:size<1> fields.
10219  bits<3> idx;
10220  let Inst{30} = idx{2};
10221  let Inst{23} = 0;
10222  let Inst{20-16} = 0b00000;
10223  let Inst{12} = idx{1};
10224  let Inst{11} = idx{0};
10225  let Inst{10} = size;
10226}
10227class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10228                      dag oops, dag iops, list<dag> pattern>
10229  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10230                           oops, iops, pattern> {
10231  // idx encoded in Q:S:size<1> fields.
10232  bits<3> idx;
10233  let Inst{30} = idx{2};
10234  let Inst{23} = 0;
10235  let Inst{20-16} = 0b00000;
10236  let Inst{12} = idx{1};
10237  let Inst{11} = idx{0};
10238  let Inst{10} = size;
10239}
10240
10241class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10242                          dag oops, dag iops>
10243  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10244                       "$Rn = $wback", oops, iops, []> {
10245  // idx encoded in Q:S:size<1> fields.
10246  bits<3> idx;
10247  bits<5> Xm;
10248  let Inst{30} = idx{2};
10249  let Inst{23} = 1;
10250  let Inst{20-16} = Xm;
10251  let Inst{12} = idx{1};
10252  let Inst{11} = idx{0};
10253  let Inst{10} = size;
10254}
10255class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10256                          dag oops, dag iops>
10257  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10258                           "$Rn = $wback", oops, iops, []> {
10259  // idx encoded in Q:S:size<1> fields.
10260  bits<3> idx;
10261  bits<5> Xm;
10262  let Inst{30} = idx{2};
10263  let Inst{23} = 1;
10264  let Inst{20-16} = Xm;
10265  let Inst{12} = idx{1};
10266  let Inst{11} = idx{0};
10267  let Inst{10} = size;
10268}
10269class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10270                      dag oops, dag iops, list<dag> pattern>
10271  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10272                       pattern> {
10273  // idx encoded in Q:S fields.
10274  bits<2> idx;
10275  let Inst{30} = idx{1};
10276  let Inst{23} = 0;
10277  let Inst{20-16} = 0b00000;
10278  let Inst{12} = idx{0};
10279  let Inst{11-10} = size;
10280}
10281class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10282                      dag oops, dag iops, list<dag> pattern>
10283  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10284                           oops, iops, pattern> {
10285  // idx encoded in Q:S fields.
10286  bits<2> idx;
10287  let Inst{30} = idx{1};
10288  let Inst{23} = 0;
10289  let Inst{20-16} = 0b00000;
10290  let Inst{12} = idx{0};
10291  let Inst{11-10} = size;
10292}
10293class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10294                          string asm, dag oops, dag iops>
10295  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10296                       "$Rn = $wback", oops, iops, []> {
10297  // idx encoded in Q:S fields.
10298  bits<2> idx;
10299  bits<5> Xm;
10300  let Inst{30} = idx{1};
10301  let Inst{23} = 1;
10302  let Inst{20-16} = Xm;
10303  let Inst{12} = idx{0};
10304  let Inst{11-10} = size;
10305}
10306class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10307                          string asm, dag oops, dag iops>
10308  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10309                           "$Rn = $wback", oops, iops, []> {
10310  // idx encoded in Q:S fields.
10311  bits<2> idx;
10312  bits<5> Xm;
10313  let Inst{30} = idx{1};
10314  let Inst{23} = 1;
10315  let Inst{20-16} = Xm;
10316  let Inst{12} = idx{0};
10317  let Inst{11-10} = size;
10318}
10319class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10320                      dag oops, dag iops, list<dag> pattern>
10321  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10322                       pattern> {
10323  // idx encoded in Q field.
10324  bits<1> idx;
10325  let Inst{30} = idx;
10326  let Inst{23} = 0;
10327  let Inst{20-16} = 0b00000;
10328  let Inst{12} = 0;
10329  let Inst{11-10} = size;
10330}
10331class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10332                      dag oops, dag iops, list<dag> pattern>
10333  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10334                           oops, iops, pattern> {
10335  // idx encoded in Q field.
10336  bits<1> idx;
10337  let Inst{30} = idx;
10338  let Inst{23} = 0;
10339  let Inst{20-16} = 0b00000;
10340  let Inst{12} = 0;
10341  let Inst{11-10} = size;
10342}
10343class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10344                          string asm, dag oops, dag iops>
10345  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10346                       "$Rn = $wback", oops, iops, []> {
10347  // idx encoded in Q field.
10348  bits<1> idx;
10349  bits<5> Xm;
10350  let Inst{30} = idx;
10351  let Inst{23} = 1;
10352  let Inst{20-16} = Xm;
10353  let Inst{12} = 0;
10354  let Inst{11-10} = size;
10355}
10356class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10357                          string asm, dag oops, dag iops>
10358  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10359                           "$Rn = $wback", oops, iops, []> {
10360  // idx encoded in Q field.
10361  bits<1> idx;
10362  bits<5> Xm;
10363  let Inst{30} = idx;
10364  let Inst{23} = 1;
10365  let Inst{20-16} = Xm;
10366  let Inst{12} = 0;
10367  let Inst{11-10} = size;
10368}
10369
10370let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10371multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10372                         RegisterOperand listtype,
10373                         RegisterOperand GPR64pi> {
10374  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10375                           (outs listtype:$dst),
10376                           (ins listtype:$Vt, VectorIndexB:$idx,
10377                                GPR64sp:$Rn), []>;
10378
10379  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10380                            (outs GPR64sp:$wback, listtype:$dst),
10381                            (ins listtype:$Vt, VectorIndexB:$idx,
10382                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10383}
10384let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10385multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10386                         RegisterOperand listtype,
10387                         RegisterOperand GPR64pi> {
10388  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10389                            (outs listtype:$dst),
10390                            (ins listtype:$Vt, VectorIndexH:$idx,
10391                                 GPR64sp:$Rn), []>;
10392
10393  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10394                            (outs GPR64sp:$wback, listtype:$dst),
10395                            (ins listtype:$Vt, VectorIndexH:$idx,
10396                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10397}
10398let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10399multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10400                         RegisterOperand listtype,
10401                         RegisterOperand GPR64pi> {
10402  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10403                            (outs listtype:$dst),
10404                            (ins listtype:$Vt, VectorIndexS:$idx,
10405                                 GPR64sp:$Rn), []>;
10406
10407  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10408                            (outs GPR64sp:$wback, listtype:$dst),
10409                            (ins listtype:$Vt, VectorIndexS:$idx,
10410                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10411}
10412let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10413multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10414                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10415  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10416                            (outs listtype:$dst),
10417                            (ins listtype:$Vt, VectorIndexD:$idx,
10418                                 GPR64sp:$Rn), []>;
10419
10420  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10421                            (outs GPR64sp:$wback, listtype:$dst),
10422                            (ins listtype:$Vt, VectorIndexD:$idx,
10423                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10424}
10425let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10426multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10427                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10428  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10429                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10430                                        GPR64sp:$Rn), []>;
10431
10432  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10433                                    (outs GPR64sp:$wback),
10434                                    (ins listtype:$Vt, VectorIndexB:$idx,
10435                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10436}
10437let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10438multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10439                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10440  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10441                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10442                                         GPR64sp:$Rn), []>;
10443
10444  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10445                            (outs GPR64sp:$wback),
10446                            (ins listtype:$Vt, VectorIndexH:$idx,
10447                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10448}
10449let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10450multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10451                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10452  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10453                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10454                                         GPR64sp:$Rn), []>;
10455
10456  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10457                            (outs GPR64sp:$wback),
10458                            (ins listtype:$Vt, VectorIndexS:$idx,
10459                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10460}
10461let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10462multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10463                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10464  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10465                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10466                                         GPR64sp:$Rn), []>;
10467
10468  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10469                            (outs GPR64sp:$wback),
10470                            (ins listtype:$Vt, VectorIndexD:$idx,
10471                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10472}
10473
10474multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10475                                 string Count, int Offset, Operand idxtype> {
10476  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10477  //      "ld1\t$Vt, [$Rn], #1"
10478  // may get mapped to
10479  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10480  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10481                  (!cast<Instruction>(NAME # Type  # "_POST")
10482                      GPR64sp:$Rn,
10483                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10484                      idxtype:$idx, XZR), 1>;
10485
10486  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10487  //      "ld1.8b\t$Vt, [$Rn], #1"
10488  // may get mapped to
10489  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10490  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10491                  (!cast<Instruction>(NAME # Type # "_POST")
10492                      GPR64sp:$Rn,
10493                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10494                      idxtype:$idx, XZR), 0>;
10495
10496  // E.g. "ld1.8b { v0 }[0], [x1]"
10497  //      "ld1.8b\t$Vt, [$Rn]"
10498  // may get mapped to
10499  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10500  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10501                      (!cast<Instruction>(NAME # Type)
10502                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10503                         idxtype:$idx, GPR64sp:$Rn), 0>;
10504
10505  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10506  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10507  // may get mapped to
10508  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10509  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10510                      (!cast<Instruction>(NAME # Type # "_POST")
10511                         GPR64sp:$Rn,
10512                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10513                         idxtype:$idx,
10514                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10515}
10516
10517multiclass SIMDLdSt1SingleAliases<string asm> {
10518  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10519  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10520  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10521  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10522}
10523
10524multiclass SIMDLdSt2SingleAliases<string asm> {
10525  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10526  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10527  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10528  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10529}
10530
10531multiclass SIMDLdSt3SingleAliases<string asm> {
10532  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10533  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10534  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10535  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10536}
10537
10538multiclass SIMDLdSt4SingleAliases<string asm> {
10539  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10540  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10541  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10542  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10543}
10544} // end of 'let Predicates = [HasNEON]'
10545
10546//----------------------------------------------------------------------------
10547// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10548//----------------------------------------------------------------------------
10549
10550let Predicates = [HasNEON, HasRDM] in {
10551
10552class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10553                                    RegisterOperand regtype, string asm,
10554                                    string kind, list<dag> pattern>
10555  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10556                                pattern> {
10557}
10558multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10559                                             SDPatternOperator op> {
10560  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10561    [(set (v4i16 V64:$dst),
10562          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10563  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10564    [(set (v8i16 V128:$dst),
10565          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10566  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10567    [(set (v2i32 V64:$dst),
10568          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10569  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10570    [(set (v4i32 V128:$dst),
10571          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10572}
10573
10574multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10575                                     SDPatternOperator op> {
10576  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10577                                          V64, V64, V128_lo, VectorIndexH,
10578                                          asm, ".4h", ".4h", ".4h", ".h",
10579    [(set (v4i16 V64:$dst),
10580          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10581                     (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10582                                              VectorIndexH:$idx)))))]> {
10583    bits<3> idx;
10584    let Inst{11} = idx{2};
10585    let Inst{21} = idx{1};
10586    let Inst{20} = idx{0};
10587  }
10588
10589  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10590                                          V128, V128, V128_lo, VectorIndexH,
10591                                          asm, ".8h", ".8h", ".8h", ".h",
10592    [(set (v8i16 V128:$dst),
10593          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10594                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10595                                              VectorIndexH:$idx)))))]> {
10596    bits<3> idx;
10597    let Inst{11} = idx{2};
10598    let Inst{21} = idx{1};
10599    let Inst{20} = idx{0};
10600  }
10601
10602  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10603                                          V64, V64, V128, VectorIndexS,
10604                                          asm, ".2s", ".2s", ".2s", ".s",
10605    [(set (v2i32 V64:$dst),
10606          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10607                     (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10608                                              VectorIndexS:$idx)))))]> {
10609    bits<2> idx;
10610    let Inst{11} = idx{1};
10611    let Inst{21} = idx{0};
10612  }
10613
10614  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10615                                          V128, V128, V128, VectorIndexS,
10616                                          asm, ".4s", ".4s", ".4s", ".s",
10617    [(set (v4i32 V128:$dst),
10618          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10619                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10620                                              VectorIndexS:$idx)))))]> {
10621    bits<2> idx;
10622    let Inst{11} = idx{1};
10623    let Inst{21} = idx{0};
10624  }
10625
10626  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10627                                        FPR16Op, FPR16Op, V128_lo,
10628                                        VectorIndexH, asm, ".h", "", "", ".h",
10629                                        []> {
10630    bits<3> idx;
10631    let Inst{11} = idx{2};
10632    let Inst{21} = idx{1};
10633    let Inst{20} = idx{0};
10634  }
10635
10636  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10637                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10638                                        asm, ".s", "", "", ".s",
10639    [(set (i32 FPR32Op:$dst),
10640          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10641                   (i32 (vector_extract (v4i32 V128:$Rm),
10642                                        VectorIndexS:$idx)))))]> {
10643    bits<2> idx;
10644    let Inst{11} = idx{1};
10645    let Inst{21} = idx{0};
10646  }
10647}
10648} // let Predicates = [HasNeon, HasRDM]
10649
10650//----------------------------------------------------------------------------
10651// ARMv8.3 Complex ADD/MLA instructions
10652//----------------------------------------------------------------------------
10653
10654class ComplexRotationOperand<int Angle, int Remainder, string Type>
10655  : AsmOperandClass {
10656  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10657  let DiagnosticType = "InvalidComplexRotation" # Type;
10658  let Name = "ComplexRotation" # Type;
10659}
10660def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10661                                                  SDNodeXForm<imm, [{
10662  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10663}]>> {
10664  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10665  let PrintMethod = "printComplexRotationOp<90, 0>";
10666}
10667def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10668                                                  SDNodeXForm<imm, [{
10669  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10670}]>> {
10671  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10672  let PrintMethod = "printComplexRotationOp<180, 90>";
10673}
10674let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10675class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10676                                     RegisterOperand regtype, Operand rottype,
10677                                     string asm, string kind, list<dag> pattern>
10678  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10679      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10680      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10681    Sched<[!if(Q, WriteVq, WriteVd)]> {
10682  bits<5> Rd;
10683  bits<5> Rn;
10684  bits<5> Rm;
10685  bits<1> rot;
10686  let Inst{31}    = 0;
10687  let Inst{30}    = Q;
10688  let Inst{29}    = U;
10689  let Inst{28-24} = 0b01110;
10690  let Inst{23-22} = size;
10691  let Inst{21}    = 0;
10692  let Inst{20-16} = Rm;
10693  let Inst{15-13} = opcode;
10694  // Non-tied version (FCADD) only has one rotation bit
10695  let Inst{12}    = rot;
10696  let Inst{11}    = 0;
10697  let Inst{10}    = 1;
10698  let Inst{9-5}   = Rn;
10699  let Inst{4-0}   = Rd;
10700}
10701
10702//8.3 CompNum - Floating-point complex number support
10703multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10704                                          string asm, SDPatternOperator OpNode>{
10705  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10706  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10707              asm, ".4h",
10708              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10709                                              (v4f16 V64:$Rn),
10710                                              (v4f16 V64:$Rm),
10711                                              (i32 rottype:$rot)))]>;
10712
10713  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10714              asm, ".8h",
10715              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10716                                               (v8f16 V128:$Rn),
10717                                               (v8f16 V128:$Rm),
10718                                               (i32 rottype:$rot)))]>;
10719  }
10720
10721  let Predicates = [HasComplxNum, HasNEON] in {
10722  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10723              asm, ".2s",
10724              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10725                                              (v2f32 V64:$Rn),
10726                                              (v2f32 V64:$Rm),
10727                                              (i32 rottype:$rot)))]>;
10728
10729  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10730              asm, ".4s",
10731              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10732                                               (v4f32 V128:$Rn),
10733                                               (v4f32 V128:$Rm),
10734                                               (i32 rottype:$rot)))]>;
10735
10736  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10737              asm, ".2d",
10738              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10739                                               (v2f64 V128:$Rn),
10740                                               (v2f64 V128:$Rm),
10741                                               (i32 rottype:$rot)))]>;
10742  }
10743}
10744
10745let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10746class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10747                                         bits<3> opcode,
10748                                         RegisterOperand regtype,
10749                                         Operand rottype, string asm,
10750                                         string kind, list<dag> pattern>
10751  : I<(outs regtype:$dst),
10752      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10753      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10754      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10755    Sched<[!if(Q, WriteVq, WriteVd)]> {
10756  bits<5> Rd;
10757  bits<5> Rn;
10758  bits<5> Rm;
10759  bits<2> rot;
10760  let Inst{31}    = 0;
10761  let Inst{30}    = Q;
10762  let Inst{29}    = U;
10763  let Inst{28-24} = 0b01110;
10764  let Inst{23-22} = size;
10765  let Inst{21}    = 0;
10766  let Inst{20-16} = Rm;
10767  let Inst{15-13} = opcode;
10768  let Inst{12-11} = rot;
10769  let Inst{10}    = 1;
10770  let Inst{9-5}   = Rn;
10771  let Inst{4-0}   = Rd;
10772}
10773
10774multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10775                                             Operand rottype, string asm,
10776                                             SDPatternOperator OpNode> {
10777  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10778  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10779              rottype, asm, ".4h",
10780              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10781                                              (v4f16 V64:$Rn),
10782                                              (v4f16 V64:$Rm),
10783                                              (i32 rottype:$rot)))]>;
10784
10785  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10786              rottype, asm, ".8h",
10787              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10788                                               (v8f16 V128:$Rn),
10789                                               (v8f16 V128:$Rm),
10790                                               (i32 rottype:$rot)))]>;
10791  }
10792
10793  let Predicates = [HasComplxNum, HasNEON] in {
10794  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10795              rottype, asm, ".2s",
10796              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10797                                              (v2f32 V64:$Rn),
10798                                              (v2f32 V64:$Rm),
10799                                              (i32 rottype:$rot)))]>;
10800
10801  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10802              rottype, asm, ".4s",
10803              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10804                                               (v4f32 V128:$Rn),
10805                                               (v4f32 V128:$Rm),
10806                                               (i32 rottype:$rot)))]>;
10807
10808  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10809              rottype, asm, ".2d",
10810              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10811                                               (v2f64 V128:$Rn),
10812                                               (v2f64 V128:$Rm),
10813                                               (i32 rottype:$rot)))]>;
10814  }
10815}
10816
10817let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10818class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10819                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10820                                 RegisterOperand lhs_reg,
10821                                 RegisterOperand rhs_reg, Operand vec_idx,
10822                                 Operand rottype, string asm, string apple_kind,
10823                                 string dst_kind, string lhs_kind,
10824                                 string rhs_kind, list<dag> pattern>
10825  : I<(outs dst_reg:$dst),
10826      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10827      asm,
10828      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10829      "$idx, $rot" # "|" # apple_kind #
10830      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10831    Sched<[!if(Q, WriteVq, WriteVd)]> {
10832  bits<5> Rd;
10833  bits<5> Rn;
10834  bits<5> Rm;
10835  bits<2> rot;
10836
10837  let Inst{31}    = 0;
10838  let Inst{30}    = Q;
10839  let Inst{29}    = U;
10840  let Inst{28}    = Scalar;
10841  let Inst{27-24} = 0b1111;
10842  let Inst{23-22} = size;
10843  // Bit 21 must be set by the derived class.
10844  let Inst{20-16} = Rm;
10845  let Inst{15}    = opc1;
10846  let Inst{14-13} = rot;
10847  let Inst{12}    = opc2;
10848  // Bit 11 must be set by the derived class.
10849  let Inst{10}    = 0;
10850  let Inst{9-5}   = Rn;
10851  let Inst{4-0}   = Rd;
10852}
10853
10854// The complex instructions index by pairs of elements, so the VectorIndexes
10855// don't match the lane types, and the index bits are different to the other
10856// classes.
10857multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
10858                                     string asm> {
10859  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10860  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10861                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10862                      ".4h", ".h", []> {
10863    bits<1> idx;
10864    let Inst{11} = 0;
10865    let Inst{21} = idx{0};
10866  }
10867
10868  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10869                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10870                      ".8h", ".8h", ".h", []> {
10871    bits<2> idx;
10872    let Inst{11} = idx{1};
10873    let Inst{21} = idx{0};
10874  }
10875  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10876
10877  let Predicates = [HasComplxNum, HasNEON] in {
10878  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10879                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10880                      ".4s", ".4s", ".s", []> {
10881    bits<1> idx;
10882    let Inst{11} = idx{0};
10883    let Inst{21} = 0;
10884  }
10885  } // Predicates = [HasComplxNum, HasNEON]
10886}
10887
10888//----------------------------------------------------------------------------
10889// Crypto extensions
10890//----------------------------------------------------------------------------
10891
10892let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10893class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10894              list<dag> pat>
10895  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10896    Sched<[WriteVq]>{
10897  bits<5> Rd;
10898  bits<5> Rn;
10899  let Inst{31-16} = 0b0100111000101000;
10900  let Inst{15-12} = opc;
10901  let Inst{11-10} = 0b10;
10902  let Inst{9-5}   = Rn;
10903  let Inst{4-0}   = Rd;
10904}
10905
10906class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10907  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10908            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10909
10910class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10911  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10912            "$Rd = $dst",
10913            [(set (v16i8 V128:$dst),
10914                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10915
10916let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10917class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10918                     dag oops, dag iops, list<dag> pat>
10919  : I<oops, iops, asm,
10920      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10921      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10922    Sched<[WriteVq]>{
10923  bits<5> Rd;
10924  bits<5> Rn;
10925  bits<5> Rm;
10926  let Inst{31-21} = 0b01011110000;
10927  let Inst{20-16} = Rm;
10928  let Inst{15}    = 0;
10929  let Inst{14-12} = opc;
10930  let Inst{11-10} = 0b00;
10931  let Inst{9-5}   = Rn;
10932  let Inst{4-0}   = Rd;
10933}
10934
10935class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10936  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10937                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10938                   [(set (v4i32 FPR128:$dst),
10939                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10940                                 (v4i32 V128:$Rm)))]>;
10941
10942class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10943  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10944                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10945                   [(set (v4i32 V128:$dst),
10946                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10947                                 (v4i32 V128:$Rm)))]>;
10948
10949class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10950  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10951                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10952                   [(set (v4i32 FPR128:$dst),
10953                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10954                                 (v4i32 V128:$Rm)))]>;
10955
10956let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10957class SHA2OpInst<bits<4> opc, string asm, string kind,
10958                 string cstr, dag oops, dag iops,
10959                 list<dag> pat>
10960  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10961                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10962    Sched<[WriteVq]>{
10963  bits<5> Rd;
10964  bits<5> Rn;
10965  let Inst{31-16} = 0b0101111000101000;
10966  let Inst{15-12} = opc;
10967  let Inst{11-10} = 0b10;
10968  let Inst{9-5}   = Rn;
10969  let Inst{4-0}   = Rd;
10970}
10971
10972class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10973  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10974               (ins V128:$Rd, V128:$Rn),
10975               [(set (v4i32 V128:$dst),
10976                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10977
10978class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10979  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10980               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10981
10982// Armv8.2-A Crypto extensions
10983class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10984                    list<dag> pattern>
10985  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
10986  bits<5> Vd;
10987  bits<5> Vn;
10988  let Inst{31-25} = 0b1100111;
10989  let Inst{9-5}   = Vn;
10990  let Inst{4-0}   = Vd;
10991}
10992
10993class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10994  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
10995                  "$Vd = $Vdst", []> {
10996  let Inst{31-25} = 0b1100111;
10997  let Inst{24-21} = 0b0110;
10998  let Inst{20-15} = 0b000001;
10999  let Inst{14}    = op0;
11000  let Inst{13-12} = 0b00;
11001  let Inst{11-10} = op1;
11002}
11003class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11004  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11005class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11006  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11007
11008class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11009                string asmops, string cst>
11010  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11011  bits<5> Vm;
11012  let Inst{24-21} = 0b0011;
11013  let Inst{20-16} = Vm;
11014  let Inst{15}    = 0b1;
11015  let Inst{14}    = op0;
11016  let Inst{13-12} = 0b00;
11017  let Inst{11-10} = op1;
11018}
11019class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11020  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11021              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11022class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11023  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11024              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11025class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11026  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11027              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11028class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11029  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11030              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11031class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11032  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11033              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11034
11035class CryptoRRRR<bits<2>op0, string asm, string asmops>
11036  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11037                  asmops, "", []> {
11038  bits<5> Vm;
11039  bits<5> Va;
11040  let Inst{24-23} = 0b00;
11041  let Inst{22-21} = op0;
11042  let Inst{20-16} = Vm;
11043  let Inst{15}    = 0b0;
11044  let Inst{14-10} = Va;
11045}
11046class CryptoRRRR_16B<bits<2>op0, string asm>
11047 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11048                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11049}
11050class CryptoRRRR_4S<bits<2>op0, string asm>
11051 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11052                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11053}
11054
11055class CryptoRRRi6<string asm>
11056  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11057                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11058                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11059  bits<6> imm;
11060  bits<5> Vm;
11061  let Inst{24-21} = 0b0100;
11062  let Inst{20-16} = Vm;
11063  let Inst{15-10} = imm;
11064  let Inst{9-5}   = Vn;
11065  let Inst{4-0}   = Vd;
11066}
11067
11068class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11069  : BaseCryptoV82<(outs V128:$Vdst),
11070                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11071                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11072                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11073  bits<2> imm;
11074  bits<5> Vm;
11075  let Inst{24-21} = 0b0010;
11076  let Inst{20-16} = Vm;
11077  let Inst{15}    = 0b1;
11078  let Inst{14}    = op0;
11079  let Inst{13-12} = imm;
11080  let Inst{11-10} = op1;
11081}
11082
11083//----------------------------------------------------------------------------
11084// v8.1 atomic instructions extension:
11085// * CAS
11086// * CASP
11087// * SWP
11088// * LDOPregister<OP>, and aliases STOPregister<OP>
11089
11090// Instruction encodings:
11091//
11092//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11093// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11094// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11095// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11096// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11097// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11098
11099// Instruction syntax:
11100//
11101// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11102// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11103// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11104// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11105// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11106// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11107// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11108// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11109// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11110// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11111
11112let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11113class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11114                      string cstr, list<dag> pattern>
11115      : I<oops, iops, asm, operands, cstr, pattern> {
11116  bits<2> Sz;
11117  bit NP;
11118  bit Acq;
11119  bit Rel;
11120  bits<5> Rs;
11121  bits<5> Rn;
11122  bits<5> Rt;
11123  let Inst{31-30} = Sz;
11124  let Inst{29-24} = 0b001000;
11125  let Inst{23} = NP;
11126  let Inst{22} = Acq;
11127  let Inst{21} = 0b1;
11128  let Inst{20-16} = Rs;
11129  let Inst{15} = Rel;
11130  let Inst{14-10} = 0b11111;
11131  let Inst{9-5} = Rn;
11132  let Inst{4-0} = Rt;
11133  let Predicates = [HasLSE];
11134}
11135
11136class BaseCAS<string order, string size, RegisterClass RC>
11137      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11138                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11139                        "$out = $Rs",[]>,
11140        Sched<[WriteAtomic]> {
11141  let NP = 1;
11142}
11143
11144multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11145  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11146  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11147  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11148  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11149}
11150
11151class BaseCASP<string order, string size, RegisterOperand RC>
11152      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11153                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11154                        "$out = $Rs",[]>,
11155        Sched<[WriteAtomic]> {
11156  let NP = 0;
11157}
11158
11159multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11160  let Sz = 0b00, Acq = Acq, Rel = Rel in
11161    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11162  let Sz = 0b01, Acq = Acq, Rel = Rel in
11163    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11164}
11165
11166let Predicates = [HasLSE] in
11167class BaseSWP<string order, string size, RegisterClass RC>
11168      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11169          "\t$Rs, $Rt, [$Rn]","",[]>,
11170        Sched<[WriteAtomic]> {
11171  bits<2> Sz;
11172  bit Acq;
11173  bit Rel;
11174  bits<5> Rs;
11175  bits<3> opc = 0b000;
11176  bits<5> Rn;
11177  bits<5> Rt;
11178  let Inst{31-30} = Sz;
11179  let Inst{29-24} = 0b111000;
11180  let Inst{23} = Acq;
11181  let Inst{22} = Rel;
11182  let Inst{21} = 0b1;
11183  let Inst{20-16} = Rs;
11184  let Inst{15} = 0b1;
11185  let Inst{14-12} = opc;
11186  let Inst{11-10} = 0b00;
11187  let Inst{9-5} = Rn;
11188  let Inst{4-0} = Rt;
11189  let Predicates = [HasLSE];
11190}
11191
11192multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11193  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11194  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11195  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11196  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11197}
11198
11199let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11200class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11201      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11202          "\t$Rs, $Rt, [$Rn]","",[]>,
11203        Sched<[WriteAtomic]> {
11204  bits<2> Sz;
11205  bit Acq;
11206  bit Rel;
11207  bits<5> Rs;
11208  bits<3> opc;
11209  bits<5> Rn;
11210  bits<5> Rt;
11211  let Inst{31-30} = Sz;
11212  let Inst{29-24} = 0b111000;
11213  let Inst{23} = Acq;
11214  let Inst{22} = Rel;
11215  let Inst{21} = 0b1;
11216  let Inst{20-16} = Rs;
11217  let Inst{15} = 0b0;
11218  let Inst{14-12} = opc;
11219  let Inst{11-10} = 0b00;
11220  let Inst{9-5} = Rn;
11221  let Inst{4-0} = Rt;
11222  let Predicates = [HasLSE];
11223}
11224
11225multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11226                        string order> {
11227  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11228    def B : BaseLDOPregister<op, order, "b", GPR32>;
11229  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11230    def H : BaseLDOPregister<op, order, "h", GPR32>;
11231  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11232    def W : BaseLDOPregister<op, order, "", GPR32>;
11233  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11234    def X : BaseLDOPregister<op, order, "", GPR64>;
11235}
11236
11237// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11238// complex DAG for DstRHS.
11239let Predicates = [HasLSE] in
11240multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11241                                         string size, dag SrcRHS, dag DstRHS> {
11242  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11243            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11244  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11245            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11246  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11247            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11248  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11249            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11250  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11251            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11252}
11253
11254multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11255                                     string size, dag RHS> {
11256  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11257}
11258
11259multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11260                                         string size, dag LHS, dag RHS> {
11261  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11262}
11263
11264multiclass LDOPregister_patterns<string inst, string op> {
11265  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11266  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11267  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11268  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11269}
11270
11271multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11272  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11273                        (i64 GPR64:$Rm),
11274                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11275  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11276                        (i32 GPR32:$Rm),
11277                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11278  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11279                        (i32 GPR32:$Rm),
11280                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11281  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11282                        (i32 GPR32:$Rm),
11283                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11284}
11285
11286let Predicates = [HasLSE] in
11287multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11288                                        string size, dag OLD, dag NEW> {
11289  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11290            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11291  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11292            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11293  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11294            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11295  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11296            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11297  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11298            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11299}
11300
11301multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11302                                    string size, dag OLD, dag NEW> {
11303  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11304}
11305
11306multiclass CASregister_patterns<string inst, string op> {
11307  defm : CASregister_patterns_ord<inst, "X", op, "64",
11308                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11309  defm : CASregister_patterns_ord<inst, "W", op, "32",
11310                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11311  defm : CASregister_patterns_ord<inst, "H", op, "16",
11312                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11313  defm : CASregister_patterns_ord<inst, "B", op, "8",
11314                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11315}
11316
11317let Predicates = [HasLSE] in
11318class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11319                        Instruction inst> :
11320      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11321
11322multiclass STOPregister<string asm, string instr> {
11323  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11324                    !cast<Instruction>(instr # "LB")>;
11325  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11326                    !cast<Instruction>(instr # "LH")>;
11327  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11328                    !cast<Instruction>(instr # "LW")>;
11329  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11330                    !cast<Instruction>(instr # "LX")>;
11331  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11332                    !cast<Instruction>(instr # "B")>;
11333  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11334                    !cast<Instruction>(instr # "H")>;
11335  def : BaseSTOPregister<asm,        GPR32, WZR,
11336                    !cast<Instruction>(instr # "W")>;
11337  def : BaseSTOPregister<asm,        GPR64, XZR,
11338                    !cast<Instruction>(instr # "X")>;
11339}
11340
11341class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11342                        dag iops, dag oops, list<dag> pat>
11343    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11344      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11345  bits<5> Rt;
11346  bits<5> Rn;
11347  let Inst{31-21} = 0b11111000001;
11348  let Inst{15}    = 1;
11349  let Inst{14-12} = opc;
11350  let Inst{11-10} = 0b00;
11351  let Inst{9-5}   = Rn;
11352  let Inst{4-0}   = Rt;
11353
11354  let Predicates = [HasV8_7a];
11355}
11356
11357class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11358                      list<dag> pat = []>
11359    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11360  let Inst{20-16} = 0b11111;
11361}
11362
11363class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11364    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11365                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11366  bits<5> Rs;
11367  let Inst{20-16} = Rs;
11368}
11369
11370class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11371                             bits<2> op2, string asm>
11372  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11373      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11374      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11375      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11376    Sched<[]> {
11377  bits<5> Rd;
11378  bits<5> Rs;
11379  bits<5> Rn;
11380  let Inst{31-27} = 0b00011;
11381  let Inst{26} = isMove;
11382  let Inst{25-24} = 0b01;
11383  let Inst{23-22} = opcode;
11384  let Inst{21} = 0b0;
11385  let Inst{20-16} = Rs;
11386  let Inst{15-14} = op2;
11387  let Inst{13-12} = op1;
11388  let Inst{11-10} = 0b01;
11389  let Inst{9-5} = Rn;
11390  let Inst{4-0} = Rd;
11391
11392  let DecoderMethod = "DecodeCPYMemOpInstruction";
11393  let mayLoad = 1;
11394  let mayStore = 1;
11395}
11396
11397class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11398  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11399
11400class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11401  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11402
11403class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11404                        string asm>
11405  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11406      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11407      asm, "\t[$Rd]!, $Rn!, $Rm",
11408      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11409    Sched<[]> {
11410  bits<5> Rd;
11411  bits<5> Rn;
11412  bits<5> Rm;
11413  let Inst{31-27} = 0b00011;
11414  let Inst{26} = isTagging;
11415  let Inst{25-21} = 0b01110;
11416  let Inst{20-16} = Rm;
11417  let Inst{15-14} = opcode;
11418  let Inst{13} = op2;
11419  let Inst{12} = op1;
11420  let Inst{11-10} = 0b01;
11421  let Inst{9-5} = Rn;
11422  let Inst{4-0} = Rd;
11423
11424  let DecoderMethod = "DecodeSETMemOpInstruction";
11425  let mayLoad = 0;
11426  let mayStore = 1;
11427}
11428
11429class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11430  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11431
11432class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11433  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11434
11435multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11436  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11437  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11438  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11439  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11440  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11441  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11442  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11443  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11444  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11445  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11446  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11447  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11448  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11449  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11450  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11451  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11452}
11453
11454multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11455  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11456  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11457  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11458  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11459  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11460  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11461  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11462  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11463  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11464  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11465  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11466  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11467  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11468  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11469  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11470  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11471}
11472
11473multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11474  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11475  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11476  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11477  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11478}
11479
11480multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11481  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11482  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11483  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11484  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11485}
11486
11487//----------------------------------------------------------------------------
11488// Allow the size specifier tokens to be upper case, not just lower.
11489def : TokenAlias<".4B", ".4b">;  // Add dot product
11490def : TokenAlias<".8B", ".8b">;
11491def : TokenAlias<".4H", ".4h">;
11492def : TokenAlias<".2S", ".2s">;
11493def : TokenAlias<".1D", ".1d">;
11494def : TokenAlias<".16B", ".16b">;
11495def : TokenAlias<".8H", ".8h">;
11496def : TokenAlias<".4S", ".4s">;
11497def : TokenAlias<".2D", ".2d">;
11498def : TokenAlias<".1Q", ".1q">;
11499def : TokenAlias<".2H", ".2h">;
11500def : TokenAlias<".B", ".b">;
11501def : TokenAlias<".H", ".h">;
11502def : TokenAlias<".S", ".s">;
11503def : TokenAlias<".D", ".d">;
11504def : TokenAlias<".Q", ".q">;
11505