Mips16InstrInfo.td revision 7617d032ae12ba96ad65f37d91274e6f8c14e690
1//===- Mips16InstrInfo.td - Target Description for Mips16  -*- tablegen -*-=//
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 Mips16 instructions.
11//
12//===----------------------------------------------------------------------===//
13//
14//
15// Mips Address
16//
17def addr16 :
18  ComplexPattern<iPTR, 3, "SelectAddr16", [frameindex], [SDNPWantParent]>;
19
20//
21// Address operand
22def mem16 : Operand<i32> {
23  let PrintMethod = "printMemOperand";
24  let MIOperandInfo = (ops CPU16Regs, simm16, CPU16Regs);
25  let EncoderMethod = "getMemEncoding";
26}
27
28def mem16_ea : Operand<i32> {
29  let PrintMethod = "printMemOperandEA";
30  let MIOperandInfo = (ops CPU16Regs, simm16);
31  let EncoderMethod = "getMemEncoding";
32}
33
34//
35//
36// I8 instruction format
37//
38
39class FI816_ins_base<bits<3> _func, string asmstr,
40                     string asmstr2, InstrItinClass itin>:
41  FI816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2),
42        [], itin>;
43
44
45class FI816_SP_ins<bits<3> _func, string asmstr,
46                   InstrItinClass itin>:
47  FI816_ins_base<_func, asmstr, "\t$$sp, $imm # 16 bit inst", itin>;
48
49//
50// RI instruction format
51//
52
53
54class FRI16_ins_base<bits<5> op, string asmstr, string asmstr2,
55                     InstrItinClass itin>:
56  FRI16<op, (outs CPU16Regs:$rx), (ins simm16:$imm),
57        !strconcat(asmstr, asmstr2), [], itin>;
58
59class FRI16_ins<bits<5> op, string asmstr,
60                InstrItinClass itin>:
61  FRI16_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;
62
63class FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2,
64                     InstrItinClass itin>:
65  FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm),
66        !strconcat(asmstr, asmstr2), [], itin>;
67
68class FRI16R_ins<bits<5> op, string asmstr,
69                InstrItinClass itin>:
70  FRI16R_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;
71
72class F2RI16_ins<bits<5> _op, string asmstr,
73                     InstrItinClass itin>:
74  FRI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm),
75        !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin> {
76  let Constraints = "$rx_ = $rx";
77}
78
79class FRI16_B_ins<bits<5> _op, string asmstr,
80                  InstrItinClass itin>:
81  FRI16<_op, (outs), (ins  CPU16Regs:$rx, brtarget:$imm),
82        !strconcat(asmstr, "\t$rx, $imm  # 16 bit inst"), [], itin>;
83//
84// Compare a register and immediate and place result in CC
85// Implicit use of T8
86//
87// EXT-CCRR Instruction format
88//
89class FEXT_CCRXI16_ins<string asmstr>:
90  MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, simm16:$imm),
91               !strconcat(asmstr, "\t$rx, $imm\n\tmove\t$cc, $$t8"), []> {
92  let isCodeGenOnly=1;
93}
94
95// JAL and JALX instruction format
96//
97class FJAL16_ins<bits<1> _X, string asmstr,
98                 InstrItinClass itin>:
99  FJAL16<_X, (outs), (ins simm20:$imm),
100         !strconcat(asmstr, "\t$imm\n\tnop"),[],
101         itin>  {
102  let isCodeGenOnly=1;
103}
104//
105// EXT-I instruction format
106//
107class FEXT_I16_ins<bits<5> eop, string asmstr, InstrItinClass itin> :
108  FEXT_I16<eop, (outs), (ins brtarget:$imm16),
109           !strconcat(asmstr, "\t$imm16"),[], itin>;
110
111//
112// EXT-I8 instruction format
113//
114
115class FEXT_I816_ins_base<bits<3> _func, string asmstr,
116                         string asmstr2, InstrItinClass itin>:
117  FEXT_I816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2),
118            [], itin>;
119
120class FEXT_I816_ins<bits<3> _func, string asmstr,
121                    InstrItinClass itin>:
122  FEXT_I816_ins_base<_func, asmstr, "\t$imm", itin>;
123
124class FEXT_I816_SP_ins<bits<3> _func, string asmstr,
125                       InstrItinClass itin>:
126      FEXT_I816_ins_base<_func, asmstr, "\t$$sp, $imm", itin>;
127
128//
129// Assembler formats in alphabetical order.
130// Natural and pseudos are mixed together.
131//
132// Compare two registers and place result in CC
133// Implicit use of T8
134//
135// CC-RR Instruction format
136//
137class FCCRR16_ins<string asmstr> :
138  MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, CPU16Regs:$ry),
139               !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$cc, $$t8"), []> {
140  let isCodeGenOnly=1;
141}
142
143//
144// EXT-RI instruction format
145//
146
147class FEXT_RI16_ins_base<bits<5> _op, string asmstr, string asmstr2,
148                         InstrItinClass itin>:
149  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins simm16:$imm),
150                  !strconcat(asmstr, asmstr2), [], itin>;
151
152class FEXT_RI16_ins<bits<5> _op, string asmstr,
153                    InstrItinClass itin>:
154  FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $imm", itin>;
155
156class FEXT_RI16R_ins_base<bits<5> _op, string asmstr, string asmstr2,
157                         InstrItinClass itin>:
158  FEXT_RI16<_op, (outs ), (ins CPU16Regs:$rx, simm16:$imm),
159                  !strconcat(asmstr, asmstr2), [], itin>;
160
161class FEXT_RI16R_ins<bits<5> _op, string asmstr,
162                    InstrItinClass itin>:
163  FEXT_RI16R_ins_base<_op, asmstr, "\t$rx, $imm", itin>;
164
165class FEXT_RI16_PC_ins<bits<5> _op, string asmstr, InstrItinClass itin>:
166  FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $$pc, $imm", itin>;
167
168class FEXT_RI16_B_ins<bits<5> _op, string asmstr,
169                      InstrItinClass itin>:
170  FEXT_RI16<_op, (outs), (ins  CPU16Regs:$rx, brtarget:$imm),
171            !strconcat(asmstr, "\t$rx, $imm"), [], itin>;
172
173class FEXT_2RI16_ins<bits<5> _op, string asmstr,
174                     InstrItinClass itin>:
175  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm),
176            !strconcat(asmstr, "\t$rx, $imm"), [], itin> {
177  let Constraints = "$rx_ = $rx";
178}
179
180
181// this has an explicit sp argument that we ignore to work around a problem
182// in the compiler
183class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr,
184                                InstrItinClass itin>:
185  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm),
186            !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
187
188//
189// EXT-RRI instruction format
190//
191
192class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd,
193                         InstrItinClass itin>:
194  FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins  MemOpnd:$addr),
195             !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
196
197class FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, Operand MemOpnd,
198                          InstrItinClass itin>:
199  FEXT_RRI16<op, (outs ), (ins  CPU16Regs:$ry, MemOpnd:$addr),
200             !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
201
202//
203//
204// EXT-RRI-A instruction format
205//
206
207class FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, Operand MemOpnd,
208                           InstrItinClass itin>:
209  FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins  MemOpnd:$addr),
210               !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
211
212//
213// EXT-SHIFT instruction format
214//
215class FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>:
216  FEXT_SHIFT16<_f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry, shamt:$sa),
217               !strconcat(asmstr, "\t$rx, $ry, $sa"), [], itin>;
218
219//
220// EXT-T8I8
221//
222class FEXT_T8I816_ins<string asmstr, string asmstr2>:
223  MipsPseudo16<(outs),
224               (ins CPU16Regs:$rx, CPU16Regs:$ry, brtarget:$imm),
225               !strconcat(asmstr2, !strconcat("\t$rx, $ry\n\t",
226               !strconcat(asmstr, "\t$imm"))),[]> {
227  let isCodeGenOnly=1;
228}
229
230//
231// EXT-T8I8I
232//
233class FEXT_T8I8I16_ins<string asmstr, string asmstr2>:
234  MipsPseudo16<(outs),
235               (ins CPU16Regs:$rx, simm16:$imm, brtarget:$targ),
236               !strconcat(asmstr2, !strconcat("\t$rx, $imm\n\t",
237               !strconcat(asmstr, "\t$targ"))), []> {
238  let isCodeGenOnly=1;
239}
240//
241
242
243//
244// I8_MOVR32 instruction format (used only by the MOVR32 instructio
245//
246class FI8_MOVR3216_ins<string asmstr, InstrItinClass itin>:
247       FI8_MOVR3216<(outs CPU16Regs:$rz), (ins CPURegs:$r32),
248       !strconcat(asmstr,  "\t$rz, $r32"), [], itin>;
249
250//
251// I8_MOV32R instruction format (used only by MOV32R instruction)
252//
253
254class FI8_MOV32R16_ins<string asmstr, InstrItinClass itin>:
255  FI8_MOV32R16<(outs CPURegs:$r32), (ins CPU16Regs:$rz),
256               !strconcat(asmstr,  "\t$r32, $rz"), [], itin>;
257
258//
259// This are pseudo formats for multiply
260// This first one can be changed to non pseudo now.
261//
262// MULT
263//
264class FMULT16_ins<string asmstr, InstrItinClass itin> :
265  MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry),
266               !strconcat(asmstr, "\t$rx, $ry"), []>;
267
268//
269// MULT-LO
270//
271class FMULT16_LO_ins<string asmstr, InstrItinClass itin> :
272  MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
273               !strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> {
274  let isCodeGenOnly=1;
275}
276
277//
278// RR-type instruction format
279//
280
281class FRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> :
282  FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
283        !strconcat(asmstr, "\t$rx, $ry"), [], itin> {
284}
285
286class FRRTR16_ins<string asmstr> :
287  MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
288               !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$rz, $$t8"), []> ;
289
290//
291// maybe refactor but need a $zero as a dummy first parameter
292//
293class FRR16_div_ins<bits<5> f, string asmstr, InstrItinClass itin> :
294  FRR16<f, (outs ), (ins CPU16Regs:$rx, CPU16Regs:$ry),
295        !strconcat(asmstr, "\t$$zero, $rx, $ry"), [], itin> ;
296
297class FUnaryRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> :
298  FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
299        !strconcat(asmstr, "\t$rx, $ry"), [], itin> ;
300
301
302class FRR16_M_ins<bits<5> f, string asmstr,
303                  InstrItinClass itin> :
304  FRR16<f, (outs CPU16Regs:$rx), (ins),
305        !strconcat(asmstr, "\t$rx"), [], itin>;
306
307class FRxRxRy16_ins<bits<5> f, string asmstr,
308                    InstrItinClass itin> :
309  FRR16<f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
310            !strconcat(asmstr, "\t$rz, $ry"),
311            [], itin> {
312  let Constraints = "$rx = $rz";
313}
314
315let rx=0 in
316class FRR16_JALRC_RA_only_ins<bits<1> nd_, bits<1> l_,
317                              string asmstr, InstrItinClass itin>:
318  FRR16_JALRC<nd_, l_, 1, (outs), (ins), !strconcat(asmstr, "\t $$ra"),
319              [], itin> ;
320
321
322class FRR16_JALRC_ins<bits<1> nd, bits<1> l, bits<1> ra,
323                      string asmstr, InstrItinClass itin>:
324  FRR16_JALRC<nd, l, ra, (outs), (ins CPU16Regs:$rx),
325              !strconcat(asmstr, "\t $rx"), [], itin> ;
326
327//
328// RRR-type instruction format
329//
330
331class FRRR16_ins<bits<2> _f, string asmstr,  InstrItinClass itin> :
332  FRRR16<_f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
333         !strconcat(asmstr, "\t$rz, $rx, $ry"), [], itin>;
334
335//
336// These Sel patterns support the generation of conditional move
337// pseudo instructions.
338//
339// The nomenclature uses the components making up the pseudo and may
340// be a bit counter intuitive when compared with the end result we seek.
341// For example using a bqez in the example directly below results in the
342// conditional move being done if the tested register is not zero.
343// I considered in easier to check by keeping the pseudo consistent with
344// it's components but it could have been done differently.
345//
346// The simplest case is when can test and operand directly and do the
347// conditional move based on a simple mips16 conditional
348//  branch instruction.
349// for example:
350// if $op == beqz or bnez:
351//
352// $op1 $rt, .+4
353// move $rd, $rs
354//
355// if $op == beqz, then if $rt != 0, then the conditional assignment
356// $rd = $rs is done.
357
358// if $op == bnez, then if $rt == 0, then the conditional assignment
359// $rd = $rs is done.
360//
361// So this pseudo class only has one operand, i.e. op
362//
363class Sel<string op>:
364  MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs,
365               CPU16Regs:$rt),
366               !strconcat(op, "\t$rt, .+4\n\t\n\tmove $rd, $rs"), []> {
367  //let isCodeGenOnly=1;
368  let Constraints = "$rd = $rd_";
369  let usesCustomInserter = 1;
370}
371
372//
373// The next two instruction classes allow for an operand which tests
374// two operands and returns a value in register T8 and
375//then does a conditional branch based on the value of T8
376//
377
378// op2 can be cmpi or slti/sltiu
379// op1 can bteqz or btnez
380// the operands for op2 are a register and a signed constant
381//
382// $op2 $t, $imm  ;test register t and branch conditionally
383// $op1 .+4       ;op1 is a conditional branch
384// move $rd, $rs
385//
386//
387class SeliT<string op1, string op2>:
388  MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs,
389                                       CPU16Regs:$rl, simm16:$imm),
390               !strconcat(op2,
391               !strconcat("\t$rl, $imm\n\t",
392               !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> {
393  let isCodeGenOnly=1;
394  let Constraints = "$rd = $rd_";
395  let usesCustomInserter = 1;
396}
397
398//
399// op2 can be cmp or slt/sltu
400// op1 can be bteqz or btnez
401// the operands for op2 are two registers
402// op1 is a conditional branch
403//
404//
405// $op2 $rl, $rr  ;test registers rl,rr
406// $op1 .+4       ;op2 is a conditional branch
407// move $rd, $rs
408//
409//
410class SelT<string op1, string op2>:
411  MipsPseudo16<(outs CPU16Regs:$rd_),
412               (ins CPU16Regs:$rd, CPU16Regs:$rs,
413                CPU16Regs:$rl, CPU16Regs:$rr),
414               !strconcat(op2,
415               !strconcat("\t$rl, $rr\n\t",
416               !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> {
417  let isCodeGenOnly=1;
418  let Constraints = "$rd = $rd_";
419}
420
421//
422// 32 bit constant
423//
424def imm32: Operand<i32>;
425
426def Constant32:
427  MipsPseudo16<(outs), (ins imm32:$imm), "\t.word $imm", []>;
428
429def LwConstant32:
430  MipsPseudo16<(outs), (ins CPU16Regs:$rx, imm32:$imm),
431    "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>;
432
433
434//
435// Some general instruction class info
436//
437//
438
439class ArithLogic16Defs<bit isCom=0> {
440  bits<5> shamt = 0;
441  bit isCommutable = isCom;
442  bit isReMaterializable = 1;
443  bit neverHasSideEffects = 1;
444}
445
446class branch16 {
447  bit isBranch = 1;
448  bit isTerminator = 1;
449  bit isBarrier = 1;
450}
451
452class cbranch16 {
453  bit isBranch = 1;
454  bit isTerminator = 1;
455}
456
457class MayLoad {
458  bit mayLoad = 1;
459}
460
461class MayStore {
462  bit mayStore = 1;
463}
464//
465
466
467// Format: ADDIU rx, immediate MIPS16e
468// Purpose: Add Immediate Unsigned Word (2-Operand, Extended)
469// To add a constant to a 32-bit integer.
470//
471def AddiuRxImmX16: FEXT_RI16_ins<0b01001, "addiu", IIAlu>;
472
473def AddiuRxRxImm16: F2RI16_ins<0b01001, "addiu", IIAlu>,
474  ArithLogic16Defs<0> {
475  let AddedComplexity = 5;
476}
477def AddiuRxRxImmX16: FEXT_2RI16_ins<0b01001, "addiu", IIAlu>,
478  ArithLogic16Defs<0> {
479  let isCodeGenOnly = 1;
480}
481
482def AddiuRxRyOffMemX16:
483  FEXT_RRI_A16_mem_ins<0, "addiu", mem16_ea, IIAlu>;
484
485//
486
487// Format: ADDIU rx, pc, immediate MIPS16e
488// Purpose: Add Immediate Unsigned Word (3-Operand, PC-Relative, Extended)
489// To add a constant to the program counter.
490//
491def AddiuRxPcImmX16: FEXT_RI16_PC_ins<0b00001, "addiu", IIAlu>;
492
493//
494// Format: ADDIU sp, immediate MIPS16e
495// Purpose: Add Immediate Unsigned Word (2-Operand, SP-Relative, Extended)
496// To add a constant to the stack pointer.
497//
498def AddiuSpImm16
499  : FI816_SP_ins<0b011, "addiu", IIAlu> {
500  let Defs = [SP];
501  let Uses = [SP];
502  let AddedComplexity = 5;
503}
504
505def AddiuSpImmX16
506  : FEXT_I816_SP_ins<0b011, "addiu", IIAlu> {
507  let Defs = [SP];
508  let Uses = [SP];
509}
510
511//
512// Format: ADDU rz, rx, ry MIPS16e
513// Purpose: Add Unsigned Word (3-Operand)
514// To add 32-bit integers.
515//
516
517def AdduRxRyRz16: FRRR16_ins<01, "addu", IIAlu>, ArithLogic16Defs<1>;
518
519//
520// Format: AND rx, ry MIPS16e
521// Purpose: AND
522// To do a bitwise logical AND.
523
524def AndRxRxRy16: FRxRxRy16_ins<0b01100, "and", IIAlu>, ArithLogic16Defs<1>;
525
526
527//
528// Format: BEQZ rx, offset MIPS16e
529// Purpose: Branch on Equal to Zero
530// To test a GPR then do a PC-relative conditional branch.
531//
532def BeqzRxImm16: FRI16_B_ins<0b00100, "beqz", IIAlu>, cbranch16;
533
534
535//
536// Format: BEQZ rx, offset MIPS16e
537// Purpose: Branch on Equal to Zero (Extended)
538// To test a GPR then do a PC-relative conditional branch.
539//
540def BeqzRxImmX16: FEXT_RI16_B_ins<0b00100, "beqz", IIAlu>, cbranch16;
541
542// Format: B offset MIPS16e
543// Purpose: Unconditional Branch
544// To do an unconditional PC-relative branch.
545//
546def BimmX16: FEXT_I16_ins<0b00010, "b", IIAlu>, branch16;
547
548//
549// Format: BNEZ rx, offset MIPS16e
550// Purpose: Branch on Not Equal to Zero
551// To test a GPR then do a PC-relative conditional branch.
552//
553def BnezRxImm16: FRI16_B_ins<0b00101, "bnez", IIAlu>, cbranch16;
554
555//
556// Format: BNEZ rx, offset MIPS16e
557// Purpose: Branch on Not Equal to Zero (Extended)
558// To test a GPR then do a PC-relative conditional branch.
559//
560def BnezRxImmX16: FEXT_RI16_B_ins<0b00101, "bnez", IIAlu>, cbranch16;
561
562//
563// Format: BTEQZ offset MIPS16e
564// Purpose: Branch on T Equal to Zero (Extended)
565// To test special register T then do a PC-relative conditional branch.
566//
567def BteqzX16: FEXT_I816_ins<0b000, "bteqz", IIAlu>, cbranch16 {
568  let Uses = [T8];
569}
570
571def BteqzT8CmpX16: FEXT_T8I816_ins<"bteqz", "cmp">, cbranch16;
572
573def BteqzT8CmpiX16: FEXT_T8I8I16_ins<"bteqz", "cmpi">,
574  cbranch16;
575
576def BteqzT8SltX16: FEXT_T8I816_ins<"bteqz", "slt">, cbranch16;
577
578def BteqzT8SltuX16: FEXT_T8I816_ins<"bteqz", "sltu">, cbranch16;
579
580def BteqzT8SltiX16: FEXT_T8I8I16_ins<"bteqz", "slti">, cbranch16;
581
582def BteqzT8SltiuX16: FEXT_T8I8I16_ins<"bteqz", "sltiu">,
583  cbranch16;
584
585//
586// Format: BTNEZ offset MIPS16e
587// Purpose: Branch on T Not Equal to Zero (Extended)
588// To test special register T then do a PC-relative conditional branch.
589//
590def BtnezX16: FEXT_I816_ins<0b001, "btnez", IIAlu> ,cbranch16 {
591  let Uses = [T8];
592}
593
594def BtnezT8CmpX16: FEXT_T8I816_ins<"btnez", "cmp">, cbranch16;
595
596def BtnezT8CmpiX16: FEXT_T8I8I16_ins<"btnez", "cmpi">, cbranch16;
597
598def BtnezT8SltX16: FEXT_T8I816_ins<"btnez", "slt">, cbranch16;
599
600def BtnezT8SltuX16: FEXT_T8I816_ins<"btnez", "sltu">, cbranch16;
601
602def BtnezT8SltiX16: FEXT_T8I8I16_ins<"btnez", "slti">, cbranch16;
603
604def BtnezT8SltiuX16: FEXT_T8I8I16_ins<"btnez", "sltiu">,
605  cbranch16;
606
607//
608// Format: CMP rx, ry MIPS16e
609// Purpose: Compare
610// To compare the contents of two GPRs.
611//
612def CmpRxRy16: FRR16_ins<0b01010, "cmp", IIAlu> {
613  let Defs = [T8];
614}
615
616//
617// Format: CMPI rx, immediate MIPS16e
618// Purpose: Compare Immediate
619// To compare a constant with the contents of a GPR.
620//
621def CmpiRxImm16: FRI16_ins<0b01110, "cmpi", IIAlu> {
622  let Defs = [T8];
623}
624
625//
626// Format: CMPI rx, immediate MIPS16e
627// Purpose: Compare Immediate (Extended)
628// To compare a constant with the contents of a GPR.
629//
630def CmpiRxImmX16: FEXT_RI16_ins<0b01110, "cmpi", IIAlu> {
631  let Defs = [T8];
632}
633
634
635//
636// Format: DIV rx, ry MIPS16e
637// Purpose: Divide Word
638// To divide 32-bit signed integers.
639//
640def DivRxRy16: FRR16_div_ins<0b11010, "div", IIAlu> {
641  let Defs = [HI, LO];
642}
643
644//
645// Format: DIVU rx, ry MIPS16e
646// Purpose: Divide Unsigned Word
647// To divide 32-bit unsigned integers.
648//
649def DivuRxRy16: FRR16_div_ins<0b11011, "divu", IIAlu> {
650  let Defs = [HI, LO];
651}
652//
653// Format: JAL target MIPS16e
654// Purpose: Jump and Link
655// To execute a procedure call within the current 256 MB-aligned
656// region and preserve the current ISA.
657//
658
659def Jal16 : FJAL16_ins<0b0, "jal", IIAlu> {
660  let isBranch = 1;
661  let hasDelaySlot = 0;  // not true, but we add the nop for now
662  let isTerminator=1;
663  let isBarrier=1;
664}
665
666//
667// Format: JR ra MIPS16e
668// Purpose: Jump Register Through Register ra
669// To execute a branch to the instruction address in the return
670// address register.
671//
672
673def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu> {
674  let isBranch = 1;
675  let isIndirectBranch = 1;
676  let hasDelaySlot = 1;
677  let isTerminator=1;
678  let isBarrier=1;
679}
680
681def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIAlu> {
682  let isBranch = 1;
683  let isIndirectBranch = 1;
684  let isTerminator=1;
685  let isBarrier=1;
686}
687
688def JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc", IIAlu> {
689  let isBranch = 1;
690  let isIndirectBranch = 1;
691  let isTerminator=1;
692  let isBarrier=1;
693}
694//
695// Format: LB ry, offset(rx) MIPS16e
696// Purpose: Load Byte (Extended)
697// To load a byte from memory as a signed value.
698//
699def LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", mem16, IILoad>, MayLoad{
700  let isCodeGenOnly = 1;
701}
702
703//
704// Format: LBU ry, offset(rx) MIPS16e
705// Purpose: Load Byte Unsigned (Extended)
706// To load a byte from memory as a unsigned value.
707//
708def LbuRxRyOffMemX16:
709  FEXT_RRI16_mem_ins<0b10100, "lbu", mem16, IILoad>, MayLoad {
710  let isCodeGenOnly = 1;
711}
712
713//
714// Format: LH ry, offset(rx) MIPS16e
715// Purpose: Load Halfword signed (Extended)
716// To load a halfword from memory as a signed value.
717//
718def LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", mem16, IILoad>, MayLoad{
719  let isCodeGenOnly = 1;
720}
721
722//
723// Format: LHU ry, offset(rx) MIPS16e
724// Purpose: Load Halfword unsigned (Extended)
725// To load a halfword from memory as an unsigned value.
726//
727def LhuRxRyOffMemX16:
728  FEXT_RRI16_mem_ins<0b10100, "lhu", mem16, IILoad>, MayLoad {
729  let isCodeGenOnly = 1;
730}
731
732//
733// Format: LI rx, immediate MIPS16e
734// Purpose: Load Immediate
735// To load a constant into a GPR.
736//
737def LiRxImm16: FRI16_ins<0b01101, "li", IIAlu>;
738
739//
740// Format: LI rx, immediate MIPS16e
741// Purpose: Load Immediate (Extended)
742// To load a constant into a GPR.
743//
744def LiRxImmX16: FEXT_RI16_ins<0b01101, "li", IIAlu>;
745
746//
747// Format: LW ry, offset(rx) MIPS16e
748// Purpose: Load Word (Extended)
749// To load a word from memory as a signed value.
750//
751def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, IILoad>, MayLoad{
752  let isCodeGenOnly = 1;
753}
754
755// Format: LW rx, offset(sp) MIPS16e
756// Purpose: Load Word (SP-Relative, Extended)
757// To load an SP-relative word from memory as a signed value.
758//
759def LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10110, "lw", IILoad>, MayLoad{
760  let Uses = [SP];
761}
762
763//
764// Format: MOVE r32, rz MIPS16e
765// Purpose: Move
766// To move the contents of a GPR to a GPR.
767//
768def Move32R16: FI8_MOV32R16_ins<"move", IIAlu>;
769
770//
771// Format: MOVE ry, r32 MIPS16e
772//Purpose: Move
773// To move the contents of a GPR to a GPR.
774//
775def MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>;
776
777//
778// Format: MFHI rx MIPS16e
779// Purpose: Move From HI Register
780// To copy the special purpose HI register to a GPR.
781//
782def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> {
783  let Uses = [HI];
784  let neverHasSideEffects = 1;
785}
786
787//
788// Format: MFLO rx MIPS16e
789// Purpose: Move From LO Register
790// To copy the special purpose LO register to a GPR.
791//
792def Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> {
793  let Uses = [LO];
794  let neverHasSideEffects = 1;
795}
796
797//
798// Pseudo Instruction for mult
799//
800def MultRxRy16:  FMULT16_ins<"mult",  IIAlu> {
801  let isCommutable = 1;
802  let neverHasSideEffects = 1;
803  let Defs = [HI, LO];
804}
805
806def MultuRxRy16: FMULT16_ins<"multu", IIAlu> {
807  let isCommutable = 1;
808  let neverHasSideEffects = 1;
809  let Defs = [HI, LO];
810}
811
812//
813// Format: MULT rx, ry MIPS16e
814// Purpose: Multiply Word
815// To multiply 32-bit signed integers.
816//
817def MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> {
818  let isCommutable = 1;
819  let neverHasSideEffects = 1;
820  let Defs = [HI, LO];
821}
822
823//
824// Format: MULTU rx, ry MIPS16e
825// Purpose: Multiply Unsigned Word
826// To multiply 32-bit unsigned integers.
827//
828def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIAlu> {
829  let isCommutable = 1;
830  let neverHasSideEffects = 1;
831  let Defs = [HI, LO];
832}
833
834//
835// Format: NEG rx, ry MIPS16e
836// Purpose: Negate
837// To negate an integer value.
838//
839def NegRxRy16: FUnaryRR16_ins<0b11101, "neg", IIAlu>;
840
841//
842// Format: NOT rx, ry MIPS16e
843// Purpose: Not
844// To complement an integer value
845//
846def NotRxRy16: FUnaryRR16_ins<0b01111, "not", IIAlu>;
847
848//
849// Format: OR rx, ry MIPS16e
850// Purpose: Or
851// To do a bitwise logical OR.
852//
853def OrRxRxRy16: FRxRxRy16_ins<0b01101, "or", IIAlu>, ArithLogic16Defs<1>;
854
855//
856// Format: RESTORE {ra,}{s0/s1/s0-1,}{framesize}
857// (All args are optional) MIPS16e
858// Purpose: Restore Registers and Deallocate Stack Frame
859// To deallocate a stack frame before exit from a subroutine,
860// restoring return address and static registers, and adjusting
861// stack
862//
863
864// fixed form for restoring RA and the frame
865// for direct object emitter, encoding needs to be adjusted for the
866// frame size
867//
868let ra=1, s=0,s0=1,s1=1 in
869def RestoreRaF16:
870  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
871             "restore\t$$ra,  $$s0, $$s1, $frame_size", [], IILoad >, MayLoad {
872  let isCodeGenOnly = 1;
873  let Defs = [S0, S1, RA, SP];
874  let Uses = [SP];
875}
876
877// Use Restore to increment SP since SP is not a Mip 16 register, this
878// is an easy way to do that which does not require a register.
879//
880let ra=0, s=0,s0=0,s1=0 in
881def RestoreIncSpF16:
882  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
883             "restore\t$frame_size", [], IILoad >, MayLoad {
884  let isCodeGenOnly = 1;
885  let Defs = [SP];
886  let Uses = [SP];
887}
888
889//
890// Format: SAVE {ra,}{s0/s1/s0-1,}{framesize} (All arguments are optional)
891// MIPS16e
892// Purpose: Save Registers and Set Up Stack Frame
893// To set up a stack frame on entry to a subroutine,
894// saving return address and static registers, and adjusting stack
895//
896let ra=1, s=1,s0=1,s1=1 in
897def SaveRaF16:
898  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
899             "save\t$$ra, $$s0, $$s1, $frame_size", [], IIStore >, MayStore {
900  let isCodeGenOnly = 1;
901  let Uses = [RA, SP, S0, S1];
902  let Defs = [SP];
903}
904
905//
906// Use Save to decrement the SP by a constant since SP is not
907// a Mips16 register.
908//
909let ra=0, s=0,s0=0,s1=0 in
910def SaveDecSpF16:
911  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
912             "save\t$frame_size", [], IIStore >, MayStore {
913  let isCodeGenOnly = 1;
914  let Uses = [SP];
915  let Defs = [SP];
916}
917//
918// Format: SB ry, offset(rx) MIPS16e
919// Purpose: Store Byte (Extended)
920// To store a byte to memory.
921//
922def SbRxRyOffMemX16:
923  FEXT_RRI16_mem2_ins<0b11000, "sb", mem16, IIStore>, MayStore;
924
925//
926// The Sel(T) instructions are pseudos
927// T means that they use T8 implicitly.
928//
929//
930// Format: SelBeqZ rd, rs, rt
931// Purpose: if rt==0, do nothing
932//          else rs = rt
933//
934def SelBeqZ: Sel<"beqz">;
935
936//
937// Format:  SelTBteqZCmp rd, rs, rl, rr
938// Purpose: b = Cmp rl, rr.
939//          If b==0 then do nothing.
940//          if b!=0 then rd = rs
941//
942def SelTBteqZCmp: SelT<"bteqz", "cmp">;
943
944//
945// Format:  SelTBteqZCmpi rd, rs, rl, rr
946// Purpose: b = Cmpi rl, imm.
947//          If b==0 then do nothing.
948//          if b!=0 then rd = rs
949//
950def SelTBteqZCmpi: SeliT<"bteqz", "cmpi">;
951
952//
953// Format:  SelTBteqZSlt rd, rs, rl, rr
954// Purpose: b = Slt rl, rr.
955//          If b==0 then do nothing.
956//          if b!=0 then rd = rs
957//
958def SelTBteqZSlt: SelT<"bteqz", "slt">;
959
960//
961// Format:  SelTBteqZSlti rd, rs, rl, rr
962// Purpose: b = Slti rl, imm.
963//          If b==0 then do nothing.
964//          if b!=0 then rd = rs
965//
966def SelTBteqZSlti: SeliT<"bteqz", "slti">;
967
968//
969// Format:  SelTBteqZSltu rd, rs, rl, rr
970// Purpose: b = Sltu rl, rr.
971//          If b==0 then do nothing.
972//          if b!=0 then rd = rs
973//
974def SelTBteqZSltu: SelT<"bteqz", "sltu">;
975
976//
977// Format:  SelTBteqZSltiu rd, rs, rl, rr
978// Purpose: b = Sltiu rl, imm.
979//          If b==0 then do nothing.
980//          if b!=0 then rd = rs
981//
982def SelTBteqZSltiu: SeliT<"bteqz", "sltiu">;
983
984//
985// Format: SelBnez rd, rs, rt
986// Purpose: if rt!=0, do nothing
987//          else rs = rt
988//
989def SelBneZ: Sel<"bnez">;
990
991//
992// Format:  SelTBtneZCmp rd, rs, rl, rr
993// Purpose: b = Cmp rl, rr.
994//          If b!=0 then do nothing.
995//          if b0=0 then rd = rs
996//
997def SelTBtneZCmp: SelT<"btnez", "cmp">;
998
999//
1000// Format:  SelTBtnezCmpi rd, rs, rl, rr
1001// Purpose: b = Cmpi rl, imm.
1002//          If b!=0 then do nothing.
1003//          if b==0 then rd = rs
1004//
1005def SelTBtneZCmpi: SeliT<"btnez", "cmpi">;
1006
1007//
1008// Format:  SelTBtneZSlt rd, rs, rl, rr
1009// Purpose: b = Slt rl, rr.
1010//          If b!=0 then do nothing.
1011//          if b==0 then rd = rs
1012//
1013def SelTBtneZSlt: SelT<"btnez", "slt">;
1014
1015//
1016// Format:  SelTBtneZSlti rd, rs, rl, rr
1017// Purpose: b = Slti rl, imm.
1018//          If b!=0 then do nothing.
1019//          if b==0 then rd = rs
1020//
1021def SelTBtneZSlti: SeliT<"btnez", "slti">;
1022
1023//
1024// Format:  SelTBtneZSltu rd, rs, rl, rr
1025// Purpose: b = Sltu rl, rr.
1026//          If b!=0 then do nothing.
1027//          if b==0 then rd = rs
1028//
1029def SelTBtneZSltu: SelT<"btnez", "sltu">;
1030
1031//
1032// Format:  SelTBtneZSltiu rd, rs, rl, rr
1033// Purpose: b = Slti rl, imm.
1034//          If b!=0 then do nothing.
1035//          if b==0 then rd = rs
1036//
1037def SelTBtneZSltiu: SeliT<"btnez", "sltiu">;
1038//
1039//
1040// Format: SH ry, offset(rx) MIPS16e
1041// Purpose: Store Halfword (Extended)
1042// To store a halfword to memory.
1043//
1044def ShRxRyOffMemX16:
1045  FEXT_RRI16_mem2_ins<0b11001, "sh", mem16, IIStore>, MayStore;
1046
1047//
1048// Format: SLL rx, ry, sa MIPS16e
1049// Purpose: Shift Word Left Logical (Extended)
1050// To execute a left-shift of a word by a fixed number of bits—0 to 31 bits.
1051//
1052def SllX16: FEXT_SHIFT16_ins<0b00, "sll", IIAlu>;
1053
1054//
1055// Format: SLLV ry, rx MIPS16e
1056// Purpose: Shift Word Left Logical Variable
1057// To execute a left-shift of a word by a variable number of bits.
1058//
1059def SllvRxRy16 : FRxRxRy16_ins<0b00100, "sllv", IIAlu>;
1060
1061// Format: SLTI rx, immediate MIPS16e
1062// Purpose: Set on Less Than Immediate
1063// To record the result of a less-than comparison with a constant.
1064//
1065//
1066def SltiRxImm16: FRI16R_ins<0b01010, "slti", IIAlu> {
1067  let Defs = [T8];
1068}
1069
1070//
1071// Format: SLTI rx, immediate MIPS16e
1072// Purpose: Set on Less Than Immediate (Extended)
1073// To record the result of a less-than comparison with a constant.
1074//
1075//
1076def SltiRxImmX16: FEXT_RI16R_ins<0b01010, "slti", IIAlu> {
1077  let Defs = [T8];
1078}
1079
1080def SltiCCRxImmX16: FEXT_CCRXI16_ins<"slti">;
1081
1082// Format: SLTIU rx, immediate MIPS16e
1083// Purpose: Set on Less Than Immediate Unsigned
1084// To record the result of a less-than comparison with a constant.
1085//
1086//
1087def SltiuRxImm16: FRI16R_ins<0b01011, "sltiu", IIAlu> {
1088  let Defs = [T8];
1089}
1090
1091//
1092// Format: SLTI rx, immediate MIPS16e
1093// Purpose: Set on Less Than Immediate Unsigned (Extended)
1094// To record the result of a less-than comparison with a constant.
1095//
1096//
1097def SltiuRxImmX16: FEXT_RI16R_ins<0b01011, "sltiu", IIAlu> {
1098  let Defs = [T8];
1099}
1100//
1101// Format: SLTIU rx, immediate MIPS16e
1102// Purpose: Set on Less Than Immediate Unsigned (Extended)
1103// To record the result of a less-than comparison with a constant.
1104//
1105def SltiuCCRxImmX16: FEXT_CCRXI16_ins<"sltiu">;
1106
1107//
1108// Format: SLT rx, ry MIPS16e
1109// Purpose: Set on Less Than
1110// To record the result of a less-than comparison.
1111//
1112def SltRxRy16: FRR16_ins<0b00010, "slt", IIAlu>{
1113  let Defs = [T8];
1114}
1115
1116def SltCCRxRy16: FCCRR16_ins<"slt">;
1117
1118// Format: SLTU rx, ry MIPS16e
1119// Purpose: Set on Less Than Unsigned
1120// To record the result of an unsigned less-than comparison.
1121//
1122def SltuRxRy16: FRR16_ins<0b00011, "sltu", IIAlu>{
1123  let Defs = [T8];
1124}
1125
1126def SltuRxRyRz16: FRRTR16_ins<"sltu"> {
1127  let isCodeGenOnly=1;
1128  let Defs = [T8];
1129}
1130
1131
1132def SltuCCRxRy16: FCCRR16_ins<"sltu">;
1133//
1134// Format: SRAV ry, rx MIPS16e
1135// Purpose: Shift Word Right Arithmetic Variable
1136// To execute an arithmetic right-shift of a word by a variable
1137// number of bits.
1138//
1139def SravRxRy16: FRxRxRy16_ins<0b00111, "srav", IIAlu>;
1140
1141
1142//
1143// Format: SRA rx, ry, sa MIPS16e
1144// Purpose: Shift Word Right Arithmetic (Extended)
1145// To execute an arithmetic right-shift of a word by a fixed
1146// number of bits—1 to 8 bits.
1147//
1148def SraX16: FEXT_SHIFT16_ins<0b11, "sra", IIAlu>;
1149
1150
1151//
1152// Format: SRLV ry, rx MIPS16e
1153// Purpose: Shift Word Right Logical Variable
1154// To execute a logical right-shift of a word by a variable
1155// number of bits.
1156//
1157def SrlvRxRy16: FRxRxRy16_ins<0b00110, "srlv", IIAlu>;
1158
1159
1160//
1161// Format: SRL rx, ry, sa MIPS16e
1162// Purpose: Shift Word Right Logical (Extended)
1163// To execute a logical right-shift of a word by a fixed
1164// number of bits—1 to 31 bits.
1165//
1166def SrlX16: FEXT_SHIFT16_ins<0b10, "srl", IIAlu>;
1167
1168//
1169// Format: SUBU rz, rx, ry MIPS16e
1170// Purpose: Subtract Unsigned Word
1171// To subtract 32-bit integers
1172//
1173def SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIAlu>, ArithLogic16Defs<0>;
1174
1175//
1176// Format: SW ry, offset(rx) MIPS16e
1177// Purpose: Store Word (Extended)
1178// To store a word to memory.
1179//
1180def SwRxRyOffMemX16:
1181  FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, IIStore>, MayStore;
1182
1183//
1184// Format: SW rx, offset(sp) MIPS16e
1185// Purpose: Store Word rx (SP-Relative)
1186// To store an SP-relative word to memory.
1187//
1188def SwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b11010, "sw", IIStore>, MayStore;
1189
1190//
1191//
1192// Format: XOR rx, ry MIPS16e
1193// Purpose: Xor
1194// To do a bitwise logical XOR.
1195//
1196def XorRxRxRy16: FRxRxRy16_ins<0b01110, "xor", IIAlu>, ArithLogic16Defs<1>;
1197
1198class Mips16Pat<dag pattern, dag result> : Pat<pattern, result> {
1199  let Predicates = [InMips16Mode];
1200}
1201
1202// Unary Arith/Logic
1203//
1204class ArithLogicU_pat<PatFrag OpNode, Instruction I> :
1205  Mips16Pat<(OpNode CPU16Regs:$r),
1206            (I CPU16Regs:$r)>;
1207
1208def: ArithLogicU_pat<not, NotRxRy16>;
1209def: ArithLogicU_pat<ineg, NegRxRy16>;
1210
1211class ArithLogic16_pat<SDNode OpNode, Instruction I> :
1212  Mips16Pat<(OpNode CPU16Regs:$l, CPU16Regs:$r),
1213            (I CPU16Regs:$l, CPU16Regs:$r)>;
1214
1215def: ArithLogic16_pat<add, AdduRxRyRz16>;
1216def: ArithLogic16_pat<and, AndRxRxRy16>;
1217def: ArithLogic16_pat<mul, MultRxRyRz16>;
1218def: ArithLogic16_pat<or, OrRxRxRy16>;
1219def: ArithLogic16_pat<sub, SubuRxRyRz16>;
1220def: ArithLogic16_pat<xor, XorRxRxRy16>;
1221
1222// Arithmetic and logical instructions with 2 register operands.
1223
1224class ArithLogicI16_pat<SDNode OpNode, PatFrag imm_type, Instruction I> :
1225  Mips16Pat<(OpNode CPU16Regs:$in, imm_type:$imm),
1226            (I CPU16Regs:$in, imm_type:$imm)>;
1227
1228def: ArithLogicI16_pat<add, immSExt8, AddiuRxRxImm16>;
1229def: ArithLogicI16_pat<add, immSExt16, AddiuRxRxImmX16>;
1230def: ArithLogicI16_pat<shl, immZExt5, SllX16>;
1231def: ArithLogicI16_pat<srl, immZExt5, SrlX16>;
1232def: ArithLogicI16_pat<sra, immZExt5, SraX16>;
1233
1234class shift_rotate_reg16_pat<SDNode OpNode, Instruction I> :
1235  Mips16Pat<(OpNode CPU16Regs:$r, CPU16Regs:$ra),
1236            (I CPU16Regs:$r, CPU16Regs:$ra)>;
1237
1238def: shift_rotate_reg16_pat<shl, SllvRxRy16>;
1239def: shift_rotate_reg16_pat<sra, SravRxRy16>;
1240def: shift_rotate_reg16_pat<srl, SrlvRxRy16>;
1241
1242class LoadM16_pat<PatFrag OpNode, Instruction I> :
1243  Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>;
1244
1245def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>;
1246def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>;
1247def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16>;
1248def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>;
1249def: LoadM16_pat<load, LwRxRyOffMemX16>;
1250
1251class StoreM16_pat<PatFrag OpNode, Instruction I> :
1252  Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr),
1253            (I CPU16Regs:$r, addr16:$addr)>;
1254
1255def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>;
1256def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>;
1257def: StoreM16_pat<store, SwRxRyOffMemX16>;
1258
1259// Unconditional branch
1260class UncondBranch16_pat<SDNode OpNode, Instruction I>:
1261  Mips16Pat<(OpNode bb:$imm16), (I bb:$imm16)> {
1262    let Predicates = [InMips16Mode];
1263  }
1264
1265def : Mips16Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
1266                (Jal16 tglobaladdr:$dst)>;
1267
1268def : Mips16Pat<(MipsJmpLink (i32 texternalsym:$dst)),
1269                (Jal16 texternalsym:$dst)>;
1270
1271// Indirect branch
1272def: Mips16Pat<
1273  (brind CPU16Regs:$rs),
1274  (JrcRx16 CPU16Regs:$rs)>;
1275
1276// Jump and Link (Call)
1277let isCall=1, hasDelaySlot=0 in
1278def JumpLinkReg16:
1279  FRR16_JALRC<0, 0, 0, (outs), (ins CPU16Regs:$rs),
1280              "jalrc \t$rs", [(MipsJmpLink CPU16Regs:$rs)], IIBranch>;
1281
1282// Mips16 pseudos
1283let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1,
1284  hasExtraSrcRegAllocReq = 1 in
1285def RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>;
1286
1287
1288// setcc patterns
1289
1290class SetCC_R16<PatFrag cond_op, Instruction I>:
1291  Mips16Pat<(cond_op CPU16Regs:$rx, CPU16Regs:$ry),
1292            (I CPU16Regs:$rx, CPU16Regs:$ry)>;
1293
1294class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>:
1295  Mips16Pat<(cond_op CPU16Regs:$rx, imm_type:$imm16),
1296            (I CPU16Regs:$rx, imm_type:$imm16)>;
1297
1298
1299def: Mips16Pat<(i32  addr16:$addr),
1300               (AddiuRxRyOffMemX16  addr16:$addr)>;
1301
1302
1303// Large (>16 bit) immediate loads
1304def : Mips16Pat<(i32 imm:$imm),
1305                (OrRxRxRy16 (SllX16 (LiRxImmX16 (HI16 imm:$imm)), 16),
1306                (LiRxImmX16 (LO16 imm:$imm)))>;
1307
1308// Carry MipsPatterns
1309def : Mips16Pat<(subc CPU16Regs:$lhs, CPU16Regs:$rhs),
1310                (SubuRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>;
1311def : Mips16Pat<(addc CPU16Regs:$lhs, CPU16Regs:$rhs),
1312                (AdduRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>;
1313def : Mips16Pat<(addc  CPU16Regs:$src, immSExt16:$imm),
1314                (AddiuRxRxImmX16 CPU16Regs:$src, imm:$imm)>;
1315
1316//
1317// Some branch conditional patterns are not generated by llvm at this time.
1318// Some are for seemingly arbitrary reasons not used: i.e. with signed number
1319// comparison they are used and for unsigned a different pattern is used.
1320// I am pushing upstream from the full mips16 port and it seemed that I needed
1321// these earlier and the mips32 port has these but now I cannot create test
1322// cases that use these patterns. While I sort this all out I will leave these
1323// extra patterns commented out and if I can be sure they are really not used,
1324// I will delete the code. I don't want to check the code in uncommented without
1325// a valid test case. In some cases, the compiler is generating patterns with
1326// setcc instead and earlier I had implemented setcc first so may have masked
1327// the problem. The setcc variants are suboptimal for mips16 so I may wantto
1328// figure out how to enable the brcond patterns or else possibly new
1329// combinations of of brcond and setcc.
1330//
1331//
1332// bcond-seteq
1333//
1334def: Mips16Pat
1335  <(brcond (i32 (seteq CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1336   (BteqzT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1337  >;
1338
1339
1340def: Mips16Pat
1341  <(brcond (i32 (seteq CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16),
1342   (BteqzT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$targ16)
1343  >;
1344
1345def: Mips16Pat
1346  <(brcond (i32 (seteq CPU16Regs:$rx, 0)), bb:$targ16),
1347   (BeqzRxImmX16 CPU16Regs:$rx, bb:$targ16)
1348  >;
1349
1350//
1351// bcond-setgt (do we need to have this pair of setlt, setgt??)
1352//
1353def: Mips16Pat
1354  <(brcond (i32 (setgt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1355   (BtnezT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1356  >;
1357
1358//
1359// bcond-setge
1360//
1361def: Mips16Pat
1362  <(brcond (i32 (setge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1363   (BteqzT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1364  >;
1365
1366//
1367// never called because compiler transforms a >= k to a > (k-1)
1368def: Mips16Pat
1369  <(brcond (i32 (setge CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16),
1370   (BteqzT8SltiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$imm16)
1371  >;
1372
1373//
1374// bcond-setlt
1375//
1376def: Mips16Pat
1377  <(brcond (i32 (setlt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1378   (BtnezT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1379  >;
1380
1381def: Mips16Pat
1382  <(brcond (i32 (setlt CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16),
1383   (BtnezT8SltiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$imm16)
1384  >;
1385
1386//
1387// bcond-setle
1388//
1389def: Mips16Pat
1390  <(brcond (i32 (setle CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1391   (BteqzT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1392  >;
1393
1394//
1395// bcond-setne
1396//
1397def: Mips16Pat
1398  <(brcond (i32 (setne CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1399   (BtnezT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1400  >;
1401
1402def: Mips16Pat
1403  <(brcond (i32 (setne CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16),
1404   (BtnezT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$targ16)
1405  >;
1406
1407def: Mips16Pat
1408  <(brcond (i32 (setne CPU16Regs:$rx, 0)), bb:$targ16),
1409   (BnezRxImmX16 CPU16Regs:$rx, bb:$targ16)
1410  >;
1411
1412//
1413// This needs to be there but I forget which code will generate it
1414//
1415def: Mips16Pat
1416  <(brcond CPU16Regs:$rx, bb:$targ16),
1417   (BnezRxImmX16 CPU16Regs:$rx, bb:$targ16)
1418  >;
1419
1420//
1421
1422//
1423// bcond-setugt
1424//
1425//def: Mips16Pat
1426//  <(brcond (i32 (setugt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1427//   (BtnezT8SltuX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1428//  >;
1429
1430//
1431// bcond-setuge
1432//
1433//def: Mips16Pat
1434//  <(brcond (i32 (setuge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1435//   (BteqzT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1436//  >;
1437
1438
1439//
1440// bcond-setult
1441//
1442//def: Mips16Pat
1443//  <(brcond (i32 (setult CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1444//   (BtnezT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1445//  >;
1446
1447def: UncondBranch16_pat<br, BimmX16>;
1448
1449// Small immediates
1450def: Mips16Pat<(i32 immSExt16:$in),
1451               (AddiuRxRxImmX16 (Move32R16 ZERO), immSExt16:$in)>;
1452
1453def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
1454
1455//
1456// MipsDivRem
1457//
1458def: Mips16Pat
1459  <(MipsDivRem CPU16Regs:$rx, CPU16Regs:$ry),
1460   (DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
1461
1462//
1463// MipsDivRemU
1464//
1465def: Mips16Pat
1466  <(MipsDivRemU CPU16Regs:$rx, CPU16Regs:$ry),
1467   (DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
1468
1469//  signed a,b
1470//  x = (a>=b)?x:y
1471//
1472//  if !(a < b) x = y
1473//
1474def : Mips16Pat<(select (i32 (setge CPU16Regs:$a, CPU16Regs:$b)),
1475                 CPU16Regs:$x, CPU16Regs:$y),
1476                (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y,
1477                 CPU16Regs:$a, CPU16Regs:$b)>;
1478
1479//  signed a,b
1480//  x = (a>b)?x:y
1481//
1482//  if  (b < a) x = y
1483//
1484def : Mips16Pat<(select (i32 (setgt CPU16Regs:$a, CPU16Regs:$b)),
1485                 CPU16Regs:$x, CPU16Regs:$y),
1486                (SelTBtneZSlt CPU16Regs:$x, CPU16Regs:$y,
1487                 CPU16Regs:$b, CPU16Regs:$a)>;
1488
1489// unsigned a,b
1490// x = (a>=b)?x:y
1491//
1492// if !(a < b) x = y;
1493//
1494def : Mips16Pat<
1495  (select (i32 (setuge CPU16Regs:$a, CPU16Regs:$b)),
1496   CPU16Regs:$x, CPU16Regs:$y),
1497  (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y,
1498   CPU16Regs:$a, CPU16Regs:$b)>;
1499
1500//  unsigned a,b
1501//  x = (a>b)?x:y
1502//
1503//  if (b < a) x = y
1504//
1505def : Mips16Pat<(select (i32 (setugt CPU16Regs:$a, CPU16Regs:$b)),
1506                 CPU16Regs:$x, CPU16Regs:$y),
1507                (SelTBtneZSltu CPU16Regs:$x, CPU16Regs:$y,
1508                 CPU16Regs:$b, CPU16Regs:$a)>;
1509
1510// signed
1511// x = (a >= k)?x:y
1512// due to an llvm optimization, i don't think that this will ever
1513// be used. This is transformed into x = (a > k-1)?x:y
1514//
1515//
1516
1517//def : Mips16Pat<
1518//  (select (i32 (setge CPU16Regs:$lhs, immSExt16:$rhs)),
1519//   CPU16Regs:$T, CPU16Regs:$F),
1520//  (SelTBteqZSlti CPU16Regs:$T, CPU16Regs:$F,
1521//   CPU16Regs:$lhs, immSExt16:$rhs)>;
1522
1523//def : Mips16Pat<
1524//  (select (i32 (setuge CPU16Regs:$lhs, immSExt16:$rhs)),
1525//   CPU16Regs:$T, CPU16Regs:$F),
1526//  (SelTBteqZSltiu CPU16Regs:$T, CPU16Regs:$F,
1527//   CPU16Regs:$lhs, immSExt16:$rhs)>;
1528
1529// signed
1530// x = (a < k)?x:y
1531//
1532// if !(a < k) x = y;
1533//
1534def : Mips16Pat<
1535  (select (i32 (setlt CPU16Regs:$a, immSExt16:$b)),
1536   CPU16Regs:$x, CPU16Regs:$y),
1537  (SelTBtneZSlti CPU16Regs:$x, CPU16Regs:$y,
1538   CPU16Regs:$a, immSExt16:$b)>;
1539
1540
1541//
1542//
1543// signed
1544// x = (a <= b)? x : y
1545//
1546// if  (b < a) x = y
1547//
1548def : Mips16Pat<(select (i32 (setle CPU16Regs:$a, CPU16Regs:$b)),
1549                 CPU16Regs:$x, CPU16Regs:$y),
1550                (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y,
1551                 CPU16Regs:$b, CPU16Regs:$a)>;
1552
1553//
1554// unnsigned
1555// x = (a <= b)? x : y
1556//
1557// if  (b < a) x = y
1558//
1559def : Mips16Pat<(select (i32 (setule CPU16Regs:$a, CPU16Regs:$b)),
1560                 CPU16Regs:$x, CPU16Regs:$y),
1561                (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y,
1562                 CPU16Regs:$b, CPU16Regs:$a)>;
1563
1564//
1565// signed/unsigned
1566// x = (a == b)? x : y
1567//
1568// if (a != b) x = y
1569//
1570def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, CPU16Regs:$b)),
1571                 CPU16Regs:$x, CPU16Regs:$y),
1572                (SelTBteqZCmp CPU16Regs:$x, CPU16Regs:$y,
1573                 CPU16Regs:$b, CPU16Regs:$a)>;
1574
1575//
1576// signed/unsigned
1577// x = (a == 0)? x : y
1578//
1579// if (a != 0) x = y
1580//
1581def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, 0)),
1582                 CPU16Regs:$x, CPU16Regs:$y),
1583                (SelBeqZ CPU16Regs:$x, CPU16Regs:$y,
1584                 CPU16Regs:$a)>;
1585
1586
1587//
1588// signed/unsigned
1589// x = (a == k)? x : y
1590//
1591// if (a != k) x = y
1592//
1593def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, immZExt16:$k)),
1594                 CPU16Regs:$x, CPU16Regs:$y),
1595                (SelTBteqZCmpi CPU16Regs:$x, CPU16Regs:$y,
1596                 CPU16Regs:$a, immZExt16:$k)>;
1597
1598
1599//
1600// signed/unsigned
1601// x = (a != b)? x : y
1602//
1603// if (a == b) x = y
1604//
1605//
1606def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, CPU16Regs:$b)),
1607                 CPU16Regs:$x, CPU16Regs:$y),
1608                (SelTBtneZCmp CPU16Regs:$x, CPU16Regs:$y,
1609                 CPU16Regs:$b, CPU16Regs:$a)>;
1610
1611//
1612// signed/unsigned
1613// x = (a != 0)? x : y
1614//
1615// if (a == 0) x = y
1616//
1617def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, 0)),
1618                 CPU16Regs:$x, CPU16Regs:$y),
1619                (SelBneZ CPU16Regs:$x, CPU16Regs:$y,
1620                 CPU16Regs:$a)>;
1621
1622// signed/unsigned
1623// x = (a)? x : y
1624//
1625// if (!a) x = y
1626//
1627def : Mips16Pat<(select  CPU16Regs:$a,
1628                 CPU16Regs:$x, CPU16Regs:$y),
1629      (SelBneZ CPU16Regs:$x, CPU16Regs:$y,
1630       CPU16Regs:$a)>;
1631
1632
1633//
1634// signed/unsigned
1635// x = (a != k)? x : y
1636//
1637// if (a == k) x = y
1638//
1639def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, immZExt16:$k)),
1640                 CPU16Regs:$x, CPU16Regs:$y),
1641                (SelTBtneZCmpi CPU16Regs:$x, CPU16Regs:$y,
1642                 CPU16Regs:$a, immZExt16:$k)>;
1643
1644//
1645// When writing C code to test setxx these patterns,
1646// some will be transformed into
1647// other things. So we test using C code but using -O3 and -O0
1648//
1649// seteq
1650//
1651def : Mips16Pat
1652  <(seteq CPU16Regs:$lhs,CPU16Regs:$rhs),
1653   (SltiuCCRxImmX16 (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs), 1)>;
1654
1655def : Mips16Pat
1656  <(seteq CPU16Regs:$lhs, 0),
1657   (SltiuCCRxImmX16 CPU16Regs:$lhs, 1)>;
1658
1659
1660//
1661// setge
1662//
1663
1664def: Mips16Pat
1665  <(setge CPU16Regs:$lhs, CPU16Regs:$rhs),
1666   (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs),
1667   (LiRxImmX16 1))>;
1668
1669//
1670// For constants, llvm transforms this to:
1671// x > (k -1) and then reverses the operands to use setlt. So this pattern
1672// is not used now by the compiler. (Presumably checking that k-1 does not
1673// overflow). The compiler never uses this at a the current time, due to
1674// other optimizations.
1675//
1676//def: Mips16Pat
1677//  <(setge CPU16Regs:$lhs, immSExt16:$rhs),
1678//   (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, immSExt16:$rhs),
1679//   (LiRxImmX16 1))>;
1680
1681// This catches the x >= -32768 case by transforming it to  x > -32769
1682//
1683def: Mips16Pat
1684  <(setgt CPU16Regs:$lhs, -32769),
1685   (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, -32768),
1686   (LiRxImmX16 1))>;
1687
1688//
1689// setgt
1690//
1691//
1692
1693def: Mips16Pat
1694  <(setgt CPU16Regs:$lhs, CPU16Regs:$rhs),
1695   (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>;
1696
1697//
1698// setle
1699//
1700def: Mips16Pat
1701  <(setle CPU16Regs:$lhs, CPU16Regs:$rhs),
1702   (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImm16 1))>;
1703
1704//
1705// setlt
1706//
1707def: SetCC_R16<setlt, SltCCRxRy16>;
1708
1709def: SetCC_I16<setlt, immSExt16, SltiCCRxImmX16>;
1710
1711//
1712// setne
1713//
1714def : Mips16Pat
1715  <(setne CPU16Regs:$lhs,CPU16Regs:$rhs),
1716   (SltuCCRxRy16 (LiRxImmX16 0),
1717   (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs))>;
1718
1719
1720//
1721// setuge
1722//
1723def: Mips16Pat
1724  <(setuge CPU16Regs:$lhs, CPU16Regs:$rhs),
1725   (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs),
1726   (LiRxImmX16 1))>;
1727
1728// this pattern will never be used because the compiler will transform
1729// x >= k to x > (k - 1) and then use SLT
1730//
1731//def: Mips16Pat
1732//  <(setuge CPU16Regs:$lhs, immZExt16:$rhs),
1733//   (XorRxRxRy16 (SltiuCCRxImmX16 CPU16Regs:$lhs, immZExt16:$rhs),
1734//   (LiRxImmX16 1))>;
1735
1736//
1737// setugt
1738//
1739def: Mips16Pat
1740  <(setugt CPU16Regs:$lhs, CPU16Regs:$rhs),
1741   (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>;
1742
1743//
1744// setule
1745//
1746def: Mips16Pat
1747  <(setule CPU16Regs:$lhs, CPU16Regs:$rhs),
1748   (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImmX16 1))>;
1749
1750//
1751// setult
1752//
1753def: SetCC_R16<setult, SltuCCRxRy16>;
1754
1755def: SetCC_I16<setult, immSExt16, SltiuCCRxImmX16>;
1756
1757def: Mips16Pat<(add CPU16Regs:$hi, (MipsLo tglobaladdr:$lo)),
1758               (AddiuRxRxImmX16 CPU16Regs:$hi, tglobaladdr:$lo)>;
1759
1760// hi/lo relocs
1761
1762def : Mips16Pat<(MipsHi tglobaladdr:$in),
1763                (SllX16 (LiRxImmX16 tglobaladdr:$in), 16)>;
1764def : Mips16Pat<(MipsHi tjumptable:$in),
1765                (SllX16 (LiRxImmX16 tjumptable:$in), 16)>;
1766def : Mips16Pat<(MipsHi tglobaltlsaddr:$in),
1767                (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>;
1768
1769// wrapper_pic
1770class Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
1771  Mips16Pat<(MipsWrapper RC:$gp, node:$in),
1772            (ADDiuOp RC:$gp, node:$in)>;
1773
1774
1775def : Wrapper16Pat<tglobaladdr, AddiuRxRxImmX16, CPU16Regs>;
1776def : Wrapper16Pat<tglobaltlsaddr, AddiuRxRxImmX16, CPU16Regs>;
1777
1778def : Mips16Pat<(i32 (extloadi8   addr16:$src)),
1779                (LbuRxRyOffMemX16  addr16:$src)>;
1780def : Mips16Pat<(i32 (extloadi16  addr16:$src)),
1781                (LhuRxRyOffMemX16  addr16:$src)>;
1782