120
|
1 //===-- LanaiInstrInfo.td - Target Description for Lanai Target -----------===//
|
|
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 // This file describes the Lanai instructions in TableGen format.
|
|
11 //
|
|
12 //===----------------------------------------------------------------------===//
|
|
13
|
|
14 //===----------------------------------------------------------------------===//
|
|
15 // Instruction format superclass
|
|
16 //===----------------------------------------------------------------------===//
|
|
17
|
|
18 include "LanaiInstrFormats.td"
|
|
19
|
|
20 // -------------------------------------------------- //
|
|
21 // Instruction Operands and Patterns
|
|
22 // -------------------------------------------------- //
|
|
23
|
|
24 // These are target-independent nodes, but have target-specific formats.
|
121
|
25 def SDT_LanaiCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
|
|
26 SDTCisVT<1, i32>]>;
|
120
|
27 def SDT_LanaiCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
|
|
28 SDTCisVT<1, i32>]>;
|
|
29 def SDT_LanaiCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>;
|
|
30 def SDT_LanaiSetFlag : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
|
|
31 def SDT_LanaiSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
|
|
32 SDTCisSameAs<1, 2>]>;
|
|
33 def SDT_LanaiSetCC : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
|
|
34 SDTCisVT<1, i32>]>;
|
|
35 def SDT_LanaiBrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>,
|
|
36 SDTCisVT<1, i32>]>;
|
|
37 def SDT_LanaiAdjDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
|
|
38 SDTCisVT<1, i32>]>;
|
|
39
|
|
40 def Call : SDNode<"LanaiISD::CALL", SDT_LanaiCall,
|
|
41 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
|
|
42 SDNPVariadic]>;
|
|
43 def RetFlag : SDNode<"LanaiISD::RET_FLAG", SDTNone,
|
|
44 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
|
|
45 def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_LanaiCallSeqStart,
|
|
46 [SDNPHasChain, SDNPOutGlue]>;
|
|
47 def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_LanaiCallSeqEnd,
|
|
48 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
|
|
49 def LanaiSetFlag : SDNode<"LanaiISD::SET_FLAG", SDT_LanaiSetFlag,
|
|
50 [SDNPOutGlue]>;
|
|
51 def LanaiSubbF : SDNode<"LanaiISD::SUBBF", SDT_LanaiSetFlag,
|
|
52 [SDNPOutGlue, SDNPInGlue]>;
|
|
53 def LanaiBrCC : SDNode<"LanaiISD::BR_CC", SDT_LanaiBrCC,
|
|
54 [SDNPHasChain, SDNPInGlue]>;
|
|
55 def LanaiSelectCC : SDNode<"LanaiISD::SELECT_CC", SDT_LanaiSelectCC,
|
|
56 [SDNPInGlue]>;
|
|
57 def LanaiSetCC : SDNode<"LanaiISD::SETCC", SDT_LanaiSetCC,
|
|
58 [SDNPInGlue]>;
|
|
59 def LanaiHi : SDNode<"LanaiISD::HI", SDTIntUnaryOp>;
|
|
60 def LanaiLo : SDNode<"LanaiISD::LO", SDTIntUnaryOp>;
|
|
61 def LanaiSmall : SDNode<"LanaiISD::SMALL", SDTIntUnaryOp>;
|
|
62 def LanaiAdjDynAlloc : SDNode<"LanaiISD::ADJDYNALLOC", SDT_LanaiAdjDynAlloc>;
|
|
63
|
|
64 // Extract bits 0-15 (low-end) of an immediate value.
|
|
65 def LO16 : SDNodeXForm<imm, [{
|
|
66 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0xffff,
|
|
67 SDLoc(N), MVT::i32);
|
|
68 }]>;
|
|
69
|
|
70 // Extract bits 16-31 (high-end) of an immediate value.
|
|
71 // Transformation function: shift the immediate value down into the low bits.
|
|
72 def HI16 : SDNodeXForm<imm, [{
|
|
73 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() >> 16, SDLoc(N),
|
|
74 MVT::i32);
|
|
75 }]>;
|
|
76
|
|
77 def NEG : SDNodeXForm<imm, [{
|
|
78 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), MVT::i32);
|
|
79 }]>;
|
|
80
|
|
81 def LO21 : SDNodeXForm<imm, [{
|
|
82 return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0x1fffff,
|
|
83 SDLoc(N), MVT::i32);
|
|
84 }]>;
|
|
85
|
|
86 // Branch targets
|
|
87 def BrTargetAsmOperand : AsmOperandClass {
|
|
88 let Name = "BrTarget";
|
|
89 }
|
|
90 def BrTarget : Operand<OtherVT> {
|
|
91 let ParserMatchClass = BrTargetAsmOperand;
|
|
92 let EncoderMethod = "getBranchTargetOpValue";
|
|
93 let DecoderMethod = "decodeBranch";
|
|
94 }
|
|
95
|
|
96 def CallTargetAsmOperand : AsmOperandClass {
|
|
97 let Name = "CallTarget";
|
|
98 }
|
|
99 def CallTarget : Operand<i32> {
|
|
100 let ParserMatchClass = CallTargetAsmOperand;
|
|
101 let EncoderMethod = "getBranchTargetOpValue";
|
|
102 let DecoderMethod = "decodeBranch";
|
|
103 }
|
|
104
|
|
105 def ImmShiftAsmOperand : AsmOperandClass { let Name = "ImmShift"; }
|
|
106 def immShift : Operand<i32>, PatLeaf<(imm), [{
|
|
107 int Imm = N->getSExtValue();
|
|
108 return Imm >= -31 && Imm <= 31;}]> {
|
|
109 let ParserMatchClass = ImmShiftAsmOperand;
|
|
110 let DecoderMethod = "decodeShiftImm";
|
|
111 }
|
|
112
|
|
113 def Imm10AsmOperand : AsmOperandClass { let Name = "Imm10"; }
|
|
114 def imm10 : Operand<i32>, PatLeaf<(imm), [{
|
|
115 return isInt<10>(N->getSExtValue()); }]> {
|
|
116 let ParserMatchClass = Imm10AsmOperand;
|
|
117 }
|
|
118
|
|
119 def LoImm16AsmOperand : AsmOperandClass { let Name = "LoImm16"; }
|
|
120 def i32lo16z : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
121 // i32lo16 predicate - true if the 32-bit immediate has only rightmost 16
|
|
122 // bits set.
|
|
123 return ((N->getZExtValue() & 0xFFFFUL) == N->getZExtValue());}], LO16> {
|
|
124 let ParserMatchClass = LoImm16AsmOperand;
|
|
125 }
|
|
126 def i32neg16 : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
127 // i32neg16 predicate - true if the 32-bit immediate is negative and can
|
|
128 // be represented by a 16 bit integer.
|
|
129 int Imm = N->getSExtValue();
|
|
130 return (Imm < 0) && (isInt<16>(Imm));}], LO16> {
|
|
131 let ParserMatchClass = LoImm16AsmOperand;
|
|
132 }
|
|
133 def i32lo16s : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
134 // i32lo16 predicate - true if the 32-bit immediate has only rightmost 16
|
|
135 // bits set.
|
|
136 return ((int64_t)(N->getSExtValue() & 0xFFFFUL) == N->getSExtValue());}], LO16> {
|
|
137 let ParserMatchClass = LoImm16AsmOperand;
|
|
138 }
|
|
139
|
|
140 def LoImm16AndAsmOperand : AsmOperandClass { let Name = "LoImm16And"; }
|
|
141 def i32lo16and : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
142 // i32lo16 predicate - true if the 32-bit immediate has the rightmost 16
|
|
143 // bits set and the leftmost 16 bits 1's.
|
|
144 return (N->getZExtValue() >= 0xFFFF0000UL);}], LO16> {
|
|
145 let ParserMatchClass = LoImm16AndAsmOperand;
|
|
146 let PrintMethod = "printLo16AndImmOperand";
|
|
147 }
|
|
148
|
|
149 def HiImm16AsmOperand : AsmOperandClass { let Name = "HiImm16"; }
|
|
150 def i32hi16 : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
151 // i32hi16 predicate - true if the 32-bit immediate has only leftmost 16
|
|
152 // bits set.
|
|
153 return ((N->getZExtValue() & 0xFFFF0000UL) == N->getZExtValue());}], HI16> {
|
|
154 let ParserMatchClass = HiImm16AsmOperand;
|
|
155 let PrintMethod = "printHi16ImmOperand";
|
|
156 }
|
|
157
|
|
158 def HiImm16AndAsmOperand : AsmOperandClass { let Name = "HiImm16And"; }
|
|
159 def i32hi16and : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
160 // i32lo16 predicate - true if the 32-bit immediate has the leftmost 16
|
|
161 // bits set and the rightmost 16 bits 1's.
|
|
162 return ((N->getZExtValue() & 0xFFFFUL) == 0xFFFFUL);}], HI16> {
|
|
163 let ParserMatchClass = HiImm16AndAsmOperand;
|
|
164 let PrintMethod = "printHi16AndImmOperand";
|
|
165 }
|
|
166
|
|
167 def LoImm21AsmOperand : AsmOperandClass { let Name = "LoImm21"; }
|
|
168 def i32lo21 : Operand<i32>, PatLeaf<(i32 imm), [{
|
|
169 // i32lo21 predicate - true if the 32-bit immediate has only rightmost 21
|
|
170 // bits set.
|
|
171 return ((N->getZExtValue() & 0x1FFFFFUL) == N->getZExtValue());}], LO21> {
|
|
172 let ParserMatchClass = LoImm21AsmOperand;
|
|
173 }
|
|
174
|
|
175 def AluOp : Operand<i32> {
|
|
176 let PrintMethod = "printAluOperand";
|
|
177 }
|
|
178
|
|
179 // Addressing modes.
|
|
180 def ADDRrr : ComplexPattern<i32, 3, "selectAddrRr", [], []>;
|
|
181 def ADDRri : ComplexPattern<i32, 3, "selectAddrRi", [frameindex], []>;
|
|
182 def ADDRsls : ComplexPattern<i32, 1, "selectAddrSls", [frameindex], []>;
|
|
183 def ADDRspls : ComplexPattern<i32, 3, "selectAddrSpls", [frameindex], []>;
|
|
184
|
|
185 // Address operands
|
|
186 def MemRegImmAsmOperand : AsmOperandClass {
|
|
187 let Name = "MemRegImm";
|
|
188 let ParserMethod = "parseMemoryOperand";
|
|
189 }
|
|
190 def MEMri : Operand<i32> {
|
|
191 let DecoderMethod = "decodeRiMemoryValue";
|
|
192 let EncoderMethod = "getRiMemoryOpValue";
|
|
193 let MIOperandInfo = (ops GPR:$base, i32lo16s:$offset, AluOp:$Opcode);
|
|
194 let ParserMatchClass = MemRegImmAsmOperand;
|
|
195 let PrintMethod = "printMemRiOperand";
|
|
196 }
|
|
197
|
|
198 def MemRegRegAsmOperand : AsmOperandClass {
|
|
199 let Name = "MemRegReg";
|
|
200 let ParserMethod = "parseMemoryOperand";
|
|
201 }
|
|
202 def MEMrr : Operand<i32> {
|
|
203 let DecoderMethod = "decodeRrMemoryValue";
|
|
204 let EncoderMethod = "getRrMemoryOpValue";
|
|
205 let MIOperandInfo = (ops GPR:$Op1, GPR:$Op2, AluOp:$Opcode);
|
|
206 let ParserMatchClass = MemRegRegAsmOperand;
|
|
207 let PrintMethod = "printMemRrOperand";
|
|
208 }
|
|
209
|
|
210 def MemImmAsmOperand : AsmOperandClass {
|
|
211 let Name = "MemImm";
|
|
212 let ParserMethod = "parseMemoryOperand";
|
|
213 }
|
|
214 def MEMi : Operand<i32> {
|
|
215 let MIOperandInfo = (ops i32lo21:$offset);
|
|
216 let ParserMatchClass = MemImmAsmOperand;
|
|
217 let PrintMethod = "printMemImmOperand";
|
|
218 }
|
|
219
|
|
220 def MemSplsAsmOperand : AsmOperandClass {
|
|
221 let Name = "MemSpls";
|
|
222 let ParserMethod = "parseMemoryOperand";
|
|
223 }
|
|
224 def MEMspls : Operand<i32> {
|
|
225 let DecoderMethod = "decodeSplsValue";
|
|
226 let EncoderMethod = "getSplsOpValue";
|
|
227 let MIOperandInfo = (ops GPR:$base, imm10:$offset, AluOp:$Opcode);
|
|
228 let ParserMatchClass = MemSplsAsmOperand;
|
|
229 let PrintMethod = "printMemSplsOperand";
|
|
230 }
|
|
231
|
|
232 def CCOp : Operand<i32> {
|
|
233 let PrintMethod = "printCCOperand";
|
|
234 }
|
|
235
|
|
236 // Predicate operand. Default to 0 = true.
|
|
237 def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; }
|
|
238
|
|
239 def pred : PredicateOperand<i32, (ops i32imm), (ops (i32 0))> {
|
|
240 let PrintMethod = "printPredicateOperand";
|
|
241 let ParserMatchClass = CondCodeOperand;
|
|
242 let DecoderMethod = "decodePredicateOperand";
|
|
243 }
|
|
244
|
|
245 let hasSideEffects = 0, Inst = 0x00000001 in
|
|
246 def NOP : InstLanai<(outs), (ins), "nop", []>;
|
|
247
|
|
248 // Special NOPs to change logging level in vlanai.
|
|
249 let hasSideEffects = 0, Inst = 0x00000002 in
|
|
250 def LOG0 : InstLanai<(outs), (ins), "log_0", []>;
|
|
251 let hasSideEffects = 0, Inst = 0x00000003 in
|
|
252 def LOG1 : InstLanai<(outs), (ins), "log_1", []>;
|
|
253 let hasSideEffects = 0, Inst = 0x00000004 in
|
|
254 def LOG2 : InstLanai<(outs), (ins), "log_2", []>;
|
|
255 let hasSideEffects = 0, Inst = 0x00000005 in
|
|
256 def LOG3 : InstLanai<(outs), (ins), "log_3", []>;
|
|
257 let hasSideEffects = 0, Inst = 0x00000006 in
|
|
258 def LOG4 : InstLanai<(outs), (ins), "log_4", []>;
|
|
259
|
|
260 // Map an SPLS instruction onto itself. All other instructions will be mapped
|
|
261 // onto -1. Used to identify SPLS instructions.
|
|
262 def splsIdempotent : InstrMapping {
|
|
263 let FilterClass = "InstSPLS";
|
|
264 let RowFields = ["AsmString"];
|
|
265 let ColFields = ["PostEncoderMethod"];
|
|
266 let KeyCol = ["adjustPqBitsSpls"];
|
|
267 let ValueCols = [["adjustPqBitsSpls"]];
|
|
268 }
|
|
269
|
|
270 // -------------------------------------------------- //
|
|
271 // ALU instructions
|
|
272 // -------------------------------------------------- //
|
|
273 multiclass ALUbase<bits<3> subOp, string AsmStr, SDNode OpNode,
|
|
274 PatLeaf LoExt, PatLeaf HiExt,
|
|
275 list<dag> loPattern, list<dag> hiPattern> {
|
|
276 // Register Immediate
|
|
277 let H = 0 in
|
|
278 def LO : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, LoExt:$imm16),
|
|
279 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"),
|
|
280 loPattern>;
|
|
281 let H = 1 in
|
|
282 def HI : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, HiExt:$imm16),
|
|
283 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"),
|
|
284 hiPattern>;
|
|
285
|
|
286 }
|
|
287
|
|
288 multiclass ALUarith<bits<3> subOp, string AsmStr, SDNode OpNode,
|
|
289 PatLeaf LoExt, PatLeaf HiExt> {
|
|
290 defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt, [], []>;
|
|
291
|
|
292 // Register Register
|
|
293 let JJJJJ = 0 in
|
|
294 def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI),
|
|
295 !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"),
|
|
296 [(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
|
|
297 }
|
|
298
|
|
299 multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode,
|
|
300 PatLeaf LoExt, PatLeaf HiExt> {
|
|
301 defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt,
|
|
302 [(set GPR:$Rd, (OpNode GPR:$Rs1, LoExt:$imm16))],
|
|
303 [(set GPR:$Rd, (OpNode GPR:$Rs1, HiExt:$imm16))]>;
|
|
304
|
|
305 // Register Register
|
|
306 let JJJJJ = 0 in
|
|
307 def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI),
|
|
308 !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"),
|
|
309 [(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
|
|
310 }
|
|
311
|
|
312 // Non flag setting ALU operations
|
|
313 let isAsCheapAsAMove = 1, F = 0 in {
|
|
314 let isCommutable = 1 in {
|
|
315 defm ADD_ : ALUarith<0b000, "add", add, i32lo16z, i32hi16>;
|
|
316 }
|
|
317 defm SUB_ : ALUarith<0b010, "sub", sub, i32lo16z, i32hi16>;
|
|
318 let isCommutable = 1 in {
|
|
319 defm AND_ : ALUlogic<0b100, "and", and, i32lo16and, i32hi16and>;
|
|
320 defm OR_ : ALUlogic<0b101, "or", or, i32lo16z, i32hi16>;
|
|
321 defm XOR_ : ALUlogic<0b110, "xor", xor, i32lo16z, i32hi16>;
|
|
322 }
|
|
323 }
|
|
324
|
|
325 def : Pat<(add GPR:$Rs1, i32lo16z:$imm),
|
|
326 (ADD_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
327
|
|
328 def : Pat<(sub GPR:$Rs1, i32lo16z:$imm),
|
|
329 (SUB_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
330
|
|
331 def : Pat<(add GPR:$Rs1, i32hi16:$imm),
|
|
332 (ADD_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
333
|
|
334 def : Pat<(sub GPR:$Rs1, i32hi16:$imm),
|
|
335 (SUB_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
336
|
|
337 def : Pat<(i32 i32lo16and:$imm), (AND_I_LO (i32 R1), i32lo16and:$imm)>;
|
|
338 def : Pat<(i32 i32hi16and:$imm), (AND_I_HI (i32 R1), i32hi16and:$imm)>;
|
|
339
|
|
340 // Change add/sub with negative number to sub/add
|
|
341 def : Pat<(add GPR:$Rs1, i32neg16:$imm),
|
|
342 (SUB_I_LO GPR:$Rs1, (NEG $imm))>;
|
|
343 def : Pat<(sub GPR:$Rs1, i32neg16:$imm),
|
|
344 (ADD_I_LO GPR:$Rs1, (NEG $imm))>;
|
|
345
|
|
346 // Flag (incl. carry) setting addition and subtraction
|
|
347 let F = 1, Defs = [SR] in {
|
|
348 defm ADD_F_ : ALUarith<0b000, "add.f", addc, i32lo16z, i32hi16>;
|
|
349 defm SUB_F_ : ALUarith<0b010, "sub.f", subc, i32lo16z, i32hi16>;
|
|
350 }
|
|
351
|
|
352 def : Pat<(addc GPR:$Rs1, i32lo16z:$imm),
|
|
353 (ADD_F_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
354
|
|
355 def : Pat<(subc GPR:$Rs1, i32lo16z:$imm),
|
|
356 (SUB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
357
|
|
358 def : Pat<(addc GPR:$Rs1, i32hi16:$imm),
|
|
359 (ADD_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
360
|
|
361 def : Pat<(subc GPR:$Rs1, i32hi16:$imm),
|
|
362 (SUB_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
363
|
|
364 // Carry using addition and subtraction
|
|
365 let F = 0, Uses = [SR] in {
|
|
366 defm ADDC_ : ALUarith<0b001, "addc", adde, i32lo16z, i32hi16>;
|
|
367 defm SUBB_ : ALUarith<0b011, "subb", sube, i32lo16z, i32hi16>;
|
|
368 }
|
|
369
|
|
370 def : Pat<(adde GPR:$Rs1, i32lo16z:$imm),
|
|
371 (ADDC_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
372
|
|
373 def : Pat<(sube GPR:$Rs1, i32lo16z:$imm),
|
|
374 (SUBB_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
375
|
|
376 def : Pat<(adde GPR:$Rs1, i32hi16:$imm),
|
|
377 (ADDC_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
378
|
|
379 def : Pat<(sube GPR:$Rs1, i32hi16:$imm),
|
|
380 (SUBB_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
381
|
|
382 // Flag setting ALU operations
|
|
383 let isAsCheapAsAMove = 1, F = 1, Defs = [SR] in {
|
|
384 let isCommutable = 1 in {
|
|
385 defm AND_F_ : ALUlogic<0b100, "and.f", and, i32lo16and, i32hi16and>;
|
|
386 defm OR_F_ : ALUlogic<0b101, "or.f", or, i32lo16z, i32hi16>;
|
|
387 defm XOR_F_ : ALUlogic<0b110, "xor.f", xor, i32lo16z, i32hi16>;
|
|
388 }
|
|
389 }
|
|
390
|
|
391 let isAsCheapAsAMove = 1, F = 1, Defs = [SR], Uses = [SR] in {
|
|
392 defm ADDC_F_ : ALUarith<0b001, "addc.f", adde, i32lo16z, i32hi16>;
|
|
393 defm SUBB_F_ : ALUarith<0b011, "subb.f", sube, i32lo16z, i32hi16>;
|
|
394 }
|
|
395
|
|
396 def : Pat<(LanaiSubbF GPR:$Rs1, GPR:$Rs2),
|
|
397 (SUBB_F_R GPR:$Rs1, GPR:$Rs2)>;
|
|
398
|
|
399 def : Pat<(LanaiSubbF GPR:$Rs1, i32lo16z:$imm),
|
|
400 (SUBB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
|
401
|
|
402 def : Pat<(LanaiSubbF GPR:$Rs1, i32hi16:$imm),
|
|
403 (SUBB_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
|
404
|
|
405 def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0, 0)>;
|
|
406
|
|
407 let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0,
|
|
408 isReMaterializable = 1 in
|
|
409 def MOVHI : InstRI<0b000, (outs GPR:$Rd), (ins i32hi16:$imm16),
|
|
410 "mov\t$imm16, $Rd",
|
|
411 [(set GPR:$Rd, i32hi16:$imm16)]>;
|
|
412
|
|
413 def : InstAlias<"mov $imm16, $dst", (ADD_I_LO GPR:$dst, R0, i32lo16z:$imm16)>;
|
|
414 def : InstAlias<"mov $imm16, $dst", (ADD_I_HI GPR:$dst, R0, i32hi16:$imm16)>;
|
|
415 def : InstAlias<"mov $imm16, $dst",
|
|
416 (AND_I_LO GPR:$dst, R1, i32lo16and:$imm16)>;
|
|
417 def : InstAlias<"mov $imm16, $dst",
|
|
418 (AND_I_HI GPR:$dst, R1, i32hi16and:$imm16)>;
|
|
419
|
|
420 // Shift instructions
|
|
421 class ShiftRI<string AsmStr, list<dag> Pattern>
|
|
422 : InstRI<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, immShift:$imm16),
|
|
423 !strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"), Pattern> {
|
|
424 let isReMaterializable = 1;
|
|
425 }
|
|
426
|
|
427 let F = 0 in {
|
|
428 let H = 0 in
|
|
429 def SL_I : ShiftRI<"sh", [(set GPR:$Rd, (shl GPR:$Rs1, immShift:$imm16))]>;
|
|
430 let H = 1 in
|
|
431 def SA_I : ShiftRI<"sha", []>;
|
|
432 }
|
|
433 def : Pat<(srl GPR:$Rs1, immShift:$imm), (SL_I GPR:$Rs1, (NEG $imm))>;
|
|
434 def : Pat<(sra GPR:$Rs1, immShift:$imm), (SA_I GPR:$Rs1, (NEG $imm))>;
|
|
435
|
|
436 let F = 1, Defs = [SR] in {
|
|
437 let H = 0 in
|
|
438 def SL_F_I : ShiftRI<"sh.f", []>;
|
|
439 let H = 1 in
|
|
440 def SA_F_I : ShiftRI<"sha.f", []>;
|
|
441 }
|
|
442
|
|
443 class ShiftRR<string AsmStr, list<dag> Pattern>
|
|
444 : InstRR<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI), AsmStr,
|
|
445 Pattern>;
|
|
446
|
|
447 let F = 0 in {
|
|
448 let JJJJJ = 0b10000 in
|
|
449 def SHL_R : ShiftRR<"sh$DDDI\t$Rs1, $Rs2, $Rd",
|
|
450 [(set GPR:$Rd, (shl GPR:$Rs1, GPR:$Rs2))]>;
|
|
451 let isCodeGenOnly = 1 in {
|
|
452 let JJJJJ = 0b10000 in
|
|
453 def SRL_R : ShiftRR<"sh$DDDI\t$Rs1, $Rs2, $Rd", []>;
|
|
454 }
|
|
455 let JJJJJ = 0b11000 in
|
|
456 def SRA_R : ShiftRR<"sha$DDDI\t$Rs1, $Rs2, $Rd", []>;
|
|
457 }
|
|
458
|
|
459 let F = 1, Defs = [SR] in {
|
|
460 let JJJJJ = 0b10000 in
|
|
461 def SHL_F_R : ShiftRR<"sh.f$DDDI\t$Rs1, $Rs2, $Rd", []>;
|
|
462 let isCodeGenOnly = 1 in {
|
|
463 let JJJJJ = 0b10000 in
|
|
464 def SRL_F_R : ShiftRR<"sh.f$DDDI\t$Rs1, $Rs2, $Rd", []>;
|
|
465 }
|
|
466 let JJJJJ = 0b11000 in
|
|
467 def SRA_F_R : ShiftRR<"sha.f$DDDI\t$Rs1, $Rs2, $Rd", []>;
|
|
468 }
|
|
469
|
|
470 // Expand shift-right operations
|
|
471 def : Pat<(srl GPR:$Rs1, GPR:$Rs2),
|
|
472 (SRL_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>;
|
|
473 def : Pat<(sra GPR:$Rs1, GPR:$Rs2),
|
|
474 (SRA_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>;
|
|
475
|
|
476 // -------------------------------------------------- //
|
|
477 // LOAD instructions
|
|
478 // -------------------------------------------------- //
|
|
479
|
|
480 class LoadRR<string OpcString, PatFrag OpNode, ValueType Ty>
|
|
481 : InstRRM<0b0, (outs GPR:$Rd), (ins MEMrr:$src),
|
|
482 !strconcat(OpcString, "\t$src, $Rd"),
|
|
483 [(set (Ty GPR:$Rd), (OpNode ADDRrr:$src))]>,
|
|
484 Sched<[WriteLD]> {
|
|
485 bits<20> src;
|
|
486
|
|
487 let Rs1 = src{19-15};
|
|
488 let Rs2 = src{14-10};
|
|
489 let P = src{9};
|
|
490 let Q = src{8};
|
|
491 let BBB = src{7-5};
|
|
492 let JJJJJ = src{4-0};
|
|
493 let mayLoad = 1;
|
|
494 }
|
|
495
|
|
496 class LoadRI<string OpcString, PatFrag OpNode, ValueType Ty>
|
|
497 : InstRM<0b0, (outs GPR:$Rd), (ins MEMri:$src),
|
|
498 !strconcat(OpcString, "\t$src, $Rd"),
|
|
499 [(set (Ty GPR:$Rd), (OpNode ADDRri:$src))]>,
|
|
500 Sched<[WriteLD]> {
|
|
501 bits<23> src;
|
|
502
|
|
503 let Itinerary = IIC_LD;
|
|
504 let Rs1 = src{22-18};
|
|
505 let P = src{17};
|
|
506 let Q = src{16};
|
|
507 let imm16 = src{15-0};
|
|
508 let isReMaterializable = 1;
|
|
509 let mayLoad = 1;
|
|
510 }
|
|
511
|
|
512 let E = 0 in {
|
|
513 let YL = 0b01 in {
|
|
514 // uld is used here and ld in the alias as the alias is printed out first if
|
|
515 // an alias exist
|
|
516 def LDW_RI : LoadRI<"uld", load, i32>;
|
|
517 def LDW_RR : LoadRR<"ld", load, i32>;
|
|
518 }
|
|
519 }
|
|
520
|
|
521 def : InstAlias<"ld $src, $dst", (LDW_RI GPR:$dst, MEMri:$src)>;
|
|
522
|
|
523 let E = 1 in {
|
|
524 let YL = 0b01 in {
|
|
525 def LDWz_RR : LoadRR<"uld", zextloadi32, i32>;
|
|
526 }
|
|
527 }
|
|
528
|
|
529 let E = 1 in {
|
|
530 let YL = 0b00 in
|
|
531 def LDHz_RR : LoadRR<"uld.h", zextloadi16, i32>;
|
|
532 let YL = 0b10 in
|
|
533 def LDBz_RR : LoadRR<"uld.b", zextloadi8, i32>;
|
|
534 }
|
|
535
|
|
536 let E = 0 in {
|
|
537 let YL = 0b00 in
|
|
538 def LDHs_RR : LoadRR<"ld.h", sextloadi16, i32>;
|
|
539 let YL = 0b10 in
|
|
540 def LDBs_RR : LoadRR<"ld.b", sextloadi8, i32>;
|
|
541 }
|
|
542
|
|
543 def LDADDR : InstSLS<0x0, (outs GPR:$Rd), (ins MEMi:$src),
|
|
544 "ld\t$src, $Rd",
|
|
545 [(set (i32 GPR:$Rd), (load ADDRsls:$src))]>,
|
|
546 Sched<[WriteLD]> {
|
|
547 bits<21> src;
|
|
548
|
|
549 let Itinerary = IIC_LD;
|
|
550 let msb = src{20-16};
|
|
551 let lsb = src{15-0};
|
|
552 let isReMaterializable = 1;
|
|
553 let mayLoad = 1;
|
|
554 }
|
|
555
|
|
556 class LoadSPLS<string asmstring, PatFrag opNode>
|
|
557 : InstSPLS<(outs GPR:$Rd), (ins MEMspls:$src),
|
|
558 !strconcat(asmstring, "\t$src, $Rd"),
|
|
559 [(set (i32 GPR:$Rd), (opNode ADDRspls:$src))]>,
|
|
560 Sched<[WriteLDSW]> {
|
|
561 bits<17> src;
|
|
562 let Itinerary = IIC_LDSW;
|
|
563 let Rs1 = src{16-12};
|
|
564 let P = src{11};
|
|
565 let Q = src{10};
|
|
566 let imm10 = src{9-0};
|
|
567 let mayLoad = 1;
|
|
568 let isReMaterializable = 1;
|
|
569 }
|
|
570
|
|
571 let Y = 0, S = 0, E = 1 in
|
|
572 def LDHz_RI : LoadSPLS<"uld.h", zextloadi16>;
|
|
573
|
|
574 let Y = 0, S = 0, E = 0 in
|
|
575 def LDHs_RI : LoadSPLS<"ld.h", sextloadi16>;
|
|
576
|
|
577 let Y = 1, S = 0, E = 1 in
|
|
578 def LDBz_RI : LoadSPLS<"uld.b", zextloadi8>;
|
|
579
|
|
580 let Y = 1, S = 0, E = 0 in
|
|
581 def LDBs_RI : LoadSPLS<"ld.b", sextloadi8>;
|
|
582
|
|
583 def SLI : InstSLI<(outs GPR:$Rd), (ins i32lo21:$imm),
|
|
584 "mov\t$imm, $Rd",
|
|
585 [(set GPR:$Rd, i32lo21:$imm)]> {
|
|
586 bits<21> imm;
|
|
587
|
|
588 let msb = imm{20-16};
|
|
589 let lsb = imm{15-0};
|
|
590 let isReMaterializable = 1;
|
|
591 let isAsCheapAsAMove = 1;
|
|
592 }
|
|
593
|
|
594 // -------------------------------------------------- //
|
|
595 // STORE instructions
|
|
596 // -------------------------------------------------- //
|
|
597
|
|
598 class StoreRR<string OpcString, PatFrag OpNode, ValueType Ty>
|
|
599 : InstRRM<0b1, (outs), (ins GPR:$Rd, MEMrr:$dst),
|
|
600 !strconcat(OpcString, "\t$Rd, $dst"),
|
|
601 [(OpNode (Ty GPR:$Rd), ADDRrr:$dst)]>,
|
|
602 Sched<[WriteST]> {
|
|
603 bits<20> dst;
|
|
604
|
|
605 let Itinerary = IIC_ST;
|
|
606 let Rs1 = dst{19-15};
|
|
607 let Rs2 = dst{14-10};
|
|
608 let P = dst{9};
|
|
609 let Q = dst{8};
|
|
610 let BBB = dst{7-5};
|
|
611 let JJJJJ = dst{4-0};
|
|
612 let mayStore = 1;
|
|
613 }
|
|
614
|
|
615 class StoreRI<string OpcString, PatFrag OpNode, ValueType Ty>
|
|
616 : InstRM<0b1, (outs), (ins GPR:$Rd, MEMri:$dst),
|
|
617 !strconcat(OpcString, "\t$Rd, $dst"),
|
|
618 [(OpNode (Ty GPR:$Rd), ADDRri:$dst)]>,
|
|
619 Sched<[WriteST]> {
|
|
620 bits<23> dst;
|
|
621
|
|
622 let Itinerary = IIC_ST;
|
|
623 let Rs1 = dst{22-18};
|
|
624 let P = dst{17};
|
|
625 let Q = dst{16};
|
|
626 let imm16 = dst{15-0};
|
|
627 let mayStore = 1;
|
|
628 }
|
|
629
|
|
630 let YL = 0b01, E = 0 in {
|
|
631 def SW_RR : StoreRR<"st", store, i32>;
|
|
632 def SW_RI : StoreRI<"st", store, i32>;
|
|
633 }
|
|
634
|
|
635 let E = 0 in {
|
|
636 let YL = 0b00 in
|
|
637 def STH_RR : StoreRR<"st.h", truncstorei16, i32>;
|
|
638 let YL = 0b10 in
|
|
639 def STB_RR : StoreRR<"st.b", truncstorei8, i32>;
|
|
640 }
|
|
641
|
|
642 def STADDR : InstSLS<0x1, (outs), (ins GPR:$Rd, MEMi:$dst),
|
|
643 "st\t$Rd, $dst",
|
|
644 [(store (i32 GPR:$Rd), ADDRsls:$dst)]>,
|
|
645 Sched<[WriteST]> {
|
|
646 bits<21> dst;
|
|
647
|
|
648 let Itinerary = IIC_ST;
|
|
649 let msb = dst{20-16};
|
|
650 let lsb = dst{15-0};
|
|
651 let mayStore = 1;
|
|
652 }
|
|
653
|
|
654 class StoreSPLS<string asmstring, PatFrag opNode>
|
|
655 : InstSPLS<(outs), (ins GPR:$Rd, MEMspls:$dst),
|
|
656 !strconcat(asmstring, "\t$Rd, $dst"),
|
|
657 [(opNode (i32 GPR:$Rd), ADDRspls:$dst)]>,
|
|
658 Sched<[WriteSTSW]> {
|
|
659 bits<17> dst;
|
|
660
|
|
661 let Itinerary = IIC_STSW;
|
|
662 let Rs1 = dst{16-12};
|
|
663 let P = dst{11};
|
|
664 let Q = dst{10};
|
|
665 let imm10 = dst{9-0};
|
|
666 let mayStore = 1;
|
|
667 }
|
|
668
|
|
669 let Y = 0, S = 1, E = 0 in
|
|
670 def STH_RI : StoreSPLS<"st.h", truncstorei16>;
|
|
671
|
|
672 let Y = 1, S = 1, E = 0 in
|
|
673 def STB_RI : StoreSPLS<"st.b", truncstorei8>;
|
|
674
|
|
675 // -------------------------------------------------- //
|
|
676 // BRANCH instructions
|
|
677 // -------------------------------------------------- //
|
|
678
|
|
679 let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
|
|
680 def BT : InstBR<(outs), (ins BrTarget:$addr),
|
|
681 "bt\t$addr",
|
|
682 [(br bb:$addr)]> {
|
|
683 let DDDI = 0b0000;
|
|
684 }
|
|
685 let Uses = [SR] in
|
|
686 def BRCC : InstBR<(outs), (ins BrTarget:$addr, CCOp:$DDDI),
|
|
687 "b$DDDI\t$addr",
|
|
688 [(LanaiBrCC bb:$addr, imm:$DDDI)]>;
|
|
689
|
|
690 let isIndirectBranch = 1 in {
|
|
691 def JR : InstRR<0b101, (outs), (ins GPR:$Rs2), "bt\t$Rs2",
|
|
692 [(brind GPR:$Rs2)]> {
|
|
693 let Rs1 = R0.Num;
|
|
694 let Rd = R2.Num;
|
|
695 let F = 0;
|
|
696 let JJJJJ = 0;
|
|
697 let DDDI = 0;
|
|
698 }
|
|
699 }
|
|
700 }
|
|
701
|
|
702 // -------------------------------------------------- //
|
|
703 // Condition/SF instructions
|
|
704 // -------------------------------------------------- //
|
|
705
|
|
706 // Instructions to set flags used in lowering comparisons.
|
|
707 multiclass SF<bits<3> op2Val, string AsmStr> {
|
|
708 let F = 1, Rd = R0.Num, JJJJJ = 0, Defs = [SR], DDDI = 0 in
|
|
709 def _RR : InstRR<op2Val, (outs), (ins GPR:$Rs1, GPR:$Rs2),
|
|
710 !strconcat(AsmStr, "\t$Rs1, $Rs2, %r0"),
|
|
711 [(LanaiSetFlag (i32 GPR:$Rs1), (i32 GPR:$Rs2))]>;
|
|
712 let F = 1, Rd = R0.Num, H = 0, Defs = [SR] in
|
|
713 def _RI_LO : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16z:$imm16),
|
|
714 !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"),
|
|
715 [(LanaiSetFlag (i32 GPR:$Rs1), i32lo16z:$imm16)]>;
|
|
716 let F = 1, Rd = R0.Num, H = 1, Defs = [SR] in
|
|
717 def _RI_HI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32hi16:$imm16),
|
|
718 !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"),
|
|
719 [(LanaiSetFlag (i32 GPR:$Rs1), i32hi16:$imm16)]>;
|
|
720 }
|
|
721 let isCodeGenOnly = 1, isCompare = 1 in {
|
|
722 defm SFSUB_F : SF<0b010, "sub.f">;
|
|
723 }
|
|
724
|
|
725 // Jump and link
|
|
726 let isCall = 1, hasDelaySlot = 1, isCodeGenOnly = 1, Uses = [SP],
|
|
727 Defs = [RCA] in {
|
|
728 def CALL : Pseudo<(outs), (ins CallTarget:$addr), "", []>;
|
|
729 def CALLR : Pseudo<(outs), (ins GPR:$Rs1), "", [(Call GPR:$Rs1)]>;
|
|
730 }
|
|
731
|
|
732 let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
|
|
733 Uses = [RCA] in {
|
|
734 def RET : InstRM<0b0, (outs), (ins),
|
|
735 "ld\t-4[%fp], %pc ! return",
|
|
736 [(RetFlag)]> {
|
|
737 let Rd = PC.Num;
|
|
738 let Rs1 = FP.Num;
|
|
739 let P = 1;
|
|
740 let Q = 0;
|
|
741 let imm16 = -4;
|
|
742
|
|
743 // Post encoding is not needed for RET.
|
|
744 let PostEncoderMethod = "";
|
|
745 }
|
|
746 }
|
|
747
|
|
748 // ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
|
|
749 // a stack adjustment and the codegen must know that they may modify the stack
|
|
750 // pointer before prolog-epilog rewriting occurs.
|
|
751 // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
|
752 // sub / add which can clobber SP.
|
|
753 let Defs = [SP], Uses = [SP] in {
|
121
|
754 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
|
|
755 "#ADJCALLSTACKDOWN $amt1 $amt2",
|
|
756 [(CallSeqStart timm:$amt1, timm:$amt2)]>;
|
120
|
757 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
|
|
758 "#ADJCALLSTACKUP $amt1 $amt2",
|
|
759 [(CallSeqEnd timm:$amt1, timm:$amt2)]>;
|
|
760 }
|
|
761
|
|
762 let Defs = [SP], Uses = [SP] in {
|
|
763 def ADJDYNALLOC : Pseudo<(outs GPR:$dst), (ins GPR:$src),
|
|
764 "#ADJDYNALLOC $dst $src",
|
|
765 [(set GPR:$dst, (LanaiAdjDynAlloc GPR:$src))]>;
|
|
766 }
|
|
767
|
|
768 let Uses = [SR] in {
|
|
769 def SCC : InstSCC<(outs GPR:$Rs1), (ins CCOp:$DDDI),
|
|
770 "s$DDDI\t$Rs1",
|
|
771 [(set (i32 GPR:$Rs1), (LanaiSetCC imm:$DDDI))]>;
|
|
772 }
|
|
773
|
|
774 // Select with hardware support
|
|
775 let Uses = [SR], isSelect = 1 in {
|
|
776 def SELECT : InstRR<0b111, (outs GPR:$Rd),
|
|
777 (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
|
778 "sel.$DDDI $Rs1, $Rs2, $Rd",
|
|
779 [(set (i32 GPR:$Rd),
|
|
780 (LanaiSelectCC (i32 GPR:$Rs1), (i32 GPR:$Rs2),
|
|
781 (imm:$DDDI)))]> {
|
|
782 let JJJJJ = 0;
|
|
783 let F = 0;
|
|
784 }
|
|
785 }
|
|
786
|
|
787 let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1,
|
|
788 isIndirectBranch = 1, Uses = [SR] in {
|
|
789 def BRIND_CC : InstRR<0b101, (outs), (ins GPR:$Rs1, CCOp:$DDDI),
|
|
790 "b$DDDI\t$Rs1", []> {
|
|
791 let F = 0;
|
|
792 let JJJJJ = 0;
|
|
793 let Rd = PC.Num;
|
|
794 let Rs2 = R0.Num;
|
|
795 }
|
|
796
|
|
797 def BRIND_CCA : InstRR<0b101, (outs), (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
|
798 "b${DDDI}\t$Rs1 add $Rs2", []> {
|
|
799 let F = 0;
|
|
800 let Rd = PC.Num;
|
|
801 let JJJJJ = 0;
|
|
802 }
|
|
803 }
|
|
804
|
|
805 // TODO: This only considers the case where BROFF is an immediate and not where
|
|
806 // it is a register. Add support for register relative branching.
|
|
807 let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1, Rs1 = 0,
|
|
808 Uses = [SR] in
|
|
809 def BRR : InstBRR<(outs), (ins i16imm:$imm16, CCOp:$DDDI),
|
|
810 "b${DDDI}.r\t$imm16", []>;
|
|
811
|
|
812 let F = 0 in {
|
|
813 // Population Count (POPC)
|
|
814 def POPC: InstSpecial<0b001, (outs GPR:$Rd), (ins GPR:$Rs1),
|
|
815 "popc\t$Rs1, $Rd",
|
|
816 [(set GPR:$Rd, (ctpop GPR:$Rs1))]>;
|
|
817
|
|
818 // Count Leading Zeros (LEADZ)
|
|
819 def LEADZ: InstSpecial<0b010, (outs GPR:$Rd), (ins GPR:$Rs1),
|
|
820 "leadz\t$Rs1, $Rd", [(set GPR:$Rd, (ctlz GPR:$Rs1))]>;
|
|
821
|
|
822 // Count Trailing Zeros (TRAILZ)
|
|
823 def TRAILZ : InstSpecial<0b011, (outs GPR:$Rd), (ins GPR:$Rs1),
|
|
824 "trailz\t$Rs1, $Rd",
|
|
825 [(set GPR:$Rd, (cttz GPR:$Rs1))]>;
|
|
826 }
|
|
827
|
|
828 //===----------------------------------------------------------------------===//
|
|
829 // Non-Instruction Patterns
|
|
830 //===----------------------------------------------------------------------===//
|
|
831
|
|
832 // unsigned 16-bit immediate
|
|
833 def : Pat<(i32 i32lo16z:$imm), (OR_I_LO (i32 R0), imm:$imm)>;
|
|
834
|
|
835 // arbitrary immediate
|
|
836 def : Pat<(i32 imm:$imm), (OR_I_LO (MOVHI (HI16 imm:$imm)), (LO16 imm:$imm))>;
|
|
837
|
|
838 // Calls
|
|
839 def : Pat<(Call tglobaladdr:$dst), (CALL tglobaladdr:$dst)>;
|
|
840 def : Pat<(Call texternalsym:$dst), (CALL texternalsym:$dst)>;
|
|
841
|
|
842 // Loads
|
|
843 def : Pat<(extloadi8 ADDRspls:$src), (i32 (LDBz_RI ADDRspls:$src))>;
|
|
844 def : Pat<(extloadi16 ADDRspls:$src), (i32 (LDHz_RI ADDRspls:$src))>;
|
|
845
|
|
846 // GlobalAddress, ExternalSymbol, Jumptable, ConstantPool
|
|
847 def : Pat<(LanaiHi tglobaladdr:$dst), (MOVHI tglobaladdr:$dst)>;
|
|
848 def : Pat<(LanaiLo tglobaladdr:$dst), (OR_I_LO (i32 R0), tglobaladdr:$dst)>;
|
|
849 def : Pat<(LanaiSmall tglobaladdr:$dst), (SLI tglobaladdr:$dst)>;
|
|
850 def : Pat<(LanaiHi texternalsym:$dst), (MOVHI texternalsym:$dst)>;
|
|
851 def : Pat<(LanaiLo texternalsym:$dst), (OR_I_LO (i32 R0), texternalsym:$dst)>;
|
|
852 def : Pat<(LanaiSmall texternalsym:$dst), (SLI texternalsym:$dst)>;
|
|
853 def : Pat<(LanaiHi tblockaddress:$dst), (MOVHI tblockaddress:$dst)>;
|
|
854 def : Pat<(LanaiLo tblockaddress:$dst), (OR_I_LO (i32 R0), tblockaddress:$dst)>;
|
|
855 def : Pat<(LanaiSmall tblockaddress:$dst), (SLI tblockaddress:$dst)>;
|
|
856 def : Pat<(LanaiHi tjumptable:$dst), (MOVHI tjumptable:$dst)>;
|
|
857 def : Pat<(LanaiLo tjumptable:$dst), (OR_I_LO (i32 R0), tjumptable:$dst)>;
|
|
858 def : Pat<(LanaiSmall tjumptable:$dst), (SLI tjumptable:$dst)>;
|
|
859 def : Pat<(LanaiHi tconstpool:$dst), (MOVHI tconstpool:$dst)>;
|
|
860 def : Pat<(LanaiLo tconstpool:$dst), (OR_I_LO (i32 R0), tconstpool:$dst)>;
|
|
861 def : Pat<(LanaiSmall tconstpool:$dst), (SLI tconstpool:$dst)>;
|
|
862
|
|
863 def : Pat<(or GPR:$hi, (LanaiLo tglobaladdr:$lo)),
|
|
864 (OR_I_LO GPR:$hi, tglobaladdr:$lo)>;
|
|
865 def : Pat<(or R0, (LanaiSmall tglobaladdr:$small)),
|
|
866 (SLI tglobaladdr:$small)>;
|
|
867 def : Pat<(or GPR:$hi, (LanaiLo texternalsym:$lo)),
|
|
868 (OR_I_LO GPR:$hi, texternalsym:$lo)>;
|
|
869 def : Pat<(or R0, (LanaiSmall texternalsym:$small)),
|
|
870 (SLI texternalsym:$small)>;
|
|
871 def : Pat<(or GPR:$hi, (LanaiLo tblockaddress:$lo)),
|
|
872 (OR_I_LO GPR:$hi, tblockaddress:$lo)>;
|
|
873 def : Pat<(or R0, (LanaiSmall tblockaddress:$small)),
|
|
874 (SLI tblockaddress:$small)>;
|
|
875 def : Pat<(or GPR:$hi, (LanaiLo tjumptable:$lo)),
|
|
876 (OR_I_LO GPR:$hi, tjumptable:$lo)>;
|
|
877 def : Pat<(or R0, (LanaiSmall tjumptable:$small)),
|
|
878 (SLI tjumptable:$small)>;
|
|
879 def : Pat<(or GPR:$hi, (LanaiLo tconstpool:$lo)),
|
|
880 (OR_I_LO GPR:$hi, tconstpool:$lo)>;
|
|
881 def : Pat<(or R0, (LanaiSmall tconstpool:$small)),
|
|
882 (SLI tconstpool:$small)>;
|