1 //===--- HexagonPseudo.td -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
12 def I1 : PatLeaf<(i1 PredRegs:$R)>;
13 def I32 : PatLeaf<(i32 IntRegs:$R)>;
14 def I64 : PatLeaf<(i64 DoubleRegs:$R)>;
15 def F32 : PatLeaf<(f32 IntRegs:$R)>;
16 def F64 : PatLeaf<(f64 DoubleRegs:$R)>;
18 let PrintMethod = "printGlobalOperand" in {
19 def globaladdress : Operand<i32>;
20 def globaladdressExt : Operand<i32>;
24 let isCodeGenOnly = 0 in
25 def A2_iconst : Pseudo<(outs IntRegs:$Rd32),
26 (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;
28 def DUPLEX_Pseudo : InstHexagon<(outs),
29 (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
32 let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
33 isAsmParserOnly = 1 in
34 def 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;
40 let isReMaterializable = 1, isMoveImm = 1, hasSideEffects = 0,
41 hasNewValue = 1, opNewValue = 0 in
42 class REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp,
44 : InstHexagon<(outs IntRegs:$dst),
45 (ins u16_0Imm:$imm_value),
46 "$dst"#RegHalf#" = #$imm_value", [], "",
47 rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
52 let Inst{26-24} = MajOp;
54 let Inst{20-16} = dst;
55 let Inst{23-22} = imm_value{15-14};
56 let Inst{13-0} = imm_value{13-0};
59 let 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>;
64 let 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)", []>;
71 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
73 def PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "",
74 [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>;
76 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
78 def PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "",
79 [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>;
81 let Defs = [R29, R30], Uses = [R31, R30, R29], isPseudo = 1 in
82 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
83 ".error \"should not emit\" ", []>;
85 let Defs = [R29, R30, R31], Uses = [R29], isPseudo = 1 in
86 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
87 ".error \"should not emit\" ", []>;
90 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
91 Defs = [PC, LC0], Uses = [SA0, LC0] in {
92 def ENDLOOP0 : Endloop<(outs), (ins b30_2Imm:$offset),
97 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
98 Defs = [PC, LC1], Uses = [SA1, LC1] in {
99 def ENDLOOP1 : Endloop<(outs), (ins b30_2Imm:$offset),
104 let isBranch = 1, isTerminator = 1, hasSideEffects = 0,
105 Defs = [PC, LC0, LC1], Uses = [SA0, SA1, LC0, LC1] in {
106 def ENDLOOP01 : Endloop<(outs), (ins b30_2Imm:$offset),
111 let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
112 opExtendable = 0, hasSideEffects = 0 in
113 class 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 {
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};
131 let isExtendable = 1, isExtentSigned = 1, opExtentBits = 9, opExtentAlign = 2,
132 opExtendable = 0, hasSideEffects = 0 in
133 class 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 {
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};
149 let 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>;
155 // Interestingly only loop0's appear to set usr.lpcfg
156 let 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>;
161 let isCall = 1, hasSideEffects = 1, isPredicable = 0,
162 isExtended = 0, isExtendable = 1, opExtendable = 0,
163 isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in
164 class T_Call<string ExtStr>
165 : InstHexagon<(outs), (ins a30_2Imm:$dst),
166 "call " # ExtStr # "$dst", [], "", J2_call.Itinerary, TypeJ>,
168 let BaseOpcode = "call";
172 let Inst{27-25} = 0b101;
173 let Inst{24-16,13-1} = dst{23-2};
177 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
179 def CALLProfile : T_Call<"">;
181 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
182 Defs = [PC, R31, R6, R7, P0] in
183 def PS_call_stk : T_Call<"">;
185 // This pseudo instruction is used to replace int_hexagon_instrprof_custom intrinsic
186 // with a call to custom handler passed as the first argument to the intrinsic.
189 // 1) The call to the custom handler is being treated as a special one as the
190 // callee is responsible for saving and restoring all the registers it needs
191 // to modify. This includes caller saved registers as well as r0-r5 argument
192 // registers. This is done to reduce the impact of instrumentation on the
193 // code being instrumented/profiled.
194 // 2) R14, R15 and R28 are reserved for PLT handling and therefore are
195 // part of the def list.
196 // 3) R0 is used to pass the unique id associated with an instrumentation site
198 // 4) All the other registers (R29, R30, R31, PC) get modified by the call
201 // TODO: It may be a good idea to add a separate pseudo instruction for
202 // static relocation which doesn't need to reserve r14, r15 and r28.
204 let hasSideEffects = 1, isCall = 1, Defs = [R0, R14, R15, R28, R29, R30, R31, PC] in
205 def PS_call_instrprof_custom : Pseudo<(outs), (ins s32_0Imm:$dst, u32_0Imm:$Ii), "">;
208 let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in
209 def PS_callr_nr: InstHexagon<(outs), (ins IntRegs:$Rs),
210 "callr $Rs", [], "", J2_callr.Itinerary, TypeJ>, OpcodeHexagon {
213 let isPredicatedFalse = 1;
216 let Inst{27-21} = 0b0000101;
217 let Inst{20-16} = Rs;
220 let isCall = 1, hasSideEffects = 1,
221 isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
222 BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in
223 class Call_nr<bits<5> nbits, bit isFalse, dag iops,
225 : Pseudo<(outs), iops, "">, PredRel {
228 let opExtentBits = nbits;
229 let isPredicable = 0; // !if(isPred, 0, 1);
230 let isPredicated = 0; // isPred;
231 let isPredicatedFalse = isFalse;
232 let Itinerary = itin;
235 def PS_call_nr : Call_nr<24, 0, (ins s32_0Imm:$Ii), J2_call.Itinerary>;
236 //def PS_call_nrt: Call_nr<17, 1, 0, (ins PredRegs:$Pu, s32_0Imm:$dst),
237 // J2_callt.Itinerary>;
238 //def PS_call_nrf: Call_nr<17, 1, 1, (ins PredRegs:$Pu, s32_0Imm:$dst),
239 // J2_callf.Itinerary>;
241 let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC],
242 isPredicable = 1, hasSideEffects = 0, InputType = "reg",
244 class T_JMPr <InstHexagon rootInst>
245 : InstHexagon<(outs), (ins IntRegs:$dst), "jumpr $dst", [],
246 "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
250 let Inst{27-21} = 0b0010100;
251 let Inst{20-16} = dst;
254 // A return through builtin_eh_return.
255 let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0,
256 isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in
257 def EH_RETURN_JMPR : T_JMPr<J2_jumpr>;
259 // Indirect tail-call.
260 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
261 isTerminator = 1, isCodeGenOnly = 1 in
262 def PS_tailcall_r : T_JMPr<J2_jumpr>;
265 // Direct tail-calls.
266 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
267 isTerminator = 1, isCodeGenOnly = 1 in
268 def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>;
270 let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in
271 def PS_aligna : Pseudo<(outs IntRegs:$Rd), (ins u32_0Imm:$A), "", []>;
273 // Generate frameindex addresses. The main reason for the offset operand is
274 // that every instruction that is allowed to have frame index as an operand
275 // will then have that operand followed by an immediate operand (the offset).
276 // This simplifies the frame-index elimination code.
278 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1,
279 isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0, isExtendable = 1,
280 isExtentSigned = 1, opExtentBits = 16, opExtentAlign = 0 in {
281 let opExtendable = 2 in
282 def PS_fi : Pseudo<(outs IntRegs:$Rd),
283 (ins IntRegs:$fi, s32_0Imm:$off), "">;
284 let opExtendable = 3 in
285 def PS_fia : Pseudo<(outs IntRegs:$Rd),
286 (ins IntRegs:$Rs, IntRegs:$fi, s32_0Imm:$off), "">;
289 class CondStr<string CReg, bit True, bit New> {
290 string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") ";
292 class JumpOpcStr<string Mnemonic, bit Taken> {
293 string S = Mnemonic # !if(Taken, ":t", ":nt");
295 let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1,
296 hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in
297 class T_JMPr_c <bit PredNot, bit isPredNew, bit isTak, InstHexagon rootInst>
298 : InstHexagon<(outs), (ins PredRegs:$src, IntRegs:$dst),
299 CondStr<"$src", !if(PredNot,0,1), isPredNew>.S #
300 JumpOpcStr<"jumpr", isTak>.S # " $dst",
301 [], "", rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
304 let isPredicatedFalse = PredNot;
305 let isPredicatedNew = isPredNew;
311 let Inst{27-22} = 0b001101;
312 let Inst{21} = PredNot;
313 let Inst{20-16} = dst;
314 let Inst{12} = isTak;
315 let Inst{11} = isPredNew;
319 let isTerminator = 1, hasSideEffects = 0, isReturn = 1, isCodeGenOnly = 1,
320 isBarrier = 1, BaseOpcode = "JMPret" in {
321 def PS_jmpret : T_JMPr<J2_jumpr>, PredNewRel;
322 def PS_jmprett : T_JMPr_c<0, 0, 0, J2_jumprt>, PredNewRel;
323 def PS_jmpretf : T_JMPr_c<1, 0, 0, J2_jumprf>, PredNewRel;
324 def PS_jmprettnew : T_JMPr_c<0, 1, 0, J2_jumprtnew>, PredNewRel;
325 def PS_jmpretfnew : T_JMPr_c<1, 1, 0, J2_jumprfnew>, PredNewRel;
326 def PS_jmprettnewpt : T_JMPr_c<0, 1, 1, J2_jumprtnewpt>, PredNewRel;
327 def PS_jmpretfnewpt : T_JMPr_c<1, 1, 1, J2_jumprfnewpt>, PredNewRel;
330 //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)>;
332 // The reason for the custom inserter is to record all ALLOCA instructions
333 // in MachineFunctionInfo.
334 let Defs = [R29], hasSideEffects = 1 in
335 def PS_alloca: Pseudo <(outs IntRegs:$Rd),
336 (ins IntRegs:$Rs, u32_0Imm:$A), "", []>;
339 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
340 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
341 def LDriw_pred : LDInst<(outs PredRegs:$dst),
342 (ins IntRegs:$addr, s32_0Imm:$off),
343 ".error \"should not emit\"", []>;
346 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
347 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
348 def LDriw_ctr : LDInst<(outs CtrRegs:$dst),
349 (ins IntRegs:$addr, s32_0Imm:$off),
350 ".error \"should not emit\"", []>;
353 let isCodeGenOnly = 1, isPseudo = 1 in
354 def PS_pselect: InstHexagon<(outs DoubleRegs:$Rd),
355 (ins PredRegs:$Pu, DoubleRegs:$Rs, DoubleRegs:$Rt),
356 ".error \"should not emit\" ", [], "", A2_tfrpt.Itinerary, TypeALU32_2op>;
358 let isBranch = 1, isBarrier = 1, Defs = [PC], hasSideEffects = 0,
360 isExtendable = 1, opExtendable = 0, isExtentSigned = 1,
361 opExtentBits = 24, opExtentAlign = 2, InputType = "imm" in
362 class T_JMP: InstHexagon<(outs), (ins b30_2Imm:$dst),
364 [], "", J2_jump.Itinerary, TypeJ>, OpcodeHexagon {
368 let Inst{27-25} = 0b100;
369 let Inst{24-16} = dst{23-15};
370 let Inst{13-1} = dst{14-2};
373 // Restore registers and dealloc return function call.
374 let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
375 Defs = [R29, R30, R31, PC], isPredicable = 0, isAsmParserOnly = 1 in {
376 def RESTORE_DEALLOC_RET_JMP_V4 : T_JMP;
378 let isExtended = 1, opExtendable = 0 in
379 def RESTORE_DEALLOC_RET_JMP_V4_EXT : T_JMP;
381 let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
382 def RESTORE_DEALLOC_RET_JMP_V4_PIC : T_JMP;
384 let isExtended = 1, opExtendable = 0 in
385 def RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC : T_JMP;
389 // Restore registers and dealloc frame before a tail call.
390 let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
391 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;
393 let isExtended = 1, opExtendable = 0 in
394 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel;
396 let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
397 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel;
399 let isExtended = 1, opExtendable = 0 in
400 def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel;
404 // Save registers function call.
405 let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
406 def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;
408 let isExtended = 1, opExtendable = 0 in
409 def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel;
412 def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel;
414 let Defs = [P0], isExtended = 1, opExtendable = 0 in
415 def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel;
417 let Defs = [R14, R15, R28] in
418 def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel;
420 let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in
421 def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel;
423 let Defs = [R14, R15, R28, P0] in
424 def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel;
426 let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in
427 def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel;
430 let Predicates = [UseHVX], isPseudo = 1, isCodeGenOnly = 1,
431 hasSideEffects = 0, hasPostISelHook = 1 in
432 class Vsplatr_template : InstHexagon<(outs HvxVR:$Vd), (ins IntRegs:$Rs),
433 "", [], "", V6_lvsplatw.Itinerary, V6_lvsplatw.Type>;
434 def PS_vsplatrb: Vsplatr_template;
435 def PS_vsplatrh: Vsplatr_template;
436 def PS_vsplatrw: Vsplatr_template;
438 let Predicates = [UseHVX], isPseudo = 1, isCodeGenOnly = 1,
439 hasSideEffects = 0, hasPostISelHook = 1 in
440 class Vsplati_template : InstHexagon<(outs HvxVR:$Vd), (ins s32_0Imm:$Val),
441 "", [], "", V6_lvsplatw.Itinerary, V6_lvsplatw.Type>;
442 def PS_vsplatib: Vsplati_template;
443 def PS_vsplatih: Vsplati_template;
444 def PS_vsplatiw: Vsplati_template;
446 // Vector store pseudos
447 let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,
448 mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
449 class STriv_template<RegisterClass RC, InstHexagon rootInst>
450 : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),
451 "", [], "", rootInst.Itinerary, rootInst.Type>;
453 def PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>,
454 Requires<[HasV60,UseHVX]>;
455 def PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>,
456 Requires<[HasV60,UseHVX]>;
457 def PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>,
458 Requires<[HasV60,UseHVX]>;
459 def PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>,
460 Requires<[HasV60,UseHVX]>;
462 let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in
463 def PS_vstorerq_ai: Pseudo<(outs),
464 (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>,
465 Requires<[HasV60,UseHVX]>;
467 // Vector load pseudos
468 let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,
469 mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
470 class LDriv_template<RegisterClass RC, InstHexagon rootInst>
471 : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),
472 "", [], "", rootInst.Itinerary, rootInst.Type>;
474 def PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>,
475 Requires<[HasV60,UseHVX]>;
476 def PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>,
477 Requires<[HasV60,UseHVX]>;
478 def PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>,
479 Requires<[HasV60,UseHVX]>;
480 def PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>,
481 Requires<[HasV60,UseHVX]>;
483 let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in
484 def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd),
485 (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>,
486 Requires<[HasV60,UseHVX]>;
489 let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
490 class VSELInst<dag outs, dag ins, InstHexagon rootInst>
491 : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>;
493 def PS_vselect: VSELInst<(outs HvxVR:$dst),
494 (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>,
495 Requires<[HasV60,UseHVX]>;
496 def PS_wselect: VSELInst<(outs HvxWR:$dst),
497 (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>,
498 Requires<[HasV60,UseHVX]>;
500 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
501 isCodeGenOnly = 1 in {
502 def PS_qtrue: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
503 V6_veqw.Itinerary, TypeCVI_VA>;
504 def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
505 V6_vgtw.Itinerary, TypeCVI_VA>;
506 def PS_vdd0: InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "",
507 V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>;
511 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
512 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
513 def STriw_pred : STInst<(outs),
514 (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1),
515 ".error \"should not emit\"", []>;
517 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
518 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
519 def STriw_ctr : STInst<(outs),
520 (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),
521 ".error \"should not emit\"", []>;
523 let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
524 isAsmParserOnly = 1 in
525 def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst),
526 (ins u64_0Imm:$src1),
527 "$dst = #$src1", [], "",
528 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
530 // Hexagon doesn't have a vector multiply with C semantics.
531 // Instead, generate a pseudo instruction that gets expanded into two
532 // scalar MPYI instructions.
533 // This is expanded by ExpandPostRAPseudos.
535 def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd),
536 (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>;
539 def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd),
540 (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [],
543 def DuplexIClass0: InstDuplex < 0 >;
544 def DuplexIClass1: InstDuplex < 1 >;
545 def DuplexIClass2: InstDuplex < 2 >;
546 let isExtendable = 1 in {
547 def DuplexIClass3: InstDuplex < 3 >;
548 def DuplexIClass4: InstDuplex < 4 >;
549 def DuplexIClass5: InstDuplex < 5 >;
550 def DuplexIClass6: InstDuplex < 6 >;
551 def DuplexIClass7: InstDuplex < 7 >;
553 def DuplexIClass8: InstDuplex < 8 >;
554 def DuplexIClass9: InstDuplex < 9 >;
555 def DuplexIClassA: InstDuplex < 0xA >;
556 def DuplexIClassB: InstDuplex < 0xB >;
557 def DuplexIClassC: InstDuplex < 0xC >;
558 def DuplexIClassD: InstDuplex < 0xD >;
559 def DuplexIClassE: InstDuplex < 0xE >;
560 def DuplexIClassF: InstDuplex < 0xF >;
562 // Pseudos for circular buffer instructions. These are needed in order to
563 // allocate the correct pair of CSx and Mx registers.
564 multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {
566 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
567 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
568 // Use timing class of L2_loadrb_pci.
569 def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
570 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),
571 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_5ceb2f9e>;
573 // Use timing class of L2_loadrb_pcr.
574 def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
575 (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),
576 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_075c8dd8>;
580 defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;
581 defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;
582 defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;
583 defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;
584 defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;
585 defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;
587 multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> {
589 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
590 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
591 // Use timing class of S2_storerb_pci.
592 def NAME#_pci : STInst<(outs IntRegs:$Rx32),
593 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
594 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_b4dc7630>;
596 // Use timing class of S2_storerb_pcr.
597 def NAME#_pcr : STInst<(outs IntRegs:$Rx32),
598 (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
599 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_a2b365d2>;
603 defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;
604 defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;
605 defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;
606 defm PS_storeri : NewCircularStore<IntRegs, WordAccess>;
607 defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;
609 // A pseudo that generates a runtime crash. This is used to implement
611 let hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in
612 def PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>;
614 // This is actual trap1 instruction from before v65. It's here since it is
615 // no longer included in DepInstrInfo.td.
616 def PS_trap1 : HInst<(outs), (ins u8_0Imm:$Ii), "trap1(#$Ii)", tc_53c851ab,
617 TypeJ>, Enc_a51a9a, Requires<[HasPreV65]> {
618 let Inst{1-0} = 0b00;
619 let Inst{7-5} = 0b000;
620 let Inst{13-13} = 0b0;
621 let Inst{31-16} = 0b0101010010000000;