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// imm0_15 predicate - True if the immediate is in the range [0,15]
918def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
919  return ((uint64_t)Imm) < 16;
920}]> {
921  let ParserMatchClass = Imm0_15Operand;
922}
923
924// imm0_7 predicate - True if the immediate is in the range [0,7]
925def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
926  return ((uint64_t)Imm) < 8;
927}]> {
928  let ParserMatchClass = Imm0_7Operand;
929}
930
931// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
932def imm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
933  return ((uint32_t)Imm) < 8;
934}]> {
935  let ParserMatchClass = Imm0_7Operand;
936}
937
938// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
939def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
940  return ((uint32_t)Imm) < 16;
941}]> {
942  let ParserMatchClass = Imm0_15Operand;
943}
944
945// An arithmetic shifter operand:
946//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
947//  {5-0} - imm6
948class arith_shift<ValueType Ty, int width> : Operand<Ty> {
949  let PrintMethod = "printShifter";
950  let ParserMatchClass = !cast<AsmOperandClass>(
951                         "ArithmeticShifterOperand" # width);
952}
953
954def arith_shift32 : arith_shift<i32, 32>;
955def arith_shift64 : arith_shift<i64, 64>;
956
957class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
958    : Operand<Ty>,
959      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
960  let PrintMethod = "printShiftedRegister";
961  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
962}
963
964def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
965def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
966
967def gi_arith_shifted_reg32 :
968  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
969  GIComplexPatternEquiv<arith_shifted_reg32>;
970
971def gi_arith_shifted_reg64 :
972  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
973  GIComplexPatternEquiv<arith_shifted_reg64>;
974
975// An arithmetic shifter operand:
976//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
977//  {5-0} - imm6
978class logical_shift<int width> : Operand<i32> {
979  let PrintMethod = "printShifter";
980  let ParserMatchClass = !cast<AsmOperandClass>(
981                         "LogicalShifterOperand" # width);
982}
983
984def logical_shift32 : logical_shift<32>;
985def logical_shift64 : logical_shift<64>;
986
987class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
988    : Operand<Ty>,
989      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
990  let PrintMethod = "printShiftedRegister";
991  let MIOperandInfo = (ops regclass, shiftop);
992}
993
994def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
995def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
996
997def gi_logical_shifted_reg32 :
998  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
999  GIComplexPatternEquiv<logical_shifted_reg32>;
1000
1001def gi_logical_shifted_reg64 :
1002  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1003  GIComplexPatternEquiv<logical_shifted_reg64>;
1004
1005// A logical vector shifter operand:
1006//  {7-6} - shift type: 00 = lsl
1007//  {5-0} - imm6: #0, #8, #16, or #24
1008def logical_vec_shift : Operand<i32> {
1009  let PrintMethod = "printShifter";
1010  let EncoderMethod = "getVecShifterOpValue";
1011  let ParserMatchClass = LogicalVecShifterOperand;
1012}
1013
1014// A logical vector half-word shifter operand:
1015//  {7-6} - shift type: 00 = lsl
1016//  {5-0} - imm6: #0 or #8
1017def logical_vec_hw_shift : Operand<i32> {
1018  let PrintMethod = "printShifter";
1019  let EncoderMethod = "getVecShifterOpValue";
1020  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1021}
1022
1023// A vector move shifter operand:
1024//  {0} - imm1: #8 or #16
1025def move_vec_shift : Operand<i32> {
1026  let PrintMethod = "printShifter";
1027  let EncoderMethod = "getMoveVecShifterOpValue";
1028  let ParserMatchClass = MoveVecShifterOperand;
1029}
1030
1031let DiagnosticType = "AddSubSecondSource" in {
1032  def AddSubImmOperand : AsmOperandClass {
1033    let Name = "AddSubImm";
1034    let ParserMethod = "tryParseImmWithOptionalShift";
1035    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1036  }
1037  def AddSubImmNegOperand : AsmOperandClass {
1038    let Name = "AddSubImmNeg";
1039    let ParserMethod = "tryParseImmWithOptionalShift";
1040    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1041  }
1042}
1043// An ADD/SUB immediate shifter operand:
1044//  second operand:
1045//  {7-6} - shift type: 00 = lsl
1046//  {5-0} - imm6: #0 or #12
1047class addsub_shifted_imm<ValueType Ty>
1048    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1049  let PrintMethod = "printAddSubImm";
1050  let EncoderMethod = "getAddSubImmOpValue";
1051  let ParserMatchClass = AddSubImmOperand;
1052  let MIOperandInfo = (ops i32imm, i32imm);
1053}
1054
1055class addsub_shifted_imm_neg<ValueType Ty>
1056    : Operand<Ty> {
1057  let EncoderMethod = "getAddSubImmOpValue";
1058  let ParserMatchClass = AddSubImmNegOperand;
1059  let MIOperandInfo = (ops i32imm, i32imm);
1060}
1061
1062def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1063def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1064def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1065def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1066
1067def gi_addsub_shifted_imm32 :
1068    GIComplexOperandMatcher<s32, "selectArithImmed">,
1069    GIComplexPatternEquiv<addsub_shifted_imm32>;
1070
1071def gi_addsub_shifted_imm64 :
1072    GIComplexOperandMatcher<s64, "selectArithImmed">,
1073    GIComplexPatternEquiv<addsub_shifted_imm64>;
1074
1075class neg_addsub_shifted_imm<ValueType Ty>
1076    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1077  let PrintMethod = "printAddSubImm";
1078  let EncoderMethod = "getAddSubImmOpValue";
1079  let ParserMatchClass = AddSubImmOperand;
1080  let MIOperandInfo = (ops i32imm, i32imm);
1081}
1082
1083def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1084def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1085
1086def gi_neg_addsub_shifted_imm32 :
1087    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1088    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1089
1090def gi_neg_addsub_shifted_imm64 :
1091    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1092    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1093
1094// An extend operand:
1095//  {5-3} - extend type
1096//  {2-0} - imm3
1097def arith_extend : Operand<i32> {
1098  let PrintMethod = "printArithExtend";
1099  let ParserMatchClass = ExtendOperand;
1100}
1101def arith_extend64 : Operand<i32> {
1102  let PrintMethod = "printArithExtend";
1103  let ParserMatchClass = ExtendOperand64;
1104}
1105
1106// 'extend' that's a lsl of a 64-bit register.
1107def arith_extendlsl64 : Operand<i32> {
1108  let PrintMethod = "printArithExtend";
1109  let ParserMatchClass = ExtendOperandLSL64;
1110}
1111
1112class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1113                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1114  let PrintMethod = "printExtendedRegister";
1115  let MIOperandInfo = (ops GPR32, arith_extend);
1116}
1117
1118class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1119                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1120  let PrintMethod = "printExtendedRegister";
1121  let MIOperandInfo = (ops GPR32, arith_extend64);
1122}
1123
1124def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1125def gi_arith_extended_reg32_i32 :
1126    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1127    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1128
1129def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1130def gi_arith_extended_reg32_i64 :
1131    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1132    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1133
1134def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1135def gi_arith_extended_reg32to64_i64 :
1136    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1137    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1138
1139// Floating-point immediate.
1140def fpimm16 : Operand<f16>,
1141              FPImmLeaf<f16, [{
1142      return AArch64_AM::getFP16Imm(Imm) != -1;
1143    }], SDNodeXForm<fpimm, [{
1144      APFloat InVal = N->getValueAPF();
1145      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1146      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1147    }]>> {
1148  let ParserMatchClass = FPImmOperand;
1149  let PrintMethod = "printFPImmOperand";
1150}
1151def fpimm32 : Operand<f32>,
1152              FPImmLeaf<f32, [{
1153      return AArch64_AM::getFP32Imm(Imm) != -1;
1154    }], SDNodeXForm<fpimm, [{
1155      APFloat InVal = N->getValueAPF();
1156      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1157      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1158    }]>> {
1159  let ParserMatchClass = FPImmOperand;
1160  let PrintMethod = "printFPImmOperand";
1161}
1162def fpimm64 : Operand<f64>,
1163              FPImmLeaf<f64, [{
1164      return AArch64_AM::getFP64Imm(Imm) != -1;
1165    }], SDNodeXForm<fpimm, [{
1166      APFloat InVal = N->getValueAPF();
1167      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1168      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1169    }]>> {
1170  let ParserMatchClass = FPImmOperand;
1171  let PrintMethod = "printFPImmOperand";
1172}
1173
1174def fpimm8 : Operand<i32> {
1175  let ParserMatchClass = FPImmOperand;
1176  let PrintMethod = "printFPImmOperand";
1177}
1178
1179def fpimm0 : FPImmLeaf<fAny, [{
1180  return Imm.isExactlyValue(+0.0);
1181}]>;
1182
1183// Vector lane operands
1184class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1185  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1186  let DiagnosticType = "Invalid" # Name;
1187  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1188  let RenderMethod = "addVectorIndexOperands";
1189}
1190
1191class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1192    : Operand<ty> {
1193  let ParserMatchClass = mc;
1194  let PrintMethod = "printVectorIndex";
1195}
1196
1197multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1198  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1199  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1200}
1201
1202def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1203def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1204def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1205def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1206def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1207
1208defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1209                                [{ return ((uint64_t)Imm) == 1; }]>;
1210defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1211                                [{ return ((uint64_t)Imm) < 16; }]>;
1212defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1213                                [{ return ((uint64_t)Imm) < 8; }]>;
1214defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1215                                [{ return ((uint64_t)Imm) < 4; }]>;
1216defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1217                                [{ return ((uint64_t)Imm) < 2; }]>;
1218
1219defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1220                                   [{ return ((uint64_t)Imm) == 1; }]>;
1221defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1222                                   [{ return ((uint64_t)Imm) < 16; }]>;
1223defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1224                                   [{ return ((uint64_t)Imm) < 8; }]>;
1225defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1226                                   [{ return ((uint64_t)Imm) < 4; }]>;
1227defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1228                                   [{ return ((uint64_t)Imm) < 2; }]>;
1229
1230def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1231def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1232def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1233def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1234def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1235
1236defm sve_elm_idx_extdup_b
1237  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1238                [{ return ((uint64_t)Imm) < 64; }]>;
1239defm sve_elm_idx_extdup_h
1240  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1241                [{ return ((uint64_t)Imm) < 32; }]>;
1242defm sve_elm_idx_extdup_s
1243  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1244                [{ return ((uint64_t)Imm) < 16; }]>;
1245defm sve_elm_idx_extdup_d
1246  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1247                [{ return ((uint64_t)Imm) < 8; }]>;
1248defm sve_elm_idx_extdup_q
1249  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1250                [{ return ((uint64_t)Imm) < 4; }]>;
1251
1252// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1253// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1254// are encoded as the eight bit value 'abcdefgh'.
1255def simdimmtype10 : Operand<i32>,
1256                    FPImmLeaf<f64, [{
1257      return AArch64_AM::isAdvSIMDModImmType10(
1258                 Imm.bitcastToAPInt().getZExtValue());
1259    }], SDNodeXForm<fpimm, [{
1260      APFloat InVal = N->getValueAPF();
1261      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1262                                                           .bitcastToAPInt()
1263                                                           .getZExtValue());
1264      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1265    }]>> {
1266  let ParserMatchClass = SIMDImmType10Operand;
1267  let PrintMethod = "printSIMDType10Operand";
1268}
1269
1270
1271//---
1272// System management
1273//---
1274
1275// Base encoding for system instruction operands.
1276let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1277class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1278                  list<dag> pattern = []>
1279    : I<oops, iops, asm, operands, "", pattern> {
1280  let Inst{31-22} = 0b1101010100;
1281  let Inst{21}    = L;
1282}
1283
1284// System instructions which do not have an Rt register.
1285class SimpleSystemI<bit L, dag iops, string asm, string operands,
1286                    list<dag> pattern = []>
1287    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1288  let Inst{4-0} = 0b11111;
1289}
1290
1291// System instructions which have an Rt register.
1292class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1293    : BaseSystemI<L, oops, iops, asm, operands>,
1294      Sched<[WriteSys]> {
1295  bits<5> Rt;
1296  let Inst{4-0} = Rt;
1297}
1298
1299// System instructions for transactional memory extension
1300class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1301                    string asm, string operands, list<dag> pattern>
1302    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1303      Sched<[WriteSys]> {
1304  let Inst{20-12} = 0b000110011;
1305  let Inst{11-8} = CRm;
1306  let Inst{7-5} = op2;
1307  let DecoderMethod = "";
1308
1309  let mayLoad = 1;
1310  let mayStore = 1;
1311}
1312
1313// System instructions for transactional memory - single input operand
1314class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1315    : TMBaseSystemI<0b1, CRm, 0b011,
1316                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1317  bits<5> Rt;
1318  let Inst{4-0} = Rt;
1319}
1320
1321// System instructions for transactional memory - no operand
1322class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1323    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1324  let Inst{4-0} = 0b11111;
1325}
1326
1327// System instructions for exit from transactions
1328class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1329    : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1330      Sched<[WriteSys]> {
1331  bits<16> imm;
1332  let Inst{31-24} = 0b11010100;
1333  let Inst{23-21} = op1;
1334  let Inst{20-5}  = imm;
1335  let Inst{4-0}   = 0b00000;
1336}
1337
1338// Hint instructions that take both a CRm and a 3-bit immediate.
1339// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1340// model patterns with sufficiently fine granularity
1341let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1342  class HintI<string mnemonic>
1343      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1344                      [(int_aarch64_hint imm0_127:$imm)]>,
1345        Sched<[WriteHint]> {
1346    bits <7> imm;
1347    let Inst{20-12} = 0b000110010;
1348    let Inst{11-5} = imm;
1349  }
1350
1351// System instructions taking a single literal operand which encodes into
1352// CRm. op2 differentiates the opcodes.
1353def BarrierAsmOperand : AsmOperandClass {
1354  let Name = "Barrier";
1355  let ParserMethod = "tryParseBarrierOperand";
1356}
1357def barrier_op : Operand<i32> {
1358  let PrintMethod = "printBarrierOption";
1359  let ParserMatchClass = BarrierAsmOperand;
1360}
1361class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1362                 list<dag> pattern = []>
1363    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1364      Sched<[WriteBarrier]> {
1365  bits<4> CRm;
1366  let Inst{20-12} = 0b000110011;
1367  let Inst{11-8} = CRm;
1368  let Inst{7-5} = opc;
1369}
1370
1371class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1372    : SimpleSystemI<0, (ins), asm, "", pattern>,
1373      Sched<[]> {
1374  bits<4> CRm;
1375  let CRm = 0b0011;
1376  let Inst{31-12} = 0b11010101000000110010;
1377  let Inst{11-8} = CRm;
1378  let Inst{7-5} = op2;
1379  let Inst{4-0} = 0b11111;
1380}
1381
1382// MRS/MSR system instructions. These have different operand classes because
1383// a different subset of registers can be accessed through each instruction.
1384def MRSSystemRegisterOperand : AsmOperandClass {
1385  let Name = "MRSSystemRegister";
1386  let ParserMethod = "tryParseSysReg";
1387  let DiagnosticType = "MRS";
1388}
1389// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1390def mrs_sysreg_op : Operand<i32> {
1391  let ParserMatchClass = MRSSystemRegisterOperand;
1392  let DecoderMethod = "DecodeMRSSystemRegister";
1393  let PrintMethod = "printMRSSystemRegister";
1394}
1395
1396def MSRSystemRegisterOperand : AsmOperandClass {
1397  let Name = "MSRSystemRegister";
1398  let ParserMethod = "tryParseSysReg";
1399  let DiagnosticType = "MSR";
1400}
1401def msr_sysreg_op : Operand<i32> {
1402  let ParserMatchClass = MSRSystemRegisterOperand;
1403  let DecoderMethod = "DecodeMSRSystemRegister";
1404  let PrintMethod = "printMSRSystemRegister";
1405}
1406
1407def PSBHintOperand : AsmOperandClass {
1408  let Name = "PSBHint";
1409  let ParserMethod = "tryParsePSBHint";
1410}
1411def psbhint_op : Operand<i32> {
1412  let ParserMatchClass = PSBHintOperand;
1413  let PrintMethod = "printPSBHintOp";
1414  let MCOperandPredicate = [{
1415    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1416    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1417    if (!MCOp.isImm())
1418      return false;
1419    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1420  }];
1421}
1422
1423def BTIHintOperand : AsmOperandClass {
1424  let Name = "BTIHint";
1425  let ParserMethod = "tryParseBTIHint";
1426}
1427def btihint_op : Operand<i32> {
1428  let ParserMatchClass = BTIHintOperand;
1429  let PrintMethod = "printBTIHintOp";
1430  let MCOperandPredicate = [{
1431    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1432    if (!MCOp.isImm())
1433      return false;
1434    return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1435  }];
1436}
1437
1438class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1439                       "mrs", "\t$Rt, $systemreg"> {
1440  bits<16> systemreg;
1441  let Inst{20-5} = systemreg;
1442}
1443
1444// FIXME: Some of these def NZCV, others don't. Best way to model that?
1445// Explicitly modeling each of the system register as a register class
1446// would do it, but feels like overkill at this point.
1447class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1448                       "msr", "\t$systemreg, $Rt"> {
1449  bits<16> systemreg;
1450  let Inst{20-5} = systemreg;
1451}
1452
1453def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1454  let Name = "SystemPStateFieldWithImm0_15";
1455  let ParserMethod = "tryParseSysReg";
1456}
1457def pstatefield4_op : Operand<i32> {
1458  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1459  let PrintMethod = "printSystemPStateField";
1460}
1461
1462// Instructions to modify PSTATE, no input reg
1463let Defs = [NZCV] in
1464class PstateWriteSimple<dag iops, string asm, string operands>
1465  : SimpleSystemI<0, iops, asm, operands> {
1466
1467  let Inst{20-19} = 0b00;
1468  let Inst{15-12} = 0b0100;
1469}
1470
1471class MSRpstateImm0_15
1472  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1473                  "\t$pstatefield, $imm">,
1474    Sched<[WriteSys]> {
1475
1476  bits<6> pstatefield;
1477  bits<4> imm;
1478  let Inst{18-16} = pstatefield{5-3};
1479  let Inst{11-8} = imm;
1480  let Inst{7-5} = pstatefield{2-0};
1481
1482  let DecoderMethod = "DecodeSystemPStateInstruction";
1483  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1484  // Fail the decoder should attempt to decode the instruction as MSRI.
1485  let hasCompleteDecoder = 0;
1486}
1487
1488def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1489  let Name = "SystemPStateFieldWithImm0_1";
1490  let ParserMethod = "tryParseSysReg";
1491}
1492def pstatefield1_op : Operand<i32> {
1493  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1494  let PrintMethod = "printSystemPStateField";
1495}
1496
1497class MSRpstateImm0_1
1498  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1499                 "\t$pstatefield, $imm">,
1500    Sched<[WriteSys]> {
1501
1502  bits<6> pstatefield;
1503  bit imm;
1504  let Inst{18-16} = pstatefield{5-3};
1505  let Inst{11-9} = 0b000;
1506  let Inst{8} = imm;
1507  let Inst{7-5} = pstatefield{2-0};
1508
1509  let DecoderMethod = "DecodeSystemPStateInstruction";
1510  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1511  // Fail the decoder should attempt to decode the instruction as MSRI.
1512  let hasCompleteDecoder = 0;
1513}
1514
1515// SYS and SYSL generic system instructions.
1516def SysCRAsmOperand : AsmOperandClass {
1517  let Name = "SysCR";
1518  let ParserMethod = "tryParseSysCROperand";
1519}
1520
1521def sys_cr_op : Operand<i32> {
1522  let PrintMethod = "printSysCROperand";
1523  let ParserMatchClass = SysCRAsmOperand;
1524}
1525
1526class SystemXtI<bit L, string asm>
1527  : RtSystemI<L, (outs),
1528       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1529       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1530  bits<3> op1;
1531  bits<4> Cn;
1532  bits<4> Cm;
1533  bits<3> op2;
1534  let Inst{20-19} = 0b01;
1535  let Inst{18-16} = op1;
1536  let Inst{15-12} = Cn;
1537  let Inst{11-8}  = Cm;
1538  let Inst{7-5}   = op2;
1539}
1540
1541class SystemLXtI<bit L, string asm>
1542  : RtSystemI<L, (outs),
1543       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1544       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1545  bits<3> op1;
1546  bits<4> Cn;
1547  bits<4> Cm;
1548  bits<3> op2;
1549  let Inst{20-19} = 0b01;
1550  let Inst{18-16} = op1;
1551  let Inst{15-12} = Cn;
1552  let Inst{11-8}  = Cm;
1553  let Inst{7-5}   = op2;
1554}
1555
1556
1557// Branch (register) instructions:
1558//
1559//  case opc of
1560//    0001 blr
1561//    0000 br
1562//    0101 dret
1563//    0100 eret
1564//    0010 ret
1565//    otherwise UNDEFINED
1566class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1567                    string operands, list<dag> pattern>
1568    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1569  let Inst{31-25} = 0b1101011;
1570  let Inst{24-21} = opc;
1571  let Inst{20-16} = 0b11111;
1572  let Inst{15-10} = 0b000000;
1573  let Inst{4-0}   = 0b00000;
1574}
1575
1576class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1577    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1578  bits<5> Rn;
1579  let Inst{9-5} = Rn;
1580}
1581
1582let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1583class SpecialReturn<bits<4> opc, string asm>
1584    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1585  let Inst{9-5} = 0b11111;
1586}
1587
1588let mayLoad = 1 in
1589class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1590  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1591  Sched<[]> {
1592  bits<5> Rn;
1593  bits<5> Rt;
1594  let Inst{31-30} = sz;
1595  let Inst{29-10} = 0b11100010111111110000;
1596  let Inst{9-5} = Rn;
1597  let Inst{4-0} = Rt;
1598}
1599
1600class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1601               list<dag> pattern>
1602  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1603  let isAuthenticated = 1;
1604  let Inst{31-25} = 0b1101011;
1605  let Inst{20-11} = 0b1111100001;
1606  let Inst{10} = M;
1607  let Inst{4-0} = 0b11111;
1608}
1609
1610class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1611  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1612  bits<5> Rn;
1613  bits<5> Rm;
1614  let Inst{24-22} = 0b100;
1615  let Inst{21} = op;
1616  let Inst{9-5} = Rn;
1617  let Inst{4-0} = Rm;
1618}
1619
1620class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1621  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1622  bits<5> Rn;
1623  let Inst{24} = 0;
1624  let Inst{23-21} = opc;
1625  let Inst{9-5} = Rn;
1626}
1627
1628let Uses = [LR,SP] in
1629class AuthReturn<bits<3> op, bits<1> M, string asm>
1630  : AuthBase<M, (outs), (ins), asm, "", []> {
1631  let Inst{24} = 0;
1632  let Inst{23-21} = op;
1633  let Inst{9-0} = 0b1111111111;
1634}
1635
1636let mayLoad = 1 in
1637class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1638                   string operands, string cstr, Operand opr>
1639  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1640  bits<10> offset;
1641  bits<5> Rn;
1642  bits<5> Rt;
1643  let isAuthenticated = 1;
1644  let Inst{31-24} = 0b11111000;
1645  let Inst{23} = M;
1646  let Inst{22} = offset{9};
1647  let Inst{21} = 1;
1648  let Inst{20-12} = offset{8-0};
1649  let Inst{11} = W;
1650  let Inst{10} = 1;
1651  let Inst{9-5} = Rn;
1652  let Inst{4-0} = Rt;
1653
1654  let DecoderMethod = "DecodeAuthLoadInstruction";
1655}
1656
1657multiclass AuthLoad<bit M, string asm, Operand opr> {
1658  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1659                               (ins GPR64sp:$Rn, opr:$offset),
1660                               asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1661  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1662                               (ins GPR64sp:$Rn, opr:$offset),
1663                               asm, "\t$Rt, [$Rn, $offset]!",
1664                               "$Rn = $wback,@earlyclobber $wback", opr>;
1665
1666  def : InstAlias<asm # "\t$Rt, [$Rn]",
1667                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1668
1669  def : InstAlias<asm # "\t$Rt, [$wback]!",
1670                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1671}
1672
1673//---
1674// Conditional branch instruction.
1675//---
1676
1677// Condition code.
1678// 4-bit immediate. Pretty-printed as <cc>
1679def ccode : Operand<i32> {
1680  let PrintMethod = "printCondCode";
1681  let ParserMatchClass = CondCode;
1682}
1683def inv_ccode : Operand<i32> {
1684  // AL and NV are invalid in the aliases which use inv_ccode
1685  let PrintMethod = "printInverseCondCode";
1686  let ParserMatchClass = CondCode;
1687  let MCOperandPredicate = [{
1688    return MCOp.isImm() &&
1689           MCOp.getImm() != AArch64CC::AL &&
1690           MCOp.getImm() != AArch64CC::NV;
1691  }];
1692}
1693
1694// Conditional branch target. 19-bit immediate. The low two bits of the target
1695// offset are implied zero and so are not part of the immediate.
1696def am_brcond : Operand<OtherVT> {
1697  let EncoderMethod = "getCondBranchTargetOpValue";
1698  let DecoderMethod = "DecodePCRelLabel19";
1699  let PrintMethod = "printAlignedLabel";
1700  let ParserMatchClass = PCRelLabel19Operand;
1701  let OperandType = "OPERAND_PCREL";
1702}
1703
1704class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1705                     "b", ".$cond\t$target", "",
1706                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1707                   Sched<[WriteBr]> {
1708  let isBranch = 1;
1709  let isTerminator = 1;
1710  let Uses = [NZCV];
1711
1712  bits<4> cond;
1713  bits<19> target;
1714  let Inst{31-24} = 0b01010100;
1715  let Inst{23-5} = target;
1716  let Inst{4} = 0;
1717  let Inst{3-0} = cond;
1718}
1719
1720//---
1721// Compare-and-branch instructions.
1722//---
1723class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1724    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1725         asm, "\t$Rt, $target", "",
1726         [(node regtype:$Rt, bb:$target)]>,
1727      Sched<[WriteBr]> {
1728  let isBranch = 1;
1729  let isTerminator = 1;
1730
1731  bits<5> Rt;
1732  bits<19> target;
1733  let Inst{30-25} = 0b011010;
1734  let Inst{24}    = op;
1735  let Inst{23-5}  = target;
1736  let Inst{4-0}   = Rt;
1737}
1738
1739multiclass CmpBranch<bit op, string asm, SDNode node> {
1740  def W : BaseCmpBranch<GPR32, op, asm, node> {
1741    let Inst{31} = 0;
1742  }
1743  def X : BaseCmpBranch<GPR64, op, asm, node> {
1744    let Inst{31} = 1;
1745  }
1746}
1747
1748//---
1749// Test-bit-and-branch instructions.
1750//---
1751// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1752// the target offset are implied zero and so are not part of the immediate.
1753def am_tbrcond : Operand<OtherVT> {
1754  let EncoderMethod = "getTestBranchTargetOpValue";
1755  let PrintMethod = "printAlignedLabel";
1756  let ParserMatchClass = BranchTarget14Operand;
1757  let OperandType = "OPERAND_PCREL";
1758}
1759
1760// AsmOperand classes to emit (or not) special diagnostics
1761def TBZImm0_31Operand : AsmOperandClass {
1762  let Name = "TBZImm0_31";
1763  let PredicateMethod = "isImmInRange<0,31>";
1764  let RenderMethod = "addImmOperands";
1765}
1766def TBZImm32_63Operand : AsmOperandClass {
1767  let Name = "Imm32_63";
1768  let PredicateMethod = "isImmInRange<32,63>";
1769  let DiagnosticType = "InvalidImm0_63";
1770  let RenderMethod = "addImmOperands";
1771}
1772
1773class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1774  return (((uint32_t)Imm) < 32);
1775}]> {
1776  let ParserMatchClass = matcher;
1777}
1778
1779def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1780def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1781
1782def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1783  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1784}]> {
1785  let ParserMatchClass = TBZImm32_63Operand;
1786}
1787
1788class BaseTestBranch<RegisterClass regtype, Operand immtype,
1789                     bit op, string asm, SDNode node>
1790    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1791       asm, "\t$Rt, $bit_off, $target", "",
1792       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1793      Sched<[WriteBr]> {
1794  let isBranch = 1;
1795  let isTerminator = 1;
1796
1797  bits<5> Rt;
1798  bits<6> bit_off;
1799  bits<14> target;
1800
1801  let Inst{30-25} = 0b011011;
1802  let Inst{24}    = op;
1803  let Inst{23-19} = bit_off{4-0};
1804  let Inst{18-5}  = target;
1805  let Inst{4-0}   = Rt;
1806
1807  let DecoderMethod = "DecodeTestAndBranch";
1808}
1809
1810multiclass TestBranch<bit op, string asm, SDNode node> {
1811  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1812    let Inst{31} = 0;
1813  }
1814
1815  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1816    let Inst{31} = 1;
1817  }
1818
1819  // Alias X-reg with 0-31 imm to W-Reg.
1820  def : InstAlias<asm # "\t$Rd, $imm, $target",
1821                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1822                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1823  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1824            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1825            tbz_imm0_31_diag:$imm, bb:$target)>;
1826}
1827
1828//---
1829// Unconditional branch (immediate) instructions.
1830//---
1831def am_b_target : Operand<OtherVT> {
1832  let EncoderMethod = "getBranchTargetOpValue";
1833  let PrintMethod = "printAlignedLabel";
1834  let ParserMatchClass = BranchTarget26Operand;
1835  let OperandType = "OPERAND_PCREL";
1836}
1837def am_bl_target : Operand<i64> {
1838  let EncoderMethod = "getBranchTargetOpValue";
1839  let PrintMethod = "printAlignedLabel";
1840  let ParserMatchClass = BranchTarget26Operand;
1841  let OperandType = "OPERAND_PCREL";
1842}
1843
1844class BImm<bit op, dag iops, string asm, list<dag> pattern>
1845    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1846  bits<26> addr;
1847  let Inst{31}    = op;
1848  let Inst{30-26} = 0b00101;
1849  let Inst{25-0}  = addr;
1850
1851  let DecoderMethod = "DecodeUnconditionalBranch";
1852}
1853
1854class BranchImm<bit op, string asm, list<dag> pattern>
1855    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1856class CallImm<bit op, string asm, list<dag> pattern>
1857    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1858
1859//---
1860// Basic one-operand data processing instructions.
1861//---
1862
1863let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1864class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1865                         SDPatternOperator node>
1866  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1867      [(set regtype:$Rd, (node regtype:$Rn))]>,
1868    Sched<[WriteI, ReadI]> {
1869  bits<5> Rd;
1870  bits<5> Rn;
1871
1872  let Inst{30-13} = 0b101101011000000000;
1873  let Inst{12-10} = opc;
1874  let Inst{9-5}   = Rn;
1875  let Inst{4-0}   = Rd;
1876}
1877
1878let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1879multiclass OneOperandData<bits<3> opc, string asm,
1880                          SDPatternOperator node = null_frag> {
1881  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1882    let Inst{31} = 0;
1883  }
1884
1885  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1886    let Inst{31} = 1;
1887  }
1888}
1889
1890class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1891    : BaseOneOperandData<opc, GPR32, asm, node> {
1892  let Inst{31} = 0;
1893}
1894
1895class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1896    : BaseOneOperandData<opc, GPR64, asm, node> {
1897  let Inst{31} = 1;
1898}
1899
1900class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1901  : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1902      []>,
1903    Sched<[WriteI, ReadI]> {
1904  bits<5> Rd;
1905  bits<5> Rn;
1906  let Inst{31-15} = 0b11011010110000010;
1907  let Inst{14-12} = opcode_prefix;
1908  let Inst{11-10} = opcode;
1909  let Inst{9-5} = Rn;
1910  let Inst{4-0} = Rd;
1911}
1912
1913class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1914  : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1915  bits<5> Rd;
1916  let Inst{31-15} = 0b11011010110000010;
1917  let Inst{14-12} = opcode_prefix;
1918  let Inst{11-10} = opcode;
1919  let Inst{9-5} = 0b11111;
1920  let Inst{4-0} = Rd;
1921}
1922
1923class SignAuthTwoOperand<bits<4> opc, string asm,
1924                         SDPatternOperator OpNode>
1925  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1926      asm, "\t$Rd, $Rn, $Rm", "",
1927      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1928    Sched<[WriteI, ReadI, ReadI]> {
1929  bits<5> Rd;
1930  bits<5> Rn;
1931  bits<5> Rm;
1932  let Inst{31-21} = 0b10011010110;
1933  let Inst{20-16} = Rm;
1934  let Inst{15-14} = 0b00;
1935  let Inst{13-10} = opc;
1936  let Inst{9-5}   = Rn;
1937  let Inst{4-0}   = Rd;
1938}
1939
1940// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1941class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1942    : I<(outs), iops, asm, ops, "", []>,
1943      Sched<[WriteI, ReadI, ReadI]> {
1944  let Uses = [NZCV];
1945  bits<5> Rn;
1946  let Inst{31}    = sf;
1947  let Inst{30-15} = 0b0111010000000000;
1948  let Inst{14}    = sz;
1949  let Inst{13-10} = 0b0010;
1950  let Inst{9-5}   = Rn;
1951  let Inst{4-0}   = 0b01101;
1952}
1953
1954class FlagRotate<dag iops, string asm, string ops>
1955    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1956  bits<6> imm;
1957  bits<4> mask;
1958  let Inst{20-15} = imm;
1959  let Inst{13-10} = 0b0001;
1960  let Inst{4}     = 0b0;
1961  let Inst{3-0}   = mask;
1962}
1963
1964//---
1965// Basic two-operand data processing instructions.
1966//---
1967class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1968                          list<dag> pattern>
1969    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1970        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1971      Sched<[WriteI, ReadI, ReadI]> {
1972  let Uses = [NZCV];
1973  bits<5> Rd;
1974  bits<5> Rn;
1975  bits<5> Rm;
1976  let Inst{30}    = isSub;
1977  let Inst{28-21} = 0b11010000;
1978  let Inst{20-16} = Rm;
1979  let Inst{15-10} = 0;
1980  let Inst{9-5}   = Rn;
1981  let Inst{4-0}   = Rd;
1982}
1983
1984class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1985                      SDNode OpNode>
1986    : BaseBaseAddSubCarry<isSub, regtype, asm,
1987        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1988
1989class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1990                              SDNode OpNode>
1991    : BaseBaseAddSubCarry<isSub, regtype, asm,
1992        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1993         (implicit NZCV)]> {
1994  let Defs = [NZCV];
1995}
1996
1997multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1998                       SDNode OpNode, SDNode OpNode_setflags> {
1999  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2000    let Inst{31} = 0;
2001    let Inst{29} = 0;
2002  }
2003  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2004    let Inst{31} = 1;
2005    let Inst{29} = 0;
2006  }
2007
2008  // Sets flags.
2009  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2010                                    OpNode_setflags> {
2011    let Inst{31} = 0;
2012    let Inst{29} = 1;
2013  }
2014  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2015                                    OpNode_setflags> {
2016    let Inst{31} = 1;
2017    let Inst{29} = 1;
2018  }
2019}
2020
2021class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2022                     SDPatternOperator OpNode,
2023                     RegisterClass in1regtype = regtype,
2024                     RegisterClass in2regtype = regtype>
2025  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2026      asm, "\t$Rd, $Rn, $Rm", "",
2027      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2028  bits<5> Rd;
2029  bits<5> Rn;
2030  bits<5> Rm;
2031  let Inst{30-21} = 0b0011010110;
2032  let Inst{20-16} = Rm;
2033  let Inst{15-14} = 0b00;
2034  let Inst{13-10} = opc;
2035  let Inst{9-5}   = Rn;
2036  let Inst{4-0}   = Rd;
2037}
2038
2039class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2040              SDPatternOperator OpNode>
2041    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2042  let Inst{10}    = isSigned;
2043}
2044
2045multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2046  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2047           Sched<[WriteID32, ReadID, ReadID]> {
2048    let Inst{31} = 0;
2049  }
2050  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2051           Sched<[WriteID64, ReadID, ReadID]> {
2052    let Inst{31} = 1;
2053  }
2054}
2055
2056class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2057                SDPatternOperator OpNode = null_frag>
2058  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2059    Sched<[WriteIS, ReadI]> {
2060  let Inst{11-10} = shift_type;
2061}
2062
2063multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2064  def Wr : BaseShift<shift_type, GPR32, asm> {
2065    let Inst{31} = 0;
2066  }
2067
2068  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2069    let Inst{31} = 1;
2070  }
2071
2072  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2073            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2074                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2075
2076  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2077            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2078
2079  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2080            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2081
2082  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2083            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2084
2085  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2086            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2087                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2088
2089  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2090            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2091                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2092}
2093
2094class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2095    : InstAlias<asm#"\t$dst, $src1, $src2",
2096                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2097
2098class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2099                       RegisterClass addtype, string asm,
2100                       list<dag> pattern>
2101  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2102      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2103  bits<5> Rd;
2104  bits<5> Rn;
2105  bits<5> Rm;
2106  bits<5> Ra;
2107  let Inst{30-24} = 0b0011011;
2108  let Inst{23-21} = opc;
2109  let Inst{20-16} = Rm;
2110  let Inst{15}    = isSub;
2111  let Inst{14-10} = Ra;
2112  let Inst{9-5}   = Rn;
2113  let Inst{4-0}   = Rd;
2114}
2115
2116multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
2117  // MADD/MSUB generation is decided by MachineCombiner.cpp
2118  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2119      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2120      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2121    let Inst{31} = 0;
2122  }
2123
2124  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2125      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2126      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2127    let Inst{31} = 1;
2128  }
2129}
2130
2131class WideMulAccum<bit isSub, bits<3> opc, string asm,
2132                   SDNode AccNode, SDNode ExtNode>
2133  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2134    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2135                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2136    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2137  let Inst{31} = 1;
2138}
2139
2140class MulHi<bits<3> opc, string asm, SDNode OpNode>
2141  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2142      asm, "\t$Rd, $Rn, $Rm", "",
2143      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2144    Sched<[WriteIM64, ReadIM, ReadIM]> {
2145  bits<5> Rd;
2146  bits<5> Rn;
2147  bits<5> Rm;
2148  let Inst{31-24} = 0b10011011;
2149  let Inst{23-21} = opc;
2150  let Inst{20-16} = Rm;
2151  let Inst{15}    = 0;
2152  let Inst{9-5}   = Rn;
2153  let Inst{4-0}   = Rd;
2154
2155  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2156  // (i.e. all bits 1) but is ignored by the processor.
2157  let PostEncoderMethod = "fixMulHigh";
2158}
2159
2160class MulAccumWAlias<string asm, Instruction inst>
2161    : InstAlias<asm#"\t$dst, $src1, $src2",
2162                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2163class MulAccumXAlias<string asm, Instruction inst>
2164    : InstAlias<asm#"\t$dst, $src1, $src2",
2165                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2166class WideMulAccumAlias<string asm, Instruction inst>
2167    : InstAlias<asm#"\t$dst, $src1, $src2",
2168                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2169
2170class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2171              SDPatternOperator OpNode, string asm>
2172  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2173      asm, "\t$Rd, $Rn, $Rm", "",
2174      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2175    Sched<[WriteISReg, ReadI, ReadISReg]> {
2176  bits<5> Rd;
2177  bits<5> Rn;
2178  bits<5> Rm;
2179
2180  let Inst{31} = sf;
2181  let Inst{30-21} = 0b0011010110;
2182  let Inst{20-16} = Rm;
2183  let Inst{15-13} = 0b010;
2184  let Inst{12} = C;
2185  let Inst{11-10} = sz;
2186  let Inst{9-5} = Rn;
2187  let Inst{4-0} = Rd;
2188  let Predicates = [HasCRC];
2189}
2190
2191//---
2192// Address generation.
2193//---
2194
2195class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2196    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2197        pattern>,
2198      Sched<[WriteI]> {
2199  bits<5>  Xd;
2200  bits<21> label;
2201  let Inst{31}    = page;
2202  let Inst{30-29} = label{1-0};
2203  let Inst{28-24} = 0b10000;
2204  let Inst{23-5}  = label{20-2};
2205  let Inst{4-0}   = Xd;
2206
2207  let DecoderMethod = "DecodeAdrInstruction";
2208}
2209
2210//---
2211// Move immediate.
2212//---
2213
2214def movimm32_imm : Operand<i32> {
2215  let ParserMatchClass = AsmImmRange<0, 65535>;
2216  let EncoderMethod = "getMoveWideImmOpValue";
2217  let PrintMethod = "printImm";
2218}
2219def movimm32_shift : Operand<i32> {
2220  let PrintMethod = "printShifter";
2221  let ParserMatchClass = MovImm32ShifterOperand;
2222}
2223def movimm64_shift : Operand<i32> {
2224  let PrintMethod = "printShifter";
2225  let ParserMatchClass = MovImm64ShifterOperand;
2226}
2227
2228let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2229class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2230                        string asm>
2231  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2232       asm, "\t$Rd, $imm$shift", "", []>,
2233    Sched<[WriteImm]> {
2234  bits<5> Rd;
2235  bits<16> imm;
2236  bits<6> shift;
2237  let Inst{30-29} = opc;
2238  let Inst{28-23} = 0b100101;
2239  let Inst{22-21} = shift{5-4};
2240  let Inst{20-5}  = imm;
2241  let Inst{4-0}   = Rd;
2242
2243  let DecoderMethod = "DecodeMoveImmInstruction";
2244}
2245
2246multiclass MoveImmediate<bits<2> opc, string asm> {
2247  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2248    let Inst{31} = 0;
2249  }
2250
2251  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2252    let Inst{31} = 1;
2253  }
2254}
2255
2256let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2257class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2258                          string asm>
2259  : I<(outs regtype:$Rd),
2260      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2261       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2262    Sched<[WriteI, ReadI]> {
2263  bits<5> Rd;
2264  bits<16> imm;
2265  bits<6> shift;
2266  let Inst{30-29} = opc;
2267  let Inst{28-23} = 0b100101;
2268  let Inst{22-21} = shift{5-4};
2269  let Inst{20-5}  = imm;
2270  let Inst{4-0}   = Rd;
2271
2272  let DecoderMethod = "DecodeMoveImmInstruction";
2273}
2274
2275multiclass InsertImmediate<bits<2> opc, string asm> {
2276  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2277    let Inst{31} = 0;
2278  }
2279
2280  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2281    let Inst{31} = 1;
2282  }
2283}
2284
2285//---
2286// Add/Subtract
2287//---
2288
2289class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2290                    string asm_inst, string asm_ops,
2291                    dag inputs, dag pattern>
2292    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2293      Sched<[WriteI, ReadI]> {
2294  bits<5>  Rd;
2295  bits<5>  Rn;
2296  let Inst{30}    = isSub;
2297  let Inst{29}    = setFlags;
2298  let Inst{28-24} = 0b10001;
2299  let Inst{9-5}   = Rn;
2300  let Inst{4-0}   = Rd;
2301}
2302
2303class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2304                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2305                     string asm_inst, SDPatternOperator OpNode>
2306    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2307                    (ins srcRegtype:$Rn, immtype:$imm),
2308                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2309  bits<14> imm;
2310  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2311  let Inst{21-10} = imm{11-0};
2312  let DecoderMethod = "DecodeAddSubImmShift";
2313}
2314
2315class BaseAddSubRegPseudo<RegisterClass regtype,
2316                          SDPatternOperator OpNode>
2317    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2318             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2319      Sched<[WriteI, ReadI, ReadI]>;
2320
2321class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2322                     arith_shifted_reg shifted_regtype, string asm,
2323                     SDPatternOperator OpNode>
2324    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2325        asm, "\t$Rd, $Rn, $Rm", "",
2326        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2327      Sched<[WriteISReg, ReadI, ReadISReg]> {
2328  // The operands are in order to match the 'addr' MI operands, so we
2329  // don't need an encoder method and by-name matching. Just use the default
2330  // in-order handling. Since we're using by-order, make sure the names
2331  // do not match.
2332  bits<5> dst;
2333  bits<5> src1;
2334  bits<5> src2;
2335  bits<8> shift;
2336  let Inst{30}    = isSub;
2337  let Inst{29}    = setFlags;
2338  let Inst{28-24} = 0b01011;
2339  let Inst{23-22} = shift{7-6};
2340  let Inst{21}    = 0;
2341  let Inst{20-16} = src2;
2342  let Inst{15-10} = shift{5-0};
2343  let Inst{9-5}   = src1;
2344  let Inst{4-0}   = dst;
2345
2346  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2347}
2348
2349class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2350                     RegisterClass src1Regtype, Operand src2Regtype,
2351                     string asm, SDPatternOperator OpNode>
2352    : I<(outs dstRegtype:$R1),
2353        (ins src1Regtype:$R2, src2Regtype:$R3),
2354        asm, "\t$R1, $R2, $R3", "",
2355        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2356      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2357  bits<5> Rd;
2358  bits<5> Rn;
2359  bits<5> Rm;
2360  bits<6> ext;
2361  let Inst{30}    = isSub;
2362  let Inst{29}    = setFlags;
2363  let Inst{28-24} = 0b01011;
2364  let Inst{23-21} = 0b001;
2365  let Inst{20-16} = Rm;
2366  let Inst{15-13} = ext{5-3};
2367  let Inst{12-10} = ext{2-0};
2368  let Inst{9-5}   = Rn;
2369  let Inst{4-0}   = Rd;
2370
2371  let DecoderMethod = "DecodeAddSubERegInstruction";
2372}
2373
2374let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2375class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2376                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2377                       Operand ext_op, string asm>
2378    : I<(outs dstRegtype:$Rd),
2379        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2380        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2381      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2382  bits<5> Rd;
2383  bits<5> Rn;
2384  bits<5> Rm;
2385  bits<6> ext;
2386  let Inst{30}    = isSub;
2387  let Inst{29}    = setFlags;
2388  let Inst{28-24} = 0b01011;
2389  let Inst{23-21} = 0b001;
2390  let Inst{20-16} = Rm;
2391  let Inst{15}    = ext{5};
2392  let Inst{12-10} = ext{2-0};
2393  let Inst{9-5}   = Rn;
2394  let Inst{4-0}   = Rd;
2395
2396  let DecoderMethod = "DecodeAddSubERegInstruction";
2397}
2398
2399// Aliases for register+register add/subtract.
2400class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2401                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2402                     int shiftExt>
2403    : InstAlias<asm#"\t$dst, $src1, $src2",
2404                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2405                      shiftExt)>;
2406
2407multiclass AddSub<bit isSub, string mnemonic, string alias,
2408                  SDPatternOperator OpNode = null_frag> {
2409  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2410  // Add/Subtract immediate
2411  // Increase the weight of the immediate variant to try to match it before
2412  // the extended register variant.
2413  // We used to match the register variant before the immediate when the
2414  // register argument could be implicitly zero-extended.
2415  let AddedComplexity = 6 in
2416  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2417                           mnemonic, OpNode> {
2418    let Inst{31} = 0;
2419  }
2420  let AddedComplexity = 6 in
2421  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2422                           mnemonic, OpNode> {
2423    let Inst{31} = 1;
2424  }
2425
2426  // Add/Subtract register - Only used for CodeGen
2427  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2428  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2429
2430  // Add/Subtract shifted register
2431  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2432                           OpNode> {
2433    let Inst{31} = 0;
2434  }
2435  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2436                           OpNode> {
2437    let Inst{31} = 1;
2438  }
2439  }
2440
2441  // Add/Subtract extended register
2442  let AddedComplexity = 1, hasSideEffects = 0 in {
2443  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2444                           arith_extended_reg32_i32, mnemonic, OpNode> {
2445    let Inst{31} = 0;
2446  }
2447  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2448                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2449    let Inst{31} = 1;
2450  }
2451  }
2452
2453  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2454                               arith_extendlsl64, mnemonic> {
2455    // UXTX and SXTX only.
2456    let Inst{14-13} = 0b11;
2457    let Inst{31} = 1;
2458  }
2459
2460  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2461  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2462                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2463                      addsub_shifted_imm32_neg:$imm), 0>;
2464  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2465                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2466                       addsub_shifted_imm64_neg:$imm), 0>;
2467
2468  // Register/register aliases with no shift when SP is not used.
2469  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2470                       GPR32, GPR32, GPR32, 0>;
2471  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2472                       GPR64, GPR64, GPR64, 0>;
2473
2474  // Register/register aliases with no shift when either the destination or
2475  // first source register is SP.
2476  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2477                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2478  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2479                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2480  def : AddSubRegAlias<mnemonic,
2481                       !cast<Instruction>(NAME#"Xrx64"),
2482                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2483  def : AddSubRegAlias<mnemonic,
2484                       !cast<Instruction>(NAME#"Xrx64"),
2485                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2486}
2487
2488multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2489                   string alias, string cmpAlias> {
2490  let isCompare = 1, Defs = [NZCV] in {
2491  // Add/Subtract immediate
2492  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2493                           mnemonic, OpNode> {
2494    let Inst{31} = 0;
2495  }
2496  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2497                           mnemonic, OpNode> {
2498    let Inst{31} = 1;
2499  }
2500
2501  // Add/Subtract register
2502  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2503  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2504
2505  // Add/Subtract shifted register
2506  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2507                           OpNode> {
2508    let Inst{31} = 0;
2509  }
2510  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2511                           OpNode> {
2512    let Inst{31} = 1;
2513  }
2514
2515  // Add/Subtract extended register
2516  let AddedComplexity = 1 in {
2517  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2518                           arith_extended_reg32_i32, mnemonic, OpNode> {
2519    let Inst{31} = 0;
2520  }
2521  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2522                           arith_extended_reg32_i64, mnemonic, OpNode> {
2523    let Inst{31} = 1;
2524  }
2525  }
2526
2527  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2528                               arith_extendlsl64, mnemonic> {
2529    // UXTX and SXTX only.
2530    let Inst{14-13} = 0b11;
2531    let Inst{31} = 1;
2532  }
2533  } // Defs = [NZCV]
2534
2535  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2536  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2537                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2538                      addsub_shifted_imm32_neg:$imm), 0>;
2539  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2540                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2541                       addsub_shifted_imm64_neg:$imm), 0>;
2542
2543  // Compare aliases
2544  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2545                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2546  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2547                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2548  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2549                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2550  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2551                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2552  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2553                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2554  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2555                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2556  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2557                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2558
2559  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2560  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2561                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2562  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2563                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2564
2565  // Compare shorthands
2566  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2567                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2568  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2569                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2570  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2571                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2572  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2573                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2574
2575  // Register/register aliases with no shift when SP is not used.
2576  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2577                       GPR32, GPR32, GPR32, 0>;
2578  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2579                       GPR64, GPR64, GPR64, 0>;
2580
2581  // Register/register aliases with no shift when the first source register
2582  // is SP.
2583  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2584                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2585  def : AddSubRegAlias<mnemonic,
2586                       !cast<Instruction>(NAME#"Xrx64"),
2587                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2588}
2589
2590class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2591      : BaseAddSubImm<
2592          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2593          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2594          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2595  bits<6> imm6;
2596  bits<4> imm4;
2597  let Inst{31} = 1;
2598  let Inst{23-22} = 0b10;
2599  let Inst{21-16} = imm6;
2600  let Inst{15-14} = 0b00;
2601  let Inst{13-10} = imm4;
2602  let Unpredictable{15-14} = 0b11;
2603}
2604
2605class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2606      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2607  let Inst{31} = 1;
2608  let Inst{29} = setsFlags;
2609}
2610
2611//---
2612// Extract
2613//---
2614def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2615                                      SDTCisPtrTy<3>]>;
2616def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2617
2618class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2619                     list<dag> patterns>
2620    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2621         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2622      Sched<[WriteExtr, ReadExtrHi]> {
2623  bits<5> Rd;
2624  bits<5> Rn;
2625  bits<5> Rm;
2626  bits<6> imm;
2627
2628  let Inst{30-23} = 0b00100111;
2629  let Inst{21}    = 0;
2630  let Inst{20-16} = Rm;
2631  let Inst{15-10} = imm;
2632  let Inst{9-5}   = Rn;
2633  let Inst{4-0}   = Rd;
2634}
2635
2636multiclass ExtractImm<string asm> {
2637  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2638                      [(set GPR32:$Rd,
2639                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2640    let Inst{31} = 0;
2641    let Inst{22} = 0;
2642    // imm<5> must be zero.
2643    let imm{5}   = 0;
2644  }
2645  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2646                      [(set GPR64:$Rd,
2647                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2648
2649    let Inst{31} = 1;
2650    let Inst{22} = 1;
2651  }
2652}
2653
2654//---
2655// Bitfield
2656//---
2657
2658let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2659class BaseBitfieldImm<bits<2> opc,
2660                      RegisterClass regtype, Operand imm_type, string asm>
2661    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2662         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2663      Sched<[WriteIS, ReadI]> {
2664  bits<5> Rd;
2665  bits<5> Rn;
2666  bits<6> immr;
2667  bits<6> imms;
2668
2669  let Inst{30-29} = opc;
2670  let Inst{28-23} = 0b100110;
2671  let Inst{21-16} = immr;
2672  let Inst{15-10} = imms;
2673  let Inst{9-5}   = Rn;
2674  let Inst{4-0}   = Rd;
2675}
2676
2677multiclass BitfieldImm<bits<2> opc, string asm> {
2678  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2679    let Inst{31} = 0;
2680    let Inst{22} = 0;
2681    // imms<5> and immr<5> must be zero, else ReservedValue().
2682    let Inst{21} = 0;
2683    let Inst{15} = 0;
2684  }
2685  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2686    let Inst{31} = 1;
2687    let Inst{22} = 1;
2688  }
2689}
2690
2691let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2692class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2693                      RegisterClass regtype, Operand imm_type, string asm>
2694    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2695                             imm_type:$imms),
2696         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2697      Sched<[WriteIS, ReadI]> {
2698  bits<5> Rd;
2699  bits<5> Rn;
2700  bits<6> immr;
2701  bits<6> imms;
2702
2703  let Inst{30-29} = opc;
2704  let Inst{28-23} = 0b100110;
2705  let Inst{21-16} = immr;
2706  let Inst{15-10} = imms;
2707  let Inst{9-5}   = Rn;
2708  let Inst{4-0}   = Rd;
2709}
2710
2711multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2712  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2713    let Inst{31} = 0;
2714    let Inst{22} = 0;
2715    // imms<5> and immr<5> must be zero, else ReservedValue().
2716    let Inst{21} = 0;
2717    let Inst{15} = 0;
2718  }
2719  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2720    let Inst{31} = 1;
2721    let Inst{22} = 1;
2722  }
2723}
2724
2725//---
2726// Logical
2727//---
2728
2729// Logical (immediate)
2730class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2731                     RegisterClass sregtype, Operand imm_type, string asm,
2732                     list<dag> pattern>
2733    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2734         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2735      Sched<[WriteI, ReadI]> {
2736  bits<5>  Rd;
2737  bits<5>  Rn;
2738  bits<13> imm;
2739  let Inst{30-29} = opc;
2740  let Inst{28-23} = 0b100100;
2741  let Inst{22}    = imm{12};
2742  let Inst{21-16} = imm{11-6};
2743  let Inst{15-10} = imm{5-0};
2744  let Inst{9-5}   = Rn;
2745  let Inst{4-0}   = Rd;
2746
2747  let DecoderMethod = "DecodeLogicalImmInstruction";
2748}
2749
2750// Logical (shifted register)
2751class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2752                      logical_shifted_reg shifted_regtype, string asm,
2753                      list<dag> pattern>
2754    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2755        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2756      Sched<[WriteISReg, ReadI, ReadISReg]> {
2757  // The operands are in order to match the 'addr' MI operands, so we
2758  // don't need an encoder method and by-name matching. Just use the default
2759  // in-order handling. Since we're using by-order, make sure the names
2760  // do not match.
2761  bits<5> dst;
2762  bits<5> src1;
2763  bits<5> src2;
2764  bits<8> shift;
2765  let Inst{30-29} = opc;
2766  let Inst{28-24} = 0b01010;
2767  let Inst{23-22} = shift{7-6};
2768  let Inst{21}    = N;
2769  let Inst{20-16} = src2;
2770  let Inst{15-10} = shift{5-0};
2771  let Inst{9-5}   = src1;
2772  let Inst{4-0}   = dst;
2773
2774  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2775}
2776
2777// Aliases for register+register logical instructions.
2778class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2779    : InstAlias<asm#"\t$dst, $src1, $src2",
2780                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2781
2782multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2783                      string Alias> {
2784  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2785  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2786                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2787                                               logical_imm32:$imm))]> {
2788    let Inst{31} = 0;
2789    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2790  }
2791  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2792  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2793                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2794                                               logical_imm64:$imm))]> {
2795    let Inst{31} = 1;
2796  }
2797
2798  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2799                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2800                      logical_imm32_not:$imm), 0>;
2801  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2802                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2803                       logical_imm64_not:$imm), 0>;
2804}
2805
2806multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2807                       string Alias> {
2808  let isCompare = 1, Defs = [NZCV] in {
2809  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2810      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2811    let Inst{31} = 0;
2812    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2813  }
2814  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2815      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2816    let Inst{31} = 1;
2817  }
2818  } // end Defs = [NZCV]
2819
2820  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2821                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2822                      logical_imm32_not:$imm), 0>;
2823  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2824                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2825                       logical_imm64_not:$imm), 0>;
2826}
2827
2828class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2829    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2830             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2831      Sched<[WriteI, ReadI, ReadI]>;
2832
2833// Split from LogicalImm as not all instructions have both.
2834multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2835                      SDPatternOperator OpNode> {
2836  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2837  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2838  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2839  }
2840
2841  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2842                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2843                                                 logical_shifted_reg32:$Rm))]> {
2844    let Inst{31} = 0;
2845  }
2846  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2847                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2848                                                 logical_shifted_reg64:$Rm))]> {
2849    let Inst{31} = 1;
2850  }
2851
2852  def : LogicalRegAlias<mnemonic,
2853                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2854  def : LogicalRegAlias<mnemonic,
2855                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2856}
2857
2858// Split from LogicalReg to allow setting NZCV Defs
2859multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2860                       SDPatternOperator OpNode = null_frag> {
2861  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2862  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2863  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2864
2865  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2866            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2867    let Inst{31} = 0;
2868  }
2869  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2870            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2871    let Inst{31} = 1;
2872  }
2873  } // Defs = [NZCV]
2874
2875  def : LogicalRegAlias<mnemonic,
2876                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2877  def : LogicalRegAlias<mnemonic,
2878                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2879}
2880
2881//---
2882// Conditionally set flags
2883//---
2884
2885let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2886class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2887                            string mnemonic, SDNode OpNode>
2888    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2889         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2890         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2891                             (i32 imm:$cond), NZCV))]>,
2892      Sched<[WriteI, ReadI]> {
2893  let Uses = [NZCV];
2894  let Defs = [NZCV];
2895
2896  bits<5> Rn;
2897  bits<5> imm;
2898  bits<4> nzcv;
2899  bits<4> cond;
2900
2901  let Inst{30}    = op;
2902  let Inst{29-21} = 0b111010010;
2903  let Inst{20-16} = imm;
2904  let Inst{15-12} = cond;
2905  let Inst{11-10} = 0b10;
2906  let Inst{9-5}   = Rn;
2907  let Inst{4}     = 0b0;
2908  let Inst{3-0}   = nzcv;
2909}
2910
2911let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2912class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2913                            SDNode OpNode>
2914    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2915         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2916         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2917                             (i32 imm:$cond), NZCV))]>,
2918      Sched<[WriteI, ReadI, ReadI]> {
2919  let Uses = [NZCV];
2920  let Defs = [NZCV];
2921
2922  bits<5> Rn;
2923  bits<5> Rm;
2924  bits<4> nzcv;
2925  bits<4> cond;
2926
2927  let Inst{30}    = op;
2928  let Inst{29-21} = 0b111010010;
2929  let Inst{20-16} = Rm;
2930  let Inst{15-12} = cond;
2931  let Inst{11-10} = 0b00;
2932  let Inst{9-5}   = Rn;
2933  let Inst{4}     = 0b0;
2934  let Inst{3-0}   = nzcv;
2935}
2936
2937multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2938  // immediate operand variants
2939  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2940    let Inst{31} = 0;
2941  }
2942  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2943    let Inst{31} = 1;
2944  }
2945  // register operand variants
2946  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2947    let Inst{31} = 0;
2948  }
2949  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2950    let Inst{31} = 1;
2951  }
2952}
2953
2954//---
2955// Conditional select
2956//---
2957
2958class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2959    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2960         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2961         [(set regtype:$Rd,
2962               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2963      Sched<[WriteI, ReadI, ReadI]> {
2964  let Uses = [NZCV];
2965
2966  bits<5> Rd;
2967  bits<5> Rn;
2968  bits<5> Rm;
2969  bits<4> cond;
2970
2971  let Inst{30}    = op;
2972  let Inst{29-21} = 0b011010100;
2973  let Inst{20-16} = Rm;
2974  let Inst{15-12} = cond;
2975  let Inst{11-10} = op2;
2976  let Inst{9-5}   = Rn;
2977  let Inst{4-0}   = Rd;
2978}
2979
2980multiclass CondSelect<bit op, bits<2> op2, string asm> {
2981  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2982    let Inst{31} = 0;
2983  }
2984  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2985    let Inst{31} = 1;
2986  }
2987}
2988
2989class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2990                       PatFrag frag>
2991    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2992         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2993         [(set regtype:$Rd,
2994               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2995               (i32 imm:$cond), NZCV))]>,
2996      Sched<[WriteI, ReadI, ReadI]> {
2997  let Uses = [NZCV];
2998
2999  bits<5> Rd;
3000  bits<5> Rn;
3001  bits<5> Rm;
3002  bits<4> cond;
3003
3004  let Inst{30}    = op;
3005  let Inst{29-21} = 0b011010100;
3006  let Inst{20-16} = Rm;
3007  let Inst{15-12} = cond;
3008  let Inst{11-10} = op2;
3009  let Inst{9-5}   = Rn;
3010  let Inst{4-0}   = Rd;
3011}
3012
3013def inv_cond_XFORM : SDNodeXForm<imm, [{
3014  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3015  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3016                                   MVT::i32);
3017}]>;
3018
3019multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3020  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3021    let Inst{31} = 0;
3022  }
3023  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3024    let Inst{31} = 1;
3025  }
3026
3027  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3028            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3029                                           (inv_cond_XFORM imm:$cond))>;
3030
3031  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3032            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3033                                           (inv_cond_XFORM imm:$cond))>;
3034}
3035
3036//---
3037// Special Mask Value
3038//---
3039def maski8_or_more : Operand<i32>,
3040  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3041}
3042def maski16_or_more : Operand<i32>,
3043  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3044}
3045
3046
3047//---
3048// Load/store
3049//---
3050
3051// (unsigned immediate)
3052// Indexed for 8-bit registers. offset is in range [0,4095].
3053def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
3054def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
3055def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
3056def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
3057def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
3058
3059def gi_am_indexed8 :
3060    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3061    GIComplexPatternEquiv<am_indexed8>;
3062def gi_am_indexed16 :
3063    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3064    GIComplexPatternEquiv<am_indexed16>;
3065def gi_am_indexed32 :
3066    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3067    GIComplexPatternEquiv<am_indexed32>;
3068def gi_am_indexed64 :
3069    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3070    GIComplexPatternEquiv<am_indexed64>;
3071def gi_am_indexed128 :
3072    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3073    GIComplexPatternEquiv<am_indexed128>;
3074
3075class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3076  let Name = "UImm12Offset" # Scale;
3077  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3078  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3079  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3080}
3081
3082def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3083def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3084def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3085def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3086def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3087
3088class uimm12_scaled<int Scale> : Operand<i64> {
3089  let ParserMatchClass
3090   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3091  let EncoderMethod
3092   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3093  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3094}
3095
3096def uimm12s1 : uimm12_scaled<1>;
3097def uimm12s2 : uimm12_scaled<2>;
3098def uimm12s4 : uimm12_scaled<4>;
3099def uimm12s8 : uimm12_scaled<8>;
3100def uimm12s16 : uimm12_scaled<16>;
3101
3102class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3103                      string asm, list<dag> pattern>
3104    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3105  bits<5> Rt;
3106
3107  bits<5> Rn;
3108  bits<12> offset;
3109
3110  let Inst{31-30} = sz;
3111  let Inst{29-27} = 0b111;
3112  let Inst{26}    = V;
3113  let Inst{25-24} = 0b01;
3114  let Inst{23-22} = opc;
3115  let Inst{21-10} = offset;
3116  let Inst{9-5}   = Rn;
3117  let Inst{4-0}   = Rt;
3118
3119  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3120}
3121
3122multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3123                  Operand indextype, string asm, list<dag> pattern> {
3124  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3125  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3126                           (ins GPR64sp:$Rn, indextype:$offset),
3127                           asm, pattern>,
3128           Sched<[WriteLD]>;
3129
3130  def : InstAlias<asm # "\t$Rt, [$Rn]",
3131                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3132}
3133
3134multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3135             Operand indextype, string asm, list<dag> pattern> {
3136  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3137  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3138                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3139                           asm, pattern>,
3140           Sched<[WriteST]>;
3141
3142  def : InstAlias<asm # "\t$Rt, [$Rn]",
3143                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3144}
3145
3146// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3147// substitute zero-registers automatically.
3148//
3149// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3150//       into StoreUI.
3151multiclass StoreUIz<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
3163def PrefetchOperand : AsmOperandClass {
3164  let Name = "Prefetch";
3165  let ParserMethod = "tryParsePrefetch";
3166}
3167def prfop : Operand<i32> {
3168  let PrintMethod = "printPrefetchOp";
3169  let ParserMatchClass = PrefetchOperand;
3170}
3171
3172let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3173class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3174    : BaseLoadStoreUI<sz, V, opc,
3175                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3176                      asm, pat>,
3177      Sched<[WriteLD]>;
3178
3179//---
3180// Load literal
3181//---
3182
3183// Load literal address: 19-bit immediate. The low two bits of the target
3184// offset are implied zero and so are not part of the immediate.
3185def am_ldrlit : Operand<iPTR> {
3186  let EncoderMethod = "getLoadLiteralOpValue";
3187  let DecoderMethod = "DecodePCRelLabel19";
3188  let PrintMethod = "printAlignedLabel";
3189  let ParserMatchClass = PCRelLabel19Operand;
3190  let OperandType = "OPERAND_PCREL";
3191}
3192
3193let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3194class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3195    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3196        asm, "\t$Rt, $label", "", pat>,
3197      Sched<[WriteLD]> {
3198  bits<5> Rt;
3199  bits<19> label;
3200  let Inst{31-30} = opc;
3201  let Inst{29-27} = 0b011;
3202  let Inst{26}    = V;
3203  let Inst{25-24} = 0b00;
3204  let Inst{23-5}  = label;
3205  let Inst{4-0}   = Rt;
3206}
3207
3208let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3209class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3210    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3211        asm, "\t$Rt, $label", "", pat>,
3212      Sched<[WriteLD]> {
3213  bits<5> Rt;
3214  bits<19> label;
3215  let Inst{31-30} = opc;
3216  let Inst{29-27} = 0b011;
3217  let Inst{26}    = V;
3218  let Inst{25-24} = 0b00;
3219  let Inst{23-5}  = label;
3220  let Inst{4-0}   = Rt;
3221}
3222
3223//---
3224// Load/store register offset
3225//---
3226
3227def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3228def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3229def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3230def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3231def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3232
3233def gi_ro_Xindexed8 :
3234    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3235    GIComplexPatternEquiv<ro_Xindexed8>;
3236def gi_ro_Xindexed16 :
3237    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3238    GIComplexPatternEquiv<ro_Xindexed16>;
3239def gi_ro_Xindexed32 :
3240    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3241    GIComplexPatternEquiv<ro_Xindexed32>;
3242def gi_ro_Xindexed64 :
3243    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3244    GIComplexPatternEquiv<ro_Xindexed64>;
3245def gi_ro_Xindexed128 :
3246    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3247    GIComplexPatternEquiv<ro_Xindexed128>;
3248
3249def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3250def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3251def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3252def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3253def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3254
3255def gi_ro_Windexed8 :
3256    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3257    GIComplexPatternEquiv<ro_Windexed8>;
3258def gi_ro_Windexed16 :
3259    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3260    GIComplexPatternEquiv<ro_Windexed16>;
3261def gi_ro_Windexed32 :
3262    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3263    GIComplexPatternEquiv<ro_Windexed32>;
3264def gi_ro_Windexed64 :
3265    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3266    GIComplexPatternEquiv<ro_Windexed64>;
3267def gi_ro_Windexed128 :
3268    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3269    GIComplexPatternEquiv<ro_Windexed128>;
3270
3271class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3272  let Name = "Mem" # Reg # "Extend" # Width;
3273  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3274  let RenderMethod = "addMemExtendOperands";
3275  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3276}
3277
3278def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3279  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3280  // the trivial shift.
3281  let RenderMethod = "addMemExtend8Operands";
3282}
3283def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3284def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3285def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3286def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3287
3288def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3289  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3290  // the trivial shift.
3291  let RenderMethod = "addMemExtend8Operands";
3292}
3293def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3294def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3295def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3296def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3297
3298class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3299        : Operand<i32> {
3300  let ParserMatchClass = ParserClass;
3301  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3302  let DecoderMethod = "DecodeMemExtend";
3303  let EncoderMethod = "getMemExtendOpValue";
3304  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3305}
3306
3307def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3308def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3309def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3310def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3311def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3312
3313def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3314def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3315def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3316def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3317def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3318
3319class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3320                  Operand wextend, Operand xextend>  {
3321  // CodeGen-level pattern covering the entire addressing mode.
3322  ComplexPattern Wpat = windex;
3323  ComplexPattern Xpat = xindex;
3324
3325  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3326  Operand Wext = wextend;
3327  Operand Xext = xextend;
3328}
3329
3330def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3331def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3332def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3333def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3334def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3335                       ro_Xextend128>;
3336
3337class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3338                      string asm, dag ins, dag outs, list<dag> pat>
3339    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3340  bits<5> Rt;
3341  bits<5> Rn;
3342  bits<5> Rm;
3343  bits<2> extend;
3344  let Inst{31-30} = sz;
3345  let Inst{29-27} = 0b111;
3346  let Inst{26}    = V;
3347  let Inst{25-24} = 0b00;
3348  let Inst{23-22} = opc;
3349  let Inst{21}    = 1;
3350  let Inst{20-16} = Rm;
3351  let Inst{15}    = extend{1}; // sign extend Rm?
3352  let Inst{14}    = 1;
3353  let Inst{12}    = extend{0}; // do shift?
3354  let Inst{11-10} = 0b10;
3355  let Inst{9-5}   = Rn;
3356  let Inst{4-0}   = Rt;
3357}
3358
3359class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3360  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3361              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3362
3363multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3364                   string asm, ValueType Ty, SDPatternOperator loadop> {
3365  let AddedComplexity = 10 in
3366  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3367                 (outs regtype:$Rt),
3368                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3369                 [(set (Ty regtype:$Rt),
3370                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3371                                             ro_Wextend8:$extend)))]>,
3372           Sched<[WriteLDIdx, ReadAdrBase]> {
3373    let Inst{13} = 0b0;
3374  }
3375
3376  let AddedComplexity = 10 in
3377  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3378                 (outs regtype:$Rt),
3379                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3380                 [(set (Ty regtype:$Rt),
3381                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3382                                             ro_Xextend8:$extend)))]>,
3383           Sched<[WriteLDIdx, ReadAdrBase]> {
3384    let Inst{13} = 0b1;
3385  }
3386
3387  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3388}
3389
3390multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3391                    string asm, ValueType Ty, SDPatternOperator storeop> {
3392  let AddedComplexity = 10 in
3393  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3394                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3395                 [(storeop (Ty regtype:$Rt),
3396                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3397                                         ro_Wextend8:$extend))]>,
3398            Sched<[WriteSTIdx, ReadAdrBase]> {
3399    let Inst{13} = 0b0;
3400  }
3401
3402  let AddedComplexity = 10 in
3403  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3404                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3405                 [(storeop (Ty regtype:$Rt),
3406                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3407                                         ro_Xextend8:$extend))]>,
3408            Sched<[WriteSTIdx, ReadAdrBase]> {
3409    let Inst{13} = 0b1;
3410  }
3411
3412  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3413}
3414
3415class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3416                      string asm, dag ins, dag outs, list<dag> pat>
3417    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3418  bits<5> Rt;
3419  bits<5> Rn;
3420  bits<5> Rm;
3421  bits<2> extend;
3422  let Inst{31-30} = sz;
3423  let Inst{29-27} = 0b111;
3424  let Inst{26}    = V;
3425  let Inst{25-24} = 0b00;
3426  let Inst{23-22} = opc;
3427  let Inst{21}    = 1;
3428  let Inst{20-16} = Rm;
3429  let Inst{15}    = extend{1}; // sign extend Rm?
3430  let Inst{14}    = 1;
3431  let Inst{12}    = extend{0}; // do shift?
3432  let Inst{11-10} = 0b10;
3433  let Inst{9-5}   = Rn;
3434  let Inst{4-0}   = Rt;
3435}
3436
3437multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3438                    string asm, ValueType Ty, SDPatternOperator loadop> {
3439  let AddedComplexity = 10 in
3440  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3441                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3442                 [(set (Ty regtype:$Rt),
3443                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3444                                              ro_Wextend16:$extend)))]>,
3445            Sched<[WriteLDIdx, ReadAdrBase]> {
3446    let Inst{13} = 0b0;
3447  }
3448
3449  let AddedComplexity = 10 in
3450  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3451                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3452                 [(set (Ty regtype:$Rt),
3453                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3454                                             ro_Xextend16:$extend)))]>,
3455            Sched<[WriteLDIdx, ReadAdrBase]> {
3456    let Inst{13} = 0b1;
3457  }
3458
3459  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3460}
3461
3462multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3463                     string asm, ValueType Ty, SDPatternOperator storeop> {
3464  let AddedComplexity = 10 in
3465  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3466                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3467                [(storeop (Ty regtype:$Rt),
3468                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3469                                         ro_Wextend16:$extend))]>,
3470           Sched<[WriteSTIdx, ReadAdrBase]> {
3471    let Inst{13} = 0b0;
3472  }
3473
3474  let AddedComplexity = 10 in
3475  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3476                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3477                [(storeop (Ty regtype:$Rt),
3478                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3479                                         ro_Xextend16:$extend))]>,
3480           Sched<[WriteSTIdx, ReadAdrBase]> {
3481    let Inst{13} = 0b1;
3482  }
3483
3484  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3485}
3486
3487class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3488                      string asm, dag ins, dag outs, list<dag> pat>
3489    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3490  bits<5> Rt;
3491  bits<5> Rn;
3492  bits<5> Rm;
3493  bits<2> extend;
3494  let Inst{31-30} = sz;
3495  let Inst{29-27} = 0b111;
3496  let Inst{26}    = V;
3497  let Inst{25-24} = 0b00;
3498  let Inst{23-22} = opc;
3499  let Inst{21}    = 1;
3500  let Inst{20-16} = Rm;
3501  let Inst{15}    = extend{1}; // sign extend Rm?
3502  let Inst{14}    = 1;
3503  let Inst{12}    = extend{0}; // do shift?
3504  let Inst{11-10} = 0b10;
3505  let Inst{9-5}   = Rn;
3506  let Inst{4-0}   = Rt;
3507}
3508
3509multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3510                    string asm, ValueType Ty, SDPatternOperator loadop> {
3511  let AddedComplexity = 10 in
3512  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3513                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3514                 [(set (Ty regtype:$Rt),
3515                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3516                                              ro_Wextend32:$extend)))]>,
3517           Sched<[WriteLDIdx, ReadAdrBase]> {
3518    let Inst{13} = 0b0;
3519  }
3520
3521  let AddedComplexity = 10 in
3522  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3523                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3524                 [(set (Ty regtype:$Rt),
3525                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3526                                              ro_Xextend32:$extend)))]>,
3527           Sched<[WriteLDIdx, ReadAdrBase]> {
3528    let Inst{13} = 0b1;
3529  }
3530
3531  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3532}
3533
3534multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3535                     string asm, ValueType Ty, SDPatternOperator storeop> {
3536  let AddedComplexity = 10 in
3537  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3538                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3539                [(storeop (Ty regtype:$Rt),
3540                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3541                                         ro_Wextend32:$extend))]>,
3542            Sched<[WriteSTIdx, ReadAdrBase]> {
3543    let Inst{13} = 0b0;
3544  }
3545
3546  let AddedComplexity = 10 in
3547  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3548                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3549                [(storeop (Ty regtype:$Rt),
3550                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3551                                        ro_Xextend32:$extend))]>,
3552            Sched<[WriteSTIdx, ReadAdrBase]> {
3553    let Inst{13} = 0b1;
3554  }
3555
3556  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3557}
3558
3559class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3560                      string asm, dag ins, dag outs, list<dag> pat>
3561    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3562  bits<5> Rt;
3563  bits<5> Rn;
3564  bits<5> Rm;
3565  bits<2> extend;
3566  let Inst{31-30} = sz;
3567  let Inst{29-27} = 0b111;
3568  let Inst{26}    = V;
3569  let Inst{25-24} = 0b00;
3570  let Inst{23-22} = opc;
3571  let Inst{21}    = 1;
3572  let Inst{20-16} = Rm;
3573  let Inst{15}    = extend{1}; // sign extend Rm?
3574  let Inst{14}    = 1;
3575  let Inst{12}    = extend{0}; // do shift?
3576  let Inst{11-10} = 0b10;
3577  let Inst{9-5}   = Rn;
3578  let Inst{4-0}   = Rt;
3579}
3580
3581multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3582                    string asm, ValueType Ty, SDPatternOperator loadop> {
3583  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3584  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3585                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3586                [(set (Ty regtype:$Rt),
3587                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3588                                             ro_Wextend64:$extend)))]>,
3589           Sched<[WriteLDIdx, ReadAdrBase]> {
3590    let Inst{13} = 0b0;
3591  }
3592
3593  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3594  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3595                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3596                 [(set (Ty regtype:$Rt),
3597                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3598                                              ro_Xextend64:$extend)))]>,
3599           Sched<[WriteLDIdx, ReadAdrBase]> {
3600    let Inst{13} = 0b1;
3601  }
3602
3603  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3604}
3605
3606multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3607                     string asm, ValueType Ty, SDPatternOperator storeop> {
3608  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3609  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3610                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3611                [(storeop (Ty regtype:$Rt),
3612                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3613                                         ro_Wextend64:$extend))]>,
3614            Sched<[WriteSTIdx, ReadAdrBase]> {
3615    let Inst{13} = 0b0;
3616  }
3617
3618  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3619  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3620                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3621                [(storeop (Ty regtype:$Rt),
3622                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3623                                         ro_Xextend64:$extend))]>,
3624            Sched<[WriteSTIdx, ReadAdrBase]> {
3625    let Inst{13} = 0b1;
3626  }
3627
3628  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3629}
3630
3631class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3632                      string asm, dag ins, dag outs, list<dag> pat>
3633    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3634  bits<5> Rt;
3635  bits<5> Rn;
3636  bits<5> Rm;
3637  bits<2> extend;
3638  let Inst{31-30} = sz;
3639  let Inst{29-27} = 0b111;
3640  let Inst{26}    = V;
3641  let Inst{25-24} = 0b00;
3642  let Inst{23-22} = opc;
3643  let Inst{21}    = 1;
3644  let Inst{20-16} = Rm;
3645  let Inst{15}    = extend{1}; // sign extend Rm?
3646  let Inst{14}    = 1;
3647  let Inst{12}    = extend{0}; // do shift?
3648  let Inst{11-10} = 0b10;
3649  let Inst{9-5}   = Rn;
3650  let Inst{4-0}   = Rt;
3651}
3652
3653multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3654                     string asm, ValueType Ty, SDPatternOperator loadop> {
3655  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3656  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3657                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3658                 [(set (Ty regtype:$Rt),
3659                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3660                                               ro_Wextend128:$extend)))]>,
3661            Sched<[WriteLDIdx, ReadAdrBase]> {
3662    let Inst{13} = 0b0;
3663  }
3664
3665  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3666  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3667                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3668                 [(set (Ty regtype:$Rt),
3669                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3670                                               ro_Xextend128:$extend)))]>,
3671            Sched<[WriteLDIdx, ReadAdrBase]> {
3672    let Inst{13} = 0b1;
3673  }
3674
3675  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3676}
3677
3678multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3679                      string asm, ValueType Ty, SDPatternOperator storeop> {
3680  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3681  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3682               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3683                []>,
3684            Sched<[WriteSTIdx, ReadAdrBase]> {
3685    let Inst{13} = 0b0;
3686  }
3687
3688  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3689  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3690               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3691                []>,
3692            Sched<[WriteSTIdx, ReadAdrBase]> {
3693    let Inst{13} = 0b1;
3694  }
3695
3696  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3697}
3698
3699let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3700class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3701                     string asm, list<dag> pat>
3702    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3703      Sched<[WriteLD]> {
3704  bits<5> Rt;
3705  bits<5> Rn;
3706  bits<5> Rm;
3707  bits<2> extend;
3708  let Inst{31-30} = sz;
3709  let Inst{29-27} = 0b111;
3710  let Inst{26}    = V;
3711  let Inst{25-24} = 0b00;
3712  let Inst{23-22} = opc;
3713  let Inst{21}    = 1;
3714  let Inst{20-16} = Rm;
3715  let Inst{15}    = extend{1}; // sign extend Rm?
3716  let Inst{14}    = 1;
3717  let Inst{12}    = extend{0}; // do shift?
3718  let Inst{11-10} = 0b10;
3719  let Inst{9-5}   = Rn;
3720  let Inst{4-0}   = Rt;
3721}
3722
3723multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3724  def roW : BasePrefetchRO<sz, V, opc, (outs),
3725                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3726                asm, [(AArch64Prefetch imm:$Rt,
3727                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3728                                                    ro_Wextend64:$extend))]> {
3729    let Inst{13} = 0b0;
3730  }
3731
3732  def roX : BasePrefetchRO<sz, V, opc, (outs),
3733                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3734                asm,  [(AArch64Prefetch imm:$Rt,
3735                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3736                                                     ro_Xextend64:$extend))]> {
3737    let Inst{13} = 0b1;
3738  }
3739
3740  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3741               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3742                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3743}
3744
3745//---
3746// Load/store unscaled immediate
3747//---
3748
3749def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3750def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3751def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3752def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3753def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3754
3755def gi_am_unscaled8 :
3756    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3757    GIComplexPatternEquiv<am_unscaled8>;
3758def gi_am_unscaled16 :
3759    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3760    GIComplexPatternEquiv<am_unscaled16>;
3761def gi_am_unscaled32 :
3762    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3763    GIComplexPatternEquiv<am_unscaled32>;
3764def gi_am_unscaled64 :
3765    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3766    GIComplexPatternEquiv<am_unscaled64>;
3767def gi_am_unscaled128 :
3768    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3769    GIComplexPatternEquiv<am_unscaled128>;
3770
3771
3772class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3773                           string asm, list<dag> pattern>
3774    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3775  bits<5> Rt;
3776  bits<5> Rn;
3777  bits<9> offset;
3778  let Inst{31-30} = sz;
3779  let Inst{29-27} = 0b111;
3780  let Inst{26}    = V;
3781  let Inst{25-24} = 0b00;
3782  let Inst{23-22} = opc;
3783  let Inst{21}    = 0;
3784  let Inst{20-12} = offset;
3785  let Inst{11-10} = 0b00;
3786  let Inst{9-5}   = Rn;
3787  let Inst{4-0}   = Rt;
3788
3789  let DecoderMethod = "DecodeSignedLdStInstruction";
3790}
3791
3792// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3793multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3794                              RegisterOperand regtype > {
3795  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3796                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3797          Sched<[WriteST]> {
3798    let Inst{29} = 0;
3799    let Inst{24} = 1;
3800  }
3801  def : InstAlias<asm # "\t$Rt, [$Rn]",
3802                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3803}
3804
3805multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3806                               RegisterOperand regtype > {
3807  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3808                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3809                               asm, []>,
3810          Sched<[WriteST]> {
3811    let Inst{29} = 0;
3812    let Inst{24} = 1;
3813  }
3814  def : InstAlias<asm # "\t$Rt, [$Rn]",
3815                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3816}
3817
3818multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3819                   string asm, list<dag> pattern> {
3820  let AddedComplexity = 1 in // try this before LoadUI
3821  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3822                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3823          Sched<[WriteLD]>;
3824
3825  def : InstAlias<asm # "\t$Rt, [$Rn]",
3826                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3827}
3828
3829multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3830                         string asm, list<dag> pattern> {
3831  let AddedComplexity = 1 in // try this before StoreUI
3832  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3833                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3834                               asm, pattern>,
3835          Sched<[WriteST]>;
3836
3837  def : InstAlias<asm # "\t$Rt, [$Rn]",
3838                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3839}
3840
3841multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3842                            list<dag> pat> {
3843  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3844  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3845                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3846                               asm, pat>,
3847          Sched<[WriteLD]>;
3848
3849  def : InstAlias<asm # "\t$Rt, [$Rn]",
3850                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3851}
3852
3853//---
3854// Load/store unscaled immediate, unprivileged
3855//---
3856
3857class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3858                                dag oops, dag iops, string asm>
3859    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3860  bits<5> Rt;
3861  bits<5> Rn;
3862  bits<9> offset;
3863  let Inst{31-30} = sz;
3864  let Inst{29-27} = 0b111;
3865  let Inst{26}    = V;
3866  let Inst{25-24} = 0b00;
3867  let Inst{23-22} = opc;
3868  let Inst{21}    = 0;
3869  let Inst{20-12} = offset;
3870  let Inst{11-10} = 0b10;
3871  let Inst{9-5}   = Rn;
3872  let Inst{4-0}   = Rt;
3873
3874  let DecoderMethod = "DecodeSignedLdStInstruction";
3875}
3876
3877multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3878                            RegisterClass regtype, string asm> {
3879  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3880  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3881                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3882          Sched<[WriteLD]>;
3883
3884  def : InstAlias<asm # "\t$Rt, [$Rn]",
3885                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3886}
3887
3888multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3889                             RegisterClass regtype, string asm> {
3890  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3891  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3892                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3893                                 asm>,
3894          Sched<[WriteST]>;
3895
3896  def : InstAlias<asm # "\t$Rt, [$Rn]",
3897                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3898}
3899
3900//---
3901// Load/store pre-indexed
3902//---
3903
3904class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3905                          string asm, string cstr, list<dag> pat>
3906    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3907  bits<5> Rt;
3908  bits<5> Rn;
3909  bits<9> offset;
3910  let Inst{31-30} = sz;
3911  let Inst{29-27} = 0b111;
3912  let Inst{26}    = V;
3913  let Inst{25-24} = 0;
3914  let Inst{23-22} = opc;
3915  let Inst{21}    = 0;
3916  let Inst{20-12} = offset;
3917  let Inst{11-10} = 0b11;
3918  let Inst{9-5}   = Rn;
3919  let Inst{4-0}   = Rt;
3920
3921  let DecoderMethod = "DecodeSignedLdStInstruction";
3922}
3923
3924let hasSideEffects = 0 in {
3925let mayStore = 0, mayLoad = 1 in
3926class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3927             string asm>
3928    : BaseLoadStorePreIdx<sz, V, opc,
3929                     (outs GPR64sp:$wback, regtype:$Rt),
3930                     (ins GPR64sp:$Rn, simm9:$offset), asm,
3931                     "$Rn = $wback,@earlyclobber $wback", []>,
3932      Sched<[WriteLD, WriteAdr]>;
3933
3934let mayStore = 1, mayLoad = 0 in
3935class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3936                  string asm, SDPatternOperator storeop, ValueType Ty>
3937    : BaseLoadStorePreIdx<sz, V, opc,
3938                      (outs GPR64sp:$wback),
3939                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3940                      asm, "$Rn = $wback,@earlyclobber $wback",
3941      [(set GPR64sp:$wback,
3942            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3943      Sched<[WriteAdr, WriteST]>;
3944} // hasSideEffects = 0
3945
3946//---
3947// Load/store post-indexed
3948//---
3949
3950class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3951                          string asm, string cstr, list<dag> pat>
3952    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3953  bits<5> Rt;
3954  bits<5> Rn;
3955  bits<9> offset;
3956  let Inst{31-30} = sz;
3957  let Inst{29-27} = 0b111;
3958  let Inst{26}    = V;
3959  let Inst{25-24} = 0b00;
3960  let Inst{23-22} = opc;
3961  let Inst{21}    = 0b0;
3962  let Inst{20-12} = offset;
3963  let Inst{11-10} = 0b01;
3964  let Inst{9-5}   = Rn;
3965  let Inst{4-0}   = Rt;
3966
3967  let DecoderMethod = "DecodeSignedLdStInstruction";
3968}
3969
3970let hasSideEffects = 0 in {
3971let mayStore = 0, mayLoad = 1 in
3972class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3973             string asm>
3974    : BaseLoadStorePostIdx<sz, V, opc,
3975                      (outs GPR64sp:$wback, regtype:$Rt),
3976                      (ins GPR64sp:$Rn, simm9:$offset),
3977                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
3978      Sched<[WriteLD, WriteAdr]>;
3979
3980let mayStore = 1, mayLoad = 0 in
3981class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3982                   string asm, SDPatternOperator storeop, ValueType Ty>
3983    : BaseLoadStorePostIdx<sz, V, opc,
3984                      (outs GPR64sp:$wback),
3985                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3986                       asm, "$Rn = $wback,@earlyclobber $wback",
3987      [(set GPR64sp:$wback,
3988            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3989    Sched<[WriteAdr, WriteST]>;
3990} // hasSideEffects = 0
3991
3992
3993//---
3994// Load/store pair
3995//---
3996
3997// (indexed, offset)
3998
3999class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4000                              string asm>
4001    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4002  bits<5> Rt;
4003  bits<5> Rt2;
4004  bits<5> Rn;
4005  bits<7> offset;
4006  let Inst{31-30} = opc;
4007  let Inst{29-27} = 0b101;
4008  let Inst{26}    = V;
4009  let Inst{25-23} = 0b010;
4010  let Inst{22}    = L;
4011  let Inst{21-15} = offset;
4012  let Inst{14-10} = Rt2;
4013  let Inst{9-5}   = Rn;
4014  let Inst{4-0}   = Rt;
4015
4016  let DecoderMethod = "DecodePairLdStInstruction";
4017}
4018
4019multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4020                          Operand indextype, string asm> {
4021  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4022  def i : BaseLoadStorePairOffset<opc, V, 1,
4023                                  (outs regtype:$Rt, regtype:$Rt2),
4024                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4025          Sched<[WriteLD, WriteLDHi]>;
4026
4027  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4028                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4029                                                  GPR64sp:$Rn, 0)>;
4030}
4031
4032
4033multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4034                           Operand indextype, string asm> {
4035  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4036  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4037                                  (ins regtype:$Rt, regtype:$Rt2,
4038                                       GPR64sp:$Rn, indextype:$offset),
4039                                  asm>,
4040          Sched<[WriteSTP]>;
4041
4042  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4043                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4044                                                  GPR64sp:$Rn, 0)>;
4045}
4046
4047// (pre-indexed)
4048class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4049                              string asm>
4050    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4051  bits<5> Rt;
4052  bits<5> Rt2;
4053  bits<5> Rn;
4054  bits<7> offset;
4055  let Inst{31-30} = opc;
4056  let Inst{29-27} = 0b101;
4057  let Inst{26}    = V;
4058  let Inst{25-23} = 0b011;
4059  let Inst{22}    = L;
4060  let Inst{21-15} = offset;
4061  let Inst{14-10} = Rt2;
4062  let Inst{9-5}   = Rn;
4063  let Inst{4-0}   = Rt;
4064
4065  let DecoderMethod = "DecodePairLdStInstruction";
4066}
4067
4068let hasSideEffects = 0 in {
4069let mayStore = 0, mayLoad = 1 in
4070class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4071                     Operand indextype, string asm>
4072    : BaseLoadStorePairPreIdx<opc, V, 1,
4073                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4074                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4075      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
4076
4077let mayStore = 1, mayLoad = 0 in
4078class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4079                      Operand indextype, string asm>
4080    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4081                             (ins regtype:$Rt, regtype:$Rt2,
4082                                  GPR64sp:$Rn, indextype:$offset),
4083                             asm>,
4084      Sched<[WriteAdr, WriteSTP]>;
4085} // hasSideEffects = 0
4086
4087// (post-indexed)
4088
4089class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4090                              string asm>
4091    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4092  bits<5> Rt;
4093  bits<5> Rt2;
4094  bits<5> Rn;
4095  bits<7> offset;
4096  let Inst{31-30} = opc;
4097  let Inst{29-27} = 0b101;
4098  let Inst{26}    = V;
4099  let Inst{25-23} = 0b001;
4100  let Inst{22}    = L;
4101  let Inst{21-15} = offset;
4102  let Inst{14-10} = Rt2;
4103  let Inst{9-5}   = Rn;
4104  let Inst{4-0}   = Rt;
4105
4106  let DecoderMethod = "DecodePairLdStInstruction";
4107}
4108
4109let hasSideEffects = 0 in {
4110let mayStore = 0, mayLoad = 1 in
4111class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4112                      Operand idxtype, string asm>
4113    : BaseLoadStorePairPostIdx<opc, V, 1,
4114                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4115                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4116      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
4117
4118let mayStore = 1, mayLoad = 0 in
4119class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4120                       Operand idxtype, string asm>
4121    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4122                             (ins regtype:$Rt, regtype:$Rt2,
4123                                  GPR64sp:$Rn, idxtype:$offset),
4124                             asm>,
4125      Sched<[WriteAdr, WriteSTP]>;
4126} // hasSideEffects = 0
4127
4128//  (no-allocate)
4129
4130class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4131                              string asm>
4132    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4133  bits<5> Rt;
4134  bits<5> Rt2;
4135  bits<5> Rn;
4136  bits<7> offset;
4137  let Inst{31-30} = opc;
4138  let Inst{29-27} = 0b101;
4139  let Inst{26}    = V;
4140  let Inst{25-23} = 0b000;
4141  let Inst{22}    = L;
4142  let Inst{21-15} = offset;
4143  let Inst{14-10} = Rt2;
4144  let Inst{9-5}   = Rn;
4145  let Inst{4-0}   = Rt;
4146
4147  let DecoderMethod = "DecodePairLdStInstruction";
4148}
4149
4150multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4151                           Operand indextype, string asm> {
4152  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4153  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4154                                   (outs regtype:$Rt, regtype:$Rt2),
4155                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4156          Sched<[WriteLD, WriteLDHi]>;
4157
4158
4159  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4160                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4161                                                  GPR64sp:$Rn, 0)>;
4162}
4163
4164multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4165                      Operand indextype, string asm> {
4166  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4167  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4168                                   (ins regtype:$Rt, regtype:$Rt2,
4169                                        GPR64sp:$Rn, indextype:$offset),
4170                                   asm>,
4171          Sched<[WriteSTP]>;
4172
4173  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4174                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4175                                                  GPR64sp:$Rn, 0)>;
4176}
4177
4178//---
4179// Load/store exclusive
4180//---
4181
4182// True exclusive operations write to and/or read from the system's exclusive
4183// monitors, which as far as a compiler is concerned can be modelled as a
4184// random shared memory address. Hence LoadExclusive mayStore.
4185//
4186// Since these instructions have the undefined register bits set to 1 in
4187// their canonical form, we need a post encoder method to set those bits
4188// to 1 when encoding these instructions. We do this using the
4189// fixLoadStoreExclusive function. This function has template parameters:
4190//
4191// fixLoadStoreExclusive<int hasRs, int hasRt2>
4192//
4193// hasRs indicates that the instruction uses the Rs field, so we won't set
4194// it to 1 (and the same for Rt2). We don't need template parameters for
4195// the other register fields since Rt and Rn are always used.
4196//
4197let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4198class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4199                             dag oops, dag iops, string asm, string operands>
4200    : I<oops, iops, asm, operands, "", []> {
4201  let Inst{31-30} = sz;
4202  let Inst{29-24} = 0b001000;
4203  let Inst{23}    = o2;
4204  let Inst{22}    = L;
4205  let Inst{21}    = o1;
4206  let Inst{15}    = o0;
4207
4208  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4209}
4210
4211// Neither Rs nor Rt2 operands.
4212class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4213                               dag oops, dag iops, string asm, string operands>
4214    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4215  bits<5> Rt;
4216  bits<5> Rn;
4217  let Inst{20-16} = 0b11111;
4218  let Unpredictable{20-16} = 0b11111;
4219  let Inst{14-10} = 0b11111;
4220  let Unpredictable{14-10} = 0b11111;
4221  let Inst{9-5} = Rn;
4222  let Inst{4-0} = Rt;
4223
4224  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4225}
4226
4227// Simple load acquires don't set the exclusive monitor
4228let mayLoad = 1, mayStore = 0 in
4229class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4230                  RegisterClass regtype, string asm>
4231    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4232                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4233      Sched<[WriteLD]>;
4234
4235class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4236                    RegisterClass regtype, string asm>
4237    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4238                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4239      Sched<[WriteLD]>;
4240
4241class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4242                       RegisterClass regtype, string asm>
4243    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4244                             (outs regtype:$Rt, regtype:$Rt2),
4245                             (ins GPR64sp0:$Rn), asm,
4246                             "\t$Rt, $Rt2, [$Rn]">,
4247      Sched<[WriteLD, WriteLDHi]> {
4248  bits<5> Rt;
4249  bits<5> Rt2;
4250  bits<5> Rn;
4251  let Inst{14-10} = Rt2;
4252  let Inst{9-5} = Rn;
4253  let Inst{4-0} = Rt;
4254
4255  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4256}
4257
4258// Simple store release operations do not check the exclusive monitor.
4259let mayLoad = 0, mayStore = 1 in
4260class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4261                   RegisterClass regtype, string asm>
4262    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4263                               (ins regtype:$Rt, GPR64sp0:$Rn),
4264                               asm, "\t$Rt, [$Rn]">,
4265      Sched<[WriteST]>;
4266
4267let mayLoad = 1, mayStore = 1 in
4268class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4269                     RegisterClass regtype, string asm>
4270    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4271                             (ins regtype:$Rt, GPR64sp0:$Rn),
4272                             asm, "\t$Ws, $Rt, [$Rn]">,
4273      Sched<[WriteSTX]> {
4274  bits<5> Ws;
4275  bits<5> Rt;
4276  bits<5> Rn;
4277  let Inst{20-16} = Ws;
4278  let Inst{9-5} = Rn;
4279  let Inst{4-0} = Rt;
4280
4281  let Constraints = "@earlyclobber $Ws";
4282  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4283}
4284
4285class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4286                         RegisterClass regtype, string asm>
4287    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4288                             (outs GPR32:$Ws),
4289                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4290                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4291      Sched<[WriteSTX]> {
4292  bits<5> Ws;
4293  bits<5> Rt;
4294  bits<5> Rt2;
4295  bits<5> Rn;
4296  let Inst{20-16} = Ws;
4297  let Inst{14-10} = Rt2;
4298  let Inst{9-5} = Rn;
4299  let Inst{4-0} = Rt;
4300
4301  let Constraints = "@earlyclobber $Ws";
4302}
4303
4304// Armv8.5-A Memory Tagging Extension
4305class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4306                 string asm_opnds, string cstr, dag oops, dag iops>
4307    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4308      Sched<[]> {
4309  bits<5> Rn;
4310
4311  let Inst{31-24} = 0b11011001;
4312  let Inst{23-22} = opc1;
4313  let Inst{21}    = 1;
4314  // Inst{20-12} defined by subclass
4315  let Inst{11-10} = opc2;
4316  let Inst{9-5}   = Rn;
4317  // Inst{4-0} defined by subclass
4318}
4319
4320class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4321                   dag oops, dag iops>
4322    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4323                  "", oops, iops> {
4324  bits<5> Rt;
4325
4326  let Inst{20-12} = 0b000000000;
4327  let Inst{4-0}   = Rt;
4328
4329  let mayLoad = Load;
4330}
4331
4332class MemTagLoad<string asm_insn, string asm_opnds>
4333    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4334                 (outs GPR64:$wback),
4335                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4336  bits<5> Rt;
4337  bits<9> offset;
4338
4339  let Inst{20-12} = offset;
4340  let Inst{4-0}   = Rt;
4341
4342  let mayLoad = 1;
4343}
4344
4345class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4346                     string asm_opnds, string cstr, dag oops, dag iops>
4347    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4348  bits<5> Rt;
4349  bits<9> offset;
4350
4351  let Inst{20-12} = offset;
4352  let Inst{4-0}   = Rt;
4353
4354  let mayStore = 1;
4355}
4356
4357multiclass MemTagStore<bits<2> opc1, string insn> {
4358  def Offset :
4359    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4360                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4361  def PreIndex :
4362    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4363                    "$Rn = $wback",
4364                    (outs GPR64sp:$wback),
4365                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4366  def PostIndex :
4367    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4368                    "$Rn = $wback",
4369                    (outs GPR64sp:$wback),
4370                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4371
4372  def : InstAlias<insn # "\t$Rt, [$Rn]",
4373                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4374}
4375
4376//---
4377// Exception generation
4378//---
4379
4380let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4381class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4382    : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4383      Sched<[WriteSys]> {
4384  bits<16> imm;
4385  let Inst{31-24} = 0b11010100;
4386  let Inst{23-21} = op1;
4387  let Inst{20-5}  = imm;
4388  let Inst{4-2}   = 0b000;
4389  let Inst{1-0}   = ll;
4390}
4391
4392//---
4393// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4394//--
4395let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4396class UDFType<bits<16> opc, string asm>
4397  : I<(outs), (ins uimm16:$imm),
4398       asm, "\t$imm", "", []>,
4399    Sched<[]> {
4400  bits<16> imm;
4401  let Inst{31-16} = opc;
4402  let Inst{15-0} = imm;
4403}
4404}
4405let Predicates = [HasFPARMv8] in {
4406
4407//---
4408// Floating point to integer conversion
4409//---
4410
4411class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4412                      RegisterClass srcType, RegisterClass dstType,
4413                      string asm, list<dag> pattern>
4414    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4415         asm, "\t$Rd, $Rn", "", pattern>,
4416      Sched<[WriteFCvt]> {
4417  bits<5> Rd;
4418  bits<5> Rn;
4419  let Inst{30-29} = 0b00;
4420  let Inst{28-24} = 0b11110;
4421  let Inst{23-22} = type;
4422  let Inst{21}    = 1;
4423  let Inst{20-19} = rmode;
4424  let Inst{18-16} = opcode;
4425  let Inst{15-10} = 0;
4426  let Inst{9-5}   = Rn;
4427  let Inst{4-0}   = Rd;
4428}
4429
4430let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4431class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4432                      RegisterClass srcType, RegisterClass dstType,
4433                      Operand immType, string asm, list<dag> pattern>
4434    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4435         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4436      Sched<[WriteFCvt]> {
4437  bits<5> Rd;
4438  bits<5> Rn;
4439  bits<6> scale;
4440  let Inst{30-29} = 0b00;
4441  let Inst{28-24} = 0b11110;
4442  let Inst{23-22} = type;
4443  let Inst{21}    = 0;
4444  let Inst{20-19} = rmode;
4445  let Inst{18-16} = opcode;
4446  let Inst{15-10} = scale;
4447  let Inst{9-5}   = Rn;
4448  let Inst{4-0}   = Rd;
4449}
4450
4451multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4452           SDPatternOperator OpN> {
4453  // Unscaled half-precision to 32-bit
4454  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4455                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4456    let Inst{31} = 0; // 32-bit GPR flag
4457    let Predicates = [HasFullFP16];
4458  }
4459
4460  // Unscaled half-precision to 64-bit
4461  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4462                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4463    let Inst{31} = 1; // 64-bit GPR flag
4464    let Predicates = [HasFullFP16];
4465  }
4466
4467  // Unscaled single-precision to 32-bit
4468  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4469                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4470    let Inst{31} = 0; // 32-bit GPR flag
4471  }
4472
4473  // Unscaled single-precision to 64-bit
4474  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4475                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4476    let Inst{31} = 1; // 64-bit GPR flag
4477  }
4478
4479  // Unscaled double-precision to 32-bit
4480  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4481                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4482    let Inst{31} = 0; // 32-bit GPR flag
4483  }
4484
4485  // Unscaled double-precision to 64-bit
4486  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4487                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4488    let Inst{31} = 1; // 64-bit GPR flag
4489  }
4490}
4491
4492multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4493                             SDPatternOperator OpN> {
4494  // Scaled half-precision to 32-bit
4495  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4496                              fixedpoint_f16_i32, asm,
4497              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4498                                          fixedpoint_f16_i32:$scale)))]> {
4499    let Inst{31} = 0; // 32-bit GPR flag
4500    let scale{5} = 1;
4501    let Predicates = [HasFullFP16];
4502  }
4503
4504  // Scaled half-precision to 64-bit
4505  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4506                              fixedpoint_f16_i64, asm,
4507              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4508                                          fixedpoint_f16_i64:$scale)))]> {
4509    let Inst{31} = 1; // 64-bit GPR flag
4510    let Predicates = [HasFullFP16];
4511  }
4512
4513  // Scaled single-precision to 32-bit
4514  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4515                              fixedpoint_f32_i32, asm,
4516              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4517                                          fixedpoint_f32_i32:$scale)))]> {
4518    let Inst{31} = 0; // 32-bit GPR flag
4519    let scale{5} = 1;
4520  }
4521
4522  // Scaled single-precision to 64-bit
4523  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4524                              fixedpoint_f32_i64, asm,
4525              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4526                                          fixedpoint_f32_i64:$scale)))]> {
4527    let Inst{31} = 1; // 64-bit GPR flag
4528  }
4529
4530  // Scaled double-precision to 32-bit
4531  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4532                              fixedpoint_f64_i32, asm,
4533              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4534                                          fixedpoint_f64_i32:$scale)))]> {
4535    let Inst{31} = 0; // 32-bit GPR flag
4536    let scale{5} = 1;
4537  }
4538
4539  // Scaled double-precision to 64-bit
4540  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4541                              fixedpoint_f64_i64, asm,
4542              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4543                                          fixedpoint_f64_i64:$scale)))]> {
4544    let Inst{31} = 1; // 64-bit GPR flag
4545  }
4546}
4547
4548//---
4549// Integer to floating point conversion
4550//---
4551
4552let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4553class BaseIntegerToFP<bit isUnsigned,
4554                      RegisterClass srcType, RegisterClass dstType,
4555                      Operand immType, string asm, list<dag> pattern>
4556    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4557         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4558      Sched<[WriteFCvt]> {
4559  bits<5> Rd;
4560  bits<5> Rn;
4561  bits<6> scale;
4562  let Inst{30-24} = 0b0011110;
4563  let Inst{21-17} = 0b00001;
4564  let Inst{16}    = isUnsigned;
4565  let Inst{15-10} = scale;
4566  let Inst{9-5}   = Rn;
4567  let Inst{4-0}   = Rd;
4568}
4569
4570class BaseIntegerToFPUnscaled<bit isUnsigned,
4571                      RegisterClass srcType, RegisterClass dstType,
4572                      ValueType dvt, string asm, SDNode node>
4573    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4574         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
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} = 0b10001;
4581  let Inst{16}    = isUnsigned;
4582  let Inst{15-10} = 0b000000;
4583  let Inst{9-5}   = Rn;
4584  let Inst{4-0}   = Rd;
4585}
4586
4587multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4588  // Unscaled
4589  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4590    let Inst{31} = 0; // 32-bit GPR flag
4591    let Inst{23-22} = 0b11; // 16-bit FPR flag
4592    let Predicates = [HasFullFP16];
4593  }
4594
4595  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4596    let Inst{31} = 0; // 32-bit GPR flag
4597    let Inst{23-22} = 0b00; // 32-bit FPR flag
4598  }
4599
4600  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4601    let Inst{31} = 0; // 32-bit GPR flag
4602    let Inst{23-22} = 0b01; // 64-bit FPR flag
4603  }
4604
4605  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4606    let Inst{31} = 1; // 64-bit GPR flag
4607    let Inst{23-22} = 0b11; // 16-bit FPR flag
4608    let Predicates = [HasFullFP16];
4609  }
4610
4611  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4612    let Inst{31} = 1; // 64-bit GPR flag
4613    let Inst{23-22} = 0b00; // 32-bit FPR flag
4614  }
4615
4616  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4617    let Inst{31} = 1; // 64-bit GPR flag
4618    let Inst{23-22} = 0b01; // 64-bit FPR flag
4619  }
4620
4621  // Scaled
4622  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4623                             [(set (f16 FPR16:$Rd),
4624                                   (fdiv (node GPR32:$Rn),
4625                                         fixedpoint_f16_i32:$scale))]> {
4626    let Inst{31} = 0; // 32-bit GPR flag
4627    let Inst{23-22} = 0b11; // 16-bit FPR flag
4628    let scale{5} = 1;
4629    let Predicates = [HasFullFP16];
4630  }
4631
4632  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4633                             [(set FPR32:$Rd,
4634                                   (fdiv (node GPR32:$Rn),
4635                                         fixedpoint_f32_i32:$scale))]> {
4636    let Inst{31} = 0; // 32-bit GPR flag
4637    let Inst{23-22} = 0b00; // 32-bit FPR flag
4638    let scale{5} = 1;
4639  }
4640
4641  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4642                             [(set FPR64:$Rd,
4643                                   (fdiv (node GPR32:$Rn),
4644                                         fixedpoint_f64_i32:$scale))]> {
4645    let Inst{31} = 0; // 32-bit GPR flag
4646    let Inst{23-22} = 0b01; // 64-bit FPR flag
4647    let scale{5} = 1;
4648  }
4649
4650  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4651                             [(set (f16 FPR16:$Rd),
4652                                   (fdiv (node GPR64:$Rn),
4653                                         fixedpoint_f16_i64:$scale))]> {
4654    let Inst{31} = 1; // 64-bit GPR flag
4655    let Inst{23-22} = 0b11; // 16-bit FPR flag
4656    let Predicates = [HasFullFP16];
4657  }
4658
4659  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4660                             [(set FPR32:$Rd,
4661                                   (fdiv (node GPR64:$Rn),
4662                                         fixedpoint_f32_i64:$scale))]> {
4663    let Inst{31} = 1; // 64-bit GPR flag
4664    let Inst{23-22} = 0b00; // 32-bit FPR flag
4665  }
4666
4667  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4668                             [(set FPR64:$Rd,
4669                                   (fdiv (node GPR64:$Rn),
4670                                         fixedpoint_f64_i64:$scale))]> {
4671    let Inst{31} = 1; // 64-bit GPR flag
4672    let Inst{23-22} = 0b01; // 64-bit FPR flag
4673  }
4674}
4675
4676//---
4677// Unscaled integer <-> floating point conversion (i.e. FMOV)
4678//---
4679
4680let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4681class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4682                      RegisterClass srcType, RegisterClass dstType,
4683                      string asm>
4684    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4685        // We use COPY_TO_REGCLASS for these bitconvert operations.
4686        // copyPhysReg() expands the resultant COPY instructions after
4687        // regalloc is done. This gives greater freedom for the allocator
4688        // and related passes (coalescing, copy propagation, et. al.) to
4689        // be more effective.
4690        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4691      Sched<[WriteFCopy]> {
4692  bits<5> Rd;
4693  bits<5> Rn;
4694  let Inst{30-24} = 0b0011110;
4695  let Inst{21}    = 1;
4696  let Inst{20-19} = rmode;
4697  let Inst{18-16} = opcode;
4698  let Inst{15-10} = 0b000000;
4699  let Inst{9-5}   = Rn;
4700  let Inst{4-0}   = Rd;
4701}
4702
4703let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4704class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4705                     RegisterClass srcType, RegisterOperand dstType, string asm,
4706                     string kind>
4707    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4708        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4709      Sched<[WriteFCopy]> {
4710  bits<5> Rd;
4711  bits<5> Rn;
4712  let Inst{30-23} = 0b00111101;
4713  let Inst{21}    = 1;
4714  let Inst{20-19} = rmode;
4715  let Inst{18-16} = opcode;
4716  let Inst{15-10} = 0b000000;
4717  let Inst{9-5}   = Rn;
4718  let Inst{4-0}   = Rd;
4719
4720  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4721}
4722
4723let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4724class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4725                     RegisterOperand srcType, RegisterClass dstType, string asm,
4726                     string kind>
4727    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4728        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4729      Sched<[WriteFCopy]> {
4730  bits<5> Rd;
4731  bits<5> Rn;
4732  let Inst{30-23} = 0b00111101;
4733  let Inst{21}    = 1;
4734  let Inst{20-19} = rmode;
4735  let Inst{18-16} = opcode;
4736  let Inst{15-10} = 0b000000;
4737  let Inst{9-5}   = Rn;
4738  let Inst{4-0}   = Rd;
4739
4740  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4741}
4742
4743
4744multiclass UnscaledConversion<string asm> {
4745  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4746    let Inst{31} = 0; // 32-bit GPR flag
4747    let Inst{23-22} = 0b11; // 16-bit FPR flag
4748    let Predicates = [HasFullFP16];
4749  }
4750
4751  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4752    let Inst{31} = 1; // 64-bit GPR flag
4753    let Inst{23-22} = 0b11; // 16-bit FPR flag
4754    let Predicates = [HasFullFP16];
4755  }
4756
4757  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4758    let Inst{31} = 0; // 32-bit GPR flag
4759    let Inst{23-22} = 0b00; // 32-bit FPR flag
4760  }
4761
4762  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4763    let Inst{31} = 1; // 64-bit GPR flag
4764    let Inst{23-22} = 0b01; // 64-bit FPR flag
4765  }
4766
4767  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4768    let Inst{31} = 0; // 32-bit GPR flag
4769    let Inst{23-22} = 0b11; // 16-bit FPR flag
4770    let Predicates = [HasFullFP16];
4771  }
4772
4773  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4774    let Inst{31} = 1; // 64-bit GPR flag
4775    let Inst{23-22} = 0b11; // 16-bit FPR flag
4776    let Predicates = [HasFullFP16];
4777  }
4778
4779  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4780    let Inst{31} = 0; // 32-bit GPR flag
4781    let Inst{23-22} = 0b00; // 32-bit FPR flag
4782  }
4783
4784  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4785    let Inst{31} = 1; // 64-bit GPR flag
4786    let Inst{23-22} = 0b01; // 64-bit FPR flag
4787  }
4788
4789  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4790                                             asm, ".d"> {
4791    let Inst{31} = 1;
4792    let Inst{22} = 0;
4793  }
4794
4795  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4796                                               asm, ".d"> {
4797    let Inst{31} = 1;
4798    let Inst{22} = 0;
4799  }
4800}
4801
4802//---
4803// Floating point conversion
4804//---
4805
4806class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4807                       RegisterClass srcType, string asm, list<dag> pattern>
4808    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4809      Sched<[WriteFCvt]> {
4810  bits<5> Rd;
4811  bits<5> Rn;
4812  let Inst{31-24} = 0b00011110;
4813  let Inst{23-22} = type;
4814  let Inst{21-17} = 0b10001;
4815  let Inst{16-15} = opcode;
4816  let Inst{14-10} = 0b10000;
4817  let Inst{9-5}   = Rn;
4818  let Inst{4-0}   = Rd;
4819}
4820
4821multiclass FPConversion<string asm> {
4822  // Double-precision to Half-precision
4823  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4824                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4825
4826  // Double-precision to Single-precision
4827  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4828                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4829
4830  // Half-precision to Double-precision
4831  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4832                             [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4833
4834  // Half-precision to Single-precision
4835  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4836                             [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4837
4838  // Single-precision to Double-precision
4839  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4840                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4841
4842  // Single-precision to Half-precision
4843  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4844                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4845}
4846
4847//---
4848// Single operand floating point data processing
4849//---
4850
4851let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4852class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4853                              ValueType vt, string asm, SDPatternOperator node>
4854    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4855         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4856      Sched<[WriteF]> {
4857  bits<5> Rd;
4858  bits<5> Rn;
4859  let Inst{31-24} = 0b00011110;
4860  let Inst{21}    = 0b1;
4861  let Inst{20-15} = opcode;
4862  let Inst{14-10} = 0b10000;
4863  let Inst{9-5}   = Rn;
4864  let Inst{4-0}   = Rd;
4865}
4866
4867multiclass SingleOperandFPData<bits<4> opcode, string asm,
4868                               SDPatternOperator node = null_frag> {
4869
4870  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4871    let Inst{23-22} = 0b11; // 16-bit size flag
4872    let Predicates = [HasFullFP16];
4873  }
4874
4875  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4876    let Inst{23-22} = 0b00; // 32-bit size flag
4877  }
4878
4879  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4880    let Inst{23-22} = 0b01; // 64-bit size flag
4881  }
4882}
4883
4884multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4885                  SDPatternOperator node = null_frag>{
4886
4887  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4888    let Inst{23-22} = 0b00; // 32-bit registers
4889  }
4890
4891  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4892    let Inst{23-22} = 0b01; // 64-bit registers
4893  }
4894}
4895
4896// FRInt[32|64][Z|N] instructions
4897multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4898      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4899
4900//---
4901// Two operand floating point data processing
4902//---
4903
4904let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4905class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4906                           string asm, list<dag> pat>
4907    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4908         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4909      Sched<[WriteF]> {
4910  bits<5> Rd;
4911  bits<5> Rn;
4912  bits<5> Rm;
4913  let Inst{31-24} = 0b00011110;
4914  let Inst{21}    = 1;
4915  let Inst{20-16} = Rm;
4916  let Inst{15-12} = opcode;
4917  let Inst{11-10} = 0b10;
4918  let Inst{9-5}   = Rn;
4919  let Inst{4-0}   = Rd;
4920}
4921
4922multiclass TwoOperandFPData<bits<4> opcode, string asm,
4923                            SDPatternOperator node = null_frag> {
4924  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4925                         [(set (f16 FPR16:$Rd),
4926                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4927    let Inst{23-22} = 0b11; // 16-bit size flag
4928    let Predicates = [HasFullFP16];
4929  }
4930
4931  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4932                         [(set (f32 FPR32:$Rd),
4933                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4934    let Inst{23-22} = 0b00; // 32-bit size flag
4935  }
4936
4937  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4938                         [(set (f64 FPR64:$Rd),
4939                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4940    let Inst{23-22} = 0b01; // 64-bit size flag
4941  }
4942}
4943
4944multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4945  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4946                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
4947    let Inst{23-22} = 0b11; // 16-bit size flag
4948    let Predicates = [HasFullFP16];
4949  }
4950
4951  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4952                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4953    let Inst{23-22} = 0b00; // 32-bit size flag
4954  }
4955
4956  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4957                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4958    let Inst{23-22} = 0b01; // 64-bit size flag
4959  }
4960}
4961
4962
4963//---
4964// Three operand floating point data processing
4965//---
4966
4967class BaseThreeOperandFPData<bit isNegated, bit isSub,
4968                             RegisterClass regtype, string asm, list<dag> pat>
4969    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4970         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4971      Sched<[WriteFMul]> {
4972  bits<5> Rd;
4973  bits<5> Rn;
4974  bits<5> Rm;
4975  bits<5> Ra;
4976  let Inst{31-24} = 0b00011111;
4977  let Inst{21}    = isNegated;
4978  let Inst{20-16} = Rm;
4979  let Inst{15}    = isSub;
4980  let Inst{14-10} = Ra;
4981  let Inst{9-5}   = Rn;
4982  let Inst{4-0}   = Rd;
4983}
4984
4985multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4986                              SDPatternOperator node> {
4987  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4988            [(set (f16 FPR16:$Rd),
4989                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4990    let Inst{23-22} = 0b11; // 16-bit size flag
4991    let Predicates = [HasFullFP16];
4992  }
4993
4994  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4995            [(set FPR32:$Rd,
4996                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4997    let Inst{23-22} = 0b00; // 32-bit size flag
4998  }
4999
5000  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5001            [(set FPR64:$Rd,
5002                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5003    let Inst{23-22} = 0b01; // 64-bit size flag
5004  }
5005}
5006
5007//---
5008// Floating point data comparisons
5009//---
5010
5011let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5012class BaseOneOperandFPComparison<bit signalAllNans,
5013                                 RegisterClass regtype, string asm,
5014                                 list<dag> pat>
5015    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5016      Sched<[WriteFCmp]> {
5017  bits<5> Rn;
5018  let Inst{31-24} = 0b00011110;
5019  let Inst{21}    = 1;
5020
5021  let Inst{15-10} = 0b001000;
5022  let Inst{9-5}   = Rn;
5023  let Inst{4}     = signalAllNans;
5024  let Inst{3-0}   = 0b1000;
5025
5026  // Rm should be 0b00000 canonically, but we need to accept any value.
5027  let PostEncoderMethod = "fixOneOperandFPComparison";
5028}
5029
5030let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5031class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5032                                string asm, list<dag> pat>
5033    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5034      Sched<[WriteFCmp]> {
5035  bits<5> Rm;
5036  bits<5> Rn;
5037  let Inst{31-24} = 0b00011110;
5038  let Inst{21}    = 1;
5039  let Inst{20-16} = Rm;
5040  let Inst{15-10} = 0b001000;
5041  let Inst{9-5}   = Rn;
5042  let Inst{4}     = signalAllNans;
5043  let Inst{3-0}   = 0b0000;
5044}
5045
5046multiclass FPComparison<bit signalAllNans, string asm,
5047                        SDPatternOperator OpNode = null_frag> {
5048  let Defs = [NZCV] in {
5049  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5050      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5051    let Inst{23-22} = 0b11;
5052    let Predicates = [HasFullFP16];
5053  }
5054
5055  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5056      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5057    let Inst{23-22} = 0b11;
5058    let Predicates = [HasFullFP16];
5059  }
5060
5061  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5062      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5063    let Inst{23-22} = 0b00;
5064  }
5065
5066  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5067      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5068    let Inst{23-22} = 0b00;
5069  }
5070
5071  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5072      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5073    let Inst{23-22} = 0b01;
5074  }
5075
5076  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5077      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5078    let Inst{23-22} = 0b01;
5079  }
5080  } // Defs = [NZCV]
5081}
5082
5083//---
5084// Floating point conditional comparisons
5085//---
5086
5087let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5088class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5089                           string mnemonic, list<dag> pat>
5090    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5091         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5092      Sched<[WriteFCmp]> {
5093  let Uses = [NZCV];
5094  let Defs = [NZCV];
5095
5096  bits<5> Rn;
5097  bits<5> Rm;
5098  bits<4> nzcv;
5099  bits<4> cond;
5100
5101  let Inst{31-24} = 0b00011110;
5102  let Inst{21}    = 1;
5103  let Inst{20-16} = Rm;
5104  let Inst{15-12} = cond;
5105  let Inst{11-10} = 0b01;
5106  let Inst{9-5}   = Rn;
5107  let Inst{4}     = signalAllNans;
5108  let Inst{3-0}   = nzcv;
5109}
5110
5111multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5112                            SDPatternOperator OpNode = null_frag> {
5113  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5114      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5115                          (i32 imm:$cond), NZCV))]> {
5116    let Inst{23-22} = 0b11;
5117    let Predicates = [HasFullFP16];
5118  }
5119
5120  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5121      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5122                          (i32 imm:$cond), NZCV))]> {
5123    let Inst{23-22} = 0b00;
5124  }
5125
5126  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5127      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5128                          (i32 imm:$cond), NZCV))]> {
5129    let Inst{23-22} = 0b01;
5130  }
5131}
5132
5133//---
5134// Floating point conditional select
5135//---
5136
5137class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5138    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5139         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5140         [(set regtype:$Rd,
5141               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5142                          (i32 imm:$cond), NZCV))]>,
5143      Sched<[WriteF]> {
5144  bits<5> Rd;
5145  bits<5> Rn;
5146  bits<5> Rm;
5147  bits<4> cond;
5148
5149  let Inst{31-24} = 0b00011110;
5150  let Inst{21}    = 1;
5151  let Inst{20-16} = Rm;
5152  let Inst{15-12} = cond;
5153  let Inst{11-10} = 0b11;
5154  let Inst{9-5}   = Rn;
5155  let Inst{4-0}   = Rd;
5156}
5157
5158multiclass FPCondSelect<string asm> {
5159  let Uses = [NZCV] in {
5160  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5161    let Inst{23-22} = 0b11;
5162    let Predicates = [HasFullFP16];
5163  }
5164
5165  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5166    let Inst{23-22} = 0b00;
5167  }
5168
5169  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5170    let Inst{23-22} = 0b01;
5171  }
5172  } // Uses = [NZCV]
5173}
5174
5175//---
5176// Floating move immediate
5177//---
5178
5179class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5180  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5181      [(set regtype:$Rd, fpimmtype:$imm)]>,
5182    Sched<[WriteFImm]> {
5183  bits<5> Rd;
5184  bits<8> imm;
5185  let Inst{31-24} = 0b00011110;
5186  let Inst{21}    = 1;
5187  let Inst{20-13} = imm;
5188  let Inst{12-5}  = 0b10000000;
5189  let Inst{4-0}   = Rd;
5190}
5191
5192multiclass FPMoveImmediate<string asm> {
5193  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5194    let Inst{23-22} = 0b11;
5195    let Predicates = [HasFullFP16];
5196  }
5197
5198  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5199    let Inst{23-22} = 0b00;
5200  }
5201
5202  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5203    let Inst{23-22} = 0b01;
5204  }
5205}
5206} // end of 'let Predicates = [HasFPARMv8]'
5207
5208//----------------------------------------------------------------------------
5209// AdvSIMD
5210//----------------------------------------------------------------------------
5211
5212let Predicates = [HasNEON] in {
5213
5214//----------------------------------------------------------------------------
5215// AdvSIMD three register vector instructions
5216//----------------------------------------------------------------------------
5217
5218let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5219class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5220                        RegisterOperand regtype, string asm, string kind,
5221                        list<dag> pattern>
5222  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5223      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5224      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5225    Sched<[WriteV]> {
5226  bits<5> Rd;
5227  bits<5> Rn;
5228  bits<5> Rm;
5229  let Inst{31}    = 0;
5230  let Inst{30}    = Q;
5231  let Inst{29}    = U;
5232  let Inst{28-24} = 0b01110;
5233  let Inst{23-21} = size;
5234  let Inst{20-16} = Rm;
5235  let Inst{15-11} = opcode;
5236  let Inst{10}    = 1;
5237  let Inst{9-5}   = Rn;
5238  let Inst{4-0}   = Rd;
5239}
5240
5241let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5242class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5243                        RegisterOperand regtype, string asm, string kind,
5244                        list<dag> pattern>
5245  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5246      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5247      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5248    Sched<[WriteV]> {
5249  bits<5> Rd;
5250  bits<5> Rn;
5251  bits<5> Rm;
5252  let Inst{31}    = 0;
5253  let Inst{30}    = Q;
5254  let Inst{29}    = U;
5255  let Inst{28-24} = 0b01110;
5256  let Inst{23-21} = size;
5257  let Inst{20-16} = Rm;
5258  let Inst{15-11} = opcode;
5259  let Inst{10}    = 1;
5260  let Inst{9-5}   = Rn;
5261  let Inst{4-0}   = Rd;
5262}
5263
5264let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5265class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5266  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5267    Sched<[WriteV]>;
5268
5269multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5270  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5271             [(set (v8i8 V64:$dst),
5272                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5273  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5274             [(set (v16i8 V128:$dst),
5275                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5276                           (v16i8 V128:$Rm)))]>;
5277
5278  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5279                           (v4i16 V64:$RHS))),
5280          (!cast<Instruction>(NAME#"v8i8")
5281            V64:$LHS, V64:$MHS, V64:$RHS)>;
5282  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5283                           (v2i32 V64:$RHS))),
5284          (!cast<Instruction>(NAME#"v8i8")
5285            V64:$LHS, V64:$MHS, V64:$RHS)>;
5286  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5287                           (v1i64 V64:$RHS))),
5288          (!cast<Instruction>(NAME#"v8i8")
5289            V64:$LHS, V64:$MHS, V64:$RHS)>;
5290
5291  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5292                           (v8i16 V128:$RHS))),
5293      (!cast<Instruction>(NAME#"v16i8")
5294        V128:$LHS, V128:$MHS, V128:$RHS)>;
5295  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5296                           (v4i32 V128:$RHS))),
5297      (!cast<Instruction>(NAME#"v16i8")
5298        V128:$LHS, V128:$MHS, V128:$RHS)>;
5299  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5300                           (v2i64 V128:$RHS))),
5301      (!cast<Instruction>(NAME#"v16i8")
5302        V128:$LHS, V128:$MHS, V128:$RHS)>;
5303}
5304
5305// All operand sizes distinguished in the encoding.
5306multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5307                               SDPatternOperator OpNode> {
5308  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5309                                      asm, ".8b",
5310         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5311  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5312                                      asm, ".16b",
5313         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5314  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5315                                      asm, ".4h",
5316         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5317  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5318                                      asm, ".8h",
5319         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5320  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5321                                      asm, ".2s",
5322         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5323  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5324                                      asm, ".4s",
5325         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5326  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5327                                      asm, ".2d",
5328         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5329}
5330
5331multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5332  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5333          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5334  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5335          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5336  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5337          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5338
5339  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5340          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5341  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5342          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5343  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5344          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5345  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5346          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5347}
5348
5349// As above, but D sized elements unsupported.
5350multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5351                                  SDPatternOperator OpNode> {
5352  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5353                                      asm, ".8b",
5354        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5355  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5356                                      asm, ".16b",
5357        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5358  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5359                                      asm, ".4h",
5360        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5361  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5362                                      asm, ".8h",
5363        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5364  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5365                                      asm, ".2s",
5366        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5367  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5368                                      asm, ".4s",
5369        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5370}
5371
5372multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5373                                  SDPatternOperator OpNode> {
5374  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5375                                      asm, ".8b",
5376      [(set (v8i8 V64:$dst),
5377            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5378  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5379                                      asm, ".16b",
5380      [(set (v16i8 V128:$dst),
5381            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5382  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5383                                      asm, ".4h",
5384      [(set (v4i16 V64:$dst),
5385            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5386  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5387                                      asm, ".8h",
5388      [(set (v8i16 V128:$dst),
5389            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5390  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5391                                      asm, ".2s",
5392      [(set (v2i32 V64:$dst),
5393            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5394  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5395                                      asm, ".4s",
5396      [(set (v4i32 V128:$dst),
5397            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5398}
5399
5400// As above, but only B sized elements supported.
5401multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5402                                SDPatternOperator OpNode> {
5403  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5404                                      asm, ".8b",
5405    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5406  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5407                                      asm, ".16b",
5408    [(set (v16i8 V128:$Rd),
5409          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5410}
5411
5412// As above, but only floating point elements supported.
5413multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5414                                 string asm, SDPatternOperator OpNode> {
5415  let Predicates = [HasNEON, HasFullFP16] in {
5416  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5417                                      asm, ".4h",
5418        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5419  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5420                                      asm, ".8h",
5421        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5422  } // Predicates = [HasNEON, HasFullFP16]
5423  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5424                                      asm, ".2s",
5425        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5426  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5427                                      asm, ".4s",
5428        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5429  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5430                                      asm, ".2d",
5431        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5432}
5433
5434multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5435                                    string asm,
5436                                    SDPatternOperator OpNode> {
5437  let Predicates = [HasNEON, HasFullFP16] in {
5438  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5439                                      asm, ".4h",
5440        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5441  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5442                                      asm, ".8h",
5443        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5444  } // Predicates = [HasNEON, HasFullFP16]
5445  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5446                                      asm, ".2s",
5447        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5448  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5449                                      asm, ".4s",
5450        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5451  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5452                                      asm, ".2d",
5453        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5454}
5455
5456multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5457                                 string asm, SDPatternOperator OpNode> {
5458  let Predicates = [HasNEON, HasFullFP16] in {
5459  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5460                                      asm, ".4h",
5461     [(set (v4f16 V64:$dst),
5462           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5463  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5464                                      asm, ".8h",
5465     [(set (v8f16 V128:$dst),
5466           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5467  } // Predicates = [HasNEON, HasFullFP16]
5468  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5469                                      asm, ".2s",
5470     [(set (v2f32 V64:$dst),
5471           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5472  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5473                                      asm, ".4s",
5474     [(set (v4f32 V128:$dst),
5475           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5476  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5477                                      asm, ".2d",
5478     [(set (v2f64 V128:$dst),
5479           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5480}
5481
5482// As above, but D and B sized elements unsupported.
5483multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5484                                SDPatternOperator OpNode> {
5485  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5486                                      asm, ".4h",
5487        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5488  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5489                                      asm, ".8h",
5490        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5491  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5492                                      asm, ".2s",
5493        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5494  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5495                                      asm, ".4s",
5496        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5497}
5498
5499// Logical three vector ops share opcode bits, and only use B sized elements.
5500multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5501                                  SDPatternOperator OpNode = null_frag> {
5502  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5503                                     asm, ".8b",
5504                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5505  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5506                                     asm, ".16b",
5507                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5508
5509  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5510          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5511  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5512          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5513  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5514          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5515
5516  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5517      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5518  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5519      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5520  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5521      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5522}
5523
5524multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5525                                  string asm, SDPatternOperator OpNode = null_frag> {
5526  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5527                                     asm, ".8b",
5528             [(set (v8i8 V64:$dst),
5529                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5530  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5531                                     asm, ".16b",
5532             [(set (v16i8 V128:$dst),
5533                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5534                           (v16i8 V128:$Rm)))]>;
5535
5536  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5537                           (v4i16 V64:$RHS))),
5538          (!cast<Instruction>(NAME#"v8i8")
5539            V64:$LHS, V64:$MHS, V64:$RHS)>;
5540  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5541                           (v2i32 V64:$RHS))),
5542          (!cast<Instruction>(NAME#"v8i8")
5543            V64:$LHS, V64:$MHS, V64:$RHS)>;
5544  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5545                           (v1i64 V64:$RHS))),
5546          (!cast<Instruction>(NAME#"v8i8")
5547            V64:$LHS, V64:$MHS, V64:$RHS)>;
5548
5549  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5550                           (v8i16 V128:$RHS))),
5551      (!cast<Instruction>(NAME#"v16i8")
5552        V128:$LHS, V128:$MHS, V128:$RHS)>;
5553  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5554                           (v4i32 V128:$RHS))),
5555      (!cast<Instruction>(NAME#"v16i8")
5556        V128:$LHS, V128:$MHS, V128:$RHS)>;
5557  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5558                           (v2i64 V128:$RHS))),
5559      (!cast<Instruction>(NAME#"v16i8")
5560        V128:$LHS, V128:$MHS, V128:$RHS)>;
5561}
5562
5563// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5564// bytes from S-sized elements.
5565class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5566                                 string kind2, RegisterOperand RegType,
5567                                 ValueType AccumType, ValueType InputType,
5568                                 SDPatternOperator OpNode> :
5569        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5570        [(set (AccumType RegType:$dst),
5571              (OpNode (AccumType RegType:$Rd),
5572                      (InputType RegType:$Rn),
5573                      (InputType RegType:$Rm)))]> {
5574  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5575}
5576
5577multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5578  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5579                                         v2i32, v8i8, OpNode>;
5580  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5581                                         v4i32, v16i8, OpNode>;
5582}
5583
5584// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5585// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5586// 8H to 4S, when Q=1).
5587class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5588                                 string kind2, RegisterOperand RegType,
5589                                 ValueType AccumType, ValueType InputType,
5590                                 SDPatternOperator OpNode> :
5591        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5592		[(set (AccumType RegType:$dst),
5593              (OpNode (AccumType RegType:$Rd),
5594                      (InputType RegType:$Rn),
5595                      (InputType RegType:$Rm)))]> {
5596  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5597  let Inst{13} = b13;
5598}
5599
5600multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5601                                  SDPatternOperator OpNode> {
5602  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5603                                         v2f32, v4f16, OpNode>;
5604  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5605                                         v4f32, v8f16, OpNode>;
5606}
5607
5608
5609//----------------------------------------------------------------------------
5610// AdvSIMD two register vector instructions.
5611//----------------------------------------------------------------------------
5612
5613let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5614class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5615                            bits<2> size2, RegisterOperand regtype, string asm,
5616                            string dstkind, string srckind, list<dag> pattern>
5617  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5618      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5619      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5620    Sched<[WriteV]> {
5621  bits<5> Rd;
5622  bits<5> Rn;
5623  let Inst{31}    = 0;
5624  let Inst{30}    = Q;
5625  let Inst{29}    = U;
5626  let Inst{28-24} = 0b01110;
5627  let Inst{23-22} = size;
5628  let Inst{21} = 0b1;
5629  let Inst{20-19} = size2;
5630  let Inst{18-17} = 0b00;
5631  let Inst{16-12} = opcode;
5632  let Inst{11-10} = 0b10;
5633  let Inst{9-5}   = Rn;
5634  let Inst{4-0}   = Rd;
5635}
5636
5637let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5638class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5639                                bits<2> size2, RegisterOperand regtype,
5640                                string asm, string dstkind, string srckind,
5641                                list<dag> pattern>
5642  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5643      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5644      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5645    Sched<[WriteV]> {
5646  bits<5> Rd;
5647  bits<5> Rn;
5648  let Inst{31}    = 0;
5649  let Inst{30}    = Q;
5650  let Inst{29}    = U;
5651  let Inst{28-24} = 0b01110;
5652  let Inst{23-22} = size;
5653  let Inst{21} = 0b1;
5654  let Inst{20-19} = size2;
5655  let Inst{18-17} = 0b00;
5656  let Inst{16-12} = opcode;
5657  let Inst{11-10} = 0b10;
5658  let Inst{9-5}   = Rn;
5659  let Inst{4-0}   = Rd;
5660}
5661
5662// Supports B, H, and S element sizes.
5663multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5664                            SDPatternOperator OpNode> {
5665  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5666                                      asm, ".8b", ".8b",
5667                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5668  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5669                                      asm, ".16b", ".16b",
5670                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5671  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5672                                      asm, ".4h", ".4h",
5673                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5674  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5675                                      asm, ".8h", ".8h",
5676                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5677  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5678                                      asm, ".2s", ".2s",
5679                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5680  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5681                                      asm, ".4s", ".4s",
5682                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5683}
5684
5685class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5686                            RegisterOperand regtype, string asm, string dstkind,
5687                            string srckind, string amount>
5688  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5689      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5690      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5691    Sched<[WriteV]> {
5692  bits<5> Rd;
5693  bits<5> Rn;
5694  let Inst{31}    = 0;
5695  let Inst{30}    = Q;
5696  let Inst{29-24} = 0b101110;
5697  let Inst{23-22} = size;
5698  let Inst{21-10} = 0b100001001110;
5699  let Inst{9-5}   = Rn;
5700  let Inst{4-0}   = Rd;
5701}
5702
5703multiclass SIMDVectorLShiftLongBySizeBHS {
5704  let hasSideEffects = 0 in {
5705  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5706                                             "shll", ".8h",  ".8b", "8">;
5707  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5708                                             "shll2", ".8h", ".16b", "8">;
5709  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5710                                             "shll", ".4s",  ".4h", "16">;
5711  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5712                                             "shll2", ".4s", ".8h", "16">;
5713  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5714                                             "shll", ".2d",  ".2s", "32">;
5715  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5716                                             "shll2", ".2d", ".4s", "32">;
5717  }
5718}
5719
5720// Supports all element sizes.
5721multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5722                             SDPatternOperator OpNode> {
5723  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5724                                      asm, ".4h", ".8b",
5725               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5726  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5727                                      asm, ".8h", ".16b",
5728               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5729  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5730                                      asm, ".2s", ".4h",
5731               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5732  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5733                                      asm, ".4s", ".8h",
5734               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5735  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5736                                      asm, ".1d", ".2s",
5737               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5738  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5739                                      asm, ".2d", ".4s",
5740               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5741}
5742
5743multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5744                                 SDPatternOperator OpNode> {
5745  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5746                                          asm, ".4h", ".8b",
5747      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5748                                      (v8i8 V64:$Rn)))]>;
5749  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5750                                          asm, ".8h", ".16b",
5751      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5752                                      (v16i8 V128:$Rn)))]>;
5753  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5754                                          asm, ".2s", ".4h",
5755      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5756                                      (v4i16 V64:$Rn)))]>;
5757  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5758                                          asm, ".4s", ".8h",
5759      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5760                                      (v8i16 V128:$Rn)))]>;
5761  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5762                                          asm, ".1d", ".2s",
5763      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5764                                      (v2i32 V64:$Rn)))]>;
5765  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5766                                          asm, ".2d", ".4s",
5767      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5768                                      (v4i32 V128:$Rn)))]>;
5769}
5770
5771// Supports all element sizes, except 1xD.
5772multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5773                                  SDPatternOperator OpNode> {
5774  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5775                                    asm, ".8b", ".8b",
5776    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5777  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5778                                    asm, ".16b", ".16b",
5779    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5780  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5781                                    asm, ".4h", ".4h",
5782    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5783  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5784                                    asm, ".8h", ".8h",
5785    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5786  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5787                                    asm, ".2s", ".2s",
5788    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5789  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5790                                    asm, ".4s", ".4s",
5791    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5792  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5793                                    asm, ".2d", ".2d",
5794    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5795}
5796
5797multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5798                             SDPatternOperator OpNode = null_frag> {
5799  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5800                                asm, ".8b", ".8b",
5801    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5802  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5803                                asm, ".16b", ".16b",
5804    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5805  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5806                                asm, ".4h", ".4h",
5807    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5808  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5809                                asm, ".8h", ".8h",
5810    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5811  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5812                                asm, ".2s", ".2s",
5813    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5814  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5815                                asm, ".4s", ".4s",
5816    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5817  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5818                                asm, ".2d", ".2d",
5819    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5820}
5821
5822
5823// Supports only B element sizes.
5824multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5825                          SDPatternOperator OpNode> {
5826  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5827                                asm, ".8b", ".8b",
5828                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5829  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5830                                asm, ".16b", ".16b",
5831                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5832
5833}
5834
5835// Supports only B and H element sizes.
5836multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5837                                SDPatternOperator OpNode> {
5838  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5839                                asm, ".8b", ".8b",
5840                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5841  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5842                                asm, ".16b", ".16b",
5843                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5844  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5845                                asm, ".4h", ".4h",
5846                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5847  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5848                                asm, ".8h", ".8h",
5849                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5850}
5851
5852// Supports H, S and D element sizes, uses high bit of the size field
5853// as an extra opcode bit.
5854multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5855                           SDPatternOperator OpNode> {
5856  let Predicates = [HasNEON, HasFullFP16] in {
5857  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5858                                asm, ".4h", ".4h",
5859                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5860  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5861                                asm, ".8h", ".8h",
5862                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5863  } // Predicates = [HasNEON, HasFullFP16]
5864  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5865                                asm, ".2s", ".2s",
5866                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5867  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5868                                asm, ".4s", ".4s",
5869                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5870  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5871                                asm, ".2d", ".2d",
5872                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5873}
5874
5875// Supports only S and D element sizes
5876multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5877                           SDPatternOperator OpNode = null_frag> {
5878
5879  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5880                                asm, ".2s", ".2s",
5881                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5882  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5883                                asm, ".4s", ".4s",
5884                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5885  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5886                                asm, ".2d", ".2d",
5887                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5888}
5889
5890multiclass FRIntNNTVector<bit U, bit op, string asm,
5891                          SDPatternOperator OpNode = null_frag> :
5892           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5893
5894// Supports only S element size.
5895multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5896                           SDPatternOperator OpNode> {
5897  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5898                                asm, ".2s", ".2s",
5899                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5900  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5901                                asm, ".4s", ".4s",
5902                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5903}
5904
5905
5906multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5907                           SDPatternOperator OpNode> {
5908  let Predicates = [HasNEON, HasFullFP16] in {
5909  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5910                                asm, ".4h", ".4h",
5911                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5912  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5913                                asm, ".8h", ".8h",
5914                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5915  } // Predicates = [HasNEON, HasFullFP16]
5916  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5917                                asm, ".2s", ".2s",
5918                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5919  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5920                                asm, ".4s", ".4s",
5921                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5922  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5923                                asm, ".2d", ".2d",
5924                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5925}
5926
5927multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5928                           SDPatternOperator OpNode> {
5929  let Predicates = [HasNEON, HasFullFP16] in {
5930  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5931                                asm, ".4h", ".4h",
5932                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5933  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5934                                asm, ".8h", ".8h",
5935                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5936  } // Predicates = [HasNEON, HasFullFP16]
5937  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5938                                asm, ".2s", ".2s",
5939                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5940  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5941                                asm, ".4s", ".4s",
5942                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5943  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5944                                asm, ".2d", ".2d",
5945                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5946}
5947
5948
5949class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5950                           RegisterOperand inreg, RegisterOperand outreg,
5951                           string asm, string outkind, string inkind,
5952                           list<dag> pattern>
5953  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5954      "{\t$Rd" # outkind # ", $Rn" # inkind #
5955      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5956    Sched<[WriteV]> {
5957  bits<5> Rd;
5958  bits<5> Rn;
5959  let Inst{31}    = 0;
5960  let Inst{30}    = Q;
5961  let Inst{29}    = U;
5962  let Inst{28-24} = 0b01110;
5963  let Inst{23-22} = size;
5964  let Inst{21-17} = 0b10000;
5965  let Inst{16-12} = opcode;
5966  let Inst{11-10} = 0b10;
5967  let Inst{9-5}   = Rn;
5968  let Inst{4-0}   = Rd;
5969}
5970
5971class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5972                           RegisterOperand inreg, RegisterOperand outreg,
5973                           string asm, string outkind, string inkind,
5974                           list<dag> pattern>
5975  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5976      "{\t$Rd" # outkind # ", $Rn" # inkind #
5977      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5978    Sched<[WriteV]> {
5979  bits<5> Rd;
5980  bits<5> Rn;
5981  let Inst{31}    = 0;
5982  let Inst{30}    = Q;
5983  let Inst{29}    = U;
5984  let Inst{28-24} = 0b01110;
5985  let Inst{23-22} = size;
5986  let Inst{21-17} = 0b10000;
5987  let Inst{16-12} = opcode;
5988  let Inst{11-10} = 0b10;
5989  let Inst{9-5}   = Rn;
5990  let Inst{4-0}   = Rd;
5991}
5992
5993multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5994                              SDPatternOperator OpNode> {
5995  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5996                                      asm, ".8b", ".8h",
5997        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5998  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5999                                      asm#"2", ".16b", ".8h", []>;
6000  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6001                                      asm, ".4h", ".4s",
6002        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6003  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6004                                      asm#"2", ".8h", ".4s", []>;
6005  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6006                                      asm, ".2s", ".2d",
6007        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6008  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6009                                      asm#"2", ".4s", ".2d", []>;
6010
6011  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6012            (!cast<Instruction>(NAME # "v16i8")
6013                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6014  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6015            (!cast<Instruction>(NAME # "v8i16")
6016                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6017  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6018            (!cast<Instruction>(NAME # "v4i32")
6019                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6020}
6021
6022class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6023                           bits<5> opcode, RegisterOperand regtype, string asm,
6024                           string kind, string zero, ValueType dty,
6025                           ValueType sty, SDNode OpNode>
6026  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6027      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6028      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6029      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6030    Sched<[WriteV]> {
6031  bits<5> Rd;
6032  bits<5> Rn;
6033  let Inst{31}    = 0;
6034  let Inst{30}    = Q;
6035  let Inst{29}    = U;
6036  let Inst{28-24} = 0b01110;
6037  let Inst{23-22} = size;
6038  let Inst{21} = 0b1;
6039  let Inst{20-19} = size2;
6040  let Inst{18-17} = 0b00;
6041  let Inst{16-12} = opcode;
6042  let Inst{11-10} = 0b10;
6043  let Inst{9-5}   = Rn;
6044  let Inst{4-0}   = Rd;
6045}
6046
6047// Comparisons support all element sizes, except 1xD.
6048multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6049                            SDNode OpNode> {
6050  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6051                                     asm, ".8b", "0",
6052                                     v8i8, v8i8, OpNode>;
6053  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6054                                     asm, ".16b", "0",
6055                                     v16i8, v16i8, OpNode>;
6056  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6057                                     asm, ".4h", "0",
6058                                     v4i16, v4i16, OpNode>;
6059  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6060                                     asm, ".8h", "0",
6061                                     v8i16, v8i16, OpNode>;
6062  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6063                                     asm, ".2s", "0",
6064                                     v2i32, v2i32, OpNode>;
6065  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6066                                     asm, ".4s", "0",
6067                                     v4i32, v4i32, OpNode>;
6068  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6069                                     asm, ".2d", "0",
6070                                     v2i64, v2i64, OpNode>;
6071}
6072
6073// FP Comparisons support only S and D element sizes (and H for v8.2a).
6074multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6075                              string asm, SDNode OpNode> {
6076
6077  let Predicates = [HasNEON, HasFullFP16] in {
6078  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6079                                     asm, ".4h", "0.0",
6080                                     v4i16, v4f16, OpNode>;
6081  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6082                                     asm, ".8h", "0.0",
6083                                     v8i16, v8f16, OpNode>;
6084  } // Predicates = [HasNEON, HasFullFP16]
6085  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6086                                     asm, ".2s", "0.0",
6087                                     v2i32, v2f32, OpNode>;
6088  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6089                                     asm, ".4s", "0.0",
6090                                     v4i32, v4f32, OpNode>;
6091  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6092                                     asm, ".2d", "0.0",
6093                                     v2i64, v2f64, OpNode>;
6094
6095  let Predicates = [HasNEON, HasFullFP16] in {
6096  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6097                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6098  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6099                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6100  }
6101  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6102                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6103  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6104                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6105  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6106                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6107  let Predicates = [HasNEON, HasFullFP16] in {
6108  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6109                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6110  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6111                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6112  }
6113  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6114                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6115  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6116                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6117  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6118                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6119}
6120
6121let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6122class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6123                             RegisterOperand outtype, RegisterOperand intype,
6124                             string asm, string VdTy, string VnTy,
6125                             list<dag> pattern>
6126  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6127      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6128    Sched<[WriteV]> {
6129  bits<5> Rd;
6130  bits<5> Rn;
6131  let Inst{31}    = 0;
6132  let Inst{30}    = Q;
6133  let Inst{29}    = U;
6134  let Inst{28-24} = 0b01110;
6135  let Inst{23-22} = size;
6136  let Inst{21-17} = 0b10000;
6137  let Inst{16-12} = opcode;
6138  let Inst{11-10} = 0b10;
6139  let Inst{9-5}   = Rn;
6140  let Inst{4-0}   = Rd;
6141}
6142
6143class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6144                             RegisterOperand outtype, RegisterOperand intype,
6145                             string asm, string VdTy, string VnTy,
6146                             list<dag> pattern>
6147  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6148      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6149    Sched<[WriteV]> {
6150  bits<5> Rd;
6151  bits<5> Rn;
6152  let Inst{31}    = 0;
6153  let Inst{30}    = Q;
6154  let Inst{29}    = U;
6155  let Inst{28-24} = 0b01110;
6156  let Inst{23-22} = size;
6157  let Inst{21-17} = 0b10000;
6158  let Inst{16-12} = opcode;
6159  let Inst{11-10} = 0b10;
6160  let Inst{9-5}   = Rn;
6161  let Inst{4-0}   = Rd;
6162}
6163
6164multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6165  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6166                                    asm, ".4s", ".4h", []>;
6167  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6168                                    asm#"2", ".4s", ".8h", []>;
6169  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6170                                    asm, ".2d", ".2s", []>;
6171  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6172                                    asm#"2", ".2d", ".4s", []>;
6173}
6174
6175multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6176  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6177                                    asm, ".4h", ".4s", []>;
6178  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6179                                    asm#"2", ".8h", ".4s", []>;
6180  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6181                                    asm, ".2s", ".2d", []>;
6182  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6183                                    asm#"2", ".4s", ".2d", []>;
6184}
6185
6186multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6187                                     Intrinsic OpNode> {
6188  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6189                                     asm, ".2s", ".2d",
6190                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6191  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6192                                    asm#"2", ".4s", ".2d", []>;
6193
6194  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6195            (!cast<Instruction>(NAME # "v4f32")
6196                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6197}
6198
6199//----------------------------------------------------------------------------
6200// AdvSIMD three register different-size vector instructions.
6201//----------------------------------------------------------------------------
6202
6203let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6204class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6205                      RegisterOperand outtype, RegisterOperand intype1,
6206                      RegisterOperand intype2, string asm,
6207                      string outkind, string inkind1, string inkind2,
6208                      list<dag> pattern>
6209  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6210      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6211      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6212    Sched<[WriteV]> {
6213  bits<5> Rd;
6214  bits<5> Rn;
6215  bits<5> Rm;
6216  let Inst{31}    = 0;
6217  let Inst{30}    = size{0};
6218  let Inst{29}    = U;
6219  let Inst{28-24} = 0b01110;
6220  let Inst{23-22} = size{2-1};
6221  let Inst{21}    = 1;
6222  let Inst{20-16} = Rm;
6223  let Inst{15-12} = opcode;
6224  let Inst{11-10} = 0b00;
6225  let Inst{9-5}   = Rn;
6226  let Inst{4-0}   = Rd;
6227}
6228
6229let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6230class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6231                      RegisterOperand outtype, RegisterOperand intype1,
6232                      RegisterOperand intype2, string asm,
6233                      string outkind, string inkind1, string inkind2,
6234                      list<dag> pattern>
6235  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6236      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6237      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6238    Sched<[WriteV]> {
6239  bits<5> Rd;
6240  bits<5> Rn;
6241  bits<5> Rm;
6242  let Inst{31}    = 0;
6243  let Inst{30}    = size{0};
6244  let Inst{29}    = U;
6245  let Inst{28-24} = 0b01110;
6246  let Inst{23-22} = size{2-1};
6247  let Inst{21}    = 1;
6248  let Inst{20-16} = Rm;
6249  let Inst{15-12} = opcode;
6250  let Inst{11-10} = 0b00;
6251  let Inst{9-5}   = Rn;
6252  let Inst{4-0}   = Rd;
6253}
6254
6255// FIXME: TableGen doesn't know how to deal with expanded types that also
6256//        change the element count (in this case, placing the results in
6257//        the high elements of the result register rather than the low
6258//        elements). Until that's fixed, we can't code-gen those.
6259multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6260                                    Intrinsic IntOp> {
6261  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6262                                                  V64, V128, V128,
6263                                                  asm, ".8b", ".8h", ".8h",
6264     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6265  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6266                                                  V128, V128, V128,
6267                                                  asm#"2", ".16b", ".8h", ".8h",
6268     []>;
6269  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6270                                                  V64, V128, V128,
6271                                                  asm, ".4h", ".4s", ".4s",
6272     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6273  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6274                                                  V128, V128, V128,
6275                                                  asm#"2", ".8h", ".4s", ".4s",
6276     []>;
6277  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6278                                                  V64, V128, V128,
6279                                                  asm, ".2s", ".2d", ".2d",
6280     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6281  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6282                                                  V128, V128, V128,
6283                                                  asm#"2", ".4s", ".2d", ".2d",
6284     []>;
6285
6286
6287  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6288  // a version attached to an instruction.
6289  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6290                                                   (v8i16 V128:$Rm))),
6291            (!cast<Instruction>(NAME # "v8i16_v16i8")
6292                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6293                V128:$Rn, V128:$Rm)>;
6294  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6295                                                    (v4i32 V128:$Rm))),
6296            (!cast<Instruction>(NAME # "v4i32_v8i16")
6297                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6298                V128:$Rn, V128:$Rm)>;
6299  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6300                                                    (v2i64 V128:$Rm))),
6301            (!cast<Instruction>(NAME # "v2i64_v4i32")
6302                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6303                V128:$Rn, V128:$Rm)>;
6304}
6305
6306multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6307                                      Intrinsic IntOp> {
6308  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6309                                            V128, V64, V64,
6310                                            asm, ".8h", ".8b", ".8b",
6311      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6312  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6313                                            V128, V128, V128,
6314                                            asm#"2", ".8h", ".16b", ".16b", []>;
6315  let Predicates = [HasAES] in {
6316    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6317                                              V128, V64, V64,
6318                                              asm, ".1q", ".1d", ".1d", []>;
6319    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6320                                              V128, V128, V128,
6321                                              asm#"2", ".1q", ".2d", ".2d", []>;
6322  }
6323
6324  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6325                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6326      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6327}
6328
6329multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6330                                 SDPatternOperator OpNode> {
6331  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6332                                                  V128, V64, V64,
6333                                                  asm, ".4s", ".4h", ".4h",
6334      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6335  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6336                                                  V128, V128, V128,
6337                                                  asm#"2", ".4s", ".8h", ".8h",
6338      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6339                                      (extract_high_v8i16 V128:$Rm)))]>;
6340  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6341                                                  V128, V64, V64,
6342                                                  asm, ".2d", ".2s", ".2s",
6343      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6344  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6345                                                  V128, V128, V128,
6346                                                  asm#"2", ".2d", ".4s", ".4s",
6347      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6348                                      (extract_high_v4i32 V128:$Rm)))]>;
6349}
6350
6351multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6352                                  SDPatternOperator OpNode = null_frag> {
6353  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6354                                                  V128, V64, V64,
6355                                                  asm, ".8h", ".8b", ".8b",
6356      [(set (v8i16 V128:$Rd),
6357            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6358  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6359                                                 V128, V128, V128,
6360                                                 asm#"2", ".8h", ".16b", ".16b",
6361      [(set (v8i16 V128:$Rd),
6362            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6363                                (extract_high_v16i8 V128:$Rm)))))]>;
6364  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6365                                                  V128, V64, V64,
6366                                                  asm, ".4s", ".4h", ".4h",
6367      [(set (v4i32 V128:$Rd),
6368            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6369  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6370                                                  V128, V128, V128,
6371                                                  asm#"2", ".4s", ".8h", ".8h",
6372      [(set (v4i32 V128:$Rd),
6373            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6374                                  (extract_high_v8i16 V128:$Rm)))))]>;
6375  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6376                                                  V128, V64, V64,
6377                                                  asm, ".2d", ".2s", ".2s",
6378      [(set (v2i64 V128:$Rd),
6379            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6380  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6381                                                  V128, V128, V128,
6382                                                  asm#"2", ".2d", ".4s", ".4s",
6383      [(set (v2i64 V128:$Rd),
6384            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6385                                 (extract_high_v4i32 V128:$Rm)))))]>;
6386}
6387
6388multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6389                                          string asm,
6390                                          SDPatternOperator OpNode> {
6391  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6392                                                  V128, V64, V64,
6393                                                  asm, ".8h", ".8b", ".8b",
6394    [(set (v8i16 V128:$dst),
6395          (add (v8i16 V128:$Rd),
6396               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6397  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6398                                                 V128, V128, V128,
6399                                                 asm#"2", ".8h", ".16b", ".16b",
6400    [(set (v8i16 V128:$dst),
6401          (add (v8i16 V128:$Rd),
6402               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6403                                   (extract_high_v16i8 V128:$Rm))))))]>;
6404  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6405                                                  V128, V64, V64,
6406                                                  asm, ".4s", ".4h", ".4h",
6407    [(set (v4i32 V128:$dst),
6408          (add (v4i32 V128:$Rd),
6409               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6410  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6411                                                  V128, V128, V128,
6412                                                  asm#"2", ".4s", ".8h", ".8h",
6413    [(set (v4i32 V128:$dst),
6414          (add (v4i32 V128:$Rd),
6415               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6416                                    (extract_high_v8i16 V128:$Rm))))))]>;
6417  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6418                                                  V128, V64, V64,
6419                                                  asm, ".2d", ".2s", ".2s",
6420    [(set (v2i64 V128:$dst),
6421          (add (v2i64 V128:$Rd),
6422               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6423  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6424                                                  V128, V128, V128,
6425                                                  asm#"2", ".2d", ".4s", ".4s",
6426    [(set (v2i64 V128:$dst),
6427          (add (v2i64 V128:$Rd),
6428               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6429                                    (extract_high_v4i32 V128:$Rm))))))]>;
6430}
6431
6432multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6433                                  SDPatternOperator OpNode = null_frag> {
6434  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6435                                                  V128, V64, V64,
6436                                                  asm, ".8h", ".8b", ".8b",
6437      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6438  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6439                                                 V128, V128, V128,
6440                                                 asm#"2", ".8h", ".16b", ".16b",
6441      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6442                                      (extract_high_v16i8 V128:$Rm)))]>;
6443  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6444                                                  V128, V64, V64,
6445                                                  asm, ".4s", ".4h", ".4h",
6446      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6447  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6448                                                  V128, V128, V128,
6449                                                  asm#"2", ".4s", ".8h", ".8h",
6450      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6451                                      (extract_high_v8i16 V128:$Rm)))]>;
6452  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6453                                                  V128, V64, V64,
6454                                                  asm, ".2d", ".2s", ".2s",
6455      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6456  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6457                                                  V128, V128, V128,
6458                                                  asm#"2", ".2d", ".4s", ".4s",
6459      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6460                                      (extract_high_v4i32 V128:$Rm)))]>;
6461}
6462
6463multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6464                                      string asm,
6465                                      SDPatternOperator OpNode> {
6466  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6467                                                  V128, V64, V64,
6468                                                  asm, ".8h", ".8b", ".8b",
6469    [(set (v8i16 V128:$dst),
6470          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6471  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6472                                                 V128, V128, V128,
6473                                                 asm#"2", ".8h", ".16b", ".16b",
6474    [(set (v8i16 V128:$dst),
6475          (OpNode (v8i16 V128:$Rd),
6476                  (extract_high_v16i8 V128:$Rn),
6477                  (extract_high_v16i8 V128:$Rm)))]>;
6478  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6479                                                  V128, V64, V64,
6480                                                  asm, ".4s", ".4h", ".4h",
6481    [(set (v4i32 V128:$dst),
6482          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6483  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6484                                                  V128, V128, V128,
6485                                                  asm#"2", ".4s", ".8h", ".8h",
6486    [(set (v4i32 V128:$dst),
6487          (OpNode (v4i32 V128:$Rd),
6488                  (extract_high_v8i16 V128:$Rn),
6489                  (extract_high_v8i16 V128:$Rm)))]>;
6490  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6491                                                  V128, V64, V64,
6492                                                  asm, ".2d", ".2s", ".2s",
6493    [(set (v2i64 V128:$dst),
6494          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6495  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6496                                                  V128, V128, V128,
6497                                                  asm#"2", ".2d", ".4s", ".4s",
6498    [(set (v2i64 V128:$dst),
6499          (OpNode (v2i64 V128:$Rd),
6500                  (extract_high_v4i32 V128:$Rn),
6501                  (extract_high_v4i32 V128:$Rm)))]>;
6502}
6503
6504multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6505                                           SDPatternOperator Accum> {
6506  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6507                                                  V128, V64, V64,
6508                                                  asm, ".4s", ".4h", ".4h",
6509    [(set (v4i32 V128:$dst),
6510          (Accum (v4i32 V128:$Rd),
6511                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6512                                                (v4i16 V64:$Rm)))))]>;
6513  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6514                                                  V128, V128, V128,
6515                                                  asm#"2", ".4s", ".8h", ".8h",
6516    [(set (v4i32 V128:$dst),
6517          (Accum (v4i32 V128:$Rd),
6518                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6519                                            (extract_high_v8i16 V128:$Rm)))))]>;
6520  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6521                                                  V128, V64, V64,
6522                                                  asm, ".2d", ".2s", ".2s",
6523    [(set (v2i64 V128:$dst),
6524          (Accum (v2i64 V128:$Rd),
6525                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6526                                                (v2i32 V64:$Rm)))))]>;
6527  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6528                                                  V128, V128, V128,
6529                                                  asm#"2", ".2d", ".4s", ".4s",
6530    [(set (v2i64 V128:$dst),
6531          (Accum (v2i64 V128:$Rd),
6532                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6533                                            (extract_high_v4i32 V128:$Rm)))))]>;
6534}
6535
6536multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6537                                  SDPatternOperator OpNode> {
6538  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6539                                                  V128, V128, V64,
6540                                                  asm, ".8h", ".8h", ".8b",
6541       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6542  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6543                                                  V128, V128, V128,
6544                                                  asm#"2", ".8h", ".8h", ".16b",
6545       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6546                                       (extract_high_v16i8 V128:$Rm)))]>;
6547  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6548                                                  V128, V128, V64,
6549                                                  asm, ".4s", ".4s", ".4h",
6550       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6551  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6552                                                  V128, V128, V128,
6553                                                  asm#"2", ".4s", ".4s", ".8h",
6554       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6555                                       (extract_high_v8i16 V128:$Rm)))]>;
6556  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6557                                                  V128, V128, V64,
6558                                                  asm, ".2d", ".2d", ".2s",
6559       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6560  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6561                                                  V128, V128, V128,
6562                                                  asm#"2", ".2d", ".2d", ".4s",
6563       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6564                                       (extract_high_v4i32 V128:$Rm)))]>;
6565}
6566
6567//----------------------------------------------------------------------------
6568// AdvSIMD bitwise extract from vector
6569//----------------------------------------------------------------------------
6570
6571class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6572                             string asm, string kind>
6573  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6574      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6575      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6576      [(set (vty regtype:$Rd),
6577            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6578    Sched<[WriteV]> {
6579  bits<5> Rd;
6580  bits<5> Rn;
6581  bits<5> Rm;
6582  bits<4> imm;
6583  let Inst{31}    = 0;
6584  let Inst{30}    = size;
6585  let Inst{29-21} = 0b101110000;
6586  let Inst{20-16} = Rm;
6587  let Inst{15}    = 0;
6588  let Inst{14-11} = imm;
6589  let Inst{10}    = 0;
6590  let Inst{9-5}   = Rn;
6591  let Inst{4-0}   = Rd;
6592}
6593
6594
6595multiclass SIMDBitwiseExtract<string asm> {
6596  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6597    let imm{3} = 0;
6598  }
6599  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6600}
6601
6602//----------------------------------------------------------------------------
6603// AdvSIMD zip vector
6604//----------------------------------------------------------------------------
6605
6606class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6607                        string asm, string kind, SDNode OpNode, ValueType valty>
6608  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6609      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6610      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6611      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6612    Sched<[WriteV]> {
6613  bits<5> Rd;
6614  bits<5> Rn;
6615  bits<5> Rm;
6616  let Inst{31}    = 0;
6617  let Inst{30}    = size{0};
6618  let Inst{29-24} = 0b001110;
6619  let Inst{23-22} = size{2-1};
6620  let Inst{21}    = 0;
6621  let Inst{20-16} = Rm;
6622  let Inst{15}    = 0;
6623  let Inst{14-12} = opc;
6624  let Inst{11-10} = 0b10;
6625  let Inst{9-5}   = Rn;
6626  let Inst{4-0}   = Rd;
6627}
6628
6629multiclass SIMDZipVector<bits<3>opc, string asm,
6630                         SDNode OpNode> {
6631  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6632      asm, ".8b", OpNode, v8i8>;
6633  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6634      asm, ".16b", OpNode, v16i8>;
6635  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6636      asm, ".4h", OpNode, v4i16>;
6637  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6638      asm, ".8h", OpNode, v8i16>;
6639  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6640      asm, ".2s", OpNode, v2i32>;
6641  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6642      asm, ".4s", OpNode, v4i32>;
6643  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6644      asm, ".2d", OpNode, v2i64>;
6645
6646  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6647        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6648  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6649        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6650  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6651        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6652  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6653        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6654  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6655        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6656}
6657
6658//----------------------------------------------------------------------------
6659// AdvSIMD three register scalar instructions
6660//----------------------------------------------------------------------------
6661
6662let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6663class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6664                        RegisterClass regtype, string asm,
6665                        list<dag> pattern>
6666  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6667      "\t$Rd, $Rn, $Rm", "", pattern>,
6668    Sched<[WriteV]> {
6669  bits<5> Rd;
6670  bits<5> Rn;
6671  bits<5> Rm;
6672  let Inst{31-30} = 0b01;
6673  let Inst{29}    = U;
6674  let Inst{28-24} = 0b11110;
6675  let Inst{23-21} = size;
6676  let Inst{20-16} = Rm;
6677  let Inst{15-11} = opcode;
6678  let Inst{10}    = 1;
6679  let Inst{9-5}   = Rn;
6680  let Inst{4-0}   = Rd;
6681}
6682
6683let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6684class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6685                        dag oops, dag iops, string asm,
6686            list<dag> pattern>
6687  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6688    Sched<[WriteV]> {
6689  bits<5> Rd;
6690  bits<5> Rn;
6691  bits<5> Rm;
6692  let Inst{31-30} = 0b01;
6693  let Inst{29}    = U;
6694  let Inst{28-24} = 0b11110;
6695  let Inst{23-22} = size;
6696  let Inst{21}    = R;
6697  let Inst{20-16} = Rm;
6698  let Inst{15-11} = opcode;
6699  let Inst{10}    = 1;
6700  let Inst{9-5}   = Rn;
6701  let Inst{4-0}   = Rd;
6702}
6703
6704multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6705                            SDPatternOperator OpNode> {
6706  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6707    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6708}
6709
6710multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6711                               SDPatternOperator OpNode> {
6712  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6713    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6714  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6715  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6716  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6717
6718  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6719            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6720  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6721            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6722}
6723
6724multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6725                             SDPatternOperator OpNode> {
6726  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6727                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6728  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6729}
6730
6731multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6732                                 SDPatternOperator OpNode = null_frag> {
6733  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6734                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6735                                     asm, []>;
6736  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6737                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6738                                     asm, []>;
6739}
6740
6741multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6742                             SDPatternOperator OpNode = null_frag> {
6743  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6744    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6745      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6746    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6747      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6748    let Predicates = [HasNEON, HasFullFP16] in {
6749    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6750      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6751    } // Predicates = [HasNEON, HasFullFP16]
6752  }
6753
6754  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6755            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6756}
6757
6758multiclass SIMDThreeScalarFPCmp<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 (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6763    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6764      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6765    let Predicates = [HasNEON, HasFullFP16] in {
6766    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6767      []>;
6768    } // Predicates = [HasNEON, HasFullFP16]
6769  }
6770
6771  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6772            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6773}
6774
6775class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6776              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6777  : I<oops, iops, asm,
6778      "\t$Rd, $Rn, $Rm", cstr, pat>,
6779    Sched<[WriteV]> {
6780  bits<5> Rd;
6781  bits<5> Rn;
6782  bits<5> Rm;
6783  let Inst{31-30} = 0b01;
6784  let Inst{29}    = U;
6785  let Inst{28-24} = 0b11110;
6786  let Inst{23-22} = size;
6787  let Inst{21}    = 1;
6788  let Inst{20-16} = Rm;
6789  let Inst{15-11} = opcode;
6790  let Inst{10}    = 0;
6791  let Inst{9-5}   = Rn;
6792  let Inst{4-0}   = Rd;
6793}
6794
6795let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6796multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6797                                  SDPatternOperator OpNode = null_frag> {
6798  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6799                                      (outs FPR32:$Rd),
6800                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6801  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6802                                      (outs FPR64:$Rd),
6803                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6804            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6805}
6806
6807let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6808multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6809                                  SDPatternOperator OpNode = null_frag> {
6810  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6811                                      (outs FPR32:$dst),
6812                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6813                                      asm, "$Rd = $dst", []>;
6814  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6815                                      (outs FPR64:$dst),
6816                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6817                                      asm, "$Rd = $dst",
6818            [(set (i64 FPR64:$dst),
6819                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6820}
6821
6822//----------------------------------------------------------------------------
6823// AdvSIMD two register scalar instructions
6824//----------------------------------------------------------------------------
6825
6826let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6827class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6828                        RegisterClass regtype, RegisterClass regtype2,
6829                        string asm, list<dag> pat>
6830  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6831      "\t$Rd, $Rn", "", pat>,
6832    Sched<[WriteV]> {
6833  bits<5> Rd;
6834  bits<5> Rn;
6835  let Inst{31-30} = 0b01;
6836  let Inst{29}    = U;
6837  let Inst{28-24} = 0b11110;
6838  let Inst{23-22} = size;
6839  let Inst{21} = 0b1;
6840  let Inst{20-19} = size2;
6841  let Inst{18-17} = 0b00;
6842  let Inst{16-12} = opcode;
6843  let Inst{11-10} = 0b10;
6844  let Inst{9-5}   = Rn;
6845  let Inst{4-0}   = Rd;
6846}
6847
6848let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6849class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6850                        RegisterClass regtype, RegisterClass regtype2,
6851                        string asm, list<dag> pat>
6852  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6853      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6854    Sched<[WriteV]> {
6855  bits<5> Rd;
6856  bits<5> Rn;
6857  let Inst{31-30} = 0b01;
6858  let Inst{29}    = U;
6859  let Inst{28-24} = 0b11110;
6860  let Inst{23-22} = size;
6861  let Inst{21-17} = 0b10000;
6862  let Inst{16-12} = opcode;
6863  let Inst{11-10} = 0b10;
6864  let Inst{9-5}   = Rn;
6865  let Inst{4-0}   = Rd;
6866}
6867
6868
6869let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6870class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6871                        RegisterClass regtype, string asm, string zero>
6872  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6873      "\t$Rd, $Rn, #" # zero, "", []>,
6874    Sched<[WriteV]> {
6875  bits<5> Rd;
6876  bits<5> Rn;
6877  let Inst{31-30} = 0b01;
6878  let Inst{29}    = U;
6879  let Inst{28-24} = 0b11110;
6880  let Inst{23-22} = size;
6881  let Inst{21} = 0b1;
6882  let Inst{20-19} = size2;
6883  let Inst{18-17} = 0b00;
6884  let Inst{16-12} = opcode;
6885  let Inst{11-10} = 0b10;
6886  let Inst{9-5}   = Rn;
6887  let Inst{4-0}   = Rd;
6888}
6889
6890class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6891  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6892     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6893    Sched<[WriteV]> {
6894  bits<5> Rd;
6895  bits<5> Rn;
6896  let Inst{31-17} = 0b011111100110000;
6897  let Inst{16-12} = opcode;
6898  let Inst{11-10} = 0b10;
6899  let Inst{9-5}   = Rn;
6900  let Inst{4-0}   = Rd;
6901}
6902
6903multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6904                             SDPatternOperator OpNode> {
6905  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6906
6907  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6908            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6909}
6910
6911multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6912                              SDPatternOperator OpNode> {
6913  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6914  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6915  let Predicates = [HasNEON, HasFullFP16] in {
6916  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6917  }
6918
6919  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6920                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6921  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6922                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6923  let Predicates = [HasNEON, HasFullFP16] in {
6924  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6925                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6926  }
6927
6928  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6929            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6930}
6931
6932multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6933                          SDPatternOperator OpNode = null_frag> {
6934  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6935    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6936
6937  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6938            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6939}
6940
6941multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6942  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6943  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6944  let Predicates = [HasNEON, HasFullFP16] in {
6945  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6946  }
6947}
6948
6949multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6950                              SDPatternOperator OpNode> {
6951  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6952                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6953  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6954                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6955  let Predicates = [HasNEON, HasFullFP16] in {
6956  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6957                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
6958  }
6959}
6960
6961multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6962                             SDPatternOperator OpNode = null_frag> {
6963  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6964    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6965           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6966    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6967           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6968    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6969    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6970  }
6971
6972  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6973            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6974}
6975
6976multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6977                                 Intrinsic OpNode> {
6978  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6979    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6980        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6981    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6982        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6983    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6984    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6985  }
6986
6987  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6988            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6989}
6990
6991
6992
6993let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6994multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6995                                 SDPatternOperator OpNode = null_frag> {
6996  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6997        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6998  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6999  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7000}
7001
7002//----------------------------------------------------------------------------
7003// AdvSIMD scalar pairwise instructions
7004//----------------------------------------------------------------------------
7005
7006let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7007class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7008                        RegisterOperand regtype, RegisterOperand vectype,
7009                        string asm, string kind>
7010  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7011      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7012    Sched<[WriteV]> {
7013  bits<5> Rd;
7014  bits<5> Rn;
7015  let Inst{31-30} = 0b01;
7016  let Inst{29}    = U;
7017  let Inst{28-24} = 0b11110;
7018  let Inst{23-22} = size;
7019  let Inst{21-17} = 0b11000;
7020  let Inst{16-12} = opcode;
7021  let Inst{11-10} = 0b10;
7022  let Inst{9-5}   = Rn;
7023  let Inst{4-0}   = Rd;
7024}
7025
7026multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7027  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7028                                      asm, ".2d">;
7029}
7030
7031multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7032  let Predicates = [HasNEON, HasFullFP16] in {
7033  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7034                                      asm, ".2h">;
7035  }
7036  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7037                                      asm, ".2s">;
7038  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7039                                      asm, ".2d">;
7040}
7041
7042//----------------------------------------------------------------------------
7043// AdvSIMD across lanes instructions
7044//----------------------------------------------------------------------------
7045
7046let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7047class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7048                          RegisterClass regtype, RegisterOperand vectype,
7049                          string asm, string kind, list<dag> pattern>
7050  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7051      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7052    Sched<[WriteV]> {
7053  bits<5> Rd;
7054  bits<5> Rn;
7055  let Inst{31}    = 0;
7056  let Inst{30}    = Q;
7057  let Inst{29}    = U;
7058  let Inst{28-24} = 0b01110;
7059  let Inst{23-22} = size;
7060  let Inst{21-17} = 0b11000;
7061  let Inst{16-12} = opcode;
7062  let Inst{11-10} = 0b10;
7063  let Inst{9-5}   = Rn;
7064  let Inst{4-0}   = Rd;
7065}
7066
7067multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7068                              string asm> {
7069  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7070                                   asm, ".8b", []>;
7071  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7072                                   asm, ".16b", []>;
7073  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7074                                   asm, ".4h", []>;
7075  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7076                                   asm, ".8h", []>;
7077  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7078                                   asm, ".4s", []>;
7079}
7080
7081multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7082  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7083                                   asm, ".8b", []>;
7084  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7085                                   asm, ".16b", []>;
7086  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7087                                   asm, ".4h", []>;
7088  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7089                                   asm, ".8h", []>;
7090  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7091                                   asm, ".4s", []>;
7092}
7093
7094multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7095                            Intrinsic intOp> {
7096  let Predicates = [HasNEON, HasFullFP16] in {
7097  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7098                                   asm, ".4h",
7099        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7100  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7101                                   asm, ".8h",
7102        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7103  } // Predicates = [HasNEON, HasFullFP16]
7104  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7105                                   asm, ".4s",
7106        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7107}
7108
7109//----------------------------------------------------------------------------
7110// AdvSIMD INS/DUP instructions
7111//----------------------------------------------------------------------------
7112
7113// FIXME: There has got to be a better way to factor these. ugh.
7114
7115class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7116                     string operands, string constraints, list<dag> pattern>
7117  : I<outs, ins, asm, operands, constraints, pattern>,
7118    Sched<[WriteV]> {
7119  bits<5> Rd;
7120  bits<5> Rn;
7121  let Inst{31} = 0;
7122  let Inst{30} = Q;
7123  let Inst{29} = op;
7124  let Inst{28-21} = 0b01110000;
7125  let Inst{15} = 0;
7126  let Inst{10} = 1;
7127  let Inst{9-5} = Rn;
7128  let Inst{4-0} = Rd;
7129}
7130
7131class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7132                      RegisterOperand vecreg, RegisterClass regtype>
7133  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7134                   "{\t$Rd" # size # ", $Rn" #
7135                   "|" # size # "\t$Rd, $Rn}", "",
7136                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7137  let Inst{20-16} = imm5;
7138  let Inst{14-11} = 0b0001;
7139}
7140
7141class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7142                         ValueType vectype, ValueType insreg,
7143                         RegisterOperand vecreg, Operand idxtype,
7144                         ValueType elttype, SDNode OpNode>
7145  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7146                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7147                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7148                 [(set (vectype vecreg:$Rd),
7149                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7150  let Inst{14-11} = 0b0000;
7151}
7152
7153class SIMDDup64FromElement
7154  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7155                       VectorIndexD, i64, AArch64duplane64> {
7156  bits<1> idx;
7157  let Inst{20} = idx;
7158  let Inst{19-16} = 0b1000;
7159}
7160
7161class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7162                           RegisterOperand vecreg>
7163  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7164                       VectorIndexS, i64, AArch64duplane32> {
7165  bits<2> idx;
7166  let Inst{20-19} = idx;
7167  let Inst{18-16} = 0b100;
7168}
7169
7170class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7171                           RegisterOperand vecreg>
7172  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7173                       VectorIndexH, i64, AArch64duplane16> {
7174  bits<3> idx;
7175  let Inst{20-18} = idx;
7176  let Inst{17-16} = 0b10;
7177}
7178
7179class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7180                          RegisterOperand vecreg>
7181  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7182                       VectorIndexB, i64, AArch64duplane8> {
7183  bits<4> idx;
7184  let Inst{20-17} = idx;
7185  let Inst{16} = 1;
7186}
7187
7188class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7189                  Operand idxtype, string asm, list<dag> pattern>
7190  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7191                   "{\t$Rd, $Rn" # size # "$idx" #
7192                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7193  let Inst{14-11} = imm4;
7194}
7195
7196class SIMDSMov<bit Q, string size, RegisterClass regtype,
7197               Operand idxtype>
7198  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7199class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7200               Operand idxtype>
7201  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7202      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7203
7204class SIMDMovAlias<string asm, string size, Instruction inst,
7205                   RegisterClass regtype, Operand idxtype>
7206    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7207                    "|" # size # "\t$dst, $src$idx}",
7208                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7209
7210multiclass SMov {
7211  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7212    bits<4> idx;
7213    let Inst{20-17} = idx;
7214    let Inst{16} = 1;
7215  }
7216  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7217    bits<4> idx;
7218    let Inst{20-17} = idx;
7219    let Inst{16} = 1;
7220  }
7221  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7222    bits<3> idx;
7223    let Inst{20-18} = idx;
7224    let Inst{17-16} = 0b10;
7225  }
7226  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7227    bits<3> idx;
7228    let Inst{20-18} = idx;
7229    let Inst{17-16} = 0b10;
7230  }
7231  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7232    bits<2> idx;
7233    let Inst{20-19} = idx;
7234    let Inst{18-16} = 0b100;
7235  }
7236}
7237
7238multiclass UMov {
7239  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7240    bits<4> idx;
7241    let Inst{20-17} = idx;
7242    let Inst{16} = 1;
7243  }
7244  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7245    bits<3> idx;
7246    let Inst{20-18} = idx;
7247    let Inst{17-16} = 0b10;
7248  }
7249  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7250    bits<2> idx;
7251    let Inst{20-19} = idx;
7252    let Inst{18-16} = 0b100;
7253  }
7254  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7255    bits<1> idx;
7256    let Inst{20} = idx;
7257    let Inst{19-16} = 0b1000;
7258  }
7259  def : SIMDMovAlias<"mov", ".s",
7260                     !cast<Instruction>(NAME#"vi32"),
7261                     GPR32, VectorIndexS>;
7262  def : SIMDMovAlias<"mov", ".d",
7263                     !cast<Instruction>(NAME#"vi64"),
7264                     GPR64, VectorIndexD>;
7265}
7266
7267class SIMDInsFromMain<string size, ValueType vectype,
7268                      RegisterClass regtype, Operand idxtype>
7269  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7270                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7271                   "{\t$Rd" # size # "$idx, $Rn" #
7272                   "|" # size # "\t$Rd$idx, $Rn}",
7273                   "$Rd = $dst",
7274            [(set V128:$dst,
7275              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7276  let Inst{14-11} = 0b0011;
7277}
7278
7279class SIMDInsFromElement<string size, ValueType vectype,
7280                         ValueType elttype, Operand idxtype>
7281  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7282                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7283                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7284                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7285                   "$Rd = $dst",
7286         [(set V128:$dst,
7287               (vector_insert
7288                 (vectype V128:$Rd),
7289                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7290                 idxtype:$idx))]>;
7291
7292class SIMDInsMainMovAlias<string size, Instruction inst,
7293                          RegisterClass regtype, Operand idxtype>
7294    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7295                        "|" # size #"\t$dst$idx, $src}",
7296                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7297class SIMDInsElementMovAlias<string size, Instruction inst,
7298                             Operand idxtype>
7299    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7300                      # "|" # size #"\t$dst$idx, $src$idx2}",
7301                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7302
7303
7304multiclass SIMDIns {
7305  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7306    bits<4> idx;
7307    let Inst{20-17} = idx;
7308    let Inst{16} = 1;
7309  }
7310  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7311    bits<3> idx;
7312    let Inst{20-18} = idx;
7313    let Inst{17-16} = 0b10;
7314  }
7315  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7316    bits<2> idx;
7317    let Inst{20-19} = idx;
7318    let Inst{18-16} = 0b100;
7319  }
7320  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7321    bits<1> idx;
7322    let Inst{20} = idx;
7323    let Inst{19-16} = 0b1000;
7324  }
7325
7326  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7327    bits<4> idx;
7328    bits<4> idx2;
7329    let Inst{20-17} = idx;
7330    let Inst{16} = 1;
7331    let Inst{14-11} = idx2;
7332  }
7333  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7334    bits<3> idx;
7335    bits<3> idx2;
7336    let Inst{20-18} = idx;
7337    let Inst{17-16} = 0b10;
7338    let Inst{14-12} = idx2;
7339    let Inst{11} = {?};
7340  }
7341  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7342    bits<2> idx;
7343    bits<2> idx2;
7344    let Inst{20-19} = idx;
7345    let Inst{18-16} = 0b100;
7346    let Inst{14-13} = idx2;
7347    let Inst{12-11} = {?,?};
7348  }
7349  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7350    bits<1> idx;
7351    bits<1> idx2;
7352    let Inst{20} = idx;
7353    let Inst{19-16} = 0b1000;
7354    let Inst{14} = idx2;
7355    let Inst{13-11} = {?,?,?};
7356  }
7357
7358  // For all forms of the INS instruction, the "mov" mnemonic is the
7359  // preferred alias. Why they didn't just call the instruction "mov" in
7360  // the first place is a very good question indeed...
7361  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7362                         GPR32, VectorIndexB>;
7363  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7364                         GPR32, VectorIndexH>;
7365  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7366                         GPR32, VectorIndexS>;
7367  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7368                         GPR64, VectorIndexD>;
7369
7370  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7371                         VectorIndexB>;
7372  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7373                         VectorIndexH>;
7374  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7375                         VectorIndexS>;
7376  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7377                         VectorIndexD>;
7378}
7379
7380//----------------------------------------------------------------------------
7381// AdvSIMD TBL/TBX
7382//----------------------------------------------------------------------------
7383
7384let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7385class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7386                          RegisterOperand listtype, string asm, string kind>
7387  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7388       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7389    Sched<[WriteV]> {
7390  bits<5> Vd;
7391  bits<5> Vn;
7392  bits<5> Vm;
7393  let Inst{31}    = 0;
7394  let Inst{30}    = Q;
7395  let Inst{29-21} = 0b001110000;
7396  let Inst{20-16} = Vm;
7397  let Inst{15}    = 0;
7398  let Inst{14-13} = len;
7399  let Inst{12}    = op;
7400  let Inst{11-10} = 0b00;
7401  let Inst{9-5}   = Vn;
7402  let Inst{4-0}   = Vd;
7403}
7404
7405let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7406class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7407                          RegisterOperand listtype, string asm, string kind>
7408  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7409       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7410    Sched<[WriteV]> {
7411  bits<5> Vd;
7412  bits<5> Vn;
7413  bits<5> Vm;
7414  let Inst{31}    = 0;
7415  let Inst{30}    = Q;
7416  let Inst{29-21} = 0b001110000;
7417  let Inst{20-16} = Vm;
7418  let Inst{15}    = 0;
7419  let Inst{14-13} = len;
7420  let Inst{12}    = op;
7421  let Inst{11-10} = 0b00;
7422  let Inst{9-5}   = Vn;
7423  let Inst{4-0}   = Vd;
7424}
7425
7426class SIMDTableLookupAlias<string asm, Instruction inst,
7427                          RegisterOperand vectype, RegisterOperand listtype>
7428    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7429                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7430
7431multiclass SIMDTableLookup<bit op, string asm> {
7432  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7433                                      asm, ".8b">;
7434  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7435                                      asm, ".8b">;
7436  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7437                                      asm, ".8b">;
7438  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7439                                      asm, ".8b">;
7440  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7441                                      asm, ".16b">;
7442  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7443                                      asm, ".16b">;
7444  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7445                                      asm, ".16b">;
7446  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7447                                      asm, ".16b">;
7448
7449  def : SIMDTableLookupAlias<asm # ".8b",
7450                         !cast<Instruction>(NAME#"v8i8One"),
7451                         V64, VecListOne128>;
7452  def : SIMDTableLookupAlias<asm # ".8b",
7453                         !cast<Instruction>(NAME#"v8i8Two"),
7454                         V64, VecListTwo128>;
7455  def : SIMDTableLookupAlias<asm # ".8b",
7456                         !cast<Instruction>(NAME#"v8i8Three"),
7457                         V64, VecListThree128>;
7458  def : SIMDTableLookupAlias<asm # ".8b",
7459                         !cast<Instruction>(NAME#"v8i8Four"),
7460                         V64, VecListFour128>;
7461  def : SIMDTableLookupAlias<asm # ".16b",
7462                         !cast<Instruction>(NAME#"v16i8One"),
7463                         V128, VecListOne128>;
7464  def : SIMDTableLookupAlias<asm # ".16b",
7465                         !cast<Instruction>(NAME#"v16i8Two"),
7466                         V128, VecListTwo128>;
7467  def : SIMDTableLookupAlias<asm # ".16b",
7468                         !cast<Instruction>(NAME#"v16i8Three"),
7469                         V128, VecListThree128>;
7470  def : SIMDTableLookupAlias<asm # ".16b",
7471                         !cast<Instruction>(NAME#"v16i8Four"),
7472                         V128, VecListFour128>;
7473}
7474
7475multiclass SIMDTableLookupTied<bit op, string asm> {
7476  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7477                                      asm, ".8b">;
7478  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7479                                      asm, ".8b">;
7480  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7481                                      asm, ".8b">;
7482  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7483                                      asm, ".8b">;
7484  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7485                                      asm, ".16b">;
7486  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7487                                      asm, ".16b">;
7488  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7489                                      asm, ".16b">;
7490  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7491                                      asm, ".16b">;
7492
7493  def : SIMDTableLookupAlias<asm # ".8b",
7494                         !cast<Instruction>(NAME#"v8i8One"),
7495                         V64, VecListOne128>;
7496  def : SIMDTableLookupAlias<asm # ".8b",
7497                         !cast<Instruction>(NAME#"v8i8Two"),
7498                         V64, VecListTwo128>;
7499  def : SIMDTableLookupAlias<asm # ".8b",
7500                         !cast<Instruction>(NAME#"v8i8Three"),
7501                         V64, VecListThree128>;
7502  def : SIMDTableLookupAlias<asm # ".8b",
7503                         !cast<Instruction>(NAME#"v8i8Four"),
7504                         V64, VecListFour128>;
7505  def : SIMDTableLookupAlias<asm # ".16b",
7506                         !cast<Instruction>(NAME#"v16i8One"),
7507                         V128, VecListOne128>;
7508  def : SIMDTableLookupAlias<asm # ".16b",
7509                         !cast<Instruction>(NAME#"v16i8Two"),
7510                         V128, VecListTwo128>;
7511  def : SIMDTableLookupAlias<asm # ".16b",
7512                         !cast<Instruction>(NAME#"v16i8Three"),
7513                         V128, VecListThree128>;
7514  def : SIMDTableLookupAlias<asm # ".16b",
7515                         !cast<Instruction>(NAME#"v16i8Four"),
7516                         V128, VecListFour128>;
7517}
7518
7519
7520//----------------------------------------------------------------------------
7521// AdvSIMD scalar CPY
7522//----------------------------------------------------------------------------
7523let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7524class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7525                        string kind, Operand idxtype>
7526  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7527       "{\t$dst, $src" # kind # "$idx" #
7528       "|\t$dst, $src$idx}", "", []>,
7529    Sched<[WriteV]> {
7530  bits<5> dst;
7531  bits<5> src;
7532  let Inst{31-21} = 0b01011110000;
7533  let Inst{15-10} = 0b000001;
7534  let Inst{9-5}   = src;
7535  let Inst{4-0}   = dst;
7536}
7537
7538class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7539      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7540    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7541                    # "|\t$dst, $src$index}",
7542                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7543
7544
7545multiclass SIMDScalarCPY<string asm> {
7546  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7547    bits<4> idx;
7548    let Inst{20-17} = idx;
7549    let Inst{16} = 1;
7550  }
7551  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7552    bits<3> idx;
7553    let Inst{20-18} = idx;
7554    let Inst{17-16} = 0b10;
7555  }
7556  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7557    bits<2> idx;
7558    let Inst{20-19} = idx;
7559    let Inst{18-16} = 0b100;
7560  }
7561  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7562    bits<1> idx;
7563    let Inst{20} = idx;
7564    let Inst{19-16} = 0b1000;
7565  }
7566
7567  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7568                                                          VectorIndexD:$idx)))),
7569            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7570
7571  // 'DUP' mnemonic aliases.
7572  def : SIMDScalarCPYAlias<"dup", ".b",
7573                           !cast<Instruction>(NAME#"i8"),
7574                           FPR8, V128, VectorIndexB>;
7575  def : SIMDScalarCPYAlias<"dup", ".h",
7576                           !cast<Instruction>(NAME#"i16"),
7577                           FPR16, V128, VectorIndexH>;
7578  def : SIMDScalarCPYAlias<"dup", ".s",
7579                           !cast<Instruction>(NAME#"i32"),
7580                           FPR32, V128, VectorIndexS>;
7581  def : SIMDScalarCPYAlias<"dup", ".d",
7582                           !cast<Instruction>(NAME#"i64"),
7583                           FPR64, V128, VectorIndexD>;
7584}
7585
7586//----------------------------------------------------------------------------
7587// AdvSIMD modified immediate instructions
7588//----------------------------------------------------------------------------
7589
7590class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7591                          string asm, string op_string,
7592                          string cstr, list<dag> pattern>
7593  : I<oops, iops, asm, op_string, cstr, pattern>,
7594    Sched<[WriteV]> {
7595  bits<5> Rd;
7596  bits<8> imm8;
7597  let Inst{31}    = 0;
7598  let Inst{30}    = Q;
7599  let Inst{29}    = op;
7600  let Inst{28-19} = 0b0111100000;
7601  let Inst{18-16} = imm8{7-5};
7602  let Inst{11} = op2;
7603  let Inst{10} = 1;
7604  let Inst{9-5}   = imm8{4-0};
7605  let Inst{4-0}   = Rd;
7606}
7607
7608class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7609                                Operand immtype, dag opt_shift_iop,
7610                                string opt_shift, string asm, string kind,
7611                                list<dag> pattern>
7612  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7613                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7614                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7615                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7616                        "", pattern> {
7617  let DecoderMethod = "DecodeModImmInstruction";
7618}
7619
7620class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7621                                Operand immtype, dag opt_shift_iop,
7622                                string opt_shift, string asm, string kind,
7623                                list<dag> pattern>
7624  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7625                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7626                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7627                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7628                        "$Rd = $dst", pattern> {
7629  let DecoderMethod = "DecodeModImmTiedInstruction";
7630}
7631
7632class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7633                                     RegisterOperand vectype, string asm,
7634                                     string kind, list<dag> pattern>
7635  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7636                              (ins logical_vec_shift:$shift),
7637                              "$shift", asm, kind, pattern> {
7638  bits<2> shift;
7639  let Inst{15}    = b15_b12{1};
7640  let Inst{14-13} = shift;
7641  let Inst{12}    = b15_b12{0};
7642}
7643
7644class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7645                                     RegisterOperand vectype, string asm,
7646                                     string kind, list<dag> pattern>
7647  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7648                              (ins logical_vec_shift:$shift),
7649                              "$shift", asm, kind, pattern> {
7650  bits<2> shift;
7651  let Inst{15}    = b15_b12{1};
7652  let Inst{14-13} = shift;
7653  let Inst{12}    = b15_b12{0};
7654}
7655
7656
7657class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7658                                         RegisterOperand vectype, string asm,
7659                                         string kind, list<dag> pattern>
7660  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7661                              (ins logical_vec_hw_shift:$shift),
7662                              "$shift", asm, kind, pattern> {
7663  bits<2> shift;
7664  let Inst{15} = b15_b12{1};
7665  let Inst{14} = 0;
7666  let Inst{13} = shift{0};
7667  let Inst{12} = b15_b12{0};
7668}
7669
7670class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7671                                         RegisterOperand vectype, string asm,
7672                                         string kind, list<dag> pattern>
7673  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7674                              (ins logical_vec_hw_shift:$shift),
7675                              "$shift", asm, kind, pattern> {
7676  bits<2> shift;
7677  let Inst{15} = b15_b12{1};
7678  let Inst{14} = 0;
7679  let Inst{13} = shift{0};
7680  let Inst{12} = b15_b12{0};
7681}
7682
7683multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7684                                      string asm> {
7685  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7686                                                 asm, ".4h", []>;
7687  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7688                                                 asm, ".8h", []>;
7689
7690  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7691                                             asm, ".2s", []>;
7692  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7693                                             asm, ".4s", []>;
7694}
7695
7696multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7697                                      bits<2> w_cmode, string asm,
7698                                      SDNode OpNode> {
7699  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7700                                                 asm, ".4h",
7701             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7702                                             imm0_255:$imm8,
7703                                             (i32 imm:$shift)))]>;
7704  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7705                                                 asm, ".8h",
7706             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7707                                              imm0_255:$imm8,
7708                                              (i32 imm:$shift)))]>;
7709
7710  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7711                                             asm, ".2s",
7712             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7713                                             imm0_255:$imm8,
7714                                             (i32 imm:$shift)))]>;
7715  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7716                                             asm, ".4s",
7717             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7718                                              imm0_255:$imm8,
7719                                              (i32 imm:$shift)))]>;
7720}
7721
7722class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7723                             RegisterOperand vectype, string asm,
7724                             string kind, list<dag> pattern>
7725  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7726                              (ins move_vec_shift:$shift),
7727                              "$shift", asm, kind, pattern> {
7728  bits<1> shift;
7729  let Inst{15-13} = cmode{3-1};
7730  let Inst{12}    = shift;
7731}
7732
7733class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7734                                   RegisterOperand vectype,
7735                                   Operand imm_type, string asm,
7736                                   string kind, list<dag> pattern>
7737  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7738                              asm, kind, pattern> {
7739  let Inst{15-12} = cmode;
7740}
7741
7742class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7743                                   list<dag> pattern>
7744  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7745                        "\t$Rd, $imm8", "", pattern> {
7746  let Inst{15-12} = cmode;
7747  let DecoderMethod = "DecodeModImmInstruction";
7748}
7749
7750//----------------------------------------------------------------------------
7751// AdvSIMD indexed element
7752//----------------------------------------------------------------------------
7753
7754let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7755class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7756                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7757                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7758                      string apple_kind, string dst_kind, string lhs_kind,
7759                      string rhs_kind, list<dag> pattern>
7760  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7761      asm,
7762      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7763      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7764    Sched<[WriteV]> {
7765  bits<5> Rd;
7766  bits<5> Rn;
7767  bits<5> Rm;
7768
7769  let Inst{31}    = 0;
7770  let Inst{30}    = Q;
7771  let Inst{29}    = U;
7772  let Inst{28}    = Scalar;
7773  let Inst{27-24} = 0b1111;
7774  let Inst{23-22} = size;
7775  // Bit 21 must be set by the derived class.
7776  let Inst{20-16} = Rm;
7777  let Inst{15-12} = opc;
7778  // Bit 11 must be set by the derived class.
7779  let Inst{10}    = 0;
7780  let Inst{9-5}   = Rn;
7781  let Inst{4-0}   = Rd;
7782}
7783
7784let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7785class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7786                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7787                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7788                      string apple_kind, string dst_kind, string lhs_kind,
7789                      string rhs_kind, list<dag> pattern>
7790  : I<(outs dst_reg:$dst),
7791      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7792      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7793      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7794    Sched<[WriteV]> {
7795  bits<5> Rd;
7796  bits<5> Rn;
7797  bits<5> Rm;
7798
7799  let Inst{31}    = 0;
7800  let Inst{30}    = Q;
7801  let Inst{29}    = U;
7802  let Inst{28}    = Scalar;
7803  let Inst{27-24} = 0b1111;
7804  let Inst{23-22} = size;
7805  // Bit 21 must be set by the derived class.
7806  let Inst{20-16} = Rm;
7807  let Inst{15-12} = opc;
7808  // Bit 11 must be set by the derived class.
7809  let Inst{10}    = 0;
7810  let Inst{9-5}   = Rn;
7811  let Inst{4-0}   = Rd;
7812}
7813
7814
7815//----------------------------------------------------------------------------
7816// Armv8.6 BFloat16 Extension
7817//----------------------------------------------------------------------------
7818let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
7819
7820class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
7821                                   string kind2, RegisterOperand RegType,
7822                                   ValueType AccumType, ValueType InputType>
7823  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
7824                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
7825                                            (InputType RegType:$Rn),
7826                                            (InputType RegType:$Rm)))]> {
7827  let AsmString = !strconcat(asm,
7828                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
7829                               ", $Rm" # kind2 # "}");
7830}
7831
7832multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
7833  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
7834                                           v2f32, v8i8>;
7835  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
7836                                           v4f32, v16i8>;
7837}
7838
7839class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
7840                                      string dst_kind, string lhs_kind,
7841                                      string rhs_kind,
7842                                      RegisterOperand RegType,
7843                                      ValueType AccumType,
7844                                      ValueType InputType>
7845  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
7846                        RegType, RegType, V128, VectorIndexS,
7847                        asm, "", dst_kind, lhs_kind, rhs_kind,
7848        [(set (AccumType RegType:$dst),
7849              (AccumType (int_aarch64_neon_bfdot
7850                                 (AccumType RegType:$Rd),
7851                                 (InputType RegType:$Rn),
7852                                 (InputType (bitconvert (AccumType
7853                                    (AArch64duplane32 (v4f32 V128:$Rm),
7854                                        VectorIndexH:$idx)))))))]> {
7855
7856  bits<2> idx;
7857  let Inst{21}    = idx{0};  // L
7858  let Inst{11}    = idx{1};  // H
7859}
7860
7861multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
7862
7863  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
7864                                               ".2h", V64, v2f32, v8i8>;
7865  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
7866                                              ".2h", V128, v4f32, v16i8>;
7867}
7868
7869class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
7870  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
7871              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
7872                                               (v16i8 V128:$Rn),
7873                                               (v16i8 V128:$Rm)))]> {
7874  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
7875}
7876
7877class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
7878  : I<(outs V128:$dst),
7879      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
7880      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
7881          [(set (v4f32 V128:$dst),
7882                (v4f32 (OpNode (v4f32 V128:$Rd),
7883                               (v16i8 V128:$Rn),
7884                               (v16i8 (bitconvert (v8bf16
7885                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
7886                                      VectorIndexH:$idx)))))))]>,
7887    Sched<[WriteV]> {
7888  bits<5> Rd;
7889  bits<5> Rn;
7890  bits<4> Rm;
7891  bits<3> idx;
7892
7893  let Inst{31}    = 0;
7894  let Inst{30}    = Q;
7895  let Inst{29-22} = 0b00111111;
7896  let Inst{21-20} = idx{1-0};
7897  let Inst{19-16} = Rm;
7898  let Inst{15-12} = 0b1111;
7899  let Inst{11}    = idx{2};   // H
7900  let Inst{10}    = 0;
7901  let Inst{9-5}   = Rn;
7902  let Inst{4-0}   = Rd;
7903}
7904
7905class SIMDThreeSameVectorBF16MatrixMul<string asm>
7906  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
7907                                V128, asm, ".4s",
7908                          [(set (v4f32 V128:$dst),
7909                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
7910                                                         (v16i8 V128:$Rn),
7911                                                         (v16i8 V128:$Rm)))]> {
7912  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
7913                                    ", $Rm", ".8h", "}");
7914}
7915
7916class SIMD_BFCVTN
7917  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
7918                           "bfcvtn", ".4h", ".4s",
7919    [(set (v8bf16 V128:$Rd),
7920          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
7921
7922class SIMD_BFCVTN2
7923  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
7924                           "bfcvtn2", ".8h", ".4s",
7925    [(set (v8bf16 V128:$dst),
7926          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
7927
7928class BF16ToSinglePrecision<string asm>
7929  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
7930    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
7931    Sched<[WriteFCvt]> {
7932  bits<5> Rd;
7933  bits<5> Rn;
7934  let Inst{31-10} = 0b0001111001100011010000;
7935  let Inst{9-5}   = Rn;
7936  let Inst{4-0}   = Rd;
7937}
7938} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
7939
7940//----------------------------------------------------------------------------
7941// Armv8.6 Matrix Multiply Extension
7942//----------------------------------------------------------------------------
7943
7944class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
7945  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
7946              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
7947                                               (v16i8 V128:$Rn),
7948                                               (v16i8 V128:$Rm)))]> {
7949  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
7950}
7951
7952//----------------------------------------------------------------------------
7953// ARMv8.2-A Dot Product Instructions (Indexed)
7954class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
7955                                      string dst_kind, string lhs_kind, string rhs_kind,
7956                                      RegisterOperand RegType,
7957                                      ValueType AccumType, ValueType InputType,
7958                                      SDPatternOperator OpNode> :
7959        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
7960                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7961        [(set (AccumType RegType:$dst),
7962              (AccumType (OpNode (AccumType RegType:$Rd),
7963                                 (InputType RegType:$Rn),
7964                                 (InputType (bitconvert (AccumType
7965                                    (AArch64duplane32 (v4i32 V128:$Rm),
7966                                        VectorIndexS:$idx)))))))]> {
7967  bits<2> idx;
7968  let Inst{21}    = idx{0};  // L
7969  let Inst{11}    = idx{1};  // H
7970}
7971
7972multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
7973                                       SDPatternOperator OpNode> {
7974  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
7975                                              V64, v2i32, v8i8, OpNode>;
7976  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
7977                                              V128, v4i32, v16i8, OpNode>;
7978}
7979
7980// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7981class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7982                                      string dst_kind, string lhs_kind,
7983                                      string rhs_kind, RegisterOperand RegType,
7984                                      ValueType AccumType, ValueType InputType,
7985                                      SDPatternOperator OpNode> :
7986        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7987                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7988          [(set (AccumType RegType:$dst),
7989                (AccumType (OpNode (AccumType RegType:$Rd),
7990                                   (InputType RegType:$Rn),
7991                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7992                                                VectorIndexH:$idx)))))]> {
7993  // idx = H:L:M
7994  bits<3> idx;
7995  let Inst{11} = idx{2}; // H
7996  let Inst{21} = idx{1}; // L
7997  let Inst{20} = idx{0}; // M
7998}
7999
8000multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8001                                       SDPatternOperator OpNode> {
8002  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8003                                              V64, v2f32, v4f16, OpNode>;
8004  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8005                                              V128, v4f32, v8f16, OpNode>;
8006}
8007
8008multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8009                         SDPatternOperator OpNode> {
8010  let Predicates = [HasNEON, HasFullFP16] in {
8011  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8012                                      V64, V64,
8013                                      V128_lo, VectorIndexH,
8014                                      asm, ".4h", ".4h", ".4h", ".h",
8015    [(set (v4f16 V64:$Rd),
8016        (OpNode (v4f16 V64:$Rn),
8017         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8018    bits<3> idx;
8019    let Inst{11} = idx{2};
8020    let Inst{21} = idx{1};
8021    let Inst{20} = idx{0};
8022  }
8023
8024  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8025                                      V128, V128,
8026                                      V128_lo, VectorIndexH,
8027                                      asm, ".8h", ".8h", ".8h", ".h",
8028    [(set (v8f16 V128:$Rd),
8029        (OpNode (v8f16 V128:$Rn),
8030         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8031    bits<3> idx;
8032    let Inst{11} = idx{2};
8033    let Inst{21} = idx{1};
8034    let Inst{20} = idx{0};
8035  }
8036  } // Predicates = [HasNEON, HasFullFP16]
8037
8038  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8039                                      V64, V64,
8040                                      V128, VectorIndexS,
8041                                      asm, ".2s", ".2s", ".2s", ".s",
8042    [(set (v2f32 V64:$Rd),
8043        (OpNode (v2f32 V64:$Rn),
8044         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8045    bits<2> idx;
8046    let Inst{11} = idx{1};
8047    let Inst{21} = idx{0};
8048  }
8049
8050  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8051                                      V128, V128,
8052                                      V128, VectorIndexS,
8053                                      asm, ".4s", ".4s", ".4s", ".s",
8054    [(set (v4f32 V128:$Rd),
8055        (OpNode (v4f32 V128:$Rn),
8056         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8057    bits<2> idx;
8058    let Inst{11} = idx{1};
8059    let Inst{21} = idx{0};
8060  }
8061
8062  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8063                                      V128, V128,
8064                                      V128, VectorIndexD,
8065                                      asm, ".2d", ".2d", ".2d", ".d",
8066    [(set (v2f64 V128:$Rd),
8067        (OpNode (v2f64 V128:$Rn),
8068         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8069    bits<1> idx;
8070    let Inst{11} = idx{0};
8071    let Inst{21} = 0;
8072  }
8073
8074  let Predicates = [HasNEON, HasFullFP16] in {
8075  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8076                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8077                                      asm, ".h", "", "", ".h",
8078    [(set (f16 FPR16Op:$Rd),
8079          (OpNode (f16 FPR16Op:$Rn),
8080                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8081                                       VectorIndexH:$idx))))]> {
8082    bits<3> idx;
8083    let Inst{11} = idx{2};
8084    let Inst{21} = idx{1};
8085    let Inst{20} = idx{0};
8086  }
8087  } // Predicates = [HasNEON, HasFullFP16]
8088
8089  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8090                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8091                                      asm, ".s", "", "", ".s",
8092    [(set (f32 FPR32Op:$Rd),
8093          (OpNode (f32 FPR32Op:$Rn),
8094                  (f32 (vector_extract (v4f32 V128:$Rm),
8095                                       VectorIndexS:$idx))))]> {
8096    bits<2> idx;
8097    let Inst{11} = idx{1};
8098    let Inst{21} = idx{0};
8099  }
8100
8101  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8102                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8103                                      asm, ".d", "", "", ".d",
8104    [(set (f64 FPR64Op:$Rd),
8105          (OpNode (f64 FPR64Op:$Rn),
8106                  (f64 (vector_extract (v2f64 V128:$Rm),
8107                                       VectorIndexD:$idx))))]> {
8108    bits<1> idx;
8109    let Inst{11} = idx{0};
8110    let Inst{21} = 0;
8111  }
8112}
8113
8114multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8115  let Predicates = [HasNEON, HasFullFP16] in {
8116  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8117  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8118                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8119                                           VectorIndexH:$idx))),
8120            (!cast<Instruction>(INST # "v8i16_indexed")
8121                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8122  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8123                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8124            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8125                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8126
8127  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8128                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8129                                           VectorIndexH:$idx))),
8130            (!cast<Instruction>(INST # "v4i16_indexed")
8131                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8132  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8133                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8134            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8135                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8136
8137  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8138                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8139            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8140                V128_lo:$Rm, VectorIndexH:$idx)>;
8141  } // Predicates = [HasNEON, HasFullFP16]
8142
8143  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8144  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8145                           (AArch64duplane32 (v4f32 V128:$Rm),
8146                                           VectorIndexS:$idx))),
8147            (!cast<Instruction>(INST # v2i32_indexed)
8148                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8149  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8150                           (AArch64dup (f32 FPR32Op:$Rm)))),
8151            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8152                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8153
8154
8155  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8156  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8157                           (AArch64duplane32 (v4f32 V128:$Rm),
8158                                           VectorIndexS:$idx))),
8159            (!cast<Instruction>(INST # "v4i32_indexed")
8160                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8161  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8162                           (AArch64dup (f32 FPR32Op:$Rm)))),
8163            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8164                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8165
8166  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8167  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8168                           (AArch64duplane64 (v2f64 V128:$Rm),
8169                                           VectorIndexD:$idx))),
8170            (!cast<Instruction>(INST # "v2i64_indexed")
8171                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8172  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8173                           (AArch64dup (f64 FPR64Op:$Rm)))),
8174            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8175                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8176
8177  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8178  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8179                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8180            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8181                V128:$Rm, VectorIndexS:$idx)>;
8182
8183  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8184  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8185                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8186            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8187                V128:$Rm, VectorIndexD:$idx)>;
8188}
8189
8190multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8191  let Predicates = [HasNEON, HasFullFP16] in {
8192  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8193                                          V128_lo, VectorIndexH,
8194                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8195    bits<3> idx;
8196    let Inst{11} = idx{2};
8197    let Inst{21} = idx{1};
8198    let Inst{20} = idx{0};
8199  }
8200
8201  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8202                                          V128, V128,
8203                                          V128_lo, VectorIndexH,
8204                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8205    bits<3> idx;
8206    let Inst{11} = idx{2};
8207    let Inst{21} = idx{1};
8208    let Inst{20} = idx{0};
8209  }
8210  } // Predicates = [HasNEON, HasFullFP16]
8211
8212  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8213                                          V128, VectorIndexS,
8214                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8215    bits<2> idx;
8216    let Inst{11} = idx{1};
8217    let Inst{21} = idx{0};
8218  }
8219
8220  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8221                                      V128, V128,
8222                                      V128, VectorIndexS,
8223                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8224    bits<2> idx;
8225    let Inst{11} = idx{1};
8226    let Inst{21} = idx{0};
8227  }
8228
8229  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8230                                      V128, V128,
8231                                      V128, VectorIndexD,
8232                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8233    bits<1> idx;
8234    let Inst{11} = idx{0};
8235    let Inst{21} = 0;
8236  }
8237
8238  let Predicates = [HasNEON, HasFullFP16] in {
8239  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8240                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8241                                      asm, ".h", "", "", ".h", []> {
8242    bits<3> idx;
8243    let Inst{11} = idx{2};
8244    let Inst{21} = idx{1};
8245    let Inst{20} = idx{0};
8246  }
8247  } // Predicates = [HasNEON, HasFullFP16]
8248
8249  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8250                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8251                                      asm, ".s", "", "", ".s", []> {
8252    bits<2> idx;
8253    let Inst{11} = idx{1};
8254    let Inst{21} = idx{0};
8255  }
8256
8257  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8258                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8259                                      asm, ".d", "", "", ".d", []> {
8260    bits<1> idx;
8261    let Inst{11} = idx{0};
8262    let Inst{21} = 0;
8263  }
8264}
8265
8266multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8267                                 SDPatternOperator OpNodeLaneQ> {
8268
8269  def : Pat<(v4i16 (OpNodeLane
8270                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8271                     VectorIndexS32b:$idx)),
8272            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8273              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8274              (UImmS1XForm $idx))>;
8275
8276  def : Pat<(v4i16 (OpNodeLaneQ
8277                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8278                     VectorIndexH32b:$idx)),
8279            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8280              (UImmS1XForm $idx))>;
8281
8282  def : Pat<(v8i16 (OpNodeLane
8283                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8284                     VectorIndexS32b:$idx)),
8285            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8286              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8287              (UImmS1XForm $idx))>;
8288
8289  def : Pat<(v8i16 (OpNodeLaneQ
8290                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8291                     VectorIndexH32b:$idx)),
8292            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8293              (UImmS1XForm $idx))>;
8294
8295  def : Pat<(v2i32 (OpNodeLane
8296                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8297                     VectorIndexD32b:$idx)),
8298            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8299              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8300              (UImmS1XForm $idx))>;
8301
8302  def : Pat<(v2i32 (OpNodeLaneQ
8303                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8304                     VectorIndexS32b:$idx)),
8305            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8306              (UImmS1XForm $idx))>;
8307
8308  def : Pat<(v4i32 (OpNodeLane
8309                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8310                     VectorIndexD32b:$idx)),
8311            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8312              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8313              (UImmS1XForm $idx))>;
8314
8315  def : Pat<(v4i32 (OpNodeLaneQ
8316                     (v4i32 V128:$Rn),
8317                     (v4i32 V128:$Rm),
8318                     VectorIndexS32b:$idx)),
8319            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8320              (UImmS1XForm $idx))>;
8321
8322}
8323
8324multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8325                         SDPatternOperator OpNode> {
8326  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8327                                      V128_lo, VectorIndexH,
8328                                      asm, ".4h", ".4h", ".4h", ".h",
8329    [(set (v4i16 V64:$Rd),
8330        (OpNode (v4i16 V64:$Rn),
8331         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8332    bits<3> idx;
8333    let Inst{11} = idx{2};
8334    let Inst{21} = idx{1};
8335    let Inst{20} = idx{0};
8336  }
8337
8338  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8339                                      V128, V128,
8340                                      V128_lo, VectorIndexH,
8341                                      asm, ".8h", ".8h", ".8h", ".h",
8342    [(set (v8i16 V128:$Rd),
8343       (OpNode (v8i16 V128:$Rn),
8344         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8345    bits<3> idx;
8346    let Inst{11} = idx{2};
8347    let Inst{21} = idx{1};
8348    let Inst{20} = idx{0};
8349  }
8350
8351  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8352                                      V64, V64,
8353                                      V128, VectorIndexS,
8354                                      asm, ".2s", ".2s", ".2s",  ".s",
8355    [(set (v2i32 V64:$Rd),
8356       (OpNode (v2i32 V64:$Rn),
8357          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8358    bits<2> idx;
8359    let Inst{11} = idx{1};
8360    let Inst{21} = idx{0};
8361  }
8362
8363  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8364                                      V128, V128,
8365                                      V128, VectorIndexS,
8366                                      asm, ".4s", ".4s", ".4s", ".s",
8367    [(set (v4i32 V128:$Rd),
8368       (OpNode (v4i32 V128:$Rn),
8369          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8370    bits<2> idx;
8371    let Inst{11} = idx{1};
8372    let Inst{21} = idx{0};
8373  }
8374
8375  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8376                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8377                                      asm, ".h", "", "", ".h", []> {
8378    bits<3> idx;
8379    let Inst{11} = idx{2};
8380    let Inst{21} = idx{1};
8381    let Inst{20} = idx{0};
8382  }
8383
8384  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8385                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8386                                      asm, ".s", "", "", ".s",
8387      [(set (i32 FPR32Op:$Rd),
8388            (OpNode FPR32Op:$Rn,
8389                    (i32 (vector_extract (v4i32 V128:$Rm),
8390                                         VectorIndexS:$idx))))]> {
8391    bits<2> idx;
8392    let Inst{11} = idx{1};
8393    let Inst{21} = idx{0};
8394  }
8395}
8396
8397multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8398                               SDPatternOperator OpNode> {
8399  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8400                                      V64, V64,
8401                                      V128_lo, VectorIndexH,
8402                                      asm, ".4h", ".4h", ".4h", ".h",
8403    [(set (v4i16 V64:$Rd),
8404        (OpNode (v4i16 V64:$Rn),
8405         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8406    bits<3> idx;
8407    let Inst{11} = idx{2};
8408    let Inst{21} = idx{1};
8409    let Inst{20} = idx{0};
8410  }
8411
8412  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8413                                      V128, V128,
8414                                      V128_lo, VectorIndexH,
8415                                      asm, ".8h", ".8h", ".8h", ".h",
8416    [(set (v8i16 V128:$Rd),
8417       (OpNode (v8i16 V128:$Rn),
8418         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8419    bits<3> idx;
8420    let Inst{11} = idx{2};
8421    let Inst{21} = idx{1};
8422    let Inst{20} = idx{0};
8423  }
8424
8425  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8426                                      V64, V64,
8427                                      V128, VectorIndexS,
8428                                      asm, ".2s", ".2s", ".2s", ".s",
8429    [(set (v2i32 V64:$Rd),
8430       (OpNode (v2i32 V64:$Rn),
8431          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8432    bits<2> idx;
8433    let Inst{11} = idx{1};
8434    let Inst{21} = idx{0};
8435  }
8436
8437  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8438                                      V128, V128,
8439                                      V128, VectorIndexS,
8440                                      asm, ".4s", ".4s", ".4s", ".s",
8441    [(set (v4i32 V128:$Rd),
8442       (OpNode (v4i32 V128:$Rn),
8443          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8444    bits<2> idx;
8445    let Inst{11} = idx{1};
8446    let Inst{21} = idx{0};
8447  }
8448}
8449
8450multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8451                                   SDPatternOperator OpNode> {
8452  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8453                                          V128_lo, VectorIndexH,
8454                                          asm, ".4h", ".4h", ".4h", ".h",
8455    [(set (v4i16 V64:$dst),
8456        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8457         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8458    bits<3> idx;
8459    let Inst{11} = idx{2};
8460    let Inst{21} = idx{1};
8461    let Inst{20} = idx{0};
8462  }
8463
8464  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8465                                      V128, V128,
8466                                      V128_lo, VectorIndexH,
8467                                      asm, ".8h", ".8h", ".8h", ".h",
8468    [(set (v8i16 V128:$dst),
8469       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8470         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8471    bits<3> idx;
8472    let Inst{11} = idx{2};
8473    let Inst{21} = idx{1};
8474    let Inst{20} = idx{0};
8475  }
8476
8477  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8478                                      V64, V64,
8479                                      V128, VectorIndexS,
8480                                      asm, ".2s", ".2s", ".2s", ".s",
8481    [(set (v2i32 V64:$dst),
8482       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8483          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8484    bits<2> idx;
8485    let Inst{11} = idx{1};
8486    let Inst{21} = idx{0};
8487  }
8488
8489  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8490                                      V128, V128,
8491                                      V128, VectorIndexS,
8492                                      asm, ".4s", ".4s", ".4s", ".s",
8493    [(set (v4i32 V128:$dst),
8494       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8495          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8496    bits<2> idx;
8497    let Inst{11} = idx{1};
8498    let Inst{21} = idx{0};
8499  }
8500}
8501
8502multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8503                             SDPatternOperator OpNode> {
8504  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8505                                      V128, V64,
8506                                      V128_lo, VectorIndexH,
8507                                      asm, ".4s", ".4s", ".4h", ".h",
8508    [(set (v4i32 V128:$Rd),
8509        (OpNode (v4i16 V64:$Rn),
8510         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8511    bits<3> idx;
8512    let Inst{11} = idx{2};
8513    let Inst{21} = idx{1};
8514    let Inst{20} = idx{0};
8515  }
8516
8517  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8518                                      V128, V128,
8519                                      V128_lo, VectorIndexH,
8520                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8521    [(set (v4i32 V128:$Rd),
8522          (OpNode (extract_high_v8i16 V128:$Rn),
8523                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8524                                                      VectorIndexH:$idx))))]> {
8525
8526    bits<3> idx;
8527    let Inst{11} = idx{2};
8528    let Inst{21} = idx{1};
8529    let Inst{20} = idx{0};
8530  }
8531
8532  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8533                                      V128, V64,
8534                                      V128, VectorIndexS,
8535                                      asm, ".2d", ".2d", ".2s", ".s",
8536    [(set (v2i64 V128:$Rd),
8537        (OpNode (v2i32 V64:$Rn),
8538         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8539    bits<2> idx;
8540    let Inst{11} = idx{1};
8541    let Inst{21} = idx{0};
8542  }
8543
8544  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8545                                      V128, V128,
8546                                      V128, VectorIndexS,
8547                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8548    [(set (v2i64 V128:$Rd),
8549          (OpNode (extract_high_v4i32 V128:$Rn),
8550                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8551                                                      VectorIndexS:$idx))))]> {
8552    bits<2> idx;
8553    let Inst{11} = idx{1};
8554    let Inst{21} = idx{0};
8555  }
8556
8557  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8558                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8559                                      asm, ".h", "", "", ".h", []> {
8560    bits<3> idx;
8561    let Inst{11} = idx{2};
8562    let Inst{21} = idx{1};
8563    let Inst{20} = idx{0};
8564  }
8565
8566  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8567                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8568                                      asm, ".s", "", "", ".s", []> {
8569    bits<2> idx;
8570    let Inst{11} = idx{1};
8571    let Inst{21} = idx{0};
8572  }
8573}
8574
8575multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8576                                       SDPatternOperator Accum> {
8577  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8578                                      V128, V64,
8579                                      V128_lo, VectorIndexH,
8580                                      asm, ".4s", ".4s", ".4h", ".h",
8581    [(set (v4i32 V128:$dst),
8582          (Accum (v4i32 V128:$Rd),
8583                 (v4i32 (int_aarch64_neon_sqdmull
8584                             (v4i16 V64:$Rn),
8585                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8586                                                    VectorIndexH:$idx))))))]> {
8587    bits<3> idx;
8588    let Inst{11} = idx{2};
8589    let Inst{21} = idx{1};
8590    let Inst{20} = idx{0};
8591  }
8592
8593  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8594  // intermediate EXTRACT_SUBREG would be untyped.
8595  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8596                (i32 (vector_extract (v4i32
8597                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8598                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8599                                                    VectorIndexH:$idx)))),
8600                         (i64 0))))),
8601            (EXTRACT_SUBREG
8602                (!cast<Instruction>(NAME # v4i16_indexed)
8603                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8604                    V128_lo:$Rm, VectorIndexH:$idx),
8605                ssub)>;
8606
8607  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8608                                      V128, V128,
8609                                      V128_lo, VectorIndexH,
8610                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8611    [(set (v4i32 V128:$dst),
8612          (Accum (v4i32 V128:$Rd),
8613                 (v4i32 (int_aarch64_neon_sqdmull
8614                            (extract_high_v8i16 V128:$Rn),
8615                            (extract_high_v8i16
8616                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8617                                                VectorIndexH:$idx))))))]> {
8618    bits<3> idx;
8619    let Inst{11} = idx{2};
8620    let Inst{21} = idx{1};
8621    let Inst{20} = idx{0};
8622  }
8623
8624  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8625                                      V128, V64,
8626                                      V128, VectorIndexS,
8627                                      asm, ".2d", ".2d", ".2s", ".s",
8628    [(set (v2i64 V128:$dst),
8629        (Accum (v2i64 V128:$Rd),
8630               (v2i64 (int_aarch64_neon_sqdmull
8631                          (v2i32 V64:$Rn),
8632                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8633                                                 VectorIndexS:$idx))))))]> {
8634    bits<2> idx;
8635    let Inst{11} = idx{1};
8636    let Inst{21} = idx{0};
8637  }
8638
8639  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8640                                      V128, V128,
8641                                      V128, VectorIndexS,
8642                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8643    [(set (v2i64 V128:$dst),
8644          (Accum (v2i64 V128:$Rd),
8645                 (v2i64 (int_aarch64_neon_sqdmull
8646                            (extract_high_v4i32 V128:$Rn),
8647                            (extract_high_v4i32
8648                                (AArch64duplane32 (v4i32 V128:$Rm),
8649                                                VectorIndexS:$idx))))))]> {
8650    bits<2> idx;
8651    let Inst{11} = idx{1};
8652    let Inst{21} = idx{0};
8653  }
8654
8655  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8656                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8657                                      asm, ".h", "", "", ".h", []> {
8658    bits<3> idx;
8659    let Inst{11} = idx{2};
8660    let Inst{21} = idx{1};
8661    let Inst{20} = idx{0};
8662  }
8663
8664
8665  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8666                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8667                                      asm, ".s", "", "", ".s",
8668    [(set (i64 FPR64Op:$dst),
8669          (Accum (i64 FPR64Op:$Rd),
8670                 (i64 (int_aarch64_neon_sqdmulls_scalar
8671                            (i32 FPR32Op:$Rn),
8672                            (i32 (vector_extract (v4i32 V128:$Rm),
8673                                                 VectorIndexS:$idx))))))]> {
8674
8675    bits<2> idx;
8676    let Inst{11} = idx{1};
8677    let Inst{21} = idx{0};
8678  }
8679}
8680
8681multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8682                                   SDPatternOperator OpNode> {
8683  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8684  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8685                                      V128, V64,
8686                                      V128_lo, VectorIndexH,
8687                                      asm, ".4s", ".4s", ".4h", ".h",
8688    [(set (v4i32 V128:$Rd),
8689        (OpNode (v4i16 V64:$Rn),
8690         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8691    bits<3> idx;
8692    let Inst{11} = idx{2};
8693    let Inst{21} = idx{1};
8694    let Inst{20} = idx{0};
8695  }
8696
8697  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8698                                      V128, V128,
8699                                      V128_lo, VectorIndexH,
8700                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8701    [(set (v4i32 V128:$Rd),
8702          (OpNode (extract_high_v8i16 V128:$Rn),
8703                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8704                                                      VectorIndexH:$idx))))]> {
8705
8706    bits<3> idx;
8707    let Inst{11} = idx{2};
8708    let Inst{21} = idx{1};
8709    let Inst{20} = idx{0};
8710  }
8711
8712  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8713                                      V128, V64,
8714                                      V128, VectorIndexS,
8715                                      asm, ".2d", ".2d", ".2s", ".s",
8716    [(set (v2i64 V128:$Rd),
8717        (OpNode (v2i32 V64:$Rn),
8718         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8719    bits<2> idx;
8720    let Inst{11} = idx{1};
8721    let Inst{21} = idx{0};
8722  }
8723
8724  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8725                                      V128, V128,
8726                                      V128, VectorIndexS,
8727                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8728    [(set (v2i64 V128:$Rd),
8729          (OpNode (extract_high_v4i32 V128:$Rn),
8730                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8731                                                      VectorIndexS:$idx))))]> {
8732    bits<2> idx;
8733    let Inst{11} = idx{1};
8734    let Inst{21} = idx{0};
8735  }
8736  }
8737}
8738
8739multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8740                                       SDPatternOperator OpNode> {
8741  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8742  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8743                                      V128, V64,
8744                                      V128_lo, VectorIndexH,
8745                                      asm, ".4s", ".4s", ".4h", ".h",
8746    [(set (v4i32 V128:$dst),
8747        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8748         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8749    bits<3> idx;
8750    let Inst{11} = idx{2};
8751    let Inst{21} = idx{1};
8752    let Inst{20} = idx{0};
8753  }
8754
8755  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8756                                      V128, V128,
8757                                      V128_lo, VectorIndexH,
8758                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8759    [(set (v4i32 V128:$dst),
8760          (OpNode (v4i32 V128:$Rd),
8761                  (extract_high_v8i16 V128:$Rn),
8762                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8763                                                      VectorIndexH:$idx))))]> {
8764    bits<3> idx;
8765    let Inst{11} = idx{2};
8766    let Inst{21} = idx{1};
8767    let Inst{20} = idx{0};
8768  }
8769
8770  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8771                                      V128, V64,
8772                                      V128, VectorIndexS,
8773                                      asm, ".2d", ".2d", ".2s", ".s",
8774    [(set (v2i64 V128:$dst),
8775        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8776         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8777    bits<2> idx;
8778    let Inst{11} = idx{1};
8779    let Inst{21} = idx{0};
8780  }
8781
8782  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8783                                      V128, V128,
8784                                      V128, VectorIndexS,
8785                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8786    [(set (v2i64 V128:$dst),
8787          (OpNode (v2i64 V128:$Rd),
8788                  (extract_high_v4i32 V128:$Rn),
8789                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8790                                                      VectorIndexS:$idx))))]> {
8791    bits<2> idx;
8792    let Inst{11} = idx{1};
8793    let Inst{21} = idx{0};
8794  }
8795  }
8796}
8797
8798//----------------------------------------------------------------------------
8799// AdvSIMD scalar shift by immediate
8800//----------------------------------------------------------------------------
8801
8802let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8803class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8804                     RegisterClass regtype1, RegisterClass regtype2,
8805                     Operand immtype, string asm, list<dag> pattern>
8806  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8807      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8808    Sched<[WriteV]> {
8809  bits<5> Rd;
8810  bits<5> Rn;
8811  bits<7> imm;
8812  let Inst{31-30} = 0b01;
8813  let Inst{29}    = U;
8814  let Inst{28-23} = 0b111110;
8815  let Inst{22-16} = fixed_imm;
8816  let Inst{15-11} = opc;
8817  let Inst{10}    = 1;
8818  let Inst{9-5} = Rn;
8819  let Inst{4-0} = Rd;
8820}
8821
8822let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8823class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8824                     RegisterClass regtype1, RegisterClass regtype2,
8825                     Operand immtype, string asm, list<dag> pattern>
8826  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8827      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8828    Sched<[WriteV]> {
8829  bits<5> Rd;
8830  bits<5> Rn;
8831  bits<7> imm;
8832  let Inst{31-30} = 0b01;
8833  let Inst{29}    = U;
8834  let Inst{28-23} = 0b111110;
8835  let Inst{22-16} = fixed_imm;
8836  let Inst{15-11} = opc;
8837  let Inst{10}    = 1;
8838  let Inst{9-5} = Rn;
8839  let Inst{4-0} = Rd;
8840}
8841
8842
8843multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8844  let Predicates = [HasNEON, HasFullFP16] in {
8845  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8846                              FPR16, FPR16, vecshiftR16, asm, []> {
8847    let Inst{19-16} = imm{3-0};
8848  }
8849  } // Predicates = [HasNEON, HasFullFP16]
8850  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8851                              FPR32, FPR32, vecshiftR32, asm, []> {
8852    let Inst{20-16} = imm{4-0};
8853  }
8854  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8855                              FPR64, FPR64, vecshiftR64, asm, []> {
8856    let Inst{21-16} = imm{5-0};
8857  }
8858}
8859
8860multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8861                             SDPatternOperator OpNode> {
8862  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8863                              FPR64, FPR64, vecshiftR64, asm,
8864  [(set (i64 FPR64:$Rd),
8865     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8866    let Inst{21-16} = imm{5-0};
8867  }
8868
8869  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8870            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8871}
8872
8873multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8874                                 SDPatternOperator OpNode = null_frag> {
8875  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8876                              FPR64, FPR64, vecshiftR64, asm,
8877  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8878                                                   (i32 vecshiftR64:$imm)))]> {
8879    let Inst{21-16} = imm{5-0};
8880  }
8881
8882  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8883                           (i32 vecshiftR64:$imm))),
8884            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8885                                            vecshiftR64:$imm)>;
8886}
8887
8888multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8889                             SDPatternOperator OpNode> {
8890  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8891                              FPR64, FPR64, vecshiftL64, asm,
8892    [(set (v1i64 FPR64:$Rd),
8893       (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8894    let Inst{21-16} = imm{5-0};
8895  }
8896}
8897
8898let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8899multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8900  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8901                              FPR64, FPR64, vecshiftL64, asm, []> {
8902    let Inst{21-16} = imm{5-0};
8903  }
8904}
8905
8906let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8907multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8908                               SDPatternOperator OpNode = null_frag> {
8909  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8910                              FPR8, FPR16, vecshiftR8, asm, []> {
8911    let Inst{18-16} = imm{2-0};
8912  }
8913
8914  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8915                              FPR16, FPR32, vecshiftR16, asm, []> {
8916    let Inst{19-16} = imm{3-0};
8917  }
8918
8919  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8920                              FPR32, FPR64, vecshiftR32, asm,
8921    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8922    let Inst{20-16} = imm{4-0};
8923  }
8924}
8925
8926multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8927                                SDPatternOperator OpNode> {
8928  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8929                              FPR8, FPR8, vecshiftL8, asm, []> {
8930    let Inst{18-16} = imm{2-0};
8931  }
8932
8933  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8934                              FPR16, FPR16, vecshiftL16, asm, []> {
8935    let Inst{19-16} = imm{3-0};
8936  }
8937
8938  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8939                              FPR32, FPR32, vecshiftL32, asm,
8940    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8941    let Inst{20-16} = imm{4-0};
8942  }
8943
8944  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8945                              FPR64, FPR64, vecshiftL64, asm,
8946    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8947    let Inst{21-16} = imm{5-0};
8948  }
8949
8950  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8951            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8952}
8953
8954multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8955  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8956                              FPR8, FPR8, vecshiftR8, asm, []> {
8957    let Inst{18-16} = imm{2-0};
8958  }
8959
8960  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8961                              FPR16, FPR16, vecshiftR16, asm, []> {
8962    let Inst{19-16} = imm{3-0};
8963  }
8964
8965  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8966                              FPR32, FPR32, vecshiftR32, asm, []> {
8967    let Inst{20-16} = imm{4-0};
8968  }
8969
8970  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8971                              FPR64, FPR64, vecshiftR64, asm, []> {
8972    let Inst{21-16} = imm{5-0};
8973  }
8974}
8975
8976//----------------------------------------------------------------------------
8977// AdvSIMD vector x indexed element
8978//----------------------------------------------------------------------------
8979
8980let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8981class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8982                     RegisterOperand dst_reg, RegisterOperand src_reg,
8983                     Operand immtype,
8984                     string asm, string dst_kind, string src_kind,
8985                     list<dag> pattern>
8986  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8987      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8988           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8989    Sched<[WriteV]> {
8990  bits<5> Rd;
8991  bits<5> Rn;
8992  let Inst{31}    = 0;
8993  let Inst{30}    = Q;
8994  let Inst{29}    = U;
8995  let Inst{28-23} = 0b011110;
8996  let Inst{22-16} = fixed_imm;
8997  let Inst{15-11} = opc;
8998  let Inst{10}    = 1;
8999  let Inst{9-5}   = Rn;
9000  let Inst{4-0}   = Rd;
9001}
9002
9003let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9004class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9005                     RegisterOperand vectype1, RegisterOperand vectype2,
9006                     Operand immtype,
9007                     string asm, string dst_kind, string src_kind,
9008                     list<dag> pattern>
9009  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9010      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9011           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9012    Sched<[WriteV]> {
9013  bits<5> Rd;
9014  bits<5> Rn;
9015  let Inst{31}    = 0;
9016  let Inst{30}    = Q;
9017  let Inst{29}    = U;
9018  let Inst{28-23} = 0b011110;
9019  let Inst{22-16} = fixed_imm;
9020  let Inst{15-11} = opc;
9021  let Inst{10}    = 1;
9022  let Inst{9-5}   = Rn;
9023  let Inst{4-0}   = Rd;
9024}
9025
9026multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9027                              Intrinsic OpNode> {
9028  let Predicates = [HasNEON, HasFullFP16] in {
9029  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9030                                  V64, V64, vecshiftR16,
9031                                  asm, ".4h", ".4h",
9032      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9033    bits<4> imm;
9034    let Inst{19-16} = imm;
9035  }
9036
9037  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9038                                  V128, V128, vecshiftR16,
9039                                  asm, ".8h", ".8h",
9040      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9041    bits<4> imm;
9042    let Inst{19-16} = imm;
9043  }
9044  } // Predicates = [HasNEON, HasFullFP16]
9045  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9046                                  V64, V64, vecshiftR32,
9047                                  asm, ".2s", ".2s",
9048      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9049    bits<5> imm;
9050    let Inst{20-16} = imm;
9051  }
9052
9053  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9054                                  V128, V128, vecshiftR32,
9055                                  asm, ".4s", ".4s",
9056      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9057    bits<5> imm;
9058    let Inst{20-16} = imm;
9059  }
9060
9061  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9062                                  V128, V128, vecshiftR64,
9063                                  asm, ".2d", ".2d",
9064      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9065    bits<6> imm;
9066    let Inst{21-16} = imm;
9067  }
9068}
9069
9070multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9071                                  Intrinsic OpNode> {
9072  let Predicates = [HasNEON, HasFullFP16] in {
9073  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9074                                  V64, V64, vecshiftR16,
9075                                  asm, ".4h", ".4h",
9076      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9077    bits<4> imm;
9078    let Inst{19-16} = imm;
9079  }
9080
9081  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9082                                  V128, V128, vecshiftR16,
9083                                  asm, ".8h", ".8h",
9084      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9085    bits<4> imm;
9086    let Inst{19-16} = imm;
9087  }
9088  } // Predicates = [HasNEON, HasFullFP16]
9089
9090  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9091                                  V64, V64, vecshiftR32,
9092                                  asm, ".2s", ".2s",
9093      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9094    bits<5> imm;
9095    let Inst{20-16} = imm;
9096  }
9097
9098  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9099                                  V128, V128, vecshiftR32,
9100                                  asm, ".4s", ".4s",
9101      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9102    bits<5> imm;
9103    let Inst{20-16} = imm;
9104  }
9105
9106  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9107                                  V128, V128, vecshiftR64,
9108                                  asm, ".2d", ".2d",
9109      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9110    bits<6> imm;
9111    let Inst{21-16} = imm;
9112  }
9113}
9114
9115multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9116                                     SDPatternOperator OpNode> {
9117  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9118                                  V64, V128, vecshiftR16Narrow,
9119                                  asm, ".8b", ".8h",
9120      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9121    bits<3> imm;
9122    let Inst{18-16} = imm;
9123  }
9124
9125  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9126                                  V128, V128, vecshiftR16Narrow,
9127                                  asm#"2", ".16b", ".8h", []> {
9128    bits<3> imm;
9129    let Inst{18-16} = imm;
9130    let hasSideEffects = 0;
9131  }
9132
9133  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9134                                  V64, V128, vecshiftR32Narrow,
9135                                  asm, ".4h", ".4s",
9136      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9137    bits<4> imm;
9138    let Inst{19-16} = imm;
9139  }
9140
9141  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9142                                  V128, V128, vecshiftR32Narrow,
9143                                  asm#"2", ".8h", ".4s", []> {
9144    bits<4> imm;
9145    let Inst{19-16} = imm;
9146    let hasSideEffects = 0;
9147  }
9148
9149  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9150                                  V64, V128, vecshiftR64Narrow,
9151                                  asm, ".2s", ".2d",
9152      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9153    bits<5> imm;
9154    let Inst{20-16} = imm;
9155  }
9156
9157  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9158                                  V128, V128, vecshiftR64Narrow,
9159                                  asm#"2", ".4s", ".2d", []> {
9160    bits<5> imm;
9161    let Inst{20-16} = imm;
9162    let hasSideEffects = 0;
9163  }
9164
9165  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9166  // themselves, so put them here instead.
9167
9168  // Patterns involving what's effectively an insert high and a normal
9169  // intrinsic, represented by CONCAT_VECTORS.
9170  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9171                                                   vecshiftR16Narrow:$imm)),
9172            (!cast<Instruction>(NAME # "v16i8_shift")
9173                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9174                V128:$Rn, vecshiftR16Narrow:$imm)>;
9175  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9176                                                     vecshiftR32Narrow:$imm)),
9177            (!cast<Instruction>(NAME # "v8i16_shift")
9178                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9179                V128:$Rn, vecshiftR32Narrow:$imm)>;
9180  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9181                                                     vecshiftR64Narrow:$imm)),
9182            (!cast<Instruction>(NAME # "v4i32_shift")
9183                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9184                V128:$Rn, vecshiftR64Narrow:$imm)>;
9185}
9186
9187multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9188                                SDPatternOperator OpNode> {
9189  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9190                                  V64, V64, vecshiftL8,
9191                                  asm, ".8b", ".8b",
9192                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9193                       (i32 vecshiftL8:$imm)))]> {
9194    bits<3> imm;
9195    let Inst{18-16} = imm;
9196  }
9197
9198  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9199                                  V128, V128, vecshiftL8,
9200                                  asm, ".16b", ".16b",
9201             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9202                   (i32 vecshiftL8:$imm)))]> {
9203    bits<3> imm;
9204    let Inst{18-16} = imm;
9205  }
9206
9207  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9208                                  V64, V64, vecshiftL16,
9209                                  asm, ".4h", ".4h",
9210              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9211                    (i32 vecshiftL16:$imm)))]> {
9212    bits<4> imm;
9213    let Inst{19-16} = imm;
9214  }
9215
9216  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9217                                  V128, V128, vecshiftL16,
9218                                  asm, ".8h", ".8h",
9219            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9220                  (i32 vecshiftL16:$imm)))]> {
9221    bits<4> imm;
9222    let Inst{19-16} = imm;
9223  }
9224
9225  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9226                                  V64, V64, vecshiftL32,
9227                                  asm, ".2s", ".2s",
9228              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9229                    (i32 vecshiftL32:$imm)))]> {
9230    bits<5> imm;
9231    let Inst{20-16} = imm;
9232  }
9233
9234  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9235                                  V128, V128, vecshiftL32,
9236                                  asm, ".4s", ".4s",
9237            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9238                  (i32 vecshiftL32:$imm)))]> {
9239    bits<5> imm;
9240    let Inst{20-16} = imm;
9241  }
9242
9243  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9244                                  V128, V128, vecshiftL64,
9245                                  asm, ".2d", ".2d",
9246            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9247                  (i32 vecshiftL64:$imm)))]> {
9248    bits<6> imm;
9249    let Inst{21-16} = imm;
9250  }
9251}
9252
9253multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9254                                SDPatternOperator OpNode> {
9255  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9256                                  V64, V64, vecshiftR8,
9257                                  asm, ".8b", ".8b",
9258                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9259                       (i32 vecshiftR8:$imm)))]> {
9260    bits<3> imm;
9261    let Inst{18-16} = imm;
9262  }
9263
9264  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9265                                  V128, V128, vecshiftR8,
9266                                  asm, ".16b", ".16b",
9267             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9268                   (i32 vecshiftR8:$imm)))]> {
9269    bits<3> imm;
9270    let Inst{18-16} = imm;
9271  }
9272
9273  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9274                                  V64, V64, vecshiftR16,
9275                                  asm, ".4h", ".4h",
9276              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9277                    (i32 vecshiftR16:$imm)))]> {
9278    bits<4> imm;
9279    let Inst{19-16} = imm;
9280  }
9281
9282  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9283                                  V128, V128, vecshiftR16,
9284                                  asm, ".8h", ".8h",
9285            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9286                  (i32 vecshiftR16:$imm)))]> {
9287    bits<4> imm;
9288    let Inst{19-16} = imm;
9289  }
9290
9291  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9292                                  V64, V64, vecshiftR32,
9293                                  asm, ".2s", ".2s",
9294              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9295                    (i32 vecshiftR32:$imm)))]> {
9296    bits<5> imm;
9297    let Inst{20-16} = imm;
9298  }
9299
9300  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9301                                  V128, V128, vecshiftR32,
9302                                  asm, ".4s", ".4s",
9303            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9304                  (i32 vecshiftR32:$imm)))]> {
9305    bits<5> imm;
9306    let Inst{20-16} = imm;
9307  }
9308
9309  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9310                                  V128, V128, vecshiftR64,
9311                                  asm, ".2d", ".2d",
9312            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9313                  (i32 vecshiftR64:$imm)))]> {
9314    bits<6> imm;
9315    let Inst{21-16} = imm;
9316  }
9317}
9318
9319let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9320multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9321                                    SDPatternOperator OpNode = null_frag> {
9322  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9323                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9324                 [(set (v8i8 V64:$dst),
9325                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9326                           (i32 vecshiftR8:$imm)))]> {
9327    bits<3> imm;
9328    let Inst{18-16} = imm;
9329  }
9330
9331  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9332                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9333             [(set (v16i8 V128:$dst),
9334               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9335                       (i32 vecshiftR8:$imm)))]> {
9336    bits<3> imm;
9337    let Inst{18-16} = imm;
9338  }
9339
9340  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9341                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9342              [(set (v4i16 V64:$dst),
9343                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9344                        (i32 vecshiftR16:$imm)))]> {
9345    bits<4> imm;
9346    let Inst{19-16} = imm;
9347  }
9348
9349  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9350                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9351            [(set (v8i16 V128:$dst),
9352              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9353                      (i32 vecshiftR16:$imm)))]> {
9354    bits<4> imm;
9355    let Inst{19-16} = imm;
9356  }
9357
9358  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9359                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9360              [(set (v2i32 V64:$dst),
9361                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9362                        (i32 vecshiftR32:$imm)))]> {
9363    bits<5> imm;
9364    let Inst{20-16} = imm;
9365  }
9366
9367  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9368                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9369            [(set (v4i32 V128:$dst),
9370              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9371                      (i32 vecshiftR32:$imm)))]> {
9372    bits<5> imm;
9373    let Inst{20-16} = imm;
9374  }
9375
9376  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9377                                  V128, V128, vecshiftR64,
9378                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9379              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9380                      (i32 vecshiftR64:$imm)))]> {
9381    bits<6> imm;
9382    let Inst{21-16} = imm;
9383  }
9384}
9385
9386multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9387                                    SDPatternOperator OpNode = null_frag> {
9388  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9389                                  V64, V64, vecshiftL8,
9390                                  asm, ".8b", ".8b",
9391                    [(set (v8i8 V64:$dst),
9392                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9393                                  (i32 vecshiftL8:$imm)))]> {
9394    bits<3> imm;
9395    let Inst{18-16} = imm;
9396  }
9397
9398  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9399                                  V128, V128, vecshiftL8,
9400                                  asm, ".16b", ".16b",
9401                    [(set (v16i8 V128:$dst),
9402                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9403                                  (i32 vecshiftL8:$imm)))]> {
9404    bits<3> imm;
9405    let Inst{18-16} = imm;
9406  }
9407
9408  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9409                                  V64, V64, vecshiftL16,
9410                                  asm, ".4h", ".4h",
9411                    [(set (v4i16 V64:$dst),
9412                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9413                                   (i32 vecshiftL16:$imm)))]> {
9414    bits<4> imm;
9415    let Inst{19-16} = imm;
9416  }
9417
9418  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9419                                  V128, V128, vecshiftL16,
9420                                  asm, ".8h", ".8h",
9421                    [(set (v8i16 V128:$dst),
9422                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9423                                  (i32 vecshiftL16:$imm)))]> {
9424    bits<4> imm;
9425    let Inst{19-16} = imm;
9426  }
9427
9428  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9429                                  V64, V64, vecshiftL32,
9430                                  asm, ".2s", ".2s",
9431                    [(set (v2i32 V64:$dst),
9432                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9433                                  (i32 vecshiftL32:$imm)))]> {
9434    bits<5> imm;
9435    let Inst{20-16} = imm;
9436  }
9437
9438  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9439                                  V128, V128, vecshiftL32,
9440                                  asm, ".4s", ".4s",
9441                    [(set (v4i32 V128:$dst),
9442                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9443                                  (i32 vecshiftL32:$imm)))]> {
9444    bits<5> imm;
9445    let Inst{20-16} = imm;
9446  }
9447
9448  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9449                                  V128, V128, vecshiftL64,
9450                                  asm, ".2d", ".2d",
9451                    [(set (v2i64 V128:$dst),
9452                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9453                                  (i32 vecshiftL64:$imm)))]> {
9454    bits<6> imm;
9455    let Inst{21-16} = imm;
9456  }
9457}
9458
9459multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9460                                   SDPatternOperator OpNode> {
9461  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9462                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9463      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9464    bits<3> imm;
9465    let Inst{18-16} = imm;
9466  }
9467
9468  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9469                                  V128, V128, vecshiftL8,
9470                                  asm#"2", ".8h", ".16b",
9471      [(set (v8i16 V128:$Rd),
9472            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9473    bits<3> imm;
9474    let Inst{18-16} = imm;
9475  }
9476
9477  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9478                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9479      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9480    bits<4> imm;
9481    let Inst{19-16} = imm;
9482  }
9483
9484  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9485                                  V128, V128, vecshiftL16,
9486                                  asm#"2", ".4s", ".8h",
9487      [(set (v4i32 V128:$Rd),
9488            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9489
9490    bits<4> imm;
9491    let Inst{19-16} = imm;
9492  }
9493
9494  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9495                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9496      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9497    bits<5> imm;
9498    let Inst{20-16} = imm;
9499  }
9500
9501  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9502                                  V128, V128, vecshiftL32,
9503                                  asm#"2", ".2d", ".4s",
9504      [(set (v2i64 V128:$Rd),
9505            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9506    bits<5> imm;
9507    let Inst{20-16} = imm;
9508  }
9509}
9510
9511
9512//---
9513// Vector load/store
9514//---
9515// SIMD ldX/stX no-index memory references don't allow the optional
9516// ", #0" constant and handle post-indexing explicitly, so we use
9517// a more specialized parse method for them. Otherwise, it's the same as
9518// the general GPR64sp handling.
9519
9520class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9521                   string asm, dag oops, dag iops, list<dag> pattern>
9522  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9523  bits<5> Vt;
9524  bits<5> Rn;
9525  let Inst{31} = 0;
9526  let Inst{30} = Q;
9527  let Inst{29-23} = 0b0011000;
9528  let Inst{22} = L;
9529  let Inst{21-16} = 0b000000;
9530  let Inst{15-12} = opcode;
9531  let Inst{11-10} = size;
9532  let Inst{9-5} = Rn;
9533  let Inst{4-0} = Vt;
9534}
9535
9536class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9537                       string asm, dag oops, dag iops>
9538  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9539  bits<5> Vt;
9540  bits<5> Rn;
9541  bits<5> Xm;
9542  let Inst{31} = 0;
9543  let Inst{30} = Q;
9544  let Inst{29-23} = 0b0011001;
9545  let Inst{22} = L;
9546  let Inst{21} = 0;
9547  let Inst{20-16} = Xm;
9548  let Inst{15-12} = opcode;
9549  let Inst{11-10} = size;
9550  let Inst{9-5} = Rn;
9551  let Inst{4-0} = Vt;
9552}
9553
9554// The immediate form of AdvSIMD post-indexed addressing is encoded with
9555// register post-index addressing from the zero register.
9556multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9557                           int Offset, int Size> {
9558  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9559  //      "ld1\t$Vt, [$Rn], #16"
9560  // may get mapped to
9561  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9562  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9563                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9564                      GPR64sp:$Rn,
9565                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9566                      XZR), 1>;
9567
9568  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9569  //      "ld1.8b\t$Vt, [$Rn], #16"
9570  // may get mapped to
9571  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9572  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9573                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9574                      GPR64sp:$Rn,
9575                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9576                      XZR), 0>;
9577
9578  // E.g. "ld1.8b { v0, v1 }, [x1]"
9579  //      "ld1\t$Vt, [$Rn]"
9580  // may get mapped to
9581  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9582  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9583                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9584                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9585                      GPR64sp:$Rn), 0>;
9586
9587  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9588  //      "ld1\t$Vt, [$Rn], $Xm"
9589  // may get mapped to
9590  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9591  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9592                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9593                      GPR64sp:$Rn,
9594                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9595                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9596}
9597
9598multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9599                       int Offset128, int Offset64, bits<4> opcode> {
9600  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9601    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9602                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9603                           (ins GPR64sp:$Rn), []>;
9604    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9605                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9606                           (ins GPR64sp:$Rn), []>;
9607    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9608                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9609                           (ins GPR64sp:$Rn), []>;
9610    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9611                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9612                           (ins GPR64sp:$Rn), []>;
9613    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9614                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9615                           (ins GPR64sp:$Rn), []>;
9616    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9617                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9618                           (ins GPR64sp:$Rn), []>;
9619    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9620                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9621                           (ins GPR64sp:$Rn), []>;
9622
9623
9624    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9625                       (outs GPR64sp:$wback,
9626                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9627                       (ins GPR64sp:$Rn,
9628                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9629    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9630                       (outs GPR64sp:$wback,
9631                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9632                       (ins GPR64sp:$Rn,
9633                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9634    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9635                       (outs GPR64sp:$wback,
9636                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9637                       (ins GPR64sp:$Rn,
9638                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9639    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9640                       (outs GPR64sp:$wback,
9641                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9642                       (ins GPR64sp:$Rn,
9643                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9644    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9645                       (outs GPR64sp:$wback,
9646                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9647                       (ins GPR64sp:$Rn,
9648                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9649    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9650                       (outs GPR64sp:$wback,
9651                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9652                       (ins GPR64sp:$Rn,
9653                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9654    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9655                       (outs GPR64sp:$wback,
9656                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9657                       (ins GPR64sp:$Rn,
9658                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9659  }
9660
9661  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9662  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9663  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9664  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9665  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9666  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9667  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9668}
9669
9670// Only ld1/st1 has a v1d version.
9671multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9672                       int Offset128, int Offset64, bits<4> opcode> {
9673  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9674    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9675                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9676                                 GPR64sp:$Rn), []>;
9677    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9678                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9679                                GPR64sp:$Rn), []>;
9680    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9681                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9682                                GPR64sp:$Rn), []>;
9683    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9684                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9685                                GPR64sp:$Rn), []>;
9686    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9687                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9688                                GPR64sp:$Rn), []>;
9689    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9690                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9691                                GPR64sp:$Rn), []>;
9692    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9693                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9694                                GPR64sp:$Rn), []>;
9695
9696    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9697                       (outs GPR64sp:$wback),
9698                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9699                            GPR64sp:$Rn,
9700                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9701    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9702                       (outs GPR64sp:$wback),
9703                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9704                            GPR64sp:$Rn,
9705                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9706    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9707                       (outs GPR64sp:$wback),
9708                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9709                            GPR64sp:$Rn,
9710                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9711    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9712                       (outs GPR64sp:$wback),
9713                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9714                            GPR64sp:$Rn,
9715                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9716    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9717                       (outs GPR64sp:$wback),
9718                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9719                            GPR64sp:$Rn,
9720                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9721    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9722                       (outs GPR64sp:$wback),
9723                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9724                            GPR64sp:$Rn,
9725                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9726    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9727                       (outs GPR64sp:$wback),
9728                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9729                            GPR64sp:$Rn,
9730                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9731  }
9732
9733  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9734  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9735  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9736  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9737  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9738  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9739  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9740}
9741
9742multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9743                       int Offset128, int Offset64, bits<4> opcode>
9744  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9745
9746  // LD1 instructions have extra "1d" variants.
9747  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9748    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9749                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9750                           (ins GPR64sp:$Rn), []>;
9751
9752    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9753                       (outs GPR64sp:$wback,
9754                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9755                       (ins GPR64sp:$Rn,
9756                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9757  }
9758
9759  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9760}
9761
9762multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9763                       int Offset128, int Offset64, bits<4> opcode>
9764  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9765
9766  // ST1 instructions have extra "1d" variants.
9767  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9768    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9769                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9770                                GPR64sp:$Rn), []>;
9771
9772    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9773                       (outs GPR64sp:$wback),
9774                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9775                            GPR64sp:$Rn,
9776                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9777  }
9778
9779  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9780}
9781
9782multiclass SIMDLd1Multiple<string asm> {
9783  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9784  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9785  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9786  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9787}
9788
9789multiclass SIMDSt1Multiple<string asm> {
9790  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9791  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9792  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9793  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9794}
9795
9796multiclass SIMDLd2Multiple<string asm> {
9797  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9798}
9799
9800multiclass SIMDSt2Multiple<string asm> {
9801  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9802}
9803
9804multiclass SIMDLd3Multiple<string asm> {
9805  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9806}
9807
9808multiclass SIMDSt3Multiple<string asm> {
9809  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9810}
9811
9812multiclass SIMDLd4Multiple<string asm> {
9813  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9814}
9815
9816multiclass SIMDSt4Multiple<string asm> {
9817  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9818}
9819
9820//---
9821// AdvSIMD Load/store single-element
9822//---
9823
9824class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9825                         string asm, string operands, string cst,
9826                         dag oops, dag iops, list<dag> pattern>
9827  : I<oops, iops, asm, operands, cst, pattern> {
9828  bits<5> Vt;
9829  bits<5> Rn;
9830  let Inst{31} = 0;
9831  let Inst{29-24} = 0b001101;
9832  let Inst{22} = L;
9833  let Inst{21} = R;
9834  let Inst{15-13} = opcode;
9835  let Inst{9-5} = Rn;
9836  let Inst{4-0} = Vt;
9837}
9838
9839class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9840                         string asm, string operands, string cst,
9841                         dag oops, dag iops, list<dag> pattern>
9842  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9843  bits<5> Vt;
9844  bits<5> Rn;
9845  let Inst{31} = 0;
9846  let Inst{29-24} = 0b001101;
9847  let Inst{22} = L;
9848  let Inst{21} = R;
9849  let Inst{15-13} = opcode;
9850  let Inst{9-5} = Rn;
9851  let Inst{4-0} = Vt;
9852}
9853
9854
9855let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9856class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9857                  DAGOperand listtype>
9858  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9859                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
9860                       []> {
9861  let Inst{30} = Q;
9862  let Inst{23} = 0;
9863  let Inst{20-16} = 0b00000;
9864  let Inst{12} = S;
9865  let Inst{11-10} = size;
9866}
9867let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9868class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9869                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
9870  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9871                       "$Rn = $wback",
9872                       (outs GPR64sp:$wback, listtype:$Vt),
9873                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9874  bits<5> Xm;
9875  let Inst{30} = Q;
9876  let Inst{23} = 1;
9877  let Inst{20-16} = Xm;
9878  let Inst{12} = S;
9879  let Inst{11-10} = size;
9880}
9881
9882multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9883                          int Offset, int Size> {
9884  // E.g. "ld1r { v0.8b }, [x1], #1"
9885  //      "ld1r.8b\t$Vt, [$Rn], #1"
9886  // may get mapped to
9887  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9888  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9889                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9890                      GPR64sp:$Rn,
9891                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9892                      XZR), 1>;
9893
9894  // E.g. "ld1r.8b { v0 }, [x1], #1"
9895  //      "ld1r.8b\t$Vt, [$Rn], #1"
9896  // may get mapped to
9897  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9898  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9899                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9900                      GPR64sp:$Rn,
9901                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9902                      XZR), 0>;
9903
9904  // E.g. "ld1r.8b { v0 }, [x1]"
9905  //      "ld1r.8b\t$Vt, [$Rn]"
9906  // may get mapped to
9907  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9908  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9909                  (!cast<Instruction>(BaseName # "v" # layout)
9910                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9911                      GPR64sp:$Rn), 0>;
9912
9913  // E.g. "ld1r.8b { v0 }, [x1], x2"
9914  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9915  // may get mapped to
9916  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9917  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9918                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9919                      GPR64sp:$Rn,
9920                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9921                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9922}
9923
9924multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9925  int Offset1, int Offset2, int Offset4, int Offset8> {
9926  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9927                        !cast<DAGOperand>("VecList" # Count # "8b")>;
9928  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9929                        !cast<DAGOperand>("VecList" # Count #"16b")>;
9930  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9931                        !cast<DAGOperand>("VecList" # Count #"4h")>;
9932  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9933                        !cast<DAGOperand>("VecList" # Count #"8h")>;
9934  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9935                        !cast<DAGOperand>("VecList" # Count #"2s")>;
9936  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9937                        !cast<DAGOperand>("VecList" # Count #"4s")>;
9938  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9939                        !cast<DAGOperand>("VecList" # Count #"1d")>;
9940  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9941                        !cast<DAGOperand>("VecList" # Count #"2d")>;
9942
9943  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9944                                 !cast<DAGOperand>("VecList" # Count # "8b"),
9945                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9946  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9947                                 !cast<DAGOperand>("VecList" # Count # "16b"),
9948                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9949  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9950                                 !cast<DAGOperand>("VecList" # Count # "4h"),
9951                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9952  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9953                                 !cast<DAGOperand>("VecList" # Count # "8h"),
9954                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9955  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9956                                 !cast<DAGOperand>("VecList" # Count # "2s"),
9957                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9958  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9959                                 !cast<DAGOperand>("VecList" # Count # "4s"),
9960                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9961  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9962                                 !cast<DAGOperand>("VecList" # Count # "1d"),
9963                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9964  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9965                                 !cast<DAGOperand>("VecList" # Count # "2d"),
9966                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9967
9968  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9969  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9970  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9971  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9972  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9973  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9974  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9975  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9976}
9977
9978class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9979                      dag oops, dag iops, list<dag> pattern>
9980  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9981                       pattern> {
9982  // idx encoded in Q:S:size fields.
9983  bits<4> idx;
9984  let Inst{30} = idx{3};
9985  let Inst{23} = 0;
9986  let Inst{20-16} = 0b00000;
9987  let Inst{12} = idx{2};
9988  let Inst{11-10} = idx{1-0};
9989}
9990class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9991                      dag oops, dag iops, list<dag> pattern>
9992  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9993                           oops, iops, pattern> {
9994  // idx encoded in Q:S:size fields.
9995  bits<4> idx;
9996  let Inst{30} = idx{3};
9997  let Inst{23} = 0;
9998  let Inst{20-16} = 0b00000;
9999  let Inst{12} = idx{2};
10000  let Inst{11-10} = idx{1-0};
10001}
10002class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10003                          dag oops, dag iops>
10004  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10005                       "$Rn = $wback", oops, iops, []> {
10006  // idx encoded in Q:S:size fields.
10007  bits<4> idx;
10008  bits<5> Xm;
10009  let Inst{30} = idx{3};
10010  let Inst{23} = 1;
10011  let Inst{20-16} = Xm;
10012  let Inst{12} = idx{2};
10013  let Inst{11-10} = idx{1-0};
10014}
10015class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10016                          dag oops, dag iops>
10017  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10018                           "$Rn = $wback", oops, iops, []> {
10019  // idx encoded in Q:S:size fields.
10020  bits<4> idx;
10021  bits<5> Xm;
10022  let Inst{30} = idx{3};
10023  let Inst{23} = 1;
10024  let Inst{20-16} = Xm;
10025  let Inst{12} = idx{2};
10026  let Inst{11-10} = idx{1-0};
10027}
10028
10029class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10030                      dag oops, dag iops, list<dag> pattern>
10031  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10032                       pattern> {
10033  // idx encoded in Q:S:size<1> fields.
10034  bits<3> idx;
10035  let Inst{30} = idx{2};
10036  let Inst{23} = 0;
10037  let Inst{20-16} = 0b00000;
10038  let Inst{12} = idx{1};
10039  let Inst{11} = idx{0};
10040  let Inst{10} = size;
10041}
10042class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10043                      dag oops, dag iops, list<dag> pattern>
10044  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10045                           oops, iops, pattern> {
10046  // idx encoded in Q:S:size<1> fields.
10047  bits<3> idx;
10048  let Inst{30} = idx{2};
10049  let Inst{23} = 0;
10050  let Inst{20-16} = 0b00000;
10051  let Inst{12} = idx{1};
10052  let Inst{11} = idx{0};
10053  let Inst{10} = size;
10054}
10055
10056class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10057                          dag oops, dag iops>
10058  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10059                       "$Rn = $wback", oops, iops, []> {
10060  // idx encoded in Q:S:size<1> fields.
10061  bits<3> idx;
10062  bits<5> Xm;
10063  let Inst{30} = idx{2};
10064  let Inst{23} = 1;
10065  let Inst{20-16} = Xm;
10066  let Inst{12} = idx{1};
10067  let Inst{11} = idx{0};
10068  let Inst{10} = size;
10069}
10070class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10071                          dag oops, dag iops>
10072  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10073                           "$Rn = $wback", oops, iops, []> {
10074  // idx encoded in Q:S:size<1> fields.
10075  bits<3> idx;
10076  bits<5> Xm;
10077  let Inst{30} = idx{2};
10078  let Inst{23} = 1;
10079  let Inst{20-16} = Xm;
10080  let Inst{12} = idx{1};
10081  let Inst{11} = idx{0};
10082  let Inst{10} = size;
10083}
10084class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10085                      dag oops, dag iops, list<dag> pattern>
10086  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10087                       pattern> {
10088  // idx encoded in Q:S fields.
10089  bits<2> idx;
10090  let Inst{30} = idx{1};
10091  let Inst{23} = 0;
10092  let Inst{20-16} = 0b00000;
10093  let Inst{12} = idx{0};
10094  let Inst{11-10} = size;
10095}
10096class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10097                      dag oops, dag iops, list<dag> pattern>
10098  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10099                           oops, iops, pattern> {
10100  // idx encoded in Q:S fields.
10101  bits<2> idx;
10102  let Inst{30} = idx{1};
10103  let Inst{23} = 0;
10104  let Inst{20-16} = 0b00000;
10105  let Inst{12} = idx{0};
10106  let Inst{11-10} = size;
10107}
10108class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10109                          string asm, dag oops, dag iops>
10110  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10111                       "$Rn = $wback", oops, iops, []> {
10112  // idx encoded in Q:S fields.
10113  bits<2> idx;
10114  bits<5> Xm;
10115  let Inst{30} = idx{1};
10116  let Inst{23} = 1;
10117  let Inst{20-16} = Xm;
10118  let Inst{12} = idx{0};
10119  let Inst{11-10} = size;
10120}
10121class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10122                          string asm, dag oops, dag iops>
10123  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10124                           "$Rn = $wback", oops, iops, []> {
10125  // idx encoded in Q:S fields.
10126  bits<2> idx;
10127  bits<5> Xm;
10128  let Inst{30} = idx{1};
10129  let Inst{23} = 1;
10130  let Inst{20-16} = Xm;
10131  let Inst{12} = idx{0};
10132  let Inst{11-10} = size;
10133}
10134class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10135                      dag oops, dag iops, list<dag> pattern>
10136  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10137                       pattern> {
10138  // idx encoded in Q field.
10139  bits<1> idx;
10140  let Inst{30} = idx;
10141  let Inst{23} = 0;
10142  let Inst{20-16} = 0b00000;
10143  let Inst{12} = 0;
10144  let Inst{11-10} = size;
10145}
10146class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10147                      dag oops, dag iops, list<dag> pattern>
10148  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10149                           oops, iops, pattern> {
10150  // idx encoded in Q field.
10151  bits<1> idx;
10152  let Inst{30} = idx;
10153  let Inst{23} = 0;
10154  let Inst{20-16} = 0b00000;
10155  let Inst{12} = 0;
10156  let Inst{11-10} = size;
10157}
10158class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10159                          string asm, dag oops, dag iops>
10160  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10161                       "$Rn = $wback", oops, iops, []> {
10162  // idx encoded in Q field.
10163  bits<1> idx;
10164  bits<5> Xm;
10165  let Inst{30} = idx;
10166  let Inst{23} = 1;
10167  let Inst{20-16} = Xm;
10168  let Inst{12} = 0;
10169  let Inst{11-10} = size;
10170}
10171class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10172                          string asm, dag oops, dag iops>
10173  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10174                           "$Rn = $wback", oops, iops, []> {
10175  // idx encoded in Q field.
10176  bits<1> idx;
10177  bits<5> Xm;
10178  let Inst{30} = idx;
10179  let Inst{23} = 1;
10180  let Inst{20-16} = Xm;
10181  let Inst{12} = 0;
10182  let Inst{11-10} = size;
10183}
10184
10185let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10186multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10187                         RegisterOperand listtype,
10188                         RegisterOperand GPR64pi> {
10189  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10190                           (outs listtype:$dst),
10191                           (ins listtype:$Vt, VectorIndexB:$idx,
10192                                GPR64sp:$Rn), []>;
10193
10194  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10195                            (outs GPR64sp:$wback, listtype:$dst),
10196                            (ins listtype:$Vt, VectorIndexB:$idx,
10197                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10198}
10199let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10200multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10201                         RegisterOperand listtype,
10202                         RegisterOperand GPR64pi> {
10203  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10204                            (outs listtype:$dst),
10205                            (ins listtype:$Vt, VectorIndexH:$idx,
10206                                 GPR64sp:$Rn), []>;
10207
10208  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10209                            (outs GPR64sp:$wback, listtype:$dst),
10210                            (ins listtype:$Vt, VectorIndexH:$idx,
10211                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10212}
10213let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10214multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10215                         RegisterOperand listtype,
10216                         RegisterOperand GPR64pi> {
10217  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10218                            (outs listtype:$dst),
10219                            (ins listtype:$Vt, VectorIndexS:$idx,
10220                                 GPR64sp:$Rn), []>;
10221
10222  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10223                            (outs GPR64sp:$wback, listtype:$dst),
10224                            (ins listtype:$Vt, VectorIndexS:$idx,
10225                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10226}
10227let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10228multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10229                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10230  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10231                            (outs listtype:$dst),
10232                            (ins listtype:$Vt, VectorIndexD:$idx,
10233                                 GPR64sp:$Rn), []>;
10234
10235  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10236                            (outs GPR64sp:$wback, listtype:$dst),
10237                            (ins listtype:$Vt, VectorIndexD:$idx,
10238                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10239}
10240let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10241multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10242                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10243  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10244                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10245                                        GPR64sp:$Rn), []>;
10246
10247  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10248                                    (outs GPR64sp:$wback),
10249                                    (ins listtype:$Vt, VectorIndexB:$idx,
10250                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10251}
10252let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10253multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10254                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10255  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10256                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10257                                         GPR64sp:$Rn), []>;
10258
10259  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10260                            (outs GPR64sp:$wback),
10261                            (ins listtype:$Vt, VectorIndexH:$idx,
10262                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10263}
10264let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10265multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10266                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10267  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10268                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10269                                         GPR64sp:$Rn), []>;
10270
10271  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10272                            (outs GPR64sp:$wback),
10273                            (ins listtype:$Vt, VectorIndexS:$idx,
10274                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10275}
10276let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10277multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10278                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10279  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10280                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10281                                         GPR64sp:$Rn), []>;
10282
10283  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10284                            (outs GPR64sp:$wback),
10285                            (ins listtype:$Vt, VectorIndexD:$idx,
10286                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10287}
10288
10289multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10290                                 string Count, int Offset, Operand idxtype> {
10291  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10292  //      "ld1\t$Vt, [$Rn], #1"
10293  // may get mapped to
10294  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10295  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10296                  (!cast<Instruction>(NAME # Type  # "_POST")
10297                      GPR64sp:$Rn,
10298                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10299                      idxtype:$idx, XZR), 1>;
10300
10301  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10302  //      "ld1.8b\t$Vt, [$Rn], #1"
10303  // may get mapped to
10304  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10305  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10306                  (!cast<Instruction>(NAME # Type # "_POST")
10307                      GPR64sp:$Rn,
10308                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10309                      idxtype:$idx, XZR), 0>;
10310
10311  // E.g. "ld1.8b { v0 }[0], [x1]"
10312  //      "ld1.8b\t$Vt, [$Rn]"
10313  // may get mapped to
10314  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10315  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10316                      (!cast<Instruction>(NAME # Type)
10317                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10318                         idxtype:$idx, GPR64sp:$Rn), 0>;
10319
10320  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10321  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10322  // may get mapped to
10323  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10324  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10325                      (!cast<Instruction>(NAME # Type # "_POST")
10326                         GPR64sp:$Rn,
10327                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10328                         idxtype:$idx,
10329                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10330}
10331
10332multiclass SIMDLdSt1SingleAliases<string asm> {
10333  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10334  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10335  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10336  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10337}
10338
10339multiclass SIMDLdSt2SingleAliases<string asm> {
10340  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10341  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10342  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10343  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10344}
10345
10346multiclass SIMDLdSt3SingleAliases<string asm> {
10347  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10348  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10349  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10350  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10351}
10352
10353multiclass SIMDLdSt4SingleAliases<string asm> {
10354  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10355  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10356  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10357  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10358}
10359} // end of 'let Predicates = [HasNEON]'
10360
10361//----------------------------------------------------------------------------
10362// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10363//----------------------------------------------------------------------------
10364
10365let Predicates = [HasNEON, HasRDM] in {
10366
10367class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10368                                    RegisterOperand regtype, string asm,
10369                                    string kind, list<dag> pattern>
10370  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10371                                pattern> {
10372}
10373multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10374                                             SDPatternOperator Accum> {
10375  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10376    [(set (v4i16 V64:$dst),
10377          (Accum (v4i16 V64:$Rd),
10378                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
10379                                                   (v4i16 V64:$Rm)))))]>;
10380  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10381    [(set (v8i16 V128:$dst),
10382          (Accum (v8i16 V128:$Rd),
10383                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10384                                                   (v8i16 V128:$Rm)))))]>;
10385  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10386    [(set (v2i32 V64:$dst),
10387          (Accum (v2i32 V64:$Rd),
10388                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10389                                                   (v2i32 V64:$Rm)))))]>;
10390  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10391    [(set (v4i32 V128:$dst),
10392          (Accum (v4i32 V128:$Rd),
10393                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10394                                                   (v4i32 V128:$Rm)))))]>;
10395}
10396
10397multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10398                                     SDPatternOperator Accum> {
10399  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10400                                          V64, V64, V128_lo, VectorIndexH,
10401                                          asm, ".4h", ".4h", ".4h", ".h",
10402    [(set (v4i16 V64:$dst),
10403          (Accum (v4i16 V64:$Rd),
10404                 (v4i16 (int_aarch64_neon_sqrdmulh
10405                          (v4i16 V64:$Rn),
10406                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10407                                                    VectorIndexH:$idx))))))]> {
10408    bits<3> idx;
10409    let Inst{11} = idx{2};
10410    let Inst{21} = idx{1};
10411    let Inst{20} = idx{0};
10412  }
10413
10414  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10415                                          V128, V128, V128_lo, VectorIndexH,
10416                                          asm, ".8h", ".8h", ".8h", ".h",
10417    [(set (v8i16 V128:$dst),
10418          (Accum (v8i16 V128:$Rd),
10419                 (v8i16 (int_aarch64_neon_sqrdmulh
10420                          (v8i16 V128:$Rn),
10421                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10422                                                   VectorIndexH:$idx))))))]> {
10423    bits<3> idx;
10424    let Inst{11} = idx{2};
10425    let Inst{21} = idx{1};
10426    let Inst{20} = idx{0};
10427  }
10428
10429  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10430                                          V64, V64, V128, VectorIndexS,
10431                                          asm, ".2s", ".2s", ".2s", ".s",
10432    [(set (v2i32 V64:$dst),
10433        (Accum (v2i32 V64:$Rd),
10434               (v2i32 (int_aarch64_neon_sqrdmulh
10435                        (v2i32 V64:$Rn),
10436                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10437                                                 VectorIndexS:$idx))))))]> {
10438    bits<2> idx;
10439    let Inst{11} = idx{1};
10440    let Inst{21} = idx{0};
10441  }
10442
10443  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10444  // an intermediate EXTRACT_SUBREG would be untyped.
10445  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10446  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10447  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10448                       (i32 (vector_extract
10449                               (v4i32 (insert_subvector
10450                                       (undef),
10451                                        (v2i32 (int_aarch64_neon_sqrdmulh
10452                                                 (v2i32 V64:$Rn),
10453                                                 (v2i32 (AArch64duplane32
10454                                                          (v4i32 V128:$Rm),
10455                                                          VectorIndexS:$idx)))),
10456                                      (i32 0))),
10457                               (i64 0))))),
10458            (EXTRACT_SUBREG
10459                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10460                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10461                                                FPR32Op:$Rd,
10462                                                ssub)),
10463                          V64:$Rn,
10464                          V128:$Rm,
10465                          VectorIndexS:$idx)),
10466                ssub)>;
10467
10468  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10469                                          V128, V128, V128, VectorIndexS,
10470                                          asm, ".4s", ".4s", ".4s", ".s",
10471    [(set (v4i32 V128:$dst),
10472          (Accum (v4i32 V128:$Rd),
10473                 (v4i32 (int_aarch64_neon_sqrdmulh
10474                          (v4i32 V128:$Rn),
10475                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10476                                                   VectorIndexS:$idx))))))]> {
10477    bits<2> idx;
10478    let Inst{11} = idx{1};
10479    let Inst{21} = idx{0};
10480  }
10481
10482  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10483  // an intermediate EXTRACT_SUBREG would be untyped.
10484  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10485                        (i32 (vector_extract
10486                               (v4i32 (int_aarch64_neon_sqrdmulh
10487                                        (v4i32 V128:$Rn),
10488                                        (v4i32 (AArch64duplane32
10489                                                 (v4i32 V128:$Rm),
10490                                                 VectorIndexS:$idx)))),
10491                               (i64 0))))),
10492            (EXTRACT_SUBREG
10493                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10494                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10495                                               FPR32Op:$Rd,
10496                                               ssub)),
10497                         V128:$Rn,
10498                         V128:$Rm,
10499                         VectorIndexS:$idx)),
10500                ssub)>;
10501
10502  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10503                                        FPR16Op, FPR16Op, V128_lo,
10504                                        VectorIndexH, asm, ".h", "", "", ".h",
10505                                        []> {
10506    bits<3> idx;
10507    let Inst{11} = idx{2};
10508    let Inst{21} = idx{1};
10509    let Inst{20} = idx{0};
10510  }
10511
10512  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10513                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10514                                        asm, ".s", "", "", ".s",
10515    [(set (i32 FPR32Op:$dst),
10516          (Accum (i32 FPR32Op:$Rd),
10517                 (i32 (int_aarch64_neon_sqrdmulh
10518                        (i32 FPR32Op:$Rn),
10519                        (i32 (vector_extract (v4i32 V128:$Rm),
10520                                             VectorIndexS:$idx))))))]> {
10521    bits<2> idx;
10522    let Inst{11} = idx{1};
10523    let Inst{21} = idx{0};
10524  }
10525}
10526} // let Predicates = [HasNeon, HasRDM]
10527
10528//----------------------------------------------------------------------------
10529// ARMv8.3 Complex ADD/MLA instructions
10530//----------------------------------------------------------------------------
10531
10532class ComplexRotationOperand<int Angle, int Remainder, string Type>
10533  : AsmOperandClass {
10534  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10535  let DiagnosticType = "InvalidComplexRotation" # Type;
10536  let Name = "ComplexRotation" # Type;
10537}
10538def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10539                                                  SDNodeXForm<imm, [{
10540  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10541}]>> {
10542  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10543  let PrintMethod = "printComplexRotationOp<90, 0>";
10544}
10545def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10546                                                  SDNodeXForm<imm, [{
10547  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10548}]>> {
10549  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10550  let PrintMethod = "printComplexRotationOp<180, 90>";
10551}
10552let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10553class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10554                                     RegisterOperand regtype, Operand rottype,
10555                                     string asm, string kind, list<dag> pattern>
10556  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10557      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10558      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10559    Sched<[WriteV]> {
10560  bits<5> Rd;
10561  bits<5> Rn;
10562  bits<5> Rm;
10563  bits<1> rot;
10564  let Inst{31}    = 0;
10565  let Inst{30}    = Q;
10566  let Inst{29}    = U;
10567  let Inst{28-24} = 0b01110;
10568  let Inst{23-22} = size;
10569  let Inst{21}    = 0;
10570  let Inst{20-16} = Rm;
10571  let Inst{15-13} = opcode;
10572  // Non-tied version (FCADD) only has one rotation bit
10573  let Inst{12}    = rot;
10574  let Inst{11}    = 0;
10575  let Inst{10}    = 1;
10576  let Inst{9-5}   = Rn;
10577  let Inst{4-0}   = Rd;
10578}
10579
10580//8.3 CompNum - Floating-point complex number support
10581multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10582                                          string asm, SDPatternOperator OpNode>{
10583  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10584  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10585              asm, ".4h",
10586              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10587                                              (v4f16 V64:$Rn),
10588                                              (v4f16 V64:$Rm),
10589                                              (rottype i32:$rot)))]>;
10590
10591  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10592              asm, ".8h",
10593              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10594                                               (v8f16 V128:$Rn),
10595                                               (v8f16 V128:$Rm),
10596                                               (rottype i32:$rot)))]>;
10597  }
10598
10599  let Predicates = [HasComplxNum, HasNEON] in {
10600  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10601              asm, ".2s",
10602              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10603                                              (v2f32 V64:$Rn),
10604                                              (v2f32 V64:$Rm),
10605                                              (rottype i32:$rot)))]>;
10606
10607  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10608              asm, ".4s",
10609              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10610                                               (v4f32 V128:$Rn),
10611                                               (v4f32 V128:$Rm),
10612                                               (rottype i32:$rot)))]>;
10613
10614  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10615              asm, ".2d",
10616              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10617                                               (v2f64 V128:$Rn),
10618                                               (v2f64 V128:$Rm),
10619                                               (rottype i32:$rot)))]>;
10620  }
10621}
10622
10623let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10624class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10625                                         bits<3> opcode,
10626                                         RegisterOperand regtype,
10627                                         Operand rottype, string asm,
10628                                         string kind, list<dag> pattern>
10629  : I<(outs regtype:$dst),
10630      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10631      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10632      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10633    Sched<[WriteV]> {
10634  bits<5> Rd;
10635  bits<5> Rn;
10636  bits<5> Rm;
10637  bits<2> rot;
10638  let Inst{31}    = 0;
10639  let Inst{30}    = Q;
10640  let Inst{29}    = U;
10641  let Inst{28-24} = 0b01110;
10642  let Inst{23-22} = size;
10643  let Inst{21}    = 0;
10644  let Inst{20-16} = Rm;
10645  let Inst{15-13} = opcode;
10646  let Inst{12-11} = rot;
10647  let Inst{10}    = 1;
10648  let Inst{9-5}   = Rn;
10649  let Inst{4-0}   = Rd;
10650}
10651
10652multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10653                                             Operand rottype, string asm,
10654                                             SDPatternOperator OpNode> {
10655  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10656  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10657              rottype, asm, ".4h",
10658              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10659                                              (v4f16 V64:$Rn),
10660                                              (v4f16 V64:$Rm),
10661                                              (rottype i32:$rot)))]>;
10662
10663  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10664              rottype, asm, ".8h",
10665              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10666                                               (v8f16 V128:$Rn),
10667                                               (v8f16 V128:$Rm),
10668                                               (rottype i32:$rot)))]>;
10669  }
10670
10671  let Predicates = [HasComplxNum, HasNEON] in {
10672  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10673              rottype, asm, ".2s",
10674              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10675                                              (v2f32 V64:$Rn),
10676                                              (v2f32 V64:$Rm),
10677                                              (rottype i32:$rot)))]>;
10678
10679  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10680              rottype, asm, ".4s",
10681              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10682                                               (v4f32 V128:$Rn),
10683                                               (v4f32 V128:$Rm),
10684                                               (rottype i32:$rot)))]>;
10685
10686  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10687              rottype, asm, ".2d",
10688              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10689                                               (v2f64 V128:$Rn),
10690                                               (v2f64 V128:$Rm),
10691                                               (rottype i32:$rot)))]>;
10692  }
10693}
10694
10695let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10696class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10697                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10698                                 RegisterOperand lhs_reg,
10699                                 RegisterOperand rhs_reg, Operand vec_idx,
10700                                 Operand rottype, string asm, string apple_kind,
10701                                 string dst_kind, string lhs_kind,
10702                                 string rhs_kind, list<dag> pattern>
10703  : I<(outs dst_reg:$dst),
10704      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10705      asm,
10706      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10707      "$idx, $rot" # "|" # apple_kind #
10708      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10709    Sched<[WriteV]> {
10710  bits<5> Rd;
10711  bits<5> Rn;
10712  bits<5> Rm;
10713  bits<2> rot;
10714
10715  let Inst{31}    = 0;
10716  let Inst{30}    = Q;
10717  let Inst{29}    = U;
10718  let Inst{28}    = Scalar;
10719  let Inst{27-24} = 0b1111;
10720  let Inst{23-22} = size;
10721  // Bit 21 must be set by the derived class.
10722  let Inst{20-16} = Rm;
10723  let Inst{15}    = opc1;
10724  let Inst{14-13} = rot;
10725  let Inst{12}    = opc2;
10726  // Bit 11 must be set by the derived class.
10727  let Inst{10}    = 0;
10728  let Inst{9-5}   = Rn;
10729  let Inst{4-0}   = Rd;
10730}
10731
10732// The complex instructions index by pairs of elements, so the VectorIndexes
10733// don't match the lane types, and the index bits are different to the other
10734// classes.
10735multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10736                                     string asm, SDPatternOperator OpNode> {
10737  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10738  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10739                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10740                      ".4h", ".h", []> {
10741    bits<1> idx;
10742    let Inst{11} = 0;
10743    let Inst{21} = idx{0};
10744  }
10745
10746  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10747                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10748                      ".8h", ".8h", ".h", []> {
10749    bits<2> idx;
10750    let Inst{11} = idx{1};
10751    let Inst{21} = idx{0};
10752  }
10753  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10754
10755  let Predicates = [HasComplxNum, HasNEON] in {
10756  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10757                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10758                      ".4s", ".4s", ".s", []> {
10759    bits<1> idx;
10760    let Inst{11} = idx{0};
10761    let Inst{21} = 0;
10762  }
10763  } // Predicates = [HasComplxNum, HasNEON]
10764}
10765
10766//----------------------------------------------------------------------------
10767// Crypto extensions
10768//----------------------------------------------------------------------------
10769
10770let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10771class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10772              list<dag> pat>
10773  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10774    Sched<[WriteV]>{
10775  bits<5> Rd;
10776  bits<5> Rn;
10777  let Inst{31-16} = 0b0100111000101000;
10778  let Inst{15-12} = opc;
10779  let Inst{11-10} = 0b10;
10780  let Inst{9-5}   = Rn;
10781  let Inst{4-0}   = Rd;
10782}
10783
10784class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10785  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10786            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10787
10788class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10789  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10790            "$Rd = $dst",
10791            [(set (v16i8 V128:$dst),
10792                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10793
10794let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10795class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10796                     dag oops, dag iops, list<dag> pat>
10797  : I<oops, iops, asm,
10798      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10799      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10800    Sched<[WriteV]>{
10801  bits<5> Rd;
10802  bits<5> Rn;
10803  bits<5> Rm;
10804  let Inst{31-21} = 0b01011110000;
10805  let Inst{20-16} = Rm;
10806  let Inst{15}    = 0;
10807  let Inst{14-12} = opc;
10808  let Inst{11-10} = 0b00;
10809  let Inst{9-5}   = Rn;
10810  let Inst{4-0}   = Rd;
10811}
10812
10813class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10814  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10815                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10816                   [(set (v4i32 FPR128:$dst),
10817                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10818                                 (v4i32 V128:$Rm)))]>;
10819
10820class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10821  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10822                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10823                   [(set (v4i32 V128:$dst),
10824                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10825                                 (v4i32 V128:$Rm)))]>;
10826
10827class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10828  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10829                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10830                   [(set (v4i32 FPR128:$dst),
10831                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10832                                 (v4i32 V128:$Rm)))]>;
10833
10834let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10835class SHA2OpInst<bits<4> opc, string asm, string kind,
10836                 string cstr, dag oops, dag iops,
10837                 list<dag> pat>
10838  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10839                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10840    Sched<[WriteV]>{
10841  bits<5> Rd;
10842  bits<5> Rn;
10843  let Inst{31-16} = 0b0101111000101000;
10844  let Inst{15-12} = opc;
10845  let Inst{11-10} = 0b10;
10846  let Inst{9-5}   = Rn;
10847  let Inst{4-0}   = Rd;
10848}
10849
10850class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10851  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10852               (ins V128:$Rd, V128:$Rn),
10853               [(set (v4i32 V128:$dst),
10854                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10855
10856class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10857  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10858               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10859
10860// Armv8.2-A Crypto extensions
10861class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10862                    list<dag> pattern>
10863  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10864  bits<5> Vd;
10865  bits<5> Vn;
10866  let Inst{31-25} = 0b1100111;
10867  let Inst{9-5}   = Vn;
10868  let Inst{4-0}   = Vd;
10869}
10870
10871class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10872  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10873                  "$Vm = $Vd", []> {
10874  let Inst{31-25} = 0b1100111;
10875  let Inst{24-21} = 0b0110;
10876  let Inst{20-15} = 0b000001;
10877  let Inst{14}    = op0;
10878  let Inst{13-12} = 0b00;
10879  let Inst{11-10} = op1;
10880}
10881class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10882  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10883class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10884  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10885
10886class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10887                string asmops, string cst>
10888  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10889  bits<5> Vm;
10890  let Inst{24-21} = 0b0011;
10891  let Inst{20-16} = Vm;
10892  let Inst{15}    = 0b1;
10893  let Inst{14}    = op0;
10894  let Inst{13-12} = 0b00;
10895  let Inst{11-10} = op1;
10896}
10897class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10898  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10899              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10900class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10901  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10902              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10903class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10904  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10905              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10906class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10907  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10908              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10909class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10910  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10911              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10912
10913class CryptoRRRR<bits<2>op0, string asm, string asmops>
10914  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10915                  asmops, "", []> {
10916  bits<5> Vm;
10917  bits<5> Va;
10918  let Inst{24-23} = 0b00;
10919  let Inst{22-21} = op0;
10920  let Inst{20-16} = Vm;
10921  let Inst{15}    = 0b0;
10922  let Inst{14-10} = Va;
10923}
10924class CryptoRRRR_16B<bits<2>op0, string asm>
10925 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
10926                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
10927}
10928class CryptoRRRR_4S<bits<2>op0, string asm>
10929 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
10930                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
10931}
10932
10933class CryptoRRRi6<string asm>
10934  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10935                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
10936                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
10937  bits<6> imm;
10938  bits<5> Vm;
10939  let Inst{24-21} = 0b0100;
10940  let Inst{20-16} = Vm;
10941  let Inst{15-10} = imm;
10942  let Inst{9-5}   = Vn;
10943  let Inst{4-0}   = Vd;
10944}
10945
10946class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10947  : BaseCryptoV82<(outs V128:$Vdst),
10948                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10949                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
10950                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
10951  bits<2> imm;
10952  bits<5> Vm;
10953  let Inst{24-21} = 0b0010;
10954  let Inst{20-16} = Vm;
10955  let Inst{15}    = 0b1;
10956  let Inst{14}    = op0;
10957  let Inst{13-12} = imm;
10958  let Inst{11-10} = op1;
10959}
10960
10961//----------------------------------------------------------------------------
10962// v8.1 atomic instructions extension:
10963// * CAS
10964// * CASP
10965// * SWP
10966// * LDOPregister<OP>, and aliases STOPregister<OP>
10967
10968// Instruction encodings:
10969//
10970//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10971// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10972// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10973// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10974// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10975// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10976
10977// Instruction syntax:
10978//
10979// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10980// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10981// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10982// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10983// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10984// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10985// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10986// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10987// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10988// ST<OP>{<order>} <Xs>, [<Xn|SP>]
10989
10990let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10991class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10992                      string cstr, list<dag> pattern>
10993      : I<oops, iops, asm, operands, cstr, pattern> {
10994  bits<2> Sz;
10995  bit NP;
10996  bit Acq;
10997  bit Rel;
10998  bits<5> Rs;
10999  bits<5> Rn;
11000  bits<5> Rt;
11001  let Inst{31-30} = Sz;
11002  let Inst{29-24} = 0b001000;
11003  let Inst{23} = NP;
11004  let Inst{22} = Acq;
11005  let Inst{21} = 0b1;
11006  let Inst{20-16} = Rs;
11007  let Inst{15} = Rel;
11008  let Inst{14-10} = 0b11111;
11009  let Inst{9-5} = Rn;
11010  let Inst{4-0} = Rt;
11011  let Predicates = [HasLSE];
11012}
11013
11014class BaseCAS<string order, string size, RegisterClass RC>
11015      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11016                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11017                        "$out = $Rs",[]>,
11018        Sched<[WriteAtomic]> {
11019  let NP = 1;
11020}
11021
11022multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11023  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11024  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11025  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11026  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11027}
11028
11029class BaseCASP<string order, string size, RegisterOperand RC>
11030      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11031                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11032                        "$out = $Rs",[]>,
11033        Sched<[WriteAtomic]> {
11034  let NP = 0;
11035}
11036
11037multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11038  let Sz = 0b00, Acq = Acq, Rel = Rel in
11039    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11040  let Sz = 0b01, Acq = Acq, Rel = Rel in
11041    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11042}
11043
11044let Predicates = [HasLSE] in
11045class BaseSWP<string order, string size, RegisterClass RC>
11046      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11047          "\t$Rs, $Rt, [$Rn]","",[]>,
11048        Sched<[WriteAtomic]> {
11049  bits<2> Sz;
11050  bit Acq;
11051  bit Rel;
11052  bits<5> Rs;
11053  bits<3> opc = 0b000;
11054  bits<5> Rn;
11055  bits<5> Rt;
11056  let Inst{31-30} = Sz;
11057  let Inst{29-24} = 0b111000;
11058  let Inst{23} = Acq;
11059  let Inst{22} = Rel;
11060  let Inst{21} = 0b1;
11061  let Inst{20-16} = Rs;
11062  let Inst{15} = 0b1;
11063  let Inst{14-12} = opc;
11064  let Inst{11-10} = 0b00;
11065  let Inst{9-5} = Rn;
11066  let Inst{4-0} = Rt;
11067  let Predicates = [HasLSE];
11068}
11069
11070multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11071  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11072  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11073  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11074  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11075}
11076
11077let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11078class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11079      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11080          "\t$Rs, $Rt, [$Rn]","",[]>,
11081        Sched<[WriteAtomic]> {
11082  bits<2> Sz;
11083  bit Acq;
11084  bit Rel;
11085  bits<5> Rs;
11086  bits<3> opc;
11087  bits<5> Rn;
11088  bits<5> Rt;
11089  let Inst{31-30} = Sz;
11090  let Inst{29-24} = 0b111000;
11091  let Inst{23} = Acq;
11092  let Inst{22} = Rel;
11093  let Inst{21} = 0b1;
11094  let Inst{20-16} = Rs;
11095  let Inst{15} = 0b0;
11096  let Inst{14-12} = opc;
11097  let Inst{11-10} = 0b00;
11098  let Inst{9-5} = Rn;
11099  let Inst{4-0} = Rt;
11100  let Predicates = [HasLSE];
11101}
11102
11103multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11104                        string order> {
11105  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11106    def B : BaseLDOPregister<op, order, "b", GPR32>;
11107  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11108    def H : BaseLDOPregister<op, order, "h", GPR32>;
11109  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11110    def W : BaseLDOPregister<op, order, "", GPR32>;
11111  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11112    def X : BaseLDOPregister<op, order, "", GPR64>;
11113}
11114
11115// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11116// complex DAG for DstRHS.
11117let Predicates = [HasLSE] in
11118multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11119                                         string size, dag SrcRHS, dag DstRHS> {
11120  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11121            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11122  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11123            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11124  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11125            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11126  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11127            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11128  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11129            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11130}
11131
11132multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11133                                     string size, dag RHS> {
11134  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11135}
11136
11137multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11138                                         string size, dag LHS, dag RHS> {
11139  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11140}
11141
11142multiclass LDOPregister_patterns<string inst, string op> {
11143  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11144  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11145  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11146  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11147}
11148
11149multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11150  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11151                        (i64 GPR64:$Rm),
11152                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11153  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11154                        (i32 GPR32:$Rm),
11155                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11156  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11157                        (i32 GPR32:$Rm),
11158                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11159  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11160                        (i32 GPR32:$Rm),
11161                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11162}
11163
11164let Predicates = [HasLSE] in
11165multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11166                                        string size, dag OLD, dag NEW> {
11167  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11168            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11169  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11170            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11171  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11172            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11173  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11174            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11175  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11176            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11177}
11178
11179multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11180                                    string size, dag OLD, dag NEW> {
11181  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11182}
11183
11184multiclass CASregister_patterns<string inst, string op> {
11185  defm : CASregister_patterns_ord<inst, "X", op, "64",
11186                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11187  defm : CASregister_patterns_ord<inst, "W", op, "32",
11188                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11189  defm : CASregister_patterns_ord<inst, "H", op, "16",
11190                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11191  defm : CASregister_patterns_ord<inst, "B", op, "8",
11192                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11193}
11194
11195let Predicates = [HasLSE] in
11196class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11197                        Instruction inst> :
11198      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11199
11200multiclass STOPregister<string asm, string instr> {
11201  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11202                    !cast<Instruction>(instr # "LB")>;
11203  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11204                    !cast<Instruction>(instr # "LH")>;
11205  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11206                    !cast<Instruction>(instr # "LW")>;
11207  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11208                    !cast<Instruction>(instr # "LX")>;
11209  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11210                    !cast<Instruction>(instr # "B")>;
11211  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11212                    !cast<Instruction>(instr # "H")>;
11213  def : BaseSTOPregister<asm,        GPR32, WZR,
11214                    !cast<Instruction>(instr # "W")>;
11215  def : BaseSTOPregister<asm,        GPR64, XZR,
11216                    !cast<Instruction>(instr # "X")>;
11217}
11218
11219//----------------------------------------------------------------------------
11220// Allow the size specifier tokens to be upper case, not just lower.
11221def : TokenAlias<".4B", ".4b">;  // Add dot product
11222def : TokenAlias<".8B", ".8b">;
11223def : TokenAlias<".4H", ".4h">;
11224def : TokenAlias<".2S", ".2s">;
11225def : TokenAlias<".1D", ".1d">;
11226def : TokenAlias<".16B", ".16b">;
11227def : TokenAlias<".8H", ".8h">;
11228def : TokenAlias<".4S", ".4s">;
11229def : TokenAlias<".2D", ".2d">;
11230def : TokenAlias<".1Q", ".1q">;
11231def : TokenAlias<".2H", ".2h">;
11232def : TokenAlias<".B", ".b">;
11233def : TokenAlias<".H", ".h">;
11234def : TokenAlias<".S", ".s">;
11235def : TokenAlias<".D", ".d">;
11236def : TokenAlias<".Q", ".q">;
11237