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>;
39
40class FalseLanesEnum<bits<2> val> {
41  bits<2> Value = val;
42}
43def FalseLanesNone  : FalseLanesEnum<0>;
44def FalseLanesZero  : FalseLanesEnum<1>;
45def FalseLanesUndef : FalseLanesEnum<2>;
46
47// AArch64 Instruction Format
48class AArch64Inst<Format f, string cstr> : Instruction {
49  field bits<32> Inst; // Instruction encoding.
50  // Mask of bits that cause an encoding to be UNPREDICTABLE.
51  // If a bit is set, then if the corresponding bit in the
52  // target encoding differs from its value in the "Inst" field,
53  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
54  field bits<32> Unpredictable = 0;
55  // SoftFail is the generic name for this field, but we alias it so
56  // as to make it more obvious what it means in ARM-land.
57  field bits<32> SoftFail = Unpredictable;
58  let Namespace   = "AArch64";
59  Format F        = f;
60  bits<2> Form    = F.Value;
61
62  // Defaults
63  FalseLanesEnum FalseLanes = FalseLanesNone;
64  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
65  ElementSizeEnum ElementSize = ElementSizeNone;
66
67  let TSFlags{8-7} = FalseLanes.Value;
68  let TSFlags{6-3} = DestructiveInstType.Value;
69  let TSFlags{2-0} = ElementSize.Value;
70
71  let Pattern     = [];
72  let Constraints = cstr;
73}
74
75class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
76  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
77
78// Pseudo instructions (don't have encoding information)
79class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
80    : AArch64Inst<PseudoFrm, cstr> {
81  dag OutOperandList = oops;
82  dag InOperandList  = iops;
83  let Pattern        = pattern;
84  let isCodeGenOnly  = 1;
85  let isPseudo       = 1;
86}
87
88// Real instructions (have encoding information)
89class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
90  let Pattern = pattern;
91  let Size = 4;
92}
93
94// Normal instructions
95class I<dag oops, dag iops, string asm, string operands, string cstr,
96        list<dag> pattern>
97    : EncodedI<cstr, pattern> {
98  dag OutOperandList = oops;
99  dag InOperandList  = iops;
100  let AsmString      = !strconcat(asm, operands);
101}
102
103class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
104class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
105class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
106
107// Helper fragment for an extract of the high portion of a 128-bit vector.
108def extract_high_v16i8 :
109   UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
110def extract_high_v8i16 :
111   UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
112def extract_high_v4i32 :
113   UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
114def extract_high_v2i64 :
115   UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
116
117//===----------------------------------------------------------------------===//
118// Asm Operand Classes.
119//
120
121// Shifter operand for arithmetic shifted encodings.
122def ShifterOperand : AsmOperandClass {
123  let Name = "Shifter";
124}
125
126// Shifter operand for mov immediate encodings.
127def MovImm32ShifterOperand : AsmOperandClass {
128  let SuperClasses = [ShifterOperand];
129  let Name = "MovImm32Shifter";
130  let RenderMethod = "addShifterOperands";
131  let DiagnosticType = "InvalidMovImm32Shift";
132}
133def MovImm64ShifterOperand : AsmOperandClass {
134  let SuperClasses = [ShifterOperand];
135  let Name = "MovImm64Shifter";
136  let RenderMethod = "addShifterOperands";
137  let DiagnosticType = "InvalidMovImm64Shift";
138}
139
140// Shifter operand for arithmetic register shifted encodings.
141class ArithmeticShifterOperand<int width> : AsmOperandClass {
142  let SuperClasses = [ShifterOperand];
143  let Name = "ArithmeticShifter" # width;
144  let PredicateMethod = "isArithmeticShifter<" # width # ">";
145  let RenderMethod = "addShifterOperands";
146  let DiagnosticType = "AddSubRegShift" # width;
147}
148
149def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
150def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
151
152// Shifter operand for logical register shifted encodings.
153class LogicalShifterOperand<int width> : AsmOperandClass {
154  let SuperClasses = [ShifterOperand];
155  let Name = "LogicalShifter" # width;
156  let PredicateMethod = "isLogicalShifter<" # width # ">";
157  let RenderMethod = "addShifterOperands";
158  let DiagnosticType = "AddSubRegShift" # width;
159}
160
161def LogicalShifterOperand32 : LogicalShifterOperand<32>;
162def LogicalShifterOperand64 : LogicalShifterOperand<64>;
163
164// Shifter operand for logical vector 128/64-bit shifted encodings.
165def LogicalVecShifterOperand : AsmOperandClass {
166  let SuperClasses = [ShifterOperand];
167  let Name = "LogicalVecShifter";
168  let RenderMethod = "addShifterOperands";
169}
170def LogicalVecHalfWordShifterOperand : AsmOperandClass {
171  let SuperClasses = [LogicalVecShifterOperand];
172  let Name = "LogicalVecHalfWordShifter";
173  let RenderMethod = "addShifterOperands";
174}
175
176// The "MSL" shifter on the vector MOVI instruction.
177def MoveVecShifterOperand : AsmOperandClass {
178  let SuperClasses = [ShifterOperand];
179  let Name = "MoveVecShifter";
180  let RenderMethod = "addShifterOperands";
181}
182
183// Extend operand for arithmetic encodings.
184def ExtendOperand : AsmOperandClass {
185  let Name = "Extend";
186  let DiagnosticType = "AddSubRegExtendLarge";
187}
188def ExtendOperand64 : AsmOperandClass {
189  let SuperClasses = [ExtendOperand];
190  let Name = "Extend64";
191  let DiagnosticType = "AddSubRegExtendSmall";
192}
193// 'extend' that's a lsl of a 64-bit register.
194def ExtendOperandLSL64 : AsmOperandClass {
195  let SuperClasses = [ExtendOperand];
196  let Name = "ExtendLSL64";
197  let RenderMethod = "addExtend64Operands";
198  let DiagnosticType = "AddSubRegExtendLarge";
199}
200
201// 8-bit floating-point immediate encodings.
202def FPImmOperand : AsmOperandClass {
203  let Name = "FPImm";
204  let ParserMethod = "tryParseFPImm<true>";
205  let DiagnosticType = "InvalidFPImm";
206}
207
208def CondCode : AsmOperandClass {
209  let Name = "CondCode";
210  let DiagnosticType = "InvalidCondCode";
211}
212
213// A 32-bit register pasrsed as 64-bit
214def GPR32as64Operand : AsmOperandClass {
215  let Name = "GPR32as64";
216  let ParserMethod =
217      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
218}
219def GPR32as64 : RegisterOperand<GPR32> {
220  let ParserMatchClass = GPR32as64Operand;
221}
222
223// A 64-bit register pasrsed as 32-bit
224def GPR64as32Operand : AsmOperandClass {
225  let Name = "GPR64as32";
226  let ParserMethod =
227      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
228}
229def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
230  let ParserMatchClass = GPR64as32Operand;
231}
232
233// 8-bit immediate for AdvSIMD where 64-bit values of the form:
234// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
235// are encoded as the eight bit value 'abcdefgh'.
236def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
237
238class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
239  let Name = "UImm" # Width # "s" # Scale;
240  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
241  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
242  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
243}
244
245class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
246  let Name = "SImm" # Width # "s" # Scale;
247  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
248  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
249  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
250}
251
252//===----------------------------------------------------------------------===//
253// Operand Definitions.
254//
255
256// ADR[P] instruction labels.
257def AdrpOperand : AsmOperandClass {
258  let Name = "AdrpLabel";
259  let ParserMethod = "tryParseAdrpLabel";
260  let DiagnosticType = "InvalidLabel";
261}
262def adrplabel : Operand<i64> {
263  let EncoderMethod = "getAdrLabelOpValue";
264  let PrintMethod = "printAdrpLabel";
265  let ParserMatchClass = AdrpOperand;
266}
267
268def AdrOperand : AsmOperandClass {
269  let Name = "AdrLabel";
270  let ParserMethod = "tryParseAdrLabel";
271  let DiagnosticType = "InvalidLabel";
272}
273def adrlabel : Operand<i64> {
274  let EncoderMethod = "getAdrLabelOpValue";
275  let ParserMatchClass = AdrOperand;
276}
277
278class SImmOperand<int width> : AsmOperandClass {
279  let Name = "SImm" # width;
280  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
281  let RenderMethod = "addImmOperands";
282  let PredicateMethod = "isSImm<" # width # ">";
283}
284
285
286class AsmImmRange<int Low, int High> : AsmOperandClass {
287  let Name = "Imm" # Low # "_" # High;
288  let DiagnosticType = "InvalidImm" # Low # "_" # High;
289  let RenderMethod = "addImmOperands";
290  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
291}
292
293// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
294def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
295def simm10Scaled : Operand<i64> {
296  let ParserMatchClass = SImm10s8Operand;
297  let DecoderMethod = "DecodeSImm<10>";
298  let PrintMethod = "printImmScale<8>";
299}
300
301def simm9s16 : Operand<i64> {
302  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
303  let DecoderMethod = "DecodeSImm<9>";
304  let PrintMethod = "printImmScale<16>";
305}
306
307// uimm6 predicate - True if the immediate is in the range [0, 63].
308def UImm6Operand : AsmOperandClass {
309  let Name = "UImm6";
310  let DiagnosticType = "InvalidImm0_63";
311}
312
313def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
314  let ParserMatchClass = UImm6Operand;
315}
316
317def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
318  let ParserMatchClass = AsmImmRange<0, 65535>;
319}
320
321def SImm9Operand : SImmOperand<9>;
322def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
323  let ParserMatchClass = SImm9Operand;
324  let DecoderMethod = "DecodeSImm<9>";
325}
326
327def SImm8Operand : SImmOperand<8>;
328def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 127; }]> {
329  let ParserMatchClass = SImm8Operand;
330  let DecoderMethod = "DecodeSImm<8>";
331}
332
333def SImm6Operand : SImmOperand<6>;
334def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
335  let ParserMatchClass = SImm6Operand;
336  let DecoderMethod = "DecodeSImm<6>";
337}
338
339def SImm5Operand : SImmOperand<5>;
340def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
341  let ParserMatchClass = SImm5Operand;
342  let DecoderMethod = "DecodeSImm<5>";
343}
344
345def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
346  let ParserMatchClass = SImm5Operand;
347  let DecoderMethod = "DecodeSImm<5>";
348}
349
350def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
351  let ParserMatchClass = SImm5Operand;
352  let DecoderMethod = "DecodeSImm<5>";
353  let PrintMethod = "printSImm<8>";
354}
355
356def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
357  let ParserMatchClass = SImm5Operand;
358  let DecoderMethod = "DecodeSImm<5>";
359  let PrintMethod = "printSImm<16>";
360}
361
362// simm7sN predicate - True if the immediate is a multiple of N in the range
363// [-64 * N, 63 * N].
364
365def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
366def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
367def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
368
369def simm7s4 : Operand<i32> {
370  let ParserMatchClass = SImm7s4Operand;
371  let PrintMethod = "printImmScale<4>";
372}
373
374def simm7s8 : Operand<i32> {
375  let ParserMatchClass = SImm7s8Operand;
376  let PrintMethod = "printImmScale<8>";
377}
378
379def simm7s16 : Operand<i32> {
380  let ParserMatchClass = SImm7s16Operand;
381  let PrintMethod = "printImmScale<16>";
382}
383
384def am_sve_fi : ComplexPattern<i64, 2, "SelectAddrModeFrameIndexSVE", []>;
385
386def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
387def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
388def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
389def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
390def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
391
392def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
393def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
394
395def UImmS1XForm : SDNodeXForm<imm, [{
396  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
397}]>;
398def UImmS2XForm : SDNodeXForm<imm, [{
399  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
400}]>;
401def UImmS4XForm : SDNodeXForm<imm, [{
402  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
403}]>;
404def UImmS8XForm : SDNodeXForm<imm, [{
405  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
406}]>;
407
408// uimm5sN predicate - True if the immediate is a multiple of N in the range
409// [0 * N, 32 * N].
410def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
411def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
412def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
413
414def uimm5s2 : Operand<i64>, ImmLeaf<i64,
415                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
416                UImmS2XForm> {
417  let ParserMatchClass = UImm5s2Operand;
418  let PrintMethod = "printImmScale<2>";
419}
420def uimm5s4 : Operand<i64>, ImmLeaf<i64,
421                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
422                UImmS4XForm> {
423  let ParserMatchClass = UImm5s4Operand;
424  let PrintMethod = "printImmScale<4>";
425}
426def uimm5s8 : Operand<i64>, ImmLeaf<i64,
427                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
428                UImmS8XForm> {
429  let ParserMatchClass = UImm5s8Operand;
430  let PrintMethod = "printImmScale<8>";
431}
432
433// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
434// instead of ImmLeaf (Constant)
435def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
436                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
437                UImmS2XForm> {
438  let ParserMatchClass = UImm5s2Operand;
439  let PrintMethod = "printImmScale<2>";
440}
441def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
442                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
443                UImmS4XForm> {
444  let ParserMatchClass = UImm5s4Operand;
445  let PrintMethod = "printImmScale<4>";
446}
447def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
448                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
449                UImmS8XForm> {
450  let ParserMatchClass = UImm5s8Operand;
451  let PrintMethod = "printImmScale<8>";
452}
453
454// uimm6sN predicate - True if the immediate is a multiple of N in the range
455// [0 * N, 64 * N].
456def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
457def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
458def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
459def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
460def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
461
462def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
463  let ParserMatchClass = UImm6s1Operand;
464}
465def uimm6s2 : Operand<i64>, ImmLeaf<i64,
466[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
467  let PrintMethod = "printImmScale<2>";
468  let ParserMatchClass = UImm6s2Operand;
469}
470def uimm6s4 : Operand<i64>, ImmLeaf<i64,
471[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
472  let PrintMethod = "printImmScale<4>";
473  let ParserMatchClass = UImm6s4Operand;
474}
475def uimm6s8 : Operand<i64>, ImmLeaf<i64,
476[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
477  let PrintMethod = "printImmScale<8>";
478  let ParserMatchClass = UImm6s8Operand;
479}
480def uimm6s16 : Operand<i64>, ImmLeaf<i64,
481[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
482  let PrintMethod = "printImmScale<16>";
483  let ParserMatchClass = UImm6s16Operand;
484}
485
486def SImmS2XForm : SDNodeXForm<imm, [{
487  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
488}]>;
489def SImmS3XForm : SDNodeXForm<imm, [{
490  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
491}]>;
492def SImmS4XForm : SDNodeXForm<imm, [{
493  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
494}]>;
495def SImmS16XForm : SDNodeXForm<imm, [{
496  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
497}]>;
498def SImmS32XForm : SDNodeXForm<imm, [{
499  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
500}]>;
501
502// simm6sN predicate - True if the immediate is a multiple of N in the range
503// [-32 * N, 31 * N].
504def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
505def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
506  let ParserMatchClass = SImm6s1Operand;
507  let DecoderMethod = "DecodeSImm<6>";
508}
509
510// simm4sN predicate - True if the immediate is a multiple of N in the range
511// [ -8* N, 7 * N].
512def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
513def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
514def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
515def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
516def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
517def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
518
519def simm4s1 : Operand<i64>, ImmLeaf<i64,
520[{ return Imm >=-8  && Imm <= 7; }]> {
521  let ParserMatchClass = SImm4s1Operand;
522  let DecoderMethod = "DecodeSImm<4>";
523}
524
525def simm4s2 : Operand<i64>, ImmLeaf<i64,
526[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
527  let PrintMethod = "printImmScale<2>";
528  let ParserMatchClass = SImm4s2Operand;
529  let DecoderMethod = "DecodeSImm<4>";
530}
531
532def simm4s3 : Operand<i64>, ImmLeaf<i64,
533[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
534  let PrintMethod = "printImmScale<3>";
535  let ParserMatchClass = SImm4s3Operand;
536  let DecoderMethod = "DecodeSImm<4>";
537}
538
539def simm4s4 : Operand<i64>, ImmLeaf<i64,
540[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
541  let PrintMethod = "printImmScale<4>";
542  let ParserMatchClass = SImm4s4Operand;
543  let DecoderMethod = "DecodeSImm<4>";
544}
545def simm4s16 : Operand<i64>, ImmLeaf<i64,
546[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
547  let PrintMethod = "printImmScale<16>";
548  let ParserMatchClass = SImm4s16Operand;
549  let DecoderMethod = "DecodeSImm<4>";
550}
551def simm4s32 : Operand<i64>, ImmLeaf<i64,
552[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
553  let PrintMethod = "printImmScale<32>";
554  let ParserMatchClass = SImm4s32Operand;
555  let DecoderMethod = "DecodeSImm<4>";
556}
557
558def Imm1_8Operand : AsmImmRange<1, 8>;
559def Imm1_16Operand : AsmImmRange<1, 16>;
560def Imm1_32Operand : AsmImmRange<1, 32>;
561def Imm1_64Operand : AsmImmRange<1, 64>;
562
563class BranchTarget<int N> : AsmOperandClass {
564  let Name = "BranchTarget" # N;
565  let DiagnosticType = "InvalidLabel";
566  let PredicateMethod = "isBranchTarget<" # N # ">";
567}
568
569class PCRelLabel<int N> : BranchTarget<N> {
570  let Name = "PCRelLabel" # N;
571}
572
573def BranchTarget14Operand : BranchTarget<14>;
574def BranchTarget26Operand : BranchTarget<26>;
575def PCRelLabel19Operand   : PCRelLabel<19>;
576
577def MovWSymbolG3AsmOperand : AsmOperandClass {
578  let Name = "MovWSymbolG3";
579  let RenderMethod = "addImmOperands";
580}
581
582def movw_symbol_g3 : Operand<i32> {
583  let ParserMatchClass = MovWSymbolG3AsmOperand;
584}
585
586def MovWSymbolG2AsmOperand : AsmOperandClass {
587  let Name = "MovWSymbolG2";
588  let RenderMethod = "addImmOperands";
589}
590
591def movw_symbol_g2 : Operand<i32> {
592  let ParserMatchClass = MovWSymbolG2AsmOperand;
593}
594
595def MovWSymbolG1AsmOperand : AsmOperandClass {
596  let Name = "MovWSymbolG1";
597  let RenderMethod = "addImmOperands";
598}
599
600def movw_symbol_g1 : Operand<i32> {
601  let ParserMatchClass = MovWSymbolG1AsmOperand;
602}
603
604def MovWSymbolG0AsmOperand : AsmOperandClass {
605  let Name = "MovWSymbolG0";
606  let RenderMethod = "addImmOperands";
607}
608
609def movw_symbol_g0 : Operand<i32> {
610  let ParserMatchClass = MovWSymbolG0AsmOperand;
611}
612
613class fixedpoint_i32<ValueType FloatVT>
614  : Operand<FloatVT>,
615    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
616  let EncoderMethod = "getFixedPointScaleOpValue";
617  let DecoderMethod = "DecodeFixedPointScaleImm32";
618  let ParserMatchClass = Imm1_32Operand;
619}
620
621class fixedpoint_i64<ValueType FloatVT>
622  : Operand<FloatVT>,
623    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
624  let EncoderMethod = "getFixedPointScaleOpValue";
625  let DecoderMethod = "DecodeFixedPointScaleImm64";
626  let ParserMatchClass = Imm1_64Operand;
627}
628
629def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
630def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
631def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
632
633def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
634def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
635def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
636
637def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
638  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
639}]> {
640  let EncoderMethod = "getVecShiftR8OpValue";
641  let DecoderMethod = "DecodeVecShiftR8Imm";
642  let ParserMatchClass = Imm1_8Operand;
643}
644def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
645  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
646}]> {
647  let EncoderMethod = "getVecShiftR16OpValue";
648  let DecoderMethod = "DecodeVecShiftR16Imm";
649  let ParserMatchClass = Imm1_16Operand;
650}
651def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
652  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
653}]> {
654  let EncoderMethod = "getVecShiftR16OpValue";
655  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
656  let ParserMatchClass = Imm1_8Operand;
657}
658def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
659  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
660}]> {
661  let EncoderMethod = "getVecShiftR32OpValue";
662  let DecoderMethod = "DecodeVecShiftR32Imm";
663  let ParserMatchClass = Imm1_32Operand;
664}
665def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
666  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
667}]> {
668  let EncoderMethod = "getVecShiftR32OpValue";
669  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
670  let ParserMatchClass = Imm1_16Operand;
671}
672def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
673  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
674}]> {
675  let EncoderMethod = "getVecShiftR64OpValue";
676  let DecoderMethod = "DecodeVecShiftR64Imm";
677  let ParserMatchClass = Imm1_64Operand;
678}
679def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
680  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
681}]> {
682  let EncoderMethod = "getVecShiftR64OpValue";
683  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
684  let ParserMatchClass = Imm1_32Operand;
685}
686
687// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
688// (ImmLeaf)
689def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
690  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
691}]> {
692  let EncoderMethod = "getVecShiftR8OpValue";
693  let DecoderMethod = "DecodeVecShiftR8Imm";
694  let ParserMatchClass = Imm1_8Operand;
695}
696def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
697  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
698}]> {
699  let EncoderMethod = "getVecShiftR16OpValue";
700  let DecoderMethod = "DecodeVecShiftR16Imm";
701  let ParserMatchClass = Imm1_16Operand;
702}
703def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
704  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
705}]> {
706  let EncoderMethod = "getVecShiftR32OpValue";
707  let DecoderMethod = "DecodeVecShiftR32Imm";
708  let ParserMatchClass = Imm1_32Operand;
709}
710def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
711  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
712}]> {
713  let EncoderMethod = "getVecShiftR64OpValue";
714  let DecoderMethod = "DecodeVecShiftR64Imm";
715  let ParserMatchClass = Imm1_64Operand;
716}
717
718def Imm0_1Operand : AsmImmRange<0, 1>;
719def Imm0_7Operand : AsmImmRange<0, 7>;
720def Imm0_15Operand : AsmImmRange<0, 15>;
721def Imm0_31Operand : AsmImmRange<0, 31>;
722def Imm0_63Operand : AsmImmRange<0, 63>;
723
724def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
725  return (((uint32_t)Imm) < 8);
726}]> {
727  let EncoderMethod = "getVecShiftL8OpValue";
728  let DecoderMethod = "DecodeVecShiftL8Imm";
729  let ParserMatchClass = Imm0_7Operand;
730}
731def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
732  return (((uint32_t)Imm) < 16);
733}]> {
734  let EncoderMethod = "getVecShiftL16OpValue";
735  let DecoderMethod = "DecodeVecShiftL16Imm";
736  let ParserMatchClass = Imm0_15Operand;
737}
738def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
739  return (((uint32_t)Imm) < 32);
740}]> {
741  let EncoderMethod = "getVecShiftL32OpValue";
742  let DecoderMethod = "DecodeVecShiftL32Imm";
743  let ParserMatchClass = Imm0_31Operand;
744}
745def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
746  return (((uint32_t)Imm) < 64);
747}]> {
748  let EncoderMethod = "getVecShiftL64OpValue";
749  let DecoderMethod = "DecodeVecShiftL64Imm";
750  let ParserMatchClass = Imm0_63Operand;
751}
752
753// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
754// (ImmLeaf)
755def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
756  return (((uint32_t)Imm) < 8);
757}]> {
758  let EncoderMethod = "getVecShiftL8OpValue";
759  let DecoderMethod = "DecodeVecShiftL8Imm";
760  let ParserMatchClass = Imm0_7Operand;
761}
762def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
763  return (((uint32_t)Imm) < 16);
764}]> {
765  let EncoderMethod = "getVecShiftL16OpValue";
766  let DecoderMethod = "DecodeVecShiftL16Imm";
767  let ParserMatchClass = Imm0_15Operand;
768}
769def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
770  return (((uint32_t)Imm) < 32);
771}]> {
772  let EncoderMethod = "getVecShiftL32OpValue";
773  let DecoderMethod = "DecodeVecShiftL32Imm";
774  let ParserMatchClass = Imm0_31Operand;
775}
776def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
777  return (((uint32_t)Imm) < 64);
778}]> {
779  let EncoderMethod = "getVecShiftL64OpValue";
780  let DecoderMethod = "DecodeVecShiftL64Imm";
781  let ParserMatchClass = Imm0_63Operand;
782}
783
784// Crazy immediate formats used by 32-bit and 64-bit logical immediate
785// instructions for splatting repeating bit patterns across the immediate.
786def logical_imm32_XFORM : SDNodeXForm<imm, [{
787  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
788  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
789}]>;
790def logical_imm64_XFORM : SDNodeXForm<imm, [{
791  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
792  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
793}]>;
794
795def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
796  GISDNodeXFormEquiv<logical_imm32_XFORM>;
797def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
798  GISDNodeXFormEquiv<logical_imm64_XFORM>;
799
800let DiagnosticType = "LogicalSecondSource" in {
801  def LogicalImm32Operand : AsmOperandClass {
802    let Name = "LogicalImm32";
803    let PredicateMethod = "isLogicalImm<int32_t>";
804    let RenderMethod = "addLogicalImmOperands<int32_t>";
805  }
806  def LogicalImm64Operand : AsmOperandClass {
807    let Name = "LogicalImm64";
808    let PredicateMethod = "isLogicalImm<int64_t>";
809    let RenderMethod = "addLogicalImmOperands<int64_t>";
810  }
811  def LogicalImm32NotOperand : AsmOperandClass {
812    let Name = "LogicalImm32Not";
813    let PredicateMethod = "isLogicalImm<int32_t>";
814    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
815  }
816  def LogicalImm64NotOperand : AsmOperandClass {
817    let Name = "LogicalImm64Not";
818    let PredicateMethod = "isLogicalImm<int64_t>";
819    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
820  }
821}
822def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
823  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
824}], logical_imm32_XFORM> {
825  let PrintMethod = "printLogicalImm<int32_t>";
826  let ParserMatchClass = LogicalImm32Operand;
827}
828def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
829  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
830}], logical_imm64_XFORM> {
831  let PrintMethod = "printLogicalImm<int64_t>";
832  let ParserMatchClass = LogicalImm64Operand;
833}
834def logical_imm32_not : Operand<i32> {
835  let ParserMatchClass = LogicalImm32NotOperand;
836}
837def logical_imm64_not : Operand<i64> {
838  let ParserMatchClass = LogicalImm64NotOperand;
839}
840
841// iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
842let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
843def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
844  return ((uint32_t)Imm) < 65536;
845}]>;
846
847def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
848  return ((uint64_t)Imm) < 65536;
849}]>;
850}
851
852// imm0_255 predicate - True if the immediate is in the range [0,255].
853def Imm0_255Operand : AsmImmRange<0,255>;
854
855def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
856  return ((uint32_t)Imm) < 256;
857}]> {
858  let ParserMatchClass = Imm0_255Operand;
859  let PrintMethod = "printImm";
860}
861
862// imm0_127 predicate - True if the immediate is in the range [0,127]
863def Imm0_127Operand : AsmImmRange<0, 127>;
864def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
865  return ((uint32_t)Imm) < 128;
866}]> {
867  let ParserMatchClass = Imm0_127Operand;
868  let PrintMethod = "printImm";
869}
870
871def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
872  return ((uint64_t)Imm) < 128;
873}]> {
874  let ParserMatchClass = Imm0_127Operand;
875  let PrintMethod = "printImm";
876}
877
878// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
879// for all shift-amounts.
880
881// imm0_63 predicate - True if the immediate is in the range [0,63]
882def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
883  return ((uint64_t)Imm) < 64;
884}]> {
885  let ParserMatchClass = Imm0_63Operand;
886}
887
888// imm0_31 predicate - True if the immediate is in the range [0,31]
889def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
890  return ((uint64_t)Imm) < 32;
891}]> {
892  let ParserMatchClass = Imm0_31Operand;
893}
894
895// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
896// instead of Constant (ImmLeaf)
897def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
898  return ((uint64_t)Imm) < 32;
899}]> {
900  let ParserMatchClass = Imm0_31Operand;
901}
902
903// True if the 32-bit immediate is in the range [0,31]
904def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
905  return ((uint64_t)Imm) < 32;
906}]> {
907  let ParserMatchClass = Imm0_31Operand;
908}
909
910// imm0_1 predicate - True if the immediate is in the range [0,1]
911def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
912  return ((uint64_t)Imm) < 2;
913}]> {
914  let ParserMatchClass = Imm0_1Operand;
915}
916
917// timm0_1 - as above, but use TargetConstant (TImmLeaf)
918def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
919  return ((uint64_t)Imm) < 2;
920}]> {
921  let ParserMatchClass = Imm0_1Operand;
922}
923
924// imm0_15 predicate - True if the immediate is in the range [0,15]
925def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
926  return ((uint64_t)Imm) < 16;
927}]> {
928  let ParserMatchClass = Imm0_15Operand;
929}
930
931// imm0_7 predicate - True if the immediate is in the range [0,7]
932def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
933  return ((uint64_t)Imm) < 8;
934}]> {
935  let ParserMatchClass = Imm0_7Operand;
936}
937
938// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
939def imm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
940  return ((uint32_t)Imm) < 8;
941}]> {
942  let ParserMatchClass = Imm0_7Operand;
943}
944
945// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
946def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
947  return ((uint32_t)Imm) < 16;
948}]> {
949  let ParserMatchClass = Imm0_15Operand;
950}
951
952// An arithmetic shifter operand:
953//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
954//  {5-0} - imm6
955class arith_shift<ValueType Ty, int width> : Operand<Ty> {
956  let PrintMethod = "printShifter";
957  let ParserMatchClass = !cast<AsmOperandClass>(
958                         "ArithmeticShifterOperand" # width);
959}
960
961def arith_shift32 : arith_shift<i32, 32>;
962def arith_shift64 : arith_shift<i64, 64>;
963
964class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
965    : Operand<Ty>,
966      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
967  let PrintMethod = "printShiftedRegister";
968  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
969}
970
971def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
972def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
973
974def gi_arith_shifted_reg32 :
975  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
976  GIComplexPatternEquiv<arith_shifted_reg32>;
977
978def gi_arith_shifted_reg64 :
979  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
980  GIComplexPatternEquiv<arith_shifted_reg64>;
981
982// An arithmetic shifter operand:
983//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
984//  {5-0} - imm6
985class logical_shift<int width> : Operand<i32> {
986  let PrintMethod = "printShifter";
987  let ParserMatchClass = !cast<AsmOperandClass>(
988                         "LogicalShifterOperand" # width);
989}
990
991def logical_shift32 : logical_shift<32>;
992def logical_shift64 : logical_shift<64>;
993
994class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
995    : Operand<Ty>,
996      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
997  let PrintMethod = "printShiftedRegister";
998  let MIOperandInfo = (ops regclass, shiftop);
999}
1000
1001def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1002def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1003
1004def gi_logical_shifted_reg32 :
1005  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1006  GIComplexPatternEquiv<logical_shifted_reg32>;
1007
1008def gi_logical_shifted_reg64 :
1009  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1010  GIComplexPatternEquiv<logical_shifted_reg64>;
1011
1012// A logical vector shifter operand:
1013//  {7-6} - shift type: 00 = lsl
1014//  {5-0} - imm6: #0, #8, #16, or #24
1015def logical_vec_shift : Operand<i32> {
1016  let PrintMethod = "printShifter";
1017  let EncoderMethod = "getVecShifterOpValue";
1018  let ParserMatchClass = LogicalVecShifterOperand;
1019}
1020
1021// A logical vector half-word shifter operand:
1022//  {7-6} - shift type: 00 = lsl
1023//  {5-0} - imm6: #0 or #8
1024def logical_vec_hw_shift : Operand<i32> {
1025  let PrintMethod = "printShifter";
1026  let EncoderMethod = "getVecShifterOpValue";
1027  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1028}
1029
1030// A vector move shifter operand:
1031//  {0} - imm1: #8 or #16
1032def move_vec_shift : Operand<i32> {
1033  let PrintMethod = "printShifter";
1034  let EncoderMethod = "getMoveVecShifterOpValue";
1035  let ParserMatchClass = MoveVecShifterOperand;
1036}
1037
1038let DiagnosticType = "AddSubSecondSource" in {
1039  def AddSubImmOperand : AsmOperandClass {
1040    let Name = "AddSubImm";
1041    let ParserMethod = "tryParseImmWithOptionalShift";
1042    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1043  }
1044  def AddSubImmNegOperand : AsmOperandClass {
1045    let Name = "AddSubImmNeg";
1046    let ParserMethod = "tryParseImmWithOptionalShift";
1047    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1048  }
1049}
1050// An ADD/SUB immediate shifter operand:
1051//  second operand:
1052//  {7-6} - shift type: 00 = lsl
1053//  {5-0} - imm6: #0 or #12
1054class addsub_shifted_imm<ValueType Ty>
1055    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1056  let PrintMethod = "printAddSubImm";
1057  let EncoderMethod = "getAddSubImmOpValue";
1058  let ParserMatchClass = AddSubImmOperand;
1059  let MIOperandInfo = (ops i32imm, i32imm);
1060}
1061
1062class addsub_shifted_imm_neg<ValueType Ty>
1063    : Operand<Ty> {
1064  let EncoderMethod = "getAddSubImmOpValue";
1065  let ParserMatchClass = AddSubImmNegOperand;
1066  let MIOperandInfo = (ops i32imm, i32imm);
1067}
1068
1069def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1070def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1071def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1072def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1073
1074def gi_addsub_shifted_imm32 :
1075    GIComplexOperandMatcher<s32, "selectArithImmed">,
1076    GIComplexPatternEquiv<addsub_shifted_imm32>;
1077
1078def gi_addsub_shifted_imm64 :
1079    GIComplexOperandMatcher<s64, "selectArithImmed">,
1080    GIComplexPatternEquiv<addsub_shifted_imm64>;
1081
1082class neg_addsub_shifted_imm<ValueType Ty>
1083    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1084  let PrintMethod = "printAddSubImm";
1085  let EncoderMethod = "getAddSubImmOpValue";
1086  let ParserMatchClass = AddSubImmOperand;
1087  let MIOperandInfo = (ops i32imm, i32imm);
1088}
1089
1090def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1091def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1092
1093def gi_neg_addsub_shifted_imm32 :
1094    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1095    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1096
1097def gi_neg_addsub_shifted_imm64 :
1098    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1099    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1100
1101// An extend operand:
1102//  {5-3} - extend type
1103//  {2-0} - imm3
1104def arith_extend : Operand<i32> {
1105  let PrintMethod = "printArithExtend";
1106  let ParserMatchClass = ExtendOperand;
1107}
1108def arith_extend64 : Operand<i32> {
1109  let PrintMethod = "printArithExtend";
1110  let ParserMatchClass = ExtendOperand64;
1111}
1112
1113// 'extend' that's a lsl of a 64-bit register.
1114def arith_extendlsl64 : Operand<i32> {
1115  let PrintMethod = "printArithExtend";
1116  let ParserMatchClass = ExtendOperandLSL64;
1117}
1118
1119class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1120                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1121  let PrintMethod = "printExtendedRegister";
1122  let MIOperandInfo = (ops GPR32, arith_extend);
1123}
1124
1125class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1126                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1127  let PrintMethod = "printExtendedRegister";
1128  let MIOperandInfo = (ops GPR32, arith_extend64);
1129}
1130
1131def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1132def gi_arith_extended_reg32_i32 :
1133    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1134    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1135
1136def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1137def gi_arith_extended_reg32_i64 :
1138    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1139    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1140
1141def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1142def gi_arith_extended_reg32to64_i64 :
1143    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1144    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1145
1146// Floating-point immediate.
1147def fpimm16 : Operand<f16>,
1148              FPImmLeaf<f16, [{
1149      return AArch64_AM::getFP16Imm(Imm) != -1;
1150    }], SDNodeXForm<fpimm, [{
1151      APFloat InVal = N->getValueAPF();
1152      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1153      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1154    }]>> {
1155  let ParserMatchClass = FPImmOperand;
1156  let PrintMethod = "printFPImmOperand";
1157}
1158def fpimm32 : Operand<f32>,
1159              FPImmLeaf<f32, [{
1160      return AArch64_AM::getFP32Imm(Imm) != -1;
1161    }], SDNodeXForm<fpimm, [{
1162      APFloat InVal = N->getValueAPF();
1163      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1164      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1165    }]>> {
1166  let ParserMatchClass = FPImmOperand;
1167  let PrintMethod = "printFPImmOperand";
1168}
1169def fpimm64 : Operand<f64>,
1170              FPImmLeaf<f64, [{
1171      return AArch64_AM::getFP64Imm(Imm) != -1;
1172    }], SDNodeXForm<fpimm, [{
1173      APFloat InVal = N->getValueAPF();
1174      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1175      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1176    }]>> {
1177  let ParserMatchClass = FPImmOperand;
1178  let PrintMethod = "printFPImmOperand";
1179}
1180
1181def fpimm8 : Operand<i32> {
1182  let ParserMatchClass = FPImmOperand;
1183  let PrintMethod = "printFPImmOperand";
1184}
1185
1186def fpimm0 : FPImmLeaf<fAny, [{
1187  return Imm.isExactlyValue(+0.0);
1188}]>;
1189
1190// Vector lane operands
1191class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1192  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1193  let DiagnosticType = "Invalid" # Name;
1194  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1195  let RenderMethod = "addVectorIndexOperands";
1196}
1197
1198class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1199    : Operand<ty> {
1200  let ParserMatchClass = mc;
1201  let PrintMethod = "printVectorIndex";
1202}
1203
1204multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1205  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1206  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1207}
1208
1209def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1210def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1211def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1212def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1213def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1214
1215defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1216                                [{ return ((uint64_t)Imm) == 1; }]>;
1217defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1218                                [{ return ((uint64_t)Imm) < 16; }]>;
1219defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1220                                [{ return ((uint64_t)Imm) < 8; }]>;
1221defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1222                                [{ return ((uint64_t)Imm) < 4; }]>;
1223defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1224                                [{ return ((uint64_t)Imm) < 2; }]>;
1225
1226defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1227                                   [{ return ((uint64_t)Imm) == 1; }]>;
1228defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1229                                   [{ return ((uint64_t)Imm) < 16; }]>;
1230defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1231                                   [{ return ((uint64_t)Imm) < 8; }]>;
1232defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1233                                   [{ return ((uint64_t)Imm) < 4; }]>;
1234defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1235                                   [{ return ((uint64_t)Imm) < 2; }]>;
1236
1237def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1238def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1239def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1240def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1241def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1242
1243defm sve_elm_idx_extdup_b
1244  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1245                [{ return ((uint64_t)Imm) < 64; }]>;
1246defm sve_elm_idx_extdup_h
1247  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1248                [{ return ((uint64_t)Imm) < 32; }]>;
1249defm sve_elm_idx_extdup_s
1250  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1251                [{ return ((uint64_t)Imm) < 16; }]>;
1252defm sve_elm_idx_extdup_d
1253  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1254                [{ return ((uint64_t)Imm) < 8; }]>;
1255defm sve_elm_idx_extdup_q
1256  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1257                [{ return ((uint64_t)Imm) < 4; }]>;
1258
1259// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1260// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1261// are encoded as the eight bit value 'abcdefgh'.
1262def simdimmtype10 : Operand<i32>,
1263                    FPImmLeaf<f64, [{
1264      return AArch64_AM::isAdvSIMDModImmType10(
1265                 Imm.bitcastToAPInt().getZExtValue());
1266    }], SDNodeXForm<fpimm, [{
1267      APFloat InVal = N->getValueAPF();
1268      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1269                                                           .bitcastToAPInt()
1270                                                           .getZExtValue());
1271      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1272    }]>> {
1273  let ParserMatchClass = SIMDImmType10Operand;
1274  let PrintMethod = "printSIMDType10Operand";
1275}
1276
1277
1278//---
1279// System management
1280//---
1281
1282// Base encoding for system instruction operands.
1283let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1284class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1285                  list<dag> pattern = []>
1286    : I<oops, iops, asm, operands, "", pattern> {
1287  let Inst{31-22} = 0b1101010100;
1288  let Inst{21}    = L;
1289}
1290
1291// System instructions which do not have an Rt register.
1292class SimpleSystemI<bit L, dag iops, string asm, string operands,
1293                    list<dag> pattern = []>
1294    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1295  let Inst{4-0} = 0b11111;
1296}
1297
1298// System instructions which have an Rt register.
1299class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1300    : BaseSystemI<L, oops, iops, asm, operands>,
1301      Sched<[WriteSys]> {
1302  bits<5> Rt;
1303  let Inst{4-0} = Rt;
1304}
1305
1306// System instructions for transactional memory extension
1307class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1308                    string asm, string operands, list<dag> pattern>
1309    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1310      Sched<[WriteSys]> {
1311  let Inst{20-12} = 0b000110011;
1312  let Inst{11-8} = CRm;
1313  let Inst{7-5} = op2;
1314  let DecoderMethod = "";
1315
1316  let mayLoad = 1;
1317  let mayStore = 1;
1318}
1319
1320// System instructions for transactional memory - single input operand
1321class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1322    : TMBaseSystemI<0b1, CRm, 0b011,
1323                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1324  bits<5> Rt;
1325  let Inst{4-0} = Rt;
1326}
1327
1328// System instructions for transactional memory - no operand
1329class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1330    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1331  let Inst{4-0} = 0b11111;
1332}
1333
1334// System instructions for exit from transactions
1335class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1336    : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1337      Sched<[WriteSys]> {
1338  bits<16> imm;
1339  let Inst{31-24} = 0b11010100;
1340  let Inst{23-21} = op1;
1341  let Inst{20-5}  = imm;
1342  let Inst{4-0}   = 0b00000;
1343}
1344
1345// Hint instructions that take both a CRm and a 3-bit immediate.
1346// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1347// model patterns with sufficiently fine granularity
1348let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1349  class HintI<string mnemonic>
1350      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1351                      [(int_aarch64_hint imm0_127:$imm)]>,
1352        Sched<[WriteHint]> {
1353    bits <7> imm;
1354    let Inst{20-12} = 0b000110010;
1355    let Inst{11-5} = imm;
1356  }
1357
1358// System instructions taking a single literal operand which encodes into
1359// CRm. op2 differentiates the opcodes.
1360def BarrierAsmOperand : AsmOperandClass {
1361  let Name = "Barrier";
1362  let ParserMethod = "tryParseBarrierOperand";
1363}
1364def barrier_op : Operand<i32> {
1365  let PrintMethod = "printBarrierOption";
1366  let ParserMatchClass = BarrierAsmOperand;
1367}
1368class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1369                 list<dag> pattern = []>
1370    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1371      Sched<[WriteBarrier]> {
1372  bits<4> CRm;
1373  let Inst{20-12} = 0b000110011;
1374  let Inst{11-8} = CRm;
1375  let Inst{7-5} = opc;
1376}
1377
1378class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1379    : SimpleSystemI<0, (ins), asm, "", pattern>,
1380      Sched<[]> {
1381  bits<4> CRm;
1382  let CRm = 0b0011;
1383  let Inst{31-12} = 0b11010101000000110010;
1384  let Inst{11-8} = CRm;
1385  let Inst{7-5} = op2;
1386  let Inst{4-0} = 0b11111;
1387}
1388
1389// MRS/MSR system instructions. These have different operand classes because
1390// a different subset of registers can be accessed through each instruction.
1391def MRSSystemRegisterOperand : AsmOperandClass {
1392  let Name = "MRSSystemRegister";
1393  let ParserMethod = "tryParseSysReg";
1394  let DiagnosticType = "MRS";
1395}
1396// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1397def mrs_sysreg_op : Operand<i32> {
1398  let ParserMatchClass = MRSSystemRegisterOperand;
1399  let DecoderMethod = "DecodeMRSSystemRegister";
1400  let PrintMethod = "printMRSSystemRegister";
1401}
1402
1403def MSRSystemRegisterOperand : AsmOperandClass {
1404  let Name = "MSRSystemRegister";
1405  let ParserMethod = "tryParseSysReg";
1406  let DiagnosticType = "MSR";
1407}
1408def msr_sysreg_op : Operand<i32> {
1409  let ParserMatchClass = MSRSystemRegisterOperand;
1410  let DecoderMethod = "DecodeMSRSystemRegister";
1411  let PrintMethod = "printMSRSystemRegister";
1412}
1413
1414def PSBHintOperand : AsmOperandClass {
1415  let Name = "PSBHint";
1416  let ParserMethod = "tryParsePSBHint";
1417}
1418def psbhint_op : Operand<i32> {
1419  let ParserMatchClass = PSBHintOperand;
1420  let PrintMethod = "printPSBHintOp";
1421  let MCOperandPredicate = [{
1422    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1423    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1424    if (!MCOp.isImm())
1425      return false;
1426    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1427  }];
1428}
1429
1430def BTIHintOperand : AsmOperandClass {
1431  let Name = "BTIHint";
1432  let ParserMethod = "tryParseBTIHint";
1433}
1434def btihint_op : Operand<i32> {
1435  let ParserMatchClass = BTIHintOperand;
1436  let PrintMethod = "printBTIHintOp";
1437  let MCOperandPredicate = [{
1438    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1439    if (!MCOp.isImm())
1440      return false;
1441    return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1442  }];
1443}
1444
1445class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1446                       "mrs", "\t$Rt, $systemreg"> {
1447  bits<16> systemreg;
1448  let Inst{20-5} = systemreg;
1449}
1450
1451// FIXME: Some of these def NZCV, others don't. Best way to model that?
1452// Explicitly modeling each of the system register as a register class
1453// would do it, but feels like overkill at this point.
1454class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1455                       "msr", "\t$systemreg, $Rt"> {
1456  bits<16> systemreg;
1457  let Inst{20-5} = systemreg;
1458}
1459
1460def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1461  let Name = "SystemPStateFieldWithImm0_15";
1462  let ParserMethod = "tryParseSysReg";
1463}
1464def pstatefield4_op : Operand<i32> {
1465  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1466  let PrintMethod = "printSystemPStateField";
1467}
1468
1469// Instructions to modify PSTATE, no input reg
1470let Defs = [NZCV] in
1471class PstateWriteSimple<dag iops, string asm, string operands>
1472  : SimpleSystemI<0, iops, asm, operands> {
1473
1474  let Inst{20-19} = 0b00;
1475  let Inst{15-12} = 0b0100;
1476}
1477
1478class MSRpstateImm0_15
1479  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1480                  "\t$pstatefield, $imm">,
1481    Sched<[WriteSys]> {
1482
1483  bits<6> pstatefield;
1484  bits<4> imm;
1485  let Inst{18-16} = pstatefield{5-3};
1486  let Inst{11-8} = imm;
1487  let Inst{7-5} = pstatefield{2-0};
1488
1489  let DecoderMethod = "DecodeSystemPStateInstruction";
1490  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1491  // Fail the decoder should attempt to decode the instruction as MSRI.
1492  let hasCompleteDecoder = 0;
1493}
1494
1495def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1496  let Name = "SystemPStateFieldWithImm0_1";
1497  let ParserMethod = "tryParseSysReg";
1498}
1499def pstatefield1_op : Operand<i32> {
1500  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1501  let PrintMethod = "printSystemPStateField";
1502}
1503
1504class MSRpstateImm0_1
1505  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1506                 "\t$pstatefield, $imm">,
1507    Sched<[WriteSys]> {
1508
1509  bits<6> pstatefield;
1510  bit imm;
1511  let Inst{18-16} = pstatefield{5-3};
1512  let Inst{11-9} = 0b000;
1513  let Inst{8} = imm;
1514  let Inst{7-5} = pstatefield{2-0};
1515
1516  let DecoderMethod = "DecodeSystemPStateInstruction";
1517  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1518  // Fail the decoder should attempt to decode the instruction as MSRI.
1519  let hasCompleteDecoder = 0;
1520}
1521
1522// SYS and SYSL generic system instructions.
1523def SysCRAsmOperand : AsmOperandClass {
1524  let Name = "SysCR";
1525  let ParserMethod = "tryParseSysCROperand";
1526}
1527
1528def sys_cr_op : Operand<i32> {
1529  let PrintMethod = "printSysCROperand";
1530  let ParserMatchClass = SysCRAsmOperand;
1531}
1532
1533class SystemXtI<bit L, string asm>
1534  : RtSystemI<L, (outs),
1535       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1536       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1537  bits<3> op1;
1538  bits<4> Cn;
1539  bits<4> Cm;
1540  bits<3> op2;
1541  let Inst{20-19} = 0b01;
1542  let Inst{18-16} = op1;
1543  let Inst{15-12} = Cn;
1544  let Inst{11-8}  = Cm;
1545  let Inst{7-5}   = op2;
1546}
1547
1548class SystemLXtI<bit L, string asm>
1549  : RtSystemI<L, (outs),
1550       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1551       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1552  bits<3> op1;
1553  bits<4> Cn;
1554  bits<4> Cm;
1555  bits<3> op2;
1556  let Inst{20-19} = 0b01;
1557  let Inst{18-16} = op1;
1558  let Inst{15-12} = Cn;
1559  let Inst{11-8}  = Cm;
1560  let Inst{7-5}   = op2;
1561}
1562
1563
1564// Branch (register) instructions:
1565//
1566//  case opc of
1567//    0001 blr
1568//    0000 br
1569//    0101 dret
1570//    0100 eret
1571//    0010 ret
1572//    otherwise UNDEFINED
1573class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1574                    string operands, list<dag> pattern>
1575    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1576  let Inst{31-25} = 0b1101011;
1577  let Inst{24-21} = opc;
1578  let Inst{20-16} = 0b11111;
1579  let Inst{15-10} = 0b000000;
1580  let Inst{4-0}   = 0b00000;
1581}
1582
1583class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1584    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1585  bits<5> Rn;
1586  let Inst{9-5} = Rn;
1587}
1588
1589let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1590class SpecialReturn<bits<4> opc, string asm>
1591    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1592  let Inst{9-5} = 0b11111;
1593}
1594
1595let mayLoad = 1 in
1596class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1597  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1598  Sched<[]> {
1599  bits<5> Rn;
1600  bits<5> Rt;
1601  let Inst{31-30} = sz;
1602  let Inst{29-10} = 0b11100010111111110000;
1603  let Inst{9-5} = Rn;
1604  let Inst{4-0} = Rt;
1605}
1606
1607class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1608               list<dag> pattern>
1609  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1610  let isAuthenticated = 1;
1611  let Inst{31-25} = 0b1101011;
1612  let Inst{20-11} = 0b1111100001;
1613  let Inst{10} = M;
1614  let Inst{4-0} = 0b11111;
1615}
1616
1617class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1618  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1619  bits<5> Rn;
1620  bits<5> Rm;
1621  let Inst{24-22} = 0b100;
1622  let Inst{21} = op;
1623  let Inst{9-5} = Rn;
1624  let Inst{4-0} = Rm;
1625}
1626
1627class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1628  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1629  bits<5> Rn;
1630  let Inst{24} = 0;
1631  let Inst{23-21} = opc;
1632  let Inst{9-5} = Rn;
1633}
1634
1635let Uses = [LR,SP] in
1636class AuthReturn<bits<3> op, bits<1> M, string asm>
1637  : AuthBase<M, (outs), (ins), asm, "", []> {
1638  let Inst{24} = 0;
1639  let Inst{23-21} = op;
1640  let Inst{9-0} = 0b1111111111;
1641}
1642
1643let mayLoad = 1 in
1644class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1645                   string operands, string cstr, Operand opr>
1646  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1647  bits<10> offset;
1648  bits<5> Rn;
1649  bits<5> Rt;
1650  let isAuthenticated = 1;
1651  let Inst{31-24} = 0b11111000;
1652  let Inst{23} = M;
1653  let Inst{22} = offset{9};
1654  let Inst{21} = 1;
1655  let Inst{20-12} = offset{8-0};
1656  let Inst{11} = W;
1657  let Inst{10} = 1;
1658  let Inst{9-5} = Rn;
1659  let Inst{4-0} = Rt;
1660
1661  let DecoderMethod = "DecodeAuthLoadInstruction";
1662}
1663
1664multiclass AuthLoad<bit M, string asm, Operand opr> {
1665  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1666                               (ins GPR64sp:$Rn, opr:$offset),
1667                               asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1668  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1669                               (ins GPR64sp:$Rn, opr:$offset),
1670                               asm, "\t$Rt, [$Rn, $offset]!",
1671                               "$Rn = $wback,@earlyclobber $wback", opr>;
1672
1673  def : InstAlias<asm # "\t$Rt, [$Rn]",
1674                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1675
1676  def : InstAlias<asm # "\t$Rt, [$wback]!",
1677                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1678}
1679
1680//---
1681// Conditional branch instruction.
1682//---
1683
1684// Condition code.
1685// 4-bit immediate. Pretty-printed as <cc>
1686def ccode : Operand<i32> {
1687  let PrintMethod = "printCondCode";
1688  let ParserMatchClass = CondCode;
1689}
1690def inv_ccode : Operand<i32> {
1691  // AL and NV are invalid in the aliases which use inv_ccode
1692  let PrintMethod = "printInverseCondCode";
1693  let ParserMatchClass = CondCode;
1694  let MCOperandPredicate = [{
1695    return MCOp.isImm() &&
1696           MCOp.getImm() != AArch64CC::AL &&
1697           MCOp.getImm() != AArch64CC::NV;
1698  }];
1699}
1700
1701// Conditional branch target. 19-bit immediate. The low two bits of the target
1702// offset are implied zero and so are not part of the immediate.
1703def am_brcond : Operand<OtherVT> {
1704  let EncoderMethod = "getCondBranchTargetOpValue";
1705  let DecoderMethod = "DecodePCRelLabel19";
1706  let PrintMethod = "printAlignedLabel";
1707  let ParserMatchClass = PCRelLabel19Operand;
1708  let OperandType = "OPERAND_PCREL";
1709}
1710
1711class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1712                     "b", ".$cond\t$target", "",
1713                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1714                   Sched<[WriteBr]> {
1715  let isBranch = 1;
1716  let isTerminator = 1;
1717  let Uses = [NZCV];
1718
1719  bits<4> cond;
1720  bits<19> target;
1721  let Inst{31-24} = 0b01010100;
1722  let Inst{23-5} = target;
1723  let Inst{4} = 0;
1724  let Inst{3-0} = cond;
1725}
1726
1727//---
1728// Compare-and-branch instructions.
1729//---
1730class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1731    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1732         asm, "\t$Rt, $target", "",
1733         [(node regtype:$Rt, bb:$target)]>,
1734      Sched<[WriteBr]> {
1735  let isBranch = 1;
1736  let isTerminator = 1;
1737
1738  bits<5> Rt;
1739  bits<19> target;
1740  let Inst{30-25} = 0b011010;
1741  let Inst{24}    = op;
1742  let Inst{23-5}  = target;
1743  let Inst{4-0}   = Rt;
1744}
1745
1746multiclass CmpBranch<bit op, string asm, SDNode node> {
1747  def W : BaseCmpBranch<GPR32, op, asm, node> {
1748    let Inst{31} = 0;
1749  }
1750  def X : BaseCmpBranch<GPR64, op, asm, node> {
1751    let Inst{31} = 1;
1752  }
1753}
1754
1755//---
1756// Test-bit-and-branch instructions.
1757//---
1758// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1759// the target offset are implied zero and so are not part of the immediate.
1760def am_tbrcond : Operand<OtherVT> {
1761  let EncoderMethod = "getTestBranchTargetOpValue";
1762  let PrintMethod = "printAlignedLabel";
1763  let ParserMatchClass = BranchTarget14Operand;
1764  let OperandType = "OPERAND_PCREL";
1765}
1766
1767// AsmOperand classes to emit (or not) special diagnostics
1768def TBZImm0_31Operand : AsmOperandClass {
1769  let Name = "TBZImm0_31";
1770  let PredicateMethod = "isImmInRange<0,31>";
1771  let RenderMethod = "addImmOperands";
1772}
1773def TBZImm32_63Operand : AsmOperandClass {
1774  let Name = "Imm32_63";
1775  let PredicateMethod = "isImmInRange<32,63>";
1776  let DiagnosticType = "InvalidImm0_63";
1777  let RenderMethod = "addImmOperands";
1778}
1779
1780class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1781  return (((uint32_t)Imm) < 32);
1782}]> {
1783  let ParserMatchClass = matcher;
1784}
1785
1786def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1787def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1788
1789def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1790  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1791}]> {
1792  let ParserMatchClass = TBZImm32_63Operand;
1793}
1794
1795class BaseTestBranch<RegisterClass regtype, Operand immtype,
1796                     bit op, string asm, SDNode node>
1797    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1798       asm, "\t$Rt, $bit_off, $target", "",
1799       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1800      Sched<[WriteBr]> {
1801  let isBranch = 1;
1802  let isTerminator = 1;
1803
1804  bits<5> Rt;
1805  bits<6> bit_off;
1806  bits<14> target;
1807
1808  let Inst{30-25} = 0b011011;
1809  let Inst{24}    = op;
1810  let Inst{23-19} = bit_off{4-0};
1811  let Inst{18-5}  = target;
1812  let Inst{4-0}   = Rt;
1813
1814  let DecoderMethod = "DecodeTestAndBranch";
1815}
1816
1817multiclass TestBranch<bit op, string asm, SDNode node> {
1818  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1819    let Inst{31} = 0;
1820  }
1821
1822  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1823    let Inst{31} = 1;
1824  }
1825
1826  // Alias X-reg with 0-31 imm to W-Reg.
1827  def : InstAlias<asm # "\t$Rd, $imm, $target",
1828                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1829                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1830  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1831            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1832            tbz_imm0_31_diag:$imm, bb:$target)>;
1833}
1834
1835//---
1836// Unconditional branch (immediate) instructions.
1837//---
1838def am_b_target : Operand<OtherVT> {
1839  let EncoderMethod = "getBranchTargetOpValue";
1840  let PrintMethod = "printAlignedLabel";
1841  let ParserMatchClass = BranchTarget26Operand;
1842  let OperandType = "OPERAND_PCREL";
1843}
1844def am_bl_target : Operand<i64> {
1845  let EncoderMethod = "getBranchTargetOpValue";
1846  let PrintMethod = "printAlignedLabel";
1847  let ParserMatchClass = BranchTarget26Operand;
1848  let OperandType = "OPERAND_PCREL";
1849}
1850
1851class BImm<bit op, dag iops, string asm, list<dag> pattern>
1852    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1853  bits<26> addr;
1854  let Inst{31}    = op;
1855  let Inst{30-26} = 0b00101;
1856  let Inst{25-0}  = addr;
1857
1858  let DecoderMethod = "DecodeUnconditionalBranch";
1859}
1860
1861class BranchImm<bit op, string asm, list<dag> pattern>
1862    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1863class CallImm<bit op, string asm, list<dag> pattern>
1864    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1865
1866//---
1867// Basic one-operand data processing instructions.
1868//---
1869
1870let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1871class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1872                         SDPatternOperator node>
1873  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1874      [(set regtype:$Rd, (node regtype:$Rn))]>,
1875    Sched<[WriteI, ReadI]> {
1876  bits<5> Rd;
1877  bits<5> Rn;
1878
1879  let Inst{30-13} = 0b101101011000000000;
1880  let Inst{12-10} = opc;
1881  let Inst{9-5}   = Rn;
1882  let Inst{4-0}   = Rd;
1883}
1884
1885let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1886multiclass OneOperandData<bits<3> opc, string asm,
1887                          SDPatternOperator node = null_frag> {
1888  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1889    let Inst{31} = 0;
1890  }
1891
1892  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1893    let Inst{31} = 1;
1894  }
1895}
1896
1897class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1898    : BaseOneOperandData<opc, GPR32, asm, node> {
1899  let Inst{31} = 0;
1900}
1901
1902class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1903    : BaseOneOperandData<opc, GPR64, asm, node> {
1904  let Inst{31} = 1;
1905}
1906
1907class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1908  : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1909      []>,
1910    Sched<[WriteI, ReadI]> {
1911  bits<5> Rd;
1912  bits<5> Rn;
1913  let Inst{31-15} = 0b11011010110000010;
1914  let Inst{14-12} = opcode_prefix;
1915  let Inst{11-10} = opcode;
1916  let Inst{9-5} = Rn;
1917  let Inst{4-0} = Rd;
1918}
1919
1920class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1921  : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1922  bits<5> Rd;
1923  let Inst{31-15} = 0b11011010110000010;
1924  let Inst{14-12} = opcode_prefix;
1925  let Inst{11-10} = opcode;
1926  let Inst{9-5} = 0b11111;
1927  let Inst{4-0} = Rd;
1928}
1929
1930class SignAuthTwoOperand<bits<4> opc, string asm,
1931                         SDPatternOperator OpNode>
1932  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1933      asm, "\t$Rd, $Rn, $Rm", "",
1934      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1935    Sched<[WriteI, ReadI, ReadI]> {
1936  bits<5> Rd;
1937  bits<5> Rn;
1938  bits<5> Rm;
1939  let Inst{31-21} = 0b10011010110;
1940  let Inst{20-16} = Rm;
1941  let Inst{15-14} = 0b00;
1942  let Inst{13-10} = opc;
1943  let Inst{9-5}   = Rn;
1944  let Inst{4-0}   = Rd;
1945}
1946
1947class ClearAuth<bits<1> data, string asm>
1948  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
1949  bits<5> Rd;
1950  let Inst{31-11} = 0b110110101100000101000;
1951  let Inst{10} = data;
1952  let Inst{9-5} = 0b11111;
1953  let Inst{4-0} = Rd;
1954}
1955
1956// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1957class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1958    : I<(outs), iops, asm, ops, "", []>,
1959      Sched<[WriteI, ReadI, ReadI]> {
1960  let Uses = [NZCV];
1961  let Defs = [NZCV];
1962  bits<5> Rn;
1963  let Inst{31}    = sf;
1964  let Inst{30-15} = 0b0111010000000000;
1965  let Inst{14}    = sz;
1966  let Inst{13-10} = 0b0010;
1967  let Inst{9-5}   = Rn;
1968  let Inst{4-0}   = 0b01101;
1969}
1970
1971class FlagRotate<dag iops, string asm, string ops>
1972    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1973  bits<6> imm;
1974  bits<4> mask;
1975  let Inst{20-15} = imm;
1976  let Inst{13-10} = 0b0001;
1977  let Inst{4}     = 0b0;
1978  let Inst{3-0}   = mask;
1979}
1980
1981//---
1982// Basic two-operand data processing instructions.
1983//---
1984class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1985                          list<dag> pattern>
1986    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1987        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1988      Sched<[WriteI, ReadI, ReadI]> {
1989  let Uses = [NZCV];
1990  bits<5> Rd;
1991  bits<5> Rn;
1992  bits<5> Rm;
1993  let Inst{30}    = isSub;
1994  let Inst{28-21} = 0b11010000;
1995  let Inst{20-16} = Rm;
1996  let Inst{15-10} = 0;
1997  let Inst{9-5}   = Rn;
1998  let Inst{4-0}   = Rd;
1999}
2000
2001class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2002                      SDNode OpNode>
2003    : BaseBaseAddSubCarry<isSub, regtype, asm,
2004        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2005
2006class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2007                              SDNode OpNode>
2008    : BaseBaseAddSubCarry<isSub, regtype, asm,
2009        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2010         (implicit NZCV)]> {
2011  let Defs = [NZCV];
2012}
2013
2014multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2015                       SDNode OpNode, SDNode OpNode_setflags> {
2016  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2017    let Inst{31} = 0;
2018    let Inst{29} = 0;
2019  }
2020  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2021    let Inst{31} = 1;
2022    let Inst{29} = 0;
2023  }
2024
2025  // Sets flags.
2026  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2027                                    OpNode_setflags> {
2028    let Inst{31} = 0;
2029    let Inst{29} = 1;
2030  }
2031  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2032                                    OpNode_setflags> {
2033    let Inst{31} = 1;
2034    let Inst{29} = 1;
2035  }
2036}
2037
2038class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2039                     SDPatternOperator OpNode,
2040                     RegisterClass in1regtype = regtype,
2041                     RegisterClass in2regtype = regtype>
2042  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2043      asm, "\t$Rd, $Rn, $Rm", "",
2044      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2045  bits<5> Rd;
2046  bits<5> Rn;
2047  bits<5> Rm;
2048  let Inst{30-21} = 0b0011010110;
2049  let Inst{20-16} = Rm;
2050  let Inst{15-14} = 0b00;
2051  let Inst{13-10} = opc;
2052  let Inst{9-5}   = Rn;
2053  let Inst{4-0}   = Rd;
2054}
2055
2056class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2057              SDPatternOperator OpNode>
2058    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2059  let Inst{10}    = isSigned;
2060}
2061
2062multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2063  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2064           Sched<[WriteID32, ReadID, ReadID]> {
2065    let Inst{31} = 0;
2066  }
2067  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2068           Sched<[WriteID64, ReadID, ReadID]> {
2069    let Inst{31} = 1;
2070  }
2071}
2072
2073class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2074                SDPatternOperator OpNode = null_frag>
2075  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2076    Sched<[WriteIS, ReadI]> {
2077  let Inst{11-10} = shift_type;
2078}
2079
2080multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2081  def Wr : BaseShift<shift_type, GPR32, asm> {
2082    let Inst{31} = 0;
2083  }
2084
2085  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2086    let Inst{31} = 1;
2087  }
2088
2089  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2090            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2091                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2092
2093  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2094            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2095
2096  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2097            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2098
2099  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2100            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2101
2102  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2103            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2104                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2105
2106  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2107            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2108                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2109}
2110
2111class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2112    : InstAlias<asm#"\t$dst, $src1, $src2",
2113                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2114
2115class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2116                       RegisterClass addtype, string asm,
2117                       list<dag> pattern>
2118  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2119      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2120  bits<5> Rd;
2121  bits<5> Rn;
2122  bits<5> Rm;
2123  bits<5> Ra;
2124  let Inst{30-24} = 0b0011011;
2125  let Inst{23-21} = opc;
2126  let Inst{20-16} = Rm;
2127  let Inst{15}    = isSub;
2128  let Inst{14-10} = Ra;
2129  let Inst{9-5}   = Rn;
2130  let Inst{4-0}   = Rd;
2131}
2132
2133multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
2134  // MADD/MSUB generation is decided by MachineCombiner.cpp
2135  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2136      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2137      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2138    let Inst{31} = 0;
2139  }
2140
2141  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2142      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2143      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2144    let Inst{31} = 1;
2145  }
2146}
2147
2148class WideMulAccum<bit isSub, bits<3> opc, string asm,
2149                   SDNode AccNode, SDNode ExtNode>
2150  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2151    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2152                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2153    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2154  let Inst{31} = 1;
2155}
2156
2157class MulHi<bits<3> opc, string asm, SDNode OpNode>
2158  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2159      asm, "\t$Rd, $Rn, $Rm", "",
2160      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2161    Sched<[WriteIM64, ReadIM, ReadIM]> {
2162  bits<5> Rd;
2163  bits<5> Rn;
2164  bits<5> Rm;
2165  let Inst{31-24} = 0b10011011;
2166  let Inst{23-21} = opc;
2167  let Inst{20-16} = Rm;
2168  let Inst{15}    = 0;
2169  let Inst{9-5}   = Rn;
2170  let Inst{4-0}   = Rd;
2171
2172  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2173  // (i.e. all bits 1) but is ignored by the processor.
2174  let PostEncoderMethod = "fixMulHigh";
2175}
2176
2177class MulAccumWAlias<string asm, Instruction inst>
2178    : InstAlias<asm#"\t$dst, $src1, $src2",
2179                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2180class MulAccumXAlias<string asm, Instruction inst>
2181    : InstAlias<asm#"\t$dst, $src1, $src2",
2182                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2183class WideMulAccumAlias<string asm, Instruction inst>
2184    : InstAlias<asm#"\t$dst, $src1, $src2",
2185                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2186
2187class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2188              SDPatternOperator OpNode, string asm>
2189  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2190      asm, "\t$Rd, $Rn, $Rm", "",
2191      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2192    Sched<[WriteISReg, ReadI, ReadISReg]> {
2193  bits<5> Rd;
2194  bits<5> Rn;
2195  bits<5> Rm;
2196
2197  let Inst{31} = sf;
2198  let Inst{30-21} = 0b0011010110;
2199  let Inst{20-16} = Rm;
2200  let Inst{15-13} = 0b010;
2201  let Inst{12} = C;
2202  let Inst{11-10} = sz;
2203  let Inst{9-5} = Rn;
2204  let Inst{4-0} = Rd;
2205  let Predicates = [HasCRC];
2206}
2207
2208//---
2209// Address generation.
2210//---
2211
2212class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2213    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2214        pattern>,
2215      Sched<[WriteI]> {
2216  bits<5>  Xd;
2217  bits<21> label;
2218  let Inst{31}    = page;
2219  let Inst{30-29} = label{1-0};
2220  let Inst{28-24} = 0b10000;
2221  let Inst{23-5}  = label{20-2};
2222  let Inst{4-0}   = Xd;
2223
2224  let DecoderMethod = "DecodeAdrInstruction";
2225}
2226
2227//---
2228// Move immediate.
2229//---
2230
2231def movimm32_imm : Operand<i32> {
2232  let ParserMatchClass = AsmImmRange<0, 65535>;
2233  let EncoderMethod = "getMoveWideImmOpValue";
2234  let PrintMethod = "printImm";
2235}
2236def movimm32_shift : Operand<i32> {
2237  let PrintMethod = "printShifter";
2238  let ParserMatchClass = MovImm32ShifterOperand;
2239}
2240def movimm64_shift : Operand<i32> {
2241  let PrintMethod = "printShifter";
2242  let ParserMatchClass = MovImm64ShifterOperand;
2243}
2244
2245let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2246class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2247                        string asm>
2248  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2249       asm, "\t$Rd, $imm$shift", "", []>,
2250    Sched<[WriteImm]> {
2251  bits<5> Rd;
2252  bits<16> imm;
2253  bits<6> shift;
2254  let Inst{30-29} = opc;
2255  let Inst{28-23} = 0b100101;
2256  let Inst{22-21} = shift{5-4};
2257  let Inst{20-5}  = imm;
2258  let Inst{4-0}   = Rd;
2259
2260  let DecoderMethod = "DecodeMoveImmInstruction";
2261}
2262
2263multiclass MoveImmediate<bits<2> opc, string asm> {
2264  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2265    let Inst{31} = 0;
2266  }
2267
2268  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2269    let Inst{31} = 1;
2270  }
2271}
2272
2273let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2274class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2275                          string asm>
2276  : I<(outs regtype:$Rd),
2277      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2278       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2279    Sched<[WriteI, ReadI]> {
2280  bits<5> Rd;
2281  bits<16> imm;
2282  bits<6> shift;
2283  let Inst{30-29} = opc;
2284  let Inst{28-23} = 0b100101;
2285  let Inst{22-21} = shift{5-4};
2286  let Inst{20-5}  = imm;
2287  let Inst{4-0}   = Rd;
2288
2289  let DecoderMethod = "DecodeMoveImmInstruction";
2290}
2291
2292multiclass InsertImmediate<bits<2> opc, string asm> {
2293  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2294    let Inst{31} = 0;
2295  }
2296
2297  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2298    let Inst{31} = 1;
2299  }
2300}
2301
2302//---
2303// Add/Subtract
2304//---
2305
2306class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2307                    string asm_inst, string asm_ops,
2308                    dag inputs, dag pattern>
2309    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2310      Sched<[WriteI, ReadI]> {
2311  bits<5>  Rd;
2312  bits<5>  Rn;
2313  let Inst{30}    = isSub;
2314  let Inst{29}    = setFlags;
2315  let Inst{28-24} = 0b10001;
2316  let Inst{9-5}   = Rn;
2317  let Inst{4-0}   = Rd;
2318}
2319
2320class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2321                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2322                     string asm_inst, SDPatternOperator OpNode>
2323    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2324                    (ins srcRegtype:$Rn, immtype:$imm),
2325                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2326  bits<14> imm;
2327  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2328  let Inst{21-10} = imm{11-0};
2329  let DecoderMethod = "DecodeAddSubImmShift";
2330}
2331
2332class BaseAddSubRegPseudo<RegisterClass regtype,
2333                          SDPatternOperator OpNode>
2334    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2335             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2336      Sched<[WriteI, ReadI, ReadI]>;
2337
2338class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2339                     arith_shifted_reg shifted_regtype, string asm,
2340                     SDPatternOperator OpNode>
2341    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2342        asm, "\t$Rd, $Rn, $Rm", "",
2343        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2344      Sched<[WriteISReg, ReadI, ReadISReg]> {
2345  // The operands are in order to match the 'addr' MI operands, so we
2346  // don't need an encoder method and by-name matching. Just use the default
2347  // in-order handling. Since we're using by-order, make sure the names
2348  // do not match.
2349  bits<5> dst;
2350  bits<5> src1;
2351  bits<5> src2;
2352  bits<8> shift;
2353  let Inst{30}    = isSub;
2354  let Inst{29}    = setFlags;
2355  let Inst{28-24} = 0b01011;
2356  let Inst{23-22} = shift{7-6};
2357  let Inst{21}    = 0;
2358  let Inst{20-16} = src2;
2359  let Inst{15-10} = shift{5-0};
2360  let Inst{9-5}   = src1;
2361  let Inst{4-0}   = dst;
2362
2363  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2364}
2365
2366class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2367                     RegisterClass src1Regtype, Operand src2Regtype,
2368                     string asm, SDPatternOperator OpNode>
2369    : I<(outs dstRegtype:$R1),
2370        (ins src1Regtype:$R2, src2Regtype:$R3),
2371        asm, "\t$R1, $R2, $R3", "",
2372        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2373      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2374  bits<5> Rd;
2375  bits<5> Rn;
2376  bits<5> Rm;
2377  bits<6> ext;
2378  let Inst{30}    = isSub;
2379  let Inst{29}    = setFlags;
2380  let Inst{28-24} = 0b01011;
2381  let Inst{23-21} = 0b001;
2382  let Inst{20-16} = Rm;
2383  let Inst{15-13} = ext{5-3};
2384  let Inst{12-10} = ext{2-0};
2385  let Inst{9-5}   = Rn;
2386  let Inst{4-0}   = Rd;
2387
2388  let DecoderMethod = "DecodeAddSubERegInstruction";
2389}
2390
2391let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2392class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2393                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2394                       Operand ext_op, string asm>
2395    : I<(outs dstRegtype:$Rd),
2396        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2397        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2398      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2399  bits<5> Rd;
2400  bits<5> Rn;
2401  bits<5> Rm;
2402  bits<6> ext;
2403  let Inst{30}    = isSub;
2404  let Inst{29}    = setFlags;
2405  let Inst{28-24} = 0b01011;
2406  let Inst{23-21} = 0b001;
2407  let Inst{20-16} = Rm;
2408  let Inst{15}    = ext{5};
2409  let Inst{12-10} = ext{2-0};
2410  let Inst{9-5}   = Rn;
2411  let Inst{4-0}   = Rd;
2412
2413  let DecoderMethod = "DecodeAddSubERegInstruction";
2414}
2415
2416// Aliases for register+register add/subtract.
2417class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2418                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2419                     int shiftExt>
2420    : InstAlias<asm#"\t$dst, $src1, $src2",
2421                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2422                      shiftExt)>;
2423
2424multiclass AddSub<bit isSub, string mnemonic, string alias,
2425                  SDPatternOperator OpNode = null_frag> {
2426  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2427  // Add/Subtract immediate
2428  // Increase the weight of the immediate variant to try to match it before
2429  // the extended register variant.
2430  // We used to match the register variant before the immediate when the
2431  // register argument could be implicitly zero-extended.
2432  let AddedComplexity = 6 in
2433  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2434                           mnemonic, OpNode> {
2435    let Inst{31} = 0;
2436  }
2437  let AddedComplexity = 6 in
2438  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2439                           mnemonic, OpNode> {
2440    let Inst{31} = 1;
2441  }
2442
2443  // Add/Subtract register - Only used for CodeGen
2444  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2445  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2446
2447  // Add/Subtract shifted register
2448  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2449                           OpNode> {
2450    let Inst{31} = 0;
2451  }
2452  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2453                           OpNode> {
2454    let Inst{31} = 1;
2455  }
2456  }
2457
2458  // Add/Subtract extended register
2459  let AddedComplexity = 1, hasSideEffects = 0 in {
2460  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2461                           arith_extended_reg32_i32, mnemonic, OpNode> {
2462    let Inst{31} = 0;
2463  }
2464  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2465                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2466    let Inst{31} = 1;
2467  }
2468  }
2469
2470  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2471                               arith_extendlsl64, mnemonic> {
2472    // UXTX and SXTX only.
2473    let Inst{14-13} = 0b11;
2474    let Inst{31} = 1;
2475  }
2476
2477  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2478  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2479                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2480                      addsub_shifted_imm32_neg:$imm), 0>;
2481  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2482                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2483                       addsub_shifted_imm64_neg:$imm), 0>;
2484
2485  // Register/register aliases with no shift when SP is not used.
2486  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2487                       GPR32, GPR32, GPR32, 0>;
2488  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2489                       GPR64, GPR64, GPR64, 0>;
2490
2491  // Register/register aliases with no shift when either the destination or
2492  // first source register is SP.
2493  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2494                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2495  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2496                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2497  def : AddSubRegAlias<mnemonic,
2498                       !cast<Instruction>(NAME#"Xrx64"),
2499                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2500  def : AddSubRegAlias<mnemonic,
2501                       !cast<Instruction>(NAME#"Xrx64"),
2502                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2503}
2504
2505multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2506                   string alias, string cmpAlias> {
2507  let isCompare = 1, Defs = [NZCV] in {
2508  // Add/Subtract immediate
2509  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2510                           mnemonic, OpNode> {
2511    let Inst{31} = 0;
2512  }
2513  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2514                           mnemonic, OpNode> {
2515    let Inst{31} = 1;
2516  }
2517
2518  // Add/Subtract register
2519  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2520  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2521
2522  // Add/Subtract shifted register
2523  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2524                           OpNode> {
2525    let Inst{31} = 0;
2526  }
2527  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2528                           OpNode> {
2529    let Inst{31} = 1;
2530  }
2531
2532  // Add/Subtract extended register
2533  let AddedComplexity = 1 in {
2534  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2535                           arith_extended_reg32_i32, mnemonic, OpNode> {
2536    let Inst{31} = 0;
2537  }
2538  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2539                           arith_extended_reg32_i64, mnemonic, OpNode> {
2540    let Inst{31} = 1;
2541  }
2542  }
2543
2544  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2545                               arith_extendlsl64, mnemonic> {
2546    // UXTX and SXTX only.
2547    let Inst{14-13} = 0b11;
2548    let Inst{31} = 1;
2549  }
2550  } // Defs = [NZCV]
2551
2552  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2553  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2554                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2555                      addsub_shifted_imm32_neg:$imm), 0>;
2556  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2557                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2558                       addsub_shifted_imm64_neg:$imm), 0>;
2559
2560  // Compare aliases
2561  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2562                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2563  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2564                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2565  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2566                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2567  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2568                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2569  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2570                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2571  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2572                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2573  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2574                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2575
2576  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2577  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2578                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2579  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2580                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2581
2582  // Compare shorthands
2583  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2584                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2585  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2586                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2587  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2588                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2589  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2590                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2591
2592  // Register/register aliases with no shift when SP is not used.
2593  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2594                       GPR32, GPR32, GPR32, 0>;
2595  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2596                       GPR64, GPR64, GPR64, 0>;
2597
2598  // Register/register aliases with no shift when the first source register
2599  // is SP.
2600  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2601                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2602  def : AddSubRegAlias<mnemonic,
2603                       !cast<Instruction>(NAME#"Xrx64"),
2604                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2605}
2606
2607class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2608      : BaseAddSubImm<
2609          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2610          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2611          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2612  bits<6> imm6;
2613  bits<4> imm4;
2614  let Inst{31} = 1;
2615  let Inst{23-22} = 0b10;
2616  let Inst{21-16} = imm6;
2617  let Inst{15-14} = 0b00;
2618  let Inst{13-10} = imm4;
2619  let Unpredictable{15-14} = 0b11;
2620}
2621
2622class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2623      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2624  let Inst{31} = 1;
2625  let Inst{29} = setsFlags;
2626}
2627
2628//---
2629// Extract
2630//---
2631def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2632                                      SDTCisPtrTy<3>]>;
2633def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2634
2635class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2636                     list<dag> patterns>
2637    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2638         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2639      Sched<[WriteExtr, ReadExtrHi]> {
2640  bits<5> Rd;
2641  bits<5> Rn;
2642  bits<5> Rm;
2643  bits<6> imm;
2644
2645  let Inst{30-23} = 0b00100111;
2646  let Inst{21}    = 0;
2647  let Inst{20-16} = Rm;
2648  let Inst{15-10} = imm;
2649  let Inst{9-5}   = Rn;
2650  let Inst{4-0}   = Rd;
2651}
2652
2653multiclass ExtractImm<string asm> {
2654  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2655                      [(set GPR32:$Rd,
2656                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2657    let Inst{31} = 0;
2658    let Inst{22} = 0;
2659    // imm<5> must be zero.
2660    let imm{5}   = 0;
2661  }
2662  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2663                      [(set GPR64:$Rd,
2664                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2665
2666    let Inst{31} = 1;
2667    let Inst{22} = 1;
2668  }
2669}
2670
2671//---
2672// Bitfield
2673//---
2674
2675let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2676class BaseBitfieldImm<bits<2> opc,
2677                      RegisterClass regtype, Operand imm_type, string asm>
2678    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2679         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2680      Sched<[WriteIS, ReadI]> {
2681  bits<5> Rd;
2682  bits<5> Rn;
2683  bits<6> immr;
2684  bits<6> imms;
2685
2686  let Inst{30-29} = opc;
2687  let Inst{28-23} = 0b100110;
2688  let Inst{21-16} = immr;
2689  let Inst{15-10} = imms;
2690  let Inst{9-5}   = Rn;
2691  let Inst{4-0}   = Rd;
2692}
2693
2694multiclass BitfieldImm<bits<2> opc, string asm> {
2695  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2696    let Inst{31} = 0;
2697    let Inst{22} = 0;
2698    // imms<5> and immr<5> must be zero, else ReservedValue().
2699    let Inst{21} = 0;
2700    let Inst{15} = 0;
2701  }
2702  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2703    let Inst{31} = 1;
2704    let Inst{22} = 1;
2705  }
2706}
2707
2708let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2709class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2710                      RegisterClass regtype, Operand imm_type, string asm>
2711    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2712                             imm_type:$imms),
2713         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2714      Sched<[WriteIS, ReadI]> {
2715  bits<5> Rd;
2716  bits<5> Rn;
2717  bits<6> immr;
2718  bits<6> imms;
2719
2720  let Inst{30-29} = opc;
2721  let Inst{28-23} = 0b100110;
2722  let Inst{21-16} = immr;
2723  let Inst{15-10} = imms;
2724  let Inst{9-5}   = Rn;
2725  let Inst{4-0}   = Rd;
2726}
2727
2728multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2729  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2730    let Inst{31} = 0;
2731    let Inst{22} = 0;
2732    // imms<5> and immr<5> must be zero, else ReservedValue().
2733    let Inst{21} = 0;
2734    let Inst{15} = 0;
2735  }
2736  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2737    let Inst{31} = 1;
2738    let Inst{22} = 1;
2739  }
2740}
2741
2742//---
2743// Logical
2744//---
2745
2746// Logical (immediate)
2747class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2748                     RegisterClass sregtype, Operand imm_type, string asm,
2749                     list<dag> pattern>
2750    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2751         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2752      Sched<[WriteI, ReadI]> {
2753  bits<5>  Rd;
2754  bits<5>  Rn;
2755  bits<13> imm;
2756  let Inst{30-29} = opc;
2757  let Inst{28-23} = 0b100100;
2758  let Inst{22}    = imm{12};
2759  let Inst{21-16} = imm{11-6};
2760  let Inst{15-10} = imm{5-0};
2761  let Inst{9-5}   = Rn;
2762  let Inst{4-0}   = Rd;
2763
2764  let DecoderMethod = "DecodeLogicalImmInstruction";
2765}
2766
2767// Logical (shifted register)
2768class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2769                      logical_shifted_reg shifted_regtype, string asm,
2770                      list<dag> pattern>
2771    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2772        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2773      Sched<[WriteISReg, ReadI, ReadISReg]> {
2774  // The operands are in order to match the 'addr' MI operands, so we
2775  // don't need an encoder method and by-name matching. Just use the default
2776  // in-order handling. Since we're using by-order, make sure the names
2777  // do not match.
2778  bits<5> dst;
2779  bits<5> src1;
2780  bits<5> src2;
2781  bits<8> shift;
2782  let Inst{30-29} = opc;
2783  let Inst{28-24} = 0b01010;
2784  let Inst{23-22} = shift{7-6};
2785  let Inst{21}    = N;
2786  let Inst{20-16} = src2;
2787  let Inst{15-10} = shift{5-0};
2788  let Inst{9-5}   = src1;
2789  let Inst{4-0}   = dst;
2790
2791  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2792}
2793
2794// Aliases for register+register logical instructions.
2795class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2796    : InstAlias<asm#"\t$dst, $src1, $src2",
2797                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2798
2799multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2800                      string Alias> {
2801  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2802  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2803                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2804                                               logical_imm32:$imm))]> {
2805    let Inst{31} = 0;
2806    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2807  }
2808  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2809  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2810                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2811                                               logical_imm64:$imm))]> {
2812    let Inst{31} = 1;
2813  }
2814
2815  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2816                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2817                      logical_imm32_not:$imm), 0>;
2818  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2819                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2820                       logical_imm64_not:$imm), 0>;
2821}
2822
2823multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2824                       string Alias> {
2825  let isCompare = 1, Defs = [NZCV] in {
2826  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2827      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2828    let Inst{31} = 0;
2829    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2830  }
2831  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2832      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2833    let Inst{31} = 1;
2834  }
2835  } // end Defs = [NZCV]
2836
2837  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2838                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2839                      logical_imm32_not:$imm), 0>;
2840  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2841                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2842                       logical_imm64_not:$imm), 0>;
2843}
2844
2845class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2846    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2847             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2848      Sched<[WriteI, ReadI, ReadI]>;
2849
2850// Split from LogicalImm as not all instructions have both.
2851multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2852                      SDPatternOperator OpNode> {
2853  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2854  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2855  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2856  }
2857
2858  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2859                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2860                                                 logical_shifted_reg32:$Rm))]> {
2861    let Inst{31} = 0;
2862  }
2863  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2864                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2865                                                 logical_shifted_reg64:$Rm))]> {
2866    let Inst{31} = 1;
2867  }
2868
2869  def : LogicalRegAlias<mnemonic,
2870                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2871  def : LogicalRegAlias<mnemonic,
2872                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2873}
2874
2875// Split from LogicalReg to allow setting NZCV Defs
2876multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2877                       SDPatternOperator OpNode = null_frag> {
2878  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2879  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2880  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2881
2882  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2883            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2884    let Inst{31} = 0;
2885  }
2886  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2887            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2888    let Inst{31} = 1;
2889  }
2890  } // Defs = [NZCV]
2891
2892  def : LogicalRegAlias<mnemonic,
2893                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2894  def : LogicalRegAlias<mnemonic,
2895                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2896}
2897
2898//---
2899// Conditionally set flags
2900//---
2901
2902let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2903class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2904                            string mnemonic, SDNode OpNode>
2905    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2906         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2907         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2908                             (i32 imm:$cond), NZCV))]>,
2909      Sched<[WriteI, ReadI]> {
2910  let Uses = [NZCV];
2911  let Defs = [NZCV];
2912
2913  bits<5> Rn;
2914  bits<5> imm;
2915  bits<4> nzcv;
2916  bits<4> cond;
2917
2918  let Inst{30}    = op;
2919  let Inst{29-21} = 0b111010010;
2920  let Inst{20-16} = imm;
2921  let Inst{15-12} = cond;
2922  let Inst{11-10} = 0b10;
2923  let Inst{9-5}   = Rn;
2924  let Inst{4}     = 0b0;
2925  let Inst{3-0}   = nzcv;
2926}
2927
2928let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2929class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2930                            SDNode OpNode>
2931    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2932         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2933         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2934                             (i32 imm:$cond), NZCV))]>,
2935      Sched<[WriteI, ReadI, ReadI]> {
2936  let Uses = [NZCV];
2937  let Defs = [NZCV];
2938
2939  bits<5> Rn;
2940  bits<5> Rm;
2941  bits<4> nzcv;
2942  bits<4> cond;
2943
2944  let Inst{30}    = op;
2945  let Inst{29-21} = 0b111010010;
2946  let Inst{20-16} = Rm;
2947  let Inst{15-12} = cond;
2948  let Inst{11-10} = 0b00;
2949  let Inst{9-5}   = Rn;
2950  let Inst{4}     = 0b0;
2951  let Inst{3-0}   = nzcv;
2952}
2953
2954multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2955  // immediate operand variants
2956  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2957    let Inst{31} = 0;
2958  }
2959  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2960    let Inst{31} = 1;
2961  }
2962  // register operand variants
2963  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2964    let Inst{31} = 0;
2965  }
2966  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2967    let Inst{31} = 1;
2968  }
2969}
2970
2971//---
2972// Conditional select
2973//---
2974
2975class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2976    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2977         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2978         [(set regtype:$Rd,
2979               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2980      Sched<[WriteI, ReadI, ReadI]> {
2981  let Uses = [NZCV];
2982
2983  bits<5> Rd;
2984  bits<5> Rn;
2985  bits<5> Rm;
2986  bits<4> cond;
2987
2988  let Inst{30}    = op;
2989  let Inst{29-21} = 0b011010100;
2990  let Inst{20-16} = Rm;
2991  let Inst{15-12} = cond;
2992  let Inst{11-10} = op2;
2993  let Inst{9-5}   = Rn;
2994  let Inst{4-0}   = Rd;
2995}
2996
2997multiclass CondSelect<bit op, bits<2> op2, string asm> {
2998  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2999    let Inst{31} = 0;
3000  }
3001  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3002    let Inst{31} = 1;
3003  }
3004}
3005
3006class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3007                       PatFrag frag>
3008    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3009         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3010         [(set regtype:$Rd,
3011               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3012               (i32 imm:$cond), NZCV))]>,
3013      Sched<[WriteI, ReadI, ReadI]> {
3014  let Uses = [NZCV];
3015
3016  bits<5> Rd;
3017  bits<5> Rn;
3018  bits<5> Rm;
3019  bits<4> cond;
3020
3021  let Inst{30}    = op;
3022  let Inst{29-21} = 0b011010100;
3023  let Inst{20-16} = Rm;
3024  let Inst{15-12} = cond;
3025  let Inst{11-10} = op2;
3026  let Inst{9-5}   = Rn;
3027  let Inst{4-0}   = Rd;
3028}
3029
3030def inv_cond_XFORM : SDNodeXForm<imm, [{
3031  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3032  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3033                                   MVT::i32);
3034}]>;
3035
3036multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3037  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3038    let Inst{31} = 0;
3039  }
3040  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3041    let Inst{31} = 1;
3042  }
3043
3044  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3045            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3046                                           (inv_cond_XFORM imm:$cond))>;
3047
3048  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3049            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3050                                           (inv_cond_XFORM imm:$cond))>;
3051}
3052
3053//---
3054// Special Mask Value
3055//---
3056def maski8_or_more : Operand<i32>,
3057  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3058}
3059def maski16_or_more : Operand<i32>,
3060  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3061}
3062
3063
3064//---
3065// Load/store
3066//---
3067
3068// (unsigned immediate)
3069// Indexed for 8-bit registers. offset is in range [0,4095].
3070def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
3071def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
3072def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
3073def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
3074def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
3075
3076def gi_am_indexed8 :
3077    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3078    GIComplexPatternEquiv<am_indexed8>;
3079def gi_am_indexed16 :
3080    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3081    GIComplexPatternEquiv<am_indexed16>;
3082def gi_am_indexed32 :
3083    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3084    GIComplexPatternEquiv<am_indexed32>;
3085def gi_am_indexed64 :
3086    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3087    GIComplexPatternEquiv<am_indexed64>;
3088def gi_am_indexed128 :
3089    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3090    GIComplexPatternEquiv<am_indexed128>;
3091
3092class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3093  let Name = "UImm12Offset" # Scale;
3094  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3095  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3096  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3097}
3098
3099def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3100def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3101def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3102def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3103def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3104
3105class uimm12_scaled<int Scale> : Operand<i64> {
3106  let ParserMatchClass
3107   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3108  let EncoderMethod
3109   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3110  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3111}
3112
3113def uimm12s1 : uimm12_scaled<1>;
3114def uimm12s2 : uimm12_scaled<2>;
3115def uimm12s4 : uimm12_scaled<4>;
3116def uimm12s8 : uimm12_scaled<8>;
3117def uimm12s16 : uimm12_scaled<16>;
3118
3119class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3120                      string asm, list<dag> pattern>
3121    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3122  bits<5> Rt;
3123
3124  bits<5> Rn;
3125  bits<12> offset;
3126
3127  let Inst{31-30} = sz;
3128  let Inst{29-27} = 0b111;
3129  let Inst{26}    = V;
3130  let Inst{25-24} = 0b01;
3131  let Inst{23-22} = opc;
3132  let Inst{21-10} = offset;
3133  let Inst{9-5}   = Rn;
3134  let Inst{4-0}   = Rt;
3135
3136  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3137}
3138
3139multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3140                  Operand indextype, string asm, list<dag> pattern> {
3141  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3142  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3143                           (ins GPR64sp:$Rn, indextype:$offset),
3144                           asm, pattern>,
3145           Sched<[WriteLD]>;
3146
3147  def : InstAlias<asm # "\t$Rt, [$Rn]",
3148                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3149}
3150
3151multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3152             Operand indextype, string asm, list<dag> pattern> {
3153  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3154  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3155                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3156                           asm, pattern>,
3157           Sched<[WriteST]>;
3158
3159  def : InstAlias<asm # "\t$Rt, [$Rn]",
3160                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3161}
3162
3163// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3164// substitute zero-registers automatically.
3165//
3166// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3167//       into StoreUI.
3168multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3169             Operand indextype, string asm, list<dag> pattern> {
3170  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3171  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3172                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3173                           asm, pattern>,
3174           Sched<[WriteST]>;
3175
3176  def : InstAlias<asm # "\t$Rt, [$Rn]",
3177                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3178}
3179
3180def PrefetchOperand : AsmOperandClass {
3181  let Name = "Prefetch";
3182  let ParserMethod = "tryParsePrefetch";
3183}
3184def prfop : Operand<i32> {
3185  let PrintMethod = "printPrefetchOp";
3186  let ParserMatchClass = PrefetchOperand;
3187}
3188
3189let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3190class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3191    : BaseLoadStoreUI<sz, V, opc,
3192                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3193                      asm, pat>,
3194      Sched<[WriteLD]>;
3195
3196//---
3197// Load literal
3198//---
3199
3200// Load literal address: 19-bit immediate. The low two bits of the target
3201// offset are implied zero and so are not part of the immediate.
3202def am_ldrlit : Operand<iPTR> {
3203  let EncoderMethod = "getLoadLiteralOpValue";
3204  let DecoderMethod = "DecodePCRelLabel19";
3205  let PrintMethod = "printAlignedLabel";
3206  let ParserMatchClass = PCRelLabel19Operand;
3207  let OperandType = "OPERAND_PCREL";
3208}
3209
3210let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3211class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3212    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3213        asm, "\t$Rt, $label", "", pat>,
3214      Sched<[WriteLD]> {
3215  bits<5> Rt;
3216  bits<19> label;
3217  let Inst{31-30} = opc;
3218  let Inst{29-27} = 0b011;
3219  let Inst{26}    = V;
3220  let Inst{25-24} = 0b00;
3221  let Inst{23-5}  = label;
3222  let Inst{4-0}   = Rt;
3223}
3224
3225let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3226class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3227    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3228        asm, "\t$Rt, $label", "", pat>,
3229      Sched<[WriteLD]> {
3230  bits<5> Rt;
3231  bits<19> label;
3232  let Inst{31-30} = opc;
3233  let Inst{29-27} = 0b011;
3234  let Inst{26}    = V;
3235  let Inst{25-24} = 0b00;
3236  let Inst{23-5}  = label;
3237  let Inst{4-0}   = Rt;
3238}
3239
3240//---
3241// Load/store register offset
3242//---
3243
3244def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3245def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3246def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3247def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3248def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3249
3250def gi_ro_Xindexed8 :
3251    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3252    GIComplexPatternEquiv<ro_Xindexed8>;
3253def gi_ro_Xindexed16 :
3254    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3255    GIComplexPatternEquiv<ro_Xindexed16>;
3256def gi_ro_Xindexed32 :
3257    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3258    GIComplexPatternEquiv<ro_Xindexed32>;
3259def gi_ro_Xindexed64 :
3260    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3261    GIComplexPatternEquiv<ro_Xindexed64>;
3262def gi_ro_Xindexed128 :
3263    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3264    GIComplexPatternEquiv<ro_Xindexed128>;
3265
3266def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3267def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3268def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3269def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3270def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3271
3272def gi_ro_Windexed8 :
3273    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3274    GIComplexPatternEquiv<ro_Windexed8>;
3275def gi_ro_Windexed16 :
3276    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3277    GIComplexPatternEquiv<ro_Windexed16>;
3278def gi_ro_Windexed32 :
3279    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3280    GIComplexPatternEquiv<ro_Windexed32>;
3281def gi_ro_Windexed64 :
3282    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3283    GIComplexPatternEquiv<ro_Windexed64>;
3284def gi_ro_Windexed128 :
3285    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3286    GIComplexPatternEquiv<ro_Windexed128>;
3287
3288class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3289  let Name = "Mem" # Reg # "Extend" # Width;
3290  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3291  let RenderMethod = "addMemExtendOperands";
3292  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3293}
3294
3295def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3296  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3297  // the trivial shift.
3298  let RenderMethod = "addMemExtend8Operands";
3299}
3300def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3301def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3302def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3303def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3304
3305def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3306  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3307  // the trivial shift.
3308  let RenderMethod = "addMemExtend8Operands";
3309}
3310def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3311def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3312def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3313def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3314
3315class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3316        : Operand<i32> {
3317  let ParserMatchClass = ParserClass;
3318  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3319  let DecoderMethod = "DecodeMemExtend";
3320  let EncoderMethod = "getMemExtendOpValue";
3321  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3322}
3323
3324def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3325def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3326def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3327def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3328def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3329
3330def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3331def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3332def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3333def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3334def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3335
3336class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3337                  Operand wextend, Operand xextend>  {
3338  // CodeGen-level pattern covering the entire addressing mode.
3339  ComplexPattern Wpat = windex;
3340  ComplexPattern Xpat = xindex;
3341
3342  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3343  Operand Wext = wextend;
3344  Operand Xext = xextend;
3345}
3346
3347def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3348def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3349def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3350def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3351def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3352                       ro_Xextend128>;
3353
3354class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3355                      string asm, dag ins, dag outs, list<dag> pat>
3356    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3357  bits<5> Rt;
3358  bits<5> Rn;
3359  bits<5> Rm;
3360  bits<2> extend;
3361  let Inst{31-30} = sz;
3362  let Inst{29-27} = 0b111;
3363  let Inst{26}    = V;
3364  let Inst{25-24} = 0b00;
3365  let Inst{23-22} = opc;
3366  let Inst{21}    = 1;
3367  let Inst{20-16} = Rm;
3368  let Inst{15}    = extend{1}; // sign extend Rm?
3369  let Inst{14}    = 1;
3370  let Inst{12}    = extend{0}; // do shift?
3371  let Inst{11-10} = 0b10;
3372  let Inst{9-5}   = Rn;
3373  let Inst{4-0}   = Rt;
3374}
3375
3376class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3377  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3378              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3379
3380multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3381                   string asm, ValueType Ty, SDPatternOperator loadop> {
3382  let AddedComplexity = 10 in
3383  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3384                 (outs regtype:$Rt),
3385                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3386                 [(set (Ty regtype:$Rt),
3387                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3388                                             ro_Wextend8:$extend)))]>,
3389           Sched<[WriteLDIdx, ReadAdrBase]> {
3390    let Inst{13} = 0b0;
3391  }
3392
3393  let AddedComplexity = 10 in
3394  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3395                 (outs regtype:$Rt),
3396                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3397                 [(set (Ty regtype:$Rt),
3398                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3399                                             ro_Xextend8:$extend)))]>,
3400           Sched<[WriteLDIdx, ReadAdrBase]> {
3401    let Inst{13} = 0b1;
3402  }
3403
3404  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3405}
3406
3407multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3408                    string asm, ValueType Ty, SDPatternOperator storeop> {
3409  let AddedComplexity = 10 in
3410  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3411                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3412                 [(storeop (Ty regtype:$Rt),
3413                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3414                                         ro_Wextend8:$extend))]>,
3415            Sched<[WriteSTIdx, ReadAdrBase]> {
3416    let Inst{13} = 0b0;
3417  }
3418
3419  let AddedComplexity = 10 in
3420  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3421                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3422                 [(storeop (Ty regtype:$Rt),
3423                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3424                                         ro_Xextend8:$extend))]>,
3425            Sched<[WriteSTIdx, ReadAdrBase]> {
3426    let Inst{13} = 0b1;
3427  }
3428
3429  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3430}
3431
3432class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3433                      string asm, dag ins, dag outs, list<dag> pat>
3434    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3435  bits<5> Rt;
3436  bits<5> Rn;
3437  bits<5> Rm;
3438  bits<2> extend;
3439  let Inst{31-30} = sz;
3440  let Inst{29-27} = 0b111;
3441  let Inst{26}    = V;
3442  let Inst{25-24} = 0b00;
3443  let Inst{23-22} = opc;
3444  let Inst{21}    = 1;
3445  let Inst{20-16} = Rm;
3446  let Inst{15}    = extend{1}; // sign extend Rm?
3447  let Inst{14}    = 1;
3448  let Inst{12}    = extend{0}; // do shift?
3449  let Inst{11-10} = 0b10;
3450  let Inst{9-5}   = Rn;
3451  let Inst{4-0}   = Rt;
3452}
3453
3454multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3455                    string asm, ValueType Ty, SDPatternOperator loadop> {
3456  let AddedComplexity = 10 in
3457  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3458                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3459                 [(set (Ty regtype:$Rt),
3460                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3461                                              ro_Wextend16:$extend)))]>,
3462            Sched<[WriteLDIdx, ReadAdrBase]> {
3463    let Inst{13} = 0b0;
3464  }
3465
3466  let AddedComplexity = 10 in
3467  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3468                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3469                 [(set (Ty regtype:$Rt),
3470                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3471                                             ro_Xextend16:$extend)))]>,
3472            Sched<[WriteLDIdx, ReadAdrBase]> {
3473    let Inst{13} = 0b1;
3474  }
3475
3476  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3477}
3478
3479multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3480                     string asm, ValueType Ty, SDPatternOperator storeop> {
3481  let AddedComplexity = 10 in
3482  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3483                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3484                [(storeop (Ty regtype:$Rt),
3485                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3486                                         ro_Wextend16:$extend))]>,
3487           Sched<[WriteSTIdx, ReadAdrBase]> {
3488    let Inst{13} = 0b0;
3489  }
3490
3491  let AddedComplexity = 10 in
3492  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3493                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3494                [(storeop (Ty regtype:$Rt),
3495                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3496                                         ro_Xextend16:$extend))]>,
3497           Sched<[WriteSTIdx, ReadAdrBase]> {
3498    let Inst{13} = 0b1;
3499  }
3500
3501  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3502}
3503
3504class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3505                      string asm, dag ins, dag outs, list<dag> pat>
3506    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3507  bits<5> Rt;
3508  bits<5> Rn;
3509  bits<5> Rm;
3510  bits<2> extend;
3511  let Inst{31-30} = sz;
3512  let Inst{29-27} = 0b111;
3513  let Inst{26}    = V;
3514  let Inst{25-24} = 0b00;
3515  let Inst{23-22} = opc;
3516  let Inst{21}    = 1;
3517  let Inst{20-16} = Rm;
3518  let Inst{15}    = extend{1}; // sign extend Rm?
3519  let Inst{14}    = 1;
3520  let Inst{12}    = extend{0}; // do shift?
3521  let Inst{11-10} = 0b10;
3522  let Inst{9-5}   = Rn;
3523  let Inst{4-0}   = Rt;
3524}
3525
3526multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3527                    string asm, ValueType Ty, SDPatternOperator loadop> {
3528  let AddedComplexity = 10 in
3529  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3530                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3531                 [(set (Ty regtype:$Rt),
3532                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3533                                              ro_Wextend32:$extend)))]>,
3534           Sched<[WriteLDIdx, ReadAdrBase]> {
3535    let Inst{13} = 0b0;
3536  }
3537
3538  let AddedComplexity = 10 in
3539  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3540                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3541                 [(set (Ty regtype:$Rt),
3542                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3543                                              ro_Xextend32:$extend)))]>,
3544           Sched<[WriteLDIdx, ReadAdrBase]> {
3545    let Inst{13} = 0b1;
3546  }
3547
3548  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3549}
3550
3551multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3552                     string asm, ValueType Ty, SDPatternOperator storeop> {
3553  let AddedComplexity = 10 in
3554  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3555                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3556                [(storeop (Ty regtype:$Rt),
3557                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3558                                         ro_Wextend32:$extend))]>,
3559            Sched<[WriteSTIdx, ReadAdrBase]> {
3560    let Inst{13} = 0b0;
3561  }
3562
3563  let AddedComplexity = 10 in
3564  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3565                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3566                [(storeop (Ty regtype:$Rt),
3567                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3568                                        ro_Xextend32:$extend))]>,
3569            Sched<[WriteSTIdx, ReadAdrBase]> {
3570    let Inst{13} = 0b1;
3571  }
3572
3573  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3574}
3575
3576class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3577                      string asm, dag ins, dag outs, list<dag> pat>
3578    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3579  bits<5> Rt;
3580  bits<5> Rn;
3581  bits<5> Rm;
3582  bits<2> extend;
3583  let Inst{31-30} = sz;
3584  let Inst{29-27} = 0b111;
3585  let Inst{26}    = V;
3586  let Inst{25-24} = 0b00;
3587  let Inst{23-22} = opc;
3588  let Inst{21}    = 1;
3589  let Inst{20-16} = Rm;
3590  let Inst{15}    = extend{1}; // sign extend Rm?
3591  let Inst{14}    = 1;
3592  let Inst{12}    = extend{0}; // do shift?
3593  let Inst{11-10} = 0b10;
3594  let Inst{9-5}   = Rn;
3595  let Inst{4-0}   = Rt;
3596}
3597
3598multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3599                    string asm, ValueType Ty, SDPatternOperator loadop> {
3600  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3601  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3602                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3603                [(set (Ty regtype:$Rt),
3604                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3605                                             ro_Wextend64:$extend)))]>,
3606           Sched<[WriteLDIdx, ReadAdrBase]> {
3607    let Inst{13} = 0b0;
3608  }
3609
3610  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3611  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3612                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3613                 [(set (Ty regtype:$Rt),
3614                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3615                                              ro_Xextend64:$extend)))]>,
3616           Sched<[WriteLDIdx, ReadAdrBase]> {
3617    let Inst{13} = 0b1;
3618  }
3619
3620  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3621}
3622
3623multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3624                     string asm, ValueType Ty, SDPatternOperator storeop> {
3625  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3626  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3627                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3628                [(storeop (Ty regtype:$Rt),
3629                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3630                                         ro_Wextend64:$extend))]>,
3631            Sched<[WriteSTIdx, ReadAdrBase]> {
3632    let Inst{13} = 0b0;
3633  }
3634
3635  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3636  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3637                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3638                [(storeop (Ty regtype:$Rt),
3639                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3640                                         ro_Xextend64:$extend))]>,
3641            Sched<[WriteSTIdx, ReadAdrBase]> {
3642    let Inst{13} = 0b1;
3643  }
3644
3645  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3646}
3647
3648class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3649                      string asm, dag ins, dag outs, list<dag> pat>
3650    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3651  bits<5> Rt;
3652  bits<5> Rn;
3653  bits<5> Rm;
3654  bits<2> extend;
3655  let Inst{31-30} = sz;
3656  let Inst{29-27} = 0b111;
3657  let Inst{26}    = V;
3658  let Inst{25-24} = 0b00;
3659  let Inst{23-22} = opc;
3660  let Inst{21}    = 1;
3661  let Inst{20-16} = Rm;
3662  let Inst{15}    = extend{1}; // sign extend Rm?
3663  let Inst{14}    = 1;
3664  let Inst{12}    = extend{0}; // do shift?
3665  let Inst{11-10} = 0b10;
3666  let Inst{9-5}   = Rn;
3667  let Inst{4-0}   = Rt;
3668}
3669
3670multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3671                     string asm, ValueType Ty, SDPatternOperator loadop> {
3672  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3673  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3674                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3675                 [(set (Ty regtype:$Rt),
3676                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3677                                               ro_Wextend128:$extend)))]>,
3678            Sched<[WriteLDIdx, ReadAdrBase]> {
3679    let Inst{13} = 0b0;
3680  }
3681
3682  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3683  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3684                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3685                 [(set (Ty regtype:$Rt),
3686                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3687                                               ro_Xextend128:$extend)))]>,
3688            Sched<[WriteLDIdx, ReadAdrBase]> {
3689    let Inst{13} = 0b1;
3690  }
3691
3692  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3693}
3694
3695multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3696                      string asm, ValueType Ty, SDPatternOperator storeop> {
3697  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3698  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3699               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3700                []>,
3701            Sched<[WriteSTIdx, ReadAdrBase]> {
3702    let Inst{13} = 0b0;
3703  }
3704
3705  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3706  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3707               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3708                []>,
3709            Sched<[WriteSTIdx, ReadAdrBase]> {
3710    let Inst{13} = 0b1;
3711  }
3712
3713  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3714}
3715
3716let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3717class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3718                     string asm, list<dag> pat>
3719    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3720      Sched<[WriteLD]> {
3721  bits<5> Rt;
3722  bits<5> Rn;
3723  bits<5> Rm;
3724  bits<2> extend;
3725  let Inst{31-30} = sz;
3726  let Inst{29-27} = 0b111;
3727  let Inst{26}    = V;
3728  let Inst{25-24} = 0b00;
3729  let Inst{23-22} = opc;
3730  let Inst{21}    = 1;
3731  let Inst{20-16} = Rm;
3732  let Inst{15}    = extend{1}; // sign extend Rm?
3733  let Inst{14}    = 1;
3734  let Inst{12}    = extend{0}; // do shift?
3735  let Inst{11-10} = 0b10;
3736  let Inst{9-5}   = Rn;
3737  let Inst{4-0}   = Rt;
3738}
3739
3740multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3741  def roW : BasePrefetchRO<sz, V, opc, (outs),
3742                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3743                asm, [(AArch64Prefetch imm:$Rt,
3744                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3745                                                    ro_Wextend64:$extend))]> {
3746    let Inst{13} = 0b0;
3747  }
3748
3749  def roX : BasePrefetchRO<sz, V, opc, (outs),
3750                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3751                asm,  [(AArch64Prefetch imm:$Rt,
3752                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3753                                                     ro_Xextend64:$extend))]> {
3754    let Inst{13} = 0b1;
3755  }
3756
3757  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3758               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3759                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3760}
3761
3762//---
3763// Load/store unscaled immediate
3764//---
3765
3766def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3767def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3768def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3769def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3770def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3771
3772def gi_am_unscaled8 :
3773    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3774    GIComplexPatternEquiv<am_unscaled8>;
3775def gi_am_unscaled16 :
3776    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3777    GIComplexPatternEquiv<am_unscaled16>;
3778def gi_am_unscaled32 :
3779    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3780    GIComplexPatternEquiv<am_unscaled32>;
3781def gi_am_unscaled64 :
3782    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3783    GIComplexPatternEquiv<am_unscaled64>;
3784def gi_am_unscaled128 :
3785    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3786    GIComplexPatternEquiv<am_unscaled128>;
3787
3788
3789class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3790                           string asm, list<dag> pattern>
3791    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3792  bits<5> Rt;
3793  bits<5> Rn;
3794  bits<9> offset;
3795  let Inst{31-30} = sz;
3796  let Inst{29-27} = 0b111;
3797  let Inst{26}    = V;
3798  let Inst{25-24} = 0b00;
3799  let Inst{23-22} = opc;
3800  let Inst{21}    = 0;
3801  let Inst{20-12} = offset;
3802  let Inst{11-10} = 0b00;
3803  let Inst{9-5}   = Rn;
3804  let Inst{4-0}   = Rt;
3805
3806  let DecoderMethod = "DecodeSignedLdStInstruction";
3807}
3808
3809// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3810multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3811                              RegisterOperand regtype > {
3812  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3813                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3814          Sched<[WriteST]> {
3815    let Inst{29} = 0;
3816    let Inst{24} = 1;
3817  }
3818  def : InstAlias<asm # "\t$Rt, [$Rn]",
3819                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3820}
3821
3822multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3823                               RegisterOperand regtype > {
3824  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3825                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3826                               asm, []>,
3827          Sched<[WriteST]> {
3828    let Inst{29} = 0;
3829    let Inst{24} = 1;
3830  }
3831  def : InstAlias<asm # "\t$Rt, [$Rn]",
3832                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3833}
3834
3835multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3836                   string asm, list<dag> pattern> {
3837  let AddedComplexity = 1 in // try this before LoadUI
3838  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3839                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3840          Sched<[WriteLD]>;
3841
3842  def : InstAlias<asm # "\t$Rt, [$Rn]",
3843                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3844}
3845
3846multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3847                         string asm, list<dag> pattern> {
3848  let AddedComplexity = 1 in // try this before StoreUI
3849  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3850                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3851                               asm, pattern>,
3852          Sched<[WriteST]>;
3853
3854  def : InstAlias<asm # "\t$Rt, [$Rn]",
3855                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3856}
3857
3858multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3859                            list<dag> pat> {
3860  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3861  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3862                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3863                               asm, pat>,
3864          Sched<[WriteLD]>;
3865
3866  def : InstAlias<asm # "\t$Rt, [$Rn]",
3867                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3868}
3869
3870//---
3871// Load/store unscaled immediate, unprivileged
3872//---
3873
3874class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3875                                dag oops, dag iops, string asm>
3876    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3877  bits<5> Rt;
3878  bits<5> Rn;
3879  bits<9> offset;
3880  let Inst{31-30} = sz;
3881  let Inst{29-27} = 0b111;
3882  let Inst{26}    = V;
3883  let Inst{25-24} = 0b00;
3884  let Inst{23-22} = opc;
3885  let Inst{21}    = 0;
3886  let Inst{20-12} = offset;
3887  let Inst{11-10} = 0b10;
3888  let Inst{9-5}   = Rn;
3889  let Inst{4-0}   = Rt;
3890
3891  let DecoderMethod = "DecodeSignedLdStInstruction";
3892}
3893
3894multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3895                            RegisterClass regtype, string asm> {
3896  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3897  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3898                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3899          Sched<[WriteLD]>;
3900
3901  def : InstAlias<asm # "\t$Rt, [$Rn]",
3902                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3903}
3904
3905multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3906                             RegisterClass regtype, string asm> {
3907  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3908  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3909                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3910                                 asm>,
3911          Sched<[WriteST]>;
3912
3913  def : InstAlias<asm # "\t$Rt, [$Rn]",
3914                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3915}
3916
3917//---
3918// Load/store pre-indexed
3919//---
3920
3921class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3922                          string asm, string cstr, list<dag> pat>
3923    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3924  bits<5> Rt;
3925  bits<5> Rn;
3926  bits<9> offset;
3927  let Inst{31-30} = sz;
3928  let Inst{29-27} = 0b111;
3929  let Inst{26}    = V;
3930  let Inst{25-24} = 0;
3931  let Inst{23-22} = opc;
3932  let Inst{21}    = 0;
3933  let Inst{20-12} = offset;
3934  let Inst{11-10} = 0b11;
3935  let Inst{9-5}   = Rn;
3936  let Inst{4-0}   = Rt;
3937
3938  let DecoderMethod = "DecodeSignedLdStInstruction";
3939}
3940
3941let hasSideEffects = 0 in {
3942let mayStore = 0, mayLoad = 1 in
3943class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3944             string asm>
3945    : BaseLoadStorePreIdx<sz, V, opc,
3946                     (outs GPR64sp:$wback, regtype:$Rt),
3947                     (ins GPR64sp:$Rn, simm9:$offset), asm,
3948                     "$Rn = $wback,@earlyclobber $wback", []>,
3949      Sched<[WriteAdr, WriteLD]>;
3950
3951let mayStore = 1, mayLoad = 0 in
3952class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3953                  string asm, SDPatternOperator storeop, ValueType Ty>
3954    : BaseLoadStorePreIdx<sz, V, opc,
3955                      (outs GPR64sp:$wback),
3956                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3957                      asm, "$Rn = $wback,@earlyclobber $wback",
3958      [(set GPR64sp:$wback,
3959            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3960      Sched<[WriteAdr, WriteST]>;
3961} // hasSideEffects = 0
3962
3963//---
3964// Load/store post-indexed
3965//---
3966
3967class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3968                          string asm, string cstr, list<dag> pat>
3969    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3970  bits<5> Rt;
3971  bits<5> Rn;
3972  bits<9> offset;
3973  let Inst{31-30} = sz;
3974  let Inst{29-27} = 0b111;
3975  let Inst{26}    = V;
3976  let Inst{25-24} = 0b00;
3977  let Inst{23-22} = opc;
3978  let Inst{21}    = 0b0;
3979  let Inst{20-12} = offset;
3980  let Inst{11-10} = 0b01;
3981  let Inst{9-5}   = Rn;
3982  let Inst{4-0}   = Rt;
3983
3984  let DecoderMethod = "DecodeSignedLdStInstruction";
3985}
3986
3987let hasSideEffects = 0 in {
3988let mayStore = 0, mayLoad = 1 in
3989class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3990             string asm>
3991    : BaseLoadStorePostIdx<sz, V, opc,
3992                      (outs GPR64sp:$wback, regtype:$Rt),
3993                      (ins GPR64sp:$Rn, simm9:$offset),
3994                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
3995      Sched<[WriteAdr, WriteLD]>;
3996
3997let mayStore = 1, mayLoad = 0 in
3998class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3999                   string asm, SDPatternOperator storeop, ValueType Ty>
4000    : BaseLoadStorePostIdx<sz, V, opc,
4001                      (outs GPR64sp:$wback),
4002                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4003                       asm, "$Rn = $wback,@earlyclobber $wback",
4004      [(set GPR64sp:$wback,
4005            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4006    Sched<[WriteAdr, WriteST]>;
4007} // hasSideEffects = 0
4008
4009
4010//---
4011// Load/store pair
4012//---
4013
4014// (indexed, offset)
4015
4016class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4017                              string asm>
4018    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4019  bits<5> Rt;
4020  bits<5> Rt2;
4021  bits<5> Rn;
4022  bits<7> offset;
4023  let Inst{31-30} = opc;
4024  let Inst{29-27} = 0b101;
4025  let Inst{26}    = V;
4026  let Inst{25-23} = 0b010;
4027  let Inst{22}    = L;
4028  let Inst{21-15} = offset;
4029  let Inst{14-10} = Rt2;
4030  let Inst{9-5}   = Rn;
4031  let Inst{4-0}   = Rt;
4032
4033  let DecoderMethod = "DecodePairLdStInstruction";
4034}
4035
4036multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4037                          Operand indextype, string asm> {
4038  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4039  def i : BaseLoadStorePairOffset<opc, V, 1,
4040                                  (outs regtype:$Rt, regtype:$Rt2),
4041                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4042          Sched<[WriteLD, WriteLDHi]>;
4043
4044  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4045                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4046                                                  GPR64sp:$Rn, 0)>;
4047}
4048
4049
4050multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4051                           Operand indextype, string asm> {
4052  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4053  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4054                                  (ins regtype:$Rt, regtype:$Rt2,
4055                                       GPR64sp:$Rn, indextype:$offset),
4056                                  asm>,
4057          Sched<[WriteSTP]>;
4058
4059  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4060                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4061                                                  GPR64sp:$Rn, 0)>;
4062}
4063
4064// (pre-indexed)
4065class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4066                              string asm>
4067    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4068  bits<5> Rt;
4069  bits<5> Rt2;
4070  bits<5> Rn;
4071  bits<7> offset;
4072  let Inst{31-30} = opc;
4073  let Inst{29-27} = 0b101;
4074  let Inst{26}    = V;
4075  let Inst{25-23} = 0b011;
4076  let Inst{22}    = L;
4077  let Inst{21-15} = offset;
4078  let Inst{14-10} = Rt2;
4079  let Inst{9-5}   = Rn;
4080  let Inst{4-0}   = Rt;
4081
4082  let DecoderMethod = "DecodePairLdStInstruction";
4083}
4084
4085let hasSideEffects = 0 in {
4086let mayStore = 0, mayLoad = 1 in
4087class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4088                     Operand indextype, string asm>
4089    : BaseLoadStorePairPreIdx<opc, V, 1,
4090                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4091                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4092      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4093
4094let mayStore = 1, mayLoad = 0 in
4095class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4096                      Operand indextype, string asm>
4097    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4098                             (ins regtype:$Rt, regtype:$Rt2,
4099                                  GPR64sp:$Rn, indextype:$offset),
4100                             asm>,
4101      Sched<[WriteAdr, WriteSTP]>;
4102} // hasSideEffects = 0
4103
4104// (post-indexed)
4105
4106class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4107                              string asm>
4108    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4109  bits<5> Rt;
4110  bits<5> Rt2;
4111  bits<5> Rn;
4112  bits<7> offset;
4113  let Inst{31-30} = opc;
4114  let Inst{29-27} = 0b101;
4115  let Inst{26}    = V;
4116  let Inst{25-23} = 0b001;
4117  let Inst{22}    = L;
4118  let Inst{21-15} = offset;
4119  let Inst{14-10} = Rt2;
4120  let Inst{9-5}   = Rn;
4121  let Inst{4-0}   = Rt;
4122
4123  let DecoderMethod = "DecodePairLdStInstruction";
4124}
4125
4126let hasSideEffects = 0 in {
4127let mayStore = 0, mayLoad = 1 in
4128class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4129                      Operand idxtype, string asm>
4130    : BaseLoadStorePairPostIdx<opc, V, 1,
4131                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4132                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4133      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4134
4135let mayStore = 1, mayLoad = 0 in
4136class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4137                       Operand idxtype, string asm>
4138    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4139                             (ins regtype:$Rt, regtype:$Rt2,
4140                                  GPR64sp:$Rn, idxtype:$offset),
4141                             asm>,
4142      Sched<[WriteAdr, WriteSTP]>;
4143} // hasSideEffects = 0
4144
4145//  (no-allocate)
4146
4147class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4148                              string asm>
4149    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4150  bits<5> Rt;
4151  bits<5> Rt2;
4152  bits<5> Rn;
4153  bits<7> offset;
4154  let Inst{31-30} = opc;
4155  let Inst{29-27} = 0b101;
4156  let Inst{26}    = V;
4157  let Inst{25-23} = 0b000;
4158  let Inst{22}    = L;
4159  let Inst{21-15} = offset;
4160  let Inst{14-10} = Rt2;
4161  let Inst{9-5}   = Rn;
4162  let Inst{4-0}   = Rt;
4163
4164  let DecoderMethod = "DecodePairLdStInstruction";
4165}
4166
4167multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4168                           Operand indextype, string asm> {
4169  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4170  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4171                                   (outs regtype:$Rt, regtype:$Rt2),
4172                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4173          Sched<[WriteLD, WriteLDHi]>;
4174
4175
4176  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4177                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4178                                                  GPR64sp:$Rn, 0)>;
4179}
4180
4181multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4182                      Operand indextype, string asm> {
4183  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4184  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4185                                   (ins regtype:$Rt, regtype:$Rt2,
4186                                        GPR64sp:$Rn, indextype:$offset),
4187                                   asm>,
4188          Sched<[WriteSTP]>;
4189
4190  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4191                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4192                                                  GPR64sp:$Rn, 0)>;
4193}
4194
4195//---
4196// Load/store exclusive
4197//---
4198
4199// True exclusive operations write to and/or read from the system's exclusive
4200// monitors, which as far as a compiler is concerned can be modelled as a
4201// random shared memory address. Hence LoadExclusive mayStore.
4202//
4203// Since these instructions have the undefined register bits set to 1 in
4204// their canonical form, we need a post encoder method to set those bits
4205// to 1 when encoding these instructions. We do this using the
4206// fixLoadStoreExclusive function. This function has template parameters:
4207//
4208// fixLoadStoreExclusive<int hasRs, int hasRt2>
4209//
4210// hasRs indicates that the instruction uses the Rs field, so we won't set
4211// it to 1 (and the same for Rt2). We don't need template parameters for
4212// the other register fields since Rt and Rn are always used.
4213//
4214let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4215class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4216                             dag oops, dag iops, string asm, string operands>
4217    : I<oops, iops, asm, operands, "", []> {
4218  let Inst{31-30} = sz;
4219  let Inst{29-24} = 0b001000;
4220  let Inst{23}    = o2;
4221  let Inst{22}    = L;
4222  let Inst{21}    = o1;
4223  let Inst{15}    = o0;
4224
4225  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4226}
4227
4228// Neither Rs nor Rt2 operands.
4229class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4230                               dag oops, dag iops, string asm, string operands>
4231    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4232  bits<5> Rt;
4233  bits<5> Rn;
4234  let Inst{20-16} = 0b11111;
4235  let Unpredictable{20-16} = 0b11111;
4236  let Inst{14-10} = 0b11111;
4237  let Unpredictable{14-10} = 0b11111;
4238  let Inst{9-5} = Rn;
4239  let Inst{4-0} = Rt;
4240
4241  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4242}
4243
4244// Simple load acquires don't set the exclusive monitor
4245let mayLoad = 1, mayStore = 0 in
4246class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4247                  RegisterClass regtype, string asm>
4248    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4249                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4250      Sched<[WriteLD]>;
4251
4252class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4253                    RegisterClass regtype, string asm>
4254    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4255                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4256      Sched<[WriteLD]>;
4257
4258class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4259                       RegisterClass regtype, string asm>
4260    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4261                             (outs regtype:$Rt, regtype:$Rt2),
4262                             (ins GPR64sp0:$Rn), asm,
4263                             "\t$Rt, $Rt2, [$Rn]">,
4264      Sched<[WriteLD, WriteLDHi]> {
4265  bits<5> Rt;
4266  bits<5> Rt2;
4267  bits<5> Rn;
4268  let Inst{14-10} = Rt2;
4269  let Inst{9-5} = Rn;
4270  let Inst{4-0} = Rt;
4271
4272  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4273}
4274
4275// Simple store release operations do not check the exclusive monitor.
4276let mayLoad = 0, mayStore = 1 in
4277class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4278                   RegisterClass regtype, string asm>
4279    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4280                               (ins regtype:$Rt, GPR64sp0:$Rn),
4281                               asm, "\t$Rt, [$Rn]">,
4282      Sched<[WriteST]>;
4283
4284let mayLoad = 1, mayStore = 1 in
4285class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4286                     RegisterClass regtype, string asm>
4287    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4288                             (ins regtype:$Rt, GPR64sp0:$Rn),
4289                             asm, "\t$Ws, $Rt, [$Rn]">,
4290      Sched<[WriteSTX]> {
4291  bits<5> Ws;
4292  bits<5> Rt;
4293  bits<5> Rn;
4294  let Inst{20-16} = Ws;
4295  let Inst{9-5} = Rn;
4296  let Inst{4-0} = Rt;
4297
4298  let Constraints = "@earlyclobber $Ws";
4299  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4300}
4301
4302class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4303                         RegisterClass regtype, string asm>
4304    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4305                             (outs GPR32:$Ws),
4306                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4307                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4308      Sched<[WriteSTX]> {
4309  bits<5> Ws;
4310  bits<5> Rt;
4311  bits<5> Rt2;
4312  bits<5> Rn;
4313  let Inst{20-16} = Ws;
4314  let Inst{14-10} = Rt2;
4315  let Inst{9-5} = Rn;
4316  let Inst{4-0} = Rt;
4317
4318  let Constraints = "@earlyclobber $Ws";
4319}
4320
4321// Armv8.5-A Memory Tagging Extension
4322class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4323                 string asm_opnds, string cstr, dag oops, dag iops>
4324    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4325      Sched<[]> {
4326  bits<5> Rn;
4327
4328  let Inst{31-24} = 0b11011001;
4329  let Inst{23-22} = opc1;
4330  let Inst{21}    = 1;
4331  // Inst{20-12} defined by subclass
4332  let Inst{11-10} = opc2;
4333  let Inst{9-5}   = Rn;
4334  // Inst{4-0} defined by subclass
4335}
4336
4337class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4338                   dag oops, dag iops>
4339    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4340                  "", oops, iops> {
4341  bits<5> Rt;
4342
4343  let Inst{20-12} = 0b000000000;
4344  let Inst{4-0}   = Rt;
4345
4346  let mayLoad = Load;
4347}
4348
4349class MemTagLoad<string asm_insn, string asm_opnds>
4350    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4351                 (outs GPR64:$wback),
4352                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4353  bits<5> Rt;
4354  bits<9> offset;
4355
4356  let Inst{20-12} = offset;
4357  let Inst{4-0}   = Rt;
4358
4359  let mayLoad = 1;
4360}
4361
4362class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4363                     string asm_opnds, string cstr, dag oops, dag iops>
4364    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4365  bits<5> Rt;
4366  bits<9> offset;
4367
4368  let Inst{20-12} = offset;
4369  let Inst{4-0}   = Rt;
4370
4371  let mayStore = 1;
4372}
4373
4374multiclass MemTagStore<bits<2> opc1, string insn> {
4375  def Offset :
4376    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4377                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4378  def PreIndex :
4379    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4380                    "$Rn = $wback",
4381                    (outs GPR64sp:$wback),
4382                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4383  def PostIndex :
4384    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4385                    "$Rn = $wback",
4386                    (outs GPR64sp:$wback),
4387                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4388
4389  def : InstAlias<insn # "\t$Rt, [$Rn]",
4390                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4391}
4392
4393//---
4394// Exception generation
4395//---
4396
4397let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4398class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4399    : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4400      Sched<[WriteSys]> {
4401  bits<16> imm;
4402  let Inst{31-24} = 0b11010100;
4403  let Inst{23-21} = op1;
4404  let Inst{20-5}  = imm;
4405  let Inst{4-2}   = 0b000;
4406  let Inst{1-0}   = ll;
4407}
4408
4409//---
4410// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4411//--
4412let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4413class UDFType<bits<16> opc, string asm>
4414  : I<(outs), (ins uimm16:$imm),
4415       asm, "\t$imm", "", []>,
4416    Sched<[]> {
4417  bits<16> imm;
4418  let Inst{31-16} = opc;
4419  let Inst{15-0} = imm;
4420}
4421}
4422let Predicates = [HasFPARMv8] in {
4423
4424//---
4425// Floating point to integer conversion
4426//---
4427
4428class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4429                      RegisterClass srcType, RegisterClass dstType,
4430                      string asm, list<dag> pattern>
4431    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4432         asm, "\t$Rd, $Rn", "", pattern>,
4433      Sched<[WriteFCvt]> {
4434  bits<5> Rd;
4435  bits<5> Rn;
4436  let Inst{30-29} = 0b00;
4437  let Inst{28-24} = 0b11110;
4438  let Inst{23-22} = type;
4439  let Inst{21}    = 1;
4440  let Inst{20-19} = rmode;
4441  let Inst{18-16} = opcode;
4442  let Inst{15-10} = 0;
4443  let Inst{9-5}   = Rn;
4444  let Inst{4-0}   = Rd;
4445}
4446
4447let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4448class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4449                      RegisterClass srcType, RegisterClass dstType,
4450                      Operand immType, string asm, list<dag> pattern>
4451    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4452         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4453      Sched<[WriteFCvt]> {
4454  bits<5> Rd;
4455  bits<5> Rn;
4456  bits<6> scale;
4457  let Inst{30-29} = 0b00;
4458  let Inst{28-24} = 0b11110;
4459  let Inst{23-22} = type;
4460  let Inst{21}    = 0;
4461  let Inst{20-19} = rmode;
4462  let Inst{18-16} = opcode;
4463  let Inst{15-10} = scale;
4464  let Inst{9-5}   = Rn;
4465  let Inst{4-0}   = Rd;
4466}
4467
4468multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4469           SDPatternOperator OpN> {
4470  // Unscaled half-precision to 32-bit
4471  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4472                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4473    let Inst{31} = 0; // 32-bit GPR flag
4474    let Predicates = [HasFullFP16];
4475  }
4476
4477  // Unscaled half-precision to 64-bit
4478  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4479                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4480    let Inst{31} = 1; // 64-bit GPR flag
4481    let Predicates = [HasFullFP16];
4482  }
4483
4484  // Unscaled single-precision to 32-bit
4485  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4486                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4487    let Inst{31} = 0; // 32-bit GPR flag
4488  }
4489
4490  // Unscaled single-precision to 64-bit
4491  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4492                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4493    let Inst{31} = 1; // 64-bit GPR flag
4494  }
4495
4496  // Unscaled double-precision to 32-bit
4497  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4498                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4499    let Inst{31} = 0; // 32-bit GPR flag
4500  }
4501
4502  // Unscaled double-precision to 64-bit
4503  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4504                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4505    let Inst{31} = 1; // 64-bit GPR flag
4506  }
4507}
4508
4509multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4510                             SDPatternOperator OpN> {
4511  // Scaled half-precision to 32-bit
4512  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4513                              fixedpoint_f16_i32, asm,
4514              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4515                                          fixedpoint_f16_i32:$scale)))]> {
4516    let Inst{31} = 0; // 32-bit GPR flag
4517    let scale{5} = 1;
4518    let Predicates = [HasFullFP16];
4519  }
4520
4521  // Scaled half-precision to 64-bit
4522  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4523                              fixedpoint_f16_i64, asm,
4524              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4525                                          fixedpoint_f16_i64:$scale)))]> {
4526    let Inst{31} = 1; // 64-bit GPR flag
4527    let Predicates = [HasFullFP16];
4528  }
4529
4530  // Scaled single-precision to 32-bit
4531  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4532                              fixedpoint_f32_i32, asm,
4533              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4534                                          fixedpoint_f32_i32:$scale)))]> {
4535    let Inst{31} = 0; // 32-bit GPR flag
4536    let scale{5} = 1;
4537  }
4538
4539  // Scaled single-precision to 64-bit
4540  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4541                              fixedpoint_f32_i64, asm,
4542              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4543                                          fixedpoint_f32_i64:$scale)))]> {
4544    let Inst{31} = 1; // 64-bit GPR flag
4545  }
4546
4547  // Scaled double-precision to 32-bit
4548  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4549                              fixedpoint_f64_i32, asm,
4550              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4551                                          fixedpoint_f64_i32:$scale)))]> {
4552    let Inst{31} = 0; // 32-bit GPR flag
4553    let scale{5} = 1;
4554  }
4555
4556  // Scaled double-precision to 64-bit
4557  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4558                              fixedpoint_f64_i64, asm,
4559              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4560                                          fixedpoint_f64_i64:$scale)))]> {
4561    let Inst{31} = 1; // 64-bit GPR flag
4562  }
4563}
4564
4565//---
4566// Integer to floating point conversion
4567//---
4568
4569let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4570class BaseIntegerToFP<bit isUnsigned,
4571                      RegisterClass srcType, RegisterClass dstType,
4572                      Operand immType, string asm, list<dag> pattern>
4573    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4574         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4575      Sched<[WriteFCvt]> {
4576  bits<5> Rd;
4577  bits<5> Rn;
4578  bits<6> scale;
4579  let Inst{30-24} = 0b0011110;
4580  let Inst{21-17} = 0b00001;
4581  let Inst{16}    = isUnsigned;
4582  let Inst{15-10} = scale;
4583  let Inst{9-5}   = Rn;
4584  let Inst{4-0}   = Rd;
4585}
4586
4587class BaseIntegerToFPUnscaled<bit isUnsigned,
4588                      RegisterClass srcType, RegisterClass dstType,
4589                      ValueType dvt, string asm, SDNode node>
4590    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4591         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4592      Sched<[WriteFCvt]> {
4593  bits<5> Rd;
4594  bits<5> Rn;
4595  bits<6> scale;
4596  let Inst{30-24} = 0b0011110;
4597  let Inst{21-17} = 0b10001;
4598  let Inst{16}    = isUnsigned;
4599  let Inst{15-10} = 0b000000;
4600  let Inst{9-5}   = Rn;
4601  let Inst{4-0}   = Rd;
4602}
4603
4604multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4605  // Unscaled
4606  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4607    let Inst{31} = 0; // 32-bit GPR flag
4608    let Inst{23-22} = 0b11; // 16-bit FPR flag
4609    let Predicates = [HasFullFP16];
4610  }
4611
4612  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4613    let Inst{31} = 0; // 32-bit GPR flag
4614    let Inst{23-22} = 0b00; // 32-bit FPR flag
4615  }
4616
4617  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4618    let Inst{31} = 0; // 32-bit GPR flag
4619    let Inst{23-22} = 0b01; // 64-bit FPR flag
4620  }
4621
4622  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4623    let Inst{31} = 1; // 64-bit GPR flag
4624    let Inst{23-22} = 0b11; // 16-bit FPR flag
4625    let Predicates = [HasFullFP16];
4626  }
4627
4628  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4629    let Inst{31} = 1; // 64-bit GPR flag
4630    let Inst{23-22} = 0b00; // 32-bit FPR flag
4631  }
4632
4633  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4634    let Inst{31} = 1; // 64-bit GPR flag
4635    let Inst{23-22} = 0b01; // 64-bit FPR flag
4636  }
4637
4638  // Scaled
4639  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4640                             [(set (f16 FPR16:$Rd),
4641                                   (fdiv (node GPR32:$Rn),
4642                                         fixedpoint_f16_i32:$scale))]> {
4643    let Inst{31} = 0; // 32-bit GPR flag
4644    let Inst{23-22} = 0b11; // 16-bit FPR flag
4645    let scale{5} = 1;
4646    let Predicates = [HasFullFP16];
4647  }
4648
4649  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4650                             [(set FPR32:$Rd,
4651                                   (fdiv (node GPR32:$Rn),
4652                                         fixedpoint_f32_i32:$scale))]> {
4653    let Inst{31} = 0; // 32-bit GPR flag
4654    let Inst{23-22} = 0b00; // 32-bit FPR flag
4655    let scale{5} = 1;
4656  }
4657
4658  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4659                             [(set FPR64:$Rd,
4660                                   (fdiv (node GPR32:$Rn),
4661                                         fixedpoint_f64_i32:$scale))]> {
4662    let Inst{31} = 0; // 32-bit GPR flag
4663    let Inst{23-22} = 0b01; // 64-bit FPR flag
4664    let scale{5} = 1;
4665  }
4666
4667  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4668                             [(set (f16 FPR16:$Rd),
4669                                   (fdiv (node GPR64:$Rn),
4670                                         fixedpoint_f16_i64:$scale))]> {
4671    let Inst{31} = 1; // 64-bit GPR flag
4672    let Inst{23-22} = 0b11; // 16-bit FPR flag
4673    let Predicates = [HasFullFP16];
4674  }
4675
4676  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4677                             [(set FPR32:$Rd,
4678                                   (fdiv (node GPR64:$Rn),
4679                                         fixedpoint_f32_i64:$scale))]> {
4680    let Inst{31} = 1; // 64-bit GPR flag
4681    let Inst{23-22} = 0b00; // 32-bit FPR flag
4682  }
4683
4684  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4685                             [(set FPR64:$Rd,
4686                                   (fdiv (node GPR64:$Rn),
4687                                         fixedpoint_f64_i64:$scale))]> {
4688    let Inst{31} = 1; // 64-bit GPR flag
4689    let Inst{23-22} = 0b01; // 64-bit FPR flag
4690  }
4691}
4692
4693//---
4694// Unscaled integer <-> floating point conversion (i.e. FMOV)
4695//---
4696
4697let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4698class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4699                      RegisterClass srcType, RegisterClass dstType,
4700                      string asm>
4701    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4702        // We use COPY_TO_REGCLASS for these bitconvert operations.
4703        // copyPhysReg() expands the resultant COPY instructions after
4704        // regalloc is done. This gives greater freedom for the allocator
4705        // and related passes (coalescing, copy propagation, et. al.) to
4706        // be more effective.
4707        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4708      Sched<[WriteFCopy]> {
4709  bits<5> Rd;
4710  bits<5> Rn;
4711  let Inst{30-24} = 0b0011110;
4712  let Inst{21}    = 1;
4713  let Inst{20-19} = rmode;
4714  let Inst{18-16} = opcode;
4715  let Inst{15-10} = 0b000000;
4716  let Inst{9-5}   = Rn;
4717  let Inst{4-0}   = Rd;
4718}
4719
4720let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4721class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4722                     RegisterClass srcType, RegisterOperand dstType, string asm,
4723                     string kind>
4724    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4725        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4726      Sched<[WriteFCopy]> {
4727  bits<5> Rd;
4728  bits<5> Rn;
4729  let Inst{30-23} = 0b00111101;
4730  let Inst{21}    = 1;
4731  let Inst{20-19} = rmode;
4732  let Inst{18-16} = opcode;
4733  let Inst{15-10} = 0b000000;
4734  let Inst{9-5}   = Rn;
4735  let Inst{4-0}   = Rd;
4736
4737  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4738}
4739
4740let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4741class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4742                     RegisterOperand srcType, RegisterClass dstType, string asm,
4743                     string kind>
4744    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4745        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4746      Sched<[WriteFCopy]> {
4747  bits<5> Rd;
4748  bits<5> Rn;
4749  let Inst{30-23} = 0b00111101;
4750  let Inst{21}    = 1;
4751  let Inst{20-19} = rmode;
4752  let Inst{18-16} = opcode;
4753  let Inst{15-10} = 0b000000;
4754  let Inst{9-5}   = Rn;
4755  let Inst{4-0}   = Rd;
4756
4757  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4758}
4759
4760
4761multiclass UnscaledConversion<string asm> {
4762  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4763    let Inst{31} = 0; // 32-bit GPR flag
4764    let Inst{23-22} = 0b11; // 16-bit FPR flag
4765    let Predicates = [HasFullFP16];
4766  }
4767
4768  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4769    let Inst{31} = 1; // 64-bit GPR flag
4770    let Inst{23-22} = 0b11; // 16-bit FPR flag
4771    let Predicates = [HasFullFP16];
4772  }
4773
4774  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4775    let Inst{31} = 0; // 32-bit GPR flag
4776    let Inst{23-22} = 0b00; // 32-bit FPR flag
4777  }
4778
4779  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4780    let Inst{31} = 1; // 64-bit GPR flag
4781    let Inst{23-22} = 0b01; // 64-bit FPR flag
4782  }
4783
4784  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4785    let Inst{31} = 0; // 32-bit GPR flag
4786    let Inst{23-22} = 0b11; // 16-bit FPR flag
4787    let Predicates = [HasFullFP16];
4788  }
4789
4790  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4791    let Inst{31} = 1; // 64-bit GPR flag
4792    let Inst{23-22} = 0b11; // 16-bit FPR flag
4793    let Predicates = [HasFullFP16];
4794  }
4795
4796  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4797    let Inst{31} = 0; // 32-bit GPR flag
4798    let Inst{23-22} = 0b00; // 32-bit FPR flag
4799  }
4800
4801  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4802    let Inst{31} = 1; // 64-bit GPR flag
4803    let Inst{23-22} = 0b01; // 64-bit FPR flag
4804  }
4805
4806  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4807                                             asm, ".d"> {
4808    let Inst{31} = 1;
4809    let Inst{22} = 0;
4810  }
4811
4812  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4813                                               asm, ".d"> {
4814    let Inst{31} = 1;
4815    let Inst{22} = 0;
4816  }
4817}
4818
4819//---
4820// Floating point conversion
4821//---
4822
4823class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4824                       RegisterClass srcType, string asm, list<dag> pattern>
4825    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4826      Sched<[WriteFCvt]> {
4827  bits<5> Rd;
4828  bits<5> Rn;
4829  let Inst{31-24} = 0b00011110;
4830  let Inst{23-22} = type;
4831  let Inst{21-17} = 0b10001;
4832  let Inst{16-15} = opcode;
4833  let Inst{14-10} = 0b10000;
4834  let Inst{9-5}   = Rn;
4835  let Inst{4-0}   = Rd;
4836}
4837
4838multiclass FPConversion<string asm> {
4839  // Double-precision to Half-precision
4840  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4841                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4842
4843  // Double-precision to Single-precision
4844  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4845                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4846
4847  // Half-precision to Double-precision
4848  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4849                             [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4850
4851  // Half-precision to Single-precision
4852  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4853                             [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4854
4855  // Single-precision to Double-precision
4856  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4857                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4858
4859  // Single-precision to Half-precision
4860  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4861                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4862}
4863
4864//---
4865// Single operand floating point data processing
4866//---
4867
4868let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4869class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4870                              ValueType vt, string asm, SDPatternOperator node>
4871    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4872         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4873      Sched<[WriteF]> {
4874  bits<5> Rd;
4875  bits<5> Rn;
4876  let Inst{31-24} = 0b00011110;
4877  let Inst{21}    = 0b1;
4878  let Inst{20-15} = opcode;
4879  let Inst{14-10} = 0b10000;
4880  let Inst{9-5}   = Rn;
4881  let Inst{4-0}   = Rd;
4882}
4883
4884multiclass SingleOperandFPData<bits<4> opcode, string asm,
4885                               SDPatternOperator node = null_frag> {
4886
4887  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4888    let Inst{23-22} = 0b11; // 16-bit size flag
4889    let Predicates = [HasFullFP16];
4890  }
4891
4892  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4893    let Inst{23-22} = 0b00; // 32-bit size flag
4894  }
4895
4896  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4897    let Inst{23-22} = 0b01; // 64-bit size flag
4898  }
4899}
4900
4901multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4902                  SDPatternOperator node = null_frag>{
4903
4904  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4905    let Inst{23-22} = 0b00; // 32-bit registers
4906  }
4907
4908  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4909    let Inst{23-22} = 0b01; // 64-bit registers
4910  }
4911}
4912
4913// FRInt[32|64][Z|N] instructions
4914multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4915      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4916
4917//---
4918// Two operand floating point data processing
4919//---
4920
4921let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4922class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4923                           string asm, list<dag> pat>
4924    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4925         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4926      Sched<[WriteF]> {
4927  bits<5> Rd;
4928  bits<5> Rn;
4929  bits<5> Rm;
4930  let Inst{31-24} = 0b00011110;
4931  let Inst{21}    = 1;
4932  let Inst{20-16} = Rm;
4933  let Inst{15-12} = opcode;
4934  let Inst{11-10} = 0b10;
4935  let Inst{9-5}   = Rn;
4936  let Inst{4-0}   = Rd;
4937}
4938
4939multiclass TwoOperandFPData<bits<4> opcode, string asm,
4940                            SDPatternOperator node = null_frag> {
4941  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4942                         [(set (f16 FPR16:$Rd),
4943                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4944    let Inst{23-22} = 0b11; // 16-bit size flag
4945    let Predicates = [HasFullFP16];
4946  }
4947
4948  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4949                         [(set (f32 FPR32:$Rd),
4950                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4951    let Inst{23-22} = 0b00; // 32-bit size flag
4952  }
4953
4954  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4955                         [(set (f64 FPR64:$Rd),
4956                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4957    let Inst{23-22} = 0b01; // 64-bit size flag
4958  }
4959}
4960
4961multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4962  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4963                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
4964    let Inst{23-22} = 0b11; // 16-bit size flag
4965    let Predicates = [HasFullFP16];
4966  }
4967
4968  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4969                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4970    let Inst{23-22} = 0b00; // 32-bit size flag
4971  }
4972
4973  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4974                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4975    let Inst{23-22} = 0b01; // 64-bit size flag
4976  }
4977}
4978
4979
4980//---
4981// Three operand floating point data processing
4982//---
4983
4984class BaseThreeOperandFPData<bit isNegated, bit isSub,
4985                             RegisterClass regtype, string asm, list<dag> pat>
4986    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4987         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4988      Sched<[WriteFMul]> {
4989  bits<5> Rd;
4990  bits<5> Rn;
4991  bits<5> Rm;
4992  bits<5> Ra;
4993  let Inst{31-24} = 0b00011111;
4994  let Inst{21}    = isNegated;
4995  let Inst{20-16} = Rm;
4996  let Inst{15}    = isSub;
4997  let Inst{14-10} = Ra;
4998  let Inst{9-5}   = Rn;
4999  let Inst{4-0}   = Rd;
5000}
5001
5002multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5003                              SDPatternOperator node> {
5004  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5005            [(set (f16 FPR16:$Rd),
5006                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5007    let Inst{23-22} = 0b11; // 16-bit size flag
5008    let Predicates = [HasFullFP16];
5009  }
5010
5011  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5012            [(set FPR32:$Rd,
5013                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5014    let Inst{23-22} = 0b00; // 32-bit size flag
5015  }
5016
5017  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5018            [(set FPR64:$Rd,
5019                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5020    let Inst{23-22} = 0b01; // 64-bit size flag
5021  }
5022}
5023
5024//---
5025// Floating point data comparisons
5026//---
5027
5028let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5029class BaseOneOperandFPComparison<bit signalAllNans,
5030                                 RegisterClass regtype, string asm,
5031                                 list<dag> pat>
5032    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5033      Sched<[WriteFCmp]> {
5034  bits<5> Rn;
5035  let Inst{31-24} = 0b00011110;
5036  let Inst{21}    = 1;
5037
5038  let Inst{15-10} = 0b001000;
5039  let Inst{9-5}   = Rn;
5040  let Inst{4}     = signalAllNans;
5041  let Inst{3-0}   = 0b1000;
5042
5043  // Rm should be 0b00000 canonically, but we need to accept any value.
5044  let PostEncoderMethod = "fixOneOperandFPComparison";
5045}
5046
5047let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5048class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5049                                string asm, list<dag> pat>
5050    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5051      Sched<[WriteFCmp]> {
5052  bits<5> Rm;
5053  bits<5> Rn;
5054  let Inst{31-24} = 0b00011110;
5055  let Inst{21}    = 1;
5056  let Inst{20-16} = Rm;
5057  let Inst{15-10} = 0b001000;
5058  let Inst{9-5}   = Rn;
5059  let Inst{4}     = signalAllNans;
5060  let Inst{3-0}   = 0b0000;
5061}
5062
5063multiclass FPComparison<bit signalAllNans, string asm,
5064                        SDPatternOperator OpNode = null_frag> {
5065  let Defs = [NZCV] in {
5066  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5067      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5068    let Inst{23-22} = 0b11;
5069    let Predicates = [HasFullFP16];
5070  }
5071
5072  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5073      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5074    let Inst{23-22} = 0b11;
5075    let Predicates = [HasFullFP16];
5076  }
5077
5078  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5079      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5080    let Inst{23-22} = 0b00;
5081  }
5082
5083  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5084      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5085    let Inst{23-22} = 0b00;
5086  }
5087
5088  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5089      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5090    let Inst{23-22} = 0b01;
5091  }
5092
5093  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5094      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5095    let Inst{23-22} = 0b01;
5096  }
5097  } // Defs = [NZCV]
5098}
5099
5100//---
5101// Floating point conditional comparisons
5102//---
5103
5104let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5105class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5106                           string mnemonic, list<dag> pat>
5107    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5108         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5109      Sched<[WriteFCmp]> {
5110  let Uses = [NZCV];
5111  let Defs = [NZCV];
5112
5113  bits<5> Rn;
5114  bits<5> Rm;
5115  bits<4> nzcv;
5116  bits<4> cond;
5117
5118  let Inst{31-24} = 0b00011110;
5119  let Inst{21}    = 1;
5120  let Inst{20-16} = Rm;
5121  let Inst{15-12} = cond;
5122  let Inst{11-10} = 0b01;
5123  let Inst{9-5}   = Rn;
5124  let Inst{4}     = signalAllNans;
5125  let Inst{3-0}   = nzcv;
5126}
5127
5128multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5129                            SDPatternOperator OpNode = null_frag> {
5130  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5131      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5132                          (i32 imm:$cond), NZCV))]> {
5133    let Inst{23-22} = 0b11;
5134    let Predicates = [HasFullFP16];
5135  }
5136
5137  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5138      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5139                          (i32 imm:$cond), NZCV))]> {
5140    let Inst{23-22} = 0b00;
5141  }
5142
5143  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5144      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5145                          (i32 imm:$cond), NZCV))]> {
5146    let Inst{23-22} = 0b01;
5147  }
5148}
5149
5150//---
5151// Floating point conditional select
5152//---
5153
5154class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5155    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5156         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5157         [(set regtype:$Rd,
5158               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5159                          (i32 imm:$cond), NZCV))]>,
5160      Sched<[WriteF]> {
5161  bits<5> Rd;
5162  bits<5> Rn;
5163  bits<5> Rm;
5164  bits<4> cond;
5165
5166  let Inst{31-24} = 0b00011110;
5167  let Inst{21}    = 1;
5168  let Inst{20-16} = Rm;
5169  let Inst{15-12} = cond;
5170  let Inst{11-10} = 0b11;
5171  let Inst{9-5}   = Rn;
5172  let Inst{4-0}   = Rd;
5173}
5174
5175multiclass FPCondSelect<string asm> {
5176  let Uses = [NZCV] in {
5177  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5178    let Inst{23-22} = 0b11;
5179    let Predicates = [HasFullFP16];
5180  }
5181
5182  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5183    let Inst{23-22} = 0b00;
5184  }
5185
5186  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5187    let Inst{23-22} = 0b01;
5188  }
5189  } // Uses = [NZCV]
5190}
5191
5192//---
5193// Floating move immediate
5194//---
5195
5196class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5197  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5198      [(set regtype:$Rd, fpimmtype:$imm)]>,
5199    Sched<[WriteFImm]> {
5200  bits<5> Rd;
5201  bits<8> imm;
5202  let Inst{31-24} = 0b00011110;
5203  let Inst{21}    = 1;
5204  let Inst{20-13} = imm;
5205  let Inst{12-5}  = 0b10000000;
5206  let Inst{4-0}   = Rd;
5207}
5208
5209multiclass FPMoveImmediate<string asm> {
5210  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5211    let Inst{23-22} = 0b11;
5212    let Predicates = [HasFullFP16];
5213  }
5214
5215  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5216    let Inst{23-22} = 0b00;
5217  }
5218
5219  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5220    let Inst{23-22} = 0b01;
5221  }
5222}
5223} // end of 'let Predicates = [HasFPARMv8]'
5224
5225//----------------------------------------------------------------------------
5226// AdvSIMD
5227//----------------------------------------------------------------------------
5228
5229let Predicates = [HasNEON] in {
5230
5231//----------------------------------------------------------------------------
5232// AdvSIMD three register vector instructions
5233//----------------------------------------------------------------------------
5234
5235let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5236class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5237                        RegisterOperand regtype, string asm, string kind,
5238                        list<dag> pattern>
5239  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5240      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5241      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5242    Sched<[WriteV]> {
5243  bits<5> Rd;
5244  bits<5> Rn;
5245  bits<5> Rm;
5246  let Inst{31}    = 0;
5247  let Inst{30}    = Q;
5248  let Inst{29}    = U;
5249  let Inst{28-24} = 0b01110;
5250  let Inst{23-21} = size;
5251  let Inst{20-16} = Rm;
5252  let Inst{15-11} = opcode;
5253  let Inst{10}    = 1;
5254  let Inst{9-5}   = Rn;
5255  let Inst{4-0}   = Rd;
5256}
5257
5258let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5259class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5260                        RegisterOperand regtype, string asm, string kind,
5261                        list<dag> pattern>
5262  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5263      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5264      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5265    Sched<[WriteV]> {
5266  bits<5> Rd;
5267  bits<5> Rn;
5268  bits<5> Rm;
5269  let Inst{31}    = 0;
5270  let Inst{30}    = Q;
5271  let Inst{29}    = U;
5272  let Inst{28-24} = 0b01110;
5273  let Inst{23-21} = size;
5274  let Inst{20-16} = Rm;
5275  let Inst{15-11} = opcode;
5276  let Inst{10}    = 1;
5277  let Inst{9-5}   = Rn;
5278  let Inst{4-0}   = Rd;
5279}
5280
5281let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5282class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5283  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5284    Sched<[WriteV]>;
5285
5286multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5287  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5288             [(set (v8i8 V64:$dst),
5289                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5290  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5291             [(set (v16i8 V128:$dst),
5292                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5293                           (v16i8 V128:$Rm)))]>;
5294
5295  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5296                           (v4i16 V64:$RHS))),
5297          (!cast<Instruction>(NAME#"v8i8")
5298            V64:$LHS, V64:$MHS, V64:$RHS)>;
5299  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5300                           (v2i32 V64:$RHS))),
5301          (!cast<Instruction>(NAME#"v8i8")
5302            V64:$LHS, V64:$MHS, V64:$RHS)>;
5303  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5304                           (v1i64 V64:$RHS))),
5305          (!cast<Instruction>(NAME#"v8i8")
5306            V64:$LHS, V64:$MHS, V64:$RHS)>;
5307
5308  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5309                           (v8i16 V128:$RHS))),
5310      (!cast<Instruction>(NAME#"v16i8")
5311        V128:$LHS, V128:$MHS, V128:$RHS)>;
5312  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5313                           (v4i32 V128:$RHS))),
5314      (!cast<Instruction>(NAME#"v16i8")
5315        V128:$LHS, V128:$MHS, V128:$RHS)>;
5316  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5317                           (v2i64 V128:$RHS))),
5318      (!cast<Instruction>(NAME#"v16i8")
5319        V128:$LHS, V128:$MHS, V128:$RHS)>;
5320}
5321
5322// All operand sizes distinguished in the encoding.
5323multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5324                               SDPatternOperator OpNode> {
5325  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5326                                      asm, ".8b",
5327         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5328  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5329                                      asm, ".16b",
5330         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5331  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5332                                      asm, ".4h",
5333         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5334  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5335                                      asm, ".8h",
5336         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5337  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5338                                      asm, ".2s",
5339         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5340  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5341                                      asm, ".4s",
5342         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5343  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5344                                      asm, ".2d",
5345         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5346}
5347
5348multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5349  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5350          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5351  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5352          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5353  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5354          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5355
5356  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5357          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5358  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5359          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5360  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5361          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5362  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5363          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5364}
5365
5366// As above, but D sized elements unsupported.
5367multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5368                                  SDPatternOperator OpNode> {
5369  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5370                                      asm, ".8b",
5371        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5372  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5373                                      asm, ".16b",
5374        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5375  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5376                                      asm, ".4h",
5377        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5378  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5379                                      asm, ".8h",
5380        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5381  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5382                                      asm, ".2s",
5383        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5384  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5385                                      asm, ".4s",
5386        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5387}
5388
5389multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5390                                  SDPatternOperator OpNode> {
5391  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5392                                      asm, ".8b",
5393      [(set (v8i8 V64:$dst),
5394            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5395  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5396                                      asm, ".16b",
5397      [(set (v16i8 V128:$dst),
5398            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5399  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5400                                      asm, ".4h",
5401      [(set (v4i16 V64:$dst),
5402            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5403  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5404                                      asm, ".8h",
5405      [(set (v8i16 V128:$dst),
5406            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5407  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5408                                      asm, ".2s",
5409      [(set (v2i32 V64:$dst),
5410            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5411  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5412                                      asm, ".4s",
5413      [(set (v4i32 V128:$dst),
5414            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5415}
5416
5417// As above, but only B sized elements supported.
5418multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5419                                SDPatternOperator OpNode> {
5420  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5421                                      asm, ".8b",
5422    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5423  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5424                                      asm, ".16b",
5425    [(set (v16i8 V128:$Rd),
5426          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5427}
5428
5429// As above, but only floating point elements supported.
5430multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5431                                 string asm, SDPatternOperator OpNode> {
5432  let Predicates = [HasNEON, HasFullFP16] in {
5433  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5434                                      asm, ".4h",
5435        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5436  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5437                                      asm, ".8h",
5438        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5439  } // Predicates = [HasNEON, HasFullFP16]
5440  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5441                                      asm, ".2s",
5442        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5443  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5444                                      asm, ".4s",
5445        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5446  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5447                                      asm, ".2d",
5448        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5449}
5450
5451multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5452                                    string asm,
5453                                    SDPatternOperator OpNode> {
5454  let Predicates = [HasNEON, HasFullFP16] in {
5455  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5456                                      asm, ".4h",
5457        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5458  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5459                                      asm, ".8h",
5460        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5461  } // Predicates = [HasNEON, HasFullFP16]
5462  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5463                                      asm, ".2s",
5464        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5465  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5466                                      asm, ".4s",
5467        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5468  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5469                                      asm, ".2d",
5470        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5471}
5472
5473multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5474                                 string asm, SDPatternOperator OpNode> {
5475  let Predicates = [HasNEON, HasFullFP16] in {
5476  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5477                                      asm, ".4h",
5478     [(set (v4f16 V64:$dst),
5479           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5480  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5481                                      asm, ".8h",
5482     [(set (v8f16 V128:$dst),
5483           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5484  } // Predicates = [HasNEON, HasFullFP16]
5485  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5486                                      asm, ".2s",
5487     [(set (v2f32 V64:$dst),
5488           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5489  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5490                                      asm, ".4s",
5491     [(set (v4f32 V128:$dst),
5492           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5493  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5494                                      asm, ".2d",
5495     [(set (v2f64 V128:$dst),
5496           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5497}
5498
5499// As above, but D and B sized elements unsupported.
5500multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5501                                SDPatternOperator OpNode> {
5502  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5503                                      asm, ".4h",
5504        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5505  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5506                                      asm, ".8h",
5507        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5508  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5509                                      asm, ".2s",
5510        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5511  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5512                                      asm, ".4s",
5513        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5514}
5515
5516// Logical three vector ops share opcode bits, and only use B sized elements.
5517multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5518                                  SDPatternOperator OpNode = null_frag> {
5519  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5520                                     asm, ".8b",
5521                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5522  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5523                                     asm, ".16b",
5524                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5525
5526  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5527          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5528  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5529          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5530  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5531          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5532
5533  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5534      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5535  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5536      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5537  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5538      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5539}
5540
5541multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5542                                  string asm, SDPatternOperator OpNode = null_frag> {
5543  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5544                                     asm, ".8b",
5545             [(set (v8i8 V64:$dst),
5546                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5547  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5548                                     asm, ".16b",
5549             [(set (v16i8 V128:$dst),
5550                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5551                           (v16i8 V128:$Rm)))]>;
5552
5553  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5554                           (v4i16 V64:$RHS))),
5555          (!cast<Instruction>(NAME#"v8i8")
5556            V64:$LHS, V64:$MHS, V64:$RHS)>;
5557  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5558                           (v2i32 V64:$RHS))),
5559          (!cast<Instruction>(NAME#"v8i8")
5560            V64:$LHS, V64:$MHS, V64:$RHS)>;
5561  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5562                           (v1i64 V64:$RHS))),
5563          (!cast<Instruction>(NAME#"v8i8")
5564            V64:$LHS, V64:$MHS, V64:$RHS)>;
5565
5566  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5567                           (v8i16 V128:$RHS))),
5568      (!cast<Instruction>(NAME#"v16i8")
5569        V128:$LHS, V128:$MHS, V128:$RHS)>;
5570  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5571                           (v4i32 V128:$RHS))),
5572      (!cast<Instruction>(NAME#"v16i8")
5573        V128:$LHS, V128:$MHS, V128:$RHS)>;
5574  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5575                           (v2i64 V128:$RHS))),
5576      (!cast<Instruction>(NAME#"v16i8")
5577        V128:$LHS, V128:$MHS, V128:$RHS)>;
5578}
5579
5580// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5581// bytes from S-sized elements.
5582class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5583                                 string kind2, RegisterOperand RegType,
5584                                 ValueType AccumType, ValueType InputType,
5585                                 SDPatternOperator OpNode> :
5586        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5587        [(set (AccumType RegType:$dst),
5588              (OpNode (AccumType RegType:$Rd),
5589                      (InputType RegType:$Rn),
5590                      (InputType RegType:$Rm)))]> {
5591  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5592}
5593
5594multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5595  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5596                                         v2i32, v8i8, OpNode>;
5597  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5598                                         v4i32, v16i8, OpNode>;
5599}
5600
5601// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5602// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5603// 8H to 4S, when Q=1).
5604class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5605                                 string kind2, RegisterOperand RegType,
5606                                 ValueType AccumType, ValueType InputType,
5607                                 SDPatternOperator OpNode> :
5608        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5609		[(set (AccumType RegType:$dst),
5610              (OpNode (AccumType RegType:$Rd),
5611                      (InputType RegType:$Rn),
5612                      (InputType RegType:$Rm)))]> {
5613  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5614  let Inst{13} = b13;
5615}
5616
5617multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5618                                  SDPatternOperator OpNode> {
5619  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5620                                         v2f32, v4f16, OpNode>;
5621  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5622                                         v4f32, v8f16, OpNode>;
5623}
5624
5625
5626//----------------------------------------------------------------------------
5627// AdvSIMD two register vector instructions.
5628//----------------------------------------------------------------------------
5629
5630let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5631class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5632                            bits<2> size2, RegisterOperand regtype, string asm,
5633                            string dstkind, string srckind, list<dag> pattern>
5634  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5635      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5636      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5637    Sched<[WriteV]> {
5638  bits<5> Rd;
5639  bits<5> Rn;
5640  let Inst{31}    = 0;
5641  let Inst{30}    = Q;
5642  let Inst{29}    = U;
5643  let Inst{28-24} = 0b01110;
5644  let Inst{23-22} = size;
5645  let Inst{21} = 0b1;
5646  let Inst{20-19} = size2;
5647  let Inst{18-17} = 0b00;
5648  let Inst{16-12} = opcode;
5649  let Inst{11-10} = 0b10;
5650  let Inst{9-5}   = Rn;
5651  let Inst{4-0}   = Rd;
5652}
5653
5654let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5655class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5656                                bits<2> size2, RegisterOperand regtype,
5657                                string asm, string dstkind, string srckind,
5658                                list<dag> pattern>
5659  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5660      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5661      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5662    Sched<[WriteV]> {
5663  bits<5> Rd;
5664  bits<5> Rn;
5665  let Inst{31}    = 0;
5666  let Inst{30}    = Q;
5667  let Inst{29}    = U;
5668  let Inst{28-24} = 0b01110;
5669  let Inst{23-22} = size;
5670  let Inst{21} = 0b1;
5671  let Inst{20-19} = size2;
5672  let Inst{18-17} = 0b00;
5673  let Inst{16-12} = opcode;
5674  let Inst{11-10} = 0b10;
5675  let Inst{9-5}   = Rn;
5676  let Inst{4-0}   = Rd;
5677}
5678
5679// Supports B, H, and S element sizes.
5680multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5681                            SDPatternOperator OpNode> {
5682  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5683                                      asm, ".8b", ".8b",
5684                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5685  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5686                                      asm, ".16b", ".16b",
5687                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5688  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5689                                      asm, ".4h", ".4h",
5690                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5691  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5692                                      asm, ".8h", ".8h",
5693                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5694  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5695                                      asm, ".2s", ".2s",
5696                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5697  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5698                                      asm, ".4s", ".4s",
5699                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5700}
5701
5702class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5703                            RegisterOperand regtype, string asm, string dstkind,
5704                            string srckind, string amount>
5705  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5706      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5707      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5708    Sched<[WriteV]> {
5709  bits<5> Rd;
5710  bits<5> Rn;
5711  let Inst{31}    = 0;
5712  let Inst{30}    = Q;
5713  let Inst{29-24} = 0b101110;
5714  let Inst{23-22} = size;
5715  let Inst{21-10} = 0b100001001110;
5716  let Inst{9-5}   = Rn;
5717  let Inst{4-0}   = Rd;
5718}
5719
5720multiclass SIMDVectorLShiftLongBySizeBHS {
5721  let hasSideEffects = 0 in {
5722  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5723                                             "shll", ".8h",  ".8b", "8">;
5724  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5725                                             "shll2", ".8h", ".16b", "8">;
5726  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5727                                             "shll", ".4s",  ".4h", "16">;
5728  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5729                                             "shll2", ".4s", ".8h", "16">;
5730  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5731                                             "shll", ".2d",  ".2s", "32">;
5732  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5733                                             "shll2", ".2d", ".4s", "32">;
5734  }
5735}
5736
5737// Supports all element sizes.
5738multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5739                             SDPatternOperator OpNode> {
5740  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5741                                      asm, ".4h", ".8b",
5742               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5743  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5744                                      asm, ".8h", ".16b",
5745               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5746  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5747                                      asm, ".2s", ".4h",
5748               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5749  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5750                                      asm, ".4s", ".8h",
5751               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5752  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5753                                      asm, ".1d", ".2s",
5754               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5755  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5756                                      asm, ".2d", ".4s",
5757               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5758}
5759
5760multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5761                                 SDPatternOperator OpNode> {
5762  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5763                                          asm, ".4h", ".8b",
5764      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5765                                      (v8i8 V64:$Rn)))]>;
5766  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5767                                          asm, ".8h", ".16b",
5768      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5769                                      (v16i8 V128:$Rn)))]>;
5770  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5771                                          asm, ".2s", ".4h",
5772      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5773                                      (v4i16 V64:$Rn)))]>;
5774  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5775                                          asm, ".4s", ".8h",
5776      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5777                                      (v8i16 V128:$Rn)))]>;
5778  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5779                                          asm, ".1d", ".2s",
5780      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5781                                      (v2i32 V64:$Rn)))]>;
5782  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5783                                          asm, ".2d", ".4s",
5784      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5785                                      (v4i32 V128:$Rn)))]>;
5786}
5787
5788// Supports all element sizes, except 1xD.
5789multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5790                                  SDPatternOperator OpNode> {
5791  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5792                                    asm, ".8b", ".8b",
5793    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5794  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5795                                    asm, ".16b", ".16b",
5796    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5797  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5798                                    asm, ".4h", ".4h",
5799    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5800  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5801                                    asm, ".8h", ".8h",
5802    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5803  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5804                                    asm, ".2s", ".2s",
5805    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5806  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5807                                    asm, ".4s", ".4s",
5808    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5809  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5810                                    asm, ".2d", ".2d",
5811    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5812}
5813
5814multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5815                             SDPatternOperator OpNode = null_frag> {
5816  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5817                                asm, ".8b", ".8b",
5818    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5819  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5820                                asm, ".16b", ".16b",
5821    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5822  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5823                                asm, ".4h", ".4h",
5824    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5825  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5826                                asm, ".8h", ".8h",
5827    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5828  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5829                                asm, ".2s", ".2s",
5830    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5831  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5832                                asm, ".4s", ".4s",
5833    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5834  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5835                                asm, ".2d", ".2d",
5836    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5837}
5838
5839
5840// Supports only B element sizes.
5841multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5842                          SDPatternOperator OpNode> {
5843  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5844                                asm, ".8b", ".8b",
5845                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5846  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5847                                asm, ".16b", ".16b",
5848                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5849
5850}
5851
5852// Supports only B and H element sizes.
5853multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5854                                SDPatternOperator OpNode> {
5855  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5856                                asm, ".8b", ".8b",
5857                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5858  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5859                                asm, ".16b", ".16b",
5860                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5861  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5862                                asm, ".4h", ".4h",
5863                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5864  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5865                                asm, ".8h", ".8h",
5866                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5867}
5868
5869// Supports H, S and D element sizes, uses high bit of the size field
5870// as an extra opcode bit.
5871multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5872                           SDPatternOperator OpNode> {
5873  let Predicates = [HasNEON, HasFullFP16] in {
5874  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5875                                asm, ".4h", ".4h",
5876                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5877  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5878                                asm, ".8h", ".8h",
5879                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5880  } // Predicates = [HasNEON, HasFullFP16]
5881  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5882                                asm, ".2s", ".2s",
5883                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5884  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5885                                asm, ".4s", ".4s",
5886                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5887  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5888                                asm, ".2d", ".2d",
5889                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5890}
5891
5892// Supports only S and D element sizes
5893multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5894                           SDPatternOperator OpNode = null_frag> {
5895
5896  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5897                                asm, ".2s", ".2s",
5898                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5899  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5900                                asm, ".4s", ".4s",
5901                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5902  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5903                                asm, ".2d", ".2d",
5904                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5905}
5906
5907multiclass FRIntNNTVector<bit U, bit op, string asm,
5908                          SDPatternOperator OpNode = null_frag> :
5909           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5910
5911// Supports only S element size.
5912multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5913                           SDPatternOperator OpNode> {
5914  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5915                                asm, ".2s", ".2s",
5916                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5917  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5918                                asm, ".4s", ".4s",
5919                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5920}
5921
5922
5923multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5924                           SDPatternOperator OpNode> {
5925  let Predicates = [HasNEON, HasFullFP16] in {
5926  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5927                                asm, ".4h", ".4h",
5928                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5929  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5930                                asm, ".8h", ".8h",
5931                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5932  } // Predicates = [HasNEON, HasFullFP16]
5933  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5934                                asm, ".2s", ".2s",
5935                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5936  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5937                                asm, ".4s", ".4s",
5938                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5939  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5940                                asm, ".2d", ".2d",
5941                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5942}
5943
5944multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5945                           SDPatternOperator OpNode> {
5946  let Predicates = [HasNEON, HasFullFP16] in {
5947  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5948                                asm, ".4h", ".4h",
5949                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5950  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5951                                asm, ".8h", ".8h",
5952                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5953  } // Predicates = [HasNEON, HasFullFP16]
5954  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5955                                asm, ".2s", ".2s",
5956                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5957  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5958                                asm, ".4s", ".4s",
5959                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5960  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5961                                asm, ".2d", ".2d",
5962                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5963}
5964
5965
5966class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5967                           RegisterOperand inreg, RegisterOperand outreg,
5968                           string asm, string outkind, string inkind,
5969                           list<dag> pattern>
5970  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5971      "{\t$Rd" # outkind # ", $Rn" # inkind #
5972      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5973    Sched<[WriteV]> {
5974  bits<5> Rd;
5975  bits<5> Rn;
5976  let Inst{31}    = 0;
5977  let Inst{30}    = Q;
5978  let Inst{29}    = U;
5979  let Inst{28-24} = 0b01110;
5980  let Inst{23-22} = size;
5981  let Inst{21-17} = 0b10000;
5982  let Inst{16-12} = opcode;
5983  let Inst{11-10} = 0b10;
5984  let Inst{9-5}   = Rn;
5985  let Inst{4-0}   = Rd;
5986}
5987
5988class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5989                           RegisterOperand inreg, RegisterOperand outreg,
5990                           string asm, string outkind, string inkind,
5991                           list<dag> pattern>
5992  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5993      "{\t$Rd" # outkind # ", $Rn" # inkind #
5994      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5995    Sched<[WriteV]> {
5996  bits<5> Rd;
5997  bits<5> Rn;
5998  let Inst{31}    = 0;
5999  let Inst{30}    = Q;
6000  let Inst{29}    = U;
6001  let Inst{28-24} = 0b01110;
6002  let Inst{23-22} = size;
6003  let Inst{21-17} = 0b10000;
6004  let Inst{16-12} = opcode;
6005  let Inst{11-10} = 0b10;
6006  let Inst{9-5}   = Rn;
6007  let Inst{4-0}   = Rd;
6008}
6009
6010multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6011                              SDPatternOperator OpNode> {
6012  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6013                                      asm, ".8b", ".8h",
6014        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6015  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6016                                      asm#"2", ".16b", ".8h", []>;
6017  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6018                                      asm, ".4h", ".4s",
6019        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6020  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6021                                      asm#"2", ".8h", ".4s", []>;
6022  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6023                                      asm, ".2s", ".2d",
6024        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6025  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6026                                      asm#"2", ".4s", ".2d", []>;
6027
6028  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6029            (!cast<Instruction>(NAME # "v16i8")
6030                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6031  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6032            (!cast<Instruction>(NAME # "v8i16")
6033                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6034  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6035            (!cast<Instruction>(NAME # "v4i32")
6036                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6037}
6038
6039class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6040                           bits<5> opcode, RegisterOperand regtype, string asm,
6041                           string kind, string zero, ValueType dty,
6042                           ValueType sty, SDNode OpNode>
6043  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6044      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6045      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6046      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6047    Sched<[WriteV]> {
6048  bits<5> Rd;
6049  bits<5> Rn;
6050  let Inst{31}    = 0;
6051  let Inst{30}    = Q;
6052  let Inst{29}    = U;
6053  let Inst{28-24} = 0b01110;
6054  let Inst{23-22} = size;
6055  let Inst{21} = 0b1;
6056  let Inst{20-19} = size2;
6057  let Inst{18-17} = 0b00;
6058  let Inst{16-12} = opcode;
6059  let Inst{11-10} = 0b10;
6060  let Inst{9-5}   = Rn;
6061  let Inst{4-0}   = Rd;
6062}
6063
6064// Comparisons support all element sizes, except 1xD.
6065multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6066                            SDNode OpNode> {
6067  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6068                                     asm, ".8b", "0",
6069                                     v8i8, v8i8, OpNode>;
6070  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6071                                     asm, ".16b", "0",
6072                                     v16i8, v16i8, OpNode>;
6073  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6074                                     asm, ".4h", "0",
6075                                     v4i16, v4i16, OpNode>;
6076  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6077                                     asm, ".8h", "0",
6078                                     v8i16, v8i16, OpNode>;
6079  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6080                                     asm, ".2s", "0",
6081                                     v2i32, v2i32, OpNode>;
6082  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6083                                     asm, ".4s", "0",
6084                                     v4i32, v4i32, OpNode>;
6085  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6086                                     asm, ".2d", "0",
6087                                     v2i64, v2i64, OpNode>;
6088}
6089
6090// FP Comparisons support only S and D element sizes (and H for v8.2a).
6091multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6092                              string asm, SDNode OpNode> {
6093
6094  let Predicates = [HasNEON, HasFullFP16] in {
6095  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6096                                     asm, ".4h", "0.0",
6097                                     v4i16, v4f16, OpNode>;
6098  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6099                                     asm, ".8h", "0.0",
6100                                     v8i16, v8f16, OpNode>;
6101  } // Predicates = [HasNEON, HasFullFP16]
6102  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6103                                     asm, ".2s", "0.0",
6104                                     v2i32, v2f32, OpNode>;
6105  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6106                                     asm, ".4s", "0.0",
6107                                     v4i32, v4f32, OpNode>;
6108  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6109                                     asm, ".2d", "0.0",
6110                                     v2i64, v2f64, OpNode>;
6111
6112  let Predicates = [HasNEON, HasFullFP16] in {
6113  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6114                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6115  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6116                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6117  }
6118  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6119                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6120  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6121                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6122  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6123                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6124  let Predicates = [HasNEON, HasFullFP16] in {
6125  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6126                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6127  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6128                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6129  }
6130  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6131                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6132  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6133                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6134  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6135                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6136}
6137
6138let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6139class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6140                             RegisterOperand outtype, RegisterOperand intype,
6141                             string asm, string VdTy, string VnTy,
6142                             list<dag> pattern>
6143  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6144      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6145    Sched<[WriteV]> {
6146  bits<5> Rd;
6147  bits<5> Rn;
6148  let Inst{31}    = 0;
6149  let Inst{30}    = Q;
6150  let Inst{29}    = U;
6151  let Inst{28-24} = 0b01110;
6152  let Inst{23-22} = size;
6153  let Inst{21-17} = 0b10000;
6154  let Inst{16-12} = opcode;
6155  let Inst{11-10} = 0b10;
6156  let Inst{9-5}   = Rn;
6157  let Inst{4-0}   = Rd;
6158}
6159
6160class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6161                             RegisterOperand outtype, RegisterOperand intype,
6162                             string asm, string VdTy, string VnTy,
6163                             list<dag> pattern>
6164  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6165      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6166    Sched<[WriteV]> {
6167  bits<5> Rd;
6168  bits<5> Rn;
6169  let Inst{31}    = 0;
6170  let Inst{30}    = Q;
6171  let Inst{29}    = U;
6172  let Inst{28-24} = 0b01110;
6173  let Inst{23-22} = size;
6174  let Inst{21-17} = 0b10000;
6175  let Inst{16-12} = opcode;
6176  let Inst{11-10} = 0b10;
6177  let Inst{9-5}   = Rn;
6178  let Inst{4-0}   = Rd;
6179}
6180
6181multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6182  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6183                                    asm, ".4s", ".4h", []>;
6184  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6185                                    asm#"2", ".4s", ".8h", []>;
6186  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6187                                    asm, ".2d", ".2s", []>;
6188  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6189                                    asm#"2", ".2d", ".4s", []>;
6190}
6191
6192multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6193  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6194                                    asm, ".4h", ".4s", []>;
6195  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6196                                    asm#"2", ".8h", ".4s", []>;
6197  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6198                                    asm, ".2s", ".2d", []>;
6199  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6200                                    asm#"2", ".4s", ".2d", []>;
6201}
6202
6203multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6204                                     Intrinsic OpNode> {
6205  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6206                                     asm, ".2s", ".2d",
6207                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6208  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6209                                    asm#"2", ".4s", ".2d", []>;
6210
6211  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6212            (!cast<Instruction>(NAME # "v4f32")
6213                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6214}
6215
6216//----------------------------------------------------------------------------
6217// AdvSIMD three register different-size vector instructions.
6218//----------------------------------------------------------------------------
6219
6220let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6221class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6222                      RegisterOperand outtype, RegisterOperand intype1,
6223                      RegisterOperand intype2, string asm,
6224                      string outkind, string inkind1, string inkind2,
6225                      list<dag> pattern>
6226  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6227      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6228      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6229    Sched<[WriteV]> {
6230  bits<5> Rd;
6231  bits<5> Rn;
6232  bits<5> Rm;
6233  let Inst{31}    = 0;
6234  let Inst{30}    = size{0};
6235  let Inst{29}    = U;
6236  let Inst{28-24} = 0b01110;
6237  let Inst{23-22} = size{2-1};
6238  let Inst{21}    = 1;
6239  let Inst{20-16} = Rm;
6240  let Inst{15-12} = opcode;
6241  let Inst{11-10} = 0b00;
6242  let Inst{9-5}   = Rn;
6243  let Inst{4-0}   = Rd;
6244}
6245
6246let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6247class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6248                      RegisterOperand outtype, RegisterOperand intype1,
6249                      RegisterOperand intype2, string asm,
6250                      string outkind, string inkind1, string inkind2,
6251                      list<dag> pattern>
6252  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6253      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6254      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6255    Sched<[WriteV]> {
6256  bits<5> Rd;
6257  bits<5> Rn;
6258  bits<5> Rm;
6259  let Inst{31}    = 0;
6260  let Inst{30}    = size{0};
6261  let Inst{29}    = U;
6262  let Inst{28-24} = 0b01110;
6263  let Inst{23-22} = size{2-1};
6264  let Inst{21}    = 1;
6265  let Inst{20-16} = Rm;
6266  let Inst{15-12} = opcode;
6267  let Inst{11-10} = 0b00;
6268  let Inst{9-5}   = Rn;
6269  let Inst{4-0}   = Rd;
6270}
6271
6272// FIXME: TableGen doesn't know how to deal with expanded types that also
6273//        change the element count (in this case, placing the results in
6274//        the high elements of the result register rather than the low
6275//        elements). Until that's fixed, we can't code-gen those.
6276multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6277                                    Intrinsic IntOp> {
6278  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6279                                                  V64, V128, V128,
6280                                                  asm, ".8b", ".8h", ".8h",
6281     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6282  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6283                                                  V128, V128, V128,
6284                                                  asm#"2", ".16b", ".8h", ".8h",
6285     []>;
6286  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6287                                                  V64, V128, V128,
6288                                                  asm, ".4h", ".4s", ".4s",
6289     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6290  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6291                                                  V128, V128, V128,
6292                                                  asm#"2", ".8h", ".4s", ".4s",
6293     []>;
6294  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6295                                                  V64, V128, V128,
6296                                                  asm, ".2s", ".2d", ".2d",
6297     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6298  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6299                                                  V128, V128, V128,
6300                                                  asm#"2", ".4s", ".2d", ".2d",
6301     []>;
6302
6303
6304  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6305  // a version attached to an instruction.
6306  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6307                                                   (v8i16 V128:$Rm))),
6308            (!cast<Instruction>(NAME # "v8i16_v16i8")
6309                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6310                V128:$Rn, V128:$Rm)>;
6311  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6312                                                    (v4i32 V128:$Rm))),
6313            (!cast<Instruction>(NAME # "v4i32_v8i16")
6314                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6315                V128:$Rn, V128:$Rm)>;
6316  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6317                                                    (v2i64 V128:$Rm))),
6318            (!cast<Instruction>(NAME # "v2i64_v4i32")
6319                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6320                V128:$Rn, V128:$Rm)>;
6321}
6322
6323multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6324                                      Intrinsic IntOp> {
6325  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6326                                            V128, V64, V64,
6327                                            asm, ".8h", ".8b", ".8b",
6328      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6329  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6330                                            V128, V128, V128,
6331                                            asm#"2", ".8h", ".16b", ".16b", []>;
6332  let Predicates = [HasAES] in {
6333    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6334                                              V128, V64, V64,
6335                                              asm, ".1q", ".1d", ".1d", []>;
6336    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6337                                              V128, V128, V128,
6338                                              asm#"2", ".1q", ".2d", ".2d", []>;
6339  }
6340
6341  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6342                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6343      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6344}
6345
6346multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6347                                 SDPatternOperator OpNode> {
6348  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6349                                                  V128, V64, V64,
6350                                                  asm, ".4s", ".4h", ".4h",
6351      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6352  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6353                                                  V128, V128, V128,
6354                                                  asm#"2", ".4s", ".8h", ".8h",
6355      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6356                                      (extract_high_v8i16 V128:$Rm)))]>;
6357  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6358                                                  V128, V64, V64,
6359                                                  asm, ".2d", ".2s", ".2s",
6360      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6361  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6362                                                  V128, V128, V128,
6363                                                  asm#"2", ".2d", ".4s", ".4s",
6364      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6365                                      (extract_high_v4i32 V128:$Rm)))]>;
6366}
6367
6368multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6369                                  SDPatternOperator OpNode = null_frag> {
6370  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6371                                                  V128, V64, V64,
6372                                                  asm, ".8h", ".8b", ".8b",
6373      [(set (v8i16 V128:$Rd),
6374            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6375  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6376                                                 V128, V128, V128,
6377                                                 asm#"2", ".8h", ".16b", ".16b",
6378      [(set (v8i16 V128:$Rd),
6379            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6380                                (extract_high_v16i8 V128:$Rm)))))]>;
6381  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6382                                                  V128, V64, V64,
6383                                                  asm, ".4s", ".4h", ".4h",
6384      [(set (v4i32 V128:$Rd),
6385            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6386  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6387                                                  V128, V128, V128,
6388                                                  asm#"2", ".4s", ".8h", ".8h",
6389      [(set (v4i32 V128:$Rd),
6390            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6391                                  (extract_high_v8i16 V128:$Rm)))))]>;
6392  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6393                                                  V128, V64, V64,
6394                                                  asm, ".2d", ".2s", ".2s",
6395      [(set (v2i64 V128:$Rd),
6396            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6397  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6398                                                  V128, V128, V128,
6399                                                  asm#"2", ".2d", ".4s", ".4s",
6400      [(set (v2i64 V128:$Rd),
6401            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6402                                 (extract_high_v4i32 V128:$Rm)))))]>;
6403}
6404
6405multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6406                                          string asm,
6407                                          SDPatternOperator OpNode> {
6408  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6409                                                  V128, V64, V64,
6410                                                  asm, ".8h", ".8b", ".8b",
6411    [(set (v8i16 V128:$dst),
6412          (add (v8i16 V128:$Rd),
6413               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6414  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6415                                                 V128, V128, V128,
6416                                                 asm#"2", ".8h", ".16b", ".16b",
6417    [(set (v8i16 V128:$dst),
6418          (add (v8i16 V128:$Rd),
6419               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6420                                   (extract_high_v16i8 V128:$Rm))))))]>;
6421  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6422                                                  V128, V64, V64,
6423                                                  asm, ".4s", ".4h", ".4h",
6424    [(set (v4i32 V128:$dst),
6425          (add (v4i32 V128:$Rd),
6426               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6427  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6428                                                  V128, V128, V128,
6429                                                  asm#"2", ".4s", ".8h", ".8h",
6430    [(set (v4i32 V128:$dst),
6431          (add (v4i32 V128:$Rd),
6432               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6433                                    (extract_high_v8i16 V128:$Rm))))))]>;
6434  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6435                                                  V128, V64, V64,
6436                                                  asm, ".2d", ".2s", ".2s",
6437    [(set (v2i64 V128:$dst),
6438          (add (v2i64 V128:$Rd),
6439               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6440  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6441                                                  V128, V128, V128,
6442                                                  asm#"2", ".2d", ".4s", ".4s",
6443    [(set (v2i64 V128:$dst),
6444          (add (v2i64 V128:$Rd),
6445               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6446                                    (extract_high_v4i32 V128:$Rm))))))]>;
6447}
6448
6449multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6450                                  SDPatternOperator OpNode = null_frag> {
6451  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6452                                                  V128, V64, V64,
6453                                                  asm, ".8h", ".8b", ".8b",
6454      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6455  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6456                                                 V128, V128, V128,
6457                                                 asm#"2", ".8h", ".16b", ".16b",
6458      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6459                                      (extract_high_v16i8 V128:$Rm)))]>;
6460  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6461                                                  V128, V64, V64,
6462                                                  asm, ".4s", ".4h", ".4h",
6463      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6464  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6465                                                  V128, V128, V128,
6466                                                  asm#"2", ".4s", ".8h", ".8h",
6467      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6468                                      (extract_high_v8i16 V128:$Rm)))]>;
6469  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6470                                                  V128, V64, V64,
6471                                                  asm, ".2d", ".2s", ".2s",
6472      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6473  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6474                                                  V128, V128, V128,
6475                                                  asm#"2", ".2d", ".4s", ".4s",
6476      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6477                                      (extract_high_v4i32 V128:$Rm)))]>;
6478}
6479
6480multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6481                                      string asm,
6482                                      SDPatternOperator OpNode> {
6483  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6484                                                  V128, V64, V64,
6485                                                  asm, ".8h", ".8b", ".8b",
6486    [(set (v8i16 V128:$dst),
6487          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6488  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6489                                                 V128, V128, V128,
6490                                                 asm#"2", ".8h", ".16b", ".16b",
6491    [(set (v8i16 V128:$dst),
6492          (OpNode (v8i16 V128:$Rd),
6493                  (extract_high_v16i8 V128:$Rn),
6494                  (extract_high_v16i8 V128:$Rm)))]>;
6495  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6496                                                  V128, V64, V64,
6497                                                  asm, ".4s", ".4h", ".4h",
6498    [(set (v4i32 V128:$dst),
6499          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6500  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6501                                                  V128, V128, V128,
6502                                                  asm#"2", ".4s", ".8h", ".8h",
6503    [(set (v4i32 V128:$dst),
6504          (OpNode (v4i32 V128:$Rd),
6505                  (extract_high_v8i16 V128:$Rn),
6506                  (extract_high_v8i16 V128:$Rm)))]>;
6507  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6508                                                  V128, V64, V64,
6509                                                  asm, ".2d", ".2s", ".2s",
6510    [(set (v2i64 V128:$dst),
6511          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6512  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6513                                                  V128, V128, V128,
6514                                                  asm#"2", ".2d", ".4s", ".4s",
6515    [(set (v2i64 V128:$dst),
6516          (OpNode (v2i64 V128:$Rd),
6517                  (extract_high_v4i32 V128:$Rn),
6518                  (extract_high_v4i32 V128:$Rm)))]>;
6519}
6520
6521multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6522                                           SDPatternOperator Accum> {
6523  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6524                                                  V128, V64, V64,
6525                                                  asm, ".4s", ".4h", ".4h",
6526    [(set (v4i32 V128:$dst),
6527          (Accum (v4i32 V128:$Rd),
6528                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6529                                                (v4i16 V64:$Rm)))))]>;
6530  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6531                                                  V128, V128, V128,
6532                                                  asm#"2", ".4s", ".8h", ".8h",
6533    [(set (v4i32 V128:$dst),
6534          (Accum (v4i32 V128:$Rd),
6535                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6536                                            (extract_high_v8i16 V128:$Rm)))))]>;
6537  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6538                                                  V128, V64, V64,
6539                                                  asm, ".2d", ".2s", ".2s",
6540    [(set (v2i64 V128:$dst),
6541          (Accum (v2i64 V128:$Rd),
6542                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6543                                                (v2i32 V64:$Rm)))))]>;
6544  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6545                                                  V128, V128, V128,
6546                                                  asm#"2", ".2d", ".4s", ".4s",
6547    [(set (v2i64 V128:$dst),
6548          (Accum (v2i64 V128:$Rd),
6549                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6550                                            (extract_high_v4i32 V128:$Rm)))))]>;
6551}
6552
6553multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6554                                  SDPatternOperator OpNode> {
6555  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6556                                                  V128, V128, V64,
6557                                                  asm, ".8h", ".8h", ".8b",
6558       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6559  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6560                                                  V128, V128, V128,
6561                                                  asm#"2", ".8h", ".8h", ".16b",
6562       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6563                                       (extract_high_v16i8 V128:$Rm)))]>;
6564  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6565                                                  V128, V128, V64,
6566                                                  asm, ".4s", ".4s", ".4h",
6567       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6568  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6569                                                  V128, V128, V128,
6570                                                  asm#"2", ".4s", ".4s", ".8h",
6571       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6572                                       (extract_high_v8i16 V128:$Rm)))]>;
6573  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6574                                                  V128, V128, V64,
6575                                                  asm, ".2d", ".2d", ".2s",
6576       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6577  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6578                                                  V128, V128, V128,
6579                                                  asm#"2", ".2d", ".2d", ".4s",
6580       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6581                                       (extract_high_v4i32 V128:$Rm)))]>;
6582}
6583
6584//----------------------------------------------------------------------------
6585// AdvSIMD bitwise extract from vector
6586//----------------------------------------------------------------------------
6587
6588class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6589                             string asm, string kind>
6590  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6591      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6592      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6593      [(set (vty regtype:$Rd),
6594            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6595    Sched<[WriteV]> {
6596  bits<5> Rd;
6597  bits<5> Rn;
6598  bits<5> Rm;
6599  bits<4> imm;
6600  let Inst{31}    = 0;
6601  let Inst{30}    = size;
6602  let Inst{29-21} = 0b101110000;
6603  let Inst{20-16} = Rm;
6604  let Inst{15}    = 0;
6605  let Inst{14-11} = imm;
6606  let Inst{10}    = 0;
6607  let Inst{9-5}   = Rn;
6608  let Inst{4-0}   = Rd;
6609}
6610
6611
6612multiclass SIMDBitwiseExtract<string asm> {
6613  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6614    let imm{3} = 0;
6615  }
6616  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6617}
6618
6619//----------------------------------------------------------------------------
6620// AdvSIMD zip vector
6621//----------------------------------------------------------------------------
6622
6623class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6624                        string asm, string kind, SDNode OpNode, ValueType valty>
6625  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6626      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6627      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6628      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6629    Sched<[WriteV]> {
6630  bits<5> Rd;
6631  bits<5> Rn;
6632  bits<5> Rm;
6633  let Inst{31}    = 0;
6634  let Inst{30}    = size{0};
6635  let Inst{29-24} = 0b001110;
6636  let Inst{23-22} = size{2-1};
6637  let Inst{21}    = 0;
6638  let Inst{20-16} = Rm;
6639  let Inst{15}    = 0;
6640  let Inst{14-12} = opc;
6641  let Inst{11-10} = 0b10;
6642  let Inst{9-5}   = Rn;
6643  let Inst{4-0}   = Rd;
6644}
6645
6646multiclass SIMDZipVector<bits<3>opc, string asm,
6647                         SDNode OpNode> {
6648  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6649      asm, ".8b", OpNode, v8i8>;
6650  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6651      asm, ".16b", OpNode, v16i8>;
6652  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6653      asm, ".4h", OpNode, v4i16>;
6654  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6655      asm, ".8h", OpNode, v8i16>;
6656  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6657      asm, ".2s", OpNode, v2i32>;
6658  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6659      asm, ".4s", OpNode, v4i32>;
6660  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6661      asm, ".2d", OpNode, v2i64>;
6662
6663  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6664        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6665  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6666        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6667  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6668        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6669  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6670        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6671  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6672        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6673}
6674
6675//----------------------------------------------------------------------------
6676// AdvSIMD three register scalar instructions
6677//----------------------------------------------------------------------------
6678
6679let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6680class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6681                        RegisterClass regtype, string asm,
6682                        list<dag> pattern>
6683  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6684      "\t$Rd, $Rn, $Rm", "", pattern>,
6685    Sched<[WriteV]> {
6686  bits<5> Rd;
6687  bits<5> Rn;
6688  bits<5> Rm;
6689  let Inst{31-30} = 0b01;
6690  let Inst{29}    = U;
6691  let Inst{28-24} = 0b11110;
6692  let Inst{23-21} = size;
6693  let Inst{20-16} = Rm;
6694  let Inst{15-11} = opcode;
6695  let Inst{10}    = 1;
6696  let Inst{9-5}   = Rn;
6697  let Inst{4-0}   = Rd;
6698}
6699
6700let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6701class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6702                        dag oops, dag iops, string asm,
6703            list<dag> pattern>
6704  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6705    Sched<[WriteV]> {
6706  bits<5> Rd;
6707  bits<5> Rn;
6708  bits<5> Rm;
6709  let Inst{31-30} = 0b01;
6710  let Inst{29}    = U;
6711  let Inst{28-24} = 0b11110;
6712  let Inst{23-22} = size;
6713  let Inst{21}    = R;
6714  let Inst{20-16} = Rm;
6715  let Inst{15-11} = opcode;
6716  let Inst{10}    = 1;
6717  let Inst{9-5}   = Rn;
6718  let Inst{4-0}   = Rd;
6719}
6720
6721multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6722                            SDPatternOperator OpNode> {
6723  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6724    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6725}
6726
6727multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6728                               SDPatternOperator OpNode> {
6729  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6730    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6731  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6732  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6733  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6734
6735  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6736            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6737  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6738            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6739}
6740
6741multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6742                             SDPatternOperator OpNode> {
6743  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6744                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6745  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6746}
6747
6748multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6749                                 SDPatternOperator OpNode = null_frag> {
6750  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6751                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6752                                     asm, []>;
6753  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6754                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6755                                     asm, []>;
6756}
6757
6758multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6759                             SDPatternOperator OpNode = null_frag> {
6760  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6761    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6762      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6763    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6764      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6765    let Predicates = [HasNEON, HasFullFP16] in {
6766    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6767      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6768    } // Predicates = [HasNEON, HasFullFP16]
6769  }
6770
6771  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6772            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6773}
6774
6775multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6776                                SDPatternOperator OpNode = null_frag> {
6777  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6778    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6779      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6780    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6781      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6782    let Predicates = [HasNEON, HasFullFP16] in {
6783    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6784      []>;
6785    } // Predicates = [HasNEON, HasFullFP16]
6786  }
6787
6788  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6789            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6790}
6791
6792class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6793              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6794  : I<oops, iops, asm,
6795      "\t$Rd, $Rn, $Rm", cstr, pat>,
6796    Sched<[WriteV]> {
6797  bits<5> Rd;
6798  bits<5> Rn;
6799  bits<5> Rm;
6800  let Inst{31-30} = 0b01;
6801  let Inst{29}    = U;
6802  let Inst{28-24} = 0b11110;
6803  let Inst{23-22} = size;
6804  let Inst{21}    = 1;
6805  let Inst{20-16} = Rm;
6806  let Inst{15-11} = opcode;
6807  let Inst{10}    = 0;
6808  let Inst{9-5}   = Rn;
6809  let Inst{4-0}   = Rd;
6810}
6811
6812let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6813multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6814                                  SDPatternOperator OpNode = null_frag> {
6815  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6816                                      (outs FPR32:$Rd),
6817                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6818  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6819                                      (outs FPR64:$Rd),
6820                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6821            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6822}
6823
6824let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6825multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6826                                  SDPatternOperator OpNode = null_frag> {
6827  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6828                                      (outs FPR32:$dst),
6829                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6830                                      asm, "$Rd = $dst", []>;
6831  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6832                                      (outs FPR64:$dst),
6833                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6834                                      asm, "$Rd = $dst",
6835            [(set (i64 FPR64:$dst),
6836                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6837}
6838
6839//----------------------------------------------------------------------------
6840// AdvSIMD two register scalar instructions
6841//----------------------------------------------------------------------------
6842
6843let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6844class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6845                        RegisterClass regtype, RegisterClass regtype2,
6846                        string asm, list<dag> pat>
6847  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6848      "\t$Rd, $Rn", "", pat>,
6849    Sched<[WriteV]> {
6850  bits<5> Rd;
6851  bits<5> Rn;
6852  let Inst{31-30} = 0b01;
6853  let Inst{29}    = U;
6854  let Inst{28-24} = 0b11110;
6855  let Inst{23-22} = size;
6856  let Inst{21} = 0b1;
6857  let Inst{20-19} = size2;
6858  let Inst{18-17} = 0b00;
6859  let Inst{16-12} = opcode;
6860  let Inst{11-10} = 0b10;
6861  let Inst{9-5}   = Rn;
6862  let Inst{4-0}   = Rd;
6863}
6864
6865let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6866class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6867                        RegisterClass regtype, RegisterClass regtype2,
6868                        string asm, list<dag> pat>
6869  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6870      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6871    Sched<[WriteV]> {
6872  bits<5> Rd;
6873  bits<5> Rn;
6874  let Inst{31-30} = 0b01;
6875  let Inst{29}    = U;
6876  let Inst{28-24} = 0b11110;
6877  let Inst{23-22} = size;
6878  let Inst{21-17} = 0b10000;
6879  let Inst{16-12} = opcode;
6880  let Inst{11-10} = 0b10;
6881  let Inst{9-5}   = Rn;
6882  let Inst{4-0}   = Rd;
6883}
6884
6885
6886let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6887class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6888                        RegisterClass regtype, string asm, string zero>
6889  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6890      "\t$Rd, $Rn, #" # zero, "", []>,
6891    Sched<[WriteV]> {
6892  bits<5> Rd;
6893  bits<5> Rn;
6894  let Inst{31-30} = 0b01;
6895  let Inst{29}    = U;
6896  let Inst{28-24} = 0b11110;
6897  let Inst{23-22} = size;
6898  let Inst{21} = 0b1;
6899  let Inst{20-19} = size2;
6900  let Inst{18-17} = 0b00;
6901  let Inst{16-12} = opcode;
6902  let Inst{11-10} = 0b10;
6903  let Inst{9-5}   = Rn;
6904  let Inst{4-0}   = Rd;
6905}
6906
6907class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6908  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6909     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6910    Sched<[WriteV]> {
6911  bits<5> Rd;
6912  bits<5> Rn;
6913  let Inst{31-17} = 0b011111100110000;
6914  let Inst{16-12} = opcode;
6915  let Inst{11-10} = 0b10;
6916  let Inst{9-5}   = Rn;
6917  let Inst{4-0}   = Rd;
6918}
6919
6920multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6921                             SDPatternOperator OpNode> {
6922  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6923
6924  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6925            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6926}
6927
6928multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6929                              SDPatternOperator OpNode> {
6930  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6931  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6932  let Predicates = [HasNEON, HasFullFP16] in {
6933  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6934  }
6935
6936  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6937                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6938  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6939                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6940  let Predicates = [HasNEON, HasFullFP16] in {
6941  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6942                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6943  }
6944
6945  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6946            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6947}
6948
6949multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6950                          SDPatternOperator OpNode = null_frag> {
6951  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6952    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6953
6954  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6955            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6956}
6957
6958multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6959  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6960  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6961  let Predicates = [HasNEON, HasFullFP16] in {
6962  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6963  }
6964}
6965
6966multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6967                              SDPatternOperator OpNode> {
6968  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6969                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6970  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6971                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6972  let Predicates = [HasNEON, HasFullFP16] in {
6973  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6974                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
6975  }
6976}
6977
6978multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6979                             SDPatternOperator OpNode = null_frag> {
6980  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6981    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6982           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6983    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6984           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6985    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6986    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6987  }
6988
6989  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6990            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6991}
6992
6993multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6994                                 Intrinsic OpNode> {
6995  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6996    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6997        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6998    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6999        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7000    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7001    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7002  }
7003
7004  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7005            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7006}
7007
7008
7009
7010let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7011multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7012                                 SDPatternOperator OpNode = null_frag> {
7013  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7014        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7015  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7016  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7017}
7018
7019//----------------------------------------------------------------------------
7020// AdvSIMD scalar pairwise instructions
7021//----------------------------------------------------------------------------
7022
7023let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7024class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7025                        RegisterOperand regtype, RegisterOperand vectype,
7026                        string asm, string kind>
7027  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7028      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7029    Sched<[WriteV]> {
7030  bits<5> Rd;
7031  bits<5> Rn;
7032  let Inst{31-30} = 0b01;
7033  let Inst{29}    = U;
7034  let Inst{28-24} = 0b11110;
7035  let Inst{23-22} = size;
7036  let Inst{21-17} = 0b11000;
7037  let Inst{16-12} = opcode;
7038  let Inst{11-10} = 0b10;
7039  let Inst{9-5}   = Rn;
7040  let Inst{4-0}   = Rd;
7041}
7042
7043multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7044  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7045                                      asm, ".2d">;
7046}
7047
7048multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7049  let Predicates = [HasNEON, HasFullFP16] in {
7050  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7051                                      asm, ".2h">;
7052  }
7053  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7054                                      asm, ".2s">;
7055  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7056                                      asm, ".2d">;
7057}
7058
7059//----------------------------------------------------------------------------
7060// AdvSIMD across lanes instructions
7061//----------------------------------------------------------------------------
7062
7063let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7064class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7065                          RegisterClass regtype, RegisterOperand vectype,
7066                          string asm, string kind, list<dag> pattern>
7067  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7068      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7069    Sched<[WriteV]> {
7070  bits<5> Rd;
7071  bits<5> Rn;
7072  let Inst{31}    = 0;
7073  let Inst{30}    = Q;
7074  let Inst{29}    = U;
7075  let Inst{28-24} = 0b01110;
7076  let Inst{23-22} = size;
7077  let Inst{21-17} = 0b11000;
7078  let Inst{16-12} = opcode;
7079  let Inst{11-10} = 0b10;
7080  let Inst{9-5}   = Rn;
7081  let Inst{4-0}   = Rd;
7082}
7083
7084multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7085                              string asm> {
7086  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7087                                   asm, ".8b", []>;
7088  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7089                                   asm, ".16b", []>;
7090  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7091                                   asm, ".4h", []>;
7092  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7093                                   asm, ".8h", []>;
7094  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7095                                   asm, ".4s", []>;
7096}
7097
7098multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7099  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7100                                   asm, ".8b", []>;
7101  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7102                                   asm, ".16b", []>;
7103  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7104                                   asm, ".4h", []>;
7105  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7106                                   asm, ".8h", []>;
7107  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7108                                   asm, ".4s", []>;
7109}
7110
7111multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7112                            Intrinsic intOp> {
7113  let Predicates = [HasNEON, HasFullFP16] in {
7114  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7115                                   asm, ".4h",
7116        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7117  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7118                                   asm, ".8h",
7119        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7120  } // Predicates = [HasNEON, HasFullFP16]
7121  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7122                                   asm, ".4s",
7123        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7124}
7125
7126//----------------------------------------------------------------------------
7127// AdvSIMD INS/DUP instructions
7128//----------------------------------------------------------------------------
7129
7130// FIXME: There has got to be a better way to factor these. ugh.
7131
7132class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7133                     string operands, string constraints, list<dag> pattern>
7134  : I<outs, ins, asm, operands, constraints, pattern>,
7135    Sched<[WriteV]> {
7136  bits<5> Rd;
7137  bits<5> Rn;
7138  let Inst{31} = 0;
7139  let Inst{30} = Q;
7140  let Inst{29} = op;
7141  let Inst{28-21} = 0b01110000;
7142  let Inst{15} = 0;
7143  let Inst{10} = 1;
7144  let Inst{9-5} = Rn;
7145  let Inst{4-0} = Rd;
7146}
7147
7148class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7149                      RegisterOperand vecreg, RegisterClass regtype>
7150  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7151                   "{\t$Rd" # size # ", $Rn" #
7152                   "|" # size # "\t$Rd, $Rn}", "",
7153                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7154  let Inst{20-16} = imm5;
7155  let Inst{14-11} = 0b0001;
7156}
7157
7158class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7159                         ValueType vectype, ValueType insreg,
7160                         RegisterOperand vecreg, Operand idxtype,
7161                         ValueType elttype, SDNode OpNode>
7162  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7163                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7164                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7165                 [(set (vectype vecreg:$Rd),
7166                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7167  let Inst{14-11} = 0b0000;
7168}
7169
7170class SIMDDup64FromElement
7171  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7172                       VectorIndexD, i64, AArch64duplane64> {
7173  bits<1> idx;
7174  let Inst{20} = idx;
7175  let Inst{19-16} = 0b1000;
7176}
7177
7178class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7179                           RegisterOperand vecreg>
7180  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7181                       VectorIndexS, i64, AArch64duplane32> {
7182  bits<2> idx;
7183  let Inst{20-19} = idx;
7184  let Inst{18-16} = 0b100;
7185}
7186
7187class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7188                           RegisterOperand vecreg>
7189  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7190                       VectorIndexH, i64, AArch64duplane16> {
7191  bits<3> idx;
7192  let Inst{20-18} = idx;
7193  let Inst{17-16} = 0b10;
7194}
7195
7196class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7197                          RegisterOperand vecreg>
7198  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7199                       VectorIndexB, i64, AArch64duplane8> {
7200  bits<4> idx;
7201  let Inst{20-17} = idx;
7202  let Inst{16} = 1;
7203}
7204
7205class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7206                  Operand idxtype, string asm, list<dag> pattern>
7207  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7208                   "{\t$Rd, $Rn" # size # "$idx" #
7209                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7210  let Inst{14-11} = imm4;
7211}
7212
7213class SIMDSMov<bit Q, string size, RegisterClass regtype,
7214               Operand idxtype>
7215  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7216class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7217               Operand idxtype>
7218  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7219      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7220
7221class SIMDMovAlias<string asm, string size, Instruction inst,
7222                   RegisterClass regtype, Operand idxtype>
7223    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7224                    "|" # size # "\t$dst, $src$idx}",
7225                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7226
7227multiclass SMov {
7228  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7229    bits<4> idx;
7230    let Inst{20-17} = idx;
7231    let Inst{16} = 1;
7232  }
7233  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7234    bits<4> idx;
7235    let Inst{20-17} = idx;
7236    let Inst{16} = 1;
7237  }
7238  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7239    bits<3> idx;
7240    let Inst{20-18} = idx;
7241    let Inst{17-16} = 0b10;
7242  }
7243  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7244    bits<3> idx;
7245    let Inst{20-18} = idx;
7246    let Inst{17-16} = 0b10;
7247  }
7248  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7249    bits<2> idx;
7250    let Inst{20-19} = idx;
7251    let Inst{18-16} = 0b100;
7252  }
7253}
7254
7255multiclass UMov {
7256  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7257    bits<4> idx;
7258    let Inst{20-17} = idx;
7259    let Inst{16} = 1;
7260  }
7261  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7262    bits<3> idx;
7263    let Inst{20-18} = idx;
7264    let Inst{17-16} = 0b10;
7265  }
7266  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7267    bits<2> idx;
7268    let Inst{20-19} = idx;
7269    let Inst{18-16} = 0b100;
7270  }
7271  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7272    bits<1> idx;
7273    let Inst{20} = idx;
7274    let Inst{19-16} = 0b1000;
7275  }
7276  def : SIMDMovAlias<"mov", ".s",
7277                     !cast<Instruction>(NAME#"vi32"),
7278                     GPR32, VectorIndexS>;
7279  def : SIMDMovAlias<"mov", ".d",
7280                     !cast<Instruction>(NAME#"vi64"),
7281                     GPR64, VectorIndexD>;
7282}
7283
7284class SIMDInsFromMain<string size, ValueType vectype,
7285                      RegisterClass regtype, Operand idxtype>
7286  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7287                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7288                   "{\t$Rd" # size # "$idx, $Rn" #
7289                   "|" # size # "\t$Rd$idx, $Rn}",
7290                   "$Rd = $dst",
7291            [(set V128:$dst,
7292              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7293  let Inst{14-11} = 0b0011;
7294}
7295
7296class SIMDInsFromElement<string size, ValueType vectype,
7297                         ValueType elttype, Operand idxtype>
7298  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7299                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7300                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7301                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7302                   "$Rd = $dst",
7303         [(set V128:$dst,
7304               (vector_insert
7305                 (vectype V128:$Rd),
7306                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7307                 idxtype:$idx))]>;
7308
7309class SIMDInsMainMovAlias<string size, Instruction inst,
7310                          RegisterClass regtype, Operand idxtype>
7311    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7312                        "|" # size #"\t$dst$idx, $src}",
7313                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7314class SIMDInsElementMovAlias<string size, Instruction inst,
7315                             Operand idxtype>
7316    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7317                      # "|" # size #"\t$dst$idx, $src$idx2}",
7318                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7319
7320
7321multiclass SIMDIns {
7322  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7323    bits<4> idx;
7324    let Inst{20-17} = idx;
7325    let Inst{16} = 1;
7326  }
7327  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7328    bits<3> idx;
7329    let Inst{20-18} = idx;
7330    let Inst{17-16} = 0b10;
7331  }
7332  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7333    bits<2> idx;
7334    let Inst{20-19} = idx;
7335    let Inst{18-16} = 0b100;
7336  }
7337  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7338    bits<1> idx;
7339    let Inst{20} = idx;
7340    let Inst{19-16} = 0b1000;
7341  }
7342
7343  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7344    bits<4> idx;
7345    bits<4> idx2;
7346    let Inst{20-17} = idx;
7347    let Inst{16} = 1;
7348    let Inst{14-11} = idx2;
7349  }
7350  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7351    bits<3> idx;
7352    bits<3> idx2;
7353    let Inst{20-18} = idx;
7354    let Inst{17-16} = 0b10;
7355    let Inst{14-12} = idx2;
7356    let Inst{11} = {?};
7357  }
7358  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7359    bits<2> idx;
7360    bits<2> idx2;
7361    let Inst{20-19} = idx;
7362    let Inst{18-16} = 0b100;
7363    let Inst{14-13} = idx2;
7364    let Inst{12-11} = {?,?};
7365  }
7366  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7367    bits<1> idx;
7368    bits<1> idx2;
7369    let Inst{20} = idx;
7370    let Inst{19-16} = 0b1000;
7371    let Inst{14} = idx2;
7372    let Inst{13-11} = {?,?,?};
7373  }
7374
7375  // For all forms of the INS instruction, the "mov" mnemonic is the
7376  // preferred alias. Why they didn't just call the instruction "mov" in
7377  // the first place is a very good question indeed...
7378  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7379                         GPR32, VectorIndexB>;
7380  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7381                         GPR32, VectorIndexH>;
7382  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7383                         GPR32, VectorIndexS>;
7384  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7385                         GPR64, VectorIndexD>;
7386
7387  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7388                         VectorIndexB>;
7389  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7390                         VectorIndexH>;
7391  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7392                         VectorIndexS>;
7393  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7394                         VectorIndexD>;
7395}
7396
7397//----------------------------------------------------------------------------
7398// AdvSIMD TBL/TBX
7399//----------------------------------------------------------------------------
7400
7401let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7402class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7403                          RegisterOperand listtype, string asm, string kind>
7404  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7405       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7406    Sched<[WriteV]> {
7407  bits<5> Vd;
7408  bits<5> Vn;
7409  bits<5> Vm;
7410  let Inst{31}    = 0;
7411  let Inst{30}    = Q;
7412  let Inst{29-21} = 0b001110000;
7413  let Inst{20-16} = Vm;
7414  let Inst{15}    = 0;
7415  let Inst{14-13} = len;
7416  let Inst{12}    = op;
7417  let Inst{11-10} = 0b00;
7418  let Inst{9-5}   = Vn;
7419  let Inst{4-0}   = Vd;
7420}
7421
7422let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7423class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7424                          RegisterOperand listtype, string asm, string kind>
7425  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7426       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7427    Sched<[WriteV]> {
7428  bits<5> Vd;
7429  bits<5> Vn;
7430  bits<5> Vm;
7431  let Inst{31}    = 0;
7432  let Inst{30}    = Q;
7433  let Inst{29-21} = 0b001110000;
7434  let Inst{20-16} = Vm;
7435  let Inst{15}    = 0;
7436  let Inst{14-13} = len;
7437  let Inst{12}    = op;
7438  let Inst{11-10} = 0b00;
7439  let Inst{9-5}   = Vn;
7440  let Inst{4-0}   = Vd;
7441}
7442
7443class SIMDTableLookupAlias<string asm, Instruction inst,
7444                          RegisterOperand vectype, RegisterOperand listtype>
7445    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7446                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7447
7448multiclass SIMDTableLookup<bit op, string asm> {
7449  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7450                                      asm, ".8b">;
7451  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7452                                      asm, ".8b">;
7453  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7454                                      asm, ".8b">;
7455  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7456                                      asm, ".8b">;
7457  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7458                                      asm, ".16b">;
7459  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7460                                      asm, ".16b">;
7461  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7462                                      asm, ".16b">;
7463  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7464                                      asm, ".16b">;
7465
7466  def : SIMDTableLookupAlias<asm # ".8b",
7467                         !cast<Instruction>(NAME#"v8i8One"),
7468                         V64, VecListOne128>;
7469  def : SIMDTableLookupAlias<asm # ".8b",
7470                         !cast<Instruction>(NAME#"v8i8Two"),
7471                         V64, VecListTwo128>;
7472  def : SIMDTableLookupAlias<asm # ".8b",
7473                         !cast<Instruction>(NAME#"v8i8Three"),
7474                         V64, VecListThree128>;
7475  def : SIMDTableLookupAlias<asm # ".8b",
7476                         !cast<Instruction>(NAME#"v8i8Four"),
7477                         V64, VecListFour128>;
7478  def : SIMDTableLookupAlias<asm # ".16b",
7479                         !cast<Instruction>(NAME#"v16i8One"),
7480                         V128, VecListOne128>;
7481  def : SIMDTableLookupAlias<asm # ".16b",
7482                         !cast<Instruction>(NAME#"v16i8Two"),
7483                         V128, VecListTwo128>;
7484  def : SIMDTableLookupAlias<asm # ".16b",
7485                         !cast<Instruction>(NAME#"v16i8Three"),
7486                         V128, VecListThree128>;
7487  def : SIMDTableLookupAlias<asm # ".16b",
7488                         !cast<Instruction>(NAME#"v16i8Four"),
7489                         V128, VecListFour128>;
7490}
7491
7492multiclass SIMDTableLookupTied<bit op, string asm> {
7493  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7494                                      asm, ".8b">;
7495  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7496                                      asm, ".8b">;
7497  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7498                                      asm, ".8b">;
7499  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7500                                      asm, ".8b">;
7501  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7502                                      asm, ".16b">;
7503  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7504                                      asm, ".16b">;
7505  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7506                                      asm, ".16b">;
7507  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7508                                      asm, ".16b">;
7509
7510  def : SIMDTableLookupAlias<asm # ".8b",
7511                         !cast<Instruction>(NAME#"v8i8One"),
7512                         V64, VecListOne128>;
7513  def : SIMDTableLookupAlias<asm # ".8b",
7514                         !cast<Instruction>(NAME#"v8i8Two"),
7515                         V64, VecListTwo128>;
7516  def : SIMDTableLookupAlias<asm # ".8b",
7517                         !cast<Instruction>(NAME#"v8i8Three"),
7518                         V64, VecListThree128>;
7519  def : SIMDTableLookupAlias<asm # ".8b",
7520                         !cast<Instruction>(NAME#"v8i8Four"),
7521                         V64, VecListFour128>;
7522  def : SIMDTableLookupAlias<asm # ".16b",
7523                         !cast<Instruction>(NAME#"v16i8One"),
7524                         V128, VecListOne128>;
7525  def : SIMDTableLookupAlias<asm # ".16b",
7526                         !cast<Instruction>(NAME#"v16i8Two"),
7527                         V128, VecListTwo128>;
7528  def : SIMDTableLookupAlias<asm # ".16b",
7529                         !cast<Instruction>(NAME#"v16i8Three"),
7530                         V128, VecListThree128>;
7531  def : SIMDTableLookupAlias<asm # ".16b",
7532                         !cast<Instruction>(NAME#"v16i8Four"),
7533                         V128, VecListFour128>;
7534}
7535
7536
7537//----------------------------------------------------------------------------
7538// AdvSIMD scalar CPY
7539//----------------------------------------------------------------------------
7540let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7541class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7542                        string kind, Operand idxtype>
7543  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7544       "{\t$dst, $src" # kind # "$idx" #
7545       "|\t$dst, $src$idx}", "", []>,
7546    Sched<[WriteV]> {
7547  bits<5> dst;
7548  bits<5> src;
7549  let Inst{31-21} = 0b01011110000;
7550  let Inst{15-10} = 0b000001;
7551  let Inst{9-5}   = src;
7552  let Inst{4-0}   = dst;
7553}
7554
7555class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7556      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7557    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7558                    # "|\t$dst, $src$index}",
7559                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7560
7561
7562multiclass SIMDScalarCPY<string asm> {
7563  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7564    bits<4> idx;
7565    let Inst{20-17} = idx;
7566    let Inst{16} = 1;
7567  }
7568  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7569    bits<3> idx;
7570    let Inst{20-18} = idx;
7571    let Inst{17-16} = 0b10;
7572  }
7573  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7574    bits<2> idx;
7575    let Inst{20-19} = idx;
7576    let Inst{18-16} = 0b100;
7577  }
7578  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7579    bits<1> idx;
7580    let Inst{20} = idx;
7581    let Inst{19-16} = 0b1000;
7582  }
7583
7584  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7585                                                          VectorIndexD:$idx)))),
7586            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7587
7588  // 'DUP' mnemonic aliases.
7589  def : SIMDScalarCPYAlias<"dup", ".b",
7590                           !cast<Instruction>(NAME#"i8"),
7591                           FPR8, V128, VectorIndexB>;
7592  def : SIMDScalarCPYAlias<"dup", ".h",
7593                           !cast<Instruction>(NAME#"i16"),
7594                           FPR16, V128, VectorIndexH>;
7595  def : SIMDScalarCPYAlias<"dup", ".s",
7596                           !cast<Instruction>(NAME#"i32"),
7597                           FPR32, V128, VectorIndexS>;
7598  def : SIMDScalarCPYAlias<"dup", ".d",
7599                           !cast<Instruction>(NAME#"i64"),
7600                           FPR64, V128, VectorIndexD>;
7601}
7602
7603//----------------------------------------------------------------------------
7604// AdvSIMD modified immediate instructions
7605//----------------------------------------------------------------------------
7606
7607class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7608                          string asm, string op_string,
7609                          string cstr, list<dag> pattern>
7610  : I<oops, iops, asm, op_string, cstr, pattern>,
7611    Sched<[WriteV]> {
7612  bits<5> Rd;
7613  bits<8> imm8;
7614  let Inst{31}    = 0;
7615  let Inst{30}    = Q;
7616  let Inst{29}    = op;
7617  let Inst{28-19} = 0b0111100000;
7618  let Inst{18-16} = imm8{7-5};
7619  let Inst{11} = op2;
7620  let Inst{10} = 1;
7621  let Inst{9-5}   = imm8{4-0};
7622  let Inst{4-0}   = Rd;
7623}
7624
7625class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7626                                Operand immtype, dag opt_shift_iop,
7627                                string opt_shift, string asm, string kind,
7628                                list<dag> pattern>
7629  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7630                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7631                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7632                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7633                        "", pattern> {
7634  let DecoderMethod = "DecodeModImmInstruction";
7635}
7636
7637class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7638                                Operand immtype, dag opt_shift_iop,
7639                                string opt_shift, string asm, string kind,
7640                                list<dag> pattern>
7641  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7642                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7643                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7644                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7645                        "$Rd = $dst", pattern> {
7646  let DecoderMethod = "DecodeModImmTiedInstruction";
7647}
7648
7649class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7650                                     RegisterOperand vectype, string asm,
7651                                     string kind, list<dag> pattern>
7652  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7653                              (ins logical_vec_shift:$shift),
7654                              "$shift", asm, kind, pattern> {
7655  bits<2> shift;
7656  let Inst{15}    = b15_b12{1};
7657  let Inst{14-13} = shift;
7658  let Inst{12}    = b15_b12{0};
7659}
7660
7661class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7662                                     RegisterOperand vectype, string asm,
7663                                     string kind, list<dag> pattern>
7664  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7665                              (ins logical_vec_shift:$shift),
7666                              "$shift", asm, kind, pattern> {
7667  bits<2> shift;
7668  let Inst{15}    = b15_b12{1};
7669  let Inst{14-13} = shift;
7670  let Inst{12}    = b15_b12{0};
7671}
7672
7673
7674class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7675                                         RegisterOperand vectype, string asm,
7676                                         string kind, list<dag> pattern>
7677  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7678                              (ins logical_vec_hw_shift:$shift),
7679                              "$shift", asm, kind, pattern> {
7680  bits<2> shift;
7681  let Inst{15} = b15_b12{1};
7682  let Inst{14} = 0;
7683  let Inst{13} = shift{0};
7684  let Inst{12} = b15_b12{0};
7685}
7686
7687class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7688                                         RegisterOperand vectype, string asm,
7689                                         string kind, list<dag> pattern>
7690  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7691                              (ins logical_vec_hw_shift:$shift),
7692                              "$shift", asm, kind, pattern> {
7693  bits<2> shift;
7694  let Inst{15} = b15_b12{1};
7695  let Inst{14} = 0;
7696  let Inst{13} = shift{0};
7697  let Inst{12} = b15_b12{0};
7698}
7699
7700multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7701                                      string asm> {
7702  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7703                                                 asm, ".4h", []>;
7704  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7705                                                 asm, ".8h", []>;
7706
7707  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7708                                             asm, ".2s", []>;
7709  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7710                                             asm, ".4s", []>;
7711}
7712
7713multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7714                                      bits<2> w_cmode, string asm,
7715                                      SDNode OpNode> {
7716  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7717                                                 asm, ".4h",
7718             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7719                                             imm0_255:$imm8,
7720                                             (i32 imm:$shift)))]>;
7721  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7722                                                 asm, ".8h",
7723             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7724                                              imm0_255:$imm8,
7725                                              (i32 imm:$shift)))]>;
7726
7727  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7728                                             asm, ".2s",
7729             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7730                                             imm0_255:$imm8,
7731                                             (i32 imm:$shift)))]>;
7732  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7733                                             asm, ".4s",
7734             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7735                                              imm0_255:$imm8,
7736                                              (i32 imm:$shift)))]>;
7737}
7738
7739class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7740                             RegisterOperand vectype, string asm,
7741                             string kind, list<dag> pattern>
7742  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7743                              (ins move_vec_shift:$shift),
7744                              "$shift", asm, kind, pattern> {
7745  bits<1> shift;
7746  let Inst{15-13} = cmode{3-1};
7747  let Inst{12}    = shift;
7748}
7749
7750class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7751                                   RegisterOperand vectype,
7752                                   Operand imm_type, string asm,
7753                                   string kind, list<dag> pattern>
7754  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7755                              asm, kind, pattern> {
7756  let Inst{15-12} = cmode;
7757}
7758
7759class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7760                                   list<dag> pattern>
7761  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7762                        "\t$Rd, $imm8", "", pattern> {
7763  let Inst{15-12} = cmode;
7764  let DecoderMethod = "DecodeModImmInstruction";
7765}
7766
7767//----------------------------------------------------------------------------
7768// AdvSIMD indexed element
7769//----------------------------------------------------------------------------
7770
7771let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7772class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7773                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7774                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7775                      string apple_kind, string dst_kind, string lhs_kind,
7776                      string rhs_kind, list<dag> pattern>
7777  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7778      asm,
7779      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7780      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7781    Sched<[WriteV]> {
7782  bits<5> Rd;
7783  bits<5> Rn;
7784  bits<5> Rm;
7785
7786  let Inst{31}    = 0;
7787  let Inst{30}    = Q;
7788  let Inst{29}    = U;
7789  let Inst{28}    = Scalar;
7790  let Inst{27-24} = 0b1111;
7791  let Inst{23-22} = size;
7792  // Bit 21 must be set by the derived class.
7793  let Inst{20-16} = Rm;
7794  let Inst{15-12} = opc;
7795  // Bit 11 must be set by the derived class.
7796  let Inst{10}    = 0;
7797  let Inst{9-5}   = Rn;
7798  let Inst{4-0}   = Rd;
7799}
7800
7801let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7802class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7803                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7804                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7805                      string apple_kind, string dst_kind, string lhs_kind,
7806                      string rhs_kind, list<dag> pattern>
7807  : I<(outs dst_reg:$dst),
7808      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7809      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7810      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7811    Sched<[WriteV]> {
7812  bits<5> Rd;
7813  bits<5> Rn;
7814  bits<5> Rm;
7815
7816  let Inst{31}    = 0;
7817  let Inst{30}    = Q;
7818  let Inst{29}    = U;
7819  let Inst{28}    = Scalar;
7820  let Inst{27-24} = 0b1111;
7821  let Inst{23-22} = size;
7822  // Bit 21 must be set by the derived class.
7823  let Inst{20-16} = Rm;
7824  let Inst{15-12} = opc;
7825  // Bit 11 must be set by the derived class.
7826  let Inst{10}    = 0;
7827  let Inst{9-5}   = Rn;
7828  let Inst{4-0}   = Rd;
7829}
7830
7831
7832//----------------------------------------------------------------------------
7833// Armv8.6 BFloat16 Extension
7834//----------------------------------------------------------------------------
7835let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
7836
7837class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
7838                                   string kind2, RegisterOperand RegType,
7839                                   ValueType AccumType, ValueType InputType>
7840  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
7841                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
7842                                            (InputType RegType:$Rn),
7843                                            (InputType RegType:$Rm)))]> {
7844  let AsmString = !strconcat(asm,
7845                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
7846                               ", $Rm" # kind2 # "}");
7847}
7848
7849multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
7850  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
7851                                           v2f32, v4bf16>;
7852  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
7853                                           v4f32, v8bf16>;
7854}
7855
7856class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
7857                                      string dst_kind, string lhs_kind,
7858                                      string rhs_kind,
7859                                      RegisterOperand RegType,
7860                                      ValueType AccumType,
7861                                      ValueType InputType>
7862  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
7863                        RegType, RegType, V128, VectorIndexS,
7864                        asm, "", dst_kind, lhs_kind, rhs_kind,
7865        [(set (AccumType RegType:$dst),
7866              (AccumType (int_aarch64_neon_bfdot
7867                                 (AccumType RegType:$Rd),
7868                                 (InputType RegType:$Rn),
7869                                 (InputType (bitconvert (AccumType
7870                                    (AArch64duplane32 (v4f32 V128:$Rm),
7871                                        VectorIndexS:$idx)))))))]> {
7872
7873  bits<2> idx;
7874  let Inst{21}    = idx{0};  // L
7875  let Inst{11}    = idx{1};  // H
7876}
7877
7878multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
7879
7880  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
7881                                               ".2h", V64, v2f32, v4bf16>;
7882  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
7883                                              ".2h", V128, v4f32, v8bf16>;
7884}
7885
7886class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
7887  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
7888              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
7889                                               (v8bf16 V128:$Rn),
7890                                               (v8bf16 V128:$Rm)))]> {
7891  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
7892}
7893
7894class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
7895  : I<(outs V128:$dst),
7896      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
7897      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
7898          [(set (v4f32 V128:$dst),
7899                (v4f32 (OpNode (v4f32 V128:$Rd),
7900                               (v8bf16 V128:$Rn),
7901                               (v8bf16
7902                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
7903                                      VectorIndexH:$idx)))))]>,
7904    Sched<[WriteV]> {
7905  bits<5> Rd;
7906  bits<5> Rn;
7907  bits<4> Rm;
7908  bits<3> idx;
7909
7910  let Inst{31}    = 0;
7911  let Inst{30}    = Q;
7912  let Inst{29-22} = 0b00111111;
7913  let Inst{21-20} = idx{1-0};
7914  let Inst{19-16} = Rm;
7915  let Inst{15-12} = 0b1111;
7916  let Inst{11}    = idx{2};   // H
7917  let Inst{10}    = 0;
7918  let Inst{9-5}   = Rn;
7919  let Inst{4-0}   = Rd;
7920}
7921
7922class SIMDThreeSameVectorBF16MatrixMul<string asm>
7923  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
7924                                V128, asm, ".4s",
7925                          [(set (v4f32 V128:$dst),
7926                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
7927                                                         (v8bf16 V128:$Rn),
7928                                                         (v8bf16 V128:$Rm)))]> {
7929  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
7930                                    ", $Rm", ".8h", "}");
7931}
7932
7933class SIMD_BFCVTN
7934  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
7935                           "bfcvtn", ".4h", ".4s",
7936    [(set (v8bf16 V128:$Rd),
7937          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
7938
7939class SIMD_BFCVTN2
7940  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
7941                           "bfcvtn2", ".8h", ".4s",
7942    [(set (v8bf16 V128:$dst),
7943          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
7944
7945class BF16ToSinglePrecision<string asm>
7946  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
7947    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
7948    Sched<[WriteFCvt]> {
7949  bits<5> Rd;
7950  bits<5> Rn;
7951  let Inst{31-10} = 0b0001111001100011010000;
7952  let Inst{9-5}   = Rn;
7953  let Inst{4-0}   = Rd;
7954}
7955} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
7956
7957//----------------------------------------------------------------------------
7958// Armv8.6 Matrix Multiply Extension
7959//----------------------------------------------------------------------------
7960
7961class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
7962  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
7963              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
7964                                               (v16i8 V128:$Rn),
7965                                               (v16i8 V128:$Rm)))]> {
7966  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
7967}
7968
7969//----------------------------------------------------------------------------
7970// ARMv8.2-A Dot Product Instructions (Indexed)
7971class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
7972                                      string dst_kind, string lhs_kind, string rhs_kind,
7973                                      RegisterOperand RegType,
7974                                      ValueType AccumType, ValueType InputType,
7975                                      SDPatternOperator OpNode> :
7976        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
7977                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7978        [(set (AccumType RegType:$dst),
7979              (AccumType (OpNode (AccumType RegType:$Rd),
7980                                 (InputType RegType:$Rn),
7981                                 (InputType (bitconvert (AccumType
7982                                    (AArch64duplane32 (v4i32 V128:$Rm),
7983                                        VectorIndexS:$idx)))))))]> {
7984  bits<2> idx;
7985  let Inst{21}    = idx{0};  // L
7986  let Inst{11}    = idx{1};  // H
7987}
7988
7989multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
7990                                       SDPatternOperator OpNode> {
7991  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
7992                                              V64, v2i32, v8i8, OpNode>;
7993  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
7994                                              V128, v4i32, v16i8, OpNode>;
7995}
7996
7997// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7998class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7999                                      string dst_kind, string lhs_kind,
8000                                      string rhs_kind, RegisterOperand RegType,
8001                                      ValueType AccumType, ValueType InputType,
8002                                      SDPatternOperator OpNode> :
8003        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8004                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8005          [(set (AccumType RegType:$dst),
8006                (AccumType (OpNode (AccumType RegType:$Rd),
8007                                   (InputType RegType:$Rn),
8008                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8009                                                VectorIndexH:$idx)))))]> {
8010  // idx = H:L:M
8011  bits<3> idx;
8012  let Inst{11} = idx{2}; // H
8013  let Inst{21} = idx{1}; // L
8014  let Inst{20} = idx{0}; // M
8015}
8016
8017multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8018                                       SDPatternOperator OpNode> {
8019  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8020                                              V64, v2f32, v4f16, OpNode>;
8021  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8022                                              V128, v4f32, v8f16, OpNode>;
8023}
8024
8025multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8026                         SDPatternOperator OpNode> {
8027  let Predicates = [HasNEON, HasFullFP16] in {
8028  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8029                                      V64, V64,
8030                                      V128_lo, VectorIndexH,
8031                                      asm, ".4h", ".4h", ".4h", ".h",
8032    [(set (v4f16 V64:$Rd),
8033        (OpNode (v4f16 V64:$Rn),
8034         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8035    bits<3> idx;
8036    let Inst{11} = idx{2};
8037    let Inst{21} = idx{1};
8038    let Inst{20} = idx{0};
8039  }
8040
8041  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8042                                      V128, V128,
8043                                      V128_lo, VectorIndexH,
8044                                      asm, ".8h", ".8h", ".8h", ".h",
8045    [(set (v8f16 V128:$Rd),
8046        (OpNode (v8f16 V128:$Rn),
8047         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8048    bits<3> idx;
8049    let Inst{11} = idx{2};
8050    let Inst{21} = idx{1};
8051    let Inst{20} = idx{0};
8052  }
8053  } // Predicates = [HasNEON, HasFullFP16]
8054
8055  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8056                                      V64, V64,
8057                                      V128, VectorIndexS,
8058                                      asm, ".2s", ".2s", ".2s", ".s",
8059    [(set (v2f32 V64:$Rd),
8060        (OpNode (v2f32 V64:$Rn),
8061         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8062    bits<2> idx;
8063    let Inst{11} = idx{1};
8064    let Inst{21} = idx{0};
8065  }
8066
8067  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8068                                      V128, V128,
8069                                      V128, VectorIndexS,
8070                                      asm, ".4s", ".4s", ".4s", ".s",
8071    [(set (v4f32 V128:$Rd),
8072        (OpNode (v4f32 V128:$Rn),
8073         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8074    bits<2> idx;
8075    let Inst{11} = idx{1};
8076    let Inst{21} = idx{0};
8077  }
8078
8079  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8080                                      V128, V128,
8081                                      V128, VectorIndexD,
8082                                      asm, ".2d", ".2d", ".2d", ".d",
8083    [(set (v2f64 V128:$Rd),
8084        (OpNode (v2f64 V128:$Rn),
8085         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8086    bits<1> idx;
8087    let Inst{11} = idx{0};
8088    let Inst{21} = 0;
8089  }
8090
8091  let Predicates = [HasNEON, HasFullFP16] in {
8092  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8093                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8094                                      asm, ".h", "", "", ".h",
8095    [(set (f16 FPR16Op:$Rd),
8096          (OpNode (f16 FPR16Op:$Rn),
8097                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8098                                       VectorIndexH:$idx))))]> {
8099    bits<3> idx;
8100    let Inst{11} = idx{2};
8101    let Inst{21} = idx{1};
8102    let Inst{20} = idx{0};
8103  }
8104  } // Predicates = [HasNEON, HasFullFP16]
8105
8106  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8107                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8108                                      asm, ".s", "", "", ".s",
8109    [(set (f32 FPR32Op:$Rd),
8110          (OpNode (f32 FPR32Op:$Rn),
8111                  (f32 (vector_extract (v4f32 V128:$Rm),
8112                                       VectorIndexS:$idx))))]> {
8113    bits<2> idx;
8114    let Inst{11} = idx{1};
8115    let Inst{21} = idx{0};
8116  }
8117
8118  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8119                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8120                                      asm, ".d", "", "", ".d",
8121    [(set (f64 FPR64Op:$Rd),
8122          (OpNode (f64 FPR64Op:$Rn),
8123                  (f64 (vector_extract (v2f64 V128:$Rm),
8124                                       VectorIndexD:$idx))))]> {
8125    bits<1> idx;
8126    let Inst{11} = idx{0};
8127    let Inst{21} = 0;
8128  }
8129}
8130
8131multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8132  let Predicates = [HasNEON, HasFullFP16] in {
8133  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8134  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8135                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8136                                           VectorIndexH:$idx))),
8137            (!cast<Instruction>(INST # "v8i16_indexed")
8138                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8139  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8140                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8141            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8142                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8143
8144  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8145                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8146                                           VectorIndexH:$idx))),
8147            (!cast<Instruction>(INST # "v4i16_indexed")
8148                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8149  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8150                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8151            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8152                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8153
8154  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8155                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8156            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8157                V128_lo:$Rm, VectorIndexH:$idx)>;
8158  } // Predicates = [HasNEON, HasFullFP16]
8159
8160  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8161  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8162                           (AArch64duplane32 (v4f32 V128:$Rm),
8163                                           VectorIndexS:$idx))),
8164            (!cast<Instruction>(INST # v2i32_indexed)
8165                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8166  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8167                           (AArch64dup (f32 FPR32Op:$Rm)))),
8168            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8169                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8170
8171
8172  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8173  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8174                           (AArch64duplane32 (v4f32 V128:$Rm),
8175                                           VectorIndexS:$idx))),
8176            (!cast<Instruction>(INST # "v4i32_indexed")
8177                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8178  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8179                           (AArch64dup (f32 FPR32Op:$Rm)))),
8180            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8181                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8182
8183  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8184  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8185                           (AArch64duplane64 (v2f64 V128:$Rm),
8186                                           VectorIndexD:$idx))),
8187            (!cast<Instruction>(INST # "v2i64_indexed")
8188                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8189  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8190                           (AArch64dup (f64 FPR64Op:$Rm)))),
8191            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8192                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8193
8194  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8195  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8196                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8197            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8198                V128:$Rm, VectorIndexS:$idx)>;
8199
8200  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8201  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8202                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8203            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8204                V128:$Rm, VectorIndexD:$idx)>;
8205}
8206
8207multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8208  let Predicates = [HasNEON, HasFullFP16] in {
8209  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8210                                          V128_lo, VectorIndexH,
8211                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8212    bits<3> idx;
8213    let Inst{11} = idx{2};
8214    let Inst{21} = idx{1};
8215    let Inst{20} = idx{0};
8216  }
8217
8218  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8219                                          V128, V128,
8220                                          V128_lo, VectorIndexH,
8221                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8222    bits<3> idx;
8223    let Inst{11} = idx{2};
8224    let Inst{21} = idx{1};
8225    let Inst{20} = idx{0};
8226  }
8227  } // Predicates = [HasNEON, HasFullFP16]
8228
8229  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8230                                          V128, VectorIndexS,
8231                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8232    bits<2> idx;
8233    let Inst{11} = idx{1};
8234    let Inst{21} = idx{0};
8235  }
8236
8237  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8238                                      V128, V128,
8239                                      V128, VectorIndexS,
8240                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8241    bits<2> idx;
8242    let Inst{11} = idx{1};
8243    let Inst{21} = idx{0};
8244  }
8245
8246  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8247                                      V128, V128,
8248                                      V128, VectorIndexD,
8249                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8250    bits<1> idx;
8251    let Inst{11} = idx{0};
8252    let Inst{21} = 0;
8253  }
8254
8255  let Predicates = [HasNEON, HasFullFP16] in {
8256  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8257                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8258                                      asm, ".h", "", "", ".h", []> {
8259    bits<3> idx;
8260    let Inst{11} = idx{2};
8261    let Inst{21} = idx{1};
8262    let Inst{20} = idx{0};
8263  }
8264  } // Predicates = [HasNEON, HasFullFP16]
8265
8266  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8267                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8268                                      asm, ".s", "", "", ".s", []> {
8269    bits<2> idx;
8270    let Inst{11} = idx{1};
8271    let Inst{21} = idx{0};
8272  }
8273
8274  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8275                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8276                                      asm, ".d", "", "", ".d", []> {
8277    bits<1> idx;
8278    let Inst{11} = idx{0};
8279    let Inst{21} = 0;
8280  }
8281}
8282
8283multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8284                                 SDPatternOperator OpNodeLaneQ> {
8285
8286  def : Pat<(v4i16 (OpNodeLane
8287                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8288                     VectorIndexS32b:$idx)),
8289            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8290              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8291              (UImmS1XForm $idx))>;
8292
8293  def : Pat<(v4i16 (OpNodeLaneQ
8294                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8295                     VectorIndexH32b:$idx)),
8296            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8297              (UImmS1XForm $idx))>;
8298
8299  def : Pat<(v8i16 (OpNodeLane
8300                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8301                     VectorIndexS32b:$idx)),
8302            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8303              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8304              (UImmS1XForm $idx))>;
8305
8306  def : Pat<(v8i16 (OpNodeLaneQ
8307                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8308                     VectorIndexH32b:$idx)),
8309            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8310              (UImmS1XForm $idx))>;
8311
8312  def : Pat<(v2i32 (OpNodeLane
8313                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8314                     VectorIndexD32b:$idx)),
8315            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8316              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8317              (UImmS1XForm $idx))>;
8318
8319  def : Pat<(v2i32 (OpNodeLaneQ
8320                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8321                     VectorIndexS32b:$idx)),
8322            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8323              (UImmS1XForm $idx))>;
8324
8325  def : Pat<(v4i32 (OpNodeLane
8326                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8327                     VectorIndexD32b:$idx)),
8328            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8329              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8330              (UImmS1XForm $idx))>;
8331
8332  def : Pat<(v4i32 (OpNodeLaneQ
8333                     (v4i32 V128:$Rn),
8334                     (v4i32 V128:$Rm),
8335                     VectorIndexS32b:$idx)),
8336            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8337              (UImmS1XForm $idx))>;
8338
8339}
8340
8341multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8342                         SDPatternOperator OpNode> {
8343  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8344                                      V128_lo, VectorIndexH,
8345                                      asm, ".4h", ".4h", ".4h", ".h",
8346    [(set (v4i16 V64:$Rd),
8347        (OpNode (v4i16 V64:$Rn),
8348         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8349    bits<3> idx;
8350    let Inst{11} = idx{2};
8351    let Inst{21} = idx{1};
8352    let Inst{20} = idx{0};
8353  }
8354
8355  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8356                                      V128, V128,
8357                                      V128_lo, VectorIndexH,
8358                                      asm, ".8h", ".8h", ".8h", ".h",
8359    [(set (v8i16 V128:$Rd),
8360       (OpNode (v8i16 V128:$Rn),
8361         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8362    bits<3> idx;
8363    let Inst{11} = idx{2};
8364    let Inst{21} = idx{1};
8365    let Inst{20} = idx{0};
8366  }
8367
8368  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8369                                      V64, V64,
8370                                      V128, VectorIndexS,
8371                                      asm, ".2s", ".2s", ".2s",  ".s",
8372    [(set (v2i32 V64:$Rd),
8373       (OpNode (v2i32 V64:$Rn),
8374          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8375    bits<2> idx;
8376    let Inst{11} = idx{1};
8377    let Inst{21} = idx{0};
8378  }
8379
8380  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8381                                      V128, V128,
8382                                      V128, VectorIndexS,
8383                                      asm, ".4s", ".4s", ".4s", ".s",
8384    [(set (v4i32 V128:$Rd),
8385       (OpNode (v4i32 V128:$Rn),
8386          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8387    bits<2> idx;
8388    let Inst{11} = idx{1};
8389    let Inst{21} = idx{0};
8390  }
8391
8392  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8393                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8394                                      asm, ".h", "", "", ".h", []> {
8395    bits<3> idx;
8396    let Inst{11} = idx{2};
8397    let Inst{21} = idx{1};
8398    let Inst{20} = idx{0};
8399  }
8400
8401  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8402                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8403                                      asm, ".s", "", "", ".s",
8404      [(set (i32 FPR32Op:$Rd),
8405            (OpNode FPR32Op:$Rn,
8406                    (i32 (vector_extract (v4i32 V128:$Rm),
8407                                         VectorIndexS:$idx))))]> {
8408    bits<2> idx;
8409    let Inst{11} = idx{1};
8410    let Inst{21} = idx{0};
8411  }
8412}
8413
8414multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8415                               SDPatternOperator OpNode> {
8416  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8417                                      V64, V64,
8418                                      V128_lo, VectorIndexH,
8419                                      asm, ".4h", ".4h", ".4h", ".h",
8420    [(set (v4i16 V64:$Rd),
8421        (OpNode (v4i16 V64:$Rn),
8422         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8423    bits<3> idx;
8424    let Inst{11} = idx{2};
8425    let Inst{21} = idx{1};
8426    let Inst{20} = idx{0};
8427  }
8428
8429  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8430                                      V128, V128,
8431                                      V128_lo, VectorIndexH,
8432                                      asm, ".8h", ".8h", ".8h", ".h",
8433    [(set (v8i16 V128:$Rd),
8434       (OpNode (v8i16 V128:$Rn),
8435         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8436    bits<3> idx;
8437    let Inst{11} = idx{2};
8438    let Inst{21} = idx{1};
8439    let Inst{20} = idx{0};
8440  }
8441
8442  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8443                                      V64, V64,
8444                                      V128, VectorIndexS,
8445                                      asm, ".2s", ".2s", ".2s", ".s",
8446    [(set (v2i32 V64:$Rd),
8447       (OpNode (v2i32 V64:$Rn),
8448          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8449    bits<2> idx;
8450    let Inst{11} = idx{1};
8451    let Inst{21} = idx{0};
8452  }
8453
8454  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8455                                      V128, V128,
8456                                      V128, VectorIndexS,
8457                                      asm, ".4s", ".4s", ".4s", ".s",
8458    [(set (v4i32 V128:$Rd),
8459       (OpNode (v4i32 V128:$Rn),
8460          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8461    bits<2> idx;
8462    let Inst{11} = idx{1};
8463    let Inst{21} = idx{0};
8464  }
8465}
8466
8467multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8468                                   SDPatternOperator OpNode> {
8469  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8470                                          V128_lo, VectorIndexH,
8471                                          asm, ".4h", ".4h", ".4h", ".h",
8472    [(set (v4i16 V64:$dst),
8473        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8474         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8475    bits<3> idx;
8476    let Inst{11} = idx{2};
8477    let Inst{21} = idx{1};
8478    let Inst{20} = idx{0};
8479  }
8480
8481  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8482                                      V128, V128,
8483                                      V128_lo, VectorIndexH,
8484                                      asm, ".8h", ".8h", ".8h", ".h",
8485    [(set (v8i16 V128:$dst),
8486       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8487         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8488    bits<3> idx;
8489    let Inst{11} = idx{2};
8490    let Inst{21} = idx{1};
8491    let Inst{20} = idx{0};
8492  }
8493
8494  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8495                                      V64, V64,
8496                                      V128, VectorIndexS,
8497                                      asm, ".2s", ".2s", ".2s", ".s",
8498    [(set (v2i32 V64:$dst),
8499       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8500          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8501    bits<2> idx;
8502    let Inst{11} = idx{1};
8503    let Inst{21} = idx{0};
8504  }
8505
8506  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8507                                      V128, V128,
8508                                      V128, VectorIndexS,
8509                                      asm, ".4s", ".4s", ".4s", ".s",
8510    [(set (v4i32 V128:$dst),
8511       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8512          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8513    bits<2> idx;
8514    let Inst{11} = idx{1};
8515    let Inst{21} = idx{0};
8516  }
8517}
8518
8519multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8520                             SDPatternOperator OpNode> {
8521  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8522                                      V128, V64,
8523                                      V128_lo, VectorIndexH,
8524                                      asm, ".4s", ".4s", ".4h", ".h",
8525    [(set (v4i32 V128:$Rd),
8526        (OpNode (v4i16 V64:$Rn),
8527         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8528    bits<3> idx;
8529    let Inst{11} = idx{2};
8530    let Inst{21} = idx{1};
8531    let Inst{20} = idx{0};
8532  }
8533
8534  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8535                                      V128, V128,
8536                                      V128_lo, VectorIndexH,
8537                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8538    [(set (v4i32 V128:$Rd),
8539          (OpNode (extract_high_v8i16 V128:$Rn),
8540                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8541                                                      VectorIndexH:$idx))))]> {
8542
8543    bits<3> idx;
8544    let Inst{11} = idx{2};
8545    let Inst{21} = idx{1};
8546    let Inst{20} = idx{0};
8547  }
8548
8549  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8550                                      V128, V64,
8551                                      V128, VectorIndexS,
8552                                      asm, ".2d", ".2d", ".2s", ".s",
8553    [(set (v2i64 V128:$Rd),
8554        (OpNode (v2i32 V64:$Rn),
8555         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8556    bits<2> idx;
8557    let Inst{11} = idx{1};
8558    let Inst{21} = idx{0};
8559  }
8560
8561  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8562                                      V128, V128,
8563                                      V128, VectorIndexS,
8564                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8565    [(set (v2i64 V128:$Rd),
8566          (OpNode (extract_high_v4i32 V128:$Rn),
8567                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8568                                                      VectorIndexS:$idx))))]> {
8569    bits<2> idx;
8570    let Inst{11} = idx{1};
8571    let Inst{21} = idx{0};
8572  }
8573
8574  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8575                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8576                                      asm, ".h", "", "", ".h", []> {
8577    bits<3> idx;
8578    let Inst{11} = idx{2};
8579    let Inst{21} = idx{1};
8580    let Inst{20} = idx{0};
8581  }
8582
8583  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8584                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8585                                      asm, ".s", "", "", ".s", []> {
8586    bits<2> idx;
8587    let Inst{11} = idx{1};
8588    let Inst{21} = idx{0};
8589  }
8590}
8591
8592multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8593                                       SDPatternOperator Accum> {
8594  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8595                                      V128, V64,
8596                                      V128_lo, VectorIndexH,
8597                                      asm, ".4s", ".4s", ".4h", ".h",
8598    [(set (v4i32 V128:$dst),
8599          (Accum (v4i32 V128:$Rd),
8600                 (v4i32 (int_aarch64_neon_sqdmull
8601                             (v4i16 V64:$Rn),
8602                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8603                                                    VectorIndexH:$idx))))))]> {
8604    bits<3> idx;
8605    let Inst{11} = idx{2};
8606    let Inst{21} = idx{1};
8607    let Inst{20} = idx{0};
8608  }
8609
8610  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8611  // intermediate EXTRACT_SUBREG would be untyped.
8612  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8613                (i32 (vector_extract (v4i32
8614                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8615                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8616                                                    VectorIndexH:$idx)))),
8617                         (i64 0))))),
8618            (EXTRACT_SUBREG
8619                (!cast<Instruction>(NAME # v4i16_indexed)
8620                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8621                    V128_lo:$Rm, VectorIndexH:$idx),
8622                ssub)>;
8623
8624  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8625                                      V128, V128,
8626                                      V128_lo, VectorIndexH,
8627                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8628    [(set (v4i32 V128:$dst),
8629          (Accum (v4i32 V128:$Rd),
8630                 (v4i32 (int_aarch64_neon_sqdmull
8631                            (extract_high_v8i16 V128:$Rn),
8632                            (extract_high_v8i16
8633                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8634                                                VectorIndexH:$idx))))))]> {
8635    bits<3> idx;
8636    let Inst{11} = idx{2};
8637    let Inst{21} = idx{1};
8638    let Inst{20} = idx{0};
8639  }
8640
8641  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8642                                      V128, V64,
8643                                      V128, VectorIndexS,
8644                                      asm, ".2d", ".2d", ".2s", ".s",
8645    [(set (v2i64 V128:$dst),
8646        (Accum (v2i64 V128:$Rd),
8647               (v2i64 (int_aarch64_neon_sqdmull
8648                          (v2i32 V64:$Rn),
8649                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8650                                                 VectorIndexS:$idx))))))]> {
8651    bits<2> idx;
8652    let Inst{11} = idx{1};
8653    let Inst{21} = idx{0};
8654  }
8655
8656  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8657                                      V128, V128,
8658                                      V128, VectorIndexS,
8659                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8660    [(set (v2i64 V128:$dst),
8661          (Accum (v2i64 V128:$Rd),
8662                 (v2i64 (int_aarch64_neon_sqdmull
8663                            (extract_high_v4i32 V128:$Rn),
8664                            (extract_high_v4i32
8665                                (AArch64duplane32 (v4i32 V128:$Rm),
8666                                                VectorIndexS:$idx))))))]> {
8667    bits<2> idx;
8668    let Inst{11} = idx{1};
8669    let Inst{21} = idx{0};
8670  }
8671
8672  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8673                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8674                                      asm, ".h", "", "", ".h", []> {
8675    bits<3> idx;
8676    let Inst{11} = idx{2};
8677    let Inst{21} = idx{1};
8678    let Inst{20} = idx{0};
8679  }
8680
8681
8682  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8683                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8684                                      asm, ".s", "", "", ".s",
8685    [(set (i64 FPR64Op:$dst),
8686          (Accum (i64 FPR64Op:$Rd),
8687                 (i64 (int_aarch64_neon_sqdmulls_scalar
8688                            (i32 FPR32Op:$Rn),
8689                            (i32 (vector_extract (v4i32 V128:$Rm),
8690                                                 VectorIndexS:$idx))))))]> {
8691
8692    bits<2> idx;
8693    let Inst{11} = idx{1};
8694    let Inst{21} = idx{0};
8695  }
8696}
8697
8698multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8699                                   SDPatternOperator OpNode> {
8700  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8701  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8702                                      V128, V64,
8703                                      V128_lo, VectorIndexH,
8704                                      asm, ".4s", ".4s", ".4h", ".h",
8705    [(set (v4i32 V128:$Rd),
8706        (OpNode (v4i16 V64:$Rn),
8707         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
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 v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8715                                      V128, V128,
8716                                      V128_lo, VectorIndexH,
8717                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8718    [(set (v4i32 V128:$Rd),
8719          (OpNode (extract_high_v8i16 V128:$Rn),
8720                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8721                                                      VectorIndexH:$idx))))]> {
8722
8723    bits<3> idx;
8724    let Inst{11} = idx{2};
8725    let Inst{21} = idx{1};
8726    let Inst{20} = idx{0};
8727  }
8728
8729  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8730                                      V128, V64,
8731                                      V128, VectorIndexS,
8732                                      asm, ".2d", ".2d", ".2s", ".s",
8733    [(set (v2i64 V128:$Rd),
8734        (OpNode (v2i32 V64:$Rn),
8735         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8736    bits<2> idx;
8737    let Inst{11} = idx{1};
8738    let Inst{21} = idx{0};
8739  }
8740
8741  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8742                                      V128, V128,
8743                                      V128, VectorIndexS,
8744                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8745    [(set (v2i64 V128:$Rd),
8746          (OpNode (extract_high_v4i32 V128:$Rn),
8747                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8748                                                      VectorIndexS:$idx))))]> {
8749    bits<2> idx;
8750    let Inst{11} = idx{1};
8751    let Inst{21} = idx{0};
8752  }
8753  }
8754}
8755
8756multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8757                                       SDPatternOperator OpNode> {
8758  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
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        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8765         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8766    bits<3> idx;
8767    let Inst{11} = idx{2};
8768    let Inst{21} = idx{1};
8769    let Inst{20} = idx{0};
8770  }
8771
8772  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8773                                      V128, V128,
8774                                      V128_lo, VectorIndexH,
8775                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8776    [(set (v4i32 V128:$dst),
8777          (OpNode (v4i32 V128:$Rd),
8778                  (extract_high_v8i16 V128:$Rn),
8779                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8780                                                      VectorIndexH:$idx))))]> {
8781    bits<3> idx;
8782    let Inst{11} = idx{2};
8783    let Inst{21} = idx{1};
8784    let Inst{20} = idx{0};
8785  }
8786
8787  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8788                                      V128, V64,
8789                                      V128, VectorIndexS,
8790                                      asm, ".2d", ".2d", ".2s", ".s",
8791    [(set (v2i64 V128:$dst),
8792        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8793         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8794    bits<2> idx;
8795    let Inst{11} = idx{1};
8796    let Inst{21} = idx{0};
8797  }
8798
8799  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8800                                      V128, V128,
8801                                      V128, VectorIndexS,
8802                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8803    [(set (v2i64 V128:$dst),
8804          (OpNode (v2i64 V128:$Rd),
8805                  (extract_high_v4i32 V128:$Rn),
8806                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8807                                                      VectorIndexS:$idx))))]> {
8808    bits<2> idx;
8809    let Inst{11} = idx{1};
8810    let Inst{21} = idx{0};
8811  }
8812  }
8813}
8814
8815//----------------------------------------------------------------------------
8816// AdvSIMD scalar shift by immediate
8817//----------------------------------------------------------------------------
8818
8819let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8820class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8821                     RegisterClass regtype1, RegisterClass regtype2,
8822                     Operand immtype, string asm, list<dag> pattern>
8823  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8824      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8825    Sched<[WriteV]> {
8826  bits<5> Rd;
8827  bits<5> Rn;
8828  bits<7> imm;
8829  let Inst{31-30} = 0b01;
8830  let Inst{29}    = U;
8831  let Inst{28-23} = 0b111110;
8832  let Inst{22-16} = fixed_imm;
8833  let Inst{15-11} = opc;
8834  let Inst{10}    = 1;
8835  let Inst{9-5} = Rn;
8836  let Inst{4-0} = Rd;
8837}
8838
8839let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8840class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8841                     RegisterClass regtype1, RegisterClass regtype2,
8842                     Operand immtype, string asm, list<dag> pattern>
8843  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8844      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8845    Sched<[WriteV]> {
8846  bits<5> Rd;
8847  bits<5> Rn;
8848  bits<7> imm;
8849  let Inst{31-30} = 0b01;
8850  let Inst{29}    = U;
8851  let Inst{28-23} = 0b111110;
8852  let Inst{22-16} = fixed_imm;
8853  let Inst{15-11} = opc;
8854  let Inst{10}    = 1;
8855  let Inst{9-5} = Rn;
8856  let Inst{4-0} = Rd;
8857}
8858
8859
8860multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8861  let Predicates = [HasNEON, HasFullFP16] in {
8862  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8863                              FPR16, FPR16, vecshiftR16, asm, []> {
8864    let Inst{19-16} = imm{3-0};
8865  }
8866  } // Predicates = [HasNEON, HasFullFP16]
8867  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8868                              FPR32, FPR32, vecshiftR32, asm, []> {
8869    let Inst{20-16} = imm{4-0};
8870  }
8871  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8872                              FPR64, FPR64, vecshiftR64, asm, []> {
8873    let Inst{21-16} = imm{5-0};
8874  }
8875}
8876
8877multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8878                             SDPatternOperator OpNode> {
8879  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8880                              FPR64, FPR64, vecshiftR64, asm,
8881  [(set (i64 FPR64:$Rd),
8882     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8883    let Inst{21-16} = imm{5-0};
8884  }
8885
8886  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8887            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8888}
8889
8890multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8891                                 SDPatternOperator OpNode = null_frag> {
8892  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8893                              FPR64, FPR64, vecshiftR64, asm,
8894  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8895                                                   (i32 vecshiftR64:$imm)))]> {
8896    let Inst{21-16} = imm{5-0};
8897  }
8898
8899  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8900                           (i32 vecshiftR64:$imm))),
8901            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8902                                            vecshiftR64:$imm)>;
8903}
8904
8905multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8906                             SDPatternOperator OpNode> {
8907  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8908                              FPR64, FPR64, vecshiftL64, asm,
8909    [(set (v1i64 FPR64:$Rd),
8910       (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8911    let Inst{21-16} = imm{5-0};
8912  }
8913}
8914
8915let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8916multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8917  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8918                              FPR64, FPR64, vecshiftL64, asm, []> {
8919    let Inst{21-16} = imm{5-0};
8920  }
8921}
8922
8923let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8924multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8925                               SDPatternOperator OpNode = null_frag> {
8926  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8927                              FPR8, FPR16, vecshiftR8, asm, []> {
8928    let Inst{18-16} = imm{2-0};
8929  }
8930
8931  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8932                              FPR16, FPR32, vecshiftR16, asm, []> {
8933    let Inst{19-16} = imm{3-0};
8934  }
8935
8936  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8937                              FPR32, FPR64, vecshiftR32, asm,
8938    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8939    let Inst{20-16} = imm{4-0};
8940  }
8941}
8942
8943multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8944                                SDPatternOperator OpNode> {
8945  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8946                              FPR8, FPR8, vecshiftL8, asm, []> {
8947    let Inst{18-16} = imm{2-0};
8948  }
8949
8950  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8951                              FPR16, FPR16, vecshiftL16, asm, []> {
8952    let Inst{19-16} = imm{3-0};
8953  }
8954
8955  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8956                              FPR32, FPR32, vecshiftL32, asm,
8957    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8958    let Inst{20-16} = imm{4-0};
8959  }
8960
8961  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8962                              FPR64, FPR64, vecshiftL64, asm,
8963    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8964    let Inst{21-16} = imm{5-0};
8965  }
8966
8967  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8968            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8969}
8970
8971multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8972  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8973                              FPR8, FPR8, vecshiftR8, asm, []> {
8974    let Inst{18-16} = imm{2-0};
8975  }
8976
8977  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8978                              FPR16, FPR16, vecshiftR16, asm, []> {
8979    let Inst{19-16} = imm{3-0};
8980  }
8981
8982  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8983                              FPR32, FPR32, vecshiftR32, asm, []> {
8984    let Inst{20-16} = imm{4-0};
8985  }
8986
8987  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8988                              FPR64, FPR64, vecshiftR64, asm, []> {
8989    let Inst{21-16} = imm{5-0};
8990  }
8991}
8992
8993//----------------------------------------------------------------------------
8994// AdvSIMD vector x indexed element
8995//----------------------------------------------------------------------------
8996
8997let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8998class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8999                     RegisterOperand dst_reg, RegisterOperand src_reg,
9000                     Operand immtype,
9001                     string asm, string dst_kind, string src_kind,
9002                     list<dag> pattern>
9003  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9004      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9005           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9006    Sched<[WriteV]> {
9007  bits<5> Rd;
9008  bits<5> Rn;
9009  let Inst{31}    = 0;
9010  let Inst{30}    = Q;
9011  let Inst{29}    = U;
9012  let Inst{28-23} = 0b011110;
9013  let Inst{22-16} = fixed_imm;
9014  let Inst{15-11} = opc;
9015  let Inst{10}    = 1;
9016  let Inst{9-5}   = Rn;
9017  let Inst{4-0}   = Rd;
9018}
9019
9020let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9021class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9022                     RegisterOperand vectype1, RegisterOperand vectype2,
9023                     Operand immtype,
9024                     string asm, string dst_kind, string src_kind,
9025                     list<dag> pattern>
9026  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9027      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9028           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9029    Sched<[WriteV]> {
9030  bits<5> Rd;
9031  bits<5> Rn;
9032  let Inst{31}    = 0;
9033  let Inst{30}    = Q;
9034  let Inst{29}    = U;
9035  let Inst{28-23} = 0b011110;
9036  let Inst{22-16} = fixed_imm;
9037  let Inst{15-11} = opc;
9038  let Inst{10}    = 1;
9039  let Inst{9-5}   = Rn;
9040  let Inst{4-0}   = Rd;
9041}
9042
9043multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9044                              Intrinsic OpNode> {
9045  let Predicates = [HasNEON, HasFullFP16] in {
9046  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9047                                  V64, V64, vecshiftR16,
9048                                  asm, ".4h", ".4h",
9049      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9050    bits<4> imm;
9051    let Inst{19-16} = imm;
9052  }
9053
9054  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9055                                  V128, V128, vecshiftR16,
9056                                  asm, ".8h", ".8h",
9057      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9058    bits<4> imm;
9059    let Inst{19-16} = imm;
9060  }
9061  } // Predicates = [HasNEON, HasFullFP16]
9062  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9063                                  V64, V64, vecshiftR32,
9064                                  asm, ".2s", ".2s",
9065      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9066    bits<5> imm;
9067    let Inst{20-16} = imm;
9068  }
9069
9070  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9071                                  V128, V128, vecshiftR32,
9072                                  asm, ".4s", ".4s",
9073      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9074    bits<5> imm;
9075    let Inst{20-16} = imm;
9076  }
9077
9078  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9079                                  V128, V128, vecshiftR64,
9080                                  asm, ".2d", ".2d",
9081      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9082    bits<6> imm;
9083    let Inst{21-16} = imm;
9084  }
9085}
9086
9087multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9088                                  Intrinsic OpNode> {
9089  let Predicates = [HasNEON, HasFullFP16] in {
9090  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9091                                  V64, V64, vecshiftR16,
9092                                  asm, ".4h", ".4h",
9093      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9094    bits<4> imm;
9095    let Inst{19-16} = imm;
9096  }
9097
9098  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9099                                  V128, V128, vecshiftR16,
9100                                  asm, ".8h", ".8h",
9101      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9102    bits<4> imm;
9103    let Inst{19-16} = imm;
9104  }
9105  } // Predicates = [HasNEON, HasFullFP16]
9106
9107  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9108                                  V64, V64, vecshiftR32,
9109                                  asm, ".2s", ".2s",
9110      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9111    bits<5> imm;
9112    let Inst{20-16} = imm;
9113  }
9114
9115  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9116                                  V128, V128, vecshiftR32,
9117                                  asm, ".4s", ".4s",
9118      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9119    bits<5> imm;
9120    let Inst{20-16} = imm;
9121  }
9122
9123  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9124                                  V128, V128, vecshiftR64,
9125                                  asm, ".2d", ".2d",
9126      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9127    bits<6> imm;
9128    let Inst{21-16} = imm;
9129  }
9130}
9131
9132multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9133                                     SDPatternOperator OpNode> {
9134  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9135                                  V64, V128, vecshiftR16Narrow,
9136                                  asm, ".8b", ".8h",
9137      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9138    bits<3> imm;
9139    let Inst{18-16} = imm;
9140  }
9141
9142  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9143                                  V128, V128, vecshiftR16Narrow,
9144                                  asm#"2", ".16b", ".8h", []> {
9145    bits<3> imm;
9146    let Inst{18-16} = imm;
9147    let hasSideEffects = 0;
9148  }
9149
9150  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9151                                  V64, V128, vecshiftR32Narrow,
9152                                  asm, ".4h", ".4s",
9153      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9154    bits<4> imm;
9155    let Inst{19-16} = imm;
9156  }
9157
9158  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9159                                  V128, V128, vecshiftR32Narrow,
9160                                  asm#"2", ".8h", ".4s", []> {
9161    bits<4> imm;
9162    let Inst{19-16} = imm;
9163    let hasSideEffects = 0;
9164  }
9165
9166  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9167                                  V64, V128, vecshiftR64Narrow,
9168                                  asm, ".2s", ".2d",
9169      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9170    bits<5> imm;
9171    let Inst{20-16} = imm;
9172  }
9173
9174  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9175                                  V128, V128, vecshiftR64Narrow,
9176                                  asm#"2", ".4s", ".2d", []> {
9177    bits<5> imm;
9178    let Inst{20-16} = imm;
9179    let hasSideEffects = 0;
9180  }
9181
9182  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9183  // themselves, so put them here instead.
9184
9185  // Patterns involving what's effectively an insert high and a normal
9186  // intrinsic, represented by CONCAT_VECTORS.
9187  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9188                                                   vecshiftR16Narrow:$imm)),
9189            (!cast<Instruction>(NAME # "v16i8_shift")
9190                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9191                V128:$Rn, vecshiftR16Narrow:$imm)>;
9192  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9193                                                     vecshiftR32Narrow:$imm)),
9194            (!cast<Instruction>(NAME # "v8i16_shift")
9195                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9196                V128:$Rn, vecshiftR32Narrow:$imm)>;
9197  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9198                                                     vecshiftR64Narrow:$imm)),
9199            (!cast<Instruction>(NAME # "v4i32_shift")
9200                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9201                V128:$Rn, vecshiftR64Narrow:$imm)>;
9202}
9203
9204multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9205                                SDPatternOperator OpNode> {
9206  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9207                                  V64, V64, vecshiftL8,
9208                                  asm, ".8b", ".8b",
9209                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9210                       (i32 vecshiftL8:$imm)))]> {
9211    bits<3> imm;
9212    let Inst{18-16} = imm;
9213  }
9214
9215  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9216                                  V128, V128, vecshiftL8,
9217                                  asm, ".16b", ".16b",
9218             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9219                   (i32 vecshiftL8:$imm)))]> {
9220    bits<3> imm;
9221    let Inst{18-16} = imm;
9222  }
9223
9224  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9225                                  V64, V64, vecshiftL16,
9226                                  asm, ".4h", ".4h",
9227              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9228                    (i32 vecshiftL16:$imm)))]> {
9229    bits<4> imm;
9230    let Inst{19-16} = imm;
9231  }
9232
9233  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9234                                  V128, V128, vecshiftL16,
9235                                  asm, ".8h", ".8h",
9236            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9237                  (i32 vecshiftL16:$imm)))]> {
9238    bits<4> imm;
9239    let Inst{19-16} = imm;
9240  }
9241
9242  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9243                                  V64, V64, vecshiftL32,
9244                                  asm, ".2s", ".2s",
9245              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9246                    (i32 vecshiftL32:$imm)))]> {
9247    bits<5> imm;
9248    let Inst{20-16} = imm;
9249  }
9250
9251  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9252                                  V128, V128, vecshiftL32,
9253                                  asm, ".4s", ".4s",
9254            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9255                  (i32 vecshiftL32:$imm)))]> {
9256    bits<5> imm;
9257    let Inst{20-16} = imm;
9258  }
9259
9260  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9261                                  V128, V128, vecshiftL64,
9262                                  asm, ".2d", ".2d",
9263            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9264                  (i32 vecshiftL64:$imm)))]> {
9265    bits<6> imm;
9266    let Inst{21-16} = imm;
9267  }
9268}
9269
9270multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9271                                SDPatternOperator OpNode> {
9272  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9273                                  V64, V64, vecshiftR8,
9274                                  asm, ".8b", ".8b",
9275                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9276                       (i32 vecshiftR8:$imm)))]> {
9277    bits<3> imm;
9278    let Inst{18-16} = imm;
9279  }
9280
9281  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9282                                  V128, V128, vecshiftR8,
9283                                  asm, ".16b", ".16b",
9284             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9285                   (i32 vecshiftR8:$imm)))]> {
9286    bits<3> imm;
9287    let Inst{18-16} = imm;
9288  }
9289
9290  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9291                                  V64, V64, vecshiftR16,
9292                                  asm, ".4h", ".4h",
9293              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9294                    (i32 vecshiftR16:$imm)))]> {
9295    bits<4> imm;
9296    let Inst{19-16} = imm;
9297  }
9298
9299  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9300                                  V128, V128, vecshiftR16,
9301                                  asm, ".8h", ".8h",
9302            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9303                  (i32 vecshiftR16:$imm)))]> {
9304    bits<4> imm;
9305    let Inst{19-16} = imm;
9306  }
9307
9308  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9309                                  V64, V64, vecshiftR32,
9310                                  asm, ".2s", ".2s",
9311              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9312                    (i32 vecshiftR32:$imm)))]> {
9313    bits<5> imm;
9314    let Inst{20-16} = imm;
9315  }
9316
9317  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9318                                  V128, V128, vecshiftR32,
9319                                  asm, ".4s", ".4s",
9320            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9321                  (i32 vecshiftR32:$imm)))]> {
9322    bits<5> imm;
9323    let Inst{20-16} = imm;
9324  }
9325
9326  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9327                                  V128, V128, vecshiftR64,
9328                                  asm, ".2d", ".2d",
9329            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9330                  (i32 vecshiftR64:$imm)))]> {
9331    bits<6> imm;
9332    let Inst{21-16} = imm;
9333  }
9334}
9335
9336let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9337multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9338                                    SDPatternOperator OpNode = null_frag> {
9339  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9340                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9341                 [(set (v8i8 V64:$dst),
9342                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9343                           (i32 vecshiftR8:$imm)))]> {
9344    bits<3> imm;
9345    let Inst{18-16} = imm;
9346  }
9347
9348  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9349                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9350             [(set (v16i8 V128:$dst),
9351               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9352                       (i32 vecshiftR8:$imm)))]> {
9353    bits<3> imm;
9354    let Inst{18-16} = imm;
9355  }
9356
9357  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9358                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9359              [(set (v4i16 V64:$dst),
9360                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9361                        (i32 vecshiftR16:$imm)))]> {
9362    bits<4> imm;
9363    let Inst{19-16} = imm;
9364  }
9365
9366  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9367                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9368            [(set (v8i16 V128:$dst),
9369              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9370                      (i32 vecshiftR16:$imm)))]> {
9371    bits<4> imm;
9372    let Inst{19-16} = imm;
9373  }
9374
9375  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9376                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9377              [(set (v2i32 V64:$dst),
9378                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9379                        (i32 vecshiftR32:$imm)))]> {
9380    bits<5> imm;
9381    let Inst{20-16} = imm;
9382  }
9383
9384  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9385                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9386            [(set (v4i32 V128:$dst),
9387              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9388                      (i32 vecshiftR32:$imm)))]> {
9389    bits<5> imm;
9390    let Inst{20-16} = imm;
9391  }
9392
9393  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9394                                  V128, V128, vecshiftR64,
9395                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9396              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9397                      (i32 vecshiftR64:$imm)))]> {
9398    bits<6> imm;
9399    let Inst{21-16} = imm;
9400  }
9401}
9402
9403multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9404                                    SDPatternOperator OpNode = null_frag> {
9405  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9406                                  V64, V64, vecshiftL8,
9407                                  asm, ".8b", ".8b",
9408                    [(set (v8i8 V64:$dst),
9409                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9410                                  (i32 vecshiftL8:$imm)))]> {
9411    bits<3> imm;
9412    let Inst{18-16} = imm;
9413  }
9414
9415  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9416                                  V128, V128, vecshiftL8,
9417                                  asm, ".16b", ".16b",
9418                    [(set (v16i8 V128:$dst),
9419                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9420                                  (i32 vecshiftL8:$imm)))]> {
9421    bits<3> imm;
9422    let Inst{18-16} = imm;
9423  }
9424
9425  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9426                                  V64, V64, vecshiftL16,
9427                                  asm, ".4h", ".4h",
9428                    [(set (v4i16 V64:$dst),
9429                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9430                                   (i32 vecshiftL16:$imm)))]> {
9431    bits<4> imm;
9432    let Inst{19-16} = imm;
9433  }
9434
9435  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9436                                  V128, V128, vecshiftL16,
9437                                  asm, ".8h", ".8h",
9438                    [(set (v8i16 V128:$dst),
9439                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9440                                  (i32 vecshiftL16:$imm)))]> {
9441    bits<4> imm;
9442    let Inst{19-16} = imm;
9443  }
9444
9445  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9446                                  V64, V64, vecshiftL32,
9447                                  asm, ".2s", ".2s",
9448                    [(set (v2i32 V64:$dst),
9449                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9450                                  (i32 vecshiftL32:$imm)))]> {
9451    bits<5> imm;
9452    let Inst{20-16} = imm;
9453  }
9454
9455  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9456                                  V128, V128, vecshiftL32,
9457                                  asm, ".4s", ".4s",
9458                    [(set (v4i32 V128:$dst),
9459                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9460                                  (i32 vecshiftL32:$imm)))]> {
9461    bits<5> imm;
9462    let Inst{20-16} = imm;
9463  }
9464
9465  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9466                                  V128, V128, vecshiftL64,
9467                                  asm, ".2d", ".2d",
9468                    [(set (v2i64 V128:$dst),
9469                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9470                                  (i32 vecshiftL64:$imm)))]> {
9471    bits<6> imm;
9472    let Inst{21-16} = imm;
9473  }
9474}
9475
9476multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9477                                   SDPatternOperator OpNode> {
9478  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9479                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9480      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9481    bits<3> imm;
9482    let Inst{18-16} = imm;
9483  }
9484
9485  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9486                                  V128, V128, vecshiftL8,
9487                                  asm#"2", ".8h", ".16b",
9488      [(set (v8i16 V128:$Rd),
9489            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9490    bits<3> imm;
9491    let Inst{18-16} = imm;
9492  }
9493
9494  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9495                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9496      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9497    bits<4> imm;
9498    let Inst{19-16} = imm;
9499  }
9500
9501  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9502                                  V128, V128, vecshiftL16,
9503                                  asm#"2", ".4s", ".8h",
9504      [(set (v4i32 V128:$Rd),
9505            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9506
9507    bits<4> imm;
9508    let Inst{19-16} = imm;
9509  }
9510
9511  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9512                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9513      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9514    bits<5> imm;
9515    let Inst{20-16} = imm;
9516  }
9517
9518  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9519                                  V128, V128, vecshiftL32,
9520                                  asm#"2", ".2d", ".4s",
9521      [(set (v2i64 V128:$Rd),
9522            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9523    bits<5> imm;
9524    let Inst{20-16} = imm;
9525  }
9526}
9527
9528
9529//---
9530// Vector load/store
9531//---
9532// SIMD ldX/stX no-index memory references don't allow the optional
9533// ", #0" constant and handle post-indexing explicitly, so we use
9534// a more specialized parse method for them. Otherwise, it's the same as
9535// the general GPR64sp handling.
9536
9537class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9538                   string asm, dag oops, dag iops, list<dag> pattern>
9539  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9540  bits<5> Vt;
9541  bits<5> Rn;
9542  let Inst{31} = 0;
9543  let Inst{30} = Q;
9544  let Inst{29-23} = 0b0011000;
9545  let Inst{22} = L;
9546  let Inst{21-16} = 0b000000;
9547  let Inst{15-12} = opcode;
9548  let Inst{11-10} = size;
9549  let Inst{9-5} = Rn;
9550  let Inst{4-0} = Vt;
9551}
9552
9553class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9554                       string asm, dag oops, dag iops>
9555  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9556  bits<5> Vt;
9557  bits<5> Rn;
9558  bits<5> Xm;
9559  let Inst{31} = 0;
9560  let Inst{30} = Q;
9561  let Inst{29-23} = 0b0011001;
9562  let Inst{22} = L;
9563  let Inst{21} = 0;
9564  let Inst{20-16} = Xm;
9565  let Inst{15-12} = opcode;
9566  let Inst{11-10} = size;
9567  let Inst{9-5} = Rn;
9568  let Inst{4-0} = Vt;
9569}
9570
9571// The immediate form of AdvSIMD post-indexed addressing is encoded with
9572// register post-index addressing from the zero register.
9573multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9574                           int Offset, int Size> {
9575  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9576  //      "ld1\t$Vt, [$Rn], #16"
9577  // may get mapped to
9578  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9579  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9580                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9581                      GPR64sp:$Rn,
9582                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9583                      XZR), 1>;
9584
9585  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9586  //      "ld1.8b\t$Vt, [$Rn], #16"
9587  // may get mapped to
9588  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9589  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9590                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9591                      GPR64sp:$Rn,
9592                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9593                      XZR), 0>;
9594
9595  // E.g. "ld1.8b { v0, v1 }, [x1]"
9596  //      "ld1\t$Vt, [$Rn]"
9597  // may get mapped to
9598  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9599  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9600                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9601                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9602                      GPR64sp:$Rn), 0>;
9603
9604  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9605  //      "ld1\t$Vt, [$Rn], $Xm"
9606  // may get mapped to
9607  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9608  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9609                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9610                      GPR64sp:$Rn,
9611                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9612                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9613}
9614
9615multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9616                       int Offset128, int Offset64, bits<4> opcode> {
9617  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9618    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9619                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9620                           (ins GPR64sp:$Rn), []>;
9621    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9622                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9623                           (ins GPR64sp:$Rn), []>;
9624    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9625                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9626                           (ins GPR64sp:$Rn), []>;
9627    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9628                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9629                           (ins GPR64sp:$Rn), []>;
9630    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9631                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9632                           (ins GPR64sp:$Rn), []>;
9633    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9634                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9635                           (ins GPR64sp:$Rn), []>;
9636    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9637                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9638                           (ins GPR64sp:$Rn), []>;
9639
9640
9641    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9642                       (outs GPR64sp:$wback,
9643                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9644                       (ins GPR64sp:$Rn,
9645                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9646    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9647                       (outs GPR64sp:$wback,
9648                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9649                       (ins GPR64sp:$Rn,
9650                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9651    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9652                       (outs GPR64sp:$wback,
9653                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9654                       (ins GPR64sp:$Rn,
9655                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9656    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9657                       (outs GPR64sp:$wback,
9658                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9659                       (ins GPR64sp:$Rn,
9660                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9661    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9662                       (outs GPR64sp:$wback,
9663                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9664                       (ins GPR64sp:$Rn,
9665                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9666    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9667                       (outs GPR64sp:$wback,
9668                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9669                       (ins GPR64sp:$Rn,
9670                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9671    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9672                       (outs GPR64sp:$wback,
9673                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9674                       (ins GPR64sp:$Rn,
9675                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9676  }
9677
9678  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9679  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9680  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9681  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9682  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9683  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9684  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9685}
9686
9687// Only ld1/st1 has a v1d version.
9688multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9689                       int Offset128, int Offset64, bits<4> opcode> {
9690  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9691    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9692                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9693                                 GPR64sp:$Rn), []>;
9694    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9695                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9696                                GPR64sp:$Rn), []>;
9697    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9698                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9699                                GPR64sp:$Rn), []>;
9700    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9701                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9702                                GPR64sp:$Rn), []>;
9703    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9704                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9705                                GPR64sp:$Rn), []>;
9706    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9707                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9708                                GPR64sp:$Rn), []>;
9709    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9710                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9711                                GPR64sp:$Rn), []>;
9712
9713    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9714                       (outs GPR64sp:$wback),
9715                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9716                            GPR64sp:$Rn,
9717                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9718    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9719                       (outs GPR64sp:$wback),
9720                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9721                            GPR64sp:$Rn,
9722                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9723    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9724                       (outs GPR64sp:$wback),
9725                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9726                            GPR64sp:$Rn,
9727                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9728    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9729                       (outs GPR64sp:$wback),
9730                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9731                            GPR64sp:$Rn,
9732                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9733    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9734                       (outs GPR64sp:$wback),
9735                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9736                            GPR64sp:$Rn,
9737                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9738    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9739                       (outs GPR64sp:$wback),
9740                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9741                            GPR64sp:$Rn,
9742                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9743    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9744                       (outs GPR64sp:$wback),
9745                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9746                            GPR64sp:$Rn,
9747                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9748  }
9749
9750  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9751  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9752  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9753  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9754  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9755  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9756  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9757}
9758
9759multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9760                       int Offset128, int Offset64, bits<4> opcode>
9761  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9762
9763  // LD1 instructions have extra "1d" variants.
9764  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9765    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9766                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9767                           (ins GPR64sp:$Rn), []>;
9768
9769    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9770                       (outs GPR64sp:$wback,
9771                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9772                       (ins GPR64sp:$Rn,
9773                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9774  }
9775
9776  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9777}
9778
9779multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9780                       int Offset128, int Offset64, bits<4> opcode>
9781  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9782
9783  // ST1 instructions have extra "1d" variants.
9784  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9785    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9786                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9787                                GPR64sp:$Rn), []>;
9788
9789    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9790                       (outs GPR64sp:$wback),
9791                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9792                            GPR64sp:$Rn,
9793                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9794  }
9795
9796  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9797}
9798
9799multiclass SIMDLd1Multiple<string asm> {
9800  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9801  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9802  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9803  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9804}
9805
9806multiclass SIMDSt1Multiple<string asm> {
9807  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9808  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9809  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9810  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9811}
9812
9813multiclass SIMDLd2Multiple<string asm> {
9814  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9815}
9816
9817multiclass SIMDSt2Multiple<string asm> {
9818  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9819}
9820
9821multiclass SIMDLd3Multiple<string asm> {
9822  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9823}
9824
9825multiclass SIMDSt3Multiple<string asm> {
9826  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9827}
9828
9829multiclass SIMDLd4Multiple<string asm> {
9830  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9831}
9832
9833multiclass SIMDSt4Multiple<string asm> {
9834  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9835}
9836
9837//---
9838// AdvSIMD Load/store single-element
9839//---
9840
9841class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9842                         string asm, string operands, string cst,
9843                         dag oops, dag iops, list<dag> pattern>
9844  : I<oops, iops, asm, operands, cst, pattern> {
9845  bits<5> Vt;
9846  bits<5> Rn;
9847  let Inst{31} = 0;
9848  let Inst{29-24} = 0b001101;
9849  let Inst{22} = L;
9850  let Inst{21} = R;
9851  let Inst{15-13} = opcode;
9852  let Inst{9-5} = Rn;
9853  let Inst{4-0} = Vt;
9854}
9855
9856class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9857                         string asm, string operands, string cst,
9858                         dag oops, dag iops, list<dag> pattern>
9859  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9860  bits<5> Vt;
9861  bits<5> Rn;
9862  let Inst{31} = 0;
9863  let Inst{29-24} = 0b001101;
9864  let Inst{22} = L;
9865  let Inst{21} = R;
9866  let Inst{15-13} = opcode;
9867  let Inst{9-5} = Rn;
9868  let Inst{4-0} = Vt;
9869}
9870
9871
9872let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9873class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9874                  DAGOperand listtype>
9875  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9876                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
9877                       []> {
9878  let Inst{30} = Q;
9879  let Inst{23} = 0;
9880  let Inst{20-16} = 0b00000;
9881  let Inst{12} = S;
9882  let Inst{11-10} = size;
9883}
9884let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9885class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9886                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
9887  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9888                       "$Rn = $wback",
9889                       (outs GPR64sp:$wback, listtype:$Vt),
9890                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9891  bits<5> Xm;
9892  let Inst{30} = Q;
9893  let Inst{23} = 1;
9894  let Inst{20-16} = Xm;
9895  let Inst{12} = S;
9896  let Inst{11-10} = size;
9897}
9898
9899multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9900                          int Offset, int Size> {
9901  // E.g. "ld1r { v0.8b }, [x1], #1"
9902  //      "ld1r.8b\t$Vt, [$Rn], #1"
9903  // may get mapped to
9904  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9905  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9906                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9907                      GPR64sp:$Rn,
9908                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9909                      XZR), 1>;
9910
9911  // E.g. "ld1r.8b { v0 }, [x1], #1"
9912  //      "ld1r.8b\t$Vt, [$Rn], #1"
9913  // may get mapped to
9914  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9915  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9916                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9917                      GPR64sp:$Rn,
9918                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9919                      XZR), 0>;
9920
9921  // E.g. "ld1r.8b { v0 }, [x1]"
9922  //      "ld1r.8b\t$Vt, [$Rn]"
9923  // may get mapped to
9924  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9925  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9926                  (!cast<Instruction>(BaseName # "v" # layout)
9927                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9928                      GPR64sp:$Rn), 0>;
9929
9930  // E.g. "ld1r.8b { v0 }, [x1], x2"
9931  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9932  // may get mapped to
9933  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9934  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9935                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9936                      GPR64sp:$Rn,
9937                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9938                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9939}
9940
9941multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9942  int Offset1, int Offset2, int Offset4, int Offset8> {
9943  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9944                        !cast<DAGOperand>("VecList" # Count # "8b")>;
9945  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9946                        !cast<DAGOperand>("VecList" # Count #"16b")>;
9947  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9948                        !cast<DAGOperand>("VecList" # Count #"4h")>;
9949  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9950                        !cast<DAGOperand>("VecList" # Count #"8h")>;
9951  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9952                        !cast<DAGOperand>("VecList" # Count #"2s")>;
9953  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9954                        !cast<DAGOperand>("VecList" # Count #"4s")>;
9955  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9956                        !cast<DAGOperand>("VecList" # Count #"1d")>;
9957  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9958                        !cast<DAGOperand>("VecList" # Count #"2d")>;
9959
9960  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9961                                 !cast<DAGOperand>("VecList" # Count # "8b"),
9962                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9963  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9964                                 !cast<DAGOperand>("VecList" # Count # "16b"),
9965                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9966  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9967                                 !cast<DAGOperand>("VecList" # Count # "4h"),
9968                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9969  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9970                                 !cast<DAGOperand>("VecList" # Count # "8h"),
9971                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9972  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9973                                 !cast<DAGOperand>("VecList" # Count # "2s"),
9974                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9975  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9976                                 !cast<DAGOperand>("VecList" # Count # "4s"),
9977                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9978  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9979                                 !cast<DAGOperand>("VecList" # Count # "1d"),
9980                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9981  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9982                                 !cast<DAGOperand>("VecList" # Count # "2d"),
9983                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9984
9985  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9986  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9987  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9988  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9989  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9990  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9991  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9992  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9993}
9994
9995class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9996                      dag oops, dag iops, list<dag> pattern>
9997  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9998                       pattern> {
9999  // idx encoded in Q:S:size fields.
10000  bits<4> idx;
10001  let Inst{30} = idx{3};
10002  let Inst{23} = 0;
10003  let Inst{20-16} = 0b00000;
10004  let Inst{12} = idx{2};
10005  let Inst{11-10} = idx{1-0};
10006}
10007class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10008                      dag oops, dag iops, list<dag> pattern>
10009  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10010                           oops, iops, pattern> {
10011  // idx encoded in Q:S:size fields.
10012  bits<4> idx;
10013  let Inst{30} = idx{3};
10014  let Inst{23} = 0;
10015  let Inst{20-16} = 0b00000;
10016  let Inst{12} = idx{2};
10017  let Inst{11-10} = idx{1-0};
10018}
10019class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10020                          dag oops, dag iops>
10021  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10022                       "$Rn = $wback", oops, iops, []> {
10023  // idx encoded in Q:S:size fields.
10024  bits<4> idx;
10025  bits<5> Xm;
10026  let Inst{30} = idx{3};
10027  let Inst{23} = 1;
10028  let Inst{20-16} = Xm;
10029  let Inst{12} = idx{2};
10030  let Inst{11-10} = idx{1-0};
10031}
10032class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10033                          dag oops, dag iops>
10034  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10035                           "$Rn = $wback", oops, iops, []> {
10036  // idx encoded in Q:S:size fields.
10037  bits<4> idx;
10038  bits<5> Xm;
10039  let Inst{30} = idx{3};
10040  let Inst{23} = 1;
10041  let Inst{20-16} = Xm;
10042  let Inst{12} = idx{2};
10043  let Inst{11-10} = idx{1-0};
10044}
10045
10046class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10047                      dag oops, dag iops, list<dag> pattern>
10048  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10049                       pattern> {
10050  // idx encoded in Q:S:size<1> fields.
10051  bits<3> idx;
10052  let Inst{30} = idx{2};
10053  let Inst{23} = 0;
10054  let Inst{20-16} = 0b00000;
10055  let Inst{12} = idx{1};
10056  let Inst{11} = idx{0};
10057  let Inst{10} = size;
10058}
10059class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10060                      dag oops, dag iops, list<dag> pattern>
10061  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10062                           oops, iops, pattern> {
10063  // idx encoded in Q:S:size<1> fields.
10064  bits<3> idx;
10065  let Inst{30} = idx{2};
10066  let Inst{23} = 0;
10067  let Inst{20-16} = 0b00000;
10068  let Inst{12} = idx{1};
10069  let Inst{11} = idx{0};
10070  let Inst{10} = size;
10071}
10072
10073class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10074                          dag oops, dag iops>
10075  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10076                       "$Rn = $wback", oops, iops, []> {
10077  // idx encoded in Q:S:size<1> fields.
10078  bits<3> idx;
10079  bits<5> Xm;
10080  let Inst{30} = idx{2};
10081  let Inst{23} = 1;
10082  let Inst{20-16} = Xm;
10083  let Inst{12} = idx{1};
10084  let Inst{11} = idx{0};
10085  let Inst{10} = size;
10086}
10087class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10088                          dag oops, dag iops>
10089  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10090                           "$Rn = $wback", oops, iops, []> {
10091  // idx encoded in Q:S:size<1> fields.
10092  bits<3> idx;
10093  bits<5> Xm;
10094  let Inst{30} = idx{2};
10095  let Inst{23} = 1;
10096  let Inst{20-16} = Xm;
10097  let Inst{12} = idx{1};
10098  let Inst{11} = idx{0};
10099  let Inst{10} = size;
10100}
10101class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10102                      dag oops, dag iops, list<dag> pattern>
10103  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10104                       pattern> {
10105  // idx encoded in Q:S fields.
10106  bits<2> idx;
10107  let Inst{30} = idx{1};
10108  let Inst{23} = 0;
10109  let Inst{20-16} = 0b00000;
10110  let Inst{12} = idx{0};
10111  let Inst{11-10} = size;
10112}
10113class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10114                      dag oops, dag iops, list<dag> pattern>
10115  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10116                           oops, iops, pattern> {
10117  // idx encoded in Q:S fields.
10118  bits<2> idx;
10119  let Inst{30} = idx{1};
10120  let Inst{23} = 0;
10121  let Inst{20-16} = 0b00000;
10122  let Inst{12} = idx{0};
10123  let Inst{11-10} = size;
10124}
10125class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10126                          string asm, dag oops, dag iops>
10127  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10128                       "$Rn = $wback", oops, iops, []> {
10129  // idx encoded in Q:S fields.
10130  bits<2> idx;
10131  bits<5> Xm;
10132  let Inst{30} = idx{1};
10133  let Inst{23} = 1;
10134  let Inst{20-16} = Xm;
10135  let Inst{12} = idx{0};
10136  let Inst{11-10} = size;
10137}
10138class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10139                          string asm, dag oops, dag iops>
10140  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10141                           "$Rn = $wback", oops, iops, []> {
10142  // idx encoded in Q:S fields.
10143  bits<2> idx;
10144  bits<5> Xm;
10145  let Inst{30} = idx{1};
10146  let Inst{23} = 1;
10147  let Inst{20-16} = Xm;
10148  let Inst{12} = idx{0};
10149  let Inst{11-10} = size;
10150}
10151class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10152                      dag oops, dag iops, list<dag> pattern>
10153  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10154                       pattern> {
10155  // idx encoded in Q field.
10156  bits<1> idx;
10157  let Inst{30} = idx;
10158  let Inst{23} = 0;
10159  let Inst{20-16} = 0b00000;
10160  let Inst{12} = 0;
10161  let Inst{11-10} = size;
10162}
10163class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10164                      dag oops, dag iops, list<dag> pattern>
10165  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10166                           oops, iops, pattern> {
10167  // idx encoded in Q field.
10168  bits<1> idx;
10169  let Inst{30} = idx;
10170  let Inst{23} = 0;
10171  let Inst{20-16} = 0b00000;
10172  let Inst{12} = 0;
10173  let Inst{11-10} = size;
10174}
10175class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10176                          string asm, dag oops, dag iops>
10177  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10178                       "$Rn = $wback", oops, iops, []> {
10179  // idx encoded in Q field.
10180  bits<1> idx;
10181  bits<5> Xm;
10182  let Inst{30} = idx;
10183  let Inst{23} = 1;
10184  let Inst{20-16} = Xm;
10185  let Inst{12} = 0;
10186  let Inst{11-10} = size;
10187}
10188class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10189                          string asm, dag oops, dag iops>
10190  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10191                           "$Rn = $wback", oops, iops, []> {
10192  // idx encoded in Q field.
10193  bits<1> idx;
10194  bits<5> Xm;
10195  let Inst{30} = idx;
10196  let Inst{23} = 1;
10197  let Inst{20-16} = Xm;
10198  let Inst{12} = 0;
10199  let Inst{11-10} = size;
10200}
10201
10202let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10203multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10204                         RegisterOperand listtype,
10205                         RegisterOperand GPR64pi> {
10206  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10207                           (outs listtype:$dst),
10208                           (ins listtype:$Vt, VectorIndexB:$idx,
10209                                GPR64sp:$Rn), []>;
10210
10211  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10212                            (outs GPR64sp:$wback, listtype:$dst),
10213                            (ins listtype:$Vt, VectorIndexB:$idx,
10214                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10215}
10216let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10217multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10218                         RegisterOperand listtype,
10219                         RegisterOperand GPR64pi> {
10220  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10221                            (outs listtype:$dst),
10222                            (ins listtype:$Vt, VectorIndexH:$idx,
10223                                 GPR64sp:$Rn), []>;
10224
10225  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10226                            (outs GPR64sp:$wback, listtype:$dst),
10227                            (ins listtype:$Vt, VectorIndexH:$idx,
10228                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10229}
10230let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10231multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10232                         RegisterOperand listtype,
10233                         RegisterOperand GPR64pi> {
10234  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10235                            (outs listtype:$dst),
10236                            (ins listtype:$Vt, VectorIndexS:$idx,
10237                                 GPR64sp:$Rn), []>;
10238
10239  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10240                            (outs GPR64sp:$wback, listtype:$dst),
10241                            (ins listtype:$Vt, VectorIndexS:$idx,
10242                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10243}
10244let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10245multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10246                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10247  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10248                            (outs listtype:$dst),
10249                            (ins listtype:$Vt, VectorIndexD:$idx,
10250                                 GPR64sp:$Rn), []>;
10251
10252  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10253                            (outs GPR64sp:$wback, listtype:$dst),
10254                            (ins listtype:$Vt, VectorIndexD:$idx,
10255                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10256}
10257let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10258multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10259                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10260  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10261                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10262                                        GPR64sp:$Rn), []>;
10263
10264  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10265                                    (outs GPR64sp:$wback),
10266                                    (ins listtype:$Vt, VectorIndexB:$idx,
10267                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10268}
10269let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10270multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10271                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10272  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10273                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10274                                         GPR64sp:$Rn), []>;
10275
10276  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10277                            (outs GPR64sp:$wback),
10278                            (ins listtype:$Vt, VectorIndexH:$idx,
10279                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10280}
10281let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10282multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10283                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10284  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10285                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10286                                         GPR64sp:$Rn), []>;
10287
10288  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10289                            (outs GPR64sp:$wback),
10290                            (ins listtype:$Vt, VectorIndexS:$idx,
10291                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10292}
10293let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10294multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10295                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10296  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10297                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10298                                         GPR64sp:$Rn), []>;
10299
10300  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10301                            (outs GPR64sp:$wback),
10302                            (ins listtype:$Vt, VectorIndexD:$idx,
10303                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10304}
10305
10306multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10307                                 string Count, int Offset, Operand idxtype> {
10308  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10309  //      "ld1\t$Vt, [$Rn], #1"
10310  // may get mapped to
10311  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10312  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10313                  (!cast<Instruction>(NAME # Type  # "_POST")
10314                      GPR64sp:$Rn,
10315                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10316                      idxtype:$idx, XZR), 1>;
10317
10318  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10319  //      "ld1.8b\t$Vt, [$Rn], #1"
10320  // may get mapped to
10321  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10322  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10323                  (!cast<Instruction>(NAME # Type # "_POST")
10324                      GPR64sp:$Rn,
10325                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10326                      idxtype:$idx, XZR), 0>;
10327
10328  // E.g. "ld1.8b { v0 }[0], [x1]"
10329  //      "ld1.8b\t$Vt, [$Rn]"
10330  // may get mapped to
10331  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10332  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10333                      (!cast<Instruction>(NAME # Type)
10334                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10335                         idxtype:$idx, GPR64sp:$Rn), 0>;
10336
10337  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10338  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10339  // may get mapped to
10340  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10341  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10342                      (!cast<Instruction>(NAME # Type # "_POST")
10343                         GPR64sp:$Rn,
10344                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10345                         idxtype:$idx,
10346                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10347}
10348
10349multiclass SIMDLdSt1SingleAliases<string asm> {
10350  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10351  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10352  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10353  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10354}
10355
10356multiclass SIMDLdSt2SingleAliases<string asm> {
10357  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10358  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10359  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10360  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10361}
10362
10363multiclass SIMDLdSt3SingleAliases<string asm> {
10364  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10365  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10366  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10367  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10368}
10369
10370multiclass SIMDLdSt4SingleAliases<string asm> {
10371  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10372  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10373  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10374  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10375}
10376} // end of 'let Predicates = [HasNEON]'
10377
10378//----------------------------------------------------------------------------
10379// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10380//----------------------------------------------------------------------------
10381
10382let Predicates = [HasNEON, HasRDM] in {
10383
10384class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10385                                    RegisterOperand regtype, string asm,
10386                                    string kind, list<dag> pattern>
10387  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10388                                pattern> {
10389}
10390multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10391                                             SDPatternOperator Accum> {
10392  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10393    [(set (v4i16 V64:$dst),
10394          (Accum (v4i16 V64:$Rd),
10395                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
10396                                                   (v4i16 V64:$Rm)))))]>;
10397  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10398    [(set (v8i16 V128:$dst),
10399          (Accum (v8i16 V128:$Rd),
10400                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10401                                                   (v8i16 V128:$Rm)))))]>;
10402  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10403    [(set (v2i32 V64:$dst),
10404          (Accum (v2i32 V64:$Rd),
10405                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10406                                                   (v2i32 V64:$Rm)))))]>;
10407  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10408    [(set (v4i32 V128:$dst),
10409          (Accum (v4i32 V128:$Rd),
10410                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10411                                                   (v4i32 V128:$Rm)))))]>;
10412}
10413
10414multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10415                                     SDPatternOperator Accum> {
10416  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10417                                          V64, V64, V128_lo, VectorIndexH,
10418                                          asm, ".4h", ".4h", ".4h", ".h",
10419    [(set (v4i16 V64:$dst),
10420          (Accum (v4i16 V64:$Rd),
10421                 (v4i16 (int_aarch64_neon_sqrdmulh
10422                          (v4i16 V64:$Rn),
10423                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10424                                                    VectorIndexH:$idx))))))]> {
10425    bits<3> idx;
10426    let Inst{11} = idx{2};
10427    let Inst{21} = idx{1};
10428    let Inst{20} = idx{0};
10429  }
10430
10431  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10432                                          V128, V128, V128_lo, VectorIndexH,
10433                                          asm, ".8h", ".8h", ".8h", ".h",
10434    [(set (v8i16 V128:$dst),
10435          (Accum (v8i16 V128:$Rd),
10436                 (v8i16 (int_aarch64_neon_sqrdmulh
10437                          (v8i16 V128:$Rn),
10438                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10439                                                   VectorIndexH:$idx))))))]> {
10440    bits<3> idx;
10441    let Inst{11} = idx{2};
10442    let Inst{21} = idx{1};
10443    let Inst{20} = idx{0};
10444  }
10445
10446  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10447                                          V64, V64, V128, VectorIndexS,
10448                                          asm, ".2s", ".2s", ".2s", ".s",
10449    [(set (v2i32 V64:$dst),
10450        (Accum (v2i32 V64:$Rd),
10451               (v2i32 (int_aarch64_neon_sqrdmulh
10452                        (v2i32 V64:$Rn),
10453                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10454                                                 VectorIndexS:$idx))))))]> {
10455    bits<2> idx;
10456    let Inst{11} = idx{1};
10457    let Inst{21} = idx{0};
10458  }
10459
10460  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10461  // an intermediate EXTRACT_SUBREG would be untyped.
10462  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10463  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10464  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10465                       (i32 (vector_extract
10466                               (v4i32 (insert_subvector
10467                                       (undef),
10468                                        (v2i32 (int_aarch64_neon_sqrdmulh
10469                                                 (v2i32 V64:$Rn),
10470                                                 (v2i32 (AArch64duplane32
10471                                                          (v4i32 V128:$Rm),
10472                                                          VectorIndexS:$idx)))),
10473                                      (i32 0))),
10474                               (i64 0))))),
10475            (EXTRACT_SUBREG
10476                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10477                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10478                                                FPR32Op:$Rd,
10479                                                ssub)),
10480                          V64:$Rn,
10481                          V128:$Rm,
10482                          VectorIndexS:$idx)),
10483                ssub)>;
10484
10485  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10486                                          V128, V128, V128, VectorIndexS,
10487                                          asm, ".4s", ".4s", ".4s", ".s",
10488    [(set (v4i32 V128:$dst),
10489          (Accum (v4i32 V128:$Rd),
10490                 (v4i32 (int_aarch64_neon_sqrdmulh
10491                          (v4i32 V128:$Rn),
10492                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10493                                                   VectorIndexS:$idx))))))]> {
10494    bits<2> idx;
10495    let Inst{11} = idx{1};
10496    let Inst{21} = idx{0};
10497  }
10498
10499  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10500  // an intermediate EXTRACT_SUBREG would be untyped.
10501  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10502                        (i32 (vector_extract
10503                               (v4i32 (int_aarch64_neon_sqrdmulh
10504                                        (v4i32 V128:$Rn),
10505                                        (v4i32 (AArch64duplane32
10506                                                 (v4i32 V128:$Rm),
10507                                                 VectorIndexS:$idx)))),
10508                               (i64 0))))),
10509            (EXTRACT_SUBREG
10510                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10511                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10512                                               FPR32Op:$Rd,
10513                                               ssub)),
10514                         V128:$Rn,
10515                         V128:$Rm,
10516                         VectorIndexS:$idx)),
10517                ssub)>;
10518
10519  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10520                                        FPR16Op, FPR16Op, V128_lo,
10521                                        VectorIndexH, asm, ".h", "", "", ".h",
10522                                        []> {
10523    bits<3> idx;
10524    let Inst{11} = idx{2};
10525    let Inst{21} = idx{1};
10526    let Inst{20} = idx{0};
10527  }
10528
10529  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10530                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10531                                        asm, ".s", "", "", ".s",
10532    [(set (i32 FPR32Op:$dst),
10533          (Accum (i32 FPR32Op:$Rd),
10534                 (i32 (int_aarch64_neon_sqrdmulh
10535                        (i32 FPR32Op:$Rn),
10536                        (i32 (vector_extract (v4i32 V128:$Rm),
10537                                             VectorIndexS:$idx))))))]> {
10538    bits<2> idx;
10539    let Inst{11} = idx{1};
10540    let Inst{21} = idx{0};
10541  }
10542}
10543} // let Predicates = [HasNeon, HasRDM]
10544
10545//----------------------------------------------------------------------------
10546// ARMv8.3 Complex ADD/MLA instructions
10547//----------------------------------------------------------------------------
10548
10549class ComplexRotationOperand<int Angle, int Remainder, string Type>
10550  : AsmOperandClass {
10551  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10552  let DiagnosticType = "InvalidComplexRotation" # Type;
10553  let Name = "ComplexRotation" # Type;
10554}
10555def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10556                                                  SDNodeXForm<imm, [{
10557  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10558}]>> {
10559  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10560  let PrintMethod = "printComplexRotationOp<90, 0>";
10561}
10562def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10563                                                  SDNodeXForm<imm, [{
10564  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10565}]>> {
10566  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10567  let PrintMethod = "printComplexRotationOp<180, 90>";
10568}
10569let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10570class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10571                                     RegisterOperand regtype, Operand rottype,
10572                                     string asm, string kind, list<dag> pattern>
10573  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10574      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10575      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10576    Sched<[WriteV]> {
10577  bits<5> Rd;
10578  bits<5> Rn;
10579  bits<5> Rm;
10580  bits<1> rot;
10581  let Inst{31}    = 0;
10582  let Inst{30}    = Q;
10583  let Inst{29}    = U;
10584  let Inst{28-24} = 0b01110;
10585  let Inst{23-22} = size;
10586  let Inst{21}    = 0;
10587  let Inst{20-16} = Rm;
10588  let Inst{15-13} = opcode;
10589  // Non-tied version (FCADD) only has one rotation bit
10590  let Inst{12}    = rot;
10591  let Inst{11}    = 0;
10592  let Inst{10}    = 1;
10593  let Inst{9-5}   = Rn;
10594  let Inst{4-0}   = Rd;
10595}
10596
10597//8.3 CompNum - Floating-point complex number support
10598multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10599                                          string asm, SDPatternOperator OpNode>{
10600  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10601  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10602              asm, ".4h",
10603              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10604                                              (v4f16 V64:$Rn),
10605                                              (v4f16 V64:$Rm),
10606                                              (i32 rottype:$rot)))]>;
10607
10608  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10609              asm, ".8h",
10610              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10611                                               (v8f16 V128:$Rn),
10612                                               (v8f16 V128:$Rm),
10613                                               (i32 rottype:$rot)))]>;
10614  }
10615
10616  let Predicates = [HasComplxNum, HasNEON] in {
10617  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10618              asm, ".2s",
10619              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10620                                              (v2f32 V64:$Rn),
10621                                              (v2f32 V64:$Rm),
10622                                              (i32 rottype:$rot)))]>;
10623
10624  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10625              asm, ".4s",
10626              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10627                                               (v4f32 V128:$Rn),
10628                                               (v4f32 V128:$Rm),
10629                                               (i32 rottype:$rot)))]>;
10630
10631  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10632              asm, ".2d",
10633              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10634                                               (v2f64 V128:$Rn),
10635                                               (v2f64 V128:$Rm),
10636                                               (i32 rottype:$rot)))]>;
10637  }
10638}
10639
10640let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10641class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10642                                         bits<3> opcode,
10643                                         RegisterOperand regtype,
10644                                         Operand rottype, string asm,
10645                                         string kind, list<dag> pattern>
10646  : I<(outs regtype:$dst),
10647      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10648      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10649      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10650    Sched<[WriteV]> {
10651  bits<5> Rd;
10652  bits<5> Rn;
10653  bits<5> Rm;
10654  bits<2> rot;
10655  let Inst{31}    = 0;
10656  let Inst{30}    = Q;
10657  let Inst{29}    = U;
10658  let Inst{28-24} = 0b01110;
10659  let Inst{23-22} = size;
10660  let Inst{21}    = 0;
10661  let Inst{20-16} = Rm;
10662  let Inst{15-13} = opcode;
10663  let Inst{12-11} = rot;
10664  let Inst{10}    = 1;
10665  let Inst{9-5}   = Rn;
10666  let Inst{4-0}   = Rd;
10667}
10668
10669multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10670                                             Operand rottype, string asm,
10671                                             SDPatternOperator OpNode> {
10672  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10673  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10674              rottype, asm, ".4h",
10675              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10676                                              (v4f16 V64:$Rn),
10677                                              (v4f16 V64:$Rm),
10678                                              (i32 rottype:$rot)))]>;
10679
10680  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10681              rottype, asm, ".8h",
10682              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10683                                               (v8f16 V128:$Rn),
10684                                               (v8f16 V128:$Rm),
10685                                               (i32 rottype:$rot)))]>;
10686  }
10687
10688  let Predicates = [HasComplxNum, HasNEON] in {
10689  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10690              rottype, asm, ".2s",
10691              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10692                                              (v2f32 V64:$Rn),
10693                                              (v2f32 V64:$Rm),
10694                                              (i32 rottype:$rot)))]>;
10695
10696  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10697              rottype, asm, ".4s",
10698              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10699                                               (v4f32 V128:$Rn),
10700                                               (v4f32 V128:$Rm),
10701                                               (i32 rottype:$rot)))]>;
10702
10703  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10704              rottype, asm, ".2d",
10705              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10706                                               (v2f64 V128:$Rn),
10707                                               (v2f64 V128:$Rm),
10708                                               (i32 rottype:$rot)))]>;
10709  }
10710}
10711
10712let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10713class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10714                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10715                                 RegisterOperand lhs_reg,
10716                                 RegisterOperand rhs_reg, Operand vec_idx,
10717                                 Operand rottype, string asm, string apple_kind,
10718                                 string dst_kind, string lhs_kind,
10719                                 string rhs_kind, list<dag> pattern>
10720  : I<(outs dst_reg:$dst),
10721      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10722      asm,
10723      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10724      "$idx, $rot" # "|" # apple_kind #
10725      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10726    Sched<[WriteV]> {
10727  bits<5> Rd;
10728  bits<5> Rn;
10729  bits<5> Rm;
10730  bits<2> rot;
10731
10732  let Inst{31}    = 0;
10733  let Inst{30}    = Q;
10734  let Inst{29}    = U;
10735  let Inst{28}    = Scalar;
10736  let Inst{27-24} = 0b1111;
10737  let Inst{23-22} = size;
10738  // Bit 21 must be set by the derived class.
10739  let Inst{20-16} = Rm;
10740  let Inst{15}    = opc1;
10741  let Inst{14-13} = rot;
10742  let Inst{12}    = opc2;
10743  // Bit 11 must be set by the derived class.
10744  let Inst{10}    = 0;
10745  let Inst{9-5}   = Rn;
10746  let Inst{4-0}   = Rd;
10747}
10748
10749// The complex instructions index by pairs of elements, so the VectorIndexes
10750// don't match the lane types, and the index bits are different to the other
10751// classes.
10752multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10753                                     string asm, SDPatternOperator OpNode> {
10754  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10755  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10756                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10757                      ".4h", ".h", []> {
10758    bits<1> idx;
10759    let Inst{11} = 0;
10760    let Inst{21} = idx{0};
10761  }
10762
10763  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10764                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10765                      ".8h", ".8h", ".h", []> {
10766    bits<2> idx;
10767    let Inst{11} = idx{1};
10768    let Inst{21} = idx{0};
10769  }
10770  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10771
10772  let Predicates = [HasComplxNum, HasNEON] in {
10773  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10774                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10775                      ".4s", ".4s", ".s", []> {
10776    bits<1> idx;
10777    let Inst{11} = idx{0};
10778    let Inst{21} = 0;
10779  }
10780  } // Predicates = [HasComplxNum, HasNEON]
10781}
10782
10783//----------------------------------------------------------------------------
10784// Crypto extensions
10785//----------------------------------------------------------------------------
10786
10787let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10788class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10789              list<dag> pat>
10790  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10791    Sched<[WriteV]>{
10792  bits<5> Rd;
10793  bits<5> Rn;
10794  let Inst{31-16} = 0b0100111000101000;
10795  let Inst{15-12} = opc;
10796  let Inst{11-10} = 0b10;
10797  let Inst{9-5}   = Rn;
10798  let Inst{4-0}   = Rd;
10799}
10800
10801class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10802  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10803            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10804
10805class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10806  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10807            "$Rd = $dst",
10808            [(set (v16i8 V128:$dst),
10809                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10810
10811let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10812class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10813                     dag oops, dag iops, list<dag> pat>
10814  : I<oops, iops, asm,
10815      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10816      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10817    Sched<[WriteV]>{
10818  bits<5> Rd;
10819  bits<5> Rn;
10820  bits<5> Rm;
10821  let Inst{31-21} = 0b01011110000;
10822  let Inst{20-16} = Rm;
10823  let Inst{15}    = 0;
10824  let Inst{14-12} = opc;
10825  let Inst{11-10} = 0b00;
10826  let Inst{9-5}   = Rn;
10827  let Inst{4-0}   = Rd;
10828}
10829
10830class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10831  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10832                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10833                   [(set (v4i32 FPR128:$dst),
10834                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10835                                 (v4i32 V128:$Rm)))]>;
10836
10837class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10838  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10839                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10840                   [(set (v4i32 V128:$dst),
10841                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10842                                 (v4i32 V128:$Rm)))]>;
10843
10844class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10845  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10846                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10847                   [(set (v4i32 FPR128:$dst),
10848                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10849                                 (v4i32 V128:$Rm)))]>;
10850
10851let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10852class SHA2OpInst<bits<4> opc, string asm, string kind,
10853                 string cstr, dag oops, dag iops,
10854                 list<dag> pat>
10855  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10856                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10857    Sched<[WriteV]>{
10858  bits<5> Rd;
10859  bits<5> Rn;
10860  let Inst{31-16} = 0b0101111000101000;
10861  let Inst{15-12} = opc;
10862  let Inst{11-10} = 0b10;
10863  let Inst{9-5}   = Rn;
10864  let Inst{4-0}   = Rd;
10865}
10866
10867class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10868  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10869               (ins V128:$Rd, V128:$Rn),
10870               [(set (v4i32 V128:$dst),
10871                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10872
10873class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10874  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10875               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10876
10877// Armv8.2-A Crypto extensions
10878class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10879                    list<dag> pattern>
10880  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10881  bits<5> Vd;
10882  bits<5> Vn;
10883  let Inst{31-25} = 0b1100111;
10884  let Inst{9-5}   = Vn;
10885  let Inst{4-0}   = Vd;
10886}
10887
10888class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10889  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10890                  "$Vm = $Vd", []> {
10891  let Inst{31-25} = 0b1100111;
10892  let Inst{24-21} = 0b0110;
10893  let Inst{20-15} = 0b000001;
10894  let Inst{14}    = op0;
10895  let Inst{13-12} = 0b00;
10896  let Inst{11-10} = op1;
10897}
10898class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10899  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10900class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10901  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10902
10903class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10904                string asmops, string cst>
10905  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10906  bits<5> Vm;
10907  let Inst{24-21} = 0b0011;
10908  let Inst{20-16} = Vm;
10909  let Inst{15}    = 0b1;
10910  let Inst{14}    = op0;
10911  let Inst{13-12} = 0b00;
10912  let Inst{11-10} = op1;
10913}
10914class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10915  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10916              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10917class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10918  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10919              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10920class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10921  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10922              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10923class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10924  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10925              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10926class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10927  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10928              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10929
10930class CryptoRRRR<bits<2>op0, string asm, string asmops>
10931  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10932                  asmops, "", []> {
10933  bits<5> Vm;
10934  bits<5> Va;
10935  let Inst{24-23} = 0b00;
10936  let Inst{22-21} = op0;
10937  let Inst{20-16} = Vm;
10938  let Inst{15}    = 0b0;
10939  let Inst{14-10} = Va;
10940}
10941class CryptoRRRR_16B<bits<2>op0, string asm>
10942 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
10943                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
10944}
10945class CryptoRRRR_4S<bits<2>op0, string asm>
10946 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
10947                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
10948}
10949
10950class CryptoRRRi6<string asm>
10951  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10952                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
10953                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
10954  bits<6> imm;
10955  bits<5> Vm;
10956  let Inst{24-21} = 0b0100;
10957  let Inst{20-16} = Vm;
10958  let Inst{15-10} = imm;
10959  let Inst{9-5}   = Vn;
10960  let Inst{4-0}   = Vd;
10961}
10962
10963class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10964  : BaseCryptoV82<(outs V128:$Vdst),
10965                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10966                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
10967                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
10968  bits<2> imm;
10969  bits<5> Vm;
10970  let Inst{24-21} = 0b0010;
10971  let Inst{20-16} = Vm;
10972  let Inst{15}    = 0b1;
10973  let Inst{14}    = op0;
10974  let Inst{13-12} = imm;
10975  let Inst{11-10} = op1;
10976}
10977
10978//----------------------------------------------------------------------------
10979// v8.1 atomic instructions extension:
10980// * CAS
10981// * CASP
10982// * SWP
10983// * LDOPregister<OP>, and aliases STOPregister<OP>
10984
10985// Instruction encodings:
10986//
10987//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10988// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10989// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10990// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10991// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10992// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10993
10994// Instruction syntax:
10995//
10996// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10997// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10998// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10999// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11000// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11001// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11002// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11003// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11004// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11005// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11006
11007let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11008class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11009                      string cstr, list<dag> pattern>
11010      : I<oops, iops, asm, operands, cstr, pattern> {
11011  bits<2> Sz;
11012  bit NP;
11013  bit Acq;
11014  bit Rel;
11015  bits<5> Rs;
11016  bits<5> Rn;
11017  bits<5> Rt;
11018  let Inst{31-30} = Sz;
11019  let Inst{29-24} = 0b001000;
11020  let Inst{23} = NP;
11021  let Inst{22} = Acq;
11022  let Inst{21} = 0b1;
11023  let Inst{20-16} = Rs;
11024  let Inst{15} = Rel;
11025  let Inst{14-10} = 0b11111;
11026  let Inst{9-5} = Rn;
11027  let Inst{4-0} = Rt;
11028  let Predicates = [HasLSE];
11029}
11030
11031class BaseCAS<string order, string size, RegisterClass RC>
11032      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11033                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11034                        "$out = $Rs",[]>,
11035        Sched<[WriteAtomic]> {
11036  let NP = 1;
11037}
11038
11039multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11040  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11041  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11042  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11043  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11044}
11045
11046class BaseCASP<string order, string size, RegisterOperand RC>
11047      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11048                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11049                        "$out = $Rs",[]>,
11050        Sched<[WriteAtomic]> {
11051  let NP = 0;
11052}
11053
11054multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11055  let Sz = 0b00, Acq = Acq, Rel = Rel in
11056    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11057  let Sz = 0b01, Acq = Acq, Rel = Rel in
11058    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11059}
11060
11061let Predicates = [HasLSE] in
11062class BaseSWP<string order, string size, RegisterClass RC>
11063      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11064          "\t$Rs, $Rt, [$Rn]","",[]>,
11065        Sched<[WriteAtomic]> {
11066  bits<2> Sz;
11067  bit Acq;
11068  bit Rel;
11069  bits<5> Rs;
11070  bits<3> opc = 0b000;
11071  bits<5> Rn;
11072  bits<5> Rt;
11073  let Inst{31-30} = Sz;
11074  let Inst{29-24} = 0b111000;
11075  let Inst{23} = Acq;
11076  let Inst{22} = Rel;
11077  let Inst{21} = 0b1;
11078  let Inst{20-16} = Rs;
11079  let Inst{15} = 0b1;
11080  let Inst{14-12} = opc;
11081  let Inst{11-10} = 0b00;
11082  let Inst{9-5} = Rn;
11083  let Inst{4-0} = Rt;
11084  let Predicates = [HasLSE];
11085}
11086
11087multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11088  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11089  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11090  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11091  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11092}
11093
11094let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11095class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11096      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11097          "\t$Rs, $Rt, [$Rn]","",[]>,
11098        Sched<[WriteAtomic]> {
11099  bits<2> Sz;
11100  bit Acq;
11101  bit Rel;
11102  bits<5> Rs;
11103  bits<3> opc;
11104  bits<5> Rn;
11105  bits<5> Rt;
11106  let Inst{31-30} = Sz;
11107  let Inst{29-24} = 0b111000;
11108  let Inst{23} = Acq;
11109  let Inst{22} = Rel;
11110  let Inst{21} = 0b1;
11111  let Inst{20-16} = Rs;
11112  let Inst{15} = 0b0;
11113  let Inst{14-12} = opc;
11114  let Inst{11-10} = 0b00;
11115  let Inst{9-5} = Rn;
11116  let Inst{4-0} = Rt;
11117  let Predicates = [HasLSE];
11118}
11119
11120multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11121                        string order> {
11122  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11123    def B : BaseLDOPregister<op, order, "b", GPR32>;
11124  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11125    def H : BaseLDOPregister<op, order, "h", GPR32>;
11126  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11127    def W : BaseLDOPregister<op, order, "", GPR32>;
11128  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11129    def X : BaseLDOPregister<op, order, "", GPR64>;
11130}
11131
11132// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11133// complex DAG for DstRHS.
11134let Predicates = [HasLSE] in
11135multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11136                                         string size, dag SrcRHS, dag DstRHS> {
11137  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11138            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11139  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11140            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11141  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11142            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11143  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11144            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11145  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11146            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11147}
11148
11149multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11150                                     string size, dag RHS> {
11151  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11152}
11153
11154multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11155                                         string size, dag LHS, dag RHS> {
11156  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11157}
11158
11159multiclass LDOPregister_patterns<string inst, string op> {
11160  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11161  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11162  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11163  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11164}
11165
11166multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11167  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11168                        (i64 GPR64:$Rm),
11169                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11170  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11171                        (i32 GPR32:$Rm),
11172                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11173  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11174                        (i32 GPR32:$Rm),
11175                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11176  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11177                        (i32 GPR32:$Rm),
11178                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11179}
11180
11181let Predicates = [HasLSE] in
11182multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11183                                        string size, dag OLD, dag NEW> {
11184  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11185            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11186  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11187            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11188  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11189            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11190  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11191            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11192  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11193            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11194}
11195
11196multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11197                                    string size, dag OLD, dag NEW> {
11198  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11199}
11200
11201multiclass CASregister_patterns<string inst, string op> {
11202  defm : CASregister_patterns_ord<inst, "X", op, "64",
11203                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11204  defm : CASregister_patterns_ord<inst, "W", op, "32",
11205                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11206  defm : CASregister_patterns_ord<inst, "H", op, "16",
11207                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11208  defm : CASregister_patterns_ord<inst, "B", op, "8",
11209                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11210}
11211
11212let Predicates = [HasLSE] in
11213class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11214                        Instruction inst> :
11215      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11216
11217multiclass STOPregister<string asm, string instr> {
11218  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11219                    !cast<Instruction>(instr # "LB")>;
11220  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11221                    !cast<Instruction>(instr # "LH")>;
11222  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11223                    !cast<Instruction>(instr # "LW")>;
11224  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11225                    !cast<Instruction>(instr # "LX")>;
11226  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11227                    !cast<Instruction>(instr # "B")>;
11228  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11229                    !cast<Instruction>(instr # "H")>;
11230  def : BaseSTOPregister<asm,        GPR32, WZR,
11231                    !cast<Instruction>(instr # "W")>;
11232  def : BaseSTOPregister<asm,        GPR64, XZR,
11233                    !cast<Instruction>(instr # "X")>;
11234}
11235
11236//----------------------------------------------------------------------------
11237// Allow the size specifier tokens to be upper case, not just lower.
11238def : TokenAlias<".4B", ".4b">;  // Add dot product
11239def : TokenAlias<".8B", ".8b">;
11240def : TokenAlias<".4H", ".4h">;
11241def : TokenAlias<".2S", ".2s">;
11242def : TokenAlias<".1D", ".1d">;
11243def : TokenAlias<".16B", ".16b">;
11244def : TokenAlias<".8H", ".8h">;
11245def : TokenAlias<".4S", ".4s">;
11246def : TokenAlias<".2D", ".2d">;
11247def : TokenAlias<".1Q", ".1q">;
11248def : TokenAlias<".2H", ".2h">;
11249def : TokenAlias<".B", ".b">;
11250def : TokenAlias<".H", ".h">;
11251def : TokenAlias<".S", ".s">;
11252def : TokenAlias<".D", ".d">;
11253def : TokenAlias<".Q", ".q">;
11254