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