blob: fc193fdd91f8c26c33a299dafafbdc3cf2056647 [file] [log] [blame]
Tim Northover00ed9962014-03-29 10:18:08 +00001//===- ARM64InstrFormats.td - ARM64 Instruction Formats ------*- tblgen -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10//===----------------------------------------------------------------------===//
11// Describe ARM64 instructions format here
12//
13
14// Format specifies the encoding used by the instruction. This is part of the
15// ad-hoc solution used to emit machine instruction encodings by our machine
16// code emitter.
17class Format<bits<2> val> {
18 bits<2> Value = val;
19}
20
21def PseudoFrm : Format<0>;
22def NormalFrm : Format<1>; // Do we need any others?
23
24// ARM64 Instruction Format
25class ARM64Inst<Format f, string cstr> : Instruction {
26 field bits<32> Inst; // Instruction encoding.
27 // Mask of bits that cause an encoding to be UNPREDICTABLE.
28 // If a bit is set, then if the corresponding bit in the
29 // target encoding differs from its value in the "Inst" field,
30 // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31 field bits<32> Unpredictable = 0;
32 // SoftFail is the generic name for this field, but we alias it so
33 // as to make it more obvious what it means in ARM-land.
34 field bits<32> SoftFail = Unpredictable;
35 let Namespace = "ARM64";
36 Format F = f;
37 bits<2> Form = F.Value;
38 let Pattern = [];
39 let Constraints = cstr;
40}
41
42// Pseudo instructions (don't have encoding information)
43class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44 : ARM64Inst<PseudoFrm, cstr> {
45 dag OutOperandList = oops;
46 dag InOperandList = iops;
47 let Pattern = pattern;
48 let isCodeGenOnly = 1;
49}
50
51// Real instructions (have encoding information)
52class EncodedI<string cstr, list<dag> pattern> : ARM64Inst<NormalFrm, cstr> {
53 let Pattern = pattern;
54 let Size = 4;
55}
56
57// Normal instructions
58class I<dag oops, dag iops, string asm, string operands, string cstr,
59 list<dag> pattern>
60 : EncodedI<cstr, pattern> {
61 dag OutOperandList = oops;
62 dag InOperandList = iops;
63 let AsmString = !strconcat(asm, operands);
64}
65
66class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68class UnOpFrag<dag res> : PatFrag<(ops node:$LHS), res>;
69
70// Helper fragment for an extract of the high portion of a 128-bit vector.
71def extract_high_v16i8 :
72 UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73def extract_high_v8i16 :
74 UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75def extract_high_v4i32 :
76 UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77def extract_high_v2i64 :
78 UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80//===----------------------------------------------------------------------===//
81// Asm Operand Classes.
82//
83
84// Shifter operand for arithmetic shifted encodings.
85def ShifterOperand : AsmOperandClass {
86 let Name = "Shifter";
87}
88
89// Shifter operand for mov immediate encodings.
90def MovImm32ShifterOperand : AsmOperandClass {
91 let SuperClasses = [ShifterOperand];
92 let Name = "MovImm32Shifter";
93}
94def MovImm64ShifterOperand : AsmOperandClass {
95 let SuperClasses = [ShifterOperand];
96 let Name = "MovImm64Shifter";
97}
98
99// Shifter operand for arithmetic register shifted encodings.
100def ArithmeticShifterOperand : AsmOperandClass {
101 let SuperClasses = [ShifterOperand];
102 let Name = "ArithmeticShifter";
103}
104
105// Shifter operand for arithmetic shifted encodings for ADD/SUB instructions.
106def AddSubShifterOperand : AsmOperandClass {
107 let SuperClasses = [ArithmeticShifterOperand];
108 let Name = "AddSubShifter";
109}
110
111// Shifter operand for logical vector 128/64-bit shifted encodings.
112def LogicalVecShifterOperand : AsmOperandClass {
113 let SuperClasses = [ShifterOperand];
114 let Name = "LogicalVecShifter";
115}
116def LogicalVecHalfWordShifterOperand : AsmOperandClass {
117 let SuperClasses = [LogicalVecShifterOperand];
118 let Name = "LogicalVecHalfWordShifter";
119}
120
121// The "MSL" shifter on the vector MOVI instruction.
122def MoveVecShifterOperand : AsmOperandClass {
123 let SuperClasses = [ShifterOperand];
124 let Name = "MoveVecShifter";
125}
126
127// Extend operand for arithmetic encodings.
128def ExtendOperand : AsmOperandClass { let Name = "Extend"; }
129def ExtendOperand64 : AsmOperandClass {
130 let SuperClasses = [ExtendOperand];
131 let Name = "Extend64";
132}
133// 'extend' that's a lsl of a 64-bit register.
134def ExtendOperandLSL64 : AsmOperandClass {
135 let SuperClasses = [ExtendOperand];
136 let Name = "ExtendLSL64";
137}
138
139// 8-bit floating-point immediate encodings.
140def FPImmOperand : AsmOperandClass {
141 let Name = "FPImm";
142 let ParserMethod = "tryParseFPImm";
143}
144
145// 8-bit immediate for AdvSIMD where 64-bit values of the form:
146// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
147// are encoded as the eight bit value 'abcdefgh'.
148def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
149
150
151//===----------------------------------------------------------------------===//
152// Operand Definitions.
153//
154
155// ADR[P] instruction labels.
156def AdrpOperand : AsmOperandClass {
157 let Name = "AdrpLabel";
158 let ParserMethod = "tryParseAdrpLabel";
Bradley Smithf8230792014-04-09 14:44:12 +0000159 let DiagnosticType = "InvalidLabel";
Tim Northover00ed9962014-03-29 10:18:08 +0000160}
161def adrplabel : Operand<i64> {
162 let EncoderMethod = "getAdrLabelOpValue";
163 let PrintMethod = "printAdrpLabel";
164 let ParserMatchClass = AdrpOperand;
165}
166
167def AdrOperand : AsmOperandClass {
168 let Name = "AdrLabel";
169 let ParserMethod = "tryParseAdrLabel";
Bradley Smithf8230792014-04-09 14:44:12 +0000170 let DiagnosticType = "InvalidLabel";
Tim Northover00ed9962014-03-29 10:18:08 +0000171}
172def adrlabel : Operand<i64> {
173 let EncoderMethod = "getAdrLabelOpValue";
174 let ParserMatchClass = AdrOperand;
175}
176
177// simm9 predicate - True if the immediate is in the range [-256, 255].
178def SImm9Operand : AsmOperandClass {
179 let Name = "SImm9";
180 let DiagnosticType = "InvalidMemoryIndexedSImm9";
181}
182def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
183 let ParserMatchClass = SImm9Operand;
184}
185
186// simm7s4 predicate - True if the immediate is a multiple of 4 in the range
187// [-256, 252].
188def SImm7s4Operand : AsmOperandClass {
189 let Name = "SImm7s4";
190 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
191}
192def simm7s4 : Operand<i32> {
193 let ParserMatchClass = SImm7s4Operand;
194 let PrintMethod = "printImmScale4";
195}
196
197// simm7s8 predicate - True if the immediate is a multiple of 8 in the range
198// [-512, 504].
199def SImm7s8Operand : AsmOperandClass {
200 let Name = "SImm7s8";
201 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
202}
203def simm7s8 : Operand<i32> {
204 let ParserMatchClass = SImm7s8Operand;
205 let PrintMethod = "printImmScale8";
206}
207
208// simm7s16 predicate - True if the immediate is a multiple of 16 in the range
209// [-1024, 1008].
210def SImm7s16Operand : AsmOperandClass {
211 let Name = "SImm7s16";
212 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
213}
214def simm7s16 : Operand<i32> {
215 let ParserMatchClass = SImm7s16Operand;
216 let PrintMethod = "printImmScale16";
217}
218
219// imm0_65535 predicate - True if the immediate is in the range [0,65535].
220def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
221def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
222 return ((uint32_t)Imm) < 65536;
223}]> {
224 let ParserMatchClass = Imm0_65535Operand;
225}
226
227def Imm1_8Operand : AsmOperandClass {
228 let Name = "Imm1_8";
229 let DiagnosticType = "InvalidImm1_8";
230}
231def Imm1_16Operand : AsmOperandClass {
232 let Name = "Imm1_16";
233 let DiagnosticType = "InvalidImm1_16";
234}
235def Imm1_32Operand : AsmOperandClass {
236 let Name = "Imm1_32";
237 let DiagnosticType = "InvalidImm1_32";
238}
239def Imm1_64Operand : AsmOperandClass {
240 let Name = "Imm1_64";
241 let DiagnosticType = "InvalidImm1_64";
242}
243
244def MovZSymbolG3AsmOperand : AsmOperandClass {
245 let Name = "MovZSymbolG3";
246 let RenderMethod = "addImmOperands";
247}
248
249def movz_symbol_g3 : Operand<i32> {
250 let ParserMatchClass = MovZSymbolG3AsmOperand;
251}
252
253def MovZSymbolG2AsmOperand : AsmOperandClass {
254 let Name = "MovZSymbolG2";
255 let RenderMethod = "addImmOperands";
256}
257
258def movz_symbol_g2 : Operand<i32> {
259 let ParserMatchClass = MovZSymbolG2AsmOperand;
260}
261
262def MovZSymbolG1AsmOperand : AsmOperandClass {
263 let Name = "MovZSymbolG1";
264 let RenderMethod = "addImmOperands";
265}
266
267def movz_symbol_g1 : Operand<i32> {
268 let ParserMatchClass = MovZSymbolG1AsmOperand;
269}
270
271def MovZSymbolG0AsmOperand : AsmOperandClass {
272 let Name = "MovZSymbolG0";
273 let RenderMethod = "addImmOperands";
274}
275
276def movz_symbol_g0 : Operand<i32> {
277 let ParserMatchClass = MovZSymbolG0AsmOperand;
278}
279
280def MovKSymbolG2AsmOperand : AsmOperandClass {
281 let Name = "MovKSymbolG2";
282 let RenderMethod = "addImmOperands";
283}
284
285def movk_symbol_g2 : Operand<i32> {
286 let ParserMatchClass = MovKSymbolG2AsmOperand;
287}
288
289def MovKSymbolG1AsmOperand : AsmOperandClass {
290 let Name = "MovKSymbolG1";
291 let RenderMethod = "addImmOperands";
292}
293
294def movk_symbol_g1 : Operand<i32> {
295 let ParserMatchClass = MovKSymbolG1AsmOperand;
296}
297
298def MovKSymbolG0AsmOperand : AsmOperandClass {
299 let Name = "MovKSymbolG0";
300 let RenderMethod = "addImmOperands";
301}
302
303def movk_symbol_g0 : Operand<i32> {
304 let ParserMatchClass = MovKSymbolG0AsmOperand;
305}
306
307def fixedpoint32 : Operand<i32> {
308 let EncoderMethod = "getFixedPointScaleOpValue";
Bradley Smitheb4ca042014-04-09 14:43:35 +0000309 let DecoderMethod = "DecodeFixedPointScaleImm32";
Tim Northover00ed9962014-03-29 10:18:08 +0000310 let ParserMatchClass = Imm1_32Operand;
311}
312def fixedpoint64 : Operand<i64> {
313 let EncoderMethod = "getFixedPointScaleOpValue";
Bradley Smitheb4ca042014-04-09 14:43:35 +0000314 let DecoderMethod = "DecodeFixedPointScaleImm64";
Tim Northover00ed9962014-03-29 10:18:08 +0000315 let ParserMatchClass = Imm1_64Operand;
316}
317
318def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
319 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
320}]> {
321 let EncoderMethod = "getVecShiftR8OpValue";
322 let DecoderMethod = "DecodeVecShiftR8Imm";
323 let ParserMatchClass = Imm1_8Operand;
324}
325def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
326 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
327}]> {
328 let EncoderMethod = "getVecShiftR16OpValue";
329 let DecoderMethod = "DecodeVecShiftR16Imm";
330 let ParserMatchClass = Imm1_16Operand;
331}
332def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
333 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
334}]> {
335 let EncoderMethod = "getVecShiftR16OpValue";
336 let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
337 let ParserMatchClass = Imm1_8Operand;
338}
339def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
340 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
341}]> {
342 let EncoderMethod = "getVecShiftR32OpValue";
343 let DecoderMethod = "DecodeVecShiftR32Imm";
344 let ParserMatchClass = Imm1_32Operand;
345}
346def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
347 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
348}]> {
349 let EncoderMethod = "getVecShiftR32OpValue";
350 let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
351 let ParserMatchClass = Imm1_16Operand;
352}
353def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
354 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
355}]> {
356 let EncoderMethod = "getVecShiftR64OpValue";
357 let DecoderMethod = "DecodeVecShiftR64Imm";
358 let ParserMatchClass = Imm1_64Operand;
359}
360def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
361 return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
362}]> {
363 let EncoderMethod = "getVecShiftR64OpValue";
364 let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
365 let ParserMatchClass = Imm1_32Operand;
366}
367
368def Imm0_7Operand : AsmOperandClass { let Name = "Imm0_7"; }
369def Imm0_15Operand : AsmOperandClass { let Name = "Imm0_15"; }
370def Imm0_31Operand : AsmOperandClass { let Name = "Imm0_31"; }
371def Imm0_63Operand : AsmOperandClass { let Name = "Imm0_63"; }
372
373def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
374 return (((uint32_t)Imm) < 8);
375}]> {
376 let EncoderMethod = "getVecShiftL8OpValue";
377 let DecoderMethod = "DecodeVecShiftL8Imm";
378 let ParserMatchClass = Imm0_7Operand;
379}
380def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
381 return (((uint32_t)Imm) < 16);
382}]> {
383 let EncoderMethod = "getVecShiftL16OpValue";
384 let DecoderMethod = "DecodeVecShiftL16Imm";
385 let ParserMatchClass = Imm0_15Operand;
386}
387def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
388 return (((uint32_t)Imm) < 32);
389}]> {
390 let EncoderMethod = "getVecShiftL32OpValue";
391 let DecoderMethod = "DecodeVecShiftL32Imm";
392 let ParserMatchClass = Imm0_31Operand;
393}
394def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
395 return (((uint32_t)Imm) < 64);
396}]> {
397 let EncoderMethod = "getVecShiftL64OpValue";
398 let DecoderMethod = "DecodeVecShiftL64Imm";
399 let ParserMatchClass = Imm0_63Operand;
400}
401
402
403// Crazy immediate formats used by 32-bit and 64-bit logical immediate
404// instructions for splatting repeating bit patterns across the immediate.
405def logical_imm32_XFORM : SDNodeXForm<imm, [{
406 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
407 return CurDAG->getTargetConstant(enc, MVT::i32);
408}]>;
409def logical_imm64_XFORM : SDNodeXForm<imm, [{
410 uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
411 return CurDAG->getTargetConstant(enc, MVT::i32);
412}]>;
413
414def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
415def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
416def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
417 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
418}], logical_imm32_XFORM> {
419 let PrintMethod = "printLogicalImm32";
420 let ParserMatchClass = LogicalImm32Operand;
421}
422def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
423 return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
424}], logical_imm64_XFORM> {
425 let PrintMethod = "printLogicalImm64";
426 let ParserMatchClass = LogicalImm64Operand;
427}
428
429// imm0_255 predicate - True if the immediate is in the range [0,255].
430def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
431def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
432 return ((uint32_t)Imm) < 256;
433}]> {
434 let ParserMatchClass = Imm0_255Operand;
435}
436
437// imm0_127 predicate - True if the immediate is in the range [0,127]
438def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
439def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
440 return ((uint32_t)Imm) < 128;
441}]> {
442 let ParserMatchClass = Imm0_127Operand;
443}
444
Tim Northover2ad88d32014-04-03 09:26:16 +0000445// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
446// for all shift-amounts.
447
Tim Northover00ed9962014-03-29 10:18:08 +0000448// imm0_63 predicate - True if the immediate is in the range [0,63]
Tim Northover00ed9962014-03-29 10:18:08 +0000449def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
450 return ((uint64_t)Imm) < 64;
451}]> {
452 let ParserMatchClass = Imm0_63Operand;
453}
454
Tim Northover2ad88d32014-04-03 09:26:16 +0000455// imm0_31 predicate - True if the immediate is in the range [0,31]
456def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000457 return ((uint64_t)Imm) < 32;
458}]> {
459 let ParserMatchClass = Imm0_31Operand;
460}
461
Tim Northover2ad88d32014-04-03 09:26:16 +0000462// imm0_15 predicate - True if the immediate is in the range [0,15]
463def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
Tim Northover00ed9962014-03-29 10:18:08 +0000464 return ((uint64_t)Imm) < 16;
465}]> {
466 let ParserMatchClass = Imm0_15Operand;
467}
468
Tim Northover00ed9962014-03-29 10:18:08 +0000469// imm0_7 predicate - True if the immediate is in the range [0,7]
Tim Northover2ad88d32014-04-03 09:26:16 +0000470def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
471 return ((uint64_t)Imm) < 8;
Tim Northover00ed9962014-03-29 10:18:08 +0000472}]> {
473 let ParserMatchClass = Imm0_7Operand;
474}
475
476// An arithmetic shifter operand:
477// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
478// {5-0} - imm6
479def arith_shift : Operand<i32> {
480 let PrintMethod = "printShifter";
481 let ParserMatchClass = ArithmeticShifterOperand;
482}
483
484class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
485 : Operand<Ty>,
486 ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
487 let PrintMethod = "printShiftedRegister";
488 let MIOperandInfo = (ops regclass, arith_shift);
489}
490
491def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
492def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
493
494// An arithmetic shifter operand:
495// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
496// {5-0} - imm6
497def logical_shift : Operand<i32> {
498 let PrintMethod = "printShifter";
499 let ParserMatchClass = ShifterOperand;
500}
501
502class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
503 : Operand<Ty>,
504 ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
505 let PrintMethod = "printShiftedRegister";
506 let MIOperandInfo = (ops regclass, logical_shift);
507}
508
509def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
510def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
511
512// A logical vector shifter operand:
513// {7-6} - shift type: 00 = lsl
514// {5-0} - imm6: #0, #8, #16, or #24
515def logical_vec_shift : Operand<i32> {
516 let PrintMethod = "printShifter";
517 let EncoderMethod = "getVecShifterOpValue";
518 let ParserMatchClass = LogicalVecShifterOperand;
519}
520
521// A logical vector half-word shifter operand:
522// {7-6} - shift type: 00 = lsl
523// {5-0} - imm6: #0 or #8
524def logical_vec_hw_shift : Operand<i32> {
525 let PrintMethod = "printShifter";
526 let EncoderMethod = "getVecShifterOpValue";
527 let ParserMatchClass = LogicalVecHalfWordShifterOperand;
528}
529
530// A vector move shifter operand:
531// {0} - imm1: #8 or #16
532def move_vec_shift : Operand<i32> {
533 let PrintMethod = "printShifter";
534 let EncoderMethod = "getMoveVecShifterOpValue";
535 let ParserMatchClass = MoveVecShifterOperand;
536}
537
538// An ADD/SUB immediate shifter operand:
539// {7-6} - shift type: 00 = lsl
540// {5-0} - imm6: #0 or #12
541def addsub_shift : Operand<i32> {
542 let ParserMatchClass = AddSubShifterOperand;
543}
544
545class addsub_shifted_imm<ValueType Ty>
546 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
547 let PrintMethod = "printAddSubImm";
548 let EncoderMethod = "getAddSubImmOpValue";
549 let MIOperandInfo = (ops i32imm, addsub_shift);
550}
551
552def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
553def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
554
555class neg_addsub_shifted_imm<ValueType Ty>
556 : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
557 let PrintMethod = "printAddSubImm";
558 let EncoderMethod = "getAddSubImmOpValue";
559 let MIOperandInfo = (ops i32imm, addsub_shift);
560}
561
562def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
563def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
564
565// An extend operand:
566// {5-3} - extend type
567// {2-0} - imm3
568def arith_extend : Operand<i32> {
569 let PrintMethod = "printExtend";
570 let ParserMatchClass = ExtendOperand;
571}
572def arith_extend64 : Operand<i32> {
573 let PrintMethod = "printExtend";
574 let ParserMatchClass = ExtendOperand64;
575}
576
577// 'extend' that's a lsl of a 64-bit register.
578def arith_extendlsl64 : Operand<i32> {
579 let PrintMethod = "printExtend";
580 let ParserMatchClass = ExtendOperandLSL64;
581}
582
583class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
584 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
585 let PrintMethod = "printExtendedRegister";
586 let MIOperandInfo = (ops GPR32, arith_extend);
587}
588
589class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
590 ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
591 let PrintMethod = "printExtendedRegister";
592 let MIOperandInfo = (ops GPR32, arith_extend64);
593}
594
595// Floating-point immediate.
596def fpimm32 : Operand<f32>,
597 PatLeaf<(f32 fpimm), [{
598 return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
599 }], SDNodeXForm<fpimm, [{
600 APFloat InVal = N->getValueAPF();
601 uint32_t enc = ARM64_AM::getFP32Imm(InVal);
602 return CurDAG->getTargetConstant(enc, MVT::i32);
603 }]>> {
604 let ParserMatchClass = FPImmOperand;
605 let PrintMethod = "printFPImmOperand";
606}
607def fpimm64 : Operand<f64>,
608 PatLeaf<(f64 fpimm), [{
609 return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
610 }], SDNodeXForm<fpimm, [{
611 APFloat InVal = N->getValueAPF();
612 uint32_t enc = ARM64_AM::getFP64Imm(InVal);
613 return CurDAG->getTargetConstant(enc, MVT::i32);
614 }]>> {
615 let ParserMatchClass = FPImmOperand;
616 let PrintMethod = "printFPImmOperand";
617}
618
619def fpimm8 : Operand<i32> {
620 let ParserMatchClass = FPImmOperand;
621 let PrintMethod = "printFPImmOperand";
622}
623
624def fpimm0 : PatLeaf<(fpimm), [{
625 return N->isExactlyValue(+0.0);
626}]>;
627
628// 8-bit immediate for AdvSIMD where 64-bit values of the form:
629// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
630// are encoded as the eight bit value 'abcdefgh'.
631def simdimmtype10 : Operand<i32>,
632 PatLeaf<(f64 fpimm), [{
633 return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
634 .bitcastToAPInt()
635 .getZExtValue());
636 }], SDNodeXForm<fpimm, [{
637 APFloat InVal = N->getValueAPF();
638 uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
639 .bitcastToAPInt()
640 .getZExtValue());
641 return CurDAG->getTargetConstant(enc, MVT::i32);
642 }]>> {
643 let ParserMatchClass = SIMDImmType10Operand;
644 let PrintMethod = "printSIMDType10Operand";
645}
646
647
648//---
649// Sytem management
650//---
651
652// Base encoding for system instruction operands.
653let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
654class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
655 : I<oops, iops, asm, operands, "", []> {
656 let Inst{31-22} = 0b1101010100;
657 let Inst{21} = L;
658}
659
660// System instructions which do not have an Rt register.
661class SimpleSystemI<bit L, dag iops, string asm, string operands>
662 : BaseSystemI<L, (outs), iops, asm, operands> {
663 let Inst{4-0} = 0b11111;
664}
665
666// System instructions which have an Rt register.
667class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
668 : BaseSystemI<L, oops, iops, asm, operands>,
669 Sched<[WriteSys]> {
670 bits<5> Rt;
671 let Inst{4-0} = Rt;
672}
673
674// Hint instructions that take both a CRm and a 3-bit immediate.
675class HintI<string mnemonic>
676 : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
677 Sched<[WriteHint]> {
678 bits <7> imm;
679 let Inst{20-12} = 0b000110010;
680 let Inst{11-5} = imm;
681}
682
683// System instructions taking a single literal operand which encodes into
684// CRm. op2 differentiates the opcodes.
685def BarrierAsmOperand : AsmOperandClass {
686 let Name = "Barrier";
687 let ParserMethod = "tryParseBarrierOperand";
688}
689def barrier_op : Operand<i32> {
690 let PrintMethod = "printBarrierOption";
691 let ParserMatchClass = BarrierAsmOperand;
692}
693class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
694 : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
695 Sched<[WriteBarrier]> {
696 bits<4> CRm;
697 let Inst{20-12} = 0b000110011;
698 let Inst{11-8} = CRm;
699 let Inst{7-5} = opc;
700}
701
Bradley Smith08c391c2014-04-09 14:42:36 +0000702// MRS/MSR system instructions. These have different operand classes because
703// a different subset of registers can be accessed through each instruction.
704def MRSSystemRegisterOperand : AsmOperandClass {
705 let Name = "MRSSystemRegister";
Bradley Smithe8b41662014-04-09 14:43:06 +0000706 let ParserMethod = "tryParseSysReg";
Tim Northover00ed9962014-03-29 10:18:08 +0000707}
708// concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
Bradley Smith08c391c2014-04-09 14:42:36 +0000709def mrs_sysreg_op : Operand<i32> {
710 let ParserMatchClass = MRSSystemRegisterOperand;
711 let DecoderMethod = "DecodeMRSSystemRegister";
712 let PrintMethod = "printMRSSystemRegister";
Tim Northover00ed9962014-03-29 10:18:08 +0000713}
714
Bradley Smith08c391c2014-04-09 14:42:36 +0000715def MSRSystemRegisterOperand : AsmOperandClass {
716 let Name = "MSRSystemRegister";
Bradley Smithe8b41662014-04-09 14:43:06 +0000717 let ParserMethod = "tryParseSysReg";
Bradley Smith08c391c2014-04-09 14:42:36 +0000718}
719def msr_sysreg_op : Operand<i32> {
720 let ParserMatchClass = MSRSystemRegisterOperand;
721 let DecoderMethod = "DecodeMSRSystemRegister";
722 let PrintMethod = "printMSRSystemRegister";
723}
724
725class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
Tim Northover00ed9962014-03-29 10:18:08 +0000726 "mrs", "\t$Rt, $systemreg"> {
727 bits<15> systemreg;
728 let Inst{20} = 1;
729 let Inst{19-5} = systemreg;
730}
731
732// FIXME: Some of these def CPSR, others don't. Best way to model that?
733// Explicitly modeling each of the system register as a register class
734// would do it, but feels like overkill at this point.
Bradley Smith08c391c2014-04-09 14:42:36 +0000735class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
Tim Northover00ed9962014-03-29 10:18:08 +0000736 "msr", "\t$systemreg, $Rt"> {
737 bits<15> systemreg;
738 let Inst{20} = 1;
739 let Inst{19-5} = systemreg;
740}
741
742def SystemCPSRFieldOperand : AsmOperandClass {
743 let Name = "SystemCPSRField";
Bradley Smithe8b41662014-04-09 14:43:06 +0000744 let ParserMethod = "tryParseSysReg";
Tim Northover00ed9962014-03-29 10:18:08 +0000745}
746def cpsrfield_op : Operand<i32> {
747 let ParserMatchClass = SystemCPSRFieldOperand;
748 let PrintMethod = "printSystemCPSRField";
749}
750
751let Defs = [CPSR] in
752class MSRcpsrI : SimpleSystemI<0, (ins cpsrfield_op:$cpsr_field, imm0_15:$imm),
753 "msr", "\t$cpsr_field, $imm">,
754 Sched<[WriteSys]> {
755 bits<6> cpsrfield;
756 bits<4> imm;
757 let Inst{20-19} = 0b00;
758 let Inst{18-16} = cpsrfield{5-3};
759 let Inst{15-12} = 0b0100;
760 let Inst{11-8} = imm;
761 let Inst{7-5} = cpsrfield{2-0};
762
763 let DecoderMethod = "DecodeSystemCPSRInstruction";
764}
765
766// SYS and SYSL generic system instructions.
767def SysCRAsmOperand : AsmOperandClass {
768 let Name = "SysCR";
769 let ParserMethod = "tryParseSysCROperand";
770}
771
772def sys_cr_op : Operand<i32> {
773 let PrintMethod = "printSysCROperand";
774 let ParserMatchClass = SysCRAsmOperand;
775}
776
777class SystemI<bit L, string asm>
778 : SimpleSystemI<L,
779 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
780 asm, "\t$op1, $Cn, $Cm, $op2">,
781 Sched<[WriteSys]> {
782 bits<3> op1;
783 bits<4> Cn;
784 bits<4> Cm;
785 bits<3> op2;
786 let Inst{20-19} = 0b01;
787 let Inst{18-16} = op1;
788 let Inst{15-12} = Cn;
789 let Inst{11-8} = Cm;
790 let Inst{7-5} = op2;
791}
792
793class SystemXtI<bit L, string asm>
794 : RtSystemI<L, (outs),
795 (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
796 asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
797 bits<3> op1;
798 bits<4> Cn;
799 bits<4> Cm;
800 bits<3> op2;
801 let Inst{20-19} = 0b01;
802 let Inst{18-16} = op1;
803 let Inst{15-12} = Cn;
804 let Inst{11-8} = Cm;
805 let Inst{7-5} = op2;
806}
807
808class SystemLXtI<bit L, string asm>
809 : RtSystemI<L, (outs),
810 (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
811 asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
812 bits<3> op1;
813 bits<4> Cn;
814 bits<4> Cm;
815 bits<3> op2;
816 let Inst{20-19} = 0b01;
817 let Inst{18-16} = op1;
818 let Inst{15-12} = Cn;
819 let Inst{11-8} = Cm;
820 let Inst{7-5} = op2;
821}
822
823
824// Branch (register) instructions:
825//
826// case opc of
827// 0001 blr
828// 0000 br
829// 0101 dret
830// 0100 eret
831// 0010 ret
832// otherwise UNDEFINED
833class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
834 string operands, list<dag> pattern>
835 : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
836 let Inst{31-25} = 0b1101011;
837 let Inst{24-21} = opc;
838 let Inst{20-16} = 0b11111;
839 let Inst{15-10} = 0b000000;
840 let Inst{4-0} = 0b00000;
841}
842
843class BranchReg<bits<4> opc, string asm, list<dag> pattern>
844 : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
845 bits<5> Rn;
846 let Inst{9-5} = Rn;
847}
848
849let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
850class SpecialReturn<bits<4> opc, string asm>
851 : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
852 let Inst{9-5} = 0b11111;
853}
854
855//---
856// Conditional branch instruction.
857//---
858// Branch condition code.
859// 4-bit immediate. Pretty-printed as .<cc>
860def dotCcode : Operand<i32> {
861 let PrintMethod = "printDotCondCode";
862}
863
864// Conditional branch target. 19-bit immediate. The low two bits of the target
865// offset are implied zero and so are not part of the immediate.
866def BranchTarget19Operand : AsmOperandClass {
867 let Name = "BranchTarget19";
868}
869def am_brcond : Operand<OtherVT> {
870 let EncoderMethod = "getCondBranchTargetOpValue";
871 let DecoderMethod = "DecodeCondBranchTarget";
872 let PrintMethod = "printAlignedBranchTarget";
873 let ParserMatchClass = BranchTarget19Operand;
874}
875
876class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
877 "b", "$cond\t$target", "",
878 [(ARM64brcond bb:$target, imm:$cond, CPSR)]>,
879 Sched<[WriteBr]> {
880 let isBranch = 1;
881 let isTerminator = 1;
882 let Uses = [CPSR];
883
884 bits<4> cond;
885 bits<19> target;
886 let Inst{31-24} = 0b01010100;
887 let Inst{23-5} = target;
888 let Inst{4} = 0;
889 let Inst{3-0} = cond;
890}
891
892//---
893// Compare-and-branch instructions.
894//---
895class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
896 : I<(outs), (ins regtype:$Rt, am_brcond:$target),
897 asm, "\t$Rt, $target", "",
898 [(node regtype:$Rt, bb:$target)]>,
899 Sched<[WriteBr]> {
900 let isBranch = 1;
901 let isTerminator = 1;
902
903 bits<5> Rt;
904 bits<19> target;
905 let Inst{30-25} = 0b011010;
906 let Inst{24} = op;
907 let Inst{23-5} = target;
908 let Inst{4-0} = Rt;
909}
910
911multiclass CmpBranch<bit op, string asm, SDNode node> {
912 def W : BaseCmpBranch<GPR32, op, asm, node> {
913 let Inst{31} = 0;
914 }
915 def X : BaseCmpBranch<GPR64, op, asm, node> {
916 let Inst{31} = 1;
917 }
918}
919
920//---
921// Test-bit-and-branch instructions.
922//---
923// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
924// the target offset are implied zero and so are not part of the immediate.
925def BranchTarget14Operand : AsmOperandClass {
926 let Name = "BranchTarget14";
927}
928def am_tbrcond : Operand<OtherVT> {
929 let EncoderMethod = "getTestBranchTargetOpValue";
930 let PrintMethod = "printAlignedBranchTarget";
931 let ParserMatchClass = BranchTarget14Operand;
932}
933
934class TestBranch<bit op, string asm, SDNode node>
935 : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
936 asm, "\t$Rt, $bit_off, $target", "",
937 [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
938 Sched<[WriteBr]> {
939 let isBranch = 1;
940 let isTerminator = 1;
941
942 bits<5> Rt;
943 bits<6> bit_off;
944 bits<14> target;
945
946 let Inst{31} = bit_off{5};
947 let Inst{30-25} = 0b011011;
948 let Inst{24} = op;
949 let Inst{23-19} = bit_off{4-0};
950 let Inst{18-5} = target;
951 let Inst{4-0} = Rt;
952
953 let DecoderMethod = "DecodeTestAndBranch";
954}
955
956//---
957// Unconditional branch (immediate) instructions.
958//---
959def BranchTarget26Operand : AsmOperandClass {
960 let Name = "BranchTarget26";
961}
962def am_b_target : Operand<OtherVT> {
963 let EncoderMethod = "getBranchTargetOpValue";
964 let PrintMethod = "printAlignedBranchTarget";
965 let ParserMatchClass = BranchTarget26Operand;
966}
967def am_bl_target : Operand<i64> {
968 let EncoderMethod = "getBranchTargetOpValue";
969 let PrintMethod = "printAlignedBranchTarget";
970 let ParserMatchClass = BranchTarget26Operand;
971}
972
973class BImm<bit op, dag iops, string asm, list<dag> pattern>
974 : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
975 bits<26> addr;
976 let Inst{31} = op;
977 let Inst{30-26} = 0b00101;
978 let Inst{25-0} = addr;
979
980 let DecoderMethod = "DecodeUnconditionalBranch";
981}
982
983class BranchImm<bit op, string asm, list<dag> pattern>
984 : BImm<op, (ins am_b_target:$addr), asm, pattern>;
985class CallImm<bit op, string asm, list<dag> pattern>
986 : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
987
988//---
989// Basic one-operand data processing instructions.
990//---
991
992let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
993class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
994 SDPatternOperator node>
995 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
996 [(set regtype:$Rd, (node regtype:$Rn))]>,
997 Sched<[WriteI]> {
998 bits<5> Rd;
999 bits<5> Rn;
1000
1001 let Inst{30-13} = 0b101101011000000000;
1002 let Inst{12-10} = opc;
1003 let Inst{9-5} = Rn;
1004 let Inst{4-0} = Rd;
1005}
1006
1007let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1008multiclass OneOperandData<bits<3> opc, string asm,
1009 SDPatternOperator node = null_frag> {
1010 def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1011 let Inst{31} = 0;
1012 }
1013
1014 def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1015 let Inst{31} = 1;
1016 }
1017}
1018
1019class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1020 : BaseOneOperandData<opc, GPR32, asm, node> {
1021 let Inst{31} = 0;
1022}
1023
1024class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1025 : BaseOneOperandData<opc, GPR64, asm, node> {
1026 let Inst{31} = 1;
1027}
1028
1029//---
1030// Basic two-operand data processing instructions.
1031//---
1032class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1033 list<dag> pattern>
1034 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1035 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1036 Sched<[WriteI]> {
1037 let Uses = [CPSR];
1038 bits<5> Rd;
1039 bits<5> Rn;
1040 bits<5> Rm;
1041 let Inst{30} = isSub;
1042 let Inst{28-21} = 0b11010000;
1043 let Inst{20-16} = Rm;
1044 let Inst{15-10} = 0;
1045 let Inst{9-5} = Rn;
1046 let Inst{4-0} = Rd;
1047}
1048
1049class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1050 SDNode OpNode>
1051 : BaseBaseAddSubCarry<isSub, regtype, asm,
1052 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR))]>;
1053
1054class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1055 SDNode OpNode>
1056 : BaseBaseAddSubCarry<isSub, regtype, asm,
1057 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, CPSR)),
1058 (implicit CPSR)]> {
1059 let Defs = [CPSR];
1060}
1061
1062multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1063 SDNode OpNode, SDNode OpNode_setflags> {
1064 def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1065 let Inst{31} = 0;
1066 let Inst{29} = 0;
1067 }
1068 def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1069 let Inst{31} = 1;
1070 let Inst{29} = 0;
1071 }
1072
1073 // Sets flags.
1074 def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1075 OpNode_setflags> {
1076 let Inst{31} = 0;
1077 let Inst{29} = 1;
1078 }
1079 def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1080 OpNode_setflags> {
1081 let Inst{31} = 1;
1082 let Inst{29} = 1;
1083 }
1084}
1085
1086class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1087 SDPatternOperator OpNode>
1088 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1089 asm, "\t$Rd, $Rn, $Rm", "",
1090 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1091 bits<5> Rd;
1092 bits<5> Rn;
1093 bits<5> Rm;
1094 let Inst{30-21} = 0b0011010110;
1095 let Inst{20-16} = Rm;
1096 let Inst{15-14} = 0b00;
1097 let Inst{13-10} = opc;
1098 let Inst{9-5} = Rn;
1099 let Inst{4-0} = Rd;
1100}
1101
1102class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1103 SDPatternOperator OpNode>
1104 : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1105 let Inst{10} = isSigned;
1106}
1107
1108multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1109 def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1110 Sched<[WriteID32]> {
1111 let Inst{31} = 0;
1112 }
1113 def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1114 Sched<[WriteID64]> {
1115 let Inst{31} = 1;
1116 }
1117}
1118
Tim Northover2ad88d32014-04-03 09:26:16 +00001119class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1120 SDPatternOperator OpNode = null_frag>
Tim Northover00ed9962014-03-29 10:18:08 +00001121 : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1122 Sched<[WriteIS]> {
1123 let Inst{11-10} = shift_type;
1124}
1125
1126multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
Tim Northover2ad88d32014-04-03 09:26:16 +00001127 def Wr : BaseShift<shift_type, GPR32, asm> {
Tim Northover00ed9962014-03-29 10:18:08 +00001128 let Inst{31} = 0;
1129 }
1130
1131 def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1132 let Inst{31} = 1;
1133 }
Tim Northover2ad88d32014-04-03 09:26:16 +00001134
1135 def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1136 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1137 (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1138
1139 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1140 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1141
1142 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1143 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1144
1145 def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1146 (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00001147}
1148
1149class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1150 : InstAlias<asm#" $dst, $src1, $src2",
1151 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1152
1153class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1154 RegisterClass addtype, string asm,
1155 list<dag> pattern>
1156 : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1157 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1158 bits<5> Rd;
1159 bits<5> Rn;
1160 bits<5> Rm;
1161 bits<5> Ra;
1162 let Inst{30-24} = 0b0011011;
1163 let Inst{23-21} = opc;
1164 let Inst{20-16} = Rm;
1165 let Inst{15} = isSub;
1166 let Inst{14-10} = Ra;
1167 let Inst{9-5} = Rn;
1168 let Inst{4-0} = Rd;
1169}
1170
1171multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1172 def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1173 [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1174 Sched<[WriteIM32]> {
1175 let Inst{31} = 0;
1176 }
1177
1178 def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1179 [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1180 Sched<[WriteIM64]> {
1181 let Inst{31} = 1;
1182 }
1183}
1184
1185class WideMulAccum<bit isSub, bits<3> opc, string asm,
1186 SDNode AccNode, SDNode ExtNode>
1187 : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1188 [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1189 (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1190 Sched<[WriteIM32]> {
1191 let Inst{31} = 1;
1192}
1193
1194class MulHi<bits<3> opc, string asm, SDNode OpNode>
1195 : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1196 asm, "\t$Rd, $Rn, $Rm", "",
1197 [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1198 Sched<[WriteIM64]> {
1199 bits<5> Rd;
1200 bits<5> Rn;
1201 bits<5> Rm;
1202 let Inst{31-24} = 0b10011011;
1203 let Inst{23-21} = opc;
1204 let Inst{20-16} = Rm;
Bradley Smith8f906a32014-04-09 14:43:15 +00001205 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001206 let Inst{9-5} = Rn;
1207 let Inst{4-0} = Rd;
Bradley Smith8f906a32014-04-09 14:43:15 +00001208
1209 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1210 // (i.e. all bits 1) but is ignored by the processor.
1211 let PostEncoderMethod = "fixMulHigh";
Tim Northover00ed9962014-03-29 10:18:08 +00001212}
1213
1214class MulAccumWAlias<string asm, Instruction inst>
1215 : InstAlias<asm#" $dst, $src1, $src2",
1216 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1217class MulAccumXAlias<string asm, Instruction inst>
1218 : InstAlias<asm#" $dst, $src1, $src2",
1219 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1220class WideMulAccumAlias<string asm, Instruction inst>
1221 : InstAlias<asm#" $dst, $src1, $src2",
1222 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1223
1224class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1225 SDPatternOperator OpNode, string asm>
1226 : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1227 asm, "\t$Rd, $Rn, $Rm", "",
1228 [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1229 Sched<[WriteISReg]> {
1230 bits<5> Rd;
1231 bits<5> Rn;
1232 bits<5> Rm;
1233
1234 let Inst{31} = sf;
1235 let Inst{30-21} = 0b0011010110;
1236 let Inst{20-16} = Rm;
1237 let Inst{15-13} = 0b010;
1238 let Inst{12} = C;
1239 let Inst{11-10} = sz;
1240 let Inst{9-5} = Rn;
1241 let Inst{4-0} = Rd;
1242}
1243
1244//---
1245// Address generation.
1246//---
1247
1248class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1249 : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1250 pattern>,
1251 Sched<[WriteI]> {
1252 bits<5> Xd;
1253 bits<21> label;
1254 let Inst{31} = page;
1255 let Inst{30-29} = label{1-0};
1256 let Inst{28-24} = 0b10000;
1257 let Inst{23-5} = label{20-2};
1258 let Inst{4-0} = Xd;
1259
1260 let DecoderMethod = "DecodeAdrInstruction";
1261}
1262
1263//---
1264// Move immediate.
1265//---
1266
1267def movimm32_imm : Operand<i32> {
1268 let ParserMatchClass = Imm0_65535Operand;
1269 let EncoderMethod = "getMoveWideImmOpValue";
1270}
1271def movimm32_shift : Operand<i32> {
1272 let PrintMethod = "printShifter";
1273 let ParserMatchClass = MovImm32ShifterOperand;
1274}
1275def movimm64_shift : Operand<i32> {
1276 let PrintMethod = "printShifter";
1277 let ParserMatchClass = MovImm64ShifterOperand;
1278}
1279let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1280class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1281 string asm>
1282 : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1283 asm, "\t$Rd, $imm$shift", "", []>,
1284 Sched<[WriteImm]> {
1285 bits<5> Rd;
1286 bits<16> imm;
1287 bits<6> shift;
1288 let Inst{30-29} = opc;
1289 let Inst{28-23} = 0b100101;
1290 let Inst{22-21} = shift{5-4};
1291 let Inst{20-5} = imm;
1292 let Inst{4-0} = Rd;
1293
1294 let DecoderMethod = "DecodeMoveImmInstruction";
1295}
1296
1297multiclass MoveImmediate<bits<2> opc, string asm> {
1298 def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1299 let Inst{31} = 0;
1300 }
1301
1302 def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1303 let Inst{31} = 1;
1304 }
1305}
1306
1307let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1308class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1309 string asm>
1310 : I<(outs regtype:$Rd),
1311 (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1312 asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1313 Sched<[WriteI]> {
1314 bits<5> Rd;
1315 bits<16> imm;
1316 bits<6> shift;
1317 let Inst{30-29} = opc;
1318 let Inst{28-23} = 0b100101;
1319 let Inst{22-21} = shift{5-4};
1320 let Inst{20-5} = imm;
1321 let Inst{4-0} = Rd;
1322
1323 let DecoderMethod = "DecodeMoveImmInstruction";
1324}
1325
1326multiclass InsertImmediate<bits<2> opc, string asm> {
1327 def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1328 let Inst{31} = 0;
1329 }
1330
1331 def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1332 let Inst{31} = 1;
1333 }
1334}
1335
1336//---
1337// Add/Subtract
1338//---
1339
1340class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1341 RegisterClass srcRegtype, addsub_shifted_imm immtype,
1342 string asm, SDPatternOperator OpNode>
1343 : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1344 asm, "\t$Rd, $Rn, $imm", "",
1345 [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1346 Sched<[WriteI]> {
1347 bits<5> Rd;
1348 bits<5> Rn;
1349 bits<14> imm;
1350 let Inst{30} = isSub;
1351 let Inst{29} = setFlags;
1352 let Inst{28-24} = 0b10001;
1353 let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1354 let Inst{21-10} = imm{11-0};
1355 let Inst{9-5} = Rn;
1356 let Inst{4-0} = Rd;
1357 let DecoderMethod = "DecodeBaseAddSubImm";
1358}
1359
1360class BaseAddSubRegPseudo<RegisterClass regtype,
1361 SDPatternOperator OpNode>
1362 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1363 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1364 Sched<[WriteI]>;
1365
1366class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1367 arith_shifted_reg shifted_regtype, string asm,
1368 SDPatternOperator OpNode>
1369 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1370 asm, "\t$Rd, $Rn, $Rm", "",
1371 [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1372 Sched<[WriteISReg]> {
1373 // The operands are in order to match the 'addr' MI operands, so we
1374 // don't need an encoder method and by-name matching. Just use the default
1375 // in-order handling. Since we're using by-order, make sure the names
1376 // do not match.
1377 bits<5> dst;
1378 bits<5> src1;
1379 bits<5> src2;
1380 bits<8> shift;
1381 let Inst{30} = isSub;
1382 let Inst{29} = setFlags;
1383 let Inst{28-24} = 0b01011;
1384 let Inst{23-22} = shift{7-6};
1385 let Inst{21} = 0;
1386 let Inst{20-16} = src2;
1387 let Inst{15-10} = shift{5-0};
1388 let Inst{9-5} = src1;
1389 let Inst{4-0} = dst;
1390
1391 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1392}
1393
1394class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1395 RegisterClass src1Regtype, Operand src2Regtype,
1396 string asm, SDPatternOperator OpNode>
1397 : I<(outs dstRegtype:$R1),
1398 (ins src1Regtype:$R2, src2Regtype:$R3),
1399 asm, "\t$R1, $R2, $R3", "",
1400 [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1401 Sched<[WriteIEReg]> {
1402 bits<5> Rd;
1403 bits<5> Rn;
1404 bits<5> Rm;
1405 bits<6> ext;
1406 let Inst{30} = isSub;
1407 let Inst{29} = setFlags;
1408 let Inst{28-24} = 0b01011;
1409 let Inst{23-21} = 0b001;
1410 let Inst{20-16} = Rm;
1411 let Inst{15-13} = ext{5-3};
1412 let Inst{12-10} = ext{2-0};
1413 let Inst{9-5} = Rn;
1414 let Inst{4-0} = Rd;
1415
1416 let DecoderMethod = "DecodeAddSubERegInstruction";
1417}
1418
1419let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1420class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1421 RegisterClass src1Regtype, RegisterClass src2Regtype,
1422 Operand ext_op, string asm>
1423 : I<(outs dstRegtype:$Rd),
1424 (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1425 asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1426 Sched<[WriteIEReg]> {
1427 bits<5> Rd;
1428 bits<5> Rn;
1429 bits<5> Rm;
1430 bits<6> ext;
1431 let Inst{30} = isSub;
1432 let Inst{29} = setFlags;
1433 let Inst{28-24} = 0b01011;
1434 let Inst{23-21} = 0b001;
1435 let Inst{20-16} = Rm;
1436 let Inst{15} = ext{5};
1437 let Inst{12-10} = ext{2-0};
1438 let Inst{9-5} = Rn;
1439 let Inst{4-0} = Rd;
1440
1441 let DecoderMethod = "DecodeAddSubERegInstruction";
1442}
1443
1444// Aliases for register+register add/subtract.
1445class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1446 RegisterClass src1Regtype, RegisterClass src2Regtype,
1447 int shiftExt>
1448 : InstAlias<asm#" $dst, $src1, $src2",
1449 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1450 shiftExt)>;
1451
1452multiclass AddSub<bit isSub, string mnemonic,
1453 SDPatternOperator OpNode = null_frag> {
1454 let hasSideEffects = 0 in {
1455 // Add/Subtract immediate
1456 def Wri : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1457 mnemonic, OpNode> {
1458 let Inst{31} = 0;
1459 }
1460 def Xri : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1461 mnemonic, OpNode> {
1462 let Inst{31} = 1;
1463 }
1464
1465 // Add/Subtract register - Only used for CodeGen
1466 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1467 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1468
1469 // Add/Subtract shifted register
1470 def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1471 OpNode> {
1472 let Inst{31} = 0;
1473 }
1474 def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1475 OpNode> {
1476 let Inst{31} = 1;
1477 }
1478 }
1479
1480 // Add/Subtract extended register
1481 let AddedComplexity = 1, hasSideEffects = 0 in {
1482 def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1483 arith_extended_reg32<i32>, mnemonic, OpNode> {
1484 let Inst{31} = 0;
1485 }
1486 def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1487 arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1488 let Inst{31} = 1;
1489 }
1490 }
1491
1492 def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1493 arith_extendlsl64, mnemonic> {
1494 // UXTX and SXTX only.
1495 let Inst{14-13} = 0b11;
1496 let Inst{31} = 1;
1497 }
1498
1499 // Register/register aliases with no shift when SP is not used.
1500 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1501 GPR32, GPR32, GPR32, 0>;
1502 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1503 GPR64, GPR64, GPR64, 0>;
1504
1505 // Register/register aliases with no shift when either the destination or
1506 // first source register is SP. This relies on the shifted register aliases
1507 // above matching first in the case when SP is not used.
1508 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1509 GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1510 def : AddSubRegAlias<mnemonic,
1511 !cast<Instruction>(NAME#"Xrx64"),
1512 GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1513}
1514
1515multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1516 let isCompare = 1, Defs = [CPSR] in {
1517 // Add/Subtract immediate
1518 def Wri : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1519 mnemonic, OpNode> {
1520 let Inst{31} = 0;
1521 }
1522 def Xri : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1523 mnemonic, OpNode> {
1524 let Inst{31} = 1;
1525 }
1526
1527 // Add/Subtract register
1528 def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1529 def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1530
1531 // Add/Subtract shifted register
1532 def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1533 OpNode> {
1534 let Inst{31} = 0;
1535 }
1536 def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1537 OpNode> {
1538 let Inst{31} = 1;
1539 }
1540
1541 // Add/Subtract extended register
1542 let AddedComplexity = 1 in {
1543 def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1544 arith_extended_reg32<i32>, mnemonic, OpNode> {
1545 let Inst{31} = 0;
1546 }
1547 def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1548 arith_extended_reg32<i64>, mnemonic, OpNode> {
1549 let Inst{31} = 1;
1550 }
1551 }
1552
1553 def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1554 arith_extendlsl64, mnemonic> {
1555 // UXTX and SXTX only.
1556 let Inst{14-13} = 0b11;
1557 let Inst{31} = 1;
1558 }
1559 } // Defs = [CPSR]
1560
1561 // Register/register aliases with no shift when SP is not used.
1562 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1563 GPR32, GPR32, GPR32, 0>;
1564 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1565 GPR64, GPR64, GPR64, 0>;
1566
1567 // Register/register aliases with no shift when the first source register
1568 // is SP. This relies on the shifted register aliases above matching first
1569 // in the case when SP is not used.
1570 def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1571 GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1572 def : AddSubRegAlias<mnemonic,
1573 !cast<Instruction>(NAME#"Xrx64"),
1574 GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1575}
1576
1577//---
1578// Extract
1579//---
1580def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
Tim Northover2ad88d32014-04-03 09:26:16 +00001581 SDTCisPtrTy<3>]>;
Tim Northover00ed9962014-03-29 10:18:08 +00001582def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1583
1584class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1585 list<dag> patterns>
1586 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1587 asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1588 Sched<[WriteExtr, ReadExtrHi]> {
1589 bits<5> Rd;
1590 bits<5> Rn;
1591 bits<5> Rm;
1592 bits<6> imm;
1593
1594 let Inst{30-23} = 0b00100111;
1595 let Inst{21} = 0;
1596 let Inst{20-16} = Rm;
1597 let Inst{15-10} = imm;
1598 let Inst{9-5} = Rn;
1599 let Inst{4-0} = Rd;
1600}
1601
1602multiclass ExtractImm<string asm> {
1603 def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1604 [(set GPR32:$Rd,
1605 (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1606 let Inst{31} = 0;
1607 let Inst{22} = 0;
Bradley Smithdb7b9b12014-04-09 14:43:31 +00001608 // imm<5> must be zero.
1609 let imm{5} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001610 }
1611 def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1612 [(set GPR64:$Rd,
1613 (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1614
1615 let Inst{31} = 1;
1616 let Inst{22} = 1;
1617 }
1618}
1619
1620//---
1621// Bitfield
1622//---
1623
1624let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1625class BaseBitfieldImm<bits<2> opc,
1626 RegisterClass regtype, Operand imm_type, string asm>
1627 : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1628 asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1629 Sched<[WriteIS]> {
1630 bits<5> Rd;
1631 bits<5> Rn;
1632 bits<6> immr;
1633 bits<6> imms;
1634
1635 let Inst{30-29} = opc;
1636 let Inst{28-23} = 0b100110;
1637 let Inst{21-16} = immr;
1638 let Inst{15-10} = imms;
1639 let Inst{9-5} = Rn;
1640 let Inst{4-0} = Rd;
1641}
1642
1643multiclass BitfieldImm<bits<2> opc, string asm> {
1644 def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1645 let Inst{31} = 0;
1646 let Inst{22} = 0;
Bradley Smith7525b472014-04-09 14:43:24 +00001647 // imms<5> and immr<5> must be zero, else ReservedValue().
1648 let Inst{21} = 0;
1649 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001650 }
1651 def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1652 let Inst{31} = 1;
1653 let Inst{22} = 1;
1654 }
1655}
1656
1657let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1658class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1659 RegisterClass regtype, Operand imm_type, string asm>
1660 : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1661 imm_type:$imms),
1662 asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1663 Sched<[WriteIS]> {
1664 bits<5> Rd;
1665 bits<5> Rn;
1666 bits<6> immr;
1667 bits<6> imms;
1668
1669 let Inst{30-29} = opc;
1670 let Inst{28-23} = 0b100110;
1671 let Inst{21-16} = immr;
1672 let Inst{15-10} = imms;
1673 let Inst{9-5} = Rn;
1674 let Inst{4-0} = Rd;
1675}
1676
1677multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1678 def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1679 let Inst{31} = 0;
1680 let Inst{22} = 0;
Bradley Smith7525b472014-04-09 14:43:24 +00001681 // imms<5> and immr<5> must be zero, else ReservedValue().
1682 let Inst{21} = 0;
1683 let Inst{15} = 0;
Tim Northover00ed9962014-03-29 10:18:08 +00001684 }
1685 def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1686 let Inst{31} = 1;
1687 let Inst{22} = 1;
1688 }
1689}
1690
1691//---
1692// Logical
1693//---
1694
1695// Logical (immediate)
1696class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1697 RegisterClass sregtype, Operand imm_type, string asm,
1698 list<dag> pattern>
1699 : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1700 asm, "\t$Rd, $Rn, $imm", "", pattern>,
1701 Sched<[WriteI]> {
1702 bits<5> Rd;
1703 bits<5> Rn;
1704 bits<13> imm;
1705 let Inst{30-29} = opc;
1706 let Inst{28-23} = 0b100100;
1707 let Inst{22} = imm{12};
1708 let Inst{21-16} = imm{11-6};
1709 let Inst{15-10} = imm{5-0};
1710 let Inst{9-5} = Rn;
1711 let Inst{4-0} = Rd;
1712
1713 let DecoderMethod = "DecodeLogicalImmInstruction";
1714}
1715
1716// Logical (shifted register)
1717class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1718 logical_shifted_reg shifted_regtype, string asm,
1719 list<dag> pattern>
1720 : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1721 asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1722 Sched<[WriteISReg]> {
1723 // The operands are in order to match the 'addr' MI operands, so we
1724 // don't need an encoder method and by-name matching. Just use the default
1725 // in-order handling. Since we're using by-order, make sure the names
1726 // do not match.
1727 bits<5> dst;
1728 bits<5> src1;
1729 bits<5> src2;
1730 bits<8> shift;
1731 let Inst{30-29} = opc;
1732 let Inst{28-24} = 0b01010;
1733 let Inst{23-22} = shift{7-6};
1734 let Inst{21} = N;
1735 let Inst{20-16} = src2;
1736 let Inst{15-10} = shift{5-0};
1737 let Inst{9-5} = src1;
1738 let Inst{4-0} = dst;
1739
1740 let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1741}
1742
1743// Aliases for register+register logical instructions.
1744class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1745 : InstAlias<asm#" $dst, $src1, $src2",
1746 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1747
1748let AddedComplexity = 6 in
1749multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1750 def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1751 [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1752 logical_imm32:$imm))]> {
1753 let Inst{31} = 0;
1754 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1755 }
1756 def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1757 [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1758 logical_imm64:$imm))]> {
1759 let Inst{31} = 1;
1760 }
1761}
1762
1763multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1764 let isCompare = 1, Defs = [CPSR] in {
1765 def Wri : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1766 [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1767 let Inst{31} = 0;
1768 let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1769 }
1770 def Xri : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1771 [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1772 let Inst{31} = 1;
1773 }
1774 } // end Defs = [CPSR]
1775}
1776
1777class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1778 : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1779 [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1780 Sched<[WriteI]>;
1781
1782// Split from LogicalImm as not all instructions have both.
1783multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1784 SDPatternOperator OpNode> {
1785 def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1786 def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1787
1788 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1789 [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1790 logical_shifted_reg32:$Rm))]> {
1791 let Inst{31} = 0;
1792 }
1793 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1794 [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1795 logical_shifted_reg64:$Rm))]> {
1796 let Inst{31} = 1;
1797 }
1798
1799 def : LogicalRegAlias<mnemonic,
1800 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1801 def : LogicalRegAlias<mnemonic,
1802 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1803}
1804
1805// Split from LogicalReg to allow setting CPSR Defs
1806multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1807 let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1808 def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1809 let Inst{31} = 0;
1810 }
1811 def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1812 let Inst{31} = 1;
1813 }
1814 } // Defs = [CPSR]
1815
1816 def : LogicalRegAlias<mnemonic,
1817 !cast<Instruction>(NAME#"Wrs"), GPR32>;
1818 def : LogicalRegAlias<mnemonic,
1819 !cast<Instruction>(NAME#"Xrs"), GPR64>;
1820}
1821
1822//---
1823// Conditionally set flags
1824//---
1825
1826// Condition code.
1827// 4-bit immediate. Pretty-printed as <cc>
1828def ccode : Operand<i32> {
1829 let PrintMethod = "printCondCode";
1830}
1831
1832let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1833class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1834 : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1835 asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1836 Sched<[WriteI]> {
1837 let Uses = [CPSR];
1838 let Defs = [CPSR];
1839
1840 bits<5> Rn;
1841 bits<5> imm;
1842 bits<4> nzcv;
1843 bits<4> cond;
1844
1845 let Inst{30} = op;
1846 let Inst{29-21} = 0b111010010;
1847 let Inst{20-16} = imm;
1848 let Inst{15-12} = cond;
1849 let Inst{11-10} = 0b10;
1850 let Inst{9-5} = Rn;
1851 let Inst{4} = 0b0;
1852 let Inst{3-0} = nzcv;
1853}
1854
1855multiclass CondSetFlagsImm<bit op, string asm> {
1856 def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1857 let Inst{31} = 0;
1858 }
1859 def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1860 let Inst{31} = 1;
1861 }
1862}
1863
1864let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1865class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1866 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1867 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1868 Sched<[WriteI]> {
1869 let Uses = [CPSR];
1870 let Defs = [CPSR];
1871
1872 bits<5> Rn;
1873 bits<5> Rm;
1874 bits<4> nzcv;
1875 bits<4> cond;
1876
1877 let Inst{30} = op;
1878 let Inst{29-21} = 0b111010010;
1879 let Inst{20-16} = Rm;
1880 let Inst{15-12} = cond;
1881 let Inst{11-10} = 0b00;
1882 let Inst{9-5} = Rn;
1883 let Inst{4} = 0b0;
1884 let Inst{3-0} = nzcv;
1885}
1886
1887multiclass CondSetFlagsReg<bit op, string asm> {
1888 def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1889 let Inst{31} = 0;
1890 }
1891 def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1892 let Inst{31} = 1;
1893 }
1894}
1895
1896//---
1897// Conditional select
1898//---
1899
1900class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1901 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1902 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1903 [(set regtype:$Rd,
1904 (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1905 Sched<[WriteI]> {
1906 let Uses = [CPSR];
1907
1908 bits<5> Rd;
1909 bits<5> Rn;
1910 bits<5> Rm;
1911 bits<4> cond;
1912
1913 let Inst{30} = op;
1914 let Inst{29-21} = 0b011010100;
1915 let Inst{20-16} = Rm;
1916 let Inst{15-12} = cond;
1917 let Inst{11-10} = op2;
1918 let Inst{9-5} = Rn;
1919 let Inst{4-0} = Rd;
1920}
1921
1922multiclass CondSelect<bit op, bits<2> op2, string asm> {
1923 def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1924 let Inst{31} = 0;
1925 }
1926 def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1927 let Inst{31} = 1;
1928 }
1929}
1930
1931class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1932 PatFrag frag>
1933 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1934 asm, "\t$Rd, $Rn, $Rm, $cond", "",
1935 [(set regtype:$Rd,
1936 (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1937 (i32 imm:$cond), CPSR))]>,
1938 Sched<[WriteI]> {
1939 let Uses = [CPSR];
1940
1941 bits<5> Rd;
1942 bits<5> Rn;
1943 bits<5> Rm;
1944 bits<4> cond;
1945
1946 let Inst{30} = op;
1947 let Inst{29-21} = 0b011010100;
1948 let Inst{20-16} = Rm;
1949 let Inst{15-12} = cond;
1950 let Inst{11-10} = op2;
1951 let Inst{9-5} = Rn;
1952 let Inst{4-0} = Rd;
1953}
1954
1955multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1956 def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1957 let Inst{31} = 0;
1958 }
1959 def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1960 let Inst{31} = 1;
1961 }
1962}
1963
1964//---
1965// Special Mask Value
1966//---
1967def maski8_or_more : Operand<i32>,
1968 ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1969}
1970def maski16_or_more : Operand<i32>,
1971 ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1972}
1973
1974
1975//---
1976// Load/store
1977//---
1978
1979// (unsigned immediate)
1980// Indexed for 8-bit registers. offset is in range [0,4095].
1981def MemoryIndexed8Operand : AsmOperandClass {
1982 let Name = "MemoryIndexed8";
1983 let DiagnosticType = "InvalidMemoryIndexed8";
1984}
1985def am_indexed8 : Operand<i64>,
1986 ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1987 let PrintMethod = "printAMIndexed8";
1988 let EncoderMethod
1989 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1990 let ParserMatchClass = MemoryIndexed8Operand;
1991 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1992}
1993
1994// Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
1995// stored as immval/2 (the 12-bit literal that encodes directly into the insn).
1996def MemoryIndexed16Operand : AsmOperandClass {
1997 let Name = "MemoryIndexed16";
1998 let DiagnosticType = "InvalidMemoryIndexed16";
1999}
2000def am_indexed16 : Operand<i64>,
2001 ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2002 let PrintMethod = "printAMIndexed16";
2003 let EncoderMethod
2004 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2005 let ParserMatchClass = MemoryIndexed16Operand;
2006 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2007}
2008
2009// Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2010// stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2011def MemoryIndexed32Operand : AsmOperandClass {
2012 let Name = "MemoryIndexed32";
2013 let DiagnosticType = "InvalidMemoryIndexed32";
2014}
2015def am_indexed32 : Operand<i64>,
2016 ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2017 let PrintMethod = "printAMIndexed32";
2018 let EncoderMethod
2019 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2020 let ParserMatchClass = MemoryIndexed32Operand;
2021 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2022}
2023
2024// Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2025// stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2026def MemoryIndexed64Operand : AsmOperandClass {
2027 let Name = "MemoryIndexed64";
2028 let DiagnosticType = "InvalidMemoryIndexed64";
2029}
2030def am_indexed64 : Operand<i64>,
2031 ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2032 let PrintMethod = "printAMIndexed64";
2033 let EncoderMethod
2034 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2035 let ParserMatchClass = MemoryIndexed64Operand;
2036 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2037}
2038
2039// Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2040// stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2041def MemoryIndexed128Operand : AsmOperandClass {
2042 let Name = "MemoryIndexed128";
2043 let DiagnosticType = "InvalidMemoryIndexed128";
2044}
2045def am_indexed128 : Operand<i64>,
2046 ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2047 let PrintMethod = "printAMIndexed128";
2048 let EncoderMethod
2049 = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2050 let ParserMatchClass = MemoryIndexed128Operand;
2051 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2052}
2053
2054// No offset.
2055def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2056def am_noindex : Operand<i64>,
2057 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2058 let PrintMethod = "printAMNoIndex";
2059 let ParserMatchClass = MemoryNoIndexOperand;
2060 let MIOperandInfo = (ops GPR64sp:$base);
2061}
2062
2063class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2064 string asm, list<dag> pattern>
2065 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2066 bits<5> dst;
2067
2068 bits<17> addr;
2069 bits<5> base = addr{4-0};
2070 bits<12> offset = addr{16-5};
2071
2072 let Inst{31-30} = sz;
2073 let Inst{29-27} = 0b111;
2074 let Inst{26} = V;
2075 let Inst{25-24} = 0b01;
2076 let Inst{23-22} = opc;
2077 let Inst{21-10} = offset;
2078 let Inst{9-5} = base;
2079 let Inst{4-0} = dst;
2080
2081 let DecoderMethod = "DecodeUnsignedLdStInstruction";
2082}
2083
2084let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2085class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2086 Operand indextype, string asm, list<dag> pattern>
2087 : BaseLoadStoreUI<sz, V, opc,
2088 (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2089 Sched<[WriteLD]>;
2090
2091let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2092class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2093 Operand indextype, string asm, list<dag> pattern>
2094 : BaseLoadStoreUI<sz, V, opc,
2095 (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2096 Sched<[WriteST]>;
2097
2098def PrefetchOperand : AsmOperandClass {
2099 let Name = "Prefetch";
2100 let ParserMethod = "tryParsePrefetch";
2101}
2102def prfop : Operand<i32> {
2103 let PrintMethod = "printPrefetchOp";
2104 let ParserMatchClass = PrefetchOperand;
2105}
2106
2107let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2108class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2109 : BaseLoadStoreUI<sz, V, opc,
2110 (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2111 Sched<[WriteLD]>;
2112
2113//---
2114// Load literal
2115//---
2116
2117let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2118class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2119 : I<(outs regtype:$Rt), (ins am_brcond:$label),
2120 asm, "\t$Rt, $label", "", []>,
2121 Sched<[WriteLD]> {
2122 bits<5> Rt;
2123 bits<19> label;
2124 let Inst{31-30} = opc;
2125 let Inst{29-27} = 0b011;
2126 let Inst{26} = V;
2127 let Inst{25-24} = 0b00;
2128 let Inst{23-5} = label;
2129 let Inst{4-0} = Rt;
2130}
2131
2132let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2133class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2134 : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2135 asm, "\t$Rt, $label", "", pat>,
2136 Sched<[WriteLD]> {
2137 bits<5> Rt;
2138 bits<19> label;
2139 let Inst{31-30} = opc;
2140 let Inst{29-27} = 0b011;
2141 let Inst{26} = V;
2142 let Inst{25-24} = 0b00;
2143 let Inst{23-5} = label;
2144 let Inst{4-0} = Rt;
2145}
2146
2147//---
2148// Load/store register offset
2149//---
2150
2151class MemROAsmOperand<int sz> : AsmOperandClass {
2152 let Name = "MemoryRegisterOffset"#sz;
2153}
2154
2155def MemROAsmOperand8 : MemROAsmOperand<8>;
2156def MemROAsmOperand16 : MemROAsmOperand<16>;
2157def MemROAsmOperand32 : MemROAsmOperand<32>;
2158def MemROAsmOperand64 : MemROAsmOperand<64>;
2159def MemROAsmOperand128 : MemROAsmOperand<128>;
2160
2161class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2162 let PrintMethod = "printMemoryRegOffset"#sz;
2163 let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2164}
2165
2166def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2167 let ParserMatchClass = MemROAsmOperand8;
2168}
2169
2170def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2171 let ParserMatchClass = MemROAsmOperand16;
2172}
2173
2174def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2175 let ParserMatchClass = MemROAsmOperand32;
2176}
2177
2178def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2179 let ParserMatchClass = MemROAsmOperand64;
2180}
2181
2182def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2183 let ParserMatchClass = MemROAsmOperand128;
2184}
2185
2186class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2187 string asm, dag ins, dag outs, list<dag> pat>
2188 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2189 // The operands are in order to match the 'addr' MI operands, so we
2190 // don't need an encoder method and by-name matching. Just use the default
2191 // in-order handling. Since we're using by-order, make sure the names
2192 // do not match.
2193 bits<5> dst;
2194 bits<5> base;
2195 bits<5> offset;
2196 bits<4> extend;
2197 let Inst{31-30} = sz;
2198 let Inst{29-27} = 0b111;
2199 let Inst{26} = V;
2200 let Inst{25-24} = 0b00;
2201 let Inst{23-22} = opc;
2202 let Inst{21} = 1;
2203 let Inst{20-16} = offset;
2204 let Inst{15-13} = extend{3-1};
2205
2206 let Inst{12} = extend{0};
2207 let Inst{11-10} = 0b10;
2208 let Inst{9-5} = base;
2209 let Inst{4-0} = dst;
2210
2211 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2212}
2213
2214class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2215 string asm, list<dag> pat>
2216 : LoadStore8RO<sz, V, opc, regtype, asm,
2217 (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2218 Sched<[WriteLDIdx, ReadAdrBase]>;
2219
2220class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2221 string asm, list<dag> pat>
2222 : LoadStore8RO<sz, V, opc, regtype, asm,
2223 (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2224 Sched<[WriteSTIdx, ReadAdrBase]>;
2225
2226class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2227 string asm, dag ins, dag outs, list<dag> pat>
2228 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2229 // The operands are in order to match the 'addr' MI operands, so we
2230 // don't need an encoder method and by-name matching. Just use the default
2231 // in-order handling. Since we're using by-order, make sure the names
2232 // do not match.
2233 bits<5> dst;
2234 bits<5> base;
2235 bits<5> offset;
2236 bits<4> extend;
2237 let Inst{31-30} = sz;
2238 let Inst{29-27} = 0b111;
2239 let Inst{26} = V;
2240 let Inst{25-24} = 0b00;
2241 let Inst{23-22} = opc;
2242 let Inst{21} = 1;
2243 let Inst{20-16} = offset;
2244 let Inst{15-13} = extend{3-1};
2245
2246 let Inst{12} = extend{0};
2247 let Inst{11-10} = 0b10;
2248 let Inst{9-5} = base;
2249 let Inst{4-0} = dst;
2250
2251 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2252}
2253
2254class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2255 string asm, list<dag> pat>
2256 : LoadStore16RO<sz, V, opc, regtype, asm,
2257 (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2258 Sched<[WriteLDIdx, ReadAdrBase]>;
2259
2260class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2261 string asm, list<dag> pat>
2262 : LoadStore16RO<sz, V, opc, regtype, asm,
2263 (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2264 Sched<[WriteSTIdx, ReadAdrBase]>;
2265
2266class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2267 string asm, dag ins, dag outs, list<dag> pat>
2268 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2269 // The operands are in order to match the 'addr' MI operands, so we
2270 // don't need an encoder method and by-name matching. Just use the default
2271 // in-order handling. Since we're using by-order, make sure the names
2272 // do not match.
2273 bits<5> dst;
2274 bits<5> base;
2275 bits<5> offset;
2276 bits<4> extend;
2277 let Inst{31-30} = sz;
2278 let Inst{29-27} = 0b111;
2279 let Inst{26} = V;
2280 let Inst{25-24} = 0b00;
2281 let Inst{23-22} = opc;
2282 let Inst{21} = 1;
2283 let Inst{20-16} = offset;
2284 let Inst{15-13} = extend{3-1};
2285
2286 let Inst{12} = extend{0};
2287 let Inst{11-10} = 0b10;
2288 let Inst{9-5} = base;
2289 let Inst{4-0} = dst;
2290
2291 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2292}
2293
2294class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2295 string asm, list<dag> pat>
2296 : LoadStore32RO<sz, V, opc, regtype, asm,
2297 (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2298 Sched<[WriteLDIdx, ReadAdrBase]>;
2299
2300class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2301 string asm, list<dag> pat>
2302 : LoadStore32RO<sz, V, opc, regtype, asm,
2303 (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2304 Sched<[WriteSTIdx, ReadAdrBase]>;
2305
2306class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2307 string asm, dag ins, dag outs, list<dag> pat>
2308 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2309 // The operands are in order to match the 'addr' MI operands, so we
2310 // don't need an encoder method and by-name matching. Just use the default
2311 // in-order handling. Since we're using by-order, make sure the names
2312 // do not match.
2313 bits<5> dst;
2314 bits<5> base;
2315 bits<5> offset;
2316 bits<4> extend;
2317 let Inst{31-30} = sz;
2318 let Inst{29-27} = 0b111;
2319 let Inst{26} = V;
2320 let Inst{25-24} = 0b00;
2321 let Inst{23-22} = opc;
2322 let Inst{21} = 1;
2323 let Inst{20-16} = offset;
2324 let Inst{15-13} = extend{3-1};
2325
2326 let Inst{12} = extend{0};
2327 let Inst{11-10} = 0b10;
2328 let Inst{9-5} = base;
2329 let Inst{4-0} = dst;
2330
2331 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2332}
2333
2334let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2335class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2336 string asm, list<dag> pat>
2337 : LoadStore64RO<sz, V, opc, regtype, asm,
2338 (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2339 Sched<[WriteLDIdx, ReadAdrBase]>;
2340
2341let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2342class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2343 string asm, list<dag> pat>
2344 : LoadStore64RO<sz, V, opc, regtype, asm,
2345 (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2346 Sched<[WriteSTIdx, ReadAdrBase]>;
2347
2348
2349class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2350 string asm, dag ins, dag outs, list<dag> pat>
2351 : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2352 // The operands are in order to match the 'addr' MI operands, so we
2353 // don't need an encoder method and by-name matching. Just use the default
2354 // in-order handling. Since we're using by-order, make sure the names
2355 // do not match.
2356 bits<5> dst;
2357 bits<5> base;
2358 bits<5> offset;
2359 bits<4> extend;
2360 let Inst{31-30} = sz;
2361 let Inst{29-27} = 0b111;
2362 let Inst{26} = V;
2363 let Inst{25-24} = 0b00;
2364 let Inst{23-22} = opc;
2365 let Inst{21} = 1;
2366 let Inst{20-16} = offset;
2367 let Inst{15-13} = extend{3-1};
2368
2369 let Inst{12} = extend{0};
2370 let Inst{11-10} = 0b10;
2371 let Inst{9-5} = base;
2372 let Inst{4-0} = dst;
2373
2374 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2375}
2376
2377let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2378class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2379 string asm, list<dag> pat>
2380 : LoadStore128RO<sz, V, opc, regtype, asm,
2381 (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2382 Sched<[WriteLDIdx, ReadAdrBase]>;
2383
2384let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2385class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2386 string asm, list<dag> pat>
2387 : LoadStore128RO<sz, V, opc, regtype, asm,
2388 (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2389 Sched<[WriteSTIdx, ReadAdrBase]>;
2390
2391let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2392class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2393 : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2394 "\t$Rt, $addr", "", pat>,
2395 Sched<[WriteLD]> {
2396 // The operands are in order to match the 'addr' MI operands, so we
2397 // don't need an encoder method and by-name matching. Just use the default
2398 // in-order handling. Since we're using by-order, make sure the names
2399 // do not match.
2400 bits<5> dst;
2401 bits<5> base;
2402 bits<5> offset;
2403 bits<4> extend;
2404 let Inst{31-30} = sz;
2405 let Inst{29-27} = 0b111;
2406 let Inst{26} = V;
2407 let Inst{25-24} = 0b00;
2408 let Inst{23-22} = opc;
2409 let Inst{21} = 1;
2410 let Inst{20-16} = offset;
2411 let Inst{15-13} = extend{3-1};
2412
2413 let Inst{12} = extend{0};
2414 let Inst{11-10} = 0b10;
2415 let Inst{9-5} = base;
2416 let Inst{4-0} = dst;
2417
2418 let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2419}
2420
2421//---
2422// Load/store unscaled immediate
2423//---
2424
2425def MemoryUnscaledOperand : AsmOperandClass {
2426 let Name = "MemoryUnscaled";
2427 let DiagnosticType = "InvalidMemoryIndexedSImm9";
2428}
2429class am_unscaled_operand : Operand<i64> {
2430 let PrintMethod = "printAMUnscaled";
2431 let ParserMatchClass = MemoryUnscaledOperand;
2432 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2433}
2434def am_unscaled : am_unscaled_operand;
2435def am_unscaled8 : am_unscaled_operand,
2436 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2437def am_unscaled16 : am_unscaled_operand,
2438 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2439def am_unscaled32 : am_unscaled_operand,
2440 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2441def am_unscaled64 : am_unscaled_operand,
2442 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2443def am_unscaled128 : am_unscaled_operand,
2444 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2445
2446class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2447 string asm, list<dag> pattern>
2448 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2449 // The operands are in order to match the 'addr' MI operands, so we
2450 // don't need an encoder method and by-name matching. Just use the default
2451 // in-order handling. Since we're using by-order, make sure the names
2452 // do not match.
2453 bits<5> dst;
2454 bits<5> base;
2455 bits<9> offset;
2456 let Inst{31-30} = sz;
2457 let Inst{29-27} = 0b111;
2458 let Inst{26} = V;
2459 let Inst{25-24} = 0b00;
2460 let Inst{23-22} = opc;
2461 let Inst{21} = 0;
2462 let Inst{20-12} = offset;
2463 let Inst{11-10} = 0b00;
2464 let Inst{9-5} = base;
2465 let Inst{4-0} = dst;
2466
2467 let DecoderMethod = "DecodeSignedLdStInstruction";
2468}
2469
2470let AddedComplexity = 1 in // try this before LoadUI
2471class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2472 Operand amtype, string asm, list<dag> pattern>
2473 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2474 (ins amtype:$addr), asm, pattern>,
2475 Sched<[WriteLD]>;
2476
2477let AddedComplexity = 1 in // try this before StoreUI
2478class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2479 Operand amtype, string asm, list<dag> pattern>
2480 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2481 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2482 Sched<[WriteST]>;
2483
2484let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2485class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2486 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2487 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2488 Sched<[WriteLD]>;
2489
2490//---
2491// Load/store unscaled immediate, unprivileged
2492//---
2493
2494class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2495 dag oops, dag iops, string asm>
2496 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2497 // The operands are in order to match the 'addr' MI operands, so we
2498 // don't need an encoder method and by-name matching. Just use the default
2499 // in-order handling. Since we're using by-order, make sure the names
2500 // do not match.
2501 bits<5> dst;
2502 bits<5> base;
2503 bits<9> offset;
2504 let Inst{31-30} = sz;
2505 let Inst{29-27} = 0b111;
2506 let Inst{26} = V;
2507 let Inst{25-24} = 0b00;
2508 let Inst{23-22} = opc;
2509 let Inst{21} = 0;
2510 let Inst{20-12} = offset;
2511 let Inst{11-10} = 0b10;
2512 let Inst{9-5} = base;
2513 let Inst{4-0} = dst;
2514
2515 let DecoderMethod = "DecodeSignedLdStInstruction";
2516}
2517
2518let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2519class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2520 string asm>
2521 : BaseLoadStoreUnprivileged<sz, V, opc,
2522 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2523 Sched<[WriteLD]>;
2524}
2525
2526let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2527class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2528 string asm>
2529 : BaseLoadStoreUnprivileged<sz, V, opc,
2530 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2531 Sched<[WriteST]>;
2532}
2533
2534//---
2535// Load/store pre-indexed
2536//---
2537
2538class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2539 string asm, string cstr>
2540 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2541 // The operands are in order to match the 'addr' MI operands, so we
2542 // don't need an encoder method and by-name matching. Just use the default
2543 // in-order handling.
2544 bits<5> dst;
2545 bits<5> base;
2546 bits<9> offset;
2547 let Inst{31-30} = sz;
2548 let Inst{29-27} = 0b111;
2549 let Inst{26} = V;
2550 let Inst{25-24} = 0;
2551 let Inst{23-22} = opc;
2552 let Inst{21} = 0;
2553 let Inst{20-12} = offset;
2554 let Inst{11-10} = 0b11;
2555 let Inst{9-5} = base;
2556 let Inst{4-0} = dst;
2557
2558 let DecoderMethod = "DecodeSignedLdStInstruction";
2559}
2560
2561let hasSideEffects = 0 in {
2562let mayStore = 0, mayLoad = 1 in
2563// FIXME: Modeling the write-back of these instructions for isel is tricky.
2564// we need the complex addressing mode for the memory reference, but
2565// we also need the write-back specified as a tied operand to the
2566// base register. That combination does not play nicely with
2567// the asm matcher and friends.
2568class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2569 string asm>
2570 : BaseLoadStorePreIdx<sz, V, opc,
2571 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2572 (ins am_unscaled:$addr), asm, ""/*"$addr.base = $wback"*/>,
2573 Sched<[WriteLD, WriteAdr]>;
2574
2575let mayStore = 1, mayLoad = 0 in
2576class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2577 string asm>
2578 : BaseLoadStorePreIdx<sz, V, opc,
2579 (outs/* GPR64sp:$wback*/),
2580 (ins regtype:$Rt, am_unscaled:$addr),
2581 asm, ""/*"$addr.base = $wback"*/>,
2582 Sched<[WriteAdr, WriteST]>;
2583} // hasSideEffects = 0
2584
2585// ISel pseudo-instructions which have the tied operands. When the MC lowering
2586// logic finally gets smart enough to strip off tied operands that are just
2587// for isel convenience, we can get rid of these pseudos and just reference
2588// the real instructions directly.
2589//
2590// Ironically, also because of the writeback operands, we can't put the
2591// matcher pattern directly on the instruction, but need to define it
2592// separately.
2593//
2594// Loads aren't matched with patterns here at all, but rather in C++
2595// custom lowering.
2596let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2597class LoadPreIdxPseudo<RegisterClass regtype>
2598 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2599 (ins am_noindex:$addr, simm9:$offset), [],
2600 "$addr.base = $wback,@earlyclobber $wback">,
2601 Sched<[WriteLD, WriteAdr]>;
2602class LoadPostIdxPseudo<RegisterClass regtype>
2603 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2604 (ins am_noindex:$addr, simm9:$offset), [],
2605 "$addr.base = $wback,@earlyclobber $wback">,
2606 Sched<[WriteLD, WriteI]>;
2607}
2608multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2609 SDPatternOperator OpNode> {
2610 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2611 def _isel: Pseudo<(outs GPR64sp:$wback),
2612 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2613 "$addr.base = $wback,@earlyclobber $wback">,
2614 Sched<[WriteAdr, WriteST]>;
2615
2616 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2617 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2618 simm9:$offset)>;
2619}
2620
2621//---
2622// Load/store post-indexed
2623//---
2624
2625// (pre-index) load/stores.
2626class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2627 string asm, string cstr>
2628 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2629 // The operands are in order to match the 'addr' MI operands, so we
2630 // don't need an encoder method and by-name matching. Just use the default
2631 // in-order handling.
2632 bits<5> dst;
2633 bits<5> base;
2634 bits<9> offset;
2635 let Inst{31-30} = sz;
2636 let Inst{29-27} = 0b111;
2637 let Inst{26} = V;
2638 let Inst{25-24} = 0b00;
2639 let Inst{23-22} = opc;
2640 let Inst{21} = 0b0;
2641 let Inst{20-12} = offset;
2642 let Inst{11-10} = 0b01;
2643 let Inst{9-5} = base;
2644 let Inst{4-0} = dst;
2645
2646 let DecoderMethod = "DecodeSignedLdStInstruction";
2647}
2648
2649let hasSideEffects = 0 in {
2650let mayStore = 0, mayLoad = 1 in
2651// FIXME: Modeling the write-back of these instructions for isel is tricky.
2652// we need the complex addressing mode for the memory reference, but
2653// we also need the write-back specified as a tied operand to the
2654// base register. That combination does not play nicely with
2655// the asm matcher and friends.
2656class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2657 string asm>
2658 : BaseLoadStorePostIdx<sz, V, opc,
2659 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2660 (ins am_noindex:$addr, simm9:$idx),
2661 asm, ""/*"$addr.base = $wback"*/>,
2662 Sched<[WriteLD, WriteI]>;
2663
2664let mayStore = 1, mayLoad = 0 in
2665class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2666 string asm>
2667 : BaseLoadStorePostIdx<sz, V, opc,
2668 (outs/* GPR64sp:$wback*/),
2669 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2670 asm, ""/*"$addr.base = $wback"*/>,
2671 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2672} // hasSideEffects = 0
2673
2674// ISel pseudo-instructions which have the tied operands. When the MC lowering
2675// logic finally gets smart enough to strip off tied operands that are just
2676// for isel convenience, we can get rid of these pseudos and just reference
2677// the real instructions directly.
2678//
2679// Ironically, also because of the writeback operands, we can't put the
2680// matcher pattern directly on the instruction, but need to define it
2681// separately.
2682multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2683 SDPatternOperator OpNode, Instruction Insn> {
2684 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2685 def _isel: Pseudo<(outs GPR64sp:$wback),
2686 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2687 "$addr.base = $wback,@earlyclobber $wback">,
2688 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2689 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2690
2691 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2692 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2693 simm9:$idx)>;
2694}
2695
2696//---
2697// Load/store pair
2698//---
2699
2700// (indexed, offset)
2701
2702class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2703 string asm>
2704 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2705 // The operands are in order to match the 'addr' MI operands, so we
2706 // don't need an encoder method and by-name matching. Just use the default
2707 // in-order handling. Since we're using by-order, make sure the names
2708 // do not match.
2709 bits<5> dst;
2710 bits<5> dst2;
2711 bits<5> base;
2712 bits<7> offset;
2713 let Inst{31-30} = opc;
2714 let Inst{29-27} = 0b101;
2715 let Inst{26} = V;
2716 let Inst{25-23} = 0b010;
2717 let Inst{22} = L;
2718 let Inst{21-15} = offset;
2719 let Inst{14-10} = dst2;
2720 let Inst{9-5} = base;
2721 let Inst{4-0} = dst;
2722
2723 let DecoderMethod = "DecodePairLdStInstruction";
2724}
2725
2726let hasSideEffects = 0 in {
2727let mayStore = 0, mayLoad = 1 in
2728class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2729 Operand indextype, string asm>
2730 : BaseLoadStorePairOffset<opc, V, 1,
2731 (outs regtype:$Rt, regtype:$Rt2),
2732 (ins indextype:$addr), asm>,
2733 Sched<[WriteLD, WriteLDHi]>;
2734
2735let mayLoad = 0, mayStore = 1 in
2736class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2737 Operand indextype, string asm>
2738 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2739 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2740 asm>,
2741 Sched<[WriteSTP]>;
2742} // hasSideEffects = 0
2743
2744// (pre-indexed)
2745
2746def MemoryIndexed32SImm7 : AsmOperandClass {
2747 let Name = "MemoryIndexed32SImm7";
2748 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2749}
2750def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2751 let PrintMethod = "printAMIndexed32";
2752 let ParserMatchClass = MemoryIndexed32SImm7;
2753 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2754}
2755
2756def MemoryIndexed64SImm7 : AsmOperandClass {
2757 let Name = "MemoryIndexed64SImm7";
2758 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2759}
2760def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2761 let PrintMethod = "printAMIndexed64";
2762 let ParserMatchClass = MemoryIndexed64SImm7;
2763 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2764}
2765
2766def MemoryIndexed128SImm7 : AsmOperandClass {
2767 let Name = "MemoryIndexed128SImm7";
2768 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2769}
2770def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2771 let PrintMethod = "printAMIndexed128";
2772 let ParserMatchClass = MemoryIndexed128SImm7;
2773 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2774}
2775
2776class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2777 string asm>
2778 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2779 // The operands are in order to match the 'addr' MI operands, so we
2780 // don't need an encoder method and by-name matching. Just use the default
2781 // in-order handling. Since we're using by-order, make sure the names
2782 // do not match.
2783 bits<5> dst;
2784 bits<5> dst2;
2785 bits<5> base;
2786 bits<7> offset;
2787 let Inst{31-30} = opc;
2788 let Inst{29-27} = 0b101;
2789 let Inst{26} = V;
2790 let Inst{25-23} = 0b011;
2791 let Inst{22} = L;
2792 let Inst{21-15} = offset;
2793 let Inst{14-10} = dst2;
2794 let Inst{9-5} = base;
2795 let Inst{4-0} = dst;
2796
2797 let DecoderMethod = "DecodePairLdStInstruction";
2798}
2799
2800let hasSideEffects = 0 in {
2801let mayStore = 0, mayLoad = 1 in
2802class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2803 Operand addrmode, string asm>
2804 : BaseLoadStorePairPreIdx<opc, V, 1,
2805 (outs regtype:$Rt, regtype:$Rt2),
2806 (ins addrmode:$addr), asm>,
2807 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2808
2809let mayStore = 1, mayLoad = 0 in
2810class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2811 Operand addrmode, string asm>
2812 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2813 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2814 asm>,
2815 Sched<[WriteAdr, WriteSTP]>;
2816} // hasSideEffects = 0
2817
2818// (post-indexed)
2819
2820class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2821 string asm>
2822 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2823 // The operands are in order to match the 'addr' MI operands, so we
2824 // don't need an encoder method and by-name matching. Just use the default
2825 // in-order handling. Since we're using by-order, make sure the names
2826 // do not match.
2827 bits<5> dst;
2828 bits<5> dst2;
2829 bits<5> base;
2830 bits<7> offset;
2831 let Inst{31-30} = opc;
2832 let Inst{29-27} = 0b101;
2833 let Inst{26} = V;
2834 let Inst{25-23} = 0b001;
2835 let Inst{22} = L;
2836 let Inst{21-15} = offset;
2837 let Inst{14-10} = dst2;
2838 let Inst{9-5} = base;
2839 let Inst{4-0} = dst;
2840
2841 let DecoderMethod = "DecodePairLdStInstruction";
2842}
2843
2844let hasSideEffects = 0 in {
2845let mayStore = 0, mayLoad = 1 in
2846class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2847 Operand idxtype, string asm>
2848 : BaseLoadStorePairPostIdx<opc, V, 1,
2849 (outs regtype:$Rt, regtype:$Rt2),
2850 (ins am_noindex:$addr, idxtype:$idx), asm>,
2851 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2852
2853let mayStore = 1, mayLoad = 0 in
2854class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2855 Operand idxtype, string asm>
2856 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2857 (ins regtype:$Rt, regtype:$Rt2,
2858 am_noindex:$addr, idxtype:$idx),
2859 asm>,
2860 Sched<[WriteAdr, WriteSTP]>;
2861} // hasSideEffects = 0
2862
2863// (no-allocate)
2864
2865class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2866 string asm>
2867 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2868 // The operands are in order to match the 'addr' MI operands, so we
2869 // don't need an encoder method and by-name matching. Just use the default
2870 // in-order handling. Since we're using by-order, make sure the names
2871 // do not match.
2872 bits<5> dst;
2873 bits<5> dst2;
2874 bits<5> base;
2875 bits<7> offset;
2876 let Inst{31-30} = opc;
2877 let Inst{29-27} = 0b101;
2878 let Inst{26} = V;
2879 let Inst{25-23} = 0b000;
2880 let Inst{22} = L;
2881 let Inst{21-15} = offset;
2882 let Inst{14-10} = dst2;
2883 let Inst{9-5} = base;
2884 let Inst{4-0} = dst;
2885
2886 let DecoderMethod = "DecodePairLdStInstruction";
2887}
2888
2889let hasSideEffects = 0 in {
2890let mayStore = 0, mayLoad = 1 in
2891class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2892 Operand indextype, string asm>
2893 : BaseLoadStorePairNoAlloc<opc, V, 1,
2894 (outs regtype:$Rt, regtype:$Rt2),
2895 (ins indextype:$addr), asm>,
2896 Sched<[WriteLD, WriteLDHi]>;
2897
2898let mayStore = 1, mayLoad = 0 in
2899class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2900 Operand indextype, string asm>
2901 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2902 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2903 asm>,
2904 Sched<[WriteSTP]>;
2905} // hasSideEffects = 0
2906
2907//---
2908// Load/store exclusive
2909//---
2910
2911// True exclusive operations write to and/or read from the system's exclusive
2912// monitors, which as far as a compiler is concerned can be modelled as a
2913// random shared memory address. Hence LoadExclusive mayStore.
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002914//
2915// Since these instructions have the undefined register bits set to 1 in
2916// their canonical form, we need a post encoder method to set those bits
2917// to 1 when encoding these instructions. We do this using the
2918// fixLoadStoreExclusive function. This function has template parameters:
2919//
2920// fixLoadStoreExclusive<int hasRs, int hasRt2>
2921//
2922// hasRs indicates that the instruction uses the Rs field, so we won't set
2923// it to 1 (and the same for Rt2). We don't need template parameters for
2924// the other register fields since Rt and Rn are always used.
2925//
Tim Northover00ed9962014-03-29 10:18:08 +00002926let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2927class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2928 dag oops, dag iops, string asm, string operands>
2929 : I<oops, iops, asm, operands, "", []> {
2930 let Inst{31-30} = sz;
2931 let Inst{29-24} = 0b001000;
2932 let Inst{23} = o2;
2933 let Inst{22} = L;
2934 let Inst{21} = o1;
2935 let Inst{15} = o0;
2936
2937 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2938}
2939
2940// Neither Rs nor Rt2 operands.
2941class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2942 dag oops, dag iops, string asm, string operands>
2943 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2944 bits<5> reg;
2945 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00002946 let Inst{9-5} = base;
2947 let Inst{4-0} = reg;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002948
2949 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00002950}
2951
2952// Simple load acquires don't set the exclusive monitor
2953let mayLoad = 1, mayStore = 0 in
2954class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2955 RegisterClass regtype, string asm>
2956 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2957 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2958 Sched<[WriteLD]>;
2959
2960class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2961 RegisterClass regtype, string asm>
2962 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2963 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2964 Sched<[WriteLD]>;
2965
2966class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2967 RegisterClass regtype, string asm>
2968 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2969 (outs regtype:$Rt, regtype:$Rt2),
2970 (ins am_noindex:$addr), asm,
2971 "\t$Rt, $Rt2, $addr">,
2972 Sched<[WriteLD, WriteLDHi]> {
2973 bits<5> dst1;
2974 bits<5> dst2;
2975 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00002976 let Inst{14-10} = dst2;
2977 let Inst{9-5} = base;
2978 let Inst{4-0} = dst1;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002979
2980 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
Tim Northover00ed9962014-03-29 10:18:08 +00002981}
2982
2983// Simple store release operations do not check the exclusive monitor.
2984let mayLoad = 0, mayStore = 1 in
2985class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2986 RegisterClass regtype, string asm>
2987 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
2988 (ins regtype:$Rt, am_noindex:$addr),
2989 asm, "\t$Rt, $addr">,
2990 Sched<[WriteST]>;
2991
2992let mayLoad = 1, mayStore = 1 in
2993class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2994 RegisterClass regtype, string asm>
2995 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
2996 (ins regtype:$Rt, am_noindex:$addr),
2997 asm, "\t$Ws, $Rt, $addr">,
2998 Sched<[WriteSTX]> {
2999 bits<5> status;
3000 bits<5> reg;
3001 bits<5> base;
3002 let Inst{20-16} = status;
Tim Northover00ed9962014-03-29 10:18:08 +00003003 let Inst{9-5} = base;
3004 let Inst{4-0} = reg;
3005
3006 let Constraints = "@earlyclobber $Ws";
Bradley Smithbc35b1f2014-04-09 14:43:01 +00003007 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00003008}
3009
3010class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3011 RegisterClass regtype, string asm>
3012 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3013 (outs GPR32:$Ws),
3014 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3015 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3016 Sched<[WriteSTX]> {
3017 bits<5> status;
3018 bits<5> dst1;
3019 bits<5> dst2;
3020 bits<5> base;
3021 let Inst{20-16} = status;
3022 let Inst{14-10} = dst2;
3023 let Inst{9-5} = base;
3024 let Inst{4-0} = dst1;
3025
3026 let Constraints = "@earlyclobber $Ws";
3027}
3028
3029//---
3030// Exception generation
3031//---
3032
3033let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3034class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3035 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3036 Sched<[WriteSys]> {
3037 bits<16> imm;
3038 let Inst{31-24} = 0b11010100;
3039 let Inst{23-21} = op1;
3040 let Inst{20-5} = imm;
3041 let Inst{4-2} = 0b000;
3042 let Inst{1-0} = ll;
3043}
3044
3045//---
3046// Floating point to integer conversion
3047//---
3048
3049class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3050 RegisterClass srcType, RegisterClass dstType,
3051 string asm, list<dag> pattern>
3052 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3053 asm, "\t$Rd, $Rn", "", pattern>,
3054 Sched<[WriteFCvt]> {
3055 bits<5> Rd;
3056 bits<5> Rn;
Bradley Smith0243aa32014-04-09 14:43:20 +00003057 let Inst{30-29} = 0b00;
Tim Northover00ed9962014-03-29 10:18:08 +00003058 let Inst{28-24} = 0b11110;
3059 let Inst{23-22} = type;
3060 let Inst{21} = 1;
3061 let Inst{20-19} = rmode;
3062 let Inst{18-16} = opcode;
3063 let Inst{15-10} = 0;
3064 let Inst{9-5} = Rn;
3065 let Inst{4-0} = Rd;
3066}
3067
3068let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3069class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3070 RegisterClass srcType, RegisterClass dstType,
3071 Operand immType, string asm>
3072 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3073 asm, "\t$Rd, $Rn, $scale", "", []>,
3074 Sched<[WriteFCvt]> {
3075 bits<5> Rd;
3076 bits<5> Rn;
3077 bits<6> scale;
Bradley Smith60e76672014-04-09 14:43:27 +00003078 let Inst{30-29} = 0b00;
Tim Northover00ed9962014-03-29 10:18:08 +00003079 let Inst{28-24} = 0b11110;
3080 let Inst{23-22} = type;
3081 let Inst{21} = 0;
3082 let Inst{20-19} = rmode;
3083 let Inst{18-16} = opcode;
3084 let Inst{15-10} = scale;
3085 let Inst{9-5} = Rn;
3086 let Inst{4-0} = Rd;
3087}
3088
Bradley Smith0243aa32014-04-09 14:43:20 +00003089multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3090 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003091 // Unscaled single-precision to 32-bit
3092 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3093 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3094 let Inst{31} = 0; // 32-bit GPR flag
3095 }
3096
3097 // Unscaled single-precision to 64-bit
3098 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3099 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3100 let Inst{31} = 1; // 64-bit GPR flag
3101 }
3102
3103 // Unscaled double-precision to 32-bit
3104 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3105 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3106 let Inst{31} = 0; // 32-bit GPR flag
3107 }
3108
3109 // Unscaled double-precision to 64-bit
3110 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3111 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3112 let Inst{31} = 1; // 64-bit GPR flag
3113 }
Bradley Smith0243aa32014-04-09 14:43:20 +00003114}
Tim Northover00ed9962014-03-29 10:18:08 +00003115
Bradley Smith0243aa32014-04-09 14:43:20 +00003116multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3117 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003118 // Scaled single-precision to 32-bit
3119 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3120 fixedpoint32, asm> {
3121 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003122 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003123 }
3124
3125 // Scaled single-precision to 64-bit
3126 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3127 fixedpoint64, asm> {
3128 let Inst{31} = 1; // 64-bit GPR flag
3129 }
3130
3131 // Scaled double-precision to 32-bit
3132 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3133 fixedpoint32, asm> {
3134 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003135 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003136 }
3137
3138 // Scaled double-precision to 64-bit
3139 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3140 fixedpoint64, asm> {
3141 let Inst{31} = 1; // 64-bit GPR flag
3142 }
3143}
3144
3145//---
3146// Integer to floating point conversion
3147//---
3148
3149let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3150class BaseIntegerToFP<bit isUnsigned,
3151 RegisterClass srcType, RegisterClass dstType,
3152 Operand immType, string asm>
3153 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3154 asm, "\t$Rd, $Rn, $scale", "", []>,
3155 Sched<[WriteFCvt]> {
3156 bits<5> Rd;
3157 bits<5> Rn;
3158 bits<6> scale;
3159 let Inst{30-23} = 0b00111100;
3160 let Inst{21-17} = 0b00001;
3161 let Inst{16} = isUnsigned;
3162 let Inst{15-10} = scale;
3163 let Inst{9-5} = Rn;
3164 let Inst{4-0} = Rd;
3165}
3166
3167class BaseIntegerToFPUnscaled<bit isUnsigned,
3168 RegisterClass srcType, RegisterClass dstType,
3169 ValueType dvt, string asm, SDNode node>
3170 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3171 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3172 Sched<[WriteFCvt]> {
3173 bits<5> Rd;
3174 bits<5> Rn;
3175 bits<6> scale;
3176 let Inst{30-23} = 0b00111100;
3177 let Inst{21-17} = 0b10001;
3178 let Inst{16} = isUnsigned;
3179 let Inst{15-10} = 0b000000;
3180 let Inst{9-5} = Rn;
3181 let Inst{4-0} = Rd;
3182}
3183
3184multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3185 // Unscaled
3186 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3187 let Inst{31} = 0; // 32-bit GPR flag
3188 let Inst{22} = 0; // 32-bit FPR flag
3189 }
3190
3191 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3192 let Inst{31} = 0; // 32-bit GPR flag
3193 let Inst{22} = 1; // 64-bit FPR flag
3194 }
3195
3196 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3197 let Inst{31} = 1; // 64-bit GPR flag
3198 let Inst{22} = 0; // 32-bit FPR flag
3199 }
3200
3201 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3202 let Inst{31} = 1; // 64-bit GPR flag
3203 let Inst{22} = 1; // 64-bit FPR flag
3204 }
3205
3206 // Scaled
3207 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint32, asm> {
3208 let Inst{31} = 0; // 32-bit GPR flag
3209 let Inst{22} = 0; // 32-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003210 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003211 }
3212
3213 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint32, asm> {
3214 let Inst{31} = 0; // 32-bit GPR flag
3215 let Inst{22} = 1; // 64-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003216 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003217 }
3218
3219 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint64, asm> {
3220 let Inst{31} = 1; // 64-bit GPR flag
3221 let Inst{22} = 0; // 32-bit FPR flag
3222 }
3223
3224 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint64, asm> {
3225 let Inst{31} = 1; // 64-bit GPR flag
3226 let Inst{22} = 1; // 64-bit FPR flag
3227 }
3228}
3229
3230//---
3231// Unscaled integer <-> floating point conversion (i.e. FMOV)
3232//---
3233
3234let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3235class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3236 RegisterClass srcType, RegisterClass dstType,
3237 string asm>
3238 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3239 // We use COPY_TO_REGCLASS for these bitconvert operations.
3240 // copyPhysReg() expands the resultant COPY instructions after
3241 // regalloc is done. This gives greater freedom for the allocator
3242 // and related passes (coalescing, copy propagation, et. al.) to
3243 // be more effective.
3244 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3245 Sched<[WriteFCopy]> {
3246 bits<5> Rd;
3247 bits<5> Rn;
3248 let Inst{30-23} = 0b00111100;
3249 let Inst{21} = 1;
3250 let Inst{20-19} = rmode;
3251 let Inst{18-16} = opcode;
3252 let Inst{15-10} = 0b000000;
3253 let Inst{9-5} = Rn;
3254 let Inst{4-0} = Rd;
3255}
3256
3257let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3258class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3259 RegisterClass srcType, RegisterOperand dstType, string asm>
3260 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd[1], $Rn", "", []>,
3261 Sched<[WriteFCopy]> {
3262 bits<5> Rd;
3263 bits<5> Rn;
3264 let Inst{30-23} = 0b00111101;
3265 let Inst{21} = 1;
3266 let Inst{20-19} = rmode;
3267 let Inst{18-16} = opcode;
3268 let Inst{15-10} = 0b000000;
3269 let Inst{9-5} = Rn;
3270 let Inst{4-0} = Rd;
3271}
3272
3273let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3274class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3275 RegisterOperand srcType, RegisterClass dstType, string asm>
3276 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn[1]", "", []>,
3277 Sched<[WriteFCopy]> {
3278 bits<5> Rd;
3279 bits<5> Rn;
3280 let Inst{30-23} = 0b00111101;
3281 let Inst{21} = 1;
3282 let Inst{20-19} = rmode;
3283 let Inst{18-16} = opcode;
3284 let Inst{15-10} = 0b000000;
3285 let Inst{9-5} = Rn;
3286 let Inst{4-0} = Rd;
3287}
3288
3289
3290
3291multiclass UnscaledConversion<string asm> {
3292 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3293 let Inst{31} = 0; // 32-bit GPR flag
3294 let Inst{22} = 0; // 32-bit FPR flag
3295 }
3296
3297 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3298 let Inst{31} = 1; // 64-bit GPR flag
3299 let Inst{22} = 1; // 64-bit FPR flag
3300 }
3301
3302 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3303 let Inst{31} = 0; // 32-bit GPR flag
3304 let Inst{22} = 0; // 32-bit FPR flag
3305 }
3306
3307 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3308 let Inst{31} = 1; // 64-bit GPR flag
3309 let Inst{22} = 1; // 64-bit FPR flag
3310 }
3311
3312 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3313 asm#".d"> {
3314 let Inst{31} = 1;
3315 let Inst{22} = 0;
3316 }
3317
3318 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3319 asm#".d"> {
3320 let Inst{31} = 1;
3321 let Inst{22} = 0;
3322 }
3323
3324 def : InstAlias<asm#"$Vd.d[1], $Rn",
3325 (!cast<Instruction>(NAME#XDHighr) V128:$Vd, GPR64:$Rn), 0>;
3326 def : InstAlias<asm#"$Rd, $Vn.d[1]",
3327 (!cast<Instruction>(NAME#DXHighr) GPR64:$Rd, V128:$Vn), 0>;
3328}
3329
3330//---
3331// Floating point conversion
3332//---
3333
3334class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3335 RegisterClass srcType, string asm, list<dag> pattern>
3336 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3337 Sched<[WriteFCvt]> {
3338 bits<5> Rd;
3339 bits<5> Rn;
3340 let Inst{31-24} = 0b00011110;
3341 let Inst{23-22} = type;
3342 let Inst{21-17} = 0b10001;
3343 let Inst{16-15} = opcode;
3344 let Inst{14-10} = 0b10000;
3345 let Inst{9-5} = Rn;
3346 let Inst{4-0} = Rd;
3347}
3348
3349multiclass FPConversion<string asm> {
3350 // Double-precision to Half-precision
3351 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3352 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, []>;
3353
3354 // Double-precision to Single-precision
3355 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3356 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3357
3358 // Half-precision to Double-precision
3359 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3360 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, []>;
3361
3362 // Half-precision to Single-precision
3363 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3364 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, []>;
3365
3366 // Single-precision to Double-precision
3367 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3368 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3369
3370 // Single-precision to Half-precision
3371 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3372 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, []>;
3373}
3374
3375//---
3376// Single operand floating point data processing
3377//---
3378
3379let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3380class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3381 ValueType vt, string asm, SDPatternOperator node>
3382 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3383 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3384 Sched<[WriteF]> {
3385 bits<5> Rd;
3386 bits<5> Rn;
3387 let Inst{31-23} = 0b000111100;
3388 let Inst{21-19} = 0b100;
3389 let Inst{18-15} = opcode;
3390 let Inst{14-10} = 0b10000;
3391 let Inst{9-5} = Rn;
3392 let Inst{4-0} = Rd;
3393}
3394
3395multiclass SingleOperandFPData<bits<4> opcode, string asm,
3396 SDPatternOperator node = null_frag> {
3397 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3398 let Inst{22} = 0; // 32-bit size flag
3399 }
3400
3401 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3402 let Inst{22} = 1; // 64-bit size flag
3403 }
3404}
3405
3406//---
3407// Two operand floating point data processing
3408//---
3409
3410let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3411class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3412 string asm, list<dag> pat>
3413 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3414 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3415 Sched<[WriteF]> {
3416 bits<5> Rd;
3417 bits<5> Rn;
3418 bits<5> Rm;
3419 let Inst{31-23} = 0b000111100;
3420 let Inst{21} = 1;
3421 let Inst{20-16} = Rm;
3422 let Inst{15-12} = opcode;
3423 let Inst{11-10} = 0b10;
3424 let Inst{9-5} = Rn;
3425 let Inst{4-0} = Rd;
3426}
3427
3428multiclass TwoOperandFPData<bits<4> opcode, string asm,
3429 SDPatternOperator node = null_frag> {
3430 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3431 [(set (f32 FPR32:$Rd),
3432 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3433 let Inst{22} = 0; // 32-bit size flag
3434 }
3435
3436 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3437 [(set (f64 FPR64:$Rd),
3438 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3439 let Inst{22} = 1; // 64-bit size flag
3440 }
3441}
3442
3443multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3444 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3445 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3446 let Inst{22} = 0; // 32-bit size flag
3447 }
3448
3449 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3450 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3451 let Inst{22} = 1; // 64-bit size flag
3452 }
3453}
3454
3455
3456//---
3457// Three operand floating point data processing
3458//---
3459
3460class BaseThreeOperandFPData<bit isNegated, bit isSub,
3461 RegisterClass regtype, string asm, list<dag> pat>
3462 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3463 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3464 Sched<[WriteFMul]> {
3465 bits<5> Rd;
3466 bits<5> Rn;
3467 bits<5> Rm;
3468 bits<5> Ra;
3469 let Inst{31-23} = 0b000111110;
3470 let Inst{21} = isNegated;
3471 let Inst{20-16} = Rm;
3472 let Inst{15} = isSub;
3473 let Inst{14-10} = Ra;
3474 let Inst{9-5} = Rn;
3475 let Inst{4-0} = Rd;
3476}
3477
3478multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3479 SDPatternOperator node> {
3480 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3481 [(set FPR32:$Rd,
3482 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3483 let Inst{22} = 0; // 32-bit size flag
3484 }
3485
3486 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3487 [(set FPR64:$Rd,
3488 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3489 let Inst{22} = 1; // 64-bit size flag
3490 }
3491}
3492
3493//---
3494// Floating point data comparisons
3495//---
3496
3497let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3498class BaseOneOperandFPComparison<bit signalAllNans,
3499 RegisterClass regtype, string asm,
3500 list<dag> pat>
3501 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3502 Sched<[WriteFCmp]> {
3503 bits<5> Rn;
3504 let Inst{31-23} = 0b000111100;
3505 let Inst{21} = 1;
3506
Tim Northover00ed9962014-03-29 10:18:08 +00003507 let Inst{15-10} = 0b001000;
3508 let Inst{9-5} = Rn;
3509 let Inst{4} = signalAllNans;
3510 let Inst{3-0} = 0b1000;
Bradley Smith5511f082014-04-09 14:43:40 +00003511
3512 // Rm should be 0b00000 canonically, but we need to accept any value.
3513 let PostEncoderMethod = "fixOneOperandFPComparison";
Tim Northover00ed9962014-03-29 10:18:08 +00003514}
3515
3516let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3517class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3518 string asm, list<dag> pat>
3519 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3520 Sched<[WriteFCmp]> {
3521 bits<5> Rm;
3522 bits<5> Rn;
3523 let Inst{31-23} = 0b000111100;
3524 let Inst{21} = 1;
3525 let Inst{20-16} = Rm;
3526 let Inst{15-10} = 0b001000;
3527 let Inst{9-5} = Rn;
3528 let Inst{4} = signalAllNans;
3529 let Inst{3-0} = 0b0000;
3530}
3531
3532multiclass FPComparison<bit signalAllNans, string asm,
3533 SDPatternOperator OpNode = null_frag> {
3534 let Defs = [CPSR] in {
3535 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3536 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3537 let Inst{22} = 0;
3538 }
3539
3540 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3541 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3542 let Inst{22} = 0;
3543 }
3544
3545 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3546 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3547 let Inst{22} = 1;
3548 }
3549
3550 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3551 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3552 let Inst{22} = 1;
3553 }
3554 } // Defs = [CPSR]
3555}
3556
3557//---
3558// Floating point conditional comparisons
3559//---
3560
3561let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3562class BaseFPCondComparison<bit signalAllNans,
3563 RegisterClass regtype, string asm>
3564 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3565 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3566 Sched<[WriteFCmp]> {
3567 bits<5> Rn;
3568 bits<5> Rm;
3569 bits<4> nzcv;
3570 bits<4> cond;
3571
3572 let Inst{31-23} = 0b000111100;
3573 let Inst{21} = 1;
3574 let Inst{20-16} = Rm;
3575 let Inst{15-12} = cond;
3576 let Inst{11-10} = 0b01;
3577 let Inst{9-5} = Rn;
3578 let Inst{4} = signalAllNans;
3579 let Inst{3-0} = nzcv;
3580}
3581
3582multiclass FPCondComparison<bit signalAllNans, string asm> {
3583 let Defs = [CPSR], Uses = [CPSR] in {
3584 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3585 let Inst{22} = 0;
3586 }
3587
3588 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3589 let Inst{22} = 1;
3590 }
3591 } // Defs = [CPSR], Uses = [CPSR]
3592}
3593
3594//---
3595// Floating point conditional select
3596//---
3597
3598class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3599 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3600 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3601 [(set regtype:$Rd,
3602 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3603 (i32 imm:$cond), CPSR))]>,
3604 Sched<[WriteF]> {
3605 bits<5> Rd;
3606 bits<5> Rn;
3607 bits<5> Rm;
3608 bits<4> cond;
3609
3610 let Inst{31-23} = 0b000111100;
3611 let Inst{21} = 1;
3612 let Inst{20-16} = Rm;
3613 let Inst{15-12} = cond;
3614 let Inst{11-10} = 0b11;
3615 let Inst{9-5} = Rn;
3616 let Inst{4-0} = Rd;
3617}
3618
3619multiclass FPCondSelect<string asm> {
3620 let Uses = [CPSR] in {
3621 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3622 let Inst{22} = 0;
3623 }
3624
3625 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3626 let Inst{22} = 1;
3627 }
3628 } // Uses = [CPSR]
3629}
3630
3631//---
3632// Floating move immediate
3633//---
3634
3635class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3636 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3637 [(set regtype:$Rd, fpimmtype:$imm)]>,
3638 Sched<[WriteFImm]> {
3639 bits<5> Rd;
3640 bits<8> imm;
3641 let Inst{31-23} = 0b000111100;
3642 let Inst{21} = 1;
3643 let Inst{20-13} = imm;
3644 let Inst{12-5} = 0b10000000;
3645 let Inst{4-0} = Rd;
3646}
3647
3648multiclass FPMoveImmediate<string asm> {
3649 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3650 let Inst{22} = 0;
3651 }
3652
3653 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3654 let Inst{22} = 1;
3655 }
3656}
3657
3658//----------------------------------------------------------------------------
3659// AdvSIMD
3660//----------------------------------------------------------------------------
3661
3662def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3663def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3664def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3665def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3666def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3667 return ((uint64_t)Imm) < 16;
3668}]> {
3669 let ParserMatchClass = VectorIndexBOperand;
3670 let PrintMethod = "printVectorIndex";
3671 let MIOperandInfo = (ops i64imm);
3672}
3673def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3674 return ((uint64_t)Imm) < 8;
3675}]> {
3676 let ParserMatchClass = VectorIndexHOperand;
3677 let PrintMethod = "printVectorIndex";
3678 let MIOperandInfo = (ops i64imm);
3679}
3680def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3681 return ((uint64_t)Imm) < 4;
3682}]> {
3683 let ParserMatchClass = VectorIndexSOperand;
3684 let PrintMethod = "printVectorIndex";
3685 let MIOperandInfo = (ops i64imm);
3686}
3687def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3688 return ((uint64_t)Imm) < 2;
3689}]> {
3690 let ParserMatchClass = VectorIndexDOperand;
3691 let PrintMethod = "printVectorIndex";
3692 let MIOperandInfo = (ops i64imm);
3693}
3694
3695//----------------------------------------------------------------------------
3696// AdvSIMD three register vector instructions
3697//----------------------------------------------------------------------------
3698
3699let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3700class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3701 RegisterOperand regtype, string asm, string kind,
3702 list<dag> pattern>
3703 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3704 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3705 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3706 Sched<[WriteV]> {
3707 bits<5> Rd;
3708 bits<5> Rn;
3709 bits<5> Rm;
3710 let Inst{31} = 0;
3711 let Inst{30} = Q;
3712 let Inst{29} = U;
3713 let Inst{28-24} = 0b01110;
3714 let Inst{23-22} = size;
3715 let Inst{21} = 1;
3716 let Inst{20-16} = Rm;
3717 let Inst{15-11} = opcode;
3718 let Inst{10} = 1;
3719 let Inst{9-5} = Rn;
3720 let Inst{4-0} = Rd;
3721}
3722
3723let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3724class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3725 RegisterOperand regtype, string asm, string kind,
3726 list<dag> pattern>
3727 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3728 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3729 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3730 Sched<[WriteV]> {
3731 bits<5> Rd;
3732 bits<5> Rn;
3733 bits<5> Rm;
3734 let Inst{31} = 0;
3735 let Inst{30} = Q;
3736 let Inst{29} = U;
3737 let Inst{28-24} = 0b01110;
3738 let Inst{23-22} = size;
3739 let Inst{21} = 1;
3740 let Inst{20-16} = Rm;
3741 let Inst{15-11} = opcode;
3742 let Inst{10} = 1;
3743 let Inst{9-5} = Rn;
3744 let Inst{4-0} = Rd;
3745}
3746
3747// All operand sizes distinguished in the encoding.
3748multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3749 SDPatternOperator OpNode> {
3750 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3751 asm, ".8b",
3752 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3753 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3754 asm, ".16b",
3755 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3756 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3757 asm, ".4h",
3758 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3759 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3760 asm, ".8h",
3761 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3762 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3763 asm, ".2s",
3764 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3765 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3766 asm, ".4s",
3767 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3768 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3769 asm, ".2d",
3770 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3771}
3772
3773// As above, but D sized elements unsupported.
3774multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3775 SDPatternOperator OpNode> {
3776 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3777 asm, ".8b",
3778 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3779 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3780 asm, ".16b",
3781 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3782 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3783 asm, ".4h",
3784 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3785 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3786 asm, ".8h",
3787 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3788 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3789 asm, ".2s",
3790 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3791 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3792 asm, ".4s",
3793 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3794}
3795
3796multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3797 SDPatternOperator OpNode> {
3798 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3799 asm, ".8b",
3800 [(set (v8i8 V64:$dst),
3801 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3802 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3803 asm, ".16b",
3804 [(set (v16i8 V128:$dst),
3805 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3806 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3807 asm, ".4h",
3808 [(set (v4i16 V64:$dst),
3809 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3810 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3811 asm, ".8h",
3812 [(set (v8i16 V128:$dst),
3813 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3814 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3815 asm, ".2s",
3816 [(set (v2i32 V64:$dst),
3817 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3818 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3819 asm, ".4s",
3820 [(set (v4i32 V128:$dst),
3821 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3822}
3823
3824// As above, but only B sized elements supported.
3825multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3826 SDPatternOperator OpNode> {
3827 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3828 asm, ".8b",
3829 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3830 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3831 asm, ".16b",
3832 [(set (v16i8 V128:$Rd),
3833 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3834}
3835
3836// As above, but only S and D sized floating point elements supported.
3837multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3838 string asm, SDPatternOperator OpNode> {
3839 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3840 asm, ".2s",
3841 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3842 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3843 asm, ".4s",
3844 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3845 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3846 asm, ".2d",
3847 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3848}
3849
3850multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3851 string asm,
3852 SDPatternOperator OpNode> {
3853 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3854 asm, ".2s",
3855 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3856 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3857 asm, ".4s",
3858 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3859 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3860 asm, ".2d",
3861 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3862}
3863
3864multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3865 string asm, SDPatternOperator OpNode> {
3866 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3867 asm, ".2s",
3868 [(set (v2f32 V64:$dst),
3869 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3870 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3871 asm, ".4s",
3872 [(set (v4f32 V128:$dst),
3873 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3874 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3875 asm, ".2d",
3876 [(set (v2f64 V128:$dst),
3877 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3878}
3879
3880// As above, but D and B sized elements unsupported.
3881multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3882 SDPatternOperator OpNode> {
3883 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3884 asm, ".4h",
3885 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3886 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3887 asm, ".8h",
3888 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3889 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3890 asm, ".2s",
3891 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3892 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3893 asm, ".4s",
3894 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3895}
3896
3897// Logical three vector ops share opcode bits, and only use B sized elements.
3898multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3899 SDPatternOperator OpNode = null_frag> {
3900 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3901 asm, ".8b",
3902 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3903 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3904 asm, ".16b",
3905 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3906
3907 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3908 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3909 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3910 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3911 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3912 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3913
3914 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3915 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3916 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3917 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3918 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3919 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3920}
3921
3922multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3923 string asm, SDPatternOperator OpNode> {
3924 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3925 asm, ".8b",
3926 [(set (v8i8 V64:$dst),
3927 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3928 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3929 asm, ".16b",
3930 [(set (v16i8 V128:$dst),
3931 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3932 (v16i8 V128:$Rm)))]>;
3933
3934 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3935 (v4i16 V64:$RHS))),
3936 (!cast<Instruction>(NAME#"v8i8")
3937 V64:$LHS, V64:$MHS, V64:$RHS)>;
3938 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3939 (v2i32 V64:$RHS))),
3940 (!cast<Instruction>(NAME#"v8i8")
3941 V64:$LHS, V64:$MHS, V64:$RHS)>;
3942 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3943 (v1i64 V64:$RHS))),
3944 (!cast<Instruction>(NAME#"v8i8")
3945 V64:$LHS, V64:$MHS, V64:$RHS)>;
3946
3947 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3948 (v8i16 V128:$RHS))),
3949 (!cast<Instruction>(NAME#"v16i8")
3950 V128:$LHS, V128:$MHS, V128:$RHS)>;
3951 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
3952 (v4i32 V128:$RHS))),
3953 (!cast<Instruction>(NAME#"v16i8")
3954 V128:$LHS, V128:$MHS, V128:$RHS)>;
3955 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
3956 (v2i64 V128:$RHS))),
3957 (!cast<Instruction>(NAME#"v16i8")
3958 V128:$LHS, V128:$MHS, V128:$RHS)>;
3959}
3960
3961
3962//----------------------------------------------------------------------------
3963// AdvSIMD two register vector instructions.
3964//----------------------------------------------------------------------------
3965
3966let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3967class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3968 RegisterOperand regtype, string asm, string dstkind,
3969 string srckind, list<dag> pattern>
3970 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
3971 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3972 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
3973 Sched<[WriteV]> {
3974 bits<5> Rd;
3975 bits<5> Rn;
3976 let Inst{31} = 0;
3977 let Inst{30} = Q;
3978 let Inst{29} = U;
3979 let Inst{28-24} = 0b01110;
3980 let Inst{23-22} = size;
3981 let Inst{21-17} = 0b10000;
3982 let Inst{16-12} = opcode;
3983 let Inst{11-10} = 0b10;
3984 let Inst{9-5} = Rn;
3985 let Inst{4-0} = Rd;
3986}
3987
3988let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3989class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3990 RegisterOperand regtype, string asm, string dstkind,
3991 string srckind, list<dag> pattern>
3992 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
3993 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3994 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
3995 Sched<[WriteV]> {
3996 bits<5> Rd;
3997 bits<5> Rn;
3998 let Inst{31} = 0;
3999 let Inst{30} = Q;
4000 let Inst{29} = U;
4001 let Inst{28-24} = 0b01110;
4002 let Inst{23-22} = size;
4003 let Inst{21-17} = 0b10000;
4004 let Inst{16-12} = opcode;
4005 let Inst{11-10} = 0b10;
4006 let Inst{9-5} = Rn;
4007 let Inst{4-0} = Rd;
4008}
4009
4010// Supports B, H, and S element sizes.
4011multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4012 SDPatternOperator OpNode> {
4013 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4014 asm, ".8b", ".8b",
4015 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4016 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4017 asm, ".16b", ".16b",
4018 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4019 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4020 asm, ".4h", ".4h",
4021 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4022 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4023 asm, ".8h", ".8h",
4024 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4025 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4026 asm, ".2s", ".2s",
4027 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4028 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4029 asm, ".4s", ".4s",
4030 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4031}
4032
4033class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4034 RegisterOperand regtype, string asm, string dstkind,
4035 string srckind, string amount>
4036 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4037 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4038 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4039 Sched<[WriteV]> {
4040 bits<5> Rd;
4041 bits<5> Rn;
4042 let Inst{31} = 0;
4043 let Inst{30} = Q;
4044 let Inst{29-24} = 0b101110;
4045 let Inst{23-22} = size;
4046 let Inst{21-10} = 0b100001001110;
4047 let Inst{9-5} = Rn;
4048 let Inst{4-0} = Rd;
4049}
4050
4051multiclass SIMDVectorLShiftLongBySizeBHS {
4052 let neverHasSideEffects = 1 in {
4053 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4054 "shll", ".8h", ".8b", "8">;
4055 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4056 "shll2", ".8h", ".16b", "8">;
4057 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4058 "shll", ".4s", ".4h", "16">;
4059 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4060 "shll2", ".4s", ".8h", "16">;
4061 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4062 "shll", ".2d", ".2s", "32">;
4063 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4064 "shll2", ".2d", ".4s", "32">;
4065 }
4066}
4067
4068// Supports all element sizes.
4069multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4070 SDPatternOperator OpNode> {
4071 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4072 asm, ".4h", ".8b",
4073 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4074 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4075 asm, ".8h", ".16b",
4076 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4077 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4078 asm, ".2s", ".4h",
4079 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4080 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4081 asm, ".4s", ".8h",
4082 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4083 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4084 asm, ".1d", ".2s",
4085 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4086 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4087 asm, ".2d", ".4s",
4088 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4089}
4090
4091multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4092 SDPatternOperator OpNode> {
4093 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4094 asm, ".4h", ".8b",
4095 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4096 (v8i8 V64:$Rn)))]>;
4097 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4098 asm, ".8h", ".16b",
4099 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4100 (v16i8 V128:$Rn)))]>;
4101 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4102 asm, ".2s", ".4h",
4103 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4104 (v4i16 V64:$Rn)))]>;
4105 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4106 asm, ".4s", ".8h",
4107 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4108 (v8i16 V128:$Rn)))]>;
4109 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4110 asm, ".1d", ".2s",
4111 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4112 (v2i32 V64:$Rn)))]>;
4113 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4114 asm, ".2d", ".4s",
4115 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4116 (v4i32 V128:$Rn)))]>;
4117}
4118
4119// Supports all element sizes, except 1xD.
4120multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4121 SDPatternOperator OpNode> {
4122 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4123 asm, ".8b", ".8b",
4124 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4125 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4126 asm, ".16b", ".16b",
4127 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4128 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4129 asm, ".4h", ".4h",
4130 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4131 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4132 asm, ".8h", ".8h",
4133 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4134 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4135 asm, ".2s", ".2s",
4136 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4137 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4138 asm, ".4s", ".4s",
4139 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4140 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4141 asm, ".2d", ".2d",
4142 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4143}
4144
4145multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4146 SDPatternOperator OpNode = null_frag> {
4147 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4148 asm, ".8b", ".8b",
4149 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4150 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4151 asm, ".16b", ".16b",
4152 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4153 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4154 asm, ".4h", ".4h",
4155 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4156 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4157 asm, ".8h", ".8h",
4158 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4159 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4160 asm, ".2s", ".2s",
4161 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4162 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4163 asm, ".4s", ".4s",
4164 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4165 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4166 asm, ".2d", ".2d",
4167 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4168}
4169
4170
4171// Supports only B element sizes.
4172multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4173 SDPatternOperator OpNode> {
4174 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4175 asm, ".8b", ".8b",
4176 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4177 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4178 asm, ".16b", ".16b",
4179 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4180
4181}
4182
4183// Supports only B and H element sizes.
4184multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4185 SDPatternOperator OpNode> {
4186 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4187 asm, ".8b", ".8b",
4188 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4189 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4190 asm, ".16b", ".16b",
4191 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4192 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4193 asm, ".4h", ".4h",
4194 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4195 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4196 asm, ".8h", ".8h",
4197 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4198}
4199
4200// Supports only S and D element sizes, uses high bit of the size field
4201// as an extra opcode bit.
4202multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4203 SDPatternOperator OpNode> {
4204 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4205 asm, ".2s", ".2s",
4206 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4207 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4208 asm, ".4s", ".4s",
4209 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4210 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4211 asm, ".2d", ".2d",
4212 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4213}
4214
4215// Supports only S element size.
4216multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4217 SDPatternOperator OpNode> {
4218 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4219 asm, ".2s", ".2s",
4220 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4221 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4222 asm, ".4s", ".4s",
4223 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4224}
4225
4226
4227multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4228 SDPatternOperator OpNode> {
4229 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4230 asm, ".2s", ".2s",
4231 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4232 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4233 asm, ".4s", ".4s",
4234 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4235 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4236 asm, ".2d", ".2d",
4237 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4238}
4239
4240multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4241 SDPatternOperator OpNode> {
4242 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4243 asm, ".2s", ".2s",
4244 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4245 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4246 asm, ".4s", ".4s",
4247 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4248 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4249 asm, ".2d", ".2d",
4250 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4251}
4252
4253
4254class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4255 RegisterOperand inreg, RegisterOperand outreg,
4256 string asm, string outkind, string inkind,
4257 list<dag> pattern>
4258 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4259 "{\t$Rd" # outkind # ", $Rn" # inkind #
4260 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4261 Sched<[WriteV]> {
4262 bits<5> Rd;
4263 bits<5> Rn;
4264 let Inst{31} = 0;
4265 let Inst{30} = Q;
4266 let Inst{29} = U;
4267 let Inst{28-24} = 0b01110;
4268 let Inst{23-22} = size;
4269 let Inst{21-17} = 0b10000;
4270 let Inst{16-12} = opcode;
4271 let Inst{11-10} = 0b10;
4272 let Inst{9-5} = Rn;
4273 let Inst{4-0} = Rd;
4274}
4275
4276class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4277 RegisterOperand inreg, RegisterOperand outreg,
4278 string asm, string outkind, string inkind,
4279 list<dag> pattern>
4280 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4281 "{\t$Rd" # outkind # ", $Rn" # inkind #
4282 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4283 Sched<[WriteV]> {
4284 bits<5> Rd;
4285 bits<5> Rn;
4286 let Inst{31} = 0;
4287 let Inst{30} = Q;
4288 let Inst{29} = U;
4289 let Inst{28-24} = 0b01110;
4290 let Inst{23-22} = size;
4291 let Inst{21-17} = 0b10000;
4292 let Inst{16-12} = opcode;
4293 let Inst{11-10} = 0b10;
4294 let Inst{9-5} = Rn;
4295 let Inst{4-0} = Rd;
4296}
4297
4298multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4299 SDPatternOperator OpNode> {
4300 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4301 asm, ".8b", ".8h",
4302 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4303 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4304 asm#"2", ".16b", ".8h", []>;
4305 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4306 asm, ".4h", ".4s",
4307 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4308 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4309 asm#"2", ".8h", ".4s", []>;
4310 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4311 asm, ".2s", ".2d",
4312 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4313 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4314 asm#"2", ".4s", ".2d", []>;
4315
4316 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4317 (!cast<Instruction>(NAME # "v16i8")
4318 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4319 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4320 (!cast<Instruction>(NAME # "v8i16")
4321 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4322 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4323 (!cast<Instruction>(NAME # "v4i32")
4324 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4325}
4326
4327class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4328 RegisterOperand regtype, string asm, string kind,
4329 ValueType dty, ValueType sty, SDNode OpNode>
4330 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4331 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4332 "|" # kind # "\t$Rd, $Rn, #0}", "",
4333 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4334 Sched<[WriteV]> {
4335 bits<5> Rd;
4336 bits<5> Rn;
4337 let Inst{31} = 0;
4338 let Inst{30} = Q;
4339 let Inst{29} = U;
4340 let Inst{28-24} = 0b01110;
4341 let Inst{23-22} = size;
4342 let Inst{21-17} = 0b10000;
4343 let Inst{16-12} = opcode;
4344 let Inst{11-10} = 0b10;
4345 let Inst{9-5} = Rn;
4346 let Inst{4-0} = Rd;
4347}
4348
4349// Comparisons support all element sizes, except 1xD.
4350multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4351 SDNode OpNode> {
4352 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4353 asm, ".8b",
4354 v8i8, v8i8, OpNode>;
4355 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4356 asm, ".16b",
4357 v16i8, v16i8, OpNode>;
4358 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4359 asm, ".4h",
4360 v4i16, v4i16, OpNode>;
4361 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4362 asm, ".8h",
4363 v8i16, v8i16, OpNode>;
4364 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4365 asm, ".2s",
4366 v2i32, v2i32, OpNode>;
4367 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4368 asm, ".4s",
4369 v4i32, v4i32, OpNode>;
4370 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4371 asm, ".2d",
4372 v2i64, v2i64, OpNode>;
4373}
4374
4375// FP Comparisons support only S and D element sizes.
4376multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4377 string asm, SDNode OpNode> {
4378 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4379 asm, ".2s",
4380 v2i32, v2f32, OpNode>;
4381 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4382 asm, ".4s",
4383 v4i32, v4f32, OpNode>;
4384 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4385 asm, ".2d",
4386 v2i64, v2f64, OpNode>;
4387}
4388
4389let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4390class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4391 RegisterOperand outtype, RegisterOperand intype,
4392 string asm, string VdTy, string VnTy,
4393 list<dag> pattern>
4394 : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4395 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4396 Sched<[WriteV]> {
4397 bits<5> Rd;
4398 bits<5> Rn;
4399 let Inst{31} = 0;
4400 let Inst{30} = Q;
4401 let Inst{29} = U;
4402 let Inst{28-24} = 0b01110;
4403 let Inst{23-22} = size;
4404 let Inst{21-17} = 0b10000;
4405 let Inst{16-12} = opcode;
4406 let Inst{11-10} = 0b10;
4407 let Inst{9-5} = Rn;
4408 let Inst{4-0} = Rd;
4409}
4410
4411class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4412 RegisterOperand outtype, RegisterOperand intype,
4413 string asm, string VdTy, string VnTy,
4414 list<dag> pattern>
4415 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4416 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4417 Sched<[WriteV]> {
4418 bits<5> Rd;
4419 bits<5> Rn;
4420 let Inst{31} = 0;
4421 let Inst{30} = Q;
4422 let Inst{29} = U;
4423 let Inst{28-24} = 0b01110;
4424 let Inst{23-22} = size;
4425 let Inst{21-17} = 0b10000;
4426 let Inst{16-12} = opcode;
4427 let Inst{11-10} = 0b10;
4428 let Inst{9-5} = Rn;
4429 let Inst{4-0} = Rd;
4430}
4431
4432multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4433 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4434 asm, ".4s", ".4h", []>;
4435 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4436 asm#"2", ".4s", ".8h", []>;
4437 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4438 asm, ".2d", ".2s", []>;
4439 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4440 asm#"2", ".2d", ".4s", []>;
4441}
4442
4443multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4444 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4445 asm, ".4h", ".4s", []>;
4446 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4447 asm#"2", ".8h", ".4s", []>;
4448 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4449 asm, ".2s", ".2d", []>;
4450 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4451 asm#"2", ".4s", ".2d", []>;
4452}
4453
4454multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4455 Intrinsic OpNode> {
4456 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4457 asm, ".2s", ".2d",
4458 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4459 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4460 asm#"2", ".4s", ".2d", []>;
4461
4462 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4463 (!cast<Instruction>(NAME # "v4f32")
4464 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4465}
4466
4467//----------------------------------------------------------------------------
4468// AdvSIMD three register different-size vector instructions.
4469//----------------------------------------------------------------------------
4470
4471let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4472class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4473 RegisterOperand outtype, RegisterOperand intype1,
4474 RegisterOperand intype2, string asm,
4475 string outkind, string inkind1, string inkind2,
4476 list<dag> pattern>
4477 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4478 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4479 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4480 Sched<[WriteV]> {
4481 bits<5> Rd;
4482 bits<5> Rn;
4483 bits<5> Rm;
4484 let Inst{31} = 0;
4485 let Inst{30} = size{0};
4486 let Inst{29} = U;
4487 let Inst{28-24} = 0b01110;
4488 let Inst{23-22} = size{2-1};
4489 let Inst{21} = 1;
4490 let Inst{20-16} = Rm;
4491 let Inst{15-12} = opcode;
4492 let Inst{11-10} = 0b00;
4493 let Inst{9-5} = Rn;
4494 let Inst{4-0} = Rd;
4495}
4496
4497let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4498class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4499 RegisterOperand outtype, RegisterOperand intype1,
4500 RegisterOperand intype2, string asm,
4501 string outkind, string inkind1, string inkind2,
4502 list<dag> pattern>
4503 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4504 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4505 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4506 Sched<[WriteV]> {
4507 bits<5> Rd;
4508 bits<5> Rn;
4509 bits<5> Rm;
4510 let Inst{31} = 0;
4511 let Inst{30} = size{0};
4512 let Inst{29} = U;
4513 let Inst{28-24} = 0b01110;
4514 let Inst{23-22} = size{2-1};
4515 let Inst{21} = 1;
4516 let Inst{20-16} = Rm;
4517 let Inst{15-12} = opcode;
4518 let Inst{11-10} = 0b00;
4519 let Inst{9-5} = Rn;
4520 let Inst{4-0} = Rd;
4521}
4522
4523// FIXME: TableGen doesn't know how to deal with expanded types that also
4524// change the element count (in this case, placing the results in
4525// the high elements of the result register rather than the low
4526// elements). Until that's fixed, we can't code-gen those.
4527multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4528 Intrinsic IntOp> {
4529 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4530 V64, V128, V128,
4531 asm, ".8b", ".8h", ".8h",
4532 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4533 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4534 V128, V128, V128,
4535 asm#"2", ".16b", ".8h", ".8h",
4536 []>;
4537 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4538 V64, V128, V128,
4539 asm, ".4h", ".4s", ".4s",
4540 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4541 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4542 V128, V128, V128,
4543 asm#"2", ".8h", ".4s", ".4s",
4544 []>;
4545 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4546 V64, V128, V128,
4547 asm, ".2s", ".2d", ".2d",
4548 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4549 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4550 V128, V128, V128,
4551 asm#"2", ".4s", ".2d", ".2d",
4552 []>;
4553
4554
4555 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4556 // a version attached to an instruction.
4557 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4558 (v8i16 V128:$Rm))),
4559 (!cast<Instruction>(NAME # "v8i16_v16i8")
4560 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4561 V128:$Rn, V128:$Rm)>;
4562 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4563 (v4i32 V128:$Rm))),
4564 (!cast<Instruction>(NAME # "v4i32_v8i16")
4565 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4566 V128:$Rn, V128:$Rm)>;
4567 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4568 (v2i64 V128:$Rm))),
4569 (!cast<Instruction>(NAME # "v2i64_v4i32")
4570 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4571 V128:$Rn, V128:$Rm)>;
4572}
4573
4574multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4575 Intrinsic IntOp> {
4576 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4577 V128, V64, V64,
4578 asm, ".8h", ".8b", ".8b",
4579 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4580 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4581 V128, V128, V128,
4582 asm#"2", ".8h", ".16b", ".16b", []>;
4583 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4584 V128, V64, V64,
4585 asm, ".1q", ".1d", ".1d", []>;
4586 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4587 V128, V128, V128,
4588 asm#"2", ".1q", ".2d", ".2d", []>;
4589
4590 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4591 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4592 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4593}
4594
4595multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4596 SDPatternOperator OpNode> {
4597 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4598 V128, V64, V64,
4599 asm, ".4s", ".4h", ".4h",
4600 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4601 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4602 V128, V128, V128,
4603 asm#"2", ".4s", ".8h", ".8h",
4604 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4605 (extract_high_v8i16 V128:$Rm)))]>;
4606 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4607 V128, V64, V64,
4608 asm, ".2d", ".2s", ".2s",
4609 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4610 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4611 V128, V128, V128,
4612 asm#"2", ".2d", ".4s", ".4s",
4613 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4614 (extract_high_v4i32 V128:$Rm)))]>;
4615}
4616
4617multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4618 SDPatternOperator OpNode = null_frag> {
4619 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4620 V128, V64, V64,
4621 asm, ".8h", ".8b", ".8b",
4622 [(set (v8i16 V128:$Rd),
4623 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4624 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4625 V128, V128, V128,
4626 asm#"2", ".8h", ".16b", ".16b",
4627 [(set (v8i16 V128:$Rd),
4628 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4629 (extract_high_v16i8 V128:$Rm)))))]>;
4630 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4631 V128, V64, V64,
4632 asm, ".4s", ".4h", ".4h",
4633 [(set (v4i32 V128:$Rd),
4634 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4635 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4636 V128, V128, V128,
4637 asm#"2", ".4s", ".8h", ".8h",
4638 [(set (v4i32 V128:$Rd),
4639 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4640 (extract_high_v8i16 V128:$Rm)))))]>;
4641 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4642 V128, V64, V64,
4643 asm, ".2d", ".2s", ".2s",
4644 [(set (v2i64 V128:$Rd),
4645 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4646 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4647 V128, V128, V128,
4648 asm#"2", ".2d", ".4s", ".4s",
4649 [(set (v2i64 V128:$Rd),
4650 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4651 (extract_high_v4i32 V128:$Rm)))))]>;
4652}
4653
4654multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4655 string asm,
4656 SDPatternOperator OpNode> {
4657 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4658 V128, V64, V64,
4659 asm, ".8h", ".8b", ".8b",
4660 [(set (v8i16 V128:$dst),
4661 (add (v8i16 V128:$Rd),
4662 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4663 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4664 V128, V128, V128,
4665 asm#"2", ".8h", ".16b", ".16b",
4666 [(set (v8i16 V128:$dst),
4667 (add (v8i16 V128:$Rd),
4668 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4669 (extract_high_v16i8 V128:$Rm))))))]>;
4670 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4671 V128, V64, V64,
4672 asm, ".4s", ".4h", ".4h",
4673 [(set (v4i32 V128:$dst),
4674 (add (v4i32 V128:$Rd),
4675 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4676 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4677 V128, V128, V128,
4678 asm#"2", ".4s", ".8h", ".8h",
4679 [(set (v4i32 V128:$dst),
4680 (add (v4i32 V128:$Rd),
4681 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4682 (extract_high_v8i16 V128:$Rm))))))]>;
4683 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4684 V128, V64, V64,
4685 asm, ".2d", ".2s", ".2s",
4686 [(set (v2i64 V128:$dst),
4687 (add (v2i64 V128:$Rd),
4688 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4689 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4690 V128, V128, V128,
4691 asm#"2", ".2d", ".4s", ".4s",
4692 [(set (v2i64 V128:$dst),
4693 (add (v2i64 V128:$Rd),
4694 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4695 (extract_high_v4i32 V128:$Rm))))))]>;
4696}
4697
4698multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4699 SDPatternOperator OpNode = null_frag> {
4700 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4701 V128, V64, V64,
4702 asm, ".8h", ".8b", ".8b",
4703 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4704 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4705 V128, V128, V128,
4706 asm#"2", ".8h", ".16b", ".16b",
4707 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4708 (extract_high_v16i8 V128:$Rm)))]>;
4709 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4710 V128, V64, V64,
4711 asm, ".4s", ".4h", ".4h",
4712 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4713 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4714 V128, V128, V128,
4715 asm#"2", ".4s", ".8h", ".8h",
4716 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4717 (extract_high_v8i16 V128:$Rm)))]>;
4718 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4719 V128, V64, V64,
4720 asm, ".2d", ".2s", ".2s",
4721 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4722 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4723 V128, V128, V128,
4724 asm#"2", ".2d", ".4s", ".4s",
4725 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4726 (extract_high_v4i32 V128:$Rm)))]>;
4727}
4728
4729multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4730 string asm,
4731 SDPatternOperator OpNode> {
4732 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4733 V128, V64, V64,
4734 asm, ".8h", ".8b", ".8b",
4735 [(set (v8i16 V128:$dst),
4736 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4737 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4738 V128, V128, V128,
4739 asm#"2", ".8h", ".16b", ".16b",
4740 [(set (v8i16 V128:$dst),
4741 (OpNode (v8i16 V128:$Rd),
4742 (extract_high_v16i8 V128:$Rn),
4743 (extract_high_v16i8 V128:$Rm)))]>;
4744 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4745 V128, V64, V64,
4746 asm, ".4s", ".4h", ".4h",
4747 [(set (v4i32 V128:$dst),
4748 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4749 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4750 V128, V128, V128,
4751 asm#"2", ".4s", ".8h", ".8h",
4752 [(set (v4i32 V128:$dst),
4753 (OpNode (v4i32 V128:$Rd),
4754 (extract_high_v8i16 V128:$Rn),
4755 (extract_high_v8i16 V128:$Rm)))]>;
4756 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4757 V128, V64, V64,
4758 asm, ".2d", ".2s", ".2s",
4759 [(set (v2i64 V128:$dst),
4760 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4761 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4762 V128, V128, V128,
4763 asm#"2", ".2d", ".4s", ".4s",
4764 [(set (v2i64 V128:$dst),
4765 (OpNode (v2i64 V128:$Rd),
4766 (extract_high_v4i32 V128:$Rn),
4767 (extract_high_v4i32 V128:$Rm)))]>;
4768}
4769
4770multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4771 SDPatternOperator Accum> {
4772 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4773 V128, V64, V64,
4774 asm, ".4s", ".4h", ".4h",
4775 [(set (v4i32 V128:$dst),
4776 (Accum (v4i32 V128:$Rd),
4777 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4778 (v4i16 V64:$Rm)))))]>;
4779 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4780 V128, V128, V128,
4781 asm#"2", ".4s", ".8h", ".8h",
4782 [(set (v4i32 V128:$dst),
4783 (Accum (v4i32 V128:$Rd),
4784 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4785 (extract_high_v8i16 V128:$Rm)))))]>;
4786 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4787 V128, V64, V64,
4788 asm, ".2d", ".2s", ".2s",
4789 [(set (v2i64 V128:$dst),
4790 (Accum (v2i64 V128:$Rd),
4791 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4792 (v2i32 V64:$Rm)))))]>;
4793 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4794 V128, V128, V128,
4795 asm#"2", ".2d", ".4s", ".4s",
4796 [(set (v2i64 V128:$dst),
4797 (Accum (v2i64 V128:$Rd),
4798 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4799 (extract_high_v4i32 V128:$Rm)))))]>;
4800}
4801
4802multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4803 SDPatternOperator OpNode> {
4804 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4805 V128, V128, V64,
4806 asm, ".8h", ".8h", ".8b",
4807 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4808 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4809 V128, V128, V128,
4810 asm#"2", ".8h", ".8h", ".16b",
4811 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4812 (extract_high_v16i8 V128:$Rm)))]>;
4813 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4814 V128, V128, V64,
4815 asm, ".4s", ".4s", ".4h",
4816 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4817 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4818 V128, V128, V128,
4819 asm#"2", ".4s", ".4s", ".8h",
4820 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4821 (extract_high_v8i16 V128:$Rm)))]>;
4822 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4823 V128, V128, V64,
4824 asm, ".2d", ".2d", ".2s",
4825 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4826 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4827 V128, V128, V128,
4828 asm#"2", ".2d", ".2d", ".4s",
4829 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4830 (extract_high_v4i32 V128:$Rm)))]>;
4831}
4832
4833//----------------------------------------------------------------------------
4834// AdvSIMD bitwise extract from vector
4835//----------------------------------------------------------------------------
4836
4837class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4838 string asm, string kind>
4839 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4840 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4841 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4842 [(set (vty regtype:$Rd),
4843 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4844 Sched<[WriteV]> {
4845 bits<5> Rd;
4846 bits<5> Rn;
4847 bits<5> Rm;
4848 bits<4> imm;
4849 let Inst{31} = 0;
4850 let Inst{30} = size;
4851 let Inst{29-21} = 0b101110000;
4852 let Inst{20-16} = Rm;
4853 let Inst{15} = 0;
4854 let Inst{14-11} = imm;
4855 let Inst{10} = 0;
4856 let Inst{9-5} = Rn;
4857 let Inst{4-0} = Rd;
4858}
4859
4860
4861multiclass SIMDBitwiseExtract<string asm> {
Bradley Smithdb7b9b12014-04-09 14:43:31 +00004862 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4863 let imm{3} = 0;
4864 }
Tim Northover00ed9962014-03-29 10:18:08 +00004865 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4866}
4867
4868//----------------------------------------------------------------------------
4869// AdvSIMD zip vector
4870//----------------------------------------------------------------------------
4871
4872class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4873 string asm, string kind, SDNode OpNode, ValueType valty>
4874 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4875 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4876 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4877 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4878 Sched<[WriteV]> {
4879 bits<5> Rd;
4880 bits<5> Rn;
4881 bits<5> Rm;
4882 let Inst{31} = 0;
4883 let Inst{30} = size{0};
4884 let Inst{29-24} = 0b001110;
4885 let Inst{23-22} = size{2-1};
4886 let Inst{21} = 0;
4887 let Inst{20-16} = Rm;
4888 let Inst{15} = 0;
4889 let Inst{14-12} = opc;
4890 let Inst{11-10} = 0b10;
4891 let Inst{9-5} = Rn;
4892 let Inst{4-0} = Rd;
4893}
4894
4895multiclass SIMDZipVector<bits<3>opc, string asm,
4896 SDNode OpNode> {
4897 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4898 asm, ".8b", OpNode, v8i8>;
4899 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4900 asm, ".16b", OpNode, v16i8>;
4901 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4902 asm, ".4h", OpNode, v4i16>;
4903 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4904 asm, ".8h", OpNode, v8i16>;
4905 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4906 asm, ".2s", OpNode, v2i32>;
4907 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4908 asm, ".4s", OpNode, v4i32>;
4909 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4910 asm, ".2d", OpNode, v2i64>;
4911
4912 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4913 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4914 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4915 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4916 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4917 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4918}
4919
4920//----------------------------------------------------------------------------
4921// AdvSIMD three register scalar instructions
4922//----------------------------------------------------------------------------
4923
4924let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4925class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4926 RegisterClass regtype, string asm,
4927 list<dag> pattern>
4928 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4929 "\t$Rd, $Rn, $Rm", "", pattern>,
4930 Sched<[WriteV]> {
4931 bits<5> Rd;
4932 bits<5> Rn;
4933 bits<5> Rm;
4934 let Inst{31-30} = 0b01;
4935 let Inst{29} = U;
4936 let Inst{28-24} = 0b11110;
4937 let Inst{23-22} = size;
4938 let Inst{21} = 1;
4939 let Inst{20-16} = Rm;
4940 let Inst{15-11} = opcode;
4941 let Inst{10} = 1;
4942 let Inst{9-5} = Rn;
4943 let Inst{4-0} = Rd;
4944}
4945
4946multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4947 SDPatternOperator OpNode> {
4948 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4949 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4950}
4951
4952multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
4953 SDPatternOperator OpNode> {
4954 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4955 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4956 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
4957 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4958 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
4959
4960 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
4961 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
4962 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
4963 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
4964}
4965
4966multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
4967 SDPatternOperator OpNode> {
4968 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
4969 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4970 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4971}
4972
4973multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
4974 SDPatternOperator OpNode = null_frag> {
4975 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4976 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4977 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4978 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4979 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4980 }
4981
4982 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4983 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4984}
4985
4986multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
4987 SDPatternOperator OpNode = null_frag> {
4988 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4989 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4990 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4991 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4992 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
4993 }
4994
4995 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4996 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4997}
4998
4999class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5000 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5001 : I<oops, iops, asm,
5002 "\t$Rd, $Rn, $Rm", cstr, pat>,
5003 Sched<[WriteV]> {
5004 bits<5> Rd;
5005 bits<5> Rn;
5006 bits<5> Rm;
5007 let Inst{31-30} = 0b01;
5008 let Inst{29} = U;
5009 let Inst{28-24} = 0b11110;
5010 let Inst{23-22} = size;
5011 let Inst{21} = 1;
5012 let Inst{20-16} = Rm;
5013 let Inst{15-11} = opcode;
5014 let Inst{10} = 0;
5015 let Inst{9-5} = Rn;
5016 let Inst{4-0} = Rd;
5017}
5018
5019let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5020multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5021 SDPatternOperator OpNode = null_frag> {
5022 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5023 (outs FPR32:$Rd),
5024 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5025 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5026 (outs FPR64:$Rd),
5027 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5028 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5029}
5030
5031let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5032multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5033 SDPatternOperator OpNode = null_frag> {
5034 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5035 (outs FPR32:$dst),
5036 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5037 asm, "$Rd = $dst", []>;
5038 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5039 (outs FPR64:$dst),
5040 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5041 asm, "$Rd = $dst",
5042 [(set (i64 FPR64:$dst),
5043 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5044}
5045
5046//----------------------------------------------------------------------------
5047// AdvSIMD two register scalar instructions
5048//----------------------------------------------------------------------------
5049
5050let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5051class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5052 RegisterClass regtype, RegisterClass regtype2,
5053 string asm, list<dag> pat>
5054 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5055 "\t$Rd, $Rn", "", pat>,
5056 Sched<[WriteV]> {
5057 bits<5> Rd;
5058 bits<5> Rn;
5059 let Inst{31-30} = 0b01;
5060 let Inst{29} = U;
5061 let Inst{28-24} = 0b11110;
5062 let Inst{23-22} = size;
5063 let Inst{21-17} = 0b10000;
5064 let Inst{16-12} = opcode;
5065 let Inst{11-10} = 0b10;
5066 let Inst{9-5} = Rn;
5067 let Inst{4-0} = Rd;
5068}
5069
5070let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5071class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5072 RegisterClass regtype, RegisterClass regtype2,
5073 string asm, list<dag> pat>
5074 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5075 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5076 Sched<[WriteV]> {
5077 bits<5> Rd;
5078 bits<5> Rn;
5079 let Inst{31-30} = 0b01;
5080 let Inst{29} = U;
5081 let Inst{28-24} = 0b11110;
5082 let Inst{23-22} = size;
5083 let Inst{21-17} = 0b10000;
5084 let Inst{16-12} = opcode;
5085 let Inst{11-10} = 0b10;
5086 let Inst{9-5} = Rn;
5087 let Inst{4-0} = Rd;
5088}
5089
5090
5091let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5092class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5093 RegisterClass regtype, string asm>
5094 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5095 "\t$Rd, $Rn, #0", "", []>,
5096 Sched<[WriteV]> {
5097 bits<5> Rd;
5098 bits<5> Rn;
5099 let Inst{31-30} = 0b01;
5100 let Inst{29} = U;
5101 let Inst{28-24} = 0b11110;
5102 let Inst{23-22} = size;
5103 let Inst{21-17} = 0b10000;
5104 let Inst{16-12} = opcode;
5105 let Inst{11-10} = 0b10;
5106 let Inst{9-5} = Rn;
5107 let Inst{4-0} = Rd;
5108}
5109
5110class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5111 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5112 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5113 Sched<[WriteV]> {
5114 bits<5> Rd;
5115 bits<5> Rn;
5116 let Inst{31-17} = 0b011111100110000;
5117 let Inst{16-12} = opcode;
5118 let Inst{11-10} = 0b10;
5119 let Inst{9-5} = Rn;
5120 let Inst{4-0} = Rd;
5121}
5122
5123multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5124 SDPatternOperator OpNode> {
5125 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5126
5127 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5128 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5129}
5130
5131multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5132 SDPatternOperator OpNode> {
5133 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5134 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5135
5136 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5137 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5138}
5139
5140multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5141 SDPatternOperator OpNode = null_frag> {
5142 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5143 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
Tim Northoverf4810362014-03-31 15:46:17 +00005144
5145 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5146 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005147}
5148
5149multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5150 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5151 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5152}
5153
5154multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5155 SDPatternOperator OpNode> {
5156 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5157 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5158 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5159 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5160}
5161
5162multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5163 SDPatternOperator OpNode = null_frag> {
5164 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5165 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5166 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5167 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5168 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5169 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5170 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5171 }
5172
5173 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5174 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5175}
5176
Tim Northover00ed9962014-03-29 10:18:08 +00005177multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5178 Intrinsic OpNode> {
Tim Northover903814c2014-03-31 15:46:26 +00005179 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5180 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5181 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5182 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5183 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5184 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5185 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5186 }
5187
5188 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5189 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005190}
5191
5192
5193
5194let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5195multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5196 SDPatternOperator OpNode = null_frag> {
5197 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5198 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5199 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5200 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5201}
5202
5203//----------------------------------------------------------------------------
5204// AdvSIMD scalar pairwise instructions
5205//----------------------------------------------------------------------------
5206
5207let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5208class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5209 RegisterOperand regtype, RegisterOperand vectype,
5210 string asm, string kind>
5211 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5212 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5213 Sched<[WriteV]> {
5214 bits<5> Rd;
5215 bits<5> Rn;
5216 let Inst{31-30} = 0b01;
5217 let Inst{29} = U;
5218 let Inst{28-24} = 0b11110;
5219 let Inst{23-22} = size;
5220 let Inst{21-17} = 0b11000;
5221 let Inst{16-12} = opcode;
5222 let Inst{11-10} = 0b10;
5223 let Inst{9-5} = Rn;
5224 let Inst{4-0} = Rd;
5225}
5226
5227multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5228 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5229 asm, ".2d">;
5230}
5231
5232multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5233 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5234 asm, ".2s">;
5235 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5236 asm, ".2d">;
5237}
5238
5239//----------------------------------------------------------------------------
5240// AdvSIMD across lanes instructions
5241//----------------------------------------------------------------------------
5242
5243let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5244class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5245 RegisterClass regtype, RegisterOperand vectype,
5246 string asm, string kind, list<dag> pattern>
5247 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5248 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5249 Sched<[WriteV]> {
5250 bits<5> Rd;
5251 bits<5> Rn;
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-22} = size;
5257 let Inst{21-17} = 0b11000;
5258 let Inst{16-12} = opcode;
5259 let Inst{11-10} = 0b10;
5260 let Inst{9-5} = Rn;
5261 let Inst{4-0} = Rd;
5262}
5263
5264multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5265 string asm> {
5266 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5267 asm, ".8b", []>;
5268 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5269 asm, ".16b", []>;
5270 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5271 asm, ".4h", []>;
5272 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5273 asm, ".8h", []>;
5274 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5275 asm, ".4s", []>;
5276}
5277
5278multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5279 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5280 asm, ".8b", []>;
5281 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5282 asm, ".16b", []>;
5283 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5284 asm, ".4h", []>;
5285 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5286 asm, ".8h", []>;
5287 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5288 asm, ".4s", []>;
5289}
5290
5291multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5292 Intrinsic intOp> {
5293 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5294 asm, ".4s",
5295 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5296}
5297
5298//----------------------------------------------------------------------------
5299// AdvSIMD INS/DUP instructions
5300//----------------------------------------------------------------------------
5301
5302// FIXME: There has got to be a better way to factor these. ugh.
5303
5304class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5305 string operands, string constraints, list<dag> pattern>
5306 : I<outs, ins, asm, operands, constraints, pattern>,
5307 Sched<[WriteV]> {
5308 bits<5> Rd;
5309 bits<5> Rn;
5310 let Inst{31} = 0;
5311 let Inst{30} = Q;
5312 let Inst{29} = op;
5313 let Inst{28-21} = 0b01110000;
5314 let Inst{15} = 0;
5315 let Inst{10} = 1;
5316 let Inst{9-5} = Rn;
5317 let Inst{4-0} = Rd;
5318}
5319
5320class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5321 RegisterOperand vecreg, RegisterClass regtype>
5322 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5323 "{\t$Rd" # size # ", $Rn" #
5324 "|" # size # "\t$Rd, $Rn}", "",
5325 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5326 let Inst{20-16} = imm5;
5327 let Inst{14-11} = 0b0001;
5328}
5329
5330class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5331 ValueType vectype, ValueType insreg,
5332 RegisterOperand vecreg, Operand idxtype,
5333 ValueType elttype, SDNode OpNode>
5334 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5335 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5336 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5337 [(set (vectype vecreg:$Rd),
5338 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5339 let Inst{14-11} = 0b0000;
5340}
5341
5342class SIMDDup64FromElement
5343 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5344 VectorIndexD, i64, ARM64duplane64> {
5345 bits<1> idx;
5346 let Inst{20} = idx;
5347 let Inst{19-16} = 0b1000;
5348}
5349
5350class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5351 RegisterOperand vecreg>
5352 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5353 VectorIndexS, i64, ARM64duplane32> {
5354 bits<2> idx;
5355 let Inst{20-19} = idx;
5356 let Inst{18-16} = 0b100;
5357}
5358
5359class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5360 RegisterOperand vecreg>
5361 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5362 VectorIndexH, i64, ARM64duplane16> {
5363 bits<3> idx;
5364 let Inst{20-18} = idx;
5365 let Inst{17-16} = 0b10;
5366}
5367
5368class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5369 RegisterOperand vecreg>
5370 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5371 VectorIndexB, i64, ARM64duplane8> {
5372 bits<4> idx;
5373 let Inst{20-17} = idx;
5374 let Inst{16} = 1;
5375}
5376
5377class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5378 Operand idxtype, string asm, list<dag> pattern>
5379 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5380 "{\t$Rd, $Rn" # size # "$idx" #
5381 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5382 let Inst{14-11} = imm4;
5383}
5384
5385class SIMDSMov<bit Q, string size, RegisterClass regtype,
5386 Operand idxtype>
5387 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5388class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5389 Operand idxtype>
5390 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5391 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5392
5393class SIMDMovAlias<string asm, string size, Instruction inst,
5394 RegisterClass regtype, Operand idxtype>
5395 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5396 "|" # size # "\t$dst, $src$idx}",
5397 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5398
5399multiclass SMov {
5400 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5401 bits<4> idx;
5402 let Inst{20-17} = idx;
5403 let Inst{16} = 1;
5404 }
5405 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5406 bits<4> idx;
5407 let Inst{20-17} = idx;
5408 let Inst{16} = 1;
5409 }
5410 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5411 bits<3> idx;
5412 let Inst{20-18} = idx;
5413 let Inst{17-16} = 0b10;
5414 }
5415 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5416 bits<3> idx;
5417 let Inst{20-18} = idx;
5418 let Inst{17-16} = 0b10;
5419 }
5420 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5421 bits<2> idx;
5422 let Inst{20-19} = idx;
5423 let Inst{18-16} = 0b100;
5424 }
5425}
5426
5427multiclass UMov {
5428 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5429 bits<4> idx;
5430 let Inst{20-17} = idx;
5431 let Inst{16} = 1;
5432 }
5433 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5434 bits<3> idx;
5435 let Inst{20-18} = idx;
5436 let Inst{17-16} = 0b10;
5437 }
5438 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5439 bits<2> idx;
5440 let Inst{20-19} = idx;
5441 let Inst{18-16} = 0b100;
5442 }
5443 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5444 bits<1> idx;
5445 let Inst{20} = idx;
5446 let Inst{19-16} = 0b1000;
5447 }
5448 def : SIMDMovAlias<"mov", ".s",
5449 !cast<Instruction>(NAME#"vi32"),
5450 GPR32, VectorIndexS>;
5451 def : SIMDMovAlias<"mov", ".d",
5452 !cast<Instruction>(NAME#"vi64"),
5453 GPR64, VectorIndexD>;
5454}
5455
5456class SIMDInsFromMain<string size, ValueType vectype,
5457 RegisterClass regtype, Operand idxtype>
5458 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5459 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5460 "{\t$Rd" # size # "$idx, $Rn" #
5461 "|" # size # "\t$Rd$idx, $Rn}",
5462 "$Rd = $dst",
5463 [(set V128:$dst,
5464 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5465 let Inst{14-11} = 0b0011;
5466}
5467
5468class SIMDInsFromElement<string size, ValueType vectype,
5469 ValueType elttype, Operand idxtype>
5470 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5471 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5472 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5473 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5474 "$Rd = $dst",
5475 [(set V128:$dst,
5476 (vector_insert
5477 (vectype V128:$Rd),
5478 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5479 idxtype:$idx))]>;
5480
5481class SIMDInsMainMovAlias<string size, Instruction inst,
5482 RegisterClass regtype, Operand idxtype>
5483 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5484 "|" # size #"\t$dst$idx, $src}",
5485 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5486class SIMDInsElementMovAlias<string size, Instruction inst,
5487 Operand idxtype>
5488 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5489 # "|" # size #" $dst$idx, $src$idx2}",
5490 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5491
5492
5493multiclass SIMDIns {
5494 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5495 bits<4> idx;
5496 let Inst{20-17} = idx;
5497 let Inst{16} = 1;
5498 }
5499 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5500 bits<3> idx;
5501 let Inst{20-18} = idx;
5502 let Inst{17-16} = 0b10;
5503 }
5504 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5505 bits<2> idx;
5506 let Inst{20-19} = idx;
5507 let Inst{18-16} = 0b100;
5508 }
5509 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5510 bits<1> idx;
5511 let Inst{20} = idx;
5512 let Inst{19-16} = 0b1000;
5513 }
5514
5515 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5516 bits<4> idx;
5517 bits<4> idx2;
5518 let Inst{20-17} = idx;
5519 let Inst{16} = 1;
5520 let Inst{14-11} = idx2;
5521 }
5522 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5523 bits<3> idx;
5524 bits<3> idx2;
5525 let Inst{20-18} = idx;
5526 let Inst{17-16} = 0b10;
5527 let Inst{14-12} = idx2;
5528 let Inst{11} = 0;
5529 }
5530 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5531 bits<2> idx;
5532 bits<2> idx2;
5533 let Inst{20-19} = idx;
5534 let Inst{18-16} = 0b100;
5535 let Inst{14-13} = idx2;
5536 let Inst{12-11} = 0;
5537 }
5538 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5539 bits<1> idx;
5540 bits<1> idx2;
5541 let Inst{20} = idx;
5542 let Inst{19-16} = 0b1000;
5543 let Inst{14} = idx2;
5544 let Inst{13-11} = 0;
5545 }
5546
5547 // For all forms of the INS instruction, the "mov" mnemonic is the
5548 // preferred alias. Why they didn't just call the instruction "mov" in
5549 // the first place is a very good question indeed...
5550 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5551 GPR32, VectorIndexB>;
5552 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5553 GPR32, VectorIndexH>;
5554 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5555 GPR32, VectorIndexS>;
5556 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5557 GPR64, VectorIndexD>;
5558
5559 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5560 VectorIndexB>;
5561 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5562 VectorIndexH>;
5563 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5564 VectorIndexS>;
5565 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5566 VectorIndexD>;
5567}
5568
5569//----------------------------------------------------------------------------
5570// AdvSIMD TBL/TBX
5571//----------------------------------------------------------------------------
5572
5573let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5574class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5575 RegisterOperand listtype, string asm, string kind>
5576 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5577 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5578 Sched<[WriteV]> {
5579 bits<5> Vd;
5580 bits<5> Vn;
5581 bits<5> Vm;
5582 let Inst{31} = 0;
5583 let Inst{30} = Q;
5584 let Inst{29-21} = 0b001110000;
5585 let Inst{20-16} = Vm;
5586 let Inst{15} = 0;
5587 let Inst{14-13} = len;
5588 let Inst{12} = op;
5589 let Inst{11-10} = 0b00;
5590 let Inst{9-5} = Vn;
5591 let Inst{4-0} = Vd;
5592}
5593
5594let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5595class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5596 RegisterOperand listtype, string asm, string kind>
5597 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5598 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5599 Sched<[WriteV]> {
5600 bits<5> Vd;
5601 bits<5> Vn;
5602 bits<5> Vm;
5603 let Inst{31} = 0;
5604 let Inst{30} = Q;
5605 let Inst{29-21} = 0b001110000;
5606 let Inst{20-16} = Vm;
5607 let Inst{15} = 0;
5608 let Inst{14-13} = len;
5609 let Inst{12} = op;
5610 let Inst{11-10} = 0b00;
5611 let Inst{9-5} = Vn;
5612 let Inst{4-0} = Vd;
5613}
5614
5615class SIMDTableLookupAlias<string asm, Instruction inst,
5616 RegisterOperand vectype, RegisterOperand listtype>
5617 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5618 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5619
5620multiclass SIMDTableLookup<bit op, string asm> {
5621 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5622 asm, ".8b">;
5623 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5624 asm, ".8b">;
5625 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5626 asm, ".8b">;
5627 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5628 asm, ".8b">;
5629 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5630 asm, ".16b">;
5631 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5632 asm, ".16b">;
5633 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5634 asm, ".16b">;
5635 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5636 asm, ".16b">;
5637
5638 def : SIMDTableLookupAlias<asm # ".8b",
5639 !cast<Instruction>(NAME#"v8i8One"),
5640 V64, VecListOne128>;
5641 def : SIMDTableLookupAlias<asm # ".8b",
5642 !cast<Instruction>(NAME#"v8i8Two"),
5643 V64, VecListTwo128>;
5644 def : SIMDTableLookupAlias<asm # ".8b",
5645 !cast<Instruction>(NAME#"v8i8Three"),
5646 V64, VecListThree128>;
5647 def : SIMDTableLookupAlias<asm # ".8b",
5648 !cast<Instruction>(NAME#"v8i8Four"),
5649 V64, VecListFour128>;
5650 def : SIMDTableLookupAlias<asm # ".16b",
5651 !cast<Instruction>(NAME#"v16i8One"),
5652 V128, VecListOne128>;
5653 def : SIMDTableLookupAlias<asm # ".16b",
5654 !cast<Instruction>(NAME#"v16i8Two"),
5655 V128, VecListTwo128>;
5656 def : SIMDTableLookupAlias<asm # ".16b",
5657 !cast<Instruction>(NAME#"v16i8Three"),
5658 V128, VecListThree128>;
5659 def : SIMDTableLookupAlias<asm # ".16b",
5660 !cast<Instruction>(NAME#"v16i8Four"),
5661 V128, VecListFour128>;
5662}
5663
5664multiclass SIMDTableLookupTied<bit op, string asm> {
5665 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5666 asm, ".8b">;
5667 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5668 asm, ".8b">;
5669 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5670 asm, ".8b">;
5671 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5672 asm, ".8b">;
5673 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5674 asm, ".16b">;
5675 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5676 asm, ".16b">;
5677 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5678 asm, ".16b">;
5679 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5680 asm, ".16b">;
5681
5682 def : SIMDTableLookupAlias<asm # ".8b",
5683 !cast<Instruction>(NAME#"v8i8One"),
5684 V64, VecListOne128>;
5685 def : SIMDTableLookupAlias<asm # ".8b",
5686 !cast<Instruction>(NAME#"v8i8Two"),
5687 V64, VecListTwo128>;
5688 def : SIMDTableLookupAlias<asm # ".8b",
5689 !cast<Instruction>(NAME#"v8i8Three"),
5690 V64, VecListThree128>;
5691 def : SIMDTableLookupAlias<asm # ".8b",
5692 !cast<Instruction>(NAME#"v8i8Four"),
5693 V64, VecListFour128>;
5694 def : SIMDTableLookupAlias<asm # ".16b",
5695 !cast<Instruction>(NAME#"v16i8One"),
5696 V128, VecListOne128>;
5697 def : SIMDTableLookupAlias<asm # ".16b",
5698 !cast<Instruction>(NAME#"v16i8Two"),
5699 V128, VecListTwo128>;
5700 def : SIMDTableLookupAlias<asm # ".16b",
5701 !cast<Instruction>(NAME#"v16i8Three"),
5702 V128, VecListThree128>;
5703 def : SIMDTableLookupAlias<asm # ".16b",
5704 !cast<Instruction>(NAME#"v16i8Four"),
5705 V128, VecListFour128>;
5706}
5707
5708
5709//----------------------------------------------------------------------------
5710// AdvSIMD scalar CPY
5711//----------------------------------------------------------------------------
5712let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5713class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5714 string kind, Operand idxtype>
5715 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5716 "{\t$dst, $src" # kind # "$idx" #
5717 "|\t$dst, $src$idx}", "", []>,
5718 Sched<[WriteV]> {
5719 bits<5> dst;
5720 bits<5> src;
5721 let Inst{31-21} = 0b01011110000;
5722 let Inst{15-10} = 0b000001;
5723 let Inst{9-5} = src;
5724 let Inst{4-0} = dst;
5725}
5726
5727class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5728 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5729 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5730 # "|\t$dst, $src$index}",
5731 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5732
5733
5734multiclass SIMDScalarCPY<string asm> {
5735 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5736 bits<4> idx;
5737 let Inst{20-17} = idx;
5738 let Inst{16} = 1;
5739 }
5740 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5741 bits<3> idx;
5742 let Inst{20-18} = idx;
5743 let Inst{17-16} = 0b10;
5744 }
5745 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5746 bits<2> idx;
5747 let Inst{20-19} = idx;
5748 let Inst{18-16} = 0b100;
5749 }
5750 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5751 bits<1> idx;
5752 let Inst{20} = idx;
5753 let Inst{19-16} = 0b1000;
5754 }
5755
5756 // 'DUP' mnemonic aliases.
5757 def : SIMDScalarCPYAlias<"dup", ".b",
5758 !cast<Instruction>(NAME#"i8"),
5759 FPR8, V128, VectorIndexB>;
5760 def : SIMDScalarCPYAlias<"dup", ".h",
5761 !cast<Instruction>(NAME#"i16"),
5762 FPR16, V128, VectorIndexH>;
5763 def : SIMDScalarCPYAlias<"dup", ".s",
5764 !cast<Instruction>(NAME#"i32"),
5765 FPR32, V128, VectorIndexS>;
5766 def : SIMDScalarCPYAlias<"dup", ".d",
5767 !cast<Instruction>(NAME#"i64"),
5768 FPR64, V128, VectorIndexD>;
5769}
5770
5771//----------------------------------------------------------------------------
5772// AdvSIMD modified immediate instructions
5773//----------------------------------------------------------------------------
5774
5775class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5776 string asm, string op_string,
5777 string cstr, list<dag> pattern>
5778 : I<oops, iops, asm, op_string, cstr, pattern>,
5779 Sched<[WriteV]> {
5780 bits<5> Rd;
5781 bits<8> imm8;
5782 let Inst{31} = 0;
5783 let Inst{30} = Q;
5784 let Inst{29} = op;
5785 let Inst{28-19} = 0b0111100000;
5786 let Inst{18-16} = imm8{7-5};
5787 let Inst{11-10} = 0b01;
5788 let Inst{9-5} = imm8{4-0};
5789 let Inst{4-0} = Rd;
5790}
5791
5792class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5793 Operand immtype, dag opt_shift_iop,
5794 string opt_shift, string asm, string kind,
5795 list<dag> pattern>
5796 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5797 !con((ins immtype:$imm8), opt_shift_iop), asm,
5798 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5799 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5800 "", pattern> {
5801 let DecoderMethod = "DecodeModImmInstruction";
5802}
5803
5804class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5805 Operand immtype, dag opt_shift_iop,
5806 string opt_shift, string asm, string kind,
5807 list<dag> pattern>
5808 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5809 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5810 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5811 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5812 "$Rd = $dst", pattern> {
5813 let DecoderMethod = "DecodeModImmTiedInstruction";
5814}
5815
5816class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5817 RegisterOperand vectype, string asm,
5818 string kind, list<dag> pattern>
5819 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5820 (ins logical_vec_shift:$shift),
5821 "$shift", asm, kind, pattern> {
5822 bits<2> shift;
5823 let Inst{15} = b15_b12{1};
5824 let Inst{14-13} = shift;
5825 let Inst{12} = b15_b12{0};
5826}
5827
5828class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5829 RegisterOperand vectype, string asm,
5830 string kind, list<dag> pattern>
5831 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5832 (ins logical_vec_shift:$shift),
5833 "$shift", asm, kind, pattern> {
5834 bits<2> shift;
5835 let Inst{15} = b15_b12{1};
5836 let Inst{14-13} = shift;
5837 let Inst{12} = b15_b12{0};
5838}
5839
5840
5841class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5842 RegisterOperand vectype, string asm,
5843 string kind, list<dag> pattern>
5844 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5845 (ins logical_vec_hw_shift:$shift),
5846 "$shift", asm, kind, pattern> {
5847 bits<2> shift;
5848 let Inst{15} = b15_b12{1};
5849 let Inst{14} = 0;
5850 let Inst{13} = shift{0};
5851 let Inst{12} = b15_b12{0};
5852}
5853
5854class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5855 RegisterOperand vectype, string asm,
5856 string kind, list<dag> pattern>
5857 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5858 (ins logical_vec_hw_shift:$shift),
5859 "$shift", asm, kind, pattern> {
5860 bits<2> shift;
5861 let Inst{15} = b15_b12{1};
5862 let Inst{14} = 0;
5863 let Inst{13} = shift{0};
5864 let Inst{12} = b15_b12{0};
5865}
5866
5867multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5868 string asm> {
5869 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5870 asm, ".4h", []>;
5871 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5872 asm, ".8h", []>;
5873
5874 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5875 asm, ".2s", []>;
5876 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5877 asm, ".4s", []>;
5878}
5879
5880multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5881 bits<2> w_cmode, string asm,
5882 SDNode OpNode> {
5883 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5884 asm, ".4h",
5885 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5886 imm0_255:$imm8,
5887 (i32 imm:$shift)))]>;
5888 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5889 asm, ".8h",
5890 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5891 imm0_255:$imm8,
5892 (i32 imm:$shift)))]>;
5893
5894 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5895 asm, ".2s",
5896 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5897 imm0_255:$imm8,
5898 (i32 imm:$shift)))]>;
5899 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5900 asm, ".4s",
5901 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5902 imm0_255:$imm8,
5903 (i32 imm:$shift)))]>;
5904}
5905
5906class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5907 RegisterOperand vectype, string asm,
5908 string kind, list<dag> pattern>
5909 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5910 (ins move_vec_shift:$shift),
5911 "$shift", asm, kind, pattern> {
5912 bits<1> shift;
5913 let Inst{15-13} = cmode{3-1};
5914 let Inst{12} = shift;
5915}
5916
5917class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5918 RegisterOperand vectype,
5919 Operand imm_type, string asm,
5920 string kind, list<dag> pattern>
5921 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5922 asm, kind, pattern> {
5923 let Inst{15-12} = cmode;
5924}
5925
5926class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5927 list<dag> pattern>
5928 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5929 "\t$Rd, $imm8", "", pattern> {
5930 let Inst{15-12} = cmode;
5931 let DecoderMethod = "DecodeModImmInstruction";
5932}
5933
5934//----------------------------------------------------------------------------
5935// AdvSIMD indexed element
5936//----------------------------------------------------------------------------
5937
5938let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5939class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5940 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5941 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5942 string apple_kind, string dst_kind, string lhs_kind,
5943 string rhs_kind, list<dag> pattern>
5944 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5945 asm,
5946 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5947 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5948 Sched<[WriteV]> {
5949 bits<5> Rd;
5950 bits<5> Rn;
5951 bits<5> Rm;
5952
5953 let Inst{31} = 0;
5954 let Inst{30} = Q;
5955 let Inst{29} = U;
5956 let Inst{28} = Scalar;
5957 let Inst{27-24} = 0b1111;
5958 let Inst{23-22} = size;
5959 // Bit 21 must be set by the derived class.
5960 let Inst{20-16} = Rm;
5961 let Inst{15-12} = opc;
5962 // Bit 11 must be set by the derived class.
5963 let Inst{10} = 0;
5964 let Inst{9-5} = Rn;
5965 let Inst{4-0} = Rd;
5966}
5967
5968let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5969class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5970 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5971 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5972 string apple_kind, string dst_kind, string lhs_kind,
5973 string rhs_kind, list<dag> pattern>
5974 : I<(outs dst_reg:$dst),
5975 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5976 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5977 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5978 Sched<[WriteV]> {
5979 bits<5> Rd;
5980 bits<5> Rn;
5981 bits<5> Rm;
5982
5983 let Inst{31} = 0;
5984 let Inst{30} = Q;
5985 let Inst{29} = U;
5986 let Inst{28} = Scalar;
5987 let Inst{27-24} = 0b1111;
5988 let Inst{23-22} = size;
5989 // Bit 21 must be set by the derived class.
5990 let Inst{20-16} = Rm;
5991 let Inst{15-12} = opc;
5992 // Bit 11 must be set by the derived class.
5993 let Inst{10} = 0;
5994 let Inst{9-5} = Rn;
5995 let Inst{4-0} = Rd;
5996}
5997
5998multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
5999 SDPatternOperator OpNode> {
6000 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6001 V64, V64,
6002 V128, VectorIndexS,
6003 asm, ".2s", ".2s", ".2s", ".s",
6004 [(set (v2f32 V64:$Rd),
6005 (OpNode (v2f32 V64:$Rn),
6006 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6007 bits<2> idx;
6008 let Inst{11} = idx{1};
6009 let Inst{21} = idx{0};
6010 }
6011
6012 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6013 V128, V128,
6014 V128, VectorIndexS,
6015 asm, ".4s", ".4s", ".4s", ".s",
6016 [(set (v4f32 V128:$Rd),
6017 (OpNode (v4f32 V128:$Rn),
6018 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6019 bits<2> idx;
6020 let Inst{11} = idx{1};
6021 let Inst{21} = idx{0};
6022 }
6023
6024 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6025 V128, V128,
6026 V128, VectorIndexD,
6027 asm, ".2d", ".2d", ".2d", ".d",
6028 [(set (v2f64 V128:$Rd),
6029 (OpNode (v2f64 V128:$Rn),
6030 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6031 bits<1> idx;
6032 let Inst{11} = idx{0};
6033 let Inst{21} = 0;
6034 }
6035
6036 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6037 FPR32Op, FPR32Op, V128, VectorIndexS,
6038 asm, ".s", "", "", ".s",
6039 [(set (f32 FPR32Op:$Rd),
6040 (OpNode (f32 FPR32Op:$Rn),
6041 (f32 (vector_extract (v4f32 V128:$Rm),
6042 VectorIndexS:$idx))))]> {
6043 bits<2> idx;
6044 let Inst{11} = idx{1};
6045 let Inst{21} = idx{0};
6046 }
6047
6048 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6049 FPR64Op, FPR64Op, V128, VectorIndexD,
6050 asm, ".d", "", "", ".d",
6051 [(set (f64 FPR64Op:$Rd),
6052 (OpNode (f64 FPR64Op:$Rn),
6053 (f64 (vector_extract (v2f64 V128:$Rm),
6054 VectorIndexD:$idx))))]> {
6055 bits<1> idx;
6056 let Inst{11} = idx{0};
6057 let Inst{21} = 0;
6058 }
6059}
6060
6061multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6062 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6063 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6064 (ARM64duplane32 (v4f32 V128:$Rm),
6065 VectorIndexS:$idx))),
6066 (!cast<Instruction>(INST # v2i32_indexed)
6067 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6068 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6069 (ARM64dup (f32 FPR32Op:$Rm)))),
6070 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6071 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6072
6073
6074 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6075 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6076 (ARM64duplane32 (v4f32 V128:$Rm),
6077 VectorIndexS:$idx))),
6078 (!cast<Instruction>(INST # "v4i32_indexed")
6079 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6080 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6081 (ARM64dup (f32 FPR32Op:$Rm)))),
6082 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6083 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6084
6085 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6086 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6087 (ARM64duplane64 (v2f64 V128:$Rm),
6088 VectorIndexD:$idx))),
6089 (!cast<Instruction>(INST # "v2i64_indexed")
6090 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6091 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6092 (ARM64dup (f64 FPR64Op:$Rm)))),
6093 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6094 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6095
6096 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6097 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6098 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6099 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6100 V128:$Rm, VectorIndexS:$idx)>;
6101 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6102 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6103 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6104 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6105
6106 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6107 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6108 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6109 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6110 V128:$Rm, VectorIndexD:$idx)>;
6111}
6112
6113multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6114 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6115 V128, VectorIndexS,
6116 asm, ".2s", ".2s", ".2s", ".s", []> {
6117 bits<2> idx;
6118 let Inst{11} = idx{1};
6119 let Inst{21} = idx{0};
6120 }
6121
6122 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6123 V128, V128,
6124 V128, VectorIndexS,
6125 asm, ".4s", ".4s", ".4s", ".s", []> {
6126 bits<2> idx;
6127 let Inst{11} = idx{1};
6128 let Inst{21} = idx{0};
6129 }
6130
6131 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6132 V128, V128,
6133 V128, VectorIndexD,
6134 asm, ".2d", ".2d", ".2d", ".d", []> {
6135 bits<1> idx;
6136 let Inst{11} = idx{0};
6137 let Inst{21} = 0;
6138 }
6139
6140
6141 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6142 FPR32Op, FPR32Op, V128, VectorIndexS,
6143 asm, ".s", "", "", ".s", []> {
6144 bits<2> idx;
6145 let Inst{11} = idx{1};
6146 let Inst{21} = idx{0};
6147 }
6148
6149 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6150 FPR64Op, FPR64Op, V128, VectorIndexD,
6151 asm, ".d", "", "", ".d", []> {
6152 bits<1> idx;
6153 let Inst{11} = idx{0};
6154 let Inst{21} = 0;
6155 }
6156}
6157
6158multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6159 SDPatternOperator OpNode> {
6160 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6161 V128_lo, VectorIndexH,
6162 asm, ".4h", ".4h", ".4h", ".h",
6163 [(set (v4i16 V64:$Rd),
6164 (OpNode (v4i16 V64:$Rn),
6165 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6166 bits<3> idx;
6167 let Inst{11} = idx{2};
6168 let Inst{21} = idx{1};
6169 let Inst{20} = idx{0};
6170 }
6171
6172 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6173 V128, V128,
6174 V128_lo, VectorIndexH,
6175 asm, ".8h", ".8h", ".8h", ".h",
6176 [(set (v8i16 V128:$Rd),
6177 (OpNode (v8i16 V128:$Rn),
6178 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6179 bits<3> idx;
6180 let Inst{11} = idx{2};
6181 let Inst{21} = idx{1};
6182 let Inst{20} = idx{0};
6183 }
6184
6185 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6186 V64, V64,
6187 V128, VectorIndexS,
6188 asm, ".2s", ".2s", ".2s", ".s",
6189 [(set (v2i32 V64:$Rd),
6190 (OpNode (v2i32 V64:$Rn),
6191 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6192 bits<2> idx;
6193 let Inst{11} = idx{1};
6194 let Inst{21} = idx{0};
6195 }
6196
6197 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6198 V128, V128,
6199 V128, VectorIndexS,
6200 asm, ".4s", ".4s", ".4s", ".s",
6201 [(set (v4i32 V128:$Rd),
6202 (OpNode (v4i32 V128:$Rn),
6203 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6204 bits<2> idx;
6205 let Inst{11} = idx{1};
6206 let Inst{21} = idx{0};
6207 }
6208
6209 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6210 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6211 asm, ".h", "", "", ".h", []> {
6212 bits<3> idx;
6213 let Inst{11} = idx{2};
6214 let Inst{21} = idx{1};
6215 let Inst{20} = idx{0};
6216 }
6217
6218 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6219 FPR32Op, FPR32Op, V128, VectorIndexS,
6220 asm, ".s", "", "", ".s",
6221 [(set (i32 FPR32Op:$Rd),
6222 (OpNode FPR32Op:$Rn,
6223 (i32 (vector_extract (v4i32 V128:$Rm),
6224 VectorIndexS:$idx))))]> {
6225 bits<2> idx;
6226 let Inst{11} = idx{1};
6227 let Inst{21} = idx{0};
6228 }
6229}
6230
6231multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6232 SDPatternOperator OpNode> {
6233 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6234 V64, V64,
6235 V128_lo, VectorIndexH,
6236 asm, ".4h", ".4h", ".4h", ".h",
6237 [(set (v4i16 V64:$Rd),
6238 (OpNode (v4i16 V64:$Rn),
6239 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6240 bits<3> idx;
6241 let Inst{11} = idx{2};
6242 let Inst{21} = idx{1};
6243 let Inst{20} = idx{0};
6244 }
6245
6246 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6247 V128, V128,
6248 V128_lo, VectorIndexH,
6249 asm, ".8h", ".8h", ".8h", ".h",
6250 [(set (v8i16 V128:$Rd),
6251 (OpNode (v8i16 V128:$Rn),
6252 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6253 bits<3> idx;
6254 let Inst{11} = idx{2};
6255 let Inst{21} = idx{1};
6256 let Inst{20} = idx{0};
6257 }
6258
6259 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6260 V64, V64,
6261 V128, VectorIndexS,
6262 asm, ".2s", ".2s", ".2s", ".s",
6263 [(set (v2i32 V64:$Rd),
6264 (OpNode (v2i32 V64:$Rn),
6265 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6266 bits<2> idx;
6267 let Inst{11} = idx{1};
6268 let Inst{21} = idx{0};
6269 }
6270
6271 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6272 V128, V128,
6273 V128, VectorIndexS,
6274 asm, ".4s", ".4s", ".4s", ".s",
6275 [(set (v4i32 V128:$Rd),
6276 (OpNode (v4i32 V128:$Rn),
6277 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6278 bits<2> idx;
6279 let Inst{11} = idx{1};
6280 let Inst{21} = idx{0};
6281 }
6282}
6283
6284multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6285 SDPatternOperator OpNode> {
6286 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6287 V128_lo, VectorIndexH,
6288 asm, ".4h", ".4h", ".4h", ".h",
6289 [(set (v4i16 V64:$dst),
6290 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6291 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6292 bits<3> idx;
6293 let Inst{11} = idx{2};
6294 let Inst{21} = idx{1};
6295 let Inst{20} = idx{0};
6296 }
6297
6298 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6299 V128, V128,
6300 V128_lo, VectorIndexH,
6301 asm, ".8h", ".8h", ".8h", ".h",
6302 [(set (v8i16 V128:$dst),
6303 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6304 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6305 bits<3> idx;
6306 let Inst{11} = idx{2};
6307 let Inst{21} = idx{1};
6308 let Inst{20} = idx{0};
6309 }
6310
6311 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6312 V64, V64,
6313 V128, VectorIndexS,
6314 asm, ".2s", ".2s", ".2s", ".s",
6315 [(set (v2i32 V64:$dst),
6316 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6317 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6318 bits<2> idx;
6319 let Inst{11} = idx{1};
6320 let Inst{21} = idx{0};
6321 }
6322
6323 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6324 V128, V128,
6325 V128, VectorIndexS,
6326 asm, ".4s", ".4s", ".4s", ".s",
6327 [(set (v4i32 V128:$dst),
6328 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6329 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6330 bits<2> idx;
6331 let Inst{11} = idx{1};
6332 let Inst{21} = idx{0};
6333 }
6334}
6335
6336multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6337 SDPatternOperator OpNode> {
6338 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6339 V128, V64,
6340 V128_lo, VectorIndexH,
6341 asm, ".4s", ".4s", ".4h", ".h",
6342 [(set (v4i32 V128:$Rd),
6343 (OpNode (v4i16 V64:$Rn),
6344 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6345 bits<3> idx;
6346 let Inst{11} = idx{2};
6347 let Inst{21} = idx{1};
6348 let Inst{20} = idx{0};
6349 }
6350
6351 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6352 V128, V128,
6353 V128_lo, VectorIndexH,
6354 asm#"2", ".4s", ".4s", ".8h", ".h",
6355 [(set (v4i32 V128:$Rd),
6356 (OpNode (extract_high_v8i16 V128:$Rn),
6357 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6358 VectorIndexH:$idx))))]> {
6359
6360 bits<3> idx;
6361 let Inst{11} = idx{2};
6362 let Inst{21} = idx{1};
6363 let Inst{20} = idx{0};
6364 }
6365
6366 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6367 V128, V64,
6368 V128, VectorIndexS,
6369 asm, ".2d", ".2d", ".2s", ".s",
6370 [(set (v2i64 V128:$Rd),
6371 (OpNode (v2i32 V64:$Rn),
6372 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6373 bits<2> idx;
6374 let Inst{11} = idx{1};
6375 let Inst{21} = idx{0};
6376 }
6377
6378 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6379 V128, V128,
6380 V128, VectorIndexS,
6381 asm#"2", ".2d", ".2d", ".4s", ".s",
6382 [(set (v2i64 V128:$Rd),
6383 (OpNode (extract_high_v4i32 V128:$Rn),
6384 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6385 VectorIndexS:$idx))))]> {
6386 bits<2> idx;
6387 let Inst{11} = idx{1};
6388 let Inst{21} = idx{0};
6389 }
6390
6391 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6392 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6393 asm, ".h", "", "", ".h", []> {
6394 bits<3> idx;
6395 let Inst{11} = idx{2};
6396 let Inst{21} = idx{1};
6397 let Inst{20} = idx{0};
6398 }
6399
6400 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6401 FPR64Op, FPR32Op, V128, VectorIndexS,
6402 asm, ".s", "", "", ".s", []> {
6403 bits<2> idx;
6404 let Inst{11} = idx{1};
6405 let Inst{21} = idx{0};
6406 }
6407}
6408
6409multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6410 SDPatternOperator Accum> {
6411 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6412 V128, V64,
6413 V128_lo, VectorIndexH,
6414 asm, ".4s", ".4s", ".4h", ".h",
6415 [(set (v4i32 V128:$dst),
6416 (Accum (v4i32 V128:$Rd),
6417 (v4i32 (int_arm64_neon_sqdmull
6418 (v4i16 V64:$Rn),
6419 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6420 VectorIndexH:$idx))))))]> {
6421 bits<3> idx;
6422 let Inst{11} = idx{2};
6423 let Inst{21} = idx{1};
6424 let Inst{20} = idx{0};
6425 }
6426
6427 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6428 // intermediate EXTRACT_SUBREG would be untyped.
6429 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6430 (i32 (vector_extract (v4i32
6431 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6432 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6433 VectorIndexH:$idx)))),
6434 (i64 0))))),
6435 (EXTRACT_SUBREG
6436 (!cast<Instruction>(NAME # v4i16_indexed)
6437 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6438 V128_lo:$Rm, VectorIndexH:$idx),
6439 ssub)>;
6440
6441 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6442 V128, V128,
6443 V128_lo, VectorIndexH,
6444 asm#"2", ".4s", ".4s", ".8h", ".h",
6445 [(set (v4i32 V128:$dst),
6446 (Accum (v4i32 V128:$Rd),
6447 (v4i32 (int_arm64_neon_sqdmull
6448 (extract_high_v8i16 V128:$Rn),
6449 (extract_high_v8i16
6450 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6451 VectorIndexH:$idx))))))]> {
6452 bits<3> idx;
6453 let Inst{11} = idx{2};
6454 let Inst{21} = idx{1};
6455 let Inst{20} = idx{0};
6456 }
6457
6458 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6459 V128, V64,
6460 V128, VectorIndexS,
6461 asm, ".2d", ".2d", ".2s", ".s",
6462 [(set (v2i64 V128:$dst),
6463 (Accum (v2i64 V128:$Rd),
6464 (v2i64 (int_arm64_neon_sqdmull
6465 (v2i32 V64:$Rn),
6466 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6467 VectorIndexS:$idx))))))]> {
6468 bits<2> idx;
6469 let Inst{11} = idx{1};
6470 let Inst{21} = idx{0};
6471 }
6472
6473 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6474 V128, V128,
6475 V128, VectorIndexS,
6476 asm#"2", ".2d", ".2d", ".4s", ".s",
6477 [(set (v2i64 V128:$dst),
6478 (Accum (v2i64 V128:$Rd),
6479 (v2i64 (int_arm64_neon_sqdmull
6480 (extract_high_v4i32 V128:$Rn),
6481 (extract_high_v4i32
6482 (ARM64duplane32 (v4i32 V128:$Rm),
6483 VectorIndexS:$idx))))))]> {
6484 bits<2> idx;
6485 let Inst{11} = idx{1};
6486 let Inst{21} = idx{0};
6487 }
6488
6489 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6490 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6491 asm, ".h", "", "", ".h", []> {
6492 bits<3> idx;
6493 let Inst{11} = idx{2};
6494 let Inst{21} = idx{1};
6495 let Inst{20} = idx{0};
6496 }
6497
6498
6499 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6500 FPR64Op, FPR32Op, V128, VectorIndexS,
6501 asm, ".s", "", "", ".s",
6502 [(set (i64 FPR64Op:$dst),
6503 (Accum (i64 FPR64Op:$Rd),
6504 (i64 (int_arm64_neon_sqdmulls_scalar
6505 (i32 FPR32Op:$Rn),
6506 (i32 (vector_extract (v4i32 V128:$Rm),
6507 VectorIndexS:$idx))))))]> {
6508
6509 bits<2> idx;
6510 let Inst{11} = idx{1};
6511 let Inst{21} = idx{0};
6512 }
6513}
6514
6515multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6516 SDPatternOperator OpNode> {
6517 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6518 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6519 V128, V64,
6520 V128_lo, VectorIndexH,
6521 asm, ".4s", ".4s", ".4h", ".h",
6522 [(set (v4i32 V128:$Rd),
6523 (OpNode (v4i16 V64:$Rn),
6524 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6525 bits<3> idx;
6526 let Inst{11} = idx{2};
6527 let Inst{21} = idx{1};
6528 let Inst{20} = idx{0};
6529 }
6530
6531 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6532 V128, V128,
6533 V128_lo, VectorIndexH,
6534 asm#"2", ".4s", ".4s", ".8h", ".h",
6535 [(set (v4i32 V128:$Rd),
6536 (OpNode (extract_high_v8i16 V128:$Rn),
6537 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6538 VectorIndexH:$idx))))]> {
6539
6540 bits<3> idx;
6541 let Inst{11} = idx{2};
6542 let Inst{21} = idx{1};
6543 let Inst{20} = idx{0};
6544 }
6545
6546 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6547 V128, V64,
6548 V128, VectorIndexS,
6549 asm, ".2d", ".2d", ".2s", ".s",
6550 [(set (v2i64 V128:$Rd),
6551 (OpNode (v2i32 V64:$Rn),
6552 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6553 bits<2> idx;
6554 let Inst{11} = idx{1};
6555 let Inst{21} = idx{0};
6556 }
6557
6558 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6559 V128, V128,
6560 V128, VectorIndexS,
6561 asm#"2", ".2d", ".2d", ".4s", ".s",
6562 [(set (v2i64 V128:$Rd),
6563 (OpNode (extract_high_v4i32 V128:$Rn),
6564 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6565 VectorIndexS:$idx))))]> {
6566 bits<2> idx;
6567 let Inst{11} = idx{1};
6568 let Inst{21} = idx{0};
6569 }
6570 }
6571}
6572
6573multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6574 SDPatternOperator OpNode> {
6575 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6576 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6577 V128, V64,
6578 V128_lo, VectorIndexH,
6579 asm, ".4s", ".4s", ".4h", ".h",
6580 [(set (v4i32 V128:$dst),
6581 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6582 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6583 bits<3> idx;
6584 let Inst{11} = idx{2};
6585 let Inst{21} = idx{1};
6586 let Inst{20} = idx{0};
6587 }
6588
6589 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6590 V128, V128,
6591 V128_lo, VectorIndexH,
6592 asm#"2", ".4s", ".4s", ".8h", ".h",
6593 [(set (v4i32 V128:$dst),
6594 (OpNode (v4i32 V128:$Rd),
6595 (extract_high_v8i16 V128:$Rn),
6596 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6597 VectorIndexH:$idx))))]> {
6598 bits<3> idx;
6599 let Inst{11} = idx{2};
6600 let Inst{21} = idx{1};
6601 let Inst{20} = idx{0};
6602 }
6603
6604 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6605 V128, V64,
6606 V128, VectorIndexS,
6607 asm, ".2d", ".2d", ".2s", ".s",
6608 [(set (v2i64 V128:$dst),
6609 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6610 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6611 bits<2> idx;
6612 let Inst{11} = idx{1};
6613 let Inst{21} = idx{0};
6614 }
6615
6616 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6617 V128, V128,
6618 V128, VectorIndexS,
6619 asm#"2", ".2d", ".2d", ".4s", ".s",
6620 [(set (v2i64 V128:$dst),
6621 (OpNode (v2i64 V128:$Rd),
6622 (extract_high_v4i32 V128:$Rn),
6623 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6624 VectorIndexS:$idx))))]> {
6625 bits<2> idx;
6626 let Inst{11} = idx{1};
6627 let Inst{21} = idx{0};
6628 }
6629 }
6630}
6631
6632//----------------------------------------------------------------------------
6633// AdvSIMD scalar shift by immediate
6634//----------------------------------------------------------------------------
6635
6636let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6637class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6638 RegisterClass regtype1, RegisterClass regtype2,
6639 Operand immtype, string asm, list<dag> pattern>
6640 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6641 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6642 Sched<[WriteV]> {
6643 bits<5> Rd;
6644 bits<5> Rn;
6645 bits<7> imm;
6646 let Inst{31-30} = 0b01;
6647 let Inst{29} = U;
6648 let Inst{28-23} = 0b111110;
6649 let Inst{22-16} = fixed_imm;
6650 let Inst{15-11} = opc;
6651 let Inst{10} = 1;
6652 let Inst{9-5} = Rn;
6653 let Inst{4-0} = Rd;
6654}
6655
6656let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6657class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6658 RegisterClass regtype1, RegisterClass regtype2,
6659 Operand immtype, string asm, list<dag> pattern>
6660 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6661 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6662 Sched<[WriteV]> {
6663 bits<5> Rd;
6664 bits<5> Rn;
6665 bits<7> imm;
6666 let Inst{31-30} = 0b01;
6667 let Inst{29} = U;
6668 let Inst{28-23} = 0b111110;
6669 let Inst{22-16} = fixed_imm;
6670 let Inst{15-11} = opc;
6671 let Inst{10} = 1;
6672 let Inst{9-5} = Rn;
6673 let Inst{4-0} = Rd;
6674}
6675
6676
6677multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6678 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6679 FPR32, FPR32, vecshiftR32, asm, []> {
6680 let Inst{20-16} = imm{4-0};
6681 }
6682
6683 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6684 FPR64, FPR64, vecshiftR64, asm, []> {
6685 let Inst{21-16} = imm{5-0};
6686 }
6687}
6688
6689multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6690 SDPatternOperator OpNode> {
6691 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6692 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006693 [(set (i64 FPR64:$Rd),
6694 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006695 let Inst{21-16} = imm{5-0};
6696 }
Tim Northover5081cd02014-03-31 15:46:46 +00006697
6698 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6699 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006700}
6701
Tim Northover00ed9962014-03-29 10:18:08 +00006702multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6703 SDPatternOperator OpNode = null_frag> {
6704 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6705 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006706 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6707 (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006708 let Inst{21-16} = imm{5-0};
6709 }
Tim Northover5081cd02014-03-31 15:46:46 +00006710
6711 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6712 (i32 vecshiftR64:$imm))),
6713 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6714 vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006715}
6716
6717multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6718 SDPatternOperator OpNode> {
6719 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6720 FPR64, FPR64, vecshiftL64, asm,
6721 [(set (v1i64 FPR64:$Rd),
6722 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6723 let Inst{21-16} = imm{5-0};
6724 }
6725}
6726
6727let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6728multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6729 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6730 FPR64, FPR64, vecshiftL64, asm, []> {
6731 let Inst{21-16} = imm{5-0};
6732 }
6733}
6734
6735let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6736multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6737 SDPatternOperator OpNode = null_frag> {
6738 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6739 FPR8, FPR16, vecshiftR8, asm, []> {
6740 let Inst{18-16} = imm{2-0};
6741 }
6742
6743 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6744 FPR16, FPR32, vecshiftR16, asm, []> {
6745 let Inst{19-16} = imm{3-0};
6746 }
6747
6748 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6749 FPR32, FPR64, vecshiftR32, asm,
6750 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6751 let Inst{20-16} = imm{4-0};
6752 }
6753}
6754
6755multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6756 SDPatternOperator OpNode> {
6757 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6758 FPR8, FPR8, vecshiftL8, asm, []> {
6759 let Inst{18-16} = imm{2-0};
6760 }
6761
6762 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6763 FPR16, FPR16, vecshiftL16, asm, []> {
6764 let Inst{19-16} = imm{3-0};
6765 }
6766
6767 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6768 FPR32, FPR32, vecshiftL32, asm,
6769 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6770 let Inst{20-16} = imm{4-0};
6771 }
6772
6773 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6774 FPR64, FPR64, vecshiftL64, asm,
6775 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6776 (i32 vecshiftL64:$imm)))]> {
6777 let Inst{21-16} = imm{5-0};
6778 }
6779}
6780
6781multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6782 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6783 FPR8, FPR8, vecshiftR8, asm, []> {
6784 let Inst{18-16} = imm{2-0};
6785 }
6786
6787 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6788 FPR16, FPR16, vecshiftR16, asm, []> {
6789 let Inst{19-16} = imm{3-0};
6790 }
6791
6792 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6793 FPR32, FPR32, vecshiftR32, asm, []> {
6794 let Inst{20-16} = imm{4-0};
6795 }
6796
6797 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6798 FPR64, FPR64, vecshiftR64, asm, []> {
6799 let Inst{21-16} = imm{5-0};
6800 }
6801}
6802
6803//----------------------------------------------------------------------------
6804// AdvSIMD vector x indexed element
6805//----------------------------------------------------------------------------
6806
6807let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6808class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6809 RegisterOperand dst_reg, RegisterOperand src_reg,
6810 Operand immtype,
6811 string asm, string dst_kind, string src_kind,
6812 list<dag> pattern>
6813 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6814 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6815 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6816 Sched<[WriteV]> {
6817 bits<5> Rd;
6818 bits<5> Rn;
6819 let Inst{31} = 0;
6820 let Inst{30} = Q;
6821 let Inst{29} = U;
6822 let Inst{28-23} = 0b011110;
6823 let Inst{22-16} = fixed_imm;
6824 let Inst{15-11} = opc;
6825 let Inst{10} = 1;
6826 let Inst{9-5} = Rn;
6827 let Inst{4-0} = Rd;
6828}
6829
6830let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6831class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6832 RegisterOperand vectype1, RegisterOperand vectype2,
6833 Operand immtype,
6834 string asm, string dst_kind, string src_kind,
6835 list<dag> pattern>
6836 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6837 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6838 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6839 Sched<[WriteV]> {
6840 bits<5> Rd;
6841 bits<5> Rn;
6842 let Inst{31} = 0;
6843 let Inst{30} = Q;
6844 let Inst{29} = U;
6845 let Inst{28-23} = 0b011110;
6846 let Inst{22-16} = fixed_imm;
6847 let Inst{15-11} = opc;
6848 let Inst{10} = 1;
6849 let Inst{9-5} = Rn;
6850 let Inst{4-0} = Rd;
6851}
6852
6853multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6854 Intrinsic OpNode> {
6855 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6856 V64, V64, vecshiftR32,
6857 asm, ".2s", ".2s",
6858 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6859 bits<5> imm;
6860 let Inst{20-16} = imm;
6861 }
6862
6863 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6864 V128, V128, vecshiftR32,
6865 asm, ".4s", ".4s",
6866 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6867 bits<5> imm;
6868 let Inst{20-16} = imm;
6869 }
6870
6871 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6872 V128, V128, vecshiftR64,
6873 asm, ".2d", ".2d",
6874 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6875 bits<6> imm;
6876 let Inst{21-16} = imm;
6877 }
6878}
6879
6880multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6881 Intrinsic OpNode> {
6882 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6883 V64, V64, vecshiftR32,
6884 asm, ".2s", ".2s",
6885 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6886 bits<5> imm;
6887 let Inst{20-16} = imm;
6888 }
6889
6890 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6891 V128, V128, vecshiftR32,
6892 asm, ".4s", ".4s",
6893 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6894 bits<5> imm;
6895 let Inst{20-16} = imm;
6896 }
6897
6898 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6899 V128, V128, vecshiftR64,
6900 asm, ".2d", ".2d",
6901 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6902 bits<6> imm;
6903 let Inst{21-16} = imm;
6904 }
6905}
6906
6907multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6908 SDPatternOperator OpNode> {
6909 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6910 V64, V128, vecshiftR16Narrow,
6911 asm, ".8b", ".8h",
6912 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6913 bits<3> imm;
6914 let Inst{18-16} = imm;
6915 }
6916
6917 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6918 V128, V128, vecshiftR16Narrow,
6919 asm#"2", ".16b", ".8h", []> {
6920 bits<3> imm;
6921 let Inst{18-16} = imm;
6922 let hasSideEffects = 0;
6923 }
6924
6925 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6926 V64, V128, vecshiftR32Narrow,
6927 asm, ".4h", ".4s",
6928 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6929 bits<4> imm;
6930 let Inst{19-16} = imm;
6931 }
6932
6933 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6934 V128, V128, vecshiftR32Narrow,
6935 asm#"2", ".8h", ".4s", []> {
6936 bits<4> imm;
6937 let Inst{19-16} = imm;
6938 let hasSideEffects = 0;
6939 }
6940
6941 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6942 V64, V128, vecshiftR64Narrow,
6943 asm, ".2s", ".2d",
6944 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6945 bits<5> imm;
6946 let Inst{20-16} = imm;
6947 }
6948
6949 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6950 V128, V128, vecshiftR64Narrow,
6951 asm#"2", ".4s", ".2d", []> {
6952 bits<5> imm;
6953 let Inst{20-16} = imm;
6954 let hasSideEffects = 0;
6955 }
6956
6957 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6958 // themselves, so put them here instead.
6959
6960 // Patterns involving what's effectively an insert high and a normal
6961 // intrinsic, represented by CONCAT_VECTORS.
6962 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6963 vecshiftR16Narrow:$imm)),
6964 (!cast<Instruction>(NAME # "v16i8_shift")
6965 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6966 V128:$Rn, vecshiftR16Narrow:$imm)>;
6967 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6968 vecshiftR32Narrow:$imm)),
6969 (!cast<Instruction>(NAME # "v8i16_shift")
6970 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6971 V128:$Rn, vecshiftR32Narrow:$imm)>;
6972 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6973 vecshiftR64Narrow:$imm)),
6974 (!cast<Instruction>(NAME # "v4i32_shift")
6975 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6976 V128:$Rn, vecshiftR64Narrow:$imm)>;
6977}
6978
6979multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
6980 SDPatternOperator OpNode> {
6981 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6982 V64, V64, vecshiftL8,
6983 asm, ".8b", ".8b",
6984 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6985 (i32 vecshiftL8:$imm)))]> {
6986 bits<3> imm;
6987 let Inst{18-16} = imm;
6988 }
6989
6990 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
6991 V128, V128, vecshiftL8,
6992 asm, ".16b", ".16b",
6993 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
6994 (i32 vecshiftL8:$imm)))]> {
6995 bits<3> imm;
6996 let Inst{18-16} = imm;
6997 }
6998
6999 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7000 V64, V64, vecshiftL16,
7001 asm, ".4h", ".4h",
7002 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7003 (i32 vecshiftL16:$imm)))]> {
7004 bits<4> imm;
7005 let Inst{19-16} = imm;
7006 }
7007
7008 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7009 V128, V128, vecshiftL16,
7010 asm, ".8h", ".8h",
7011 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7012 (i32 vecshiftL16:$imm)))]> {
7013 bits<4> imm;
7014 let Inst{19-16} = imm;
7015 }
7016
7017 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7018 V64, V64, vecshiftL32,
7019 asm, ".2s", ".2s",
7020 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7021 (i32 vecshiftL32:$imm)))]> {
7022 bits<5> imm;
7023 let Inst{20-16} = imm;
7024 }
7025
7026 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7027 V128, V128, vecshiftL32,
7028 asm, ".4s", ".4s",
7029 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7030 (i32 vecshiftL32:$imm)))]> {
7031 bits<5> imm;
7032 let Inst{20-16} = imm;
7033 }
7034
7035 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7036 V128, V128, vecshiftL64,
7037 asm, ".2d", ".2d",
7038 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7039 (i32 vecshiftL64:$imm)))]> {
7040 bits<6> imm;
7041 let Inst{21-16} = imm;
7042 }
7043}
7044
7045multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7046 SDPatternOperator OpNode> {
7047 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7048 V64, V64, vecshiftR8,
7049 asm, ".8b", ".8b",
7050 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7051 (i32 vecshiftR8:$imm)))]> {
7052 bits<3> imm;
7053 let Inst{18-16} = imm;
7054 }
7055
7056 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7057 V128, V128, vecshiftR8,
7058 asm, ".16b", ".16b",
7059 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7060 (i32 vecshiftR8:$imm)))]> {
7061 bits<3> imm;
7062 let Inst{18-16} = imm;
7063 }
7064
7065 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7066 V64, V64, vecshiftR16,
7067 asm, ".4h", ".4h",
7068 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7069 (i32 vecshiftR16:$imm)))]> {
7070 bits<4> imm;
7071 let Inst{19-16} = imm;
7072 }
7073
7074 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7075 V128, V128, vecshiftR16,
7076 asm, ".8h", ".8h",
7077 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7078 (i32 vecshiftR16:$imm)))]> {
7079 bits<4> imm;
7080 let Inst{19-16} = imm;
7081 }
7082
7083 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7084 V64, V64, vecshiftR32,
7085 asm, ".2s", ".2s",
7086 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7087 (i32 vecshiftR32:$imm)))]> {
7088 bits<5> imm;
7089 let Inst{20-16} = imm;
7090 }
7091
7092 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7093 V128, V128, vecshiftR32,
7094 asm, ".4s", ".4s",
7095 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7096 (i32 vecshiftR32:$imm)))]> {
7097 bits<5> imm;
7098 let Inst{20-16} = imm;
7099 }
7100
7101 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7102 V128, V128, vecshiftR64,
7103 asm, ".2d", ".2d",
7104 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7105 (i32 vecshiftR64:$imm)))]> {
7106 bits<6> imm;
7107 let Inst{21-16} = imm;
7108 }
7109}
7110
7111let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7112multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7113 SDPatternOperator OpNode = null_frag> {
7114 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7115 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7116 [(set (v8i8 V64:$dst),
7117 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7118 (i32 vecshiftR8:$imm)))]> {
7119 bits<3> imm;
7120 let Inst{18-16} = imm;
7121 }
7122
7123 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7124 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7125 [(set (v16i8 V128:$dst),
7126 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7127 (i32 vecshiftR8:$imm)))]> {
7128 bits<3> imm;
7129 let Inst{18-16} = imm;
7130 }
7131
7132 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7133 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7134 [(set (v4i16 V64:$dst),
7135 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7136 (i32 vecshiftR16:$imm)))]> {
7137 bits<4> imm;
7138 let Inst{19-16} = imm;
7139 }
7140
7141 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7142 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7143 [(set (v8i16 V128:$dst),
7144 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7145 (i32 vecshiftR16:$imm)))]> {
7146 bits<4> imm;
7147 let Inst{19-16} = imm;
7148 }
7149
7150 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7151 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7152 [(set (v2i32 V64:$dst),
7153 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7154 (i32 vecshiftR32:$imm)))]> {
7155 bits<5> imm;
7156 let Inst{20-16} = imm;
7157 }
7158
7159 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7160 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7161 [(set (v4i32 V128:$dst),
7162 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7163 (i32 vecshiftR32:$imm)))]> {
7164 bits<5> imm;
7165 let Inst{20-16} = imm;
7166 }
7167
7168 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7169 V128, V128, vecshiftR64,
7170 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7171 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7172 (i32 vecshiftR64:$imm)))]> {
7173 bits<6> imm;
7174 let Inst{21-16} = imm;
7175 }
7176}
7177
7178multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7179 SDPatternOperator OpNode = null_frag> {
7180 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7181 V64, V64, vecshiftL8,
7182 asm, ".8b", ".8b",
7183 [(set (v8i8 V64:$dst),
7184 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7185 (i32 vecshiftL8:$imm)))]> {
7186 bits<3> imm;
7187 let Inst{18-16} = imm;
7188 }
7189
7190 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7191 V128, V128, vecshiftL8,
7192 asm, ".16b", ".16b",
7193 [(set (v16i8 V128:$dst),
7194 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7195 (i32 vecshiftL8:$imm)))]> {
7196 bits<3> imm;
7197 let Inst{18-16} = imm;
7198 }
7199
7200 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7201 V64, V64, vecshiftL16,
7202 asm, ".4h", ".4h",
7203 [(set (v4i16 V64:$dst),
7204 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7205 (i32 vecshiftL16:$imm)))]> {
7206 bits<4> imm;
7207 let Inst{19-16} = imm;
7208 }
7209
7210 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7211 V128, V128, vecshiftL16,
7212 asm, ".8h", ".8h",
7213 [(set (v8i16 V128:$dst),
7214 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7215 (i32 vecshiftL16:$imm)))]> {
7216 bits<4> imm;
7217 let Inst{19-16} = imm;
7218 }
7219
7220 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7221 V64, V64, vecshiftL32,
7222 asm, ".2s", ".2s",
7223 [(set (v2i32 V64:$dst),
7224 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7225 (i32 vecshiftL32:$imm)))]> {
7226 bits<5> imm;
7227 let Inst{20-16} = imm;
7228 }
7229
7230 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7231 V128, V128, vecshiftL32,
7232 asm, ".4s", ".4s",
7233 [(set (v4i32 V128:$dst),
7234 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7235 (i32 vecshiftL32:$imm)))]> {
7236 bits<5> imm;
7237 let Inst{20-16} = imm;
7238 }
7239
7240 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7241 V128, V128, vecshiftL64,
7242 asm, ".2d", ".2d",
7243 [(set (v2i64 V128:$dst),
7244 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7245 (i32 vecshiftL64:$imm)))]> {
7246 bits<6> imm;
7247 let Inst{21-16} = imm;
7248 }
7249}
7250
7251multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7252 SDPatternOperator OpNode> {
7253 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7254 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7255 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7256 bits<3> imm;
7257 let Inst{18-16} = imm;
7258 }
7259
7260 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7261 V128, V128, vecshiftL8,
7262 asm#"2", ".8h", ".16b",
7263 [(set (v8i16 V128:$Rd),
7264 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7265 bits<3> imm;
7266 let Inst{18-16} = imm;
7267 }
7268
7269 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7270 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7271 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7272 bits<4> imm;
7273 let Inst{19-16} = imm;
7274 }
7275
7276 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7277 V128, V128, vecshiftL16,
7278 asm#"2", ".4s", ".8h",
7279 [(set (v4i32 V128:$Rd),
7280 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7281
7282 bits<4> imm;
7283 let Inst{19-16} = imm;
7284 }
7285
7286 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7287 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7288 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7289 bits<5> imm;
7290 let Inst{20-16} = imm;
7291 }
7292
7293 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7294 V128, V128, vecshiftL32,
7295 asm#"2", ".2d", ".4s",
7296 [(set (v2i64 V128:$Rd),
7297 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7298 bits<5> imm;
7299 let Inst{20-16} = imm;
7300 }
7301}
7302
7303
7304//---
7305// Vector load/store
7306//---
7307// SIMD ldX/stX no-index memory references don't allow the optional
7308// ", #0" constant and handle post-indexing explicitly, so we use
7309// a more specialized parse method for them. Otherwise, it's the same as
7310// the general am_noindex handling.
7311def MemorySIMDNoIndexOperand : AsmOperandClass {
7312 let Name = "MemorySIMDNoIndex";
7313 let ParserMethod = "tryParseNoIndexMemory";
7314}
7315def am_simdnoindex : Operand<i64>,
7316 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7317 let PrintMethod = "printAMNoIndex";
7318 let ParserMatchClass = MemorySIMDNoIndexOperand;
7319 let MIOperandInfo = (ops GPR64sp:$base);
7320 let DecoderMethod = "DecodeGPR64spRegisterClass";
7321}
7322
7323class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7324 string asm, dag oops, dag iops, list<dag> pattern>
7325 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7326 bits<5> Vt;
7327 bits<5> vaddr;
7328 let Inst{31} = 0;
7329 let Inst{30} = Q;
7330 let Inst{29-23} = 0b0011000;
7331 let Inst{22} = L;
7332 let Inst{21-16} = 0b000000;
7333 let Inst{15-12} = opcode;
7334 let Inst{11-10} = size;
7335 let Inst{9-5} = vaddr;
7336 let Inst{4-0} = Vt;
7337}
7338
7339class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7340 string asm, dag oops, dag iops>
7341 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7342 bits<5> Vt;
7343 bits<5> vaddr;
7344 bits<5> Xm;
7345 let Inst{31} = 0;
7346 let Inst{30} = Q;
7347 let Inst{29-23} = 0b0011001;
7348 let Inst{22} = L;
7349 let Inst{21} = 0;
7350 let Inst{20-16} = Xm;
7351 let Inst{15-12} = opcode;
7352 let Inst{11-10} = size;
7353 let Inst{9-5} = vaddr;
7354 let Inst{4-0} = Vt;
7355 let DecoderMethod = "DecodeSIMDLdStPost";
7356}
7357
7358// The immediate form of AdvSIMD post-indexed addressing is encoded with
7359// register post-index addressing from the zero register.
7360multiclass SIMDLdStAliases<string asm, string layout, string Count,
7361 int Offset, int Size> {
7362 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7363 // "ld1\t$Vt, $vaddr, #16"
7364 // may get mapped to
7365 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7366 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7367 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7368 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7369 am_simdnoindex:$vaddr, XZR), 1>;
7370
7371 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7372 // "ld1.8b\t$Vt, $vaddr, #16"
7373 // may get mapped to
7374 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7375 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7376 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7377 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7378 am_simdnoindex:$vaddr, XZR), 0>;
7379
7380 // E.g. "ld1.8b { v0, v1 }, [x1]"
7381 // "ld1\t$Vt, $vaddr"
7382 // may get mapped to
7383 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7384 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7385 (!cast<Instruction>(NAME # Count # "v" # layout)
7386 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7387 am_simdnoindex:$vaddr), 0>;
7388
7389 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7390 // "ld1\t$Vt, $vaddr, $Xm"
7391 // may get mapped to
7392 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7393 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7394 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7395 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7396 am_simdnoindex:$vaddr,
7397 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7398}
7399
7400multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7401 int Offset64, bits<4> opcode> {
7402 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7403 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7404 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7405 (ins am_simdnoindex:$vaddr), []>;
7406 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7407 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7408 (ins am_simdnoindex:$vaddr), []>;
7409 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7410 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7411 (ins am_simdnoindex:$vaddr), []>;
7412 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7413 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7414 (ins am_simdnoindex:$vaddr), []>;
7415 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7416 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7417 (ins am_simdnoindex:$vaddr), []>;
7418 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7419 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7420 (ins am_simdnoindex:$vaddr), []>;
7421 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7422 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7423 (ins am_simdnoindex:$vaddr), []>;
7424
7425
7426 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7427 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7428 (ins am_simdnoindex:$vaddr,
7429 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7430 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7431 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7432 (ins am_simdnoindex:$vaddr,
7433 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7434 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7435 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7436 (ins am_simdnoindex:$vaddr,
7437 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7438 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7439 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7440 (ins am_simdnoindex:$vaddr,
7441 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7442 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7443 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7444 (ins am_simdnoindex:$vaddr,
7445 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7446 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7447 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7448 (ins am_simdnoindex:$vaddr,
7449 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7450 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7451 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7452 (ins am_simdnoindex:$vaddr,
7453 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7454 }
7455
7456 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7457 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7458 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7459 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7460 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7461 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7462 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7463}
7464
7465// Only ld1/st1 has a v1d version.
7466multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7467 int Offset64, bits<4> opcode> {
7468 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7469 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7470 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7471 am_simdnoindex:$vaddr), []>;
7472 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7473 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7474 am_simdnoindex:$vaddr), []>;
7475 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7476 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7477 am_simdnoindex:$vaddr), []>;
7478 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7479 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7480 am_simdnoindex:$vaddr), []>;
7481 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7482 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7483 am_simdnoindex:$vaddr), []>;
7484 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7485 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7486 am_simdnoindex:$vaddr), []>;
7487 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7488 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7489 am_simdnoindex:$vaddr), []>;
7490
7491 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7492 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7493 am_simdnoindex:$vaddr,
7494 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7495 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7496 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7497 am_simdnoindex:$vaddr,
7498 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7499 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7500 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7501 am_simdnoindex:$vaddr,
7502 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7503 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7504 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7505 am_simdnoindex:$vaddr,
7506 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7507 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7508 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7509 am_simdnoindex:$vaddr,
7510 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7511 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7512 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7513 am_simdnoindex:$vaddr,
7514 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7515 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7516 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7517 am_simdnoindex:$vaddr,
7518 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7519 }
7520
7521 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7522 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7523 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7524 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7525 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7526 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7527 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7528}
7529
7530multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7531 int Offset128, int Offset64, bits<4> opcode>
7532 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7533
7534 // LD1 instructions have extra "1d" variants.
7535 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7536 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7537 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7538 (ins am_simdnoindex:$vaddr), []>;
7539
7540 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7541 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7542 (ins am_simdnoindex:$vaddr,
7543 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7544 }
7545
7546 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7547}
7548
7549multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7550 int Offset128, int Offset64, bits<4> opcode>
7551 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7552
7553 // ST1 instructions have extra "1d" variants.
7554 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7555 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7556 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7557 am_simdnoindex:$vaddr), []>;
7558
7559 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7560 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7561 am_simdnoindex:$vaddr,
7562 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7563 }
7564
7565 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7566}
7567
7568multiclass SIMDLd1Multiple<string asm> {
7569 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7570 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7571 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7572 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7573}
7574
7575multiclass SIMDSt1Multiple<string asm> {
7576 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7577 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7578 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7579 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7580}
7581
7582multiclass SIMDLd2Multiple<string asm> {
7583 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7584}
7585
7586multiclass SIMDSt2Multiple<string asm> {
7587 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7588}
7589
7590multiclass SIMDLd3Multiple<string asm> {
7591 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7592}
7593
7594multiclass SIMDSt3Multiple<string asm> {
7595 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7596}
7597
7598multiclass SIMDLd4Multiple<string asm> {
7599 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7600}
7601
7602multiclass SIMDSt4Multiple<string asm> {
7603 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7604}
7605
7606//---
7607// AdvSIMD Load/store single-element
7608//---
7609
7610class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7611 string asm, string operands, dag oops, dag iops,
7612 list<dag> pattern>
7613 : I<oops, iops, asm, operands, "", pattern> {
7614 bits<5> Vt;
7615 bits<5> vaddr;
7616 let Inst{31} = 0;
7617 let Inst{29-24} = 0b001101;
7618 let Inst{22} = L;
7619 let Inst{21} = R;
7620 let Inst{15-13} = opcode;
7621 let Inst{9-5} = vaddr;
7622 let Inst{4-0} = Vt;
7623 let DecoderMethod = "DecodeSIMDLdStSingle";
7624}
7625
7626class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7627 string asm, string operands, dag oops, dag iops,
7628 list<dag> pattern>
7629 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7630 bits<5> Vt;
7631 bits<5> vaddr;
7632 let Inst{31} = 0;
7633 let Inst{29-24} = 0b001101;
7634 let Inst{22} = L;
7635 let Inst{21} = R;
7636 let Inst{15-13} = opcode;
7637 let Inst{9-5} = vaddr;
7638 let Inst{4-0} = Vt;
7639 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7640}
7641
7642
7643let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7644class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7645 Operand listtype>
7646 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7647 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7648 let Inst{30} = Q;
7649 let Inst{23} = 0;
7650 let Inst{20-16} = 0b00000;
7651 let Inst{12} = S;
7652 let Inst{11-10} = size;
7653}
7654let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7655class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7656 string asm, Operand listtype, Operand GPR64pi>
7657 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7658 (outs listtype:$Vt),
7659 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7660 bits<5> Xm;
7661 let Inst{30} = Q;
7662 let Inst{23} = 1;
7663 let Inst{20-16} = Xm;
7664 let Inst{12} = S;
7665 let Inst{11-10} = size;
7666}
7667
7668multiclass SIMDLdrAliases<string asm, string layout, string Count,
7669 int Offset, int Size> {
7670 // E.g. "ld1r { v0.8b }, [x1], #1"
7671 // "ld1r.8b\t$Vt, $vaddr, #1"
7672 // may get mapped to
7673 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7674 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7675 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7676 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7677 am_simdnoindex:$vaddr, XZR), 1>;
7678
7679 // E.g. "ld1r.8b { v0 }, [x1], #1"
7680 // "ld1r.8b\t$Vt, $vaddr, #1"
7681 // may get mapped to
7682 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7683 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7684 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7685 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7686 am_simdnoindex:$vaddr, XZR), 0>;
7687
7688 // E.g. "ld1r.8b { v0 }, [x1]"
7689 // "ld1r.8b\t$Vt, $vaddr"
7690 // may get mapped to
7691 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7692 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7693 (!cast<Instruction>(NAME # "v" # layout)
7694 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7695 am_simdnoindex:$vaddr), 0>;
7696
7697 // E.g. "ld1r.8b { v0 }, [x1], x2"
7698 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7699 // may get mapped to
7700 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7701 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7702 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7703 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7704 am_simdnoindex:$vaddr,
7705 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7706}
7707
7708multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7709 int Offset1, int Offset2, int Offset4, int Offset8> {
7710 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7711 !cast<Operand>("VecList" # Count # "8b")>;
7712 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7713 !cast<Operand>("VecList" # Count #"16b")>;
7714 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7715 !cast<Operand>("VecList" # Count #"4h")>;
7716 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7717 !cast<Operand>("VecList" # Count #"8h")>;
7718 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7719 !cast<Operand>("VecList" # Count #"2s")>;
7720 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7721 !cast<Operand>("VecList" # Count #"4s")>;
7722 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7723 !cast<Operand>("VecList" # Count #"1d")>;
7724 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7725 !cast<Operand>("VecList" # Count #"2d")>;
7726
7727 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7728 !cast<Operand>("VecList" # Count # "8b"),
7729 !cast<Operand>("GPR64pi" # Offset1)>;
7730 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7731 !cast<Operand>("VecList" # Count # "16b"),
7732 !cast<Operand>("GPR64pi" # Offset1)>;
7733 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7734 !cast<Operand>("VecList" # Count # "4h"),
7735 !cast<Operand>("GPR64pi" # Offset2)>;
7736 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7737 !cast<Operand>("VecList" # Count # "8h"),
7738 !cast<Operand>("GPR64pi" # Offset2)>;
7739 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7740 !cast<Operand>("VecList" # Count # "2s"),
7741 !cast<Operand>("GPR64pi" # Offset4)>;
7742 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7743 !cast<Operand>("VecList" # Count # "4s"),
7744 !cast<Operand>("GPR64pi" # Offset4)>;
7745 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7746 !cast<Operand>("VecList" # Count # "1d"),
7747 !cast<Operand>("GPR64pi" # Offset8)>;
7748 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7749 !cast<Operand>("VecList" # Count # "2d"),
7750 !cast<Operand>("GPR64pi" # Offset8)>;
7751
7752 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7753 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7754 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7755 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7756 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7757 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7758 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7759 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7760}
7761
7762class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7763 dag oops, dag iops, list<dag> pattern>
7764 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7765 pattern> {
7766 // idx encoded in Q:S:size fields.
7767 bits<4> idx;
7768 let Inst{30} = idx{3};
7769 let Inst{23} = 0;
7770 let Inst{20-16} = 0b00000;
7771 let Inst{12} = idx{2};
7772 let Inst{11-10} = idx{1-0};
7773}
7774class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7775 dag oops, dag iops, list<dag> pattern>
7776 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7777 pattern> {
7778 // idx encoded in Q:S:size fields.
7779 bits<4> idx;
7780 let Inst{30} = idx{3};
7781 let Inst{23} = 0;
7782 let Inst{20-16} = 0b00000;
7783 let Inst{12} = idx{2};
7784 let Inst{11-10} = idx{1-0};
7785}
7786class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7787 dag oops, dag iops>
7788 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7789 oops, iops, []> {
7790 // idx encoded in Q:S:size fields.
7791 bits<4> idx;
7792 bits<5> Xm;
7793 let Inst{30} = idx{3};
7794 let Inst{23} = 1;
7795 let Inst{20-16} = Xm;
7796 let Inst{12} = idx{2};
7797 let Inst{11-10} = idx{1-0};
7798}
7799class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7800 dag oops, dag iops>
7801 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7802 oops, iops, []> {
7803 // idx encoded in Q:S:size fields.
7804 bits<4> idx;
7805 bits<5> Xm;
7806 let Inst{30} = idx{3};
7807 let Inst{23} = 1;
7808 let Inst{20-16} = Xm;
7809 let Inst{12} = idx{2};
7810 let Inst{11-10} = idx{1-0};
7811}
7812
7813class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7814 dag oops, dag iops, list<dag> pattern>
7815 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7816 pattern> {
7817 // idx encoded in Q:S:size<1> fields.
7818 bits<3> idx;
7819 let Inst{30} = idx{2};
7820 let Inst{23} = 0;
7821 let Inst{20-16} = 0b00000;
7822 let Inst{12} = idx{1};
7823 let Inst{11} = idx{0};
7824 let Inst{10} = size;
7825}
7826class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7827 dag oops, dag iops, list<dag> pattern>
7828 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7829 pattern> {
7830 // idx encoded in Q:S:size<1> fields.
7831 bits<3> idx;
7832 let Inst{30} = idx{2};
7833 let Inst{23} = 0;
7834 let Inst{20-16} = 0b00000;
7835 let Inst{12} = idx{1};
7836 let Inst{11} = idx{0};
7837 let Inst{10} = size;
7838}
7839
7840class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7841 dag oops, dag iops>
7842 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7843 oops, iops, []> {
7844 // idx encoded in Q:S:size<1> fields.
7845 bits<3> idx;
7846 bits<5> Xm;
7847 let Inst{30} = idx{2};
7848 let Inst{23} = 1;
7849 let Inst{20-16} = Xm;
7850 let Inst{12} = idx{1};
7851 let Inst{11} = idx{0};
7852 let Inst{10} = size;
7853}
7854class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7855 dag oops, dag iops>
7856 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7857 oops, iops, []> {
7858 // idx encoded in Q:S:size<1> fields.
7859 bits<3> idx;
7860 bits<5> Xm;
7861 let Inst{30} = idx{2};
7862 let Inst{23} = 1;
7863 let Inst{20-16} = Xm;
7864 let Inst{12} = idx{1};
7865 let Inst{11} = idx{0};
7866 let Inst{10} = size;
7867}
7868class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7869 dag oops, dag iops, list<dag> pattern>
7870 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7871 pattern> {
7872 // idx encoded in Q:S fields.
7873 bits<2> idx;
7874 let Inst{30} = idx{1};
7875 let Inst{23} = 0;
7876 let Inst{20-16} = 0b00000;
7877 let Inst{12} = idx{0};
7878 let Inst{11-10} = size;
7879}
7880class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7881 dag oops, dag iops, list<dag> pattern>
7882 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7883 pattern> {
7884 // idx encoded in Q:S fields.
7885 bits<2> idx;
7886 let Inst{30} = idx{1};
7887 let Inst{23} = 0;
7888 let Inst{20-16} = 0b00000;
7889 let Inst{12} = idx{0};
7890 let Inst{11-10} = size;
7891}
7892class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7893 string asm, dag oops, dag iops>
7894 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7895 oops, iops, []> {
7896 // idx encoded in Q:S fields.
7897 bits<2> idx;
7898 bits<5> Xm;
7899 let Inst{30} = idx{1};
7900 let Inst{23} = 1;
7901 let Inst{20-16} = Xm;
7902 let Inst{12} = idx{0};
7903 let Inst{11-10} = size;
7904}
7905class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7906 string asm, dag oops, dag iops>
7907 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7908 oops, iops, []> {
7909 // idx encoded in Q:S fields.
7910 bits<2> idx;
7911 bits<5> Xm;
7912 let Inst{30} = idx{1};
7913 let Inst{23} = 1;
7914 let Inst{20-16} = Xm;
7915 let Inst{12} = idx{0};
7916 let Inst{11-10} = size;
7917}
7918class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7919 dag oops, dag iops, list<dag> pattern>
7920 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7921 pattern> {
7922 // idx encoded in Q field.
7923 bits<1> idx;
7924 let Inst{30} = idx;
7925 let Inst{23} = 0;
7926 let Inst{20-16} = 0b00000;
7927 let Inst{12} = 0;
7928 let Inst{11-10} = size;
7929}
7930class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7931 dag oops, dag iops, list<dag> pattern>
7932 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7933 pattern> {
7934 // idx encoded in Q field.
7935 bits<1> idx;
7936 let Inst{30} = idx;
7937 let Inst{23} = 0;
7938 let Inst{20-16} = 0b00000;
7939 let Inst{12} = 0;
7940 let Inst{11-10} = size;
7941}
7942class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7943 string asm, dag oops, dag iops>
7944 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7945 oops, iops, []> {
7946 // idx encoded in Q field.
7947 bits<1> idx;
7948 bits<5> Xm;
7949 let Inst{30} = idx;
7950 let Inst{23} = 1;
7951 let Inst{20-16} = Xm;
7952 let Inst{12} = 0;
7953 let Inst{11-10} = size;
7954}
7955class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7956 string asm, dag oops, dag iops>
7957 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7958 oops, iops, []> {
7959 // idx encoded in Q field.
7960 bits<1> idx;
7961 bits<5> Xm;
7962 let Inst{30} = idx;
7963 let Inst{23} = 1;
7964 let Inst{20-16} = Xm;
7965 let Inst{12} = 0;
7966 let Inst{11-10} = size;
7967}
7968
7969let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7970multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7971 RegisterOperand listtype,
7972 RegisterOperand GPR64pi> {
7973 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7974 (outs listtype:$dst),
7975 (ins listtype:$Vt, VectorIndexB:$idx,
7976 am_simdnoindex:$vaddr), []>;
7977
7978 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
7979 (outs listtype:$dst),
7980 (ins listtype:$Vt, VectorIndexB:$idx,
7981 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7982}
7983let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7984multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
7985 RegisterOperand listtype,
7986 RegisterOperand GPR64pi> {
7987 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
7988 (outs listtype:$dst),
7989 (ins listtype:$Vt, VectorIndexH:$idx,
7990 am_simdnoindex:$vaddr), []>;
7991
7992 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
7993 (outs listtype:$dst),
7994 (ins listtype:$Vt, VectorIndexH:$idx,
7995 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7996}
7997let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7998multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
7999 RegisterOperand listtype,
8000 RegisterOperand GPR64pi> {
8001 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8002 (outs listtype:$dst),
8003 (ins listtype:$Vt, VectorIndexS:$idx,
8004 am_simdnoindex:$vaddr), []>;
8005
8006 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8007 (outs listtype:$dst),
8008 (ins listtype:$Vt, VectorIndexS:$idx,
8009 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8010}
8011let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8012multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008013 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008014 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8015 (outs listtype:$dst),
8016 (ins listtype:$Vt, VectorIndexD:$idx,
8017 am_simdnoindex:$vaddr), []>;
8018
8019 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8020 (outs listtype:$dst),
8021 (ins listtype:$Vt, VectorIndexD:$idx,
8022 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8023}
8024let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8025multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008026 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008027 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8028 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008029 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008030
8031 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8032 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8033 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8034}
8035let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8036multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008037 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008038 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8039 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008040 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008041
8042 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8043 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8044 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8045}
8046let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8047multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008048 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008049 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8050 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008051 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008052
8053 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8054 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8055 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8056}
8057let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8058multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008059 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008060 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8061 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008062 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008063
8064 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8065 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8066 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8067}
8068
8069multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8070 string Count, int Offset, Operand idxtype> {
8071 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8072 // "ld1\t$Vt, $vaddr, #1"
8073 // may get mapped to
8074 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8075 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8076 (!cast<Instruction>(NAME # Type # "_POST")
8077 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8078 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8079
8080 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8081 // "ld1.8b\t$Vt, $vaddr, #1"
8082 // may get mapped to
8083 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8084 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8085 (!cast<Instruction>(NAME # Type # "_POST")
8086 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8087 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8088
8089 // E.g. "ld1.8b { v0 }[0], [x1]"
8090 // "ld1.8b\t$Vt, $vaddr"
8091 // may get mapped to
8092 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8093 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8094 (!cast<Instruction>(NAME # Type)
8095 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8096 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8097
8098 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8099 // "ld1.8b\t$Vt, $vaddr, $Xm"
8100 // may get mapped to
8101 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8102 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8103 (!cast<Instruction>(NAME # Type # "_POST")
8104 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8105 idxtype:$idx, am_simdnoindex:$vaddr,
8106 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8107}
8108
8109multiclass SIMDLdSt1SingleAliases<string asm> {
8110 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8111 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8112 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8113 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8114}
8115
8116multiclass SIMDLdSt2SingleAliases<string asm> {
8117 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8118 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8119 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8120 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8121}
8122
8123multiclass SIMDLdSt3SingleAliases<string asm> {
8124 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8125 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8126 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8127 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8128}
8129
8130multiclass SIMDLdSt4SingleAliases<string asm> {
8131 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8132 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8133 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8134 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8135}
8136
8137//----------------------------------------------------------------------------
8138// Crypto extensions
8139//----------------------------------------------------------------------------
8140
8141let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8142class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8143 list<dag> pat>
8144 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8145 Sched<[WriteV]>{
8146 bits<5> Rd;
8147 bits<5> Rn;
8148 let Inst{31-16} = 0b0100111000101000;
8149 let Inst{15-12} = opc;
8150 let Inst{11-10} = 0b10;
8151 let Inst{9-5} = Rn;
8152 let Inst{4-0} = Rd;
8153}
8154
8155class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8156 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8157 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8158
8159class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8160 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8161 "$Rd = $dst",
8162 [(set (v16i8 V128:$dst),
8163 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8164
8165let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8166class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8167 dag oops, dag iops, list<dag> pat>
8168 : I<oops, iops, asm,
8169 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8170 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8171 Sched<[WriteV]>{
8172 bits<5> Rd;
8173 bits<5> Rn;
8174 bits<5> Rm;
8175 let Inst{31-21} = 0b01011110000;
8176 let Inst{20-16} = Rm;
8177 let Inst{15} = 0;
8178 let Inst{14-12} = opc;
8179 let Inst{11-10} = 0b00;
8180 let Inst{9-5} = Rn;
8181 let Inst{4-0} = Rd;
8182}
8183
8184class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8185 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8186 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8187 [(set (v4i32 FPR128:$dst),
8188 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8189 (v4i32 V128:$Rm)))]>;
8190
8191class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8192 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8193 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8194 [(set (v4i32 V128:$dst),
8195 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8196 (v4i32 V128:$Rm)))]>;
8197
8198class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8199 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8200 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8201 [(set (v4i32 FPR128:$dst),
8202 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8203 (v4i32 V128:$Rm)))]>;
8204
8205let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8206class SHA2OpInst<bits<4> opc, string asm, string kind,
8207 string cstr, dag oops, dag iops,
8208 list<dag> pat>
8209 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8210 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8211 Sched<[WriteV]>{
8212 bits<5> Rd;
8213 bits<5> Rn;
8214 let Inst{31-16} = 0b0101111000101000;
8215 let Inst{15-12} = opc;
8216 let Inst{11-10} = 0b10;
8217 let Inst{9-5} = Rn;
8218 let Inst{4-0} = Rd;
8219}
8220
8221class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8222 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8223 (ins V128:$Rd, V128:$Rn),
8224 [(set (v4i32 V128:$dst),
8225 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8226
8227class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8228 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8229 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8230
8231// Allow the size specifier tokens to be upper case, not just lower.
8232def : TokenAlias<".8B", ".8b">;
8233def : TokenAlias<".4H", ".4h">;
8234def : TokenAlias<".2S", ".2s">;
8235def : TokenAlias<".1D", ".1d">;
8236def : TokenAlias<".16B", ".16b">;
8237def : TokenAlias<".8H", ".8h">;
8238def : TokenAlias<".4S", ".4s">;
8239def : TokenAlias<".2D", ".2d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008240def : TokenAlias<".1Q", ".1q">;
Tim Northover00ed9962014-03-29 10:18:08 +00008241def : TokenAlias<".B", ".b">;
8242def : TokenAlias<".H", ".h">;
8243def : TokenAlias<".S", ".s">;
8244def : TokenAlias<".D", ".d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008245def : TokenAlias<".Q", ".q">;