]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/Hexagon/HexagonPseudo.td
Merge ^/head r344178 through r344512.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / Hexagon / HexagonPseudo.td
1 //===--- HexagonPseudo.td -------------------------------------------------===//
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 // The pat frags in the definitions below need to have a named register,
11 // otherwise i32 will be assumed regardless of the register class. The
12 // name of the register does not matter.
13 def I1  : PatLeaf<(i1 PredRegs:$R)>;
14 def I32 : PatLeaf<(i32 IntRegs:$R)>;
15 def I64 : PatLeaf<(i64 DoubleRegs:$R)>;
16 def F32 : PatLeaf<(f32 IntRegs:$R)>;
17 def F64 : PatLeaf<(f64 DoubleRegs:$R)>;
18
19 let PrintMethod = "printGlobalOperand" in {
20   def globaladdress : Operand<i32>;
21   def globaladdressExt : Operand<i32>;
22 }
23
24 let isPseudo = 1 in {
25 let isCodeGenOnly = 0 in
26 def A2_iconst : Pseudo<(outs IntRegs:$Rd32),
27     (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;
28
29 def DUPLEX_Pseudo : InstHexagon<(outs),
30     (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
31 }
32
33 let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
34     isAsmParserOnly = 1 in
35 def TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst),
36     (ins s32_0Imm:$src1, s8_0Imm:$src2),
37     "$dst = combine(#$src1,#$src2)", [], "",
38     A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
39
40 // HI/LO Instructions
41 let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0,
42     hasNewValue = 1, opNewValue = 0 in
43 class REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp,
44                 InstHexagon rootInst>
45   : InstHexagon<(outs IntRegs:$dst),
46                 (ins u16_0Imm:$imm_value),
47                 "$dst"#RegHalf#" = #$imm_value", [], "",
48                 rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
49     bits<5> dst;
50     bits<32> imm_value;
51
52     let Inst{27} = Rs;
53     let Inst{26-24} = MajOp;
54     let Inst{21} = MinOp;
55     let Inst{20-16} = dst;
56     let Inst{23-22} = imm_value{15-14};
57     let Inst{13-0} = imm_value{13-0};
58 }
59
60 let isAsmParserOnly = 1 in {
61   def LO : REG_IMMED<".l", 0b0, 0b001, 0b1, A2_tfril>;
62   def HI : REG_IMMED<".h", 0b0, 0b010, 0b1, A2_tfrih>;
63 }
64
65 let isReMaterializable = 1, isMoveImm = 1, isAsmParserOnly = 1 in {
66   def CONST32 : CONSTLDInst<(outs IntRegs:$Rd), (ins i32imm:$v),
67                 "$Rd = CONST32(#$v)", []>;
68   def CONST64 : CONSTLDInst<(outs DoubleRegs:$Rd), (ins i64imm:$v),
69                 "$Rd = CONST64(#$v)", []>;
70 }
71
72 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
73     isCodeGenOnly = 1 in
74 def PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "",
75               [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>;
76
77 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
78     isCodeGenOnly = 1 in
79 def PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "",
80                [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>;
81
82 let Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in
83 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
84                               ".error \"should not emit\" ", []>;
85
86 let Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in
87 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
88                              ".error \"should not emit\" ", []>;
89
90
91 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
92     Defs = [PC, LC0], Uses = [SA0, LC0] in {
93 def ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset),
94                        ":endloop0",
95                        []>;
96 }
97
98 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
99     Defs = [PC, LC1], Uses = [SA1, LC1] in {
100 def ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset),
101                        ":endloop1",
102                        []>;
103 }
104
105 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
106     Defs = [PC, LC0, LC1], Uses = [SA0, SA1, LC0, LC1] in {
107 def ENDLOOP01 : Endloop<(outs), (ins b30_2Imm:$offset),
108                         ":endloop01",
109                         []>;
110 }
111
112 let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
113     opExtendable = 0, hasSideEffects = 0 in
114 class LOOP_iBase<string mnemonic, InstHexagon rootInst>
115          : InstHexagon <(outs), (ins b30_2Imm:$offset, u10_0Imm:$src2),
116            #mnemonic#"($offset,#$src2)",
117            [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
118     bits<9> offset;
119     bits<10> src2;
120
121     let IClass = 0b0110;
122
123     let Inst{27-22} = 0b100100;
124     let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);
125     let Inst{20-16} = src2{9-5};
126     let Inst{12-8} = offset{8-4};
127     let Inst{7-5} = src2{4-2};
128     let Inst{4-3} = offset{3-2};
129     let Inst{1-0} = src2{1-0};
130 }
131
132 let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
133     opExtendable = 0, hasSideEffects = 0 in
134 class LOOP_rBase<string mnemonic, InstHexagon rootInst>
135          : InstHexagon<(outs), (ins b30_2Imm:$offset, IntRegs:$src2),
136            #mnemonic#"($offset,$src2)",
137            [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
138     bits<9> offset;
139     bits<5> src2;
140
141     let IClass = 0b0110;
142
143     let Inst{27-22} = 0b000000;
144     let Inst{21} = !if (!eq(mnemonic, "loop0"), 0b0, 0b1);
145     let Inst{20-16} = src2;
146     let Inst{12-8} = offset{8-4};
147     let Inst{4-3} = offset{3-2};
148   }
149
150 let Defs = [SA0, LC0, USR], isCodeGenOnly = 1, isExtended = 1,
151     opExtendable = 0 in {
152   def J2_loop0iext : LOOP_iBase<"loop0", J2_loop0i>;
153   def J2_loop1iext : LOOP_iBase<"loop1", J2_loop1i>;
154 }
155
156 // Interestingly only loop0's appear to set usr.lpcfg
157 let Defs = [SA1, LC1], isCodeGenOnly = 1, isExtended = 1, opExtendable = 0 in {
158   def J2_loop0rext : LOOP_rBase<"loop0", J2_loop0r>;
159   def J2_loop1rext : LOOP_rBase<"loop1", J2_loop1r>;
160 }
161
162 let isCall = 1, hasSideEffects = 1, isPredicable = 0,
163     isExtended = 0, isExtendable = 1, opExtendable = 0,
164     isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in
165 class T_Call<string ExtStr>
166   : InstHexagon<(outs), (ins a30_2Imm:$dst),
167       "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>,
168     OpcodeHexagon {
169   let BaseOpcode = "call";
170   bits<24> dst;
171
172   let IClass = 0b0101;
173   let Inst{27-25} = 0b101;
174   let Inst{24-16,13-1} = dst{23-2};
175   let Inst{0} = 0b0;
176 }
177
178 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
179     isPredicable = 0 in
180 def CALLProfile :  T_Call<"">;
181
182 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
183     Defs = [PC, R31, R6, R7, P0] in
184 def PS_call_stk : T_Call<"">;
185
186 // Call, no return.
187 let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in
188 def PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs),
189     "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon {
190     bits<5> Rs;
191     bits<2> Pu;
192     let isPredicatedFalse = 1;
193
194     let IClass = 0b0101;
195     let Inst{27-21} = 0b0000101;
196     let Inst{20-16} = Rs;
197   }
198
199 let isCall = 1, hasSideEffects = 1,
200     isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
201     BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in
202 class Call_nr<bits<5> nbits, bit isPred, bit isFalse, dag iops,
203               InstrItinClass itin>
204   : Pseudo<(outs), iops, "">, PredRel {
205     bits<2> Pu;
206     bits<17> dst;
207     let opExtentBits = nbits;
208     let isPredicable = 0;  // !if(isPred, 0, 1);
209     let isPredicated = 0;  // isPred;
210     let isPredicatedFalse = isFalse;
211     let Itinerary = itin;
212 }
213
214 def PS_call_nr : Call_nr<24, 0, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>;
215 //def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst),
216 //                         J2_callt.Itinerary>;
217 //def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst),
218 //                         J2_callf.Itinerary>;
219
220 let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC],
221     isPredicable = 1, hasSideEffects = 0, InputType = "reg",
222     cofMax1 = 1 in
223 class T_JMPr <InstHexagon rootInst>
224   :  InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [],
225                  "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
226     bits<5> dst;
227
228     let IClass = 0b0101;
229     let Inst{27-21} = 0b0010100;
230     let Inst{20-16} = dst;
231 }
232
233 // A return through builtin_eh_return.
234 let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0,
235     isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in
236 def EH_RETURN_JMPR : T_JMPr<J2_jumpr>;
237
238 // Indirect tail-call.
239 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
240     isTerminator = 1, isCodeGenOnly = 1 in
241 def PS_tailcall_r : T_JMPr<J2_jumpr>;
242
243 //
244 // Direct tail-calls.
245 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
246     isTerminator = 1, isCodeGenOnly = 1 in
247 def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>;
248
249 let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in
250 def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>;
251
252 // Generate frameindex addresses. The main reason for the offset operand is
253 // that every instruction that is allowed to have frame index as an operand
254 // will then have that operand followed by an immediate operand (the offset).
255 // This simplifies the frame-index elimination code.
256 //
257 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1,
258     isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1,
259     isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in {
260   let opExtendable = 2 in
261   def PS_fi  : Pseudo<(outs IntRegs:$Rd),
262                       (ins IntRegs:$fi, s32_0Imm:$off), "">;
263   let opExtendable = 3 in
264   def PS_fia : Pseudo<(outs IntRegs:$Rd),
265                       (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">;
266 }
267
268 class CondStr<string CReg, bit True, bit New> {
269   string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") ";
270 }
271 class JumpOpcStr<string Mnemonic, bit New, bit Taken> {
272   string S = Mnemonic # !if(Taken, ":t", ":nt");
273 }
274 let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1,
275     hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in
276 class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst>
277   :  InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst),
278                  CondStr<"$src", !if(PredNot,0,1), isPredNew>.S #
279                  JumpOpcStr<"jumpr", isPredNew, isTak>.S # " $dst",
280                  [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
281
282     let isTaken = isTak;
283     let isPredicatedFalse = PredNot;
284     let isPredicatedNew = isPredNew;
285     bits<2> src;
286     bits<5> dst;
287
288     let IClass = 0b0101;
289
290     let Inst{27-22} = 0b001101;
291     let Inst{21} = PredNot;
292     let Inst{20-16} = dst;
293     let Inst{12} = isTak;
294     let Inst{11} = isPredNew;
295     let Inst{9-8} = src;
296 }
297
298 let isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1,
299     isBarrier = 1, BaseOpcode = "JMPret" in {
300   def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel;
301   def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel;
302   def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel;
303   def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel;
304   def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel;
305   def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel;
306   def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel;
307 }
308
309 //defm V6_vtran2x2_map : HexagonMapping<(outs HvxVR:$Vy32, HvxVR:$Vx32), (ins HvxVR:$Vx32in, IntRegs:$Rt32), "vtrans2x2(${Vy32},${Vx32},${Rt32})", (V6_vshuff HvxVR:$Vy32, HvxVR:$Vx32, HvxVR:$Vx32in, IntRegs:$Rt32)>;
310
311 // The reason for the custom inserter is to record all ALLOCA instructions
312 // in MachineFunctionInfo.
313 let Defs = [R29], hasSideEffects = 1 in
314 def PS_alloca: Pseudo <(outs IntRegs:$Rd),
315                        (ins IntRegs:$Rs, u32_0Imm:$A), "", []>;
316
317 // Load predicate.
318 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
319     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
320 def LDriw_pred : LDInst<(outs PredRegs:$dst),
321                         (ins IntRegs:$addr, s32_0Imm:$off),
322                         ".error \"should not emit\"", []>;
323
324 // Load modifier.
325 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
326     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
327 def LDriw_ctr : LDInst<(outs CtrRegs:$dst),
328                         (ins IntRegs:$addr, s32_0Imm:$off),
329                         ".error \"should not emit\"", []>;
330
331
332 let isCodeGenOnly = 1, isPseudo = 1 in
333 def PS_pselect: InstHexagon<(outs DoubleRegs:$Rd),
334       (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt),
335       ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>;
336
337 let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0,
338     isPredicable = 1,
339     isExtendable = 1, opExtendable = 0, isExtentSigned = 1,
340     opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in
341 class T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst),
342       "jump $dst",
343       [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon {
344     bits<24> dst;
345     let IClass = 0b0101;
346
347     let Inst{27-25} = 0b100;
348     let Inst{24-16} = dst{23-15};
349     let Inst{13-1} = dst{14-2};
350 }
351
352 // Restore registers and dealloc return function call.
353 let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
354     Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in {
355   def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP;
356
357   let isExtended = 1, opExtendable = 0 in
358   def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP;
359
360   let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
361     def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP;
362
363     let isExtended = 1, opExtendable = 0 in
364     def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP;
365   }
366 }
367
368 // Restore registers and dealloc frame before a tail call.
369 let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
370   def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;
371
372   let isExtended = 1, opExtendable = 0 in
373   def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel;
374
375   let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
376     def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel;
377
378     let isExtended = 1, opExtendable = 0 in
379     def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel;
380   }
381 }
382
383 // Save registers function call.
384 let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
385   def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;
386
387   let isExtended = 1, opExtendable = 0 in
388   def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel;
389
390   let Defs = [P0] in
391   def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel;
392
393   let Defs = [P0], isExtended = 1, opExtendable = 0 in
394   def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel;
395
396   let Defs = [R14, R15, R28] in
397   def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel;
398
399   let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in
400   def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel;
401
402   let Defs = [R14, R15, R28, P0] in
403   def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel;
404
405   let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in
406   def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel;
407 }
408
409 // Vector store pseudos
410 let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,
411     mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
412 class STrivv_template<RegisterClass RC, InstHexagon rootInst>
413   : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),
414     "", [], "", rootInst.Itinerary, rootInst.Type>;
415
416 def PS_vstorerw_ai: STrivv_template<HvxWR, V6_vS32b_ai>,
417       Requires<[HasV60,UseHVX]>;
418 def PS_vstorerw_nt_ai: STrivv_template<HvxWR, V6_vS32b_nt_ai>,
419       Requires<[HasV60,UseHVX]>;
420 def PS_vstorerwu_ai: STrivv_template<HvxWR, V6_vS32Ub_ai>,
421       Requires<[HasV60,UseHVX]>;
422
423 let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in
424 def PS_vstorerq_ai: Pseudo<(outs),
425       (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>,
426       Requires<[HasV60,UseHVX]>;
427
428 // Vector load pseudos
429 let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,
430     mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
431 class LDrivv_template<RegisterClass RC, InstHexagon rootInst>
432   : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),
433     "", [], "", rootInst.Itinerary, rootInst.Type>;
434
435 def PS_vloadrw_ai: LDrivv_template<HvxWR, V6_vL32b_ai>,
436       Requires<[HasV60,UseHVX]>;
437 def PS_vloadrw_nt_ai: LDrivv_template<HvxWR, V6_vL32b_nt_ai>,
438       Requires<[HasV60,UseHVX]>;
439 def PS_vloadrwu_ai: LDrivv_template<HvxWR, V6_vL32Ub_ai>,
440       Requires<[HasV60,UseHVX]>;
441
442 let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in
443 def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd),
444       (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>,
445       Requires<[HasV60,UseHVX]>;
446
447
448 let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
449 class VSELInst<dag outs, dag ins, InstHexagon rootInst>
450   : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>;
451
452 def PS_vselect: VSELInst<(outs HvxVR:$dst),
453       (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>,
454       Requires<[HasV60,UseHVX]>;
455 def PS_wselect: VSELInst<(outs HvxWR:$dst),
456       (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>,
457       Requires<[HasV60,UseHVX]>;
458
459 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
460     isCodeGenOnly = 1 in {
461   def PS_qtrue:  InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
462                  V6_veqw.Itinerary, TypeCVI_VA>;
463   def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
464                  V6_vgtw.Itinerary, TypeCVI_VA>;
465   def PS_vdd0:   InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "",
466                  V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>;
467 }
468
469 // Store predicate.
470 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
471     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
472 def STriw_pred : STInst<(outs),
473       (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1),
474       ".error \"should not emit\"", []>;
475 // Store modifier.
476 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
477     isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
478 def STriw_ctr : STInst<(outs),
479       (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),
480       ".error \"should not emit\"", []>;
481
482 let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
483     isAsmParserOnly = 1 in
484 def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst),
485     (ins u64_0Imm:$src1),
486     "$dst = #$src1", [], "",
487     A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
488
489 // Hexagon doesn't have a vector multiply with C semantics.
490 // Instead, generate a pseudo instruction that gets expaneded into two
491 // scalar MPYI instructions.
492 // This is expanded by ExpandPostRAPseudos.
493 let isPseudo = 1 in
494 def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd),
495       (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>;
496
497 let isPseudo = 1 in
498 def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd),
499       (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [],
500       "$Rd = $Rx">;
501
502 def DuplexIClass0:  InstDuplex < 0 >;
503 def DuplexIClass1:  InstDuplex < 1 >;
504 def DuplexIClass2:  InstDuplex < 2 >;
505 let isExtendable = 1 in {
506   def DuplexIClass3:  InstDuplex < 3 >;
507   def DuplexIClass4:  InstDuplex < 4 >;
508   def DuplexIClass5:  InstDuplex < 5 >;
509   def DuplexIClass6:  InstDuplex < 6 >;
510   def DuplexIClass7:  InstDuplex < 7 >;
511 }
512 def DuplexIClass8:  InstDuplex < 8 >;
513 def DuplexIClass9:  InstDuplex < 9 >;
514 def DuplexIClassA:  InstDuplex < 0xA >;
515 def DuplexIClassB:  InstDuplex < 0xB >;
516 def DuplexIClassC:  InstDuplex < 0xC >;
517 def DuplexIClassD:  InstDuplex < 0xD >;
518 def DuplexIClassE:  InstDuplex < 0xE >;
519 def DuplexIClassF:  InstDuplex < 0xF >;
520
521 // Pseudos for circular buffer instructions. These are needed in order to
522 // allocate the correct pair of CSx and Mx registers.
523 multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {
524
525 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
526     addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
527   def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
528        (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),
529        ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e93a3d71>;
530
531   def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
532        (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),
533        ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_44d3da28>;
534 }
535 }
536
537 defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;
538 defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;
539 defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;
540 defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;
541 defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;
542 defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;
543
544 multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> {
545
546 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
547     addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
548   def NAME#_pci : STInst<(outs IntRegs:$Rx32),
549        (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
550        ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e86aa961>;
551
552   def NAME#_pcr : STInst<(outs IntRegs:$Rx32),
553        (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
554        ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_da97ee82>;
555 }
556 }
557
558 defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;
559 defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;
560 defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;
561 defm PS_storeri : NewCircularStore<IntRegs, WordAccess>;
562 defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;