blob: af8b683821282cd07e5ba3f6fb457bfd453c5a1b [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}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002434class am_unscaled_wb_operand : Operand<i64> {
2435 let PrintMethod = "printAMUnscaledWB";
2436 let ParserMatchClass = MemoryUnscaledOperand;
2437 let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2438}
Tim Northover00ed9962014-03-29 10:18:08 +00002439def am_unscaled : am_unscaled_operand;
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002440def am_unscaled_wb: am_unscaled_wb_operand;
Tim Northover00ed9962014-03-29 10:18:08 +00002441def am_unscaled8 : am_unscaled_operand,
2442 ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2443def am_unscaled16 : am_unscaled_operand,
2444 ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2445def am_unscaled32 : am_unscaled_operand,
2446 ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2447def am_unscaled64 : am_unscaled_operand,
2448 ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2449def am_unscaled128 : am_unscaled_operand,
2450 ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2451
2452class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2453 string asm, list<dag> pattern>
2454 : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2455 // The operands are in order to match the 'addr' MI operands, so we
2456 // don't need an encoder method and by-name matching. Just use the default
2457 // in-order handling. Since we're using by-order, make sure the names
2458 // do not match.
2459 bits<5> dst;
2460 bits<5> base;
2461 bits<9> offset;
2462 let Inst{31-30} = sz;
2463 let Inst{29-27} = 0b111;
2464 let Inst{26} = V;
2465 let Inst{25-24} = 0b00;
2466 let Inst{23-22} = opc;
2467 let Inst{21} = 0;
2468 let Inst{20-12} = offset;
2469 let Inst{11-10} = 0b00;
2470 let Inst{9-5} = base;
2471 let Inst{4-0} = dst;
2472
2473 let DecoderMethod = "DecodeSignedLdStInstruction";
2474}
2475
2476let AddedComplexity = 1 in // try this before LoadUI
2477class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2478 Operand amtype, string asm, list<dag> pattern>
2479 : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2480 (ins amtype:$addr), asm, pattern>,
2481 Sched<[WriteLD]>;
2482
2483let AddedComplexity = 1 in // try this before StoreUI
2484class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2485 Operand amtype, string asm, list<dag> pattern>
2486 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2487 (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2488 Sched<[WriteST]>;
2489
2490let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2491class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2492 : BaseLoadStoreUnscale<sz, V, opc, (outs),
2493 (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2494 Sched<[WriteLD]>;
2495
2496//---
2497// Load/store unscaled immediate, unprivileged
2498//---
2499
2500class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2501 dag oops, dag iops, string asm>
2502 : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2503 // The operands are in order to match the 'addr' MI operands, so we
2504 // don't need an encoder method and by-name matching. Just use the default
2505 // in-order handling. Since we're using by-order, make sure the names
2506 // do not match.
2507 bits<5> dst;
2508 bits<5> base;
2509 bits<9> offset;
2510 let Inst{31-30} = sz;
2511 let Inst{29-27} = 0b111;
2512 let Inst{26} = V;
2513 let Inst{25-24} = 0b00;
2514 let Inst{23-22} = opc;
2515 let Inst{21} = 0;
2516 let Inst{20-12} = offset;
2517 let Inst{11-10} = 0b10;
2518 let Inst{9-5} = base;
2519 let Inst{4-0} = dst;
2520
2521 let DecoderMethod = "DecodeSignedLdStInstruction";
2522}
2523
2524let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2525class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2526 string asm>
2527 : BaseLoadStoreUnprivileged<sz, V, opc,
2528 (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2529 Sched<[WriteLD]>;
2530}
2531
2532let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2533class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2534 string asm>
2535 : BaseLoadStoreUnprivileged<sz, V, opc,
2536 (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2537 Sched<[WriteST]>;
2538}
2539
2540//---
2541// Load/store pre-indexed
2542//---
2543
2544class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2545 string asm, string cstr>
2546 : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2547 // The operands are in order to match the 'addr' MI operands, so we
2548 // don't need an encoder method and by-name matching. Just use the default
2549 // in-order handling.
2550 bits<5> dst;
2551 bits<5> base;
2552 bits<9> offset;
2553 let Inst{31-30} = sz;
2554 let Inst{29-27} = 0b111;
2555 let Inst{26} = V;
2556 let Inst{25-24} = 0;
2557 let Inst{23-22} = opc;
2558 let Inst{21} = 0;
2559 let Inst{20-12} = offset;
2560 let Inst{11-10} = 0b11;
2561 let Inst{9-5} = base;
2562 let Inst{4-0} = dst;
2563
2564 let DecoderMethod = "DecodeSignedLdStInstruction";
2565}
2566
2567let hasSideEffects = 0 in {
2568let mayStore = 0, mayLoad = 1 in
2569// FIXME: Modeling the write-back of these instructions for isel is tricky.
2570// we need the complex addressing mode for the memory reference, but
2571// we also need the write-back specified as a tied operand to the
2572// base register. That combination does not play nicely with
2573// the asm matcher and friends.
2574class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2575 string asm>
2576 : BaseLoadStorePreIdx<sz, V, opc,
2577 (outs regtype:$Rt/*, GPR64sp:$wback*/),
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002578 (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
Tim Northover00ed9962014-03-29 10:18:08 +00002579 Sched<[WriteLD, WriteAdr]>;
2580
2581let mayStore = 1, mayLoad = 0 in
2582class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2583 string asm>
2584 : BaseLoadStorePreIdx<sz, V, opc,
2585 (outs/* GPR64sp:$wback*/),
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002586 (ins regtype:$Rt, am_unscaled_wb:$addr),
Tim Northover00ed9962014-03-29 10:18:08 +00002587 asm, ""/*"$addr.base = $wback"*/>,
2588 Sched<[WriteAdr, WriteST]>;
2589} // hasSideEffects = 0
2590
2591// ISel pseudo-instructions which have the tied operands. When the MC lowering
2592// logic finally gets smart enough to strip off tied operands that are just
2593// for isel convenience, we can get rid of these pseudos and just reference
2594// the real instructions directly.
2595//
2596// Ironically, also because of the writeback operands, we can't put the
2597// matcher pattern directly on the instruction, but need to define it
2598// separately.
2599//
2600// Loads aren't matched with patterns here at all, but rather in C++
2601// custom lowering.
2602let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2603class LoadPreIdxPseudo<RegisterClass regtype>
2604 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2605 (ins am_noindex:$addr, simm9:$offset), [],
2606 "$addr.base = $wback,@earlyclobber $wback">,
2607 Sched<[WriteLD, WriteAdr]>;
2608class LoadPostIdxPseudo<RegisterClass regtype>
2609 : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2610 (ins am_noindex:$addr, simm9:$offset), [],
2611 "$addr.base = $wback,@earlyclobber $wback">,
2612 Sched<[WriteLD, WriteI]>;
2613}
2614multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2615 SDPatternOperator OpNode> {
2616 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2617 def _isel: Pseudo<(outs GPR64sp:$wback),
2618 (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2619 "$addr.base = $wback,@earlyclobber $wback">,
2620 Sched<[WriteAdr, WriteST]>;
2621
2622 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2623 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2624 simm9:$offset)>;
2625}
2626
2627//---
2628// Load/store post-indexed
2629//---
2630
2631// (pre-index) load/stores.
2632class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2633 string asm, string cstr>
2634 : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2635 // The operands are in order to match the 'addr' MI operands, so we
2636 // don't need an encoder method and by-name matching. Just use the default
2637 // in-order handling.
2638 bits<5> dst;
2639 bits<5> base;
2640 bits<9> offset;
2641 let Inst{31-30} = sz;
2642 let Inst{29-27} = 0b111;
2643 let Inst{26} = V;
2644 let Inst{25-24} = 0b00;
2645 let Inst{23-22} = opc;
2646 let Inst{21} = 0b0;
2647 let Inst{20-12} = offset;
2648 let Inst{11-10} = 0b01;
2649 let Inst{9-5} = base;
2650 let Inst{4-0} = dst;
2651
2652 let DecoderMethod = "DecodeSignedLdStInstruction";
2653}
2654
2655let hasSideEffects = 0 in {
2656let mayStore = 0, mayLoad = 1 in
2657// FIXME: Modeling the write-back of these instructions for isel is tricky.
2658// we need the complex addressing mode for the memory reference, but
2659// we also need the write-back specified as a tied operand to the
2660// base register. That combination does not play nicely with
2661// the asm matcher and friends.
2662class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2663 string asm>
2664 : BaseLoadStorePostIdx<sz, V, opc,
2665 (outs regtype:$Rt/*, GPR64sp:$wback*/),
2666 (ins am_noindex:$addr, simm9:$idx),
2667 asm, ""/*"$addr.base = $wback"*/>,
2668 Sched<[WriteLD, WriteI]>;
2669
2670let mayStore = 1, mayLoad = 0 in
2671class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2672 string asm>
2673 : BaseLoadStorePostIdx<sz, V, opc,
2674 (outs/* GPR64sp:$wback*/),
2675 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2676 asm, ""/*"$addr.base = $wback"*/>,
2677 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2678} // hasSideEffects = 0
2679
2680// ISel pseudo-instructions which have the tied operands. When the MC lowering
2681// logic finally gets smart enough to strip off tied operands that are just
2682// for isel convenience, we can get rid of these pseudos and just reference
2683// the real instructions directly.
2684//
2685// Ironically, also because of the writeback operands, we can't put the
2686// matcher pattern directly on the instruction, but need to define it
2687// separately.
2688multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2689 SDPatternOperator OpNode, Instruction Insn> {
2690 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2691 def _isel: Pseudo<(outs GPR64sp:$wback),
2692 (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2693 "$addr.base = $wback,@earlyclobber $wback">,
2694 PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2695 Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2696
2697 def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2698 (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2699 simm9:$idx)>;
2700}
2701
2702//---
2703// Load/store pair
2704//---
2705
2706// (indexed, offset)
2707
2708class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2709 string asm>
2710 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2711 // The operands are in order to match the 'addr' MI operands, so we
2712 // don't need an encoder method and by-name matching. Just use the default
2713 // in-order handling. Since we're using by-order, make sure the names
2714 // do not match.
2715 bits<5> dst;
2716 bits<5> dst2;
2717 bits<5> base;
2718 bits<7> offset;
2719 let Inst{31-30} = opc;
2720 let Inst{29-27} = 0b101;
2721 let Inst{26} = V;
2722 let Inst{25-23} = 0b010;
2723 let Inst{22} = L;
2724 let Inst{21-15} = offset;
2725 let Inst{14-10} = dst2;
2726 let Inst{9-5} = base;
2727 let Inst{4-0} = dst;
2728
2729 let DecoderMethod = "DecodePairLdStInstruction";
2730}
2731
2732let hasSideEffects = 0 in {
2733let mayStore = 0, mayLoad = 1 in
2734class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2735 Operand indextype, string asm>
2736 : BaseLoadStorePairOffset<opc, V, 1,
2737 (outs regtype:$Rt, regtype:$Rt2),
2738 (ins indextype:$addr), asm>,
2739 Sched<[WriteLD, WriteLDHi]>;
2740
2741let mayLoad = 0, mayStore = 1 in
2742class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2743 Operand indextype, string asm>
2744 : BaseLoadStorePairOffset<opc, V, 0, (outs),
2745 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2746 asm>,
2747 Sched<[WriteSTP]>;
2748} // hasSideEffects = 0
2749
2750// (pre-indexed)
2751
2752def MemoryIndexed32SImm7 : AsmOperandClass {
2753 let Name = "MemoryIndexed32SImm7";
2754 let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2755}
2756def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2757 let PrintMethod = "printAMIndexed32";
2758 let ParserMatchClass = MemoryIndexed32SImm7;
2759 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2760}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002761def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2762 let PrintMethod = "printAMIndexed32WB";
2763 let ParserMatchClass = MemoryIndexed32SImm7;
2764 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2765}
Tim Northover00ed9962014-03-29 10:18:08 +00002766
2767def MemoryIndexed64SImm7 : AsmOperandClass {
2768 let Name = "MemoryIndexed64SImm7";
2769 let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2770}
2771def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2772 let PrintMethod = "printAMIndexed64";
2773 let ParserMatchClass = MemoryIndexed64SImm7;
2774 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2775}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002776def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2777 let PrintMethod = "printAMIndexed64WB";
2778 let ParserMatchClass = MemoryIndexed64SImm7;
2779 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2780}
Tim Northover00ed9962014-03-29 10:18:08 +00002781
2782def MemoryIndexed128SImm7 : AsmOperandClass {
2783 let Name = "MemoryIndexed128SImm7";
2784 let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2785}
2786def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2787 let PrintMethod = "printAMIndexed128";
2788 let ParserMatchClass = MemoryIndexed128SImm7;
2789 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2790}
Bradley Smitha0d7a9a2014-04-09 14:44:31 +00002791def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2792 let PrintMethod = "printAMIndexed128WB";
2793 let ParserMatchClass = MemoryIndexed128SImm7;
2794 let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2795}
Tim Northover00ed9962014-03-29 10:18:08 +00002796
2797class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2798 string asm>
2799 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2800 // The operands are in order to match the 'addr' MI operands, so we
2801 // don't need an encoder method and by-name matching. Just use the default
2802 // in-order handling. Since we're using by-order, make sure the names
2803 // do not match.
2804 bits<5> dst;
2805 bits<5> dst2;
2806 bits<5> base;
2807 bits<7> offset;
2808 let Inst{31-30} = opc;
2809 let Inst{29-27} = 0b101;
2810 let Inst{26} = V;
2811 let Inst{25-23} = 0b011;
2812 let Inst{22} = L;
2813 let Inst{21-15} = offset;
2814 let Inst{14-10} = dst2;
2815 let Inst{9-5} = base;
2816 let Inst{4-0} = dst;
2817
2818 let DecoderMethod = "DecodePairLdStInstruction";
2819}
2820
2821let hasSideEffects = 0 in {
2822let mayStore = 0, mayLoad = 1 in
2823class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2824 Operand addrmode, string asm>
2825 : BaseLoadStorePairPreIdx<opc, V, 1,
2826 (outs regtype:$Rt, regtype:$Rt2),
2827 (ins addrmode:$addr), asm>,
2828 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2829
2830let mayStore = 1, mayLoad = 0 in
2831class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2832 Operand addrmode, string asm>
2833 : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2834 (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2835 asm>,
2836 Sched<[WriteAdr, WriteSTP]>;
2837} // hasSideEffects = 0
2838
2839// (post-indexed)
2840
2841class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2842 string asm>
2843 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2844 // The operands are in order to match the 'addr' MI operands, so we
2845 // don't need an encoder method and by-name matching. Just use the default
2846 // in-order handling. Since we're using by-order, make sure the names
2847 // do not match.
2848 bits<5> dst;
2849 bits<5> dst2;
2850 bits<5> base;
2851 bits<7> offset;
2852 let Inst{31-30} = opc;
2853 let Inst{29-27} = 0b101;
2854 let Inst{26} = V;
2855 let Inst{25-23} = 0b001;
2856 let Inst{22} = L;
2857 let Inst{21-15} = offset;
2858 let Inst{14-10} = dst2;
2859 let Inst{9-5} = base;
2860 let Inst{4-0} = dst;
2861
2862 let DecoderMethod = "DecodePairLdStInstruction";
2863}
2864
2865let hasSideEffects = 0 in {
2866let mayStore = 0, mayLoad = 1 in
2867class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2868 Operand idxtype, string asm>
2869 : BaseLoadStorePairPostIdx<opc, V, 1,
2870 (outs regtype:$Rt, regtype:$Rt2),
2871 (ins am_noindex:$addr, idxtype:$idx), asm>,
2872 Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2873
2874let mayStore = 1, mayLoad = 0 in
2875class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2876 Operand idxtype, string asm>
2877 : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2878 (ins regtype:$Rt, regtype:$Rt2,
2879 am_noindex:$addr, idxtype:$idx),
2880 asm>,
2881 Sched<[WriteAdr, WriteSTP]>;
2882} // hasSideEffects = 0
2883
2884// (no-allocate)
2885
2886class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2887 string asm>
2888 : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2889 // The operands are in order to match the 'addr' MI operands, so we
2890 // don't need an encoder method and by-name matching. Just use the default
2891 // in-order handling. Since we're using by-order, make sure the names
2892 // do not match.
2893 bits<5> dst;
2894 bits<5> dst2;
2895 bits<5> base;
2896 bits<7> offset;
2897 let Inst{31-30} = opc;
2898 let Inst{29-27} = 0b101;
2899 let Inst{26} = V;
2900 let Inst{25-23} = 0b000;
2901 let Inst{22} = L;
2902 let Inst{21-15} = offset;
2903 let Inst{14-10} = dst2;
2904 let Inst{9-5} = base;
2905 let Inst{4-0} = dst;
2906
2907 let DecoderMethod = "DecodePairLdStInstruction";
2908}
2909
2910let hasSideEffects = 0 in {
2911let mayStore = 0, mayLoad = 1 in
2912class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2913 Operand indextype, string asm>
2914 : BaseLoadStorePairNoAlloc<opc, V, 1,
2915 (outs regtype:$Rt, regtype:$Rt2),
2916 (ins indextype:$addr), asm>,
2917 Sched<[WriteLD, WriteLDHi]>;
2918
2919let mayStore = 1, mayLoad = 0 in
2920class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2921 Operand indextype, string asm>
2922 : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2923 (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2924 asm>,
2925 Sched<[WriteSTP]>;
2926} // hasSideEffects = 0
2927
2928//---
2929// Load/store exclusive
2930//---
2931
2932// True exclusive operations write to and/or read from the system's exclusive
2933// monitors, which as far as a compiler is concerned can be modelled as a
2934// random shared memory address. Hence LoadExclusive mayStore.
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002935//
2936// Since these instructions have the undefined register bits set to 1 in
2937// their canonical form, we need a post encoder method to set those bits
2938// to 1 when encoding these instructions. We do this using the
2939// fixLoadStoreExclusive function. This function has template parameters:
2940//
2941// fixLoadStoreExclusive<int hasRs, int hasRt2>
2942//
2943// hasRs indicates that the instruction uses the Rs field, so we won't set
2944// it to 1 (and the same for Rt2). We don't need template parameters for
2945// the other register fields since Rt and Rn are always used.
2946//
Tim Northover00ed9962014-03-29 10:18:08 +00002947let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2948class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2949 dag oops, dag iops, string asm, string operands>
2950 : I<oops, iops, asm, operands, "", []> {
2951 let Inst{31-30} = sz;
2952 let Inst{29-24} = 0b001000;
2953 let Inst{23} = o2;
2954 let Inst{22} = L;
2955 let Inst{21} = o1;
2956 let Inst{15} = o0;
2957
2958 let DecoderMethod = "DecodeExclusiveLdStInstruction";
2959}
2960
2961// Neither Rs nor Rt2 operands.
2962class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2963 dag oops, dag iops, string asm, string operands>
2964 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2965 bits<5> reg;
2966 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00002967 let Inst{9-5} = base;
2968 let Inst{4-0} = reg;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00002969
2970 let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00002971}
2972
2973// Simple load acquires don't set the exclusive monitor
2974let mayLoad = 1, mayStore = 0 in
2975class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2976 RegisterClass regtype, string asm>
2977 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2978 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2979 Sched<[WriteLD]>;
2980
2981class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2982 RegisterClass regtype, string asm>
2983 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2984 (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2985 Sched<[WriteLD]>;
2986
2987class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2988 RegisterClass regtype, string asm>
2989 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2990 (outs regtype:$Rt, regtype:$Rt2),
2991 (ins am_noindex:$addr), asm,
2992 "\t$Rt, $Rt2, $addr">,
2993 Sched<[WriteLD, WriteLDHi]> {
2994 bits<5> dst1;
2995 bits<5> dst2;
2996 bits<5> base;
Tim Northover00ed9962014-03-29 10:18:08 +00002997 let Inst{14-10} = dst2;
2998 let Inst{9-5} = base;
2999 let Inst{4-0} = dst1;
Bradley Smithbc35b1f2014-04-09 14:43:01 +00003000
3001 let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
Tim Northover00ed9962014-03-29 10:18:08 +00003002}
3003
3004// Simple store release operations do not check the exclusive monitor.
3005let mayLoad = 0, mayStore = 1 in
3006class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3007 RegisterClass regtype, string asm>
3008 : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3009 (ins regtype:$Rt, am_noindex:$addr),
3010 asm, "\t$Rt, $addr">,
3011 Sched<[WriteST]>;
3012
3013let mayLoad = 1, mayStore = 1 in
3014class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3015 RegisterClass regtype, string asm>
3016 : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3017 (ins regtype:$Rt, am_noindex:$addr),
3018 asm, "\t$Ws, $Rt, $addr">,
3019 Sched<[WriteSTX]> {
3020 bits<5> status;
3021 bits<5> reg;
3022 bits<5> base;
3023 let Inst{20-16} = status;
Tim Northover00ed9962014-03-29 10:18:08 +00003024 let Inst{9-5} = base;
3025 let Inst{4-0} = reg;
3026
3027 let Constraints = "@earlyclobber $Ws";
Bradley Smithbc35b1f2014-04-09 14:43:01 +00003028 let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
Tim Northover00ed9962014-03-29 10:18:08 +00003029}
3030
3031class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3032 RegisterClass regtype, string asm>
3033 : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3034 (outs GPR32:$Ws),
3035 (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3036 asm, "\t$Ws, $Rt, $Rt2, $addr">,
3037 Sched<[WriteSTX]> {
3038 bits<5> status;
3039 bits<5> dst1;
3040 bits<5> dst2;
3041 bits<5> base;
3042 let Inst{20-16} = status;
3043 let Inst{14-10} = dst2;
3044 let Inst{9-5} = base;
3045 let Inst{4-0} = dst1;
3046
3047 let Constraints = "@earlyclobber $Ws";
3048}
3049
3050//---
3051// Exception generation
3052//---
3053
3054let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3055class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3056 : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3057 Sched<[WriteSys]> {
3058 bits<16> imm;
3059 let Inst{31-24} = 0b11010100;
3060 let Inst{23-21} = op1;
3061 let Inst{20-5} = imm;
3062 let Inst{4-2} = 0b000;
3063 let Inst{1-0} = ll;
3064}
3065
3066//---
3067// Floating point to integer conversion
3068//---
3069
3070class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3071 RegisterClass srcType, RegisterClass dstType,
3072 string asm, list<dag> pattern>
3073 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3074 asm, "\t$Rd, $Rn", "", pattern>,
3075 Sched<[WriteFCvt]> {
3076 bits<5> Rd;
3077 bits<5> Rn;
Bradley Smith0243aa32014-04-09 14:43:20 +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} = 1;
3082 let Inst{20-19} = rmode;
3083 let Inst{18-16} = opcode;
3084 let Inst{15-10} = 0;
3085 let Inst{9-5} = Rn;
3086 let Inst{4-0} = Rd;
3087}
3088
3089let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3090class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3091 RegisterClass srcType, RegisterClass dstType,
3092 Operand immType, string asm>
3093 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3094 asm, "\t$Rd, $Rn, $scale", "", []>,
3095 Sched<[WriteFCvt]> {
3096 bits<5> Rd;
3097 bits<5> Rn;
3098 bits<6> scale;
Bradley Smith60e76672014-04-09 14:43:27 +00003099 let Inst{30-29} = 0b00;
Tim Northover00ed9962014-03-29 10:18:08 +00003100 let Inst{28-24} = 0b11110;
3101 let Inst{23-22} = type;
3102 let Inst{21} = 0;
3103 let Inst{20-19} = rmode;
3104 let Inst{18-16} = opcode;
3105 let Inst{15-10} = scale;
3106 let Inst{9-5} = Rn;
3107 let Inst{4-0} = Rd;
3108}
3109
Bradley Smith0243aa32014-04-09 14:43:20 +00003110multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3111 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003112 // Unscaled single-precision to 32-bit
3113 def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3114 [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3115 let Inst{31} = 0; // 32-bit GPR flag
3116 }
3117
3118 // Unscaled single-precision to 64-bit
3119 def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3120 [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3121 let Inst{31} = 1; // 64-bit GPR flag
3122 }
3123
3124 // Unscaled double-precision to 32-bit
3125 def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3126 [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3127 let Inst{31} = 0; // 32-bit GPR flag
3128 }
3129
3130 // Unscaled double-precision to 64-bit
3131 def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3132 [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3133 let Inst{31} = 1; // 64-bit GPR flag
3134 }
Bradley Smith0243aa32014-04-09 14:43:20 +00003135}
Tim Northover00ed9962014-03-29 10:18:08 +00003136
Bradley Smith0243aa32014-04-09 14:43:20 +00003137multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3138 SDPatternOperator OpN> {
Tim Northover00ed9962014-03-29 10:18:08 +00003139 // Scaled single-precision to 32-bit
3140 def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3141 fixedpoint32, asm> {
3142 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003143 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003144 }
3145
3146 // Scaled single-precision to 64-bit
3147 def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3148 fixedpoint64, asm> {
3149 let Inst{31} = 1; // 64-bit GPR flag
3150 }
3151
3152 // Scaled double-precision to 32-bit
3153 def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3154 fixedpoint32, asm> {
3155 let Inst{31} = 0; // 32-bit GPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003156 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003157 }
3158
3159 // Scaled double-precision to 64-bit
3160 def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3161 fixedpoint64, asm> {
3162 let Inst{31} = 1; // 64-bit GPR flag
3163 }
3164}
3165
3166//---
3167// Integer to floating point conversion
3168//---
3169
3170let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3171class BaseIntegerToFP<bit isUnsigned,
3172 RegisterClass srcType, RegisterClass dstType,
3173 Operand immType, string asm>
3174 : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3175 asm, "\t$Rd, $Rn, $scale", "", []>,
3176 Sched<[WriteFCvt]> {
3177 bits<5> Rd;
3178 bits<5> Rn;
3179 bits<6> scale;
3180 let Inst{30-23} = 0b00111100;
3181 let Inst{21-17} = 0b00001;
3182 let Inst{16} = isUnsigned;
3183 let Inst{15-10} = scale;
3184 let Inst{9-5} = Rn;
3185 let Inst{4-0} = Rd;
3186}
3187
3188class BaseIntegerToFPUnscaled<bit isUnsigned,
3189 RegisterClass srcType, RegisterClass dstType,
3190 ValueType dvt, string asm, SDNode node>
3191 : I<(outs dstType:$Rd), (ins srcType:$Rn),
3192 asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3193 Sched<[WriteFCvt]> {
3194 bits<5> Rd;
3195 bits<5> Rn;
3196 bits<6> scale;
3197 let Inst{30-23} = 0b00111100;
3198 let Inst{21-17} = 0b10001;
3199 let Inst{16} = isUnsigned;
3200 let Inst{15-10} = 0b000000;
3201 let Inst{9-5} = Rn;
3202 let Inst{4-0} = Rd;
3203}
3204
3205multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3206 // Unscaled
3207 def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3208 let Inst{31} = 0; // 32-bit GPR flag
3209 let Inst{22} = 0; // 32-bit FPR flag
3210 }
3211
3212 def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3213 let Inst{31} = 0; // 32-bit GPR flag
3214 let Inst{22} = 1; // 64-bit FPR flag
3215 }
3216
3217 def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3218 let Inst{31} = 1; // 64-bit GPR flag
3219 let Inst{22} = 0; // 32-bit FPR flag
3220 }
3221
3222 def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3223 let Inst{31} = 1; // 64-bit GPR flag
3224 let Inst{22} = 1; // 64-bit FPR flag
3225 }
3226
3227 // Scaled
3228 def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint32, asm> {
3229 let Inst{31} = 0; // 32-bit GPR flag
3230 let Inst{22} = 0; // 32-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003231 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003232 }
3233
3234 def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint32, asm> {
3235 let Inst{31} = 0; // 32-bit GPR flag
3236 let Inst{22} = 1; // 64-bit FPR flag
Bradley Smitheb4ca042014-04-09 14:43:35 +00003237 let scale{5} = 1;
Tim Northover00ed9962014-03-29 10:18:08 +00003238 }
3239
3240 def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint64, asm> {
3241 let Inst{31} = 1; // 64-bit GPR flag
3242 let Inst{22} = 0; // 32-bit FPR flag
3243 }
3244
3245 def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint64, asm> {
3246 let Inst{31} = 1; // 64-bit GPR flag
3247 let Inst{22} = 1; // 64-bit FPR flag
3248 }
3249}
3250
3251//---
3252// Unscaled integer <-> floating point conversion (i.e. FMOV)
3253//---
3254
3255let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3256class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3257 RegisterClass srcType, RegisterClass dstType,
3258 string asm>
3259 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3260 // We use COPY_TO_REGCLASS for these bitconvert operations.
3261 // copyPhysReg() expands the resultant COPY instructions after
3262 // regalloc is done. This gives greater freedom for the allocator
3263 // and related passes (coalescing, copy propagation, et. al.) to
3264 // be more effective.
3265 [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3266 Sched<[WriteFCopy]> {
3267 bits<5> Rd;
3268 bits<5> Rn;
3269 let Inst{30-23} = 0b00111100;
3270 let Inst{21} = 1;
3271 let Inst{20-19} = rmode;
3272 let Inst{18-16} = opcode;
3273 let Inst{15-10} = 0b000000;
3274 let Inst{9-5} = Rn;
3275 let Inst{4-0} = Rd;
3276}
3277
3278let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3279class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3280 RegisterClass srcType, RegisterOperand dstType, string asm>
3281 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd[1], $Rn", "", []>,
3282 Sched<[WriteFCopy]> {
3283 bits<5> Rd;
3284 bits<5> Rn;
3285 let Inst{30-23} = 0b00111101;
3286 let Inst{21} = 1;
3287 let Inst{20-19} = rmode;
3288 let Inst{18-16} = opcode;
3289 let Inst{15-10} = 0b000000;
3290 let Inst{9-5} = Rn;
3291 let Inst{4-0} = Rd;
3292}
3293
3294let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3295class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3296 RegisterOperand srcType, RegisterClass dstType, string asm>
3297 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn[1]", "", []>,
3298 Sched<[WriteFCopy]> {
3299 bits<5> Rd;
3300 bits<5> Rn;
3301 let Inst{30-23} = 0b00111101;
3302 let Inst{21} = 1;
3303 let Inst{20-19} = rmode;
3304 let Inst{18-16} = opcode;
3305 let Inst{15-10} = 0b000000;
3306 let Inst{9-5} = Rn;
3307 let Inst{4-0} = Rd;
3308}
3309
3310
3311
3312multiclass UnscaledConversion<string asm> {
3313 def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3314 let Inst{31} = 0; // 32-bit GPR flag
3315 let Inst{22} = 0; // 32-bit FPR flag
3316 }
3317
3318 def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3319 let Inst{31} = 1; // 64-bit GPR flag
3320 let Inst{22} = 1; // 64-bit FPR flag
3321 }
3322
3323 def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3324 let Inst{31} = 0; // 32-bit GPR flag
3325 let Inst{22} = 0; // 32-bit FPR flag
3326 }
3327
3328 def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3329 let Inst{31} = 1; // 64-bit GPR flag
3330 let Inst{22} = 1; // 64-bit FPR flag
3331 }
3332
3333 def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3334 asm#".d"> {
3335 let Inst{31} = 1;
3336 let Inst{22} = 0;
3337 }
3338
3339 def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3340 asm#".d"> {
3341 let Inst{31} = 1;
3342 let Inst{22} = 0;
3343 }
3344
3345 def : InstAlias<asm#"$Vd.d[1], $Rn",
3346 (!cast<Instruction>(NAME#XDHighr) V128:$Vd, GPR64:$Rn), 0>;
3347 def : InstAlias<asm#"$Rd, $Vn.d[1]",
3348 (!cast<Instruction>(NAME#DXHighr) GPR64:$Rd, V128:$Vn), 0>;
3349}
3350
3351//---
3352// Floating point conversion
3353//---
3354
3355class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3356 RegisterClass srcType, string asm, list<dag> pattern>
3357 : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3358 Sched<[WriteFCvt]> {
3359 bits<5> Rd;
3360 bits<5> Rn;
3361 let Inst{31-24} = 0b00011110;
3362 let Inst{23-22} = type;
3363 let Inst{21-17} = 0b10001;
3364 let Inst{16-15} = opcode;
3365 let Inst{14-10} = 0b10000;
3366 let Inst{9-5} = Rn;
3367 let Inst{4-0} = Rd;
3368}
3369
3370multiclass FPConversion<string asm> {
3371 // Double-precision to Half-precision
3372 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3373 def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, []>;
3374
3375 // Double-precision to Single-precision
3376 def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3377 [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3378
3379 // Half-precision to Double-precision
3380 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3381 def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, []>;
3382
3383 // Half-precision to Single-precision
3384 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3385 def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, []>;
3386
3387 // Single-precision to Double-precision
3388 def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3389 [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3390
3391 // Single-precision to Half-precision
3392 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3393 def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, []>;
3394}
3395
3396//---
3397// Single operand floating point data processing
3398//---
3399
3400let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3401class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3402 ValueType vt, string asm, SDPatternOperator node>
3403 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3404 [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3405 Sched<[WriteF]> {
3406 bits<5> Rd;
3407 bits<5> Rn;
3408 let Inst{31-23} = 0b000111100;
3409 let Inst{21-19} = 0b100;
3410 let Inst{18-15} = opcode;
3411 let Inst{14-10} = 0b10000;
3412 let Inst{9-5} = Rn;
3413 let Inst{4-0} = Rd;
3414}
3415
3416multiclass SingleOperandFPData<bits<4> opcode, string asm,
3417 SDPatternOperator node = null_frag> {
3418 def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3419 let Inst{22} = 0; // 32-bit size flag
3420 }
3421
3422 def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3423 let Inst{22} = 1; // 64-bit size flag
3424 }
3425}
3426
3427//---
3428// Two operand floating point data processing
3429//---
3430
3431let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3432class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3433 string asm, list<dag> pat>
3434 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3435 asm, "\t$Rd, $Rn, $Rm", "", pat>,
3436 Sched<[WriteF]> {
3437 bits<5> Rd;
3438 bits<5> Rn;
3439 bits<5> Rm;
3440 let Inst{31-23} = 0b000111100;
3441 let Inst{21} = 1;
3442 let Inst{20-16} = Rm;
3443 let Inst{15-12} = opcode;
3444 let Inst{11-10} = 0b10;
3445 let Inst{9-5} = Rn;
3446 let Inst{4-0} = Rd;
3447}
3448
3449multiclass TwoOperandFPData<bits<4> opcode, string asm,
3450 SDPatternOperator node = null_frag> {
3451 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3452 [(set (f32 FPR32:$Rd),
3453 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3454 let Inst{22} = 0; // 32-bit size flag
3455 }
3456
3457 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3458 [(set (f64 FPR64:$Rd),
3459 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3460 let Inst{22} = 1; // 64-bit size flag
3461 }
3462}
3463
3464multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3465 def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3466 [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3467 let Inst{22} = 0; // 32-bit size flag
3468 }
3469
3470 def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3471 [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3472 let Inst{22} = 1; // 64-bit size flag
3473 }
3474}
3475
3476
3477//---
3478// Three operand floating point data processing
3479//---
3480
3481class BaseThreeOperandFPData<bit isNegated, bit isSub,
3482 RegisterClass regtype, string asm, list<dag> pat>
3483 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3484 asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3485 Sched<[WriteFMul]> {
3486 bits<5> Rd;
3487 bits<5> Rn;
3488 bits<5> Rm;
3489 bits<5> Ra;
3490 let Inst{31-23} = 0b000111110;
3491 let Inst{21} = isNegated;
3492 let Inst{20-16} = Rm;
3493 let Inst{15} = isSub;
3494 let Inst{14-10} = Ra;
3495 let Inst{9-5} = Rn;
3496 let Inst{4-0} = Rd;
3497}
3498
3499multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3500 SDPatternOperator node> {
3501 def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3502 [(set FPR32:$Rd,
3503 (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3504 let Inst{22} = 0; // 32-bit size flag
3505 }
3506
3507 def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3508 [(set FPR64:$Rd,
3509 (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3510 let Inst{22} = 1; // 64-bit size flag
3511 }
3512}
3513
3514//---
3515// Floating point data comparisons
3516//---
3517
3518let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3519class BaseOneOperandFPComparison<bit signalAllNans,
3520 RegisterClass regtype, string asm,
3521 list<dag> pat>
3522 : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3523 Sched<[WriteFCmp]> {
3524 bits<5> Rn;
3525 let Inst{31-23} = 0b000111100;
3526 let Inst{21} = 1;
3527
Tim Northover00ed9962014-03-29 10:18:08 +00003528 let Inst{15-10} = 0b001000;
3529 let Inst{9-5} = Rn;
3530 let Inst{4} = signalAllNans;
3531 let Inst{3-0} = 0b1000;
Bradley Smith5511f082014-04-09 14:43:40 +00003532
3533 // Rm should be 0b00000 canonically, but we need to accept any value.
3534 let PostEncoderMethod = "fixOneOperandFPComparison";
Tim Northover00ed9962014-03-29 10:18:08 +00003535}
3536
3537let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3538class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3539 string asm, list<dag> pat>
3540 : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3541 Sched<[WriteFCmp]> {
3542 bits<5> Rm;
3543 bits<5> Rn;
3544 let Inst{31-23} = 0b000111100;
3545 let Inst{21} = 1;
3546 let Inst{20-16} = Rm;
3547 let Inst{15-10} = 0b001000;
3548 let Inst{9-5} = Rn;
3549 let Inst{4} = signalAllNans;
3550 let Inst{3-0} = 0b0000;
3551}
3552
3553multiclass FPComparison<bit signalAllNans, string asm,
3554 SDPatternOperator OpNode = null_frag> {
3555 let Defs = [CPSR] in {
3556 def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3557 [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3558 let Inst{22} = 0;
3559 }
3560
3561 def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3562 [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3563 let Inst{22} = 0;
3564 }
3565
3566 def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3567 [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3568 let Inst{22} = 1;
3569 }
3570
3571 def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3572 [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3573 let Inst{22} = 1;
3574 }
3575 } // Defs = [CPSR]
3576}
3577
3578//---
3579// Floating point conditional comparisons
3580//---
3581
3582let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3583class BaseFPCondComparison<bit signalAllNans,
3584 RegisterClass regtype, string asm>
3585 : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3586 asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3587 Sched<[WriteFCmp]> {
3588 bits<5> Rn;
3589 bits<5> Rm;
3590 bits<4> nzcv;
3591 bits<4> cond;
3592
3593 let Inst{31-23} = 0b000111100;
3594 let Inst{21} = 1;
3595 let Inst{20-16} = Rm;
3596 let Inst{15-12} = cond;
3597 let Inst{11-10} = 0b01;
3598 let Inst{9-5} = Rn;
3599 let Inst{4} = signalAllNans;
3600 let Inst{3-0} = nzcv;
3601}
3602
3603multiclass FPCondComparison<bit signalAllNans, string asm> {
3604 let Defs = [CPSR], Uses = [CPSR] in {
3605 def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3606 let Inst{22} = 0;
3607 }
3608
3609 def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3610 let Inst{22} = 1;
3611 }
3612 } // Defs = [CPSR], Uses = [CPSR]
3613}
3614
3615//---
3616// Floating point conditional select
3617//---
3618
3619class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3620 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3621 asm, "\t$Rd, $Rn, $Rm, $cond", "",
3622 [(set regtype:$Rd,
3623 (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3624 (i32 imm:$cond), CPSR))]>,
3625 Sched<[WriteF]> {
3626 bits<5> Rd;
3627 bits<5> Rn;
3628 bits<5> Rm;
3629 bits<4> cond;
3630
3631 let Inst{31-23} = 0b000111100;
3632 let Inst{21} = 1;
3633 let Inst{20-16} = Rm;
3634 let Inst{15-12} = cond;
3635 let Inst{11-10} = 0b11;
3636 let Inst{9-5} = Rn;
3637 let Inst{4-0} = Rd;
3638}
3639
3640multiclass FPCondSelect<string asm> {
3641 let Uses = [CPSR] in {
3642 def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3643 let Inst{22} = 0;
3644 }
3645
3646 def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3647 let Inst{22} = 1;
3648 }
3649 } // Uses = [CPSR]
3650}
3651
3652//---
3653// Floating move immediate
3654//---
3655
3656class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3657 : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3658 [(set regtype:$Rd, fpimmtype:$imm)]>,
3659 Sched<[WriteFImm]> {
3660 bits<5> Rd;
3661 bits<8> imm;
3662 let Inst{31-23} = 0b000111100;
3663 let Inst{21} = 1;
3664 let Inst{20-13} = imm;
3665 let Inst{12-5} = 0b10000000;
3666 let Inst{4-0} = Rd;
3667}
3668
3669multiclass FPMoveImmediate<string asm> {
3670 def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3671 let Inst{22} = 0;
3672 }
3673
3674 def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3675 let Inst{22} = 1;
3676 }
3677}
3678
3679//----------------------------------------------------------------------------
3680// AdvSIMD
3681//----------------------------------------------------------------------------
3682
3683def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3684def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3685def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3686def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3687def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3688 return ((uint64_t)Imm) < 16;
3689}]> {
3690 let ParserMatchClass = VectorIndexBOperand;
3691 let PrintMethod = "printVectorIndex";
3692 let MIOperandInfo = (ops i64imm);
3693}
3694def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3695 return ((uint64_t)Imm) < 8;
3696}]> {
3697 let ParserMatchClass = VectorIndexHOperand;
3698 let PrintMethod = "printVectorIndex";
3699 let MIOperandInfo = (ops i64imm);
3700}
3701def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3702 return ((uint64_t)Imm) < 4;
3703}]> {
3704 let ParserMatchClass = VectorIndexSOperand;
3705 let PrintMethod = "printVectorIndex";
3706 let MIOperandInfo = (ops i64imm);
3707}
3708def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3709 return ((uint64_t)Imm) < 2;
3710}]> {
3711 let ParserMatchClass = VectorIndexDOperand;
3712 let PrintMethod = "printVectorIndex";
3713 let MIOperandInfo = (ops i64imm);
3714}
3715
3716//----------------------------------------------------------------------------
3717// AdvSIMD three register vector instructions
3718//----------------------------------------------------------------------------
3719
3720let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3721class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3722 RegisterOperand regtype, string asm, string kind,
3723 list<dag> pattern>
3724 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3725 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3726 "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3727 Sched<[WriteV]> {
3728 bits<5> Rd;
3729 bits<5> Rn;
3730 bits<5> Rm;
3731 let Inst{31} = 0;
3732 let Inst{30} = Q;
3733 let Inst{29} = U;
3734 let Inst{28-24} = 0b01110;
3735 let Inst{23-22} = size;
3736 let Inst{21} = 1;
3737 let Inst{20-16} = Rm;
3738 let Inst{15-11} = opcode;
3739 let Inst{10} = 1;
3740 let Inst{9-5} = Rn;
3741 let Inst{4-0} = Rd;
3742}
3743
3744let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3745class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3746 RegisterOperand regtype, string asm, string kind,
3747 list<dag> pattern>
3748 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3749 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3750 "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3751 Sched<[WriteV]> {
3752 bits<5> Rd;
3753 bits<5> Rn;
3754 bits<5> Rm;
3755 let Inst{31} = 0;
3756 let Inst{30} = Q;
3757 let Inst{29} = U;
3758 let Inst{28-24} = 0b01110;
3759 let Inst{23-22} = size;
3760 let Inst{21} = 1;
3761 let Inst{20-16} = Rm;
3762 let Inst{15-11} = opcode;
3763 let Inst{10} = 1;
3764 let Inst{9-5} = Rn;
3765 let Inst{4-0} = Rd;
3766}
3767
3768// All operand sizes distinguished in the encoding.
3769multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3770 SDPatternOperator OpNode> {
3771 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3772 asm, ".8b",
3773 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3774 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3775 asm, ".16b",
3776 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3777 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3778 asm, ".4h",
3779 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3780 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3781 asm, ".8h",
3782 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3783 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3784 asm, ".2s",
3785 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3786 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3787 asm, ".4s",
3788 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3789 def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3790 asm, ".2d",
3791 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3792}
3793
3794// As above, but D sized elements unsupported.
3795multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3796 SDPatternOperator OpNode> {
3797 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3798 asm, ".8b",
3799 [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3800 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3801 asm, ".16b",
3802 [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3803 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3804 asm, ".4h",
3805 [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3806 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3807 asm, ".8h",
3808 [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3809 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3810 asm, ".2s",
3811 [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3812 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3813 asm, ".4s",
3814 [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3815}
3816
3817multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3818 SDPatternOperator OpNode> {
3819 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3820 asm, ".8b",
3821 [(set (v8i8 V64:$dst),
3822 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3823 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3824 asm, ".16b",
3825 [(set (v16i8 V128:$dst),
3826 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3827 def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3828 asm, ".4h",
3829 [(set (v4i16 V64:$dst),
3830 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3831 def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3832 asm, ".8h",
3833 [(set (v8i16 V128:$dst),
3834 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3835 def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3836 asm, ".2s",
3837 [(set (v2i32 V64:$dst),
3838 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3839 def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3840 asm, ".4s",
3841 [(set (v4i32 V128:$dst),
3842 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3843}
3844
3845// As above, but only B sized elements supported.
3846multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3847 SDPatternOperator OpNode> {
3848 def v8i8 : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3849 asm, ".8b",
3850 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3851 def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3852 asm, ".16b",
3853 [(set (v16i8 V128:$Rd),
3854 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3855}
3856
3857// As above, but only S and D sized floating point elements supported.
3858multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3859 string asm, SDPatternOperator OpNode> {
3860 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3861 asm, ".2s",
3862 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3863 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3864 asm, ".4s",
3865 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3866 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3867 asm, ".2d",
3868 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3869}
3870
3871multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3872 string asm,
3873 SDPatternOperator OpNode> {
3874 def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3875 asm, ".2s",
3876 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3877 def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3878 asm, ".4s",
3879 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3880 def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3881 asm, ".2d",
3882 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3883}
3884
3885multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3886 string asm, SDPatternOperator OpNode> {
3887 def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3888 asm, ".2s",
3889 [(set (v2f32 V64:$dst),
3890 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3891 def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3892 asm, ".4s",
3893 [(set (v4f32 V128:$dst),
3894 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3895 def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3896 asm, ".2d",
3897 [(set (v2f64 V128:$dst),
3898 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3899}
3900
3901// As above, but D and B sized elements unsupported.
3902multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3903 SDPatternOperator OpNode> {
3904 def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3905 asm, ".4h",
3906 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3907 def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3908 asm, ".8h",
3909 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3910 def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3911 asm, ".2s",
3912 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3913 def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3914 asm, ".4s",
3915 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3916}
3917
3918// Logical three vector ops share opcode bits, and only use B sized elements.
3919multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3920 SDPatternOperator OpNode = null_frag> {
3921 def v8i8 : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3922 asm, ".8b",
3923 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3924 def v16i8 : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3925 asm, ".16b",
3926 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3927
3928 def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3929 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3930 def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3931 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3932 def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3933 (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3934
3935 def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3936 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3937 def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3938 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3939 def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3940 (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3941}
3942
3943multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3944 string asm, SDPatternOperator OpNode> {
3945 def v8i8 : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3946 asm, ".8b",
3947 [(set (v8i8 V64:$dst),
3948 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3949 def v16i8 : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3950 asm, ".16b",
3951 [(set (v16i8 V128:$dst),
3952 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3953 (v16i8 V128:$Rm)))]>;
3954
3955 def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3956 (v4i16 V64:$RHS))),
3957 (!cast<Instruction>(NAME#"v8i8")
3958 V64:$LHS, V64:$MHS, V64:$RHS)>;
3959 def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3960 (v2i32 V64:$RHS))),
3961 (!cast<Instruction>(NAME#"v8i8")
3962 V64:$LHS, V64:$MHS, V64:$RHS)>;
3963 def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3964 (v1i64 V64:$RHS))),
3965 (!cast<Instruction>(NAME#"v8i8")
3966 V64:$LHS, V64:$MHS, V64:$RHS)>;
3967
3968 def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3969 (v8i16 V128:$RHS))),
3970 (!cast<Instruction>(NAME#"v16i8")
3971 V128:$LHS, V128:$MHS, V128:$RHS)>;
3972 def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
3973 (v4i32 V128:$RHS))),
3974 (!cast<Instruction>(NAME#"v16i8")
3975 V128:$LHS, V128:$MHS, V128:$RHS)>;
3976 def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
3977 (v2i64 V128:$RHS))),
3978 (!cast<Instruction>(NAME#"v16i8")
3979 V128:$LHS, V128:$MHS, V128:$RHS)>;
3980}
3981
3982
3983//----------------------------------------------------------------------------
3984// AdvSIMD two register vector instructions.
3985//----------------------------------------------------------------------------
3986
3987let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3988class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3989 RegisterOperand regtype, string asm, string dstkind,
3990 string srckind, list<dag> pattern>
3991 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
3992 "{\t$Rd" # dstkind # ", $Rn" # srckind #
3993 "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
3994 Sched<[WriteV]> {
3995 bits<5> Rd;
3996 bits<5> Rn;
3997 let Inst{31} = 0;
3998 let Inst{30} = Q;
3999 let Inst{29} = U;
4000 let Inst{28-24} = 0b01110;
4001 let Inst{23-22} = size;
4002 let Inst{21-17} = 0b10000;
4003 let Inst{16-12} = opcode;
4004 let Inst{11-10} = 0b10;
4005 let Inst{9-5} = Rn;
4006 let Inst{4-0} = Rd;
4007}
4008
4009let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4010class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4011 RegisterOperand regtype, string asm, string dstkind,
4012 string srckind, list<dag> pattern>
4013 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4014 "{\t$Rd" # dstkind # ", $Rn" # srckind #
4015 "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4016 Sched<[WriteV]> {
4017 bits<5> Rd;
4018 bits<5> Rn;
4019 let Inst{31} = 0;
4020 let Inst{30} = Q;
4021 let Inst{29} = U;
4022 let Inst{28-24} = 0b01110;
4023 let Inst{23-22} = size;
4024 let Inst{21-17} = 0b10000;
4025 let Inst{16-12} = opcode;
4026 let Inst{11-10} = 0b10;
4027 let Inst{9-5} = Rn;
4028 let Inst{4-0} = Rd;
4029}
4030
4031// Supports B, H, and S element sizes.
4032multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4033 SDPatternOperator OpNode> {
4034 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4035 asm, ".8b", ".8b",
4036 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4037 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4038 asm, ".16b", ".16b",
4039 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4040 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4041 asm, ".4h", ".4h",
4042 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4043 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4044 asm, ".8h", ".8h",
4045 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4046 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4047 asm, ".2s", ".2s",
4048 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4049 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4050 asm, ".4s", ".4s",
4051 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4052}
4053
4054class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4055 RegisterOperand regtype, string asm, string dstkind,
4056 string srckind, string amount>
4057 : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4058 "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4059 "|" # dstkind # "\t$Rd, $Rn, #" # amount # "}", "", []>,
4060 Sched<[WriteV]> {
4061 bits<5> Rd;
4062 bits<5> Rn;
4063 let Inst{31} = 0;
4064 let Inst{30} = Q;
4065 let Inst{29-24} = 0b101110;
4066 let Inst{23-22} = size;
4067 let Inst{21-10} = 0b100001001110;
4068 let Inst{9-5} = Rn;
4069 let Inst{4-0} = Rd;
4070}
4071
4072multiclass SIMDVectorLShiftLongBySizeBHS {
4073 let neverHasSideEffects = 1 in {
4074 def v8i8 : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4075 "shll", ".8h", ".8b", "8">;
4076 def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4077 "shll2", ".8h", ".16b", "8">;
4078 def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4079 "shll", ".4s", ".4h", "16">;
4080 def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4081 "shll2", ".4s", ".8h", "16">;
4082 def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4083 "shll", ".2d", ".2s", "32">;
4084 def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4085 "shll2", ".2d", ".4s", "32">;
4086 }
4087}
4088
4089// Supports all element sizes.
4090multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4091 SDPatternOperator OpNode> {
4092 def v8i8_v4i16 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4093 asm, ".4h", ".8b",
4094 [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4095 def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4096 asm, ".8h", ".16b",
4097 [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4098 def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4099 asm, ".2s", ".4h",
4100 [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4101 def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4102 asm, ".4s", ".8h",
4103 [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4104 def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4105 asm, ".1d", ".2s",
4106 [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4107 def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4108 asm, ".2d", ".4s",
4109 [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4110}
4111
4112multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4113 SDPatternOperator OpNode> {
4114 def v8i8_v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4115 asm, ".4h", ".8b",
4116 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4117 (v8i8 V64:$Rn)))]>;
4118 def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4119 asm, ".8h", ".16b",
4120 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4121 (v16i8 V128:$Rn)))]>;
4122 def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4123 asm, ".2s", ".4h",
4124 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4125 (v4i16 V64:$Rn)))]>;
4126 def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4127 asm, ".4s", ".8h",
4128 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4129 (v8i16 V128:$Rn)))]>;
4130 def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4131 asm, ".1d", ".2s",
4132 [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4133 (v2i32 V64:$Rn)))]>;
4134 def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4135 asm, ".2d", ".4s",
4136 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4137 (v4i32 V128:$Rn)))]>;
4138}
4139
4140// Supports all element sizes, except 1xD.
4141multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4142 SDPatternOperator OpNode> {
4143 def v8i8 : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4144 asm, ".8b", ".8b",
4145 [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4146 def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4147 asm, ".16b", ".16b",
4148 [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4149 def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4150 asm, ".4h", ".4h",
4151 [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4152 def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4153 asm, ".8h", ".8h",
4154 [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4155 def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4156 asm, ".2s", ".2s",
4157 [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4158 def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4159 asm, ".4s", ".4s",
4160 [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4161 def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4162 asm, ".2d", ".2d",
4163 [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4164}
4165
4166multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4167 SDPatternOperator OpNode = null_frag> {
4168 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4169 asm, ".8b", ".8b",
4170 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4171 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4172 asm, ".16b", ".16b",
4173 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4174 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4175 asm, ".4h", ".4h",
4176 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4177 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4178 asm, ".8h", ".8h",
4179 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4180 def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4181 asm, ".2s", ".2s",
4182 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4183 def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4184 asm, ".4s", ".4s",
4185 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4186 def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4187 asm, ".2d", ".2d",
4188 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4189}
4190
4191
4192// Supports only B element sizes.
4193multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4194 SDPatternOperator OpNode> {
4195 def v8i8 : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4196 asm, ".8b", ".8b",
4197 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4198 def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4199 asm, ".16b", ".16b",
4200 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4201
4202}
4203
4204// Supports only B and H element sizes.
4205multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4206 SDPatternOperator OpNode> {
4207 def v8i8 : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4208 asm, ".8b", ".8b",
4209 [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4210 def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4211 asm, ".16b", ".16b",
4212 [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4213 def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4214 asm, ".4h", ".4h",
4215 [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4216 def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4217 asm, ".8h", ".8h",
4218 [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4219}
4220
4221// Supports only S and D element sizes, uses high bit of the size field
4222// as an extra opcode bit.
4223multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4224 SDPatternOperator OpNode> {
4225 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4226 asm, ".2s", ".2s",
4227 [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4228 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4229 asm, ".4s", ".4s",
4230 [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4231 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4232 asm, ".2d", ".2d",
4233 [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4234}
4235
4236// Supports only S element size.
4237multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4238 SDPatternOperator OpNode> {
4239 def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4240 asm, ".2s", ".2s",
4241 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4242 def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4243 asm, ".4s", ".4s",
4244 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4245}
4246
4247
4248multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4249 SDPatternOperator OpNode> {
4250 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4251 asm, ".2s", ".2s",
4252 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4253 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4254 asm, ".4s", ".4s",
4255 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4256 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4257 asm, ".2d", ".2d",
4258 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4259}
4260
4261multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4262 SDPatternOperator OpNode> {
4263 def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4264 asm, ".2s", ".2s",
4265 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4266 def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4267 asm, ".4s", ".4s",
4268 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4269 def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4270 asm, ".2d", ".2d",
4271 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4272}
4273
4274
4275class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4276 RegisterOperand inreg, RegisterOperand outreg,
4277 string asm, string outkind, string inkind,
4278 list<dag> pattern>
4279 : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4280 "{\t$Rd" # outkind # ", $Rn" # inkind #
4281 "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4282 Sched<[WriteV]> {
4283 bits<5> Rd;
4284 bits<5> Rn;
4285 let Inst{31} = 0;
4286 let Inst{30} = Q;
4287 let Inst{29} = U;
4288 let Inst{28-24} = 0b01110;
4289 let Inst{23-22} = size;
4290 let Inst{21-17} = 0b10000;
4291 let Inst{16-12} = opcode;
4292 let Inst{11-10} = 0b10;
4293 let Inst{9-5} = Rn;
4294 let Inst{4-0} = Rd;
4295}
4296
4297class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4298 RegisterOperand inreg, RegisterOperand outreg,
4299 string asm, string outkind, string inkind,
4300 list<dag> pattern>
4301 : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4302 "{\t$Rd" # outkind # ", $Rn" # inkind #
4303 "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4304 Sched<[WriteV]> {
4305 bits<5> Rd;
4306 bits<5> Rn;
4307 let Inst{31} = 0;
4308 let Inst{30} = Q;
4309 let Inst{29} = U;
4310 let Inst{28-24} = 0b01110;
4311 let Inst{23-22} = size;
4312 let Inst{21-17} = 0b10000;
4313 let Inst{16-12} = opcode;
4314 let Inst{11-10} = 0b10;
4315 let Inst{9-5} = Rn;
4316 let Inst{4-0} = Rd;
4317}
4318
4319multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4320 SDPatternOperator OpNode> {
4321 def v8i8 : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4322 asm, ".8b", ".8h",
4323 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4324 def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4325 asm#"2", ".16b", ".8h", []>;
4326 def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4327 asm, ".4h", ".4s",
4328 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4329 def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4330 asm#"2", ".8h", ".4s", []>;
4331 def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4332 asm, ".2s", ".2d",
4333 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4334 def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4335 asm#"2", ".4s", ".2d", []>;
4336
4337 def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4338 (!cast<Instruction>(NAME # "v16i8")
4339 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4340 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4341 (!cast<Instruction>(NAME # "v8i16")
4342 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4343 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4344 (!cast<Instruction>(NAME # "v4i32")
4345 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4346}
4347
4348class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4349 RegisterOperand regtype, string asm, string kind,
4350 ValueType dty, ValueType sty, SDNode OpNode>
4351 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4352 "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4353 "|" # kind # "\t$Rd, $Rn, #0}", "",
4354 [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4355 Sched<[WriteV]> {
4356 bits<5> Rd;
4357 bits<5> Rn;
4358 let Inst{31} = 0;
4359 let Inst{30} = Q;
4360 let Inst{29} = U;
4361 let Inst{28-24} = 0b01110;
4362 let Inst{23-22} = size;
4363 let Inst{21-17} = 0b10000;
4364 let Inst{16-12} = opcode;
4365 let Inst{11-10} = 0b10;
4366 let Inst{9-5} = Rn;
4367 let Inst{4-0} = Rd;
4368}
4369
4370// Comparisons support all element sizes, except 1xD.
4371multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4372 SDNode OpNode> {
4373 def v8i8rz : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4374 asm, ".8b",
4375 v8i8, v8i8, OpNode>;
4376 def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4377 asm, ".16b",
4378 v16i8, v16i8, OpNode>;
4379 def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4380 asm, ".4h",
4381 v4i16, v4i16, OpNode>;
4382 def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4383 asm, ".8h",
4384 v8i16, v8i16, OpNode>;
4385 def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4386 asm, ".2s",
4387 v2i32, v2i32, OpNode>;
4388 def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4389 asm, ".4s",
4390 v4i32, v4i32, OpNode>;
4391 def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4392 asm, ".2d",
4393 v2i64, v2i64, OpNode>;
4394}
4395
4396// FP Comparisons support only S and D element sizes.
4397multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4398 string asm, SDNode OpNode> {
4399 def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4400 asm, ".2s",
4401 v2i32, v2f32, OpNode>;
4402 def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4403 asm, ".4s",
4404 v4i32, v4f32, OpNode>;
4405 def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4406 asm, ".2d",
4407 v2i64, v2f64, OpNode>;
4408}
4409
4410let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4411class BaseSIMDFPCvtTwoVector<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:$Rd), (ins intype:$Rn), asm,
4416 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", 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
4432class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4433 RegisterOperand outtype, RegisterOperand intype,
4434 string asm, string VdTy, string VnTy,
4435 list<dag> pattern>
4436 : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4437 !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4438 Sched<[WriteV]> {
4439 bits<5> Rd;
4440 bits<5> Rn;
4441 let Inst{31} = 0;
4442 let Inst{30} = Q;
4443 let Inst{29} = U;
4444 let Inst{28-24} = 0b01110;
4445 let Inst{23-22} = size;
4446 let Inst{21-17} = 0b10000;
4447 let Inst{16-12} = opcode;
4448 let Inst{11-10} = 0b10;
4449 let Inst{9-5} = Rn;
4450 let Inst{4-0} = Rd;
4451}
4452
4453multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4454 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4455 asm, ".4s", ".4h", []>;
4456 def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4457 asm#"2", ".4s", ".8h", []>;
4458 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4459 asm, ".2d", ".2s", []>;
4460 def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4461 asm#"2", ".2d", ".4s", []>;
4462}
4463
4464multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4465 def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4466 asm, ".4h", ".4s", []>;
4467 def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4468 asm#"2", ".8h", ".4s", []>;
4469 def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4470 asm, ".2s", ".2d", []>;
4471 def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4472 asm#"2", ".4s", ".2d", []>;
4473}
4474
4475multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4476 Intrinsic OpNode> {
4477 def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4478 asm, ".2s", ".2d",
4479 [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4480 def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4481 asm#"2", ".4s", ".2d", []>;
4482
4483 def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4484 (!cast<Instruction>(NAME # "v4f32")
4485 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4486}
4487
4488//----------------------------------------------------------------------------
4489// AdvSIMD three register different-size vector instructions.
4490//----------------------------------------------------------------------------
4491
4492let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4493class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4494 RegisterOperand outtype, RegisterOperand intype1,
4495 RegisterOperand intype2, string asm,
4496 string outkind, string inkind1, string inkind2,
4497 list<dag> pattern>
4498 : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4499 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4500 "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4501 Sched<[WriteV]> {
4502 bits<5> Rd;
4503 bits<5> Rn;
4504 bits<5> Rm;
4505 let Inst{31} = 0;
4506 let Inst{30} = size{0};
4507 let Inst{29} = U;
4508 let Inst{28-24} = 0b01110;
4509 let Inst{23-22} = size{2-1};
4510 let Inst{21} = 1;
4511 let Inst{20-16} = Rm;
4512 let Inst{15-12} = opcode;
4513 let Inst{11-10} = 0b00;
4514 let Inst{9-5} = Rn;
4515 let Inst{4-0} = Rd;
4516}
4517
4518let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4519class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4520 RegisterOperand outtype, RegisterOperand intype1,
4521 RegisterOperand intype2, string asm,
4522 string outkind, string inkind1, string inkind2,
4523 list<dag> pattern>
4524 : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4525 "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4526 "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4527 Sched<[WriteV]> {
4528 bits<5> Rd;
4529 bits<5> Rn;
4530 bits<5> Rm;
4531 let Inst{31} = 0;
4532 let Inst{30} = size{0};
4533 let Inst{29} = U;
4534 let Inst{28-24} = 0b01110;
4535 let Inst{23-22} = size{2-1};
4536 let Inst{21} = 1;
4537 let Inst{20-16} = Rm;
4538 let Inst{15-12} = opcode;
4539 let Inst{11-10} = 0b00;
4540 let Inst{9-5} = Rn;
4541 let Inst{4-0} = Rd;
4542}
4543
4544// FIXME: TableGen doesn't know how to deal with expanded types that also
4545// change the element count (in this case, placing the results in
4546// the high elements of the result register rather than the low
4547// elements). Until that's fixed, we can't code-gen those.
4548multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4549 Intrinsic IntOp> {
4550 def v8i16_v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4551 V64, V128, V128,
4552 asm, ".8b", ".8h", ".8h",
4553 [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4554 def v8i16_v16i8 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4555 V128, V128, V128,
4556 asm#"2", ".16b", ".8h", ".8h",
4557 []>;
4558 def v4i32_v4i16 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4559 V64, V128, V128,
4560 asm, ".4h", ".4s", ".4s",
4561 [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4562 def v4i32_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4563 V128, V128, V128,
4564 asm#"2", ".8h", ".4s", ".4s",
4565 []>;
4566 def v2i64_v2i32 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4567 V64, V128, V128,
4568 asm, ".2s", ".2d", ".2d",
4569 [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4570 def v2i64_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4571 V128, V128, V128,
4572 asm#"2", ".4s", ".2d", ".2d",
4573 []>;
4574
4575
4576 // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4577 // a version attached to an instruction.
4578 def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4579 (v8i16 V128:$Rm))),
4580 (!cast<Instruction>(NAME # "v8i16_v16i8")
4581 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4582 V128:$Rn, V128:$Rm)>;
4583 def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4584 (v4i32 V128:$Rm))),
4585 (!cast<Instruction>(NAME # "v4i32_v8i16")
4586 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4587 V128:$Rn, V128:$Rm)>;
4588 def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4589 (v2i64 V128:$Rm))),
4590 (!cast<Instruction>(NAME # "v2i64_v4i32")
4591 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4592 V128:$Rn, V128:$Rm)>;
4593}
4594
4595multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4596 Intrinsic IntOp> {
4597 def v8i8 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4598 V128, V64, V64,
4599 asm, ".8h", ".8b", ".8b",
4600 [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4601 def v16i8 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4602 V128, V128, V128,
4603 asm#"2", ".8h", ".16b", ".16b", []>;
4604 def v1i64 : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4605 V128, V64, V64,
4606 asm, ".1q", ".1d", ".1d", []>;
4607 def v2i64 : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4608 V128, V128, V128,
4609 asm#"2", ".1q", ".2d", ".2d", []>;
4610
4611 def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4612 (v8i8 (extract_high_v16i8 V128:$Rm)))),
4613 (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4614}
4615
4616multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4617 SDPatternOperator OpNode> {
4618 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4619 V128, V64, V64,
4620 asm, ".4s", ".4h", ".4h",
4621 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4622 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4623 V128, V128, V128,
4624 asm#"2", ".4s", ".8h", ".8h",
4625 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4626 (extract_high_v8i16 V128:$Rm)))]>;
4627 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4628 V128, V64, V64,
4629 asm, ".2d", ".2s", ".2s",
4630 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4631 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4632 V128, V128, V128,
4633 asm#"2", ".2d", ".4s", ".4s",
4634 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4635 (extract_high_v4i32 V128:$Rm)))]>;
4636}
4637
4638multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4639 SDPatternOperator OpNode = null_frag> {
4640 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4641 V128, V64, V64,
4642 asm, ".8h", ".8b", ".8b",
4643 [(set (v8i16 V128:$Rd),
4644 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4645 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4646 V128, V128, V128,
4647 asm#"2", ".8h", ".16b", ".16b",
4648 [(set (v8i16 V128:$Rd),
4649 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4650 (extract_high_v16i8 V128:$Rm)))))]>;
4651 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4652 V128, V64, V64,
4653 asm, ".4s", ".4h", ".4h",
4654 [(set (v4i32 V128:$Rd),
4655 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4656 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4657 V128, V128, V128,
4658 asm#"2", ".4s", ".8h", ".8h",
4659 [(set (v4i32 V128:$Rd),
4660 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4661 (extract_high_v8i16 V128:$Rm)))))]>;
4662 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4663 V128, V64, V64,
4664 asm, ".2d", ".2s", ".2s",
4665 [(set (v2i64 V128:$Rd),
4666 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4667 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4668 V128, V128, V128,
4669 asm#"2", ".2d", ".4s", ".4s",
4670 [(set (v2i64 V128:$Rd),
4671 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4672 (extract_high_v4i32 V128:$Rm)))))]>;
4673}
4674
4675multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4676 string asm,
4677 SDPatternOperator OpNode> {
4678 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4679 V128, V64, V64,
4680 asm, ".8h", ".8b", ".8b",
4681 [(set (v8i16 V128:$dst),
4682 (add (v8i16 V128:$Rd),
4683 (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4684 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4685 V128, V128, V128,
4686 asm#"2", ".8h", ".16b", ".16b",
4687 [(set (v8i16 V128:$dst),
4688 (add (v8i16 V128:$Rd),
4689 (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4690 (extract_high_v16i8 V128:$Rm))))))]>;
4691 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4692 V128, V64, V64,
4693 asm, ".4s", ".4h", ".4h",
4694 [(set (v4i32 V128:$dst),
4695 (add (v4i32 V128:$Rd),
4696 (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4697 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4698 V128, V128, V128,
4699 asm#"2", ".4s", ".8h", ".8h",
4700 [(set (v4i32 V128:$dst),
4701 (add (v4i32 V128:$Rd),
4702 (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4703 (extract_high_v8i16 V128:$Rm))))))]>;
4704 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4705 V128, V64, V64,
4706 asm, ".2d", ".2s", ".2s",
4707 [(set (v2i64 V128:$dst),
4708 (add (v2i64 V128:$Rd),
4709 (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4710 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4711 V128, V128, V128,
4712 asm#"2", ".2d", ".4s", ".4s",
4713 [(set (v2i64 V128:$dst),
4714 (add (v2i64 V128:$Rd),
4715 (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4716 (extract_high_v4i32 V128:$Rm))))))]>;
4717}
4718
4719multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4720 SDPatternOperator OpNode = null_frag> {
4721 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4722 V128, V64, V64,
4723 asm, ".8h", ".8b", ".8b",
4724 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4725 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4726 V128, V128, V128,
4727 asm#"2", ".8h", ".16b", ".16b",
4728 [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4729 (extract_high_v16i8 V128:$Rm)))]>;
4730 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4731 V128, V64, V64,
4732 asm, ".4s", ".4h", ".4h",
4733 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4734 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4735 V128, V128, V128,
4736 asm#"2", ".4s", ".8h", ".8h",
4737 [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4738 (extract_high_v8i16 V128:$Rm)))]>;
4739 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4740 V128, V64, V64,
4741 asm, ".2d", ".2s", ".2s",
4742 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4743 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4744 V128, V128, V128,
4745 asm#"2", ".2d", ".4s", ".4s",
4746 [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4747 (extract_high_v4i32 V128:$Rm)))]>;
4748}
4749
4750multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4751 string asm,
4752 SDPatternOperator OpNode> {
4753 def v8i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4754 V128, V64, V64,
4755 asm, ".8h", ".8b", ".8b",
4756 [(set (v8i16 V128:$dst),
4757 (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4758 def v16i8_v8i16 : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4759 V128, V128, V128,
4760 asm#"2", ".8h", ".16b", ".16b",
4761 [(set (v8i16 V128:$dst),
4762 (OpNode (v8i16 V128:$Rd),
4763 (extract_high_v16i8 V128:$Rn),
4764 (extract_high_v16i8 V128:$Rm)))]>;
4765 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4766 V128, V64, V64,
4767 asm, ".4s", ".4h", ".4h",
4768 [(set (v4i32 V128:$dst),
4769 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4770 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4771 V128, V128, V128,
4772 asm#"2", ".4s", ".8h", ".8h",
4773 [(set (v4i32 V128:$dst),
4774 (OpNode (v4i32 V128:$Rd),
4775 (extract_high_v8i16 V128:$Rn),
4776 (extract_high_v8i16 V128:$Rm)))]>;
4777 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4778 V128, V64, V64,
4779 asm, ".2d", ".2s", ".2s",
4780 [(set (v2i64 V128:$dst),
4781 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4782 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4783 V128, V128, V128,
4784 asm#"2", ".2d", ".4s", ".4s",
4785 [(set (v2i64 V128:$dst),
4786 (OpNode (v2i64 V128:$Rd),
4787 (extract_high_v4i32 V128:$Rn),
4788 (extract_high_v4i32 V128:$Rm)))]>;
4789}
4790
4791multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4792 SDPatternOperator Accum> {
4793 def v4i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4794 V128, V64, V64,
4795 asm, ".4s", ".4h", ".4h",
4796 [(set (v4i32 V128:$dst),
4797 (Accum (v4i32 V128:$Rd),
4798 (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4799 (v4i16 V64:$Rm)))))]>;
4800 def v8i16_v4i32 : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4801 V128, V128, V128,
4802 asm#"2", ".4s", ".8h", ".8h",
4803 [(set (v4i32 V128:$dst),
4804 (Accum (v4i32 V128:$Rd),
4805 (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4806 (extract_high_v8i16 V128:$Rm)))))]>;
4807 def v2i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4808 V128, V64, V64,
4809 asm, ".2d", ".2s", ".2s",
4810 [(set (v2i64 V128:$dst),
4811 (Accum (v2i64 V128:$Rd),
4812 (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4813 (v2i32 V64:$Rm)))))]>;
4814 def v4i32_v2i64 : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4815 V128, V128, V128,
4816 asm#"2", ".2d", ".4s", ".4s",
4817 [(set (v2i64 V128:$dst),
4818 (Accum (v2i64 V128:$Rd),
4819 (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4820 (extract_high_v4i32 V128:$Rm)))))]>;
4821}
4822
4823multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4824 SDPatternOperator OpNode> {
4825 def v8i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4826 V128, V128, V64,
4827 asm, ".8h", ".8h", ".8b",
4828 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4829 def v16i8_v8i16 : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4830 V128, V128, V128,
4831 asm#"2", ".8h", ".8h", ".16b",
4832 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4833 (extract_high_v16i8 V128:$Rm)))]>;
4834 def v4i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4835 V128, V128, V64,
4836 asm, ".4s", ".4s", ".4h",
4837 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4838 def v8i16_v4i32 : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4839 V128, V128, V128,
4840 asm#"2", ".4s", ".4s", ".8h",
4841 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4842 (extract_high_v8i16 V128:$Rm)))]>;
4843 def v2i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4844 V128, V128, V64,
4845 asm, ".2d", ".2d", ".2s",
4846 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4847 def v4i32_v2i64 : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4848 V128, V128, V128,
4849 asm#"2", ".2d", ".2d", ".4s",
4850 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4851 (extract_high_v4i32 V128:$Rm)))]>;
4852}
4853
4854//----------------------------------------------------------------------------
4855// AdvSIMD bitwise extract from vector
4856//----------------------------------------------------------------------------
4857
4858class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4859 string asm, string kind>
4860 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4861 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4862 "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4863 [(set (vty regtype:$Rd),
4864 (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4865 Sched<[WriteV]> {
4866 bits<5> Rd;
4867 bits<5> Rn;
4868 bits<5> Rm;
4869 bits<4> imm;
4870 let Inst{31} = 0;
4871 let Inst{30} = size;
4872 let Inst{29-21} = 0b101110000;
4873 let Inst{20-16} = Rm;
4874 let Inst{15} = 0;
4875 let Inst{14-11} = imm;
4876 let Inst{10} = 0;
4877 let Inst{9-5} = Rn;
4878 let Inst{4-0} = Rd;
4879}
4880
4881
4882multiclass SIMDBitwiseExtract<string asm> {
Bradley Smithdb7b9b12014-04-09 14:43:31 +00004883 def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4884 let imm{3} = 0;
4885 }
Tim Northover00ed9962014-03-29 10:18:08 +00004886 def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4887}
4888
4889//----------------------------------------------------------------------------
4890// AdvSIMD zip vector
4891//----------------------------------------------------------------------------
4892
4893class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4894 string asm, string kind, SDNode OpNode, ValueType valty>
4895 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4896 "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4897 "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4898 [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4899 Sched<[WriteV]> {
4900 bits<5> Rd;
4901 bits<5> Rn;
4902 bits<5> Rm;
4903 let Inst{31} = 0;
4904 let Inst{30} = size{0};
4905 let Inst{29-24} = 0b001110;
4906 let Inst{23-22} = size{2-1};
4907 let Inst{21} = 0;
4908 let Inst{20-16} = Rm;
4909 let Inst{15} = 0;
4910 let Inst{14-12} = opc;
4911 let Inst{11-10} = 0b10;
4912 let Inst{9-5} = Rn;
4913 let Inst{4-0} = Rd;
4914}
4915
4916multiclass SIMDZipVector<bits<3>opc, string asm,
4917 SDNode OpNode> {
4918 def v8i8 : BaseSIMDZipVector<0b000, opc, V64,
4919 asm, ".8b", OpNode, v8i8>;
4920 def v16i8 : BaseSIMDZipVector<0b001, opc, V128,
4921 asm, ".16b", OpNode, v16i8>;
4922 def v4i16 : BaseSIMDZipVector<0b010, opc, V64,
4923 asm, ".4h", OpNode, v4i16>;
4924 def v8i16 : BaseSIMDZipVector<0b011, opc, V128,
4925 asm, ".8h", OpNode, v8i16>;
4926 def v2i32 : BaseSIMDZipVector<0b100, opc, V64,
4927 asm, ".2s", OpNode, v2i32>;
4928 def v4i32 : BaseSIMDZipVector<0b101, opc, V128,
4929 asm, ".4s", OpNode, v4i32>;
4930 def v2i64 : BaseSIMDZipVector<0b111, opc, V128,
4931 asm, ".2d", OpNode, v2i64>;
4932
4933 def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4934 (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4935 def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4936 (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4937 def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4938 (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4939}
4940
4941//----------------------------------------------------------------------------
4942// AdvSIMD three register scalar instructions
4943//----------------------------------------------------------------------------
4944
4945let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4946class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4947 RegisterClass regtype, string asm,
4948 list<dag> pattern>
4949 : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4950 "\t$Rd, $Rn, $Rm", "", pattern>,
4951 Sched<[WriteV]> {
4952 bits<5> Rd;
4953 bits<5> Rn;
4954 bits<5> Rm;
4955 let Inst{31-30} = 0b01;
4956 let Inst{29} = U;
4957 let Inst{28-24} = 0b11110;
4958 let Inst{23-22} = size;
4959 let Inst{21} = 1;
4960 let Inst{20-16} = Rm;
4961 let Inst{15-11} = opcode;
4962 let Inst{10} = 1;
4963 let Inst{9-5} = Rn;
4964 let Inst{4-0} = Rd;
4965}
4966
4967multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4968 SDPatternOperator OpNode> {
4969 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4970 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4971}
4972
4973multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
4974 SDPatternOperator OpNode> {
4975 def v1i64 : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4976 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4977 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
4978 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4979 def v1i8 : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
4980
4981 def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
4982 (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
4983 def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
4984 (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
4985}
4986
4987multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
4988 SDPatternOperator OpNode> {
4989 def v1i32 : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
4990 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4991 def v1i16 : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4992}
4993
4994multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
4995 SDPatternOperator OpNode = null_frag> {
4996 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4997 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4998 [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4999 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5000 [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5001 }
5002
5003 def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5004 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5005}
5006
5007multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5008 SDPatternOperator OpNode = null_frag> {
5009 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5010 def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5011 [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5012 def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5013 [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5014 }
5015
5016 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5017 (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5018}
5019
5020class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5021 dag oops, dag iops, string asm, string cstr, list<dag> pat>
5022 : I<oops, iops, asm,
5023 "\t$Rd, $Rn, $Rm", cstr, pat>,
5024 Sched<[WriteV]> {
5025 bits<5> Rd;
5026 bits<5> Rn;
5027 bits<5> Rm;
5028 let Inst{31-30} = 0b01;
5029 let Inst{29} = U;
5030 let Inst{28-24} = 0b11110;
5031 let Inst{23-22} = size;
5032 let Inst{21} = 1;
5033 let Inst{20-16} = Rm;
5034 let Inst{15-11} = opcode;
5035 let Inst{10} = 0;
5036 let Inst{9-5} = Rn;
5037 let Inst{4-0} = Rd;
5038}
5039
5040let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5041multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5042 SDPatternOperator OpNode = null_frag> {
5043 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5044 (outs FPR32:$Rd),
5045 (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5046 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5047 (outs FPR64:$Rd),
5048 (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5049 [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5050}
5051
5052let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5053multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5054 SDPatternOperator OpNode = null_frag> {
5055 def i16 : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5056 (outs FPR32:$dst),
5057 (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5058 asm, "$Rd = $dst", []>;
5059 def i32 : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5060 (outs FPR64:$dst),
5061 (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5062 asm, "$Rd = $dst",
5063 [(set (i64 FPR64:$dst),
5064 (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5065}
5066
5067//----------------------------------------------------------------------------
5068// AdvSIMD two register scalar instructions
5069//----------------------------------------------------------------------------
5070
5071let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5072class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5073 RegisterClass regtype, RegisterClass regtype2,
5074 string asm, list<dag> pat>
5075 : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5076 "\t$Rd, $Rn", "", pat>,
5077 Sched<[WriteV]> {
5078 bits<5> Rd;
5079 bits<5> Rn;
5080 let Inst{31-30} = 0b01;
5081 let Inst{29} = U;
5082 let Inst{28-24} = 0b11110;
5083 let Inst{23-22} = size;
5084 let Inst{21-17} = 0b10000;
5085 let Inst{16-12} = opcode;
5086 let Inst{11-10} = 0b10;
5087 let Inst{9-5} = Rn;
5088 let Inst{4-0} = Rd;
5089}
5090
5091let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5092class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5093 RegisterClass regtype, RegisterClass regtype2,
5094 string asm, list<dag> pat>
5095 : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5096 "\t$Rd, $Rn", "$Rd = $dst", pat>,
5097 Sched<[WriteV]> {
5098 bits<5> Rd;
5099 bits<5> Rn;
5100 let Inst{31-30} = 0b01;
5101 let Inst{29} = U;
5102 let Inst{28-24} = 0b11110;
5103 let Inst{23-22} = size;
5104 let Inst{21-17} = 0b10000;
5105 let Inst{16-12} = opcode;
5106 let Inst{11-10} = 0b10;
5107 let Inst{9-5} = Rn;
5108 let Inst{4-0} = Rd;
5109}
5110
5111
5112let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5113class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5114 RegisterClass regtype, string asm>
5115 : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5116 "\t$Rd, $Rn, #0", "", []>,
5117 Sched<[WriteV]> {
5118 bits<5> Rd;
5119 bits<5> Rn;
5120 let Inst{31-30} = 0b01;
5121 let Inst{29} = U;
5122 let Inst{28-24} = 0b11110;
5123 let Inst{23-22} = size;
5124 let Inst{21-17} = 0b10000;
5125 let Inst{16-12} = opcode;
5126 let Inst{11-10} = 0b10;
5127 let Inst{9-5} = Rn;
5128 let Inst{4-0} = Rd;
5129}
5130
5131class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5132 : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5133 [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5134 Sched<[WriteV]> {
5135 bits<5> Rd;
5136 bits<5> Rn;
5137 let Inst{31-17} = 0b011111100110000;
5138 let Inst{16-12} = opcode;
5139 let Inst{11-10} = 0b10;
5140 let Inst{9-5} = Rn;
5141 let Inst{4-0} = Rd;
5142}
5143
5144multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5145 SDPatternOperator OpNode> {
5146 def v1i64rz : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5147
5148 def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5149 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5150}
5151
5152multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5153 SDPatternOperator OpNode> {
5154 def v1i64rz : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5155 def v1i32rz : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5156
5157 def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5158 (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5159}
5160
5161multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5162 SDPatternOperator OpNode = null_frag> {
5163 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5164 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
Tim Northoverf4810362014-03-31 15:46:17 +00005165
5166 def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5167 (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005168}
5169
5170multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5171 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5172 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5173}
5174
5175multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5176 SDPatternOperator OpNode> {
5177 def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5178 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5179 def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5180 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5181}
5182
5183multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5184 SDPatternOperator OpNode = null_frag> {
5185 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5186 def v1i64 : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5187 [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5188 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5189 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5190 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5191 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5192 }
5193
5194 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5195 (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5196}
5197
Tim Northover00ed9962014-03-29 10:18:08 +00005198multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5199 Intrinsic OpNode> {
Tim Northover903814c2014-03-31 15:46:26 +00005200 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5201 def v1i64 : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5202 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5203 def v1i32 : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5204 [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5205 def v1i16 : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5206 def v1i8 : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5207 }
5208
5209 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5210 (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
Tim Northover00ed9962014-03-29 10:18:08 +00005211}
5212
5213
5214
5215let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5216multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5217 SDPatternOperator OpNode = null_frag> {
5218 def v1i32 : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5219 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5220 def v1i16 : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5221 def v1i8 : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5222}
5223
5224//----------------------------------------------------------------------------
5225// AdvSIMD scalar pairwise instructions
5226//----------------------------------------------------------------------------
5227
5228let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5229class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5230 RegisterOperand regtype, RegisterOperand vectype,
5231 string asm, string kind>
5232 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5233 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5234 Sched<[WriteV]> {
5235 bits<5> Rd;
5236 bits<5> Rn;
5237 let Inst{31-30} = 0b01;
5238 let Inst{29} = U;
5239 let Inst{28-24} = 0b11110;
5240 let Inst{23-22} = size;
5241 let Inst{21-17} = 0b11000;
5242 let Inst{16-12} = opcode;
5243 let Inst{11-10} = 0b10;
5244 let Inst{9-5} = Rn;
5245 let Inst{4-0} = Rd;
5246}
5247
5248multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5249 def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5250 asm, ".2d">;
5251}
5252
5253multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5254 def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5255 asm, ".2s">;
5256 def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5257 asm, ".2d">;
5258}
5259
5260//----------------------------------------------------------------------------
5261// AdvSIMD across lanes instructions
5262//----------------------------------------------------------------------------
5263
5264let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5265class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5266 RegisterClass regtype, RegisterOperand vectype,
5267 string asm, string kind, list<dag> pattern>
5268 : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5269 "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5270 Sched<[WriteV]> {
5271 bits<5> Rd;
5272 bits<5> Rn;
5273 let Inst{31} = 0;
5274 let Inst{30} = Q;
5275 let Inst{29} = U;
5276 let Inst{28-24} = 0b01110;
5277 let Inst{23-22} = size;
5278 let Inst{21-17} = 0b11000;
5279 let Inst{16-12} = opcode;
5280 let Inst{11-10} = 0b10;
5281 let Inst{9-5} = Rn;
5282 let Inst{4-0} = Rd;
5283}
5284
5285multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5286 string asm> {
5287 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8, V64,
5288 asm, ".8b", []>;
5289 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8, V128,
5290 asm, ".16b", []>;
5291 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5292 asm, ".4h", []>;
5293 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5294 asm, ".8h", []>;
5295 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5296 asm, ".4s", []>;
5297}
5298
5299multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5300 def v8i8v : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5301 asm, ".8b", []>;
5302 def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5303 asm, ".16b", []>;
5304 def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5305 asm, ".4h", []>;
5306 def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5307 asm, ".8h", []>;
5308 def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5309 asm, ".4s", []>;
5310}
5311
5312multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5313 Intrinsic intOp> {
5314 def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5315 asm, ".4s",
5316 [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5317}
5318
5319//----------------------------------------------------------------------------
5320// AdvSIMD INS/DUP instructions
5321//----------------------------------------------------------------------------
5322
5323// FIXME: There has got to be a better way to factor these. ugh.
5324
5325class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5326 string operands, string constraints, list<dag> pattern>
5327 : I<outs, ins, asm, operands, constraints, pattern>,
5328 Sched<[WriteV]> {
5329 bits<5> Rd;
5330 bits<5> Rn;
5331 let Inst{31} = 0;
5332 let Inst{30} = Q;
5333 let Inst{29} = op;
5334 let Inst{28-21} = 0b01110000;
5335 let Inst{15} = 0;
5336 let Inst{10} = 1;
5337 let Inst{9-5} = Rn;
5338 let Inst{4-0} = Rd;
5339}
5340
5341class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5342 RegisterOperand vecreg, RegisterClass regtype>
5343 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5344 "{\t$Rd" # size # ", $Rn" #
5345 "|" # size # "\t$Rd, $Rn}", "",
5346 [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5347 let Inst{20-16} = imm5;
5348 let Inst{14-11} = 0b0001;
5349}
5350
5351class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5352 ValueType vectype, ValueType insreg,
5353 RegisterOperand vecreg, Operand idxtype,
5354 ValueType elttype, SDNode OpNode>
5355 : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5356 "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5357 "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5358 [(set (vectype vecreg:$Rd),
5359 (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5360 let Inst{14-11} = 0b0000;
5361}
5362
5363class SIMDDup64FromElement
5364 : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5365 VectorIndexD, i64, ARM64duplane64> {
5366 bits<1> idx;
5367 let Inst{20} = idx;
5368 let Inst{19-16} = 0b1000;
5369}
5370
5371class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5372 RegisterOperand vecreg>
5373 : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5374 VectorIndexS, i64, ARM64duplane32> {
5375 bits<2> idx;
5376 let Inst{20-19} = idx;
5377 let Inst{18-16} = 0b100;
5378}
5379
5380class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5381 RegisterOperand vecreg>
5382 : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5383 VectorIndexH, i64, ARM64duplane16> {
5384 bits<3> idx;
5385 let Inst{20-18} = idx;
5386 let Inst{17-16} = 0b10;
5387}
5388
5389class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5390 RegisterOperand vecreg>
5391 : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5392 VectorIndexB, i64, ARM64duplane8> {
5393 bits<4> idx;
5394 let Inst{20-17} = idx;
5395 let Inst{16} = 1;
5396}
5397
5398class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5399 Operand idxtype, string asm, list<dag> pattern>
5400 : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5401 "{\t$Rd, $Rn" # size # "$idx" #
5402 "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5403 let Inst{14-11} = imm4;
5404}
5405
5406class SIMDSMov<bit Q, string size, RegisterClass regtype,
5407 Operand idxtype>
5408 : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5409class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5410 Operand idxtype>
5411 : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5412 [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5413
5414class SIMDMovAlias<string asm, string size, Instruction inst,
5415 RegisterClass regtype, Operand idxtype>
5416 : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5417 "|" # size # "\t$dst, $src$idx}",
5418 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5419
5420multiclass SMov {
5421 def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5422 bits<4> idx;
5423 let Inst{20-17} = idx;
5424 let Inst{16} = 1;
5425 }
5426 def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5427 bits<4> idx;
5428 let Inst{20-17} = idx;
5429 let Inst{16} = 1;
5430 }
5431 def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5432 bits<3> idx;
5433 let Inst{20-18} = idx;
5434 let Inst{17-16} = 0b10;
5435 }
5436 def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5437 bits<3> idx;
5438 let Inst{20-18} = idx;
5439 let Inst{17-16} = 0b10;
5440 }
5441 def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5442 bits<2> idx;
5443 let Inst{20-19} = idx;
5444 let Inst{18-16} = 0b100;
5445 }
5446}
5447
5448multiclass UMov {
5449 def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5450 bits<4> idx;
5451 let Inst{20-17} = idx;
5452 let Inst{16} = 1;
5453 }
5454 def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5455 bits<3> idx;
5456 let Inst{20-18} = idx;
5457 let Inst{17-16} = 0b10;
5458 }
5459 def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5460 bits<2> idx;
5461 let Inst{20-19} = idx;
5462 let Inst{18-16} = 0b100;
5463 }
5464 def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5465 bits<1> idx;
5466 let Inst{20} = idx;
5467 let Inst{19-16} = 0b1000;
5468 }
5469 def : SIMDMovAlias<"mov", ".s",
5470 !cast<Instruction>(NAME#"vi32"),
5471 GPR32, VectorIndexS>;
5472 def : SIMDMovAlias<"mov", ".d",
5473 !cast<Instruction>(NAME#"vi64"),
5474 GPR64, VectorIndexD>;
5475}
5476
5477class SIMDInsFromMain<string size, ValueType vectype,
5478 RegisterClass regtype, Operand idxtype>
5479 : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5480 (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5481 "{\t$Rd" # size # "$idx, $Rn" #
5482 "|" # size # "\t$Rd$idx, $Rn}",
5483 "$Rd = $dst",
5484 [(set V128:$dst,
5485 (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5486 let Inst{14-11} = 0b0011;
5487}
5488
5489class SIMDInsFromElement<string size, ValueType vectype,
5490 ValueType elttype, Operand idxtype>
5491 : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5492 (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5493 "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5494 "|" # size # "\t$Rd$idx, $Rn$idx2}",
5495 "$Rd = $dst",
5496 [(set V128:$dst,
5497 (vector_insert
5498 (vectype V128:$Rd),
5499 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5500 idxtype:$idx))]>;
5501
5502class SIMDInsMainMovAlias<string size, Instruction inst,
5503 RegisterClass regtype, Operand idxtype>
5504 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5505 "|" # size #"\t$dst$idx, $src}",
5506 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5507class SIMDInsElementMovAlias<string size, Instruction inst,
5508 Operand idxtype>
5509 : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5510 # "|" # size #" $dst$idx, $src$idx2}",
5511 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5512
5513
5514multiclass SIMDIns {
5515 def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5516 bits<4> idx;
5517 let Inst{20-17} = idx;
5518 let Inst{16} = 1;
5519 }
5520 def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5521 bits<3> idx;
5522 let Inst{20-18} = idx;
5523 let Inst{17-16} = 0b10;
5524 }
5525 def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5526 bits<2> idx;
5527 let Inst{20-19} = idx;
5528 let Inst{18-16} = 0b100;
5529 }
5530 def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5531 bits<1> idx;
5532 let Inst{20} = idx;
5533 let Inst{19-16} = 0b1000;
5534 }
5535
5536 def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5537 bits<4> idx;
5538 bits<4> idx2;
5539 let Inst{20-17} = idx;
5540 let Inst{16} = 1;
5541 let Inst{14-11} = idx2;
5542 }
5543 def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5544 bits<3> idx;
5545 bits<3> idx2;
5546 let Inst{20-18} = idx;
5547 let Inst{17-16} = 0b10;
5548 let Inst{14-12} = idx2;
5549 let Inst{11} = 0;
5550 }
5551 def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5552 bits<2> idx;
5553 bits<2> idx2;
5554 let Inst{20-19} = idx;
5555 let Inst{18-16} = 0b100;
5556 let Inst{14-13} = idx2;
5557 let Inst{12-11} = 0;
5558 }
5559 def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5560 bits<1> idx;
5561 bits<1> idx2;
5562 let Inst{20} = idx;
5563 let Inst{19-16} = 0b1000;
5564 let Inst{14} = idx2;
5565 let Inst{13-11} = 0;
5566 }
5567
5568 // For all forms of the INS instruction, the "mov" mnemonic is the
5569 // preferred alias. Why they didn't just call the instruction "mov" in
5570 // the first place is a very good question indeed...
5571 def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5572 GPR32, VectorIndexB>;
5573 def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5574 GPR32, VectorIndexH>;
5575 def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5576 GPR32, VectorIndexS>;
5577 def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5578 GPR64, VectorIndexD>;
5579
5580 def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5581 VectorIndexB>;
5582 def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5583 VectorIndexH>;
5584 def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5585 VectorIndexS>;
5586 def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5587 VectorIndexD>;
5588}
5589
5590//----------------------------------------------------------------------------
5591// AdvSIMD TBL/TBX
5592//----------------------------------------------------------------------------
5593
5594let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5595class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5596 RegisterOperand listtype, string asm, string kind>
5597 : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5598 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
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
5615let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5616class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5617 RegisterOperand listtype, string asm, string kind>
5618 : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5619 "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5620 Sched<[WriteV]> {
5621 bits<5> Vd;
5622 bits<5> Vn;
5623 bits<5> Vm;
5624 let Inst{31} = 0;
5625 let Inst{30} = Q;
5626 let Inst{29-21} = 0b001110000;
5627 let Inst{20-16} = Vm;
5628 let Inst{15} = 0;
5629 let Inst{14-13} = len;
5630 let Inst{12} = op;
5631 let Inst{11-10} = 0b00;
5632 let Inst{9-5} = Vn;
5633 let Inst{4-0} = Vd;
5634}
5635
5636class SIMDTableLookupAlias<string asm, Instruction inst,
5637 RegisterOperand vectype, RegisterOperand listtype>
5638 : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5639 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5640
5641multiclass SIMDTableLookup<bit op, string asm> {
5642 def v8i8One : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5643 asm, ".8b">;
5644 def v8i8Two : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5645 asm, ".8b">;
5646 def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5647 asm, ".8b">;
5648 def v8i8Four : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5649 asm, ".8b">;
5650 def v16i8One : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5651 asm, ".16b">;
5652 def v16i8Two : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5653 asm, ".16b">;
5654 def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5655 asm, ".16b">;
5656 def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5657 asm, ".16b">;
5658
5659 def : SIMDTableLookupAlias<asm # ".8b",
5660 !cast<Instruction>(NAME#"v8i8One"),
5661 V64, VecListOne128>;
5662 def : SIMDTableLookupAlias<asm # ".8b",
5663 !cast<Instruction>(NAME#"v8i8Two"),
5664 V64, VecListTwo128>;
5665 def : SIMDTableLookupAlias<asm # ".8b",
5666 !cast<Instruction>(NAME#"v8i8Three"),
5667 V64, VecListThree128>;
5668 def : SIMDTableLookupAlias<asm # ".8b",
5669 !cast<Instruction>(NAME#"v8i8Four"),
5670 V64, VecListFour128>;
5671 def : SIMDTableLookupAlias<asm # ".16b",
5672 !cast<Instruction>(NAME#"v16i8One"),
5673 V128, VecListOne128>;
5674 def : SIMDTableLookupAlias<asm # ".16b",
5675 !cast<Instruction>(NAME#"v16i8Two"),
5676 V128, VecListTwo128>;
5677 def : SIMDTableLookupAlias<asm # ".16b",
5678 !cast<Instruction>(NAME#"v16i8Three"),
5679 V128, VecListThree128>;
5680 def : SIMDTableLookupAlias<asm # ".16b",
5681 !cast<Instruction>(NAME#"v16i8Four"),
5682 V128, VecListFour128>;
5683}
5684
5685multiclass SIMDTableLookupTied<bit op, string asm> {
5686 def v8i8One : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5687 asm, ".8b">;
5688 def v8i8Two : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5689 asm, ".8b">;
5690 def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5691 asm, ".8b">;
5692 def v8i8Four : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5693 asm, ".8b">;
5694 def v16i8One : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5695 asm, ".16b">;
5696 def v16i8Two : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5697 asm, ".16b">;
5698 def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5699 asm, ".16b">;
5700 def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5701 asm, ".16b">;
5702
5703 def : SIMDTableLookupAlias<asm # ".8b",
5704 !cast<Instruction>(NAME#"v8i8One"),
5705 V64, VecListOne128>;
5706 def : SIMDTableLookupAlias<asm # ".8b",
5707 !cast<Instruction>(NAME#"v8i8Two"),
5708 V64, VecListTwo128>;
5709 def : SIMDTableLookupAlias<asm # ".8b",
5710 !cast<Instruction>(NAME#"v8i8Three"),
5711 V64, VecListThree128>;
5712 def : SIMDTableLookupAlias<asm # ".8b",
5713 !cast<Instruction>(NAME#"v8i8Four"),
5714 V64, VecListFour128>;
5715 def : SIMDTableLookupAlias<asm # ".16b",
5716 !cast<Instruction>(NAME#"v16i8One"),
5717 V128, VecListOne128>;
5718 def : SIMDTableLookupAlias<asm # ".16b",
5719 !cast<Instruction>(NAME#"v16i8Two"),
5720 V128, VecListTwo128>;
5721 def : SIMDTableLookupAlias<asm # ".16b",
5722 !cast<Instruction>(NAME#"v16i8Three"),
5723 V128, VecListThree128>;
5724 def : SIMDTableLookupAlias<asm # ".16b",
5725 !cast<Instruction>(NAME#"v16i8Four"),
5726 V128, VecListFour128>;
5727}
5728
5729
5730//----------------------------------------------------------------------------
5731// AdvSIMD scalar CPY
5732//----------------------------------------------------------------------------
5733let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5734class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5735 string kind, Operand idxtype>
5736 : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5737 "{\t$dst, $src" # kind # "$idx" #
5738 "|\t$dst, $src$idx}", "", []>,
5739 Sched<[WriteV]> {
5740 bits<5> dst;
5741 bits<5> src;
5742 let Inst{31-21} = 0b01011110000;
5743 let Inst{15-10} = 0b000001;
5744 let Inst{9-5} = src;
5745 let Inst{4-0} = dst;
5746}
5747
5748class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5749 RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5750 : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5751 # "|\t$dst, $src$index}",
5752 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5753
5754
5755multiclass SIMDScalarCPY<string asm> {
5756 def i8 : BaseSIMDScalarCPY<FPR8, V128, ".b", VectorIndexB> {
5757 bits<4> idx;
5758 let Inst{20-17} = idx;
5759 let Inst{16} = 1;
5760 }
5761 def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5762 bits<3> idx;
5763 let Inst{20-18} = idx;
5764 let Inst{17-16} = 0b10;
5765 }
5766 def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5767 bits<2> idx;
5768 let Inst{20-19} = idx;
5769 let Inst{18-16} = 0b100;
5770 }
5771 def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5772 bits<1> idx;
5773 let Inst{20} = idx;
5774 let Inst{19-16} = 0b1000;
5775 }
5776
5777 // 'DUP' mnemonic aliases.
5778 def : SIMDScalarCPYAlias<"dup", ".b",
5779 !cast<Instruction>(NAME#"i8"),
5780 FPR8, V128, VectorIndexB>;
5781 def : SIMDScalarCPYAlias<"dup", ".h",
5782 !cast<Instruction>(NAME#"i16"),
5783 FPR16, V128, VectorIndexH>;
5784 def : SIMDScalarCPYAlias<"dup", ".s",
5785 !cast<Instruction>(NAME#"i32"),
5786 FPR32, V128, VectorIndexS>;
5787 def : SIMDScalarCPYAlias<"dup", ".d",
5788 !cast<Instruction>(NAME#"i64"),
5789 FPR64, V128, VectorIndexD>;
5790}
5791
5792//----------------------------------------------------------------------------
5793// AdvSIMD modified immediate instructions
5794//----------------------------------------------------------------------------
5795
5796class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5797 string asm, string op_string,
5798 string cstr, list<dag> pattern>
5799 : I<oops, iops, asm, op_string, cstr, pattern>,
5800 Sched<[WriteV]> {
5801 bits<5> Rd;
5802 bits<8> imm8;
5803 let Inst{31} = 0;
5804 let Inst{30} = Q;
5805 let Inst{29} = op;
5806 let Inst{28-19} = 0b0111100000;
5807 let Inst{18-16} = imm8{7-5};
5808 let Inst{11-10} = 0b01;
5809 let Inst{9-5} = imm8{4-0};
5810 let Inst{4-0} = Rd;
5811}
5812
5813class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5814 Operand immtype, dag opt_shift_iop,
5815 string opt_shift, string asm, string kind,
5816 list<dag> pattern>
5817 : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5818 !con((ins immtype:$imm8), opt_shift_iop), asm,
5819 "{\t$Rd" # kind # ", $imm8" # opt_shift #
5820 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5821 "", pattern> {
5822 let DecoderMethod = "DecodeModImmInstruction";
5823}
5824
5825class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5826 Operand immtype, dag opt_shift_iop,
5827 string opt_shift, string asm, string kind,
5828 list<dag> pattern>
5829 : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5830 !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5831 asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5832 "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5833 "$Rd = $dst", pattern> {
5834 let DecoderMethod = "DecodeModImmTiedInstruction";
5835}
5836
5837class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5838 RegisterOperand vectype, string asm,
5839 string kind, list<dag> pattern>
5840 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5841 (ins logical_vec_shift:$shift),
5842 "$shift", asm, kind, pattern> {
5843 bits<2> shift;
5844 let Inst{15} = b15_b12{1};
5845 let Inst{14-13} = shift;
5846 let Inst{12} = b15_b12{0};
5847}
5848
5849class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5850 RegisterOperand vectype, string asm,
5851 string kind, list<dag> pattern>
5852 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5853 (ins logical_vec_shift:$shift),
5854 "$shift", asm, kind, pattern> {
5855 bits<2> shift;
5856 let Inst{15} = b15_b12{1};
5857 let Inst{14-13} = shift;
5858 let Inst{12} = b15_b12{0};
5859}
5860
5861
5862class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5863 RegisterOperand vectype, string asm,
5864 string kind, list<dag> pattern>
5865 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5866 (ins logical_vec_hw_shift:$shift),
5867 "$shift", asm, kind, pattern> {
5868 bits<2> shift;
5869 let Inst{15} = b15_b12{1};
5870 let Inst{14} = 0;
5871 let Inst{13} = shift{0};
5872 let Inst{12} = b15_b12{0};
5873}
5874
5875class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5876 RegisterOperand vectype, string asm,
5877 string kind, list<dag> pattern>
5878 : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5879 (ins logical_vec_hw_shift:$shift),
5880 "$shift", asm, kind, pattern> {
5881 bits<2> shift;
5882 let Inst{15} = b15_b12{1};
5883 let Inst{14} = 0;
5884 let Inst{13} = shift{0};
5885 let Inst{12} = b15_b12{0};
5886}
5887
5888multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5889 string asm> {
5890 def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5891 asm, ".4h", []>;
5892 def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5893 asm, ".8h", []>;
5894
5895 def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5896 asm, ".2s", []>;
5897 def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5898 asm, ".4s", []>;
5899}
5900
5901multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5902 bits<2> w_cmode, string asm,
5903 SDNode OpNode> {
5904 def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5905 asm, ".4h",
5906 [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5907 imm0_255:$imm8,
5908 (i32 imm:$shift)))]>;
5909 def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5910 asm, ".8h",
5911 [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5912 imm0_255:$imm8,
5913 (i32 imm:$shift)))]>;
5914
5915 def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5916 asm, ".2s",
5917 [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5918 imm0_255:$imm8,
5919 (i32 imm:$shift)))]>;
5920 def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5921 asm, ".4s",
5922 [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5923 imm0_255:$imm8,
5924 (i32 imm:$shift)))]>;
5925}
5926
5927class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5928 RegisterOperand vectype, string asm,
5929 string kind, list<dag> pattern>
5930 : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5931 (ins move_vec_shift:$shift),
5932 "$shift", asm, kind, pattern> {
5933 bits<1> shift;
5934 let Inst{15-13} = cmode{3-1};
5935 let Inst{12} = shift;
5936}
5937
5938class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5939 RegisterOperand vectype,
5940 Operand imm_type, string asm,
5941 string kind, list<dag> pattern>
5942 : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5943 asm, kind, pattern> {
5944 let Inst{15-12} = cmode;
5945}
5946
5947class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5948 list<dag> pattern>
5949 : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5950 "\t$Rd, $imm8", "", pattern> {
5951 let Inst{15-12} = cmode;
5952 let DecoderMethod = "DecodeModImmInstruction";
5953}
5954
5955//----------------------------------------------------------------------------
5956// AdvSIMD indexed element
5957//----------------------------------------------------------------------------
5958
5959let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5960class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5961 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5962 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5963 string apple_kind, string dst_kind, string lhs_kind,
5964 string rhs_kind, list<dag> pattern>
5965 : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5966 asm,
5967 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5968 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5969 Sched<[WriteV]> {
5970 bits<5> Rd;
5971 bits<5> Rn;
5972 bits<5> Rm;
5973
5974 let Inst{31} = 0;
5975 let Inst{30} = Q;
5976 let Inst{29} = U;
5977 let Inst{28} = Scalar;
5978 let Inst{27-24} = 0b1111;
5979 let Inst{23-22} = size;
5980 // Bit 21 must be set by the derived class.
5981 let Inst{20-16} = Rm;
5982 let Inst{15-12} = opc;
5983 // Bit 11 must be set by the derived class.
5984 let Inst{10} = 0;
5985 let Inst{9-5} = Rn;
5986 let Inst{4-0} = Rd;
5987}
5988
5989let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5990class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5991 RegisterOperand dst_reg, RegisterOperand lhs_reg,
5992 RegisterOperand rhs_reg, Operand vec_idx, string asm,
5993 string apple_kind, string dst_kind, string lhs_kind,
5994 string rhs_kind, list<dag> pattern>
5995 : I<(outs dst_reg:$dst),
5996 (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5997 "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5998 "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5999 Sched<[WriteV]> {
6000 bits<5> Rd;
6001 bits<5> Rn;
6002 bits<5> Rm;
6003
6004 let Inst{31} = 0;
6005 let Inst{30} = Q;
6006 let Inst{29} = U;
6007 let Inst{28} = Scalar;
6008 let Inst{27-24} = 0b1111;
6009 let Inst{23-22} = size;
6010 // Bit 21 must be set by the derived class.
6011 let Inst{20-16} = Rm;
6012 let Inst{15-12} = opc;
6013 // Bit 11 must be set by the derived class.
6014 let Inst{10} = 0;
6015 let Inst{9-5} = Rn;
6016 let Inst{4-0} = Rd;
6017}
6018
6019multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6020 SDPatternOperator OpNode> {
6021 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6022 V64, V64,
6023 V128, VectorIndexS,
6024 asm, ".2s", ".2s", ".2s", ".s",
6025 [(set (v2f32 V64:$Rd),
6026 (OpNode (v2f32 V64:$Rn),
6027 (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6028 bits<2> idx;
6029 let Inst{11} = idx{1};
6030 let Inst{21} = idx{0};
6031 }
6032
6033 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6034 V128, V128,
6035 V128, VectorIndexS,
6036 asm, ".4s", ".4s", ".4s", ".s",
6037 [(set (v4f32 V128:$Rd),
6038 (OpNode (v4f32 V128:$Rn),
6039 (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6040 bits<2> idx;
6041 let Inst{11} = idx{1};
6042 let Inst{21} = idx{0};
6043 }
6044
6045 def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6046 V128, V128,
6047 V128, VectorIndexD,
6048 asm, ".2d", ".2d", ".2d", ".d",
6049 [(set (v2f64 V128:$Rd),
6050 (OpNode (v2f64 V128:$Rn),
6051 (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6052 bits<1> idx;
6053 let Inst{11} = idx{0};
6054 let Inst{21} = 0;
6055 }
6056
6057 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6058 FPR32Op, FPR32Op, V128, VectorIndexS,
6059 asm, ".s", "", "", ".s",
6060 [(set (f32 FPR32Op:$Rd),
6061 (OpNode (f32 FPR32Op:$Rn),
6062 (f32 (vector_extract (v4f32 V128:$Rm),
6063 VectorIndexS:$idx))))]> {
6064 bits<2> idx;
6065 let Inst{11} = idx{1};
6066 let Inst{21} = idx{0};
6067 }
6068
6069 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6070 FPR64Op, FPR64Op, V128, VectorIndexD,
6071 asm, ".d", "", "", ".d",
6072 [(set (f64 FPR64Op:$Rd),
6073 (OpNode (f64 FPR64Op:$Rn),
6074 (f64 (vector_extract (v2f64 V128:$Rm),
6075 VectorIndexD:$idx))))]> {
6076 bits<1> idx;
6077 let Inst{11} = idx{0};
6078 let Inst{21} = 0;
6079 }
6080}
6081
6082multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6083 // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6084 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6085 (ARM64duplane32 (v4f32 V128:$Rm),
6086 VectorIndexS:$idx))),
6087 (!cast<Instruction>(INST # v2i32_indexed)
6088 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6089 def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6090 (ARM64dup (f32 FPR32Op:$Rm)))),
6091 (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6092 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6093
6094
6095 // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6096 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6097 (ARM64duplane32 (v4f32 V128:$Rm),
6098 VectorIndexS:$idx))),
6099 (!cast<Instruction>(INST # "v4i32_indexed")
6100 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6101 def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6102 (ARM64dup (f32 FPR32Op:$Rm)))),
6103 (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6104 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6105
6106 // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6107 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6108 (ARM64duplane64 (v2f64 V128:$Rm),
6109 VectorIndexD:$idx))),
6110 (!cast<Instruction>(INST # "v2i64_indexed")
6111 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6112 def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6113 (ARM64dup (f64 FPR64Op:$Rm)))),
6114 (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6115 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6116
6117 // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6118 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6119 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6120 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6121 V128:$Rm, VectorIndexS:$idx)>;
6122 def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6123 (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6124 (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6125 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6126
6127 // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6128 def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6129 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6130 (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6131 V128:$Rm, VectorIndexD:$idx)>;
6132}
6133
6134multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6135 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6136 V128, VectorIndexS,
6137 asm, ".2s", ".2s", ".2s", ".s", []> {
6138 bits<2> idx;
6139 let Inst{11} = idx{1};
6140 let Inst{21} = idx{0};
6141 }
6142
6143 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6144 V128, V128,
6145 V128, VectorIndexS,
6146 asm, ".4s", ".4s", ".4s", ".s", []> {
6147 bits<2> idx;
6148 let Inst{11} = idx{1};
6149 let Inst{21} = idx{0};
6150 }
6151
6152 def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6153 V128, V128,
6154 V128, VectorIndexD,
6155 asm, ".2d", ".2d", ".2d", ".d", []> {
6156 bits<1> idx;
6157 let Inst{11} = idx{0};
6158 let Inst{21} = 0;
6159 }
6160
6161
6162 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6163 FPR32Op, FPR32Op, V128, VectorIndexS,
6164 asm, ".s", "", "", ".s", []> {
6165 bits<2> idx;
6166 let Inst{11} = idx{1};
6167 let Inst{21} = idx{0};
6168 }
6169
6170 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6171 FPR64Op, FPR64Op, V128, VectorIndexD,
6172 asm, ".d", "", "", ".d", []> {
6173 bits<1> idx;
6174 let Inst{11} = idx{0};
6175 let Inst{21} = 0;
6176 }
6177}
6178
6179multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6180 SDPatternOperator OpNode> {
6181 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6182 V128_lo, VectorIndexH,
6183 asm, ".4h", ".4h", ".4h", ".h",
6184 [(set (v4i16 V64:$Rd),
6185 (OpNode (v4i16 V64:$Rn),
6186 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6187 bits<3> idx;
6188 let Inst{11} = idx{2};
6189 let Inst{21} = idx{1};
6190 let Inst{20} = idx{0};
6191 }
6192
6193 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6194 V128, V128,
6195 V128_lo, VectorIndexH,
6196 asm, ".8h", ".8h", ".8h", ".h",
6197 [(set (v8i16 V128:$Rd),
6198 (OpNode (v8i16 V128:$Rn),
6199 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6200 bits<3> idx;
6201 let Inst{11} = idx{2};
6202 let Inst{21} = idx{1};
6203 let Inst{20} = idx{0};
6204 }
6205
6206 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6207 V64, V64,
6208 V128, VectorIndexS,
6209 asm, ".2s", ".2s", ".2s", ".s",
6210 [(set (v2i32 V64:$Rd),
6211 (OpNode (v2i32 V64:$Rn),
6212 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6213 bits<2> idx;
6214 let Inst{11} = idx{1};
6215 let Inst{21} = idx{0};
6216 }
6217
6218 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6219 V128, V128,
6220 V128, VectorIndexS,
6221 asm, ".4s", ".4s", ".4s", ".s",
6222 [(set (v4i32 V128:$Rd),
6223 (OpNode (v4i32 V128:$Rn),
6224 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6225 bits<2> idx;
6226 let Inst{11} = idx{1};
6227 let Inst{21} = idx{0};
6228 }
6229
6230 def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6231 FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6232 asm, ".h", "", "", ".h", []> {
6233 bits<3> idx;
6234 let Inst{11} = idx{2};
6235 let Inst{21} = idx{1};
6236 let Inst{20} = idx{0};
6237 }
6238
6239 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6240 FPR32Op, FPR32Op, V128, VectorIndexS,
6241 asm, ".s", "", "", ".s",
6242 [(set (i32 FPR32Op:$Rd),
6243 (OpNode FPR32Op:$Rn,
6244 (i32 (vector_extract (v4i32 V128:$Rm),
6245 VectorIndexS:$idx))))]> {
6246 bits<2> idx;
6247 let Inst{11} = idx{1};
6248 let Inst{21} = idx{0};
6249 }
6250}
6251
6252multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6253 SDPatternOperator OpNode> {
6254 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6255 V64, V64,
6256 V128_lo, VectorIndexH,
6257 asm, ".4h", ".4h", ".4h", ".h",
6258 [(set (v4i16 V64:$Rd),
6259 (OpNode (v4i16 V64:$Rn),
6260 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6261 bits<3> idx;
6262 let Inst{11} = idx{2};
6263 let Inst{21} = idx{1};
6264 let Inst{20} = idx{0};
6265 }
6266
6267 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6268 V128, V128,
6269 V128_lo, VectorIndexH,
6270 asm, ".8h", ".8h", ".8h", ".h",
6271 [(set (v8i16 V128:$Rd),
6272 (OpNode (v8i16 V128:$Rn),
6273 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6274 bits<3> idx;
6275 let Inst{11} = idx{2};
6276 let Inst{21} = idx{1};
6277 let Inst{20} = idx{0};
6278 }
6279
6280 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6281 V64, V64,
6282 V128, VectorIndexS,
6283 asm, ".2s", ".2s", ".2s", ".s",
6284 [(set (v2i32 V64:$Rd),
6285 (OpNode (v2i32 V64:$Rn),
6286 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6287 bits<2> idx;
6288 let Inst{11} = idx{1};
6289 let Inst{21} = idx{0};
6290 }
6291
6292 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6293 V128, V128,
6294 V128, VectorIndexS,
6295 asm, ".4s", ".4s", ".4s", ".s",
6296 [(set (v4i32 V128:$Rd),
6297 (OpNode (v4i32 V128:$Rn),
6298 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6299 bits<2> idx;
6300 let Inst{11} = idx{1};
6301 let Inst{21} = idx{0};
6302 }
6303}
6304
6305multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6306 SDPatternOperator OpNode> {
6307 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6308 V128_lo, VectorIndexH,
6309 asm, ".4h", ".4h", ".4h", ".h",
6310 [(set (v4i16 V64:$dst),
6311 (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6312 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6313 bits<3> idx;
6314 let Inst{11} = idx{2};
6315 let Inst{21} = idx{1};
6316 let Inst{20} = idx{0};
6317 }
6318
6319 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6320 V128, V128,
6321 V128_lo, VectorIndexH,
6322 asm, ".8h", ".8h", ".8h", ".h",
6323 [(set (v8i16 V128:$dst),
6324 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6325 (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6326 bits<3> idx;
6327 let Inst{11} = idx{2};
6328 let Inst{21} = idx{1};
6329 let Inst{20} = idx{0};
6330 }
6331
6332 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6333 V64, V64,
6334 V128, VectorIndexS,
6335 asm, ".2s", ".2s", ".2s", ".s",
6336 [(set (v2i32 V64:$dst),
6337 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6338 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6339 bits<2> idx;
6340 let Inst{11} = idx{1};
6341 let Inst{21} = idx{0};
6342 }
6343
6344 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6345 V128, V128,
6346 V128, VectorIndexS,
6347 asm, ".4s", ".4s", ".4s", ".s",
6348 [(set (v4i32 V128:$dst),
6349 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6350 (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6351 bits<2> idx;
6352 let Inst{11} = idx{1};
6353 let Inst{21} = idx{0};
6354 }
6355}
6356
6357multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6358 SDPatternOperator OpNode> {
6359 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6360 V128, V64,
6361 V128_lo, VectorIndexH,
6362 asm, ".4s", ".4s", ".4h", ".h",
6363 [(set (v4i32 V128:$Rd),
6364 (OpNode (v4i16 V64:$Rn),
6365 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6366 bits<3> idx;
6367 let Inst{11} = idx{2};
6368 let Inst{21} = idx{1};
6369 let Inst{20} = idx{0};
6370 }
6371
6372 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6373 V128, V128,
6374 V128_lo, VectorIndexH,
6375 asm#"2", ".4s", ".4s", ".8h", ".h",
6376 [(set (v4i32 V128:$Rd),
6377 (OpNode (extract_high_v8i16 V128:$Rn),
6378 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6379 VectorIndexH:$idx))))]> {
6380
6381 bits<3> idx;
6382 let Inst{11} = idx{2};
6383 let Inst{21} = idx{1};
6384 let Inst{20} = idx{0};
6385 }
6386
6387 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6388 V128, V64,
6389 V128, VectorIndexS,
6390 asm, ".2d", ".2d", ".2s", ".s",
6391 [(set (v2i64 V128:$Rd),
6392 (OpNode (v2i32 V64:$Rn),
6393 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6394 bits<2> idx;
6395 let Inst{11} = idx{1};
6396 let Inst{21} = idx{0};
6397 }
6398
6399 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6400 V128, V128,
6401 V128, VectorIndexS,
6402 asm#"2", ".2d", ".2d", ".4s", ".s",
6403 [(set (v2i64 V128:$Rd),
6404 (OpNode (extract_high_v4i32 V128:$Rn),
6405 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6406 VectorIndexS:$idx))))]> {
6407 bits<2> idx;
6408 let Inst{11} = idx{1};
6409 let Inst{21} = idx{0};
6410 }
6411
6412 def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6413 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6414 asm, ".h", "", "", ".h", []> {
6415 bits<3> idx;
6416 let Inst{11} = idx{2};
6417 let Inst{21} = idx{1};
6418 let Inst{20} = idx{0};
6419 }
6420
6421 def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6422 FPR64Op, FPR32Op, V128, VectorIndexS,
6423 asm, ".s", "", "", ".s", []> {
6424 bits<2> idx;
6425 let Inst{11} = idx{1};
6426 let Inst{21} = idx{0};
6427 }
6428}
6429
6430multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6431 SDPatternOperator Accum> {
6432 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6433 V128, V64,
6434 V128_lo, VectorIndexH,
6435 asm, ".4s", ".4s", ".4h", ".h",
6436 [(set (v4i32 V128:$dst),
6437 (Accum (v4i32 V128:$Rd),
6438 (v4i32 (int_arm64_neon_sqdmull
6439 (v4i16 V64:$Rn),
6440 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6441 VectorIndexH:$idx))))))]> {
6442 bits<3> idx;
6443 let Inst{11} = idx{2};
6444 let Inst{21} = idx{1};
6445 let Inst{20} = idx{0};
6446 }
6447
6448 // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6449 // intermediate EXTRACT_SUBREG would be untyped.
6450 def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6451 (i32 (vector_extract (v4i32
6452 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6453 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6454 VectorIndexH:$idx)))),
6455 (i64 0))))),
6456 (EXTRACT_SUBREG
6457 (!cast<Instruction>(NAME # v4i16_indexed)
6458 (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6459 V128_lo:$Rm, VectorIndexH:$idx),
6460 ssub)>;
6461
6462 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6463 V128, V128,
6464 V128_lo, VectorIndexH,
6465 asm#"2", ".4s", ".4s", ".8h", ".h",
6466 [(set (v4i32 V128:$dst),
6467 (Accum (v4i32 V128:$Rd),
6468 (v4i32 (int_arm64_neon_sqdmull
6469 (extract_high_v8i16 V128:$Rn),
6470 (extract_high_v8i16
6471 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6472 VectorIndexH:$idx))))))]> {
6473 bits<3> idx;
6474 let Inst{11} = idx{2};
6475 let Inst{21} = idx{1};
6476 let Inst{20} = idx{0};
6477 }
6478
6479 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6480 V128, V64,
6481 V128, VectorIndexS,
6482 asm, ".2d", ".2d", ".2s", ".s",
6483 [(set (v2i64 V128:$dst),
6484 (Accum (v2i64 V128:$Rd),
6485 (v2i64 (int_arm64_neon_sqdmull
6486 (v2i32 V64:$Rn),
6487 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6488 VectorIndexS:$idx))))))]> {
6489 bits<2> idx;
6490 let Inst{11} = idx{1};
6491 let Inst{21} = idx{0};
6492 }
6493
6494 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6495 V128, V128,
6496 V128, VectorIndexS,
6497 asm#"2", ".2d", ".2d", ".4s", ".s",
6498 [(set (v2i64 V128:$dst),
6499 (Accum (v2i64 V128:$Rd),
6500 (v2i64 (int_arm64_neon_sqdmull
6501 (extract_high_v4i32 V128:$Rn),
6502 (extract_high_v4i32
6503 (ARM64duplane32 (v4i32 V128:$Rm),
6504 VectorIndexS:$idx))))))]> {
6505 bits<2> idx;
6506 let Inst{11} = idx{1};
6507 let Inst{21} = idx{0};
6508 }
6509
6510 def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6511 FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6512 asm, ".h", "", "", ".h", []> {
6513 bits<3> idx;
6514 let Inst{11} = idx{2};
6515 let Inst{21} = idx{1};
6516 let Inst{20} = idx{0};
6517 }
6518
6519
6520 def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6521 FPR64Op, FPR32Op, V128, VectorIndexS,
6522 asm, ".s", "", "", ".s",
6523 [(set (i64 FPR64Op:$dst),
6524 (Accum (i64 FPR64Op:$Rd),
6525 (i64 (int_arm64_neon_sqdmulls_scalar
6526 (i32 FPR32Op:$Rn),
6527 (i32 (vector_extract (v4i32 V128:$Rm),
6528 VectorIndexS:$idx))))))]> {
6529
6530 bits<2> idx;
6531 let Inst{11} = idx{1};
6532 let Inst{21} = idx{0};
6533 }
6534}
6535
6536multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6537 SDPatternOperator OpNode> {
6538 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6539 def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6540 V128, V64,
6541 V128_lo, VectorIndexH,
6542 asm, ".4s", ".4s", ".4h", ".h",
6543 [(set (v4i32 V128:$Rd),
6544 (OpNode (v4i16 V64:$Rn),
6545 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6546 bits<3> idx;
6547 let Inst{11} = idx{2};
6548 let Inst{21} = idx{1};
6549 let Inst{20} = idx{0};
6550 }
6551
6552 def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6553 V128, V128,
6554 V128_lo, VectorIndexH,
6555 asm#"2", ".4s", ".4s", ".8h", ".h",
6556 [(set (v4i32 V128:$Rd),
6557 (OpNode (extract_high_v8i16 V128:$Rn),
6558 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6559 VectorIndexH:$idx))))]> {
6560
6561 bits<3> idx;
6562 let Inst{11} = idx{2};
6563 let Inst{21} = idx{1};
6564 let Inst{20} = idx{0};
6565 }
6566
6567 def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6568 V128, V64,
6569 V128, VectorIndexS,
6570 asm, ".2d", ".2d", ".2s", ".s",
6571 [(set (v2i64 V128:$Rd),
6572 (OpNode (v2i32 V64:$Rn),
6573 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6574 bits<2> idx;
6575 let Inst{11} = idx{1};
6576 let Inst{21} = idx{0};
6577 }
6578
6579 def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6580 V128, V128,
6581 V128, VectorIndexS,
6582 asm#"2", ".2d", ".2d", ".4s", ".s",
6583 [(set (v2i64 V128:$Rd),
6584 (OpNode (extract_high_v4i32 V128:$Rn),
6585 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6586 VectorIndexS:$idx))))]> {
6587 bits<2> idx;
6588 let Inst{11} = idx{1};
6589 let Inst{21} = idx{0};
6590 }
6591 }
6592}
6593
6594multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6595 SDPatternOperator OpNode> {
6596 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6597 def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6598 V128, V64,
6599 V128_lo, VectorIndexH,
6600 asm, ".4s", ".4s", ".4h", ".h",
6601 [(set (v4i32 V128:$dst),
6602 (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6603 (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6604 bits<3> idx;
6605 let Inst{11} = idx{2};
6606 let Inst{21} = idx{1};
6607 let Inst{20} = idx{0};
6608 }
6609
6610 def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6611 V128, V128,
6612 V128_lo, VectorIndexH,
6613 asm#"2", ".4s", ".4s", ".8h", ".h",
6614 [(set (v4i32 V128:$dst),
6615 (OpNode (v4i32 V128:$Rd),
6616 (extract_high_v8i16 V128:$Rn),
6617 (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6618 VectorIndexH:$idx))))]> {
6619 bits<3> idx;
6620 let Inst{11} = idx{2};
6621 let Inst{21} = idx{1};
6622 let Inst{20} = idx{0};
6623 }
6624
6625 def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6626 V128, V64,
6627 V128, VectorIndexS,
6628 asm, ".2d", ".2d", ".2s", ".s",
6629 [(set (v2i64 V128:$dst),
6630 (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6631 (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6632 bits<2> idx;
6633 let Inst{11} = idx{1};
6634 let Inst{21} = idx{0};
6635 }
6636
6637 def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6638 V128, V128,
6639 V128, VectorIndexS,
6640 asm#"2", ".2d", ".2d", ".4s", ".s",
6641 [(set (v2i64 V128:$dst),
6642 (OpNode (v2i64 V128:$Rd),
6643 (extract_high_v4i32 V128:$Rn),
6644 (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6645 VectorIndexS:$idx))))]> {
6646 bits<2> idx;
6647 let Inst{11} = idx{1};
6648 let Inst{21} = idx{0};
6649 }
6650 }
6651}
6652
6653//----------------------------------------------------------------------------
6654// AdvSIMD scalar shift by immediate
6655//----------------------------------------------------------------------------
6656
6657let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6658class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6659 RegisterClass regtype1, RegisterClass regtype2,
6660 Operand immtype, string asm, list<dag> pattern>
6661 : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6662 asm, "\t$Rd, $Rn, $imm", "", pattern>,
6663 Sched<[WriteV]> {
6664 bits<5> Rd;
6665 bits<5> Rn;
6666 bits<7> imm;
6667 let Inst{31-30} = 0b01;
6668 let Inst{29} = U;
6669 let Inst{28-23} = 0b111110;
6670 let Inst{22-16} = fixed_imm;
6671 let Inst{15-11} = opc;
6672 let Inst{10} = 1;
6673 let Inst{9-5} = Rn;
6674 let Inst{4-0} = Rd;
6675}
6676
6677let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6678class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6679 RegisterClass regtype1, RegisterClass regtype2,
6680 Operand immtype, string asm, list<dag> pattern>
6681 : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6682 asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6683 Sched<[WriteV]> {
6684 bits<5> Rd;
6685 bits<5> Rn;
6686 bits<7> imm;
6687 let Inst{31-30} = 0b01;
6688 let Inst{29} = U;
6689 let Inst{28-23} = 0b111110;
6690 let Inst{22-16} = fixed_imm;
6691 let Inst{15-11} = opc;
6692 let Inst{10} = 1;
6693 let Inst{9-5} = Rn;
6694 let Inst{4-0} = Rd;
6695}
6696
6697
6698multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6699 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6700 FPR32, FPR32, vecshiftR32, asm, []> {
6701 let Inst{20-16} = imm{4-0};
6702 }
6703
6704 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6705 FPR64, FPR64, vecshiftR64, asm, []> {
6706 let Inst{21-16} = imm{5-0};
6707 }
6708}
6709
6710multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6711 SDPatternOperator OpNode> {
6712 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6713 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006714 [(set (i64 FPR64:$Rd),
6715 (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006716 let Inst{21-16} = imm{5-0};
6717 }
Tim Northover5081cd02014-03-31 15:46:46 +00006718
6719 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6720 (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006721}
6722
Tim Northover00ed9962014-03-29 10:18:08 +00006723multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6724 SDPatternOperator OpNode = null_frag> {
6725 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6726 FPR64, FPR64, vecshiftR64, asm,
Tim Northover5081cd02014-03-31 15:46:46 +00006727 [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6728 (i32 vecshiftR64:$imm)))]> {
Tim Northover00ed9962014-03-29 10:18:08 +00006729 let Inst{21-16} = imm{5-0};
6730 }
Tim Northover5081cd02014-03-31 15:46:46 +00006731
6732 def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6733 (i32 vecshiftR64:$imm))),
6734 (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6735 vecshiftR64:$imm)>;
Tim Northover00ed9962014-03-29 10:18:08 +00006736}
6737
6738multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6739 SDPatternOperator OpNode> {
6740 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6741 FPR64, FPR64, vecshiftL64, asm,
6742 [(set (v1i64 FPR64:$Rd),
6743 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6744 let Inst{21-16} = imm{5-0};
6745 }
6746}
6747
6748let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6749multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6750 def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6751 FPR64, FPR64, vecshiftL64, asm, []> {
6752 let Inst{21-16} = imm{5-0};
6753 }
6754}
6755
6756let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6757multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6758 SDPatternOperator OpNode = null_frag> {
6759 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6760 FPR8, FPR16, vecshiftR8, asm, []> {
6761 let Inst{18-16} = imm{2-0};
6762 }
6763
6764 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6765 FPR16, FPR32, vecshiftR16, asm, []> {
6766 let Inst{19-16} = imm{3-0};
6767 }
6768
6769 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6770 FPR32, FPR64, vecshiftR32, asm,
6771 [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6772 let Inst{20-16} = imm{4-0};
6773 }
6774}
6775
6776multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6777 SDPatternOperator OpNode> {
6778 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6779 FPR8, FPR8, vecshiftL8, asm, []> {
6780 let Inst{18-16} = imm{2-0};
6781 }
6782
6783 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6784 FPR16, FPR16, vecshiftL16, asm, []> {
6785 let Inst{19-16} = imm{3-0};
6786 }
6787
6788 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6789 FPR32, FPR32, vecshiftL32, asm,
6790 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6791 let Inst{20-16} = imm{4-0};
6792 }
6793
6794 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6795 FPR64, FPR64, vecshiftL64, asm,
6796 [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6797 (i32 vecshiftL64:$imm)))]> {
6798 let Inst{21-16} = imm{5-0};
6799 }
6800}
6801
6802multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6803 def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6804 FPR8, FPR8, vecshiftR8, asm, []> {
6805 let Inst{18-16} = imm{2-0};
6806 }
6807
6808 def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6809 FPR16, FPR16, vecshiftR16, asm, []> {
6810 let Inst{19-16} = imm{3-0};
6811 }
6812
6813 def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6814 FPR32, FPR32, vecshiftR32, asm, []> {
6815 let Inst{20-16} = imm{4-0};
6816 }
6817
6818 def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6819 FPR64, FPR64, vecshiftR64, asm, []> {
6820 let Inst{21-16} = imm{5-0};
6821 }
6822}
6823
6824//----------------------------------------------------------------------------
6825// AdvSIMD vector x indexed element
6826//----------------------------------------------------------------------------
6827
6828let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6829class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6830 RegisterOperand dst_reg, RegisterOperand src_reg,
6831 Operand immtype,
6832 string asm, string dst_kind, string src_kind,
6833 list<dag> pattern>
6834 : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6835 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6836 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6837 Sched<[WriteV]> {
6838 bits<5> Rd;
6839 bits<5> Rn;
6840 let Inst{31} = 0;
6841 let Inst{30} = Q;
6842 let Inst{29} = U;
6843 let Inst{28-23} = 0b011110;
6844 let Inst{22-16} = fixed_imm;
6845 let Inst{15-11} = opc;
6846 let Inst{10} = 1;
6847 let Inst{9-5} = Rn;
6848 let Inst{4-0} = Rd;
6849}
6850
6851let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6852class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6853 RegisterOperand vectype1, RegisterOperand vectype2,
6854 Operand immtype,
6855 string asm, string dst_kind, string src_kind,
6856 list<dag> pattern>
6857 : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6858 asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6859 "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6860 Sched<[WriteV]> {
6861 bits<5> Rd;
6862 bits<5> Rn;
6863 let Inst{31} = 0;
6864 let Inst{30} = Q;
6865 let Inst{29} = U;
6866 let Inst{28-23} = 0b011110;
6867 let Inst{22-16} = fixed_imm;
6868 let Inst{15-11} = opc;
6869 let Inst{10} = 1;
6870 let Inst{9-5} = Rn;
6871 let Inst{4-0} = Rd;
6872}
6873
6874multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6875 Intrinsic OpNode> {
6876 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6877 V64, V64, vecshiftR32,
6878 asm, ".2s", ".2s",
6879 [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6880 bits<5> imm;
6881 let Inst{20-16} = imm;
6882 }
6883
6884 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6885 V128, V128, vecshiftR32,
6886 asm, ".4s", ".4s",
6887 [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6888 bits<5> imm;
6889 let Inst{20-16} = imm;
6890 }
6891
6892 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6893 V128, V128, vecshiftR64,
6894 asm, ".2d", ".2d",
6895 [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6896 bits<6> imm;
6897 let Inst{21-16} = imm;
6898 }
6899}
6900
6901multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6902 Intrinsic OpNode> {
6903 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6904 V64, V64, vecshiftR32,
6905 asm, ".2s", ".2s",
6906 [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6907 bits<5> imm;
6908 let Inst{20-16} = imm;
6909 }
6910
6911 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6912 V128, V128, vecshiftR32,
6913 asm, ".4s", ".4s",
6914 [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6915 bits<5> imm;
6916 let Inst{20-16} = imm;
6917 }
6918
6919 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6920 V128, V128, vecshiftR64,
6921 asm, ".2d", ".2d",
6922 [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6923 bits<6> imm;
6924 let Inst{21-16} = imm;
6925 }
6926}
6927
6928multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6929 SDPatternOperator OpNode> {
6930 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6931 V64, V128, vecshiftR16Narrow,
6932 asm, ".8b", ".8h",
6933 [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6934 bits<3> imm;
6935 let Inst{18-16} = imm;
6936 }
6937
6938 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6939 V128, V128, vecshiftR16Narrow,
6940 asm#"2", ".16b", ".8h", []> {
6941 bits<3> imm;
6942 let Inst{18-16} = imm;
6943 let hasSideEffects = 0;
6944 }
6945
6946 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6947 V64, V128, vecshiftR32Narrow,
6948 asm, ".4h", ".4s",
6949 [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6950 bits<4> imm;
6951 let Inst{19-16} = imm;
6952 }
6953
6954 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6955 V128, V128, vecshiftR32Narrow,
6956 asm#"2", ".8h", ".4s", []> {
6957 bits<4> imm;
6958 let Inst{19-16} = imm;
6959 let hasSideEffects = 0;
6960 }
6961
6962 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6963 V64, V128, vecshiftR64Narrow,
6964 asm, ".2s", ".2d",
6965 [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6966 bits<5> imm;
6967 let Inst{20-16} = imm;
6968 }
6969
6970 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6971 V128, V128, vecshiftR64Narrow,
6972 asm#"2", ".4s", ".2d", []> {
6973 bits<5> imm;
6974 let Inst{20-16} = imm;
6975 let hasSideEffects = 0;
6976 }
6977
6978 // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6979 // themselves, so put them here instead.
6980
6981 // Patterns involving what's effectively an insert high and a normal
6982 // intrinsic, represented by CONCAT_VECTORS.
6983 def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6984 vecshiftR16Narrow:$imm)),
6985 (!cast<Instruction>(NAME # "v16i8_shift")
6986 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6987 V128:$Rn, vecshiftR16Narrow:$imm)>;
6988 def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6989 vecshiftR32Narrow:$imm)),
6990 (!cast<Instruction>(NAME # "v8i16_shift")
6991 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6992 V128:$Rn, vecshiftR32Narrow:$imm)>;
6993 def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6994 vecshiftR64Narrow:$imm)),
6995 (!cast<Instruction>(NAME # "v4i32_shift")
6996 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6997 V128:$Rn, vecshiftR64Narrow:$imm)>;
6998}
6999
7000multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7001 SDPatternOperator OpNode> {
7002 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7003 V64, V64, vecshiftL8,
7004 asm, ".8b", ".8b",
7005 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7006 (i32 vecshiftL8:$imm)))]> {
7007 bits<3> imm;
7008 let Inst{18-16} = imm;
7009 }
7010
7011 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7012 V128, V128, vecshiftL8,
7013 asm, ".16b", ".16b",
7014 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7015 (i32 vecshiftL8:$imm)))]> {
7016 bits<3> imm;
7017 let Inst{18-16} = imm;
7018 }
7019
7020 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7021 V64, V64, vecshiftL16,
7022 asm, ".4h", ".4h",
7023 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7024 (i32 vecshiftL16:$imm)))]> {
7025 bits<4> imm;
7026 let Inst{19-16} = imm;
7027 }
7028
7029 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7030 V128, V128, vecshiftL16,
7031 asm, ".8h", ".8h",
7032 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7033 (i32 vecshiftL16:$imm)))]> {
7034 bits<4> imm;
7035 let Inst{19-16} = imm;
7036 }
7037
7038 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7039 V64, V64, vecshiftL32,
7040 asm, ".2s", ".2s",
7041 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7042 (i32 vecshiftL32:$imm)))]> {
7043 bits<5> imm;
7044 let Inst{20-16} = imm;
7045 }
7046
7047 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7048 V128, V128, vecshiftL32,
7049 asm, ".4s", ".4s",
7050 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7051 (i32 vecshiftL32:$imm)))]> {
7052 bits<5> imm;
7053 let Inst{20-16} = imm;
7054 }
7055
7056 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7057 V128, V128, vecshiftL64,
7058 asm, ".2d", ".2d",
7059 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7060 (i32 vecshiftL64:$imm)))]> {
7061 bits<6> imm;
7062 let Inst{21-16} = imm;
7063 }
7064}
7065
7066multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7067 SDPatternOperator OpNode> {
7068 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7069 V64, V64, vecshiftR8,
7070 asm, ".8b", ".8b",
7071 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7072 (i32 vecshiftR8:$imm)))]> {
7073 bits<3> imm;
7074 let Inst{18-16} = imm;
7075 }
7076
7077 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7078 V128, V128, vecshiftR8,
7079 asm, ".16b", ".16b",
7080 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7081 (i32 vecshiftR8:$imm)))]> {
7082 bits<3> imm;
7083 let Inst{18-16} = imm;
7084 }
7085
7086 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7087 V64, V64, vecshiftR16,
7088 asm, ".4h", ".4h",
7089 [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7090 (i32 vecshiftR16:$imm)))]> {
7091 bits<4> imm;
7092 let Inst{19-16} = imm;
7093 }
7094
7095 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7096 V128, V128, vecshiftR16,
7097 asm, ".8h", ".8h",
7098 [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7099 (i32 vecshiftR16:$imm)))]> {
7100 bits<4> imm;
7101 let Inst{19-16} = imm;
7102 }
7103
7104 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7105 V64, V64, vecshiftR32,
7106 asm, ".2s", ".2s",
7107 [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7108 (i32 vecshiftR32:$imm)))]> {
7109 bits<5> imm;
7110 let Inst{20-16} = imm;
7111 }
7112
7113 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7114 V128, V128, vecshiftR32,
7115 asm, ".4s", ".4s",
7116 [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7117 (i32 vecshiftR32:$imm)))]> {
7118 bits<5> imm;
7119 let Inst{20-16} = imm;
7120 }
7121
7122 def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7123 V128, V128, vecshiftR64,
7124 asm, ".2d", ".2d",
7125 [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7126 (i32 vecshiftR64:$imm)))]> {
7127 bits<6> imm;
7128 let Inst{21-16} = imm;
7129 }
7130}
7131
7132let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7133multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7134 SDPatternOperator OpNode = null_frag> {
7135 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7136 V64, V64, vecshiftR8, asm, ".8b", ".8b",
7137 [(set (v8i8 V64:$dst),
7138 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7139 (i32 vecshiftR8:$imm)))]> {
7140 bits<3> imm;
7141 let Inst{18-16} = imm;
7142 }
7143
7144 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7145 V128, V128, vecshiftR8, asm, ".16b", ".16b",
7146 [(set (v16i8 V128:$dst),
7147 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7148 (i32 vecshiftR8:$imm)))]> {
7149 bits<3> imm;
7150 let Inst{18-16} = imm;
7151 }
7152
7153 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7154 V64, V64, vecshiftR16, asm, ".4h", ".4h",
7155 [(set (v4i16 V64:$dst),
7156 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7157 (i32 vecshiftR16:$imm)))]> {
7158 bits<4> imm;
7159 let Inst{19-16} = imm;
7160 }
7161
7162 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7163 V128, V128, vecshiftR16, asm, ".8h", ".8h",
7164 [(set (v8i16 V128:$dst),
7165 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7166 (i32 vecshiftR16:$imm)))]> {
7167 bits<4> imm;
7168 let Inst{19-16} = imm;
7169 }
7170
7171 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7172 V64, V64, vecshiftR32, asm, ".2s", ".2s",
7173 [(set (v2i32 V64:$dst),
7174 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7175 (i32 vecshiftR32:$imm)))]> {
7176 bits<5> imm;
7177 let Inst{20-16} = imm;
7178 }
7179
7180 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7181 V128, V128, vecshiftR32, asm, ".4s", ".4s",
7182 [(set (v4i32 V128:$dst),
7183 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7184 (i32 vecshiftR32:$imm)))]> {
7185 bits<5> imm;
7186 let Inst{20-16} = imm;
7187 }
7188
7189 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7190 V128, V128, vecshiftR64,
7191 asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7192 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7193 (i32 vecshiftR64:$imm)))]> {
7194 bits<6> imm;
7195 let Inst{21-16} = imm;
7196 }
7197}
7198
7199multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7200 SDPatternOperator OpNode = null_frag> {
7201 def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7202 V64, V64, vecshiftL8,
7203 asm, ".8b", ".8b",
7204 [(set (v8i8 V64:$dst),
7205 (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7206 (i32 vecshiftL8:$imm)))]> {
7207 bits<3> imm;
7208 let Inst{18-16} = imm;
7209 }
7210
7211 def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7212 V128, V128, vecshiftL8,
7213 asm, ".16b", ".16b",
7214 [(set (v16i8 V128:$dst),
7215 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7216 (i32 vecshiftL8:$imm)))]> {
7217 bits<3> imm;
7218 let Inst{18-16} = imm;
7219 }
7220
7221 def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7222 V64, V64, vecshiftL16,
7223 asm, ".4h", ".4h",
7224 [(set (v4i16 V64:$dst),
7225 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7226 (i32 vecshiftL16:$imm)))]> {
7227 bits<4> imm;
7228 let Inst{19-16} = imm;
7229 }
7230
7231 def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7232 V128, V128, vecshiftL16,
7233 asm, ".8h", ".8h",
7234 [(set (v8i16 V128:$dst),
7235 (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7236 (i32 vecshiftL16:$imm)))]> {
7237 bits<4> imm;
7238 let Inst{19-16} = imm;
7239 }
7240
7241 def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7242 V64, V64, vecshiftL32,
7243 asm, ".2s", ".2s",
7244 [(set (v2i32 V64:$dst),
7245 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7246 (i32 vecshiftL32:$imm)))]> {
7247 bits<5> imm;
7248 let Inst{20-16} = imm;
7249 }
7250
7251 def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7252 V128, V128, vecshiftL32,
7253 asm, ".4s", ".4s",
7254 [(set (v4i32 V128:$dst),
7255 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7256 (i32 vecshiftL32:$imm)))]> {
7257 bits<5> imm;
7258 let Inst{20-16} = imm;
7259 }
7260
7261 def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7262 V128, V128, vecshiftL64,
7263 asm, ".2d", ".2d",
7264 [(set (v2i64 V128:$dst),
7265 (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7266 (i32 vecshiftL64:$imm)))]> {
7267 bits<6> imm;
7268 let Inst{21-16} = imm;
7269 }
7270}
7271
7272multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7273 SDPatternOperator OpNode> {
7274 def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7275 V128, V64, vecshiftL8, asm, ".8h", ".8b",
7276 [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7277 bits<3> imm;
7278 let Inst{18-16} = imm;
7279 }
7280
7281 def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7282 V128, V128, vecshiftL8,
7283 asm#"2", ".8h", ".16b",
7284 [(set (v8i16 V128:$Rd),
7285 (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7286 bits<3> imm;
7287 let Inst{18-16} = imm;
7288 }
7289
7290 def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7291 V128, V64, vecshiftL16, asm, ".4s", ".4h",
7292 [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7293 bits<4> imm;
7294 let Inst{19-16} = imm;
7295 }
7296
7297 def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7298 V128, V128, vecshiftL16,
7299 asm#"2", ".4s", ".8h",
7300 [(set (v4i32 V128:$Rd),
7301 (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7302
7303 bits<4> imm;
7304 let Inst{19-16} = imm;
7305 }
7306
7307 def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7308 V128, V64, vecshiftL32, asm, ".2d", ".2s",
7309 [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7310 bits<5> imm;
7311 let Inst{20-16} = imm;
7312 }
7313
7314 def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7315 V128, V128, vecshiftL32,
7316 asm#"2", ".2d", ".4s",
7317 [(set (v2i64 V128:$Rd),
7318 (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7319 bits<5> imm;
7320 let Inst{20-16} = imm;
7321 }
7322}
7323
7324
7325//---
7326// Vector load/store
7327//---
7328// SIMD ldX/stX no-index memory references don't allow the optional
7329// ", #0" constant and handle post-indexing explicitly, so we use
7330// a more specialized parse method for them. Otherwise, it's the same as
7331// the general am_noindex handling.
7332def MemorySIMDNoIndexOperand : AsmOperandClass {
7333 let Name = "MemorySIMDNoIndex";
7334 let ParserMethod = "tryParseNoIndexMemory";
7335}
7336def am_simdnoindex : Operand<i64>,
7337 ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7338 let PrintMethod = "printAMNoIndex";
7339 let ParserMatchClass = MemorySIMDNoIndexOperand;
7340 let MIOperandInfo = (ops GPR64sp:$base);
7341 let DecoderMethod = "DecodeGPR64spRegisterClass";
7342}
7343
7344class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7345 string asm, dag oops, dag iops, list<dag> pattern>
7346 : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7347 bits<5> Vt;
7348 bits<5> vaddr;
7349 let Inst{31} = 0;
7350 let Inst{30} = Q;
7351 let Inst{29-23} = 0b0011000;
7352 let Inst{22} = L;
7353 let Inst{21-16} = 0b000000;
7354 let Inst{15-12} = opcode;
7355 let Inst{11-10} = size;
7356 let Inst{9-5} = vaddr;
7357 let Inst{4-0} = Vt;
7358}
7359
7360class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7361 string asm, dag oops, dag iops>
7362 : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7363 bits<5> Vt;
7364 bits<5> vaddr;
7365 bits<5> Xm;
7366 let Inst{31} = 0;
7367 let Inst{30} = Q;
7368 let Inst{29-23} = 0b0011001;
7369 let Inst{22} = L;
7370 let Inst{21} = 0;
7371 let Inst{20-16} = Xm;
7372 let Inst{15-12} = opcode;
7373 let Inst{11-10} = size;
7374 let Inst{9-5} = vaddr;
7375 let Inst{4-0} = Vt;
7376 let DecoderMethod = "DecodeSIMDLdStPost";
7377}
7378
7379// The immediate form of AdvSIMD post-indexed addressing is encoded with
7380// register post-index addressing from the zero register.
7381multiclass SIMDLdStAliases<string asm, string layout, string Count,
7382 int Offset, int Size> {
7383 // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7384 // "ld1\t$Vt, $vaddr, #16"
7385 // may get mapped to
7386 // (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7387 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7388 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7389 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7390 am_simdnoindex:$vaddr, XZR), 1>;
7391
7392 // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7393 // "ld1.8b\t$Vt, $vaddr, #16"
7394 // may get mapped to
7395 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7396 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7397 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7398 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7399 am_simdnoindex:$vaddr, XZR), 0>;
7400
7401 // E.g. "ld1.8b { v0, v1 }, [x1]"
7402 // "ld1\t$Vt, $vaddr"
7403 // may get mapped to
7404 // (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7405 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7406 (!cast<Instruction>(NAME # Count # "v" # layout)
7407 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7408 am_simdnoindex:$vaddr), 0>;
7409
7410 // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7411 // "ld1\t$Vt, $vaddr, $Xm"
7412 // may get mapped to
7413 // (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7414 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7415 (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7416 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7417 am_simdnoindex:$vaddr,
7418 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7419}
7420
7421multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7422 int Offset64, bits<4> opcode> {
7423 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7424 def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7425 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7426 (ins am_simdnoindex:$vaddr), []>;
7427 def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7428 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7429 (ins am_simdnoindex:$vaddr), []>;
7430 def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7431 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7432 (ins am_simdnoindex:$vaddr), []>;
7433 def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7434 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7435 (ins am_simdnoindex:$vaddr), []>;
7436 def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7437 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7438 (ins am_simdnoindex:$vaddr), []>;
7439 def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7440 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7441 (ins am_simdnoindex:$vaddr), []>;
7442 def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7443 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7444 (ins am_simdnoindex:$vaddr), []>;
7445
7446
7447 def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7448 (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7449 (ins am_simdnoindex:$vaddr,
7450 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7451 def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7452 (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7453 (ins am_simdnoindex:$vaddr,
7454 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7455 def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7456 (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7457 (ins am_simdnoindex:$vaddr,
7458 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7459 def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7460 (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7461 (ins am_simdnoindex:$vaddr,
7462 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7463 def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7464 (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7465 (ins am_simdnoindex:$vaddr,
7466 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7467 def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7468 (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7469 (ins am_simdnoindex:$vaddr,
7470 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7471 def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7472 (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7473 (ins am_simdnoindex:$vaddr,
7474 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7475 }
7476
7477 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7478 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7479 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7480 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7481 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7482 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7483 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7484}
7485
7486// Only ld1/st1 has a v1d version.
7487multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7488 int Offset64, bits<4> opcode> {
7489 let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7490 def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7491 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7492 am_simdnoindex:$vaddr), []>;
7493 def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7494 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7495 am_simdnoindex:$vaddr), []>;
7496 def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7497 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7498 am_simdnoindex:$vaddr), []>;
7499 def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7500 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7501 am_simdnoindex:$vaddr), []>;
7502 def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7503 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7504 am_simdnoindex:$vaddr), []>;
7505 def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7506 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7507 am_simdnoindex:$vaddr), []>;
7508 def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7509 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7510 am_simdnoindex:$vaddr), []>;
7511
7512 def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7513 (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7514 am_simdnoindex:$vaddr,
7515 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7516 def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7517 (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7518 am_simdnoindex:$vaddr,
7519 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7520 def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7521 (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7522 am_simdnoindex:$vaddr,
7523 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7524 def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7525 (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7526 am_simdnoindex:$vaddr,
7527 !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7528 def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7529 (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7530 am_simdnoindex:$vaddr,
7531 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7532 def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7533 (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7534 am_simdnoindex:$vaddr,
7535 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7536 def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7537 (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7538 am_simdnoindex:$vaddr,
7539 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7540 }
7541
7542 defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7543 defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7544 defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7545 defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7546 defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7547 defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7548 defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7549}
7550
7551multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7552 int Offset128, int Offset64, bits<4> opcode>
7553 : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7554
7555 // LD1 instructions have extra "1d" variants.
7556 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7557 def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7558 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7559 (ins am_simdnoindex:$vaddr), []>;
7560
7561 def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7562 (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7563 (ins am_simdnoindex:$vaddr,
7564 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7565 }
7566
7567 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7568}
7569
7570multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7571 int Offset128, int Offset64, bits<4> opcode>
7572 : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7573
7574 // ST1 instructions have extra "1d" variants.
7575 let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7576 def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7577 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7578 am_simdnoindex:$vaddr), []>;
7579
7580 def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7581 (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7582 am_simdnoindex:$vaddr,
7583 !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7584 }
7585
7586 defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7587}
7588
7589multiclass SIMDLd1Multiple<string asm> {
7590 defm One : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7591 defm Two : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7592 defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7593 defm Four : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7594}
7595
7596multiclass SIMDSt1Multiple<string asm> {
7597 defm One : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8, 0b0111>;
7598 defm Two : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7599 defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7600 defm Four : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7601}
7602
7603multiclass SIMDLd2Multiple<string asm> {
7604 defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7605}
7606
7607multiclass SIMDSt2Multiple<string asm> {
7608 defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7609}
7610
7611multiclass SIMDLd3Multiple<string asm> {
7612 defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7613}
7614
7615multiclass SIMDSt3Multiple<string asm> {
7616 defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7617}
7618
7619multiclass SIMDLd4Multiple<string asm> {
7620 defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7621}
7622
7623multiclass SIMDSt4Multiple<string asm> {
7624 defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7625}
7626
7627//---
7628// AdvSIMD Load/store single-element
7629//---
7630
7631class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7632 string asm, string operands, dag oops, dag iops,
7633 list<dag> pattern>
7634 : I<oops, iops, asm, operands, "", pattern> {
7635 bits<5> Vt;
7636 bits<5> vaddr;
7637 let Inst{31} = 0;
7638 let Inst{29-24} = 0b001101;
7639 let Inst{22} = L;
7640 let Inst{21} = R;
7641 let Inst{15-13} = opcode;
7642 let Inst{9-5} = vaddr;
7643 let Inst{4-0} = Vt;
7644 let DecoderMethod = "DecodeSIMDLdStSingle";
7645}
7646
7647class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7648 string asm, string operands, dag oops, dag iops,
7649 list<dag> pattern>
7650 : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7651 bits<5> Vt;
7652 bits<5> vaddr;
7653 let Inst{31} = 0;
7654 let Inst{29-24} = 0b001101;
7655 let Inst{22} = L;
7656 let Inst{21} = R;
7657 let Inst{15-13} = opcode;
7658 let Inst{9-5} = vaddr;
7659 let Inst{4-0} = Vt;
7660 let DecoderMethod = "DecodeSIMDLdStSingleTied";
7661}
7662
7663
7664let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7665class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7666 Operand listtype>
7667 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7668 (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7669 let Inst{30} = Q;
7670 let Inst{23} = 0;
7671 let Inst{20-16} = 0b00000;
7672 let Inst{12} = S;
7673 let Inst{11-10} = size;
7674}
7675let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7676class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7677 string asm, Operand listtype, Operand GPR64pi>
7678 : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7679 (outs listtype:$Vt),
7680 (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7681 bits<5> Xm;
7682 let Inst{30} = Q;
7683 let Inst{23} = 1;
7684 let Inst{20-16} = Xm;
7685 let Inst{12} = S;
7686 let Inst{11-10} = size;
7687}
7688
7689multiclass SIMDLdrAliases<string asm, string layout, string Count,
7690 int Offset, int Size> {
7691 // E.g. "ld1r { v0.8b }, [x1], #1"
7692 // "ld1r.8b\t$Vt, $vaddr, #1"
7693 // may get mapped to
7694 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7695 def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7696 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7697 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7698 am_simdnoindex:$vaddr, XZR), 1>;
7699
7700 // E.g. "ld1r.8b { v0 }, [x1], #1"
7701 // "ld1r.8b\t$Vt, $vaddr, #1"
7702 // may get mapped to
7703 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7704 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7705 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7706 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7707 am_simdnoindex:$vaddr, XZR), 0>;
7708
7709 // E.g. "ld1r.8b { v0 }, [x1]"
7710 // "ld1r.8b\t$Vt, $vaddr"
7711 // may get mapped to
7712 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7713 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7714 (!cast<Instruction>(NAME # "v" # layout)
7715 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7716 am_simdnoindex:$vaddr), 0>;
7717
7718 // E.g. "ld1r.8b { v0 }, [x1], x2"
7719 // "ld1r.8b\t$Vt, $vaddr, $Xm"
7720 // may get mapped to
7721 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7722 def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7723 (!cast<Instruction>(NAME # "v" # layout # "_POST")
7724 !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7725 am_simdnoindex:$vaddr,
7726 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7727}
7728
7729multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7730 int Offset1, int Offset2, int Offset4, int Offset8> {
7731 def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7732 !cast<Operand>("VecList" # Count # "8b")>;
7733 def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7734 !cast<Operand>("VecList" # Count #"16b")>;
7735 def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7736 !cast<Operand>("VecList" # Count #"4h")>;
7737 def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7738 !cast<Operand>("VecList" # Count #"8h")>;
7739 def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7740 !cast<Operand>("VecList" # Count #"2s")>;
7741 def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7742 !cast<Operand>("VecList" # Count #"4s")>;
7743 def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7744 !cast<Operand>("VecList" # Count #"1d")>;
7745 def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7746 !cast<Operand>("VecList" # Count #"2d")>;
7747
7748 def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7749 !cast<Operand>("VecList" # Count # "8b"),
7750 !cast<Operand>("GPR64pi" # Offset1)>;
7751 def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7752 !cast<Operand>("VecList" # Count # "16b"),
7753 !cast<Operand>("GPR64pi" # Offset1)>;
7754 def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7755 !cast<Operand>("VecList" # Count # "4h"),
7756 !cast<Operand>("GPR64pi" # Offset2)>;
7757 def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7758 !cast<Operand>("VecList" # Count # "8h"),
7759 !cast<Operand>("GPR64pi" # Offset2)>;
7760 def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7761 !cast<Operand>("VecList" # Count # "2s"),
7762 !cast<Operand>("GPR64pi" # Offset4)>;
7763 def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7764 !cast<Operand>("VecList" # Count # "4s"),
7765 !cast<Operand>("GPR64pi" # Offset4)>;
7766 def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7767 !cast<Operand>("VecList" # Count # "1d"),
7768 !cast<Operand>("GPR64pi" # Offset8)>;
7769 def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7770 !cast<Operand>("VecList" # Count # "2d"),
7771 !cast<Operand>("GPR64pi" # Offset8)>;
7772
7773 defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
7774 defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7775 defm : SIMDLdrAliases<asm, "4h", Count, Offset2, 64>;
7776 defm : SIMDLdrAliases<asm, "8h", Count, Offset2, 128>;
7777 defm : SIMDLdrAliases<asm, "2s", Count, Offset4, 64>;
7778 defm : SIMDLdrAliases<asm, "4s", Count, Offset4, 128>;
7779 defm : SIMDLdrAliases<asm, "1d", Count, Offset8, 64>;
7780 defm : SIMDLdrAliases<asm, "2d", Count, Offset8, 128>;
7781}
7782
7783class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7784 dag oops, dag iops, list<dag> pattern>
7785 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7786 pattern> {
7787 // idx encoded in Q:S:size fields.
7788 bits<4> idx;
7789 let Inst{30} = idx{3};
7790 let Inst{23} = 0;
7791 let Inst{20-16} = 0b00000;
7792 let Inst{12} = idx{2};
7793 let Inst{11-10} = idx{1-0};
7794}
7795class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7796 dag oops, dag iops, list<dag> pattern>
7797 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7798 pattern> {
7799 // idx encoded in Q:S:size fields.
7800 bits<4> idx;
7801 let Inst{30} = idx{3};
7802 let Inst{23} = 0;
7803 let Inst{20-16} = 0b00000;
7804 let Inst{12} = idx{2};
7805 let Inst{11-10} = idx{1-0};
7806}
7807class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7808 dag oops, dag iops>
7809 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7810 oops, iops, []> {
7811 // idx encoded in Q:S:size fields.
7812 bits<4> idx;
7813 bits<5> Xm;
7814 let Inst{30} = idx{3};
7815 let Inst{23} = 1;
7816 let Inst{20-16} = Xm;
7817 let Inst{12} = idx{2};
7818 let Inst{11-10} = idx{1-0};
7819}
7820class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7821 dag oops, dag iops>
7822 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7823 oops, iops, []> {
7824 // idx encoded in Q:S:size fields.
7825 bits<4> idx;
7826 bits<5> Xm;
7827 let Inst{30} = idx{3};
7828 let Inst{23} = 1;
7829 let Inst{20-16} = Xm;
7830 let Inst{12} = idx{2};
7831 let Inst{11-10} = idx{1-0};
7832}
7833
7834class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7835 dag oops, dag iops, list<dag> pattern>
7836 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7837 pattern> {
7838 // idx encoded in Q:S:size<1> fields.
7839 bits<3> idx;
7840 let Inst{30} = idx{2};
7841 let Inst{23} = 0;
7842 let Inst{20-16} = 0b00000;
7843 let Inst{12} = idx{1};
7844 let Inst{11} = idx{0};
7845 let Inst{10} = size;
7846}
7847class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7848 dag oops, dag iops, list<dag> pattern>
7849 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7850 pattern> {
7851 // idx encoded in Q:S:size<1> fields.
7852 bits<3> idx;
7853 let Inst{30} = idx{2};
7854 let Inst{23} = 0;
7855 let Inst{20-16} = 0b00000;
7856 let Inst{12} = idx{1};
7857 let Inst{11} = idx{0};
7858 let Inst{10} = size;
7859}
7860
7861class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7862 dag oops, dag iops>
7863 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7864 oops, iops, []> {
7865 // idx encoded in Q:S:size<1> fields.
7866 bits<3> idx;
7867 bits<5> Xm;
7868 let Inst{30} = idx{2};
7869 let Inst{23} = 1;
7870 let Inst{20-16} = Xm;
7871 let Inst{12} = idx{1};
7872 let Inst{11} = idx{0};
7873 let Inst{10} = size;
7874}
7875class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7876 dag oops, dag iops>
7877 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7878 oops, iops, []> {
7879 // idx encoded in Q:S:size<1> fields.
7880 bits<3> idx;
7881 bits<5> Xm;
7882 let Inst{30} = idx{2};
7883 let Inst{23} = 1;
7884 let Inst{20-16} = Xm;
7885 let Inst{12} = idx{1};
7886 let Inst{11} = idx{0};
7887 let Inst{10} = size;
7888}
7889class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7890 dag oops, dag iops, list<dag> pattern>
7891 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7892 pattern> {
7893 // idx encoded in Q:S fields.
7894 bits<2> idx;
7895 let Inst{30} = idx{1};
7896 let Inst{23} = 0;
7897 let Inst{20-16} = 0b00000;
7898 let Inst{12} = idx{0};
7899 let Inst{11-10} = size;
7900}
7901class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7902 dag oops, dag iops, list<dag> pattern>
7903 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7904 pattern> {
7905 // idx encoded in Q:S fields.
7906 bits<2> idx;
7907 let Inst{30} = idx{1};
7908 let Inst{23} = 0;
7909 let Inst{20-16} = 0b00000;
7910 let Inst{12} = idx{0};
7911 let Inst{11-10} = size;
7912}
7913class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7914 string asm, dag oops, dag iops>
7915 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7916 oops, iops, []> {
7917 // idx encoded in Q:S fields.
7918 bits<2> idx;
7919 bits<5> Xm;
7920 let Inst{30} = idx{1};
7921 let Inst{23} = 1;
7922 let Inst{20-16} = Xm;
7923 let Inst{12} = idx{0};
7924 let Inst{11-10} = size;
7925}
7926class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7927 string asm, dag oops, dag iops>
7928 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7929 oops, iops, []> {
7930 // idx encoded in Q:S fields.
7931 bits<2> idx;
7932 bits<5> Xm;
7933 let Inst{30} = idx{1};
7934 let Inst{23} = 1;
7935 let Inst{20-16} = Xm;
7936 let Inst{12} = idx{0};
7937 let Inst{11-10} = size;
7938}
7939class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7940 dag oops, dag iops, list<dag> pattern>
7941 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7942 pattern> {
7943 // idx encoded in Q field.
7944 bits<1> idx;
7945 let Inst{30} = idx;
7946 let Inst{23} = 0;
7947 let Inst{20-16} = 0b00000;
7948 let Inst{12} = 0;
7949 let Inst{11-10} = size;
7950}
7951class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7952 dag oops, dag iops, list<dag> pattern>
7953 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7954 pattern> {
7955 // idx encoded in Q field.
7956 bits<1> idx;
7957 let Inst{30} = idx;
7958 let Inst{23} = 0;
7959 let Inst{20-16} = 0b00000;
7960 let Inst{12} = 0;
7961 let Inst{11-10} = size;
7962}
7963class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7964 string asm, dag oops, dag iops>
7965 : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7966 oops, iops, []> {
7967 // idx encoded in Q field.
7968 bits<1> idx;
7969 bits<5> Xm;
7970 let Inst{30} = idx;
7971 let Inst{23} = 1;
7972 let Inst{20-16} = Xm;
7973 let Inst{12} = 0;
7974 let Inst{11-10} = size;
7975}
7976class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7977 string asm, dag oops, dag iops>
7978 : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7979 oops, iops, []> {
7980 // idx encoded in Q field.
7981 bits<1> idx;
7982 bits<5> Xm;
7983 let Inst{30} = idx;
7984 let Inst{23} = 1;
7985 let Inst{20-16} = Xm;
7986 let Inst{12} = 0;
7987 let Inst{11-10} = size;
7988}
7989
7990let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7991multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7992 RegisterOperand listtype,
7993 RegisterOperand GPR64pi> {
7994 def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7995 (outs listtype:$dst),
7996 (ins listtype:$Vt, VectorIndexB:$idx,
7997 am_simdnoindex:$vaddr), []>;
7998
7999 def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8000 (outs listtype:$dst),
8001 (ins listtype:$Vt, VectorIndexB:$idx,
8002 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8003}
8004let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8005multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8006 RegisterOperand listtype,
8007 RegisterOperand GPR64pi> {
8008 def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8009 (outs listtype:$dst),
8010 (ins listtype:$Vt, VectorIndexH:$idx,
8011 am_simdnoindex:$vaddr), []>;
8012
8013 def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8014 (outs listtype:$dst),
8015 (ins listtype:$Vt, VectorIndexH:$idx,
8016 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8017}
8018let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8019multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8020 RegisterOperand listtype,
8021 RegisterOperand GPR64pi> {
8022 def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8023 (outs listtype:$dst),
8024 (ins listtype:$Vt, VectorIndexS:$idx,
8025 am_simdnoindex:$vaddr), []>;
8026
8027 def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8028 (outs listtype:$dst),
8029 (ins listtype:$Vt, VectorIndexS:$idx,
8030 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8031}
8032let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8033multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008034 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008035 def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8036 (outs listtype:$dst),
8037 (ins listtype:$Vt, VectorIndexD:$idx,
8038 am_simdnoindex:$vaddr), []>;
8039
8040 def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8041 (outs listtype:$dst),
8042 (ins listtype:$Vt, VectorIndexD:$idx,
8043 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8044}
8045let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8046multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008047 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008048 def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8049 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008050 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008051
8052 def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8053 (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8054 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8055}
8056let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8057multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008058 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008059 def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8060 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008061 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008062
8063 def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8064 (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8065 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8066}
8067let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8068multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008069 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008070 def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8071 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008072 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008073
8074 def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8075 (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8076 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8077}
8078let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8079multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
Tim Northoverff179ba2014-04-01 10:37:09 +00008080 RegisterOperand listtype, RegisterOperand GPR64pi> {
Tim Northover00ed9962014-03-29 10:18:08 +00008081 def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8082 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
Tim Northoverff179ba2014-04-01 10:37:09 +00008083 am_simdnoindex:$vaddr), []>;
Tim Northover00ed9962014-03-29 10:18:08 +00008084
8085 def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8086 (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8087 am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8088}
8089
8090multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8091 string Count, int Offset, Operand idxtype> {
8092 // E.g. "ld1 { v0.8b }[0], [x1], #1"
8093 // "ld1\t$Vt, $vaddr, #1"
8094 // may get mapped to
8095 // (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8096 def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8097 (!cast<Instruction>(NAME # Type # "_POST")
8098 !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8099 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8100
8101 // E.g. "ld1.8b { v0 }[0], [x1], #1"
8102 // "ld1.8b\t$Vt, $vaddr, #1"
8103 // may get mapped to
8104 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8105 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8106 (!cast<Instruction>(NAME # Type # "_POST")
8107 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8108 idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8109
8110 // E.g. "ld1.8b { v0 }[0], [x1]"
8111 // "ld1.8b\t$Vt, $vaddr"
8112 // may get mapped to
8113 // (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8114 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8115 (!cast<Instruction>(NAME # Type)
8116 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8117 idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8118
8119 // E.g. "ld1.8b { v0 }[0], [x1], x2"
8120 // "ld1.8b\t$Vt, $vaddr, $Xm"
8121 // may get mapped to
8122 // (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8123 def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8124 (!cast<Instruction>(NAME # Type # "_POST")
8125 !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8126 idxtype:$idx, am_simdnoindex:$vaddr,
8127 !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8128}
8129
8130multiclass SIMDLdSt1SingleAliases<string asm> {
8131 defm : SIMDLdStSingleAliases<asm, "b", "i8", "One", 1, VectorIndexB>;
8132 defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8133 defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8134 defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8135}
8136
8137multiclass SIMDLdSt2SingleAliases<string asm> {
8138 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Two", 2, VectorIndexB>;
8139 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4, VectorIndexH>;
8140 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8, VectorIndexS>;
8141 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8142}
8143
8144multiclass SIMDLdSt3SingleAliases<string asm> {
8145 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Three", 3, VectorIndexB>;
8146 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6, VectorIndexH>;
8147 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8148 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8149}
8150
8151multiclass SIMDLdSt4SingleAliases<string asm> {
8152 defm : SIMDLdStSingleAliases<asm, "b", "i8", "Four", 4, VectorIndexB>;
8153 defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8, VectorIndexH>;
8154 defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8155 defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8156}
8157
8158//----------------------------------------------------------------------------
8159// Crypto extensions
8160//----------------------------------------------------------------------------
8161
8162let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8163class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8164 list<dag> pat>
8165 : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8166 Sched<[WriteV]>{
8167 bits<5> Rd;
8168 bits<5> Rn;
8169 let Inst{31-16} = 0b0100111000101000;
8170 let Inst{15-12} = opc;
8171 let Inst{11-10} = 0b10;
8172 let Inst{9-5} = Rn;
8173 let Inst{4-0} = Rd;
8174}
8175
8176class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8177 : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8178 [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8179
8180class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8181 : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8182 "$Rd = $dst",
8183 [(set (v16i8 V128:$dst),
8184 (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8185
8186let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8187class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8188 dag oops, dag iops, list<dag> pat>
8189 : I<oops, iops, asm,
8190 "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8191 "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8192 Sched<[WriteV]>{
8193 bits<5> Rd;
8194 bits<5> Rn;
8195 bits<5> Rm;
8196 let Inst{31-21} = 0b01011110000;
8197 let Inst{20-16} = Rm;
8198 let Inst{15} = 0;
8199 let Inst{14-12} = opc;
8200 let Inst{11-10} = 0b00;
8201 let Inst{9-5} = Rn;
8202 let Inst{4-0} = Rd;
8203}
8204
8205class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8206 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8207 (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8208 [(set (v4i32 FPR128:$dst),
8209 (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8210 (v4i32 V128:$Rm)))]>;
8211
8212class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8213 : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8214 (ins V128:$Rd, V128:$Rn, V128:$Rm),
8215 [(set (v4i32 V128:$dst),
8216 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8217 (v4i32 V128:$Rm)))]>;
8218
8219class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8220 : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8221 (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8222 [(set (v4i32 FPR128:$dst),
8223 (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8224 (v4i32 V128:$Rm)))]>;
8225
8226let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8227class SHA2OpInst<bits<4> opc, string asm, string kind,
8228 string cstr, dag oops, dag iops,
8229 list<dag> pat>
8230 : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8231 "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8232 Sched<[WriteV]>{
8233 bits<5> Rd;
8234 bits<5> Rn;
8235 let Inst{31-16} = 0b0101111000101000;
8236 let Inst{15-12} = opc;
8237 let Inst{11-10} = 0b10;
8238 let Inst{9-5} = Rn;
8239 let Inst{4-0} = Rd;
8240}
8241
8242class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8243 : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8244 (ins V128:$Rd, V128:$Rn),
8245 [(set (v4i32 V128:$dst),
8246 (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8247
8248class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8249 : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8250 [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8251
8252// Allow the size specifier tokens to be upper case, not just lower.
8253def : TokenAlias<".8B", ".8b">;
8254def : TokenAlias<".4H", ".4h">;
8255def : TokenAlias<".2S", ".2s">;
8256def : TokenAlias<".1D", ".1d">;
8257def : TokenAlias<".16B", ".16b">;
8258def : TokenAlias<".8H", ".8h">;
8259def : TokenAlias<".4S", ".4s">;
8260def : TokenAlias<".2D", ".2d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008261def : TokenAlias<".1Q", ".1q">;
Tim Northover00ed9962014-03-29 10:18:08 +00008262def : TokenAlias<".B", ".b">;
8263def : TokenAlias<".H", ".h">;
8264def : TokenAlias<".S", ".s">;
8265def : TokenAlias<".D", ".d">;
Bradley Smith6d7af172014-04-09 14:42:01 +00008266def : TokenAlias<".Q", ".q">;