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