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