121
|
1 //===--- HexagonPseudo.td -------------------------------------------------===//
|
|
2 //
|
147
|
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
|
121
|
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.
|
|
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)>;
|
|
17
|
|
18 let PrintMethod = "printGlobalOperand" in {
|
|
19 def globaladdress : Operand<i32>;
|
|
20 def globaladdressExt : Operand<i32>;
|
|
21 }
|
|
22
|
|
23 let isPseudo = 1 in {
|
|
24 let isCodeGenOnly = 0 in
|
|
25 def A2_iconst : Pseudo<(outs IntRegs:$Rd32),
|
147
|
26 (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;
|
121
|
27
|
|
28 def DUPLEX_Pseudo : InstHexagon<(outs),
|
|
29 (ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
|
|
30 }
|
|
31
|
|
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),
|
147
|
36 "$dst = combine(#$src1,#$src2)", [], "",
|
121
|
37 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
|
|
38
|
|
39 // HI/LO Instructions
|
|
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,
|
|
43 InstHexagon rootInst>
|
|
44 : InstHexagon<(outs IntRegs:$dst),
|
|
45 (ins u16_0Imm:$imm_value),
|
147
|
46 "$dst"#RegHalf#" = #$imm_value", [], "",
|
121
|
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
|
|
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>;
|
|
62 }
|
|
63
|
|
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)", []>;
|
|
69 }
|
|
70
|
|
71 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
|
|
72 isCodeGenOnly = 1 in
|
|
73 def PS_true : InstHexagon<(outs PredRegs:$dst), (ins), "",
|
|
74 [(set I1:$dst, 1)], "", C2_orn.Itinerary, TypeCR>;
|
|
75
|
|
76 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
|
|
77 isCodeGenOnly = 1 in
|
|
78 def PS_false : InstHexagon<(outs PredRegs:$dst), (ins), "",
|
|
79 [(set I1:$dst, 0)], "", C2_andn.Itinerary, TypeCR>;
|
|
80
|
|
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\" ", []>;
|
|
84
|
|
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\" ", []>;
|
|
88
|
|
89
|
|
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),
|
|
93 ":endloop0",
|
|
94 []>;
|
|
95 }
|
|
96
|
|
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),
|
|
100 ":endloop1",
|
|
101 []>;
|
|
102 }
|
|
103
|
147
|
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),
|
|
107 ":endloop01",
|
|
108 []>;
|
|
109 }
|
|
110
|
121
|
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 {
|
|
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
|
|
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 {
|
|
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
|
|
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>;
|
|
153 }
|
|
154
|
|
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>;
|
|
159 }
|
|
160
|
|
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>,
|
|
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
|
|
177 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
|
|
178 isPredicable = 0 in
|
|
179 def CALLProfile : T_Call<"">;
|
|
180
|
|
181 let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
|
|
182 Defs = [PC, R31, R6, R7, P0] in
|
|
183 def PS_call_stk : T_Call<"">;
|
|
184
|
|
185 // Call, no return.
|
|
186 let isCall = 1, hasSideEffects = 1, cofMax1 = 1, isCodeGenOnly = 1 in
|
|
187 def 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
|
|
198 let isCall = 1, hasSideEffects = 1,
|
|
199 isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
|
|
200 BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2 in
|
|
201 class 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;
|
147
|
210 let Itinerary = itin;
|
121
|
211 }
|
|
212
|
|
213 def 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
|
|
219 let isBranch = 1, isIndirectBranch = 1, isBarrier = 1, Defs = [PC],
|
|
220 isPredicable = 1, hasSideEffects = 0, InputType = "reg",
|
|
221 cofMax1 = 1 in
|
|
222 class 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.
|
|
233 let isReturn = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 0,
|
|
234 isCodeGenOnly = 1, Defs = [PC], Uses = [R28], isPredicable = 0 in
|
|
235 def EH_RETURN_JMPR : T_JMPr<J2_jumpr>;
|
|
236
|
|
237 // Indirect tail-call.
|
|
238 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
|
|
239 isTerminator = 1, isCodeGenOnly = 1 in
|
|
240 def PS_tailcall_r : T_JMPr<J2_jumpr>;
|
|
241
|
|
242 //
|
|
243 // Direct tail-calls.
|
|
244 let isPseudo = 1, isCall = 1, isReturn = 1, isBarrier = 1, isPredicable = 0,
|
|
245 isTerminator = 1, isCodeGenOnly = 1 in
|
|
246 def PS_tailcall_i : Pseudo<(outs), (ins a30_2Imm:$dst), "", []>;
|
|
247
|
|
248 let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in
|
|
249 def 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 //
|
|
256 let 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
|
|
267 class CondStr<string CReg, bit True, bit New> {
|
|
268 string S = "if (" # !if(True,"","!") # CReg # !if(New,".new","") # ") ";
|
|
269 }
|
|
270 class JumpOpcStr<string Mnemonic, bit New, bit Taken> {
|
|
271 string S = Mnemonic # !if(Taken, ":t", ":nt");
|
|
272 }
|
|
273 let isBranch = 1, isIndirectBranch = 1, Defs = [PC], isPredicated = 1,
|
|
274 hasSideEffects = 0, InputType = "reg", cofMax1 = 1 in
|
|
275 class 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
|
|
297 let 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.
|
|
312 let Defs = [R29], hasSideEffects = 1 in
|
|
313 def PS_alloca: Pseudo <(outs IntRegs:$Rd),
|
|
314 (ins IntRegs:$Rs, u32_0Imm:$A), "", []>;
|
|
315
|
|
316 // Load predicate.
|
|
317 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
|
|
318 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
|
|
319 def LDriw_pred : LDInst<(outs PredRegs:$dst),
|
|
320 (ins IntRegs:$addr, s32_0Imm:$off),
|
|
321 ".error \"should not emit\"", []>;
|
|
322
|
|
323 // Load modifier.
|
|
324 let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
|
|
325 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
|
147
|
326 def LDriw_ctr : LDInst<(outs CtrRegs:$dst),
|
121
|
327 (ins IntRegs:$addr, s32_0Imm:$off),
|
|
328 ".error \"should not emit\"", []>;
|
|
329
|
|
330
|
|
331 let isCodeGenOnly = 1, isPseudo = 1 in
|
|
332 def 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
|
|
336 let 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
|
|
340 class 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.
|
|
352 let 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.
|
|
368 let 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.
|
|
383 let 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
|
147
|
409 let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,
|
121
|
410 mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
|
|
411 class STrivv_template<RegisterClass RC, InstHexagon rootInst>
|
|
412 : InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),
|
|
413 "", [], "", rootInst.Itinerary, rootInst.Type>;
|
|
414
|
|
415 def PS_vstorerw_ai: STrivv_template<HvxWR, V6_vS32b_ai>,
|
147
|
416 Requires<[HasV60,UseHVX]>;
|
121
|
417 def PS_vstorerw_nt_ai: STrivv_template<HvxWR, V6_vS32b_nt_ai>,
|
147
|
418 Requires<[HasV60,UseHVX]>;
|
121
|
419 def PS_vstorerwu_ai: STrivv_template<HvxWR, V6_vS32Ub_ai>,
|
147
|
420 Requires<[HasV60,UseHVX]>;
|
121
|
421
|
|
422 let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in
|
|
423 def PS_vstorerq_ai: Pseudo<(outs),
|
|
424 (ins IntRegs:$Rs, s32_0Imm:$Off, HvxQR:$Qt), "", []>,
|
147
|
425 Requires<[HasV60,UseHVX]>;
|
121
|
426
|
|
427 // Vector load pseudos
|
147
|
428 let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,
|
121
|
429 mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
|
|
430 class LDrivv_template<RegisterClass RC, InstHexagon rootInst>
|
|
431 : InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),
|
|
432 "", [], "", rootInst.Itinerary, rootInst.Type>;
|
|
433
|
|
434 def PS_vloadrw_ai: LDrivv_template<HvxWR, V6_vL32b_ai>,
|
147
|
435 Requires<[HasV60,UseHVX]>;
|
121
|
436 def PS_vloadrw_nt_ai: LDrivv_template<HvxWR, V6_vL32b_nt_ai>,
|
147
|
437 Requires<[HasV60,UseHVX]>;
|
121
|
438 def PS_vloadrwu_ai: LDrivv_template<HvxWR, V6_vL32Ub_ai>,
|
147
|
439 Requires<[HasV60,UseHVX]>;
|
121
|
440
|
|
441 let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in
|
|
442 def PS_vloadrq_ai: Pseudo<(outs HvxQR:$Qd),
|
|
443 (ins IntRegs:$Rs, s32_0Imm:$Off), "", []>,
|
147
|
444 Requires<[HasV60,UseHVX]>;
|
121
|
445
|
|
446
|
|
447 let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
|
|
448 class VSELInst<dag outs, dag ins, InstHexagon rootInst>
|
|
449 : InstHexagon<outs, ins, "", [], "", rootInst.Itinerary, rootInst.Type>;
|
|
450
|
|
451 def PS_vselect: VSELInst<(outs HvxVR:$dst),
|
|
452 (ins PredRegs:$src1, HvxVR:$src2, HvxVR:$src3), V6_vcmov>,
|
147
|
453 Requires<[HasV60,UseHVX]>;
|
121
|
454 def PS_wselect: VSELInst<(outs HvxWR:$dst),
|
|
455 (ins PredRegs:$src1, HvxWR:$src2, HvxWR:$src3), V6_vccombine>,
|
147
|
456 Requires<[HasV60,UseHVX]>;
|
121
|
457
|
134
|
458 let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
|
|
459 isCodeGenOnly = 1 in {
|
|
460 def PS_qtrue: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
|
|
461 V6_veqw.Itinerary, TypeCVI_VA>;
|
|
462 def PS_qfalse: InstHexagon<(outs HvxQR:$Qd), (ins), "", [], "",
|
|
463 V6_vgtw.Itinerary, TypeCVI_VA>;
|
147
|
464 def PS_vdd0: InstHexagon<(outs HvxWR:$Vd), (ins), "", [], "",
|
|
465 V6_vsubw_dv.Itinerary, TypeCVI_VA_DV>;
|
134
|
466 }
|
|
467
|
121
|
468 // Store predicate.
|
|
469 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
|
|
470 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
|
|
471 def STriw_pred : STInst<(outs),
|
|
472 (ins IntRegs:$addr, s32_0Imm:$off, PredRegs:$src1),
|
|
473 ".error \"should not emit\"", []>;
|
|
474 // Store modifier.
|
|
475 let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
|
|
476 isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
|
147
|
477 def STriw_ctr : STInst<(outs),
|
|
478 (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),
|
121
|
479 ".error \"should not emit\"", []>;
|
|
480
|
|
481 let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
|
|
482 isAsmParserOnly = 1 in
|
|
483 def TFRI64_V4 : InstHexagon<(outs DoubleRegs:$dst),
|
|
484 (ins u64_0Imm:$src1),
|
|
485 "$dst = #$src1", [], "",
|
|
486 A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
|
|
487
|
|
488 // Hexagon doesn't have a vector multiply with C semantics.
|
|
489 // Instead, generate a pseudo instruction that gets expaneded into two
|
|
490 // scalar MPYI instructions.
|
|
491 // This is expanded by ExpandPostRAPseudos.
|
|
492 let isPseudo = 1 in
|
|
493 def PS_vmulw : PseudoM<(outs DoubleRegs:$Rd),
|
|
494 (ins DoubleRegs:$Rs, DoubleRegs:$Rt), "", []>;
|
|
495
|
|
496 let isPseudo = 1 in
|
|
497 def PS_vmulw_acc : PseudoM<(outs DoubleRegs:$Rd),
|
|
498 (ins DoubleRegs:$Rx, DoubleRegs:$Rs, DoubleRegs:$Rt), "", [],
|
|
499 "$Rd = $Rx">;
|
|
500
|
|
501 def DuplexIClass0: InstDuplex < 0 >;
|
|
502 def DuplexIClass1: InstDuplex < 1 >;
|
|
503 def DuplexIClass2: InstDuplex < 2 >;
|
|
504 let isExtendable = 1 in {
|
|
505 def DuplexIClass3: InstDuplex < 3 >;
|
|
506 def DuplexIClass4: InstDuplex < 4 >;
|
|
507 def DuplexIClass5: InstDuplex < 5 >;
|
|
508 def DuplexIClass6: InstDuplex < 6 >;
|
|
509 def DuplexIClass7: InstDuplex < 7 >;
|
|
510 }
|
|
511 def DuplexIClass8: InstDuplex < 8 >;
|
|
512 def DuplexIClass9: InstDuplex < 9 >;
|
|
513 def DuplexIClassA: InstDuplex < 0xA >;
|
|
514 def DuplexIClassB: InstDuplex < 0xB >;
|
|
515 def DuplexIClassC: InstDuplex < 0xC >;
|
|
516 def DuplexIClassD: InstDuplex < 0xD >;
|
|
517 def DuplexIClassE: InstDuplex < 0xE >;
|
|
518 def DuplexIClassF: InstDuplex < 0xF >;
|
147
|
519
|
|
520 // Pseudos for circular buffer instructions. These are needed in order to
|
|
521 // allocate the correct pair of CSx and Mx registers.
|
|
522 multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {
|
|
523
|
|
524 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
|
|
525 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
|
|
526 def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
|
|
527 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),
|
|
528 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e93a3d71>;
|
|
529
|
|
530 def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
|
|
531 (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),
|
|
532 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_44d3da28>;
|
|
533 }
|
|
534 }
|
|
535
|
|
536 defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;
|
|
537 defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;
|
|
538 defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;
|
|
539 defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;
|
|
540 defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;
|
|
541 defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;
|
|
542
|
|
543 multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> {
|
|
544
|
|
545 let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
|
|
546 addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
|
|
547 def NAME#_pci : STInst<(outs IntRegs:$Rx32),
|
|
548 (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
|
|
549 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_e86aa961>;
|
|
550
|
|
551 def NAME#_pcr : STInst<(outs IntRegs:$Rx32),
|
|
552 (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
|
|
553 ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_da97ee82>;
|
|
554 }
|
|
555 }
|
|
556
|
|
557 defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;
|
|
558 defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;
|
|
559 defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;
|
|
560 defm PS_storeri : NewCircularStore<IntRegs, WordAccess>;
|
|
561 defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;
|
|
562
|
|
563 // A pseudo that generates a runtime crash. This is used to implement
|
|
564 // __builtin_trap.
|
|
565 let hasSideEffects = 1, isPseudo = 1, isCodeGenOnly = 1, isSolo = 1 in
|
|
566 def PS_crash: InstHexagon<(outs), (ins), "", [], "", PSEUDO, TypePSEUDO>;
|