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