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