1239310Sdim//===- Mips16InstrInfo.td - Target Description for Mips16  -*- tablegen -*-=//
2239310Sdim//
3239310Sdim//                     The LLVM Compiler Infrastructure
4239310Sdim//
5239310Sdim// This file is distributed under the University of Illinois Open Source
6239310Sdim// License. See LICENSE.TXT for details.
7239310Sdim//
8239310Sdim//===----------------------------------------------------------------------===//
9239310Sdim//
10239310Sdim// This file describes Mips16 instructions.
11239310Sdim//
12239310Sdim//===----------------------------------------------------------------------===//
13243830Sdim//
14243830Sdim//
15243830Sdim// Mips Address
16243830Sdim//
17243830Sdimdef addr16 :
18249423Sdim  ComplexPattern<iPTR, 3, "selectAddr16", [frameindex], [SDNPWantParent]>;
19239310Sdim
20239310Sdim//
21243830Sdim// Address operand
22243830Sdimdef mem16 : Operand<i32> {
23243830Sdim  let PrintMethod = "printMemOperand";
24263508Sdim  let MIOperandInfo = (ops CPU16Regs, simm16, CPU16RegsPlusSP);
25243830Sdim  let EncoderMethod = "getMemEncoding";
26243830Sdim}
27243830Sdim
28243830Sdimdef mem16_ea : Operand<i32> {
29243830Sdim  let PrintMethod = "printMemOperandEA";
30263508Sdim  let MIOperandInfo = (ops CPU16RegsPlusSP, simm16);
31243830Sdim  let EncoderMethod = "getMemEncoding";
32243830Sdim}
33243830Sdim
34239310Sdim//
35263508Sdim// I-type instruction format
36249423Sdim//
37263508Sdim// this is only used by bimm. the actual assembly value is a 12 bit signed
38263508Sdim// number
39263508Sdim//
40263508Sdimclass FI16_ins<bits<5> op, string asmstr, InstrItinClass itin>:
41263508Sdim  FI16<op, (outs), (ins brtarget:$imm16),
42263508Sdim            !strconcat(asmstr, "\t$imm16 # 16 bit inst"), [], itin>;
43263508Sdim
44263508Sdim//
45263508Sdim//
46249423Sdim// I8 instruction format
47249423Sdim//
48249423Sdim
49249423Sdimclass FI816_ins_base<bits<3> _func, string asmstr,
50249423Sdim                     string asmstr2, InstrItinClass itin>:
51249423Sdim  FI816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2),
52249423Sdim        [], itin>;
53249423Sdim
54263508Sdimclass FI816_ins<bits<3> _func, string asmstr,
55263508Sdim                InstrItinClass itin>:
56263508Sdim  FI816_ins_base<_func, asmstr, "\t$imm  # 16 bit inst", itin>;
57263508Sdim 
58249423Sdimclass FI816_SP_ins<bits<3> _func, string asmstr,
59249423Sdim                   InstrItinClass itin>:
60249423Sdim  FI816_ins_base<_func, asmstr, "\t$$sp, $imm # 16 bit inst", itin>;
61249423Sdim
62249423Sdim//
63249423Sdim// RI instruction format
64249423Sdim//
65249423Sdim
66249423Sdim
67249423Sdimclass FRI16_ins_base<bits<5> op, string asmstr, string asmstr2,
68249423Sdim                     InstrItinClass itin>:
69249423Sdim  FRI16<op, (outs CPU16Regs:$rx), (ins simm16:$imm),
70249423Sdim        !strconcat(asmstr, asmstr2), [], itin>;
71249423Sdim
72249423Sdimclass FRI16_ins<bits<5> op, string asmstr,
73249423Sdim                InstrItinClass itin>:
74249423Sdim  FRI16_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;
75249423Sdim
76263508Sdimclass FRI16_TCP_ins<bits<5> _op, string asmstr,
77263508Sdim                    InstrItinClass itin>:
78263508Sdim  FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),
79263508Sdim            !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>;
80263508Sdim            
81249423Sdimclass FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2,
82249423Sdim                     InstrItinClass itin>:
83249423Sdim  FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm),
84249423Sdim        !strconcat(asmstr, asmstr2), [], itin>;
85249423Sdim
86249423Sdimclass FRI16R_ins<bits<5> op, string asmstr,
87249423Sdim                InstrItinClass itin>:
88249423Sdim  FRI16R_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>;
89249423Sdim
90249423Sdimclass F2RI16_ins<bits<5> _op, string asmstr,
91249423Sdim                     InstrItinClass itin>:
92249423Sdim  FRI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm),
93249423Sdim        !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin> {
94249423Sdim  let Constraints = "$rx_ = $rx";
95249423Sdim}
96249423Sdim
97249423Sdimclass FRI16_B_ins<bits<5> _op, string asmstr,
98249423Sdim                  InstrItinClass itin>:
99249423Sdim  FRI16<_op, (outs), (ins  CPU16Regs:$rx, brtarget:$imm),
100249423Sdim        !strconcat(asmstr, "\t$rx, $imm  # 16 bit inst"), [], itin>;
101249423Sdim//
102243830Sdim// Compare a register and immediate and place result in CC
103243830Sdim// Implicit use of T8
104243830Sdim//
105243830Sdim// EXT-CCRR Instruction format
106243830Sdim//
107249423Sdimclass FEXT_CCRXI16_ins<string asmstr>:
108249423Sdim  MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, simm16:$imm),
109249423Sdim               !strconcat(asmstr, "\t$rx, $imm\n\tmove\t$cc, $$t8"), []> {
110243830Sdim  let isCodeGenOnly=1;
111249423Sdim  let usesCustomInserter = 1;
112243830Sdim}
113239310Sdim
114249423Sdim// JAL and JALX instruction format
115243830Sdim//
116249423Sdimclass FJAL16_ins<bits<1> _X, string asmstr,
117249423Sdim                 InstrItinClass itin>:
118249423Sdim  FJAL16<_X, (outs), (ins simm20:$imm),
119249423Sdim         !strconcat(asmstr, "\t$imm\n\tnop"),[],
120249423Sdim         itin>  {
121249423Sdim  let isCodeGenOnly=1;
122249423Sdim}
123249423Sdim//
124243830Sdim// EXT-I instruction format
125243830Sdim//
126243830Sdimclass FEXT_I16_ins<bits<5> eop, string asmstr, InstrItinClass itin> :
127243830Sdim  FEXT_I16<eop, (outs), (ins brtarget:$imm16),
128243830Sdim           !strconcat(asmstr, "\t$imm16"),[], itin>;
129239310Sdim
130239310Sdim//
131243830Sdim// EXT-I8 instruction format
132239310Sdim//
133239310Sdim
134243830Sdimclass FEXT_I816_ins_base<bits<3> _func, string asmstr,
135243830Sdim                         string asmstr2, InstrItinClass itin>:
136249423Sdim  FEXT_I816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2),
137243830Sdim            [], itin>;
138243830Sdim
139243830Sdimclass FEXT_I816_ins<bits<3> _func, string asmstr,
140243830Sdim                    InstrItinClass itin>:
141243830Sdim  FEXT_I816_ins_base<_func, asmstr, "\t$imm", itin>;
142243830Sdim
143249423Sdimclass FEXT_I816_SP_ins<bits<3> _func, string asmstr,
144249423Sdim                       InstrItinClass itin>:
145249423Sdim      FEXT_I816_ins_base<_func, asmstr, "\t$$sp, $imm", itin>;
146249423Sdim
147239310Sdim//
148243830Sdim// Assembler formats in alphabetical order.
149243830Sdim// Natural and pseudos are mixed together.
150243830Sdim//
151243830Sdim// Compare two registers and place result in CC
152243830Sdim// Implicit use of T8
153243830Sdim//
154243830Sdim// CC-RR Instruction format
155243830Sdim//
156249423Sdimclass FCCRR16_ins<string asmstr> :
157249423Sdim  MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, CPU16Regs:$ry),
158249423Sdim               !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$cc, $$t8"), []> {
159243830Sdim  let isCodeGenOnly=1;
160249423Sdim  let usesCustomInserter = 1;
161243830Sdim}
162243830Sdim
163243830Sdim//
164239310Sdim// EXT-RI instruction format
165239310Sdim//
166239310Sdim
167239310Sdimclass FEXT_RI16_ins_base<bits<5> _op, string asmstr, string asmstr2,
168239310Sdim                         InstrItinClass itin>:
169239310Sdim  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins simm16:$imm),
170239310Sdim                  !strconcat(asmstr, asmstr2), [], itin>;
171239310Sdim
172239310Sdimclass FEXT_RI16_ins<bits<5> _op, string asmstr,
173239310Sdim                    InstrItinClass itin>:
174239310Sdim  FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $imm", itin>;
175239310Sdim
176249423Sdimclass FEXT_RI16R_ins_base<bits<5> _op, string asmstr, string asmstr2,
177249423Sdim                         InstrItinClass itin>:
178249423Sdim  FEXT_RI16<_op, (outs ), (ins CPU16Regs:$rx, simm16:$imm),
179249423Sdim                  !strconcat(asmstr, asmstr2), [], itin>;
180249423Sdim
181249423Sdimclass FEXT_RI16R_ins<bits<5> _op, string asmstr,
182249423Sdim                    InstrItinClass itin>:
183249423Sdim  FEXT_RI16R_ins_base<_op, asmstr, "\t$rx, $imm", itin>;
184249423Sdim
185239310Sdimclass FEXT_RI16_PC_ins<bits<5> _op, string asmstr, InstrItinClass itin>:
186239310Sdim  FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $$pc, $imm", itin>;
187239310Sdim
188243830Sdimclass FEXT_RI16_B_ins<bits<5> _op, string asmstr,
189243830Sdim                      InstrItinClass itin>:
190243830Sdim  FEXT_RI16<_op, (outs), (ins  CPU16Regs:$rx, brtarget:$imm),
191243830Sdim            !strconcat(asmstr, "\t$rx, $imm"), [], itin>;
192239310Sdim
193263508Sdimclass FEXT_RI16_TCP_ins<bits<5> _op, string asmstr,
194263508Sdim                        InstrItinClass itin>:
195263508Sdim  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size),
196263508Sdim            !strconcat(asmstr, "\t$rx, $imm"), [], itin>;
197263508Sdim
198239310Sdimclass FEXT_2RI16_ins<bits<5> _op, string asmstr,
199239310Sdim                     InstrItinClass itin>:
200239310Sdim  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm),
201239310Sdim            !strconcat(asmstr, "\t$rx, $imm"), [], itin> {
202239310Sdim  let Constraints = "$rx_ = $rx";
203239310Sdim}
204239310Sdim
205239310Sdim
206243830Sdim// this has an explicit sp argument that we ignore to work around a problem
207243830Sdim// in the compiler
208243830Sdimclass FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr,
209243830Sdim                                InstrItinClass itin>:
210243830Sdim  FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm),
211243830Sdim            !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
212243830Sdim
213263508Sdimclass FEXT_RI16_SP_Store_explicit_ins<bits<5> _op, string asmstr,
214263508Sdim                                InstrItinClass itin>:
215263508Sdim  FEXT_RI16<_op, (outs), (ins  CPU16Regs:$rx, CPUSPReg:$ry, simm16:$imm),
216263508Sdim            !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
217263508Sdim
218239310Sdim//
219243830Sdim// EXT-RRI instruction format
220243830Sdim//
221243830Sdim
222243830Sdimclass FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd,
223243830Sdim                         InstrItinClass itin>:
224243830Sdim  FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins  MemOpnd:$addr),
225243830Sdim             !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
226243830Sdim
227243830Sdimclass FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, Operand MemOpnd,
228243830Sdim                          InstrItinClass itin>:
229243830Sdim  FEXT_RRI16<op, (outs ), (ins  CPU16Regs:$ry, MemOpnd:$addr),
230243830Sdim             !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
231243830Sdim
232243830Sdim//
233243830Sdim//
234243830Sdim// EXT-RRI-A instruction format
235243830Sdim//
236243830Sdim
237243830Sdimclass FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, Operand MemOpnd,
238243830Sdim                           InstrItinClass itin>:
239243830Sdim  FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins  MemOpnd:$addr),
240243830Sdim               !strconcat(asmstr, "\t$ry, $addr"), [], itin>;
241243830Sdim
242243830Sdim//
243243830Sdim// EXT-SHIFT instruction format
244243830Sdim//
245243830Sdimclass FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>:
246263508Sdim  FEXT_SHIFT16<_f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry, uimm5:$sa),
247243830Sdim               !strconcat(asmstr, "\t$rx, $ry, $sa"), [], itin>;
248243830Sdim
249243830Sdim//
250243830Sdim// EXT-T8I8
251243830Sdim//
252249423Sdimclass FEXT_T8I816_ins<string asmstr, string asmstr2>:
253249423Sdim  MipsPseudo16<(outs),
254249423Sdim               (ins CPU16Regs:$rx, CPU16Regs:$ry, brtarget:$imm),
255249423Sdim               !strconcat(asmstr2, !strconcat("\t$rx, $ry\n\t",
256249423Sdim               !strconcat(asmstr, "\t$imm"))),[]> {
257243830Sdim  let isCodeGenOnly=1;
258249423Sdim  let usesCustomInserter = 1;
259243830Sdim}
260243830Sdim
261243830Sdim//
262243830Sdim// EXT-T8I8I
263243830Sdim//
264249423Sdimclass FEXT_T8I8I16_ins<string asmstr, string asmstr2>:
265249423Sdim  MipsPseudo16<(outs),
266249423Sdim               (ins CPU16Regs:$rx, simm16:$imm, brtarget:$targ),
267249423Sdim               !strconcat(asmstr2, !strconcat("\t$rx, $imm\n\t",
268249423Sdim               !strconcat(asmstr, "\t$targ"))), []> {
269243830Sdim  let isCodeGenOnly=1;
270249423Sdim  let usesCustomInserter = 1;
271243830Sdim}
272243830Sdim//
273243830Sdim
274243830Sdim
275243830Sdim//
276243830Sdim// I8_MOVR32 instruction format (used only by the MOVR32 instructio
277243830Sdim//
278243830Sdimclass FI8_MOVR3216_ins<string asmstr, InstrItinClass itin>:
279263508Sdim       FI8_MOVR3216<(outs CPU16Regs:$rz), (ins GPR32:$r32),
280243830Sdim       !strconcat(asmstr,  "\t$rz, $r32"), [], itin>;
281243830Sdim
282243830Sdim//
283243830Sdim// I8_MOV32R instruction format (used only by MOV32R instruction)
284243830Sdim//
285243830Sdim
286243830Sdimclass FI8_MOV32R16_ins<string asmstr, InstrItinClass itin>:
287263508Sdim  FI8_MOV32R16<(outs GPR32:$r32), (ins CPU16Regs:$rz),
288243830Sdim               !strconcat(asmstr,  "\t$r32, $rz"), [], itin>;
289243830Sdim
290243830Sdim//
291243830Sdim// This are pseudo formats for multiply
292243830Sdim// This first one can be changed to non pseudo now.
293243830Sdim//
294243830Sdim// MULT
295243830Sdim//
296243830Sdimclass FMULT16_ins<string asmstr, InstrItinClass itin> :
297243830Sdim  MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry),
298243830Sdim               !strconcat(asmstr, "\t$rx, $ry"), []>;
299243830Sdim
300243830Sdim//
301243830Sdim// MULT-LO
302243830Sdim//
303243830Sdimclass FMULT16_LO_ins<string asmstr, InstrItinClass itin> :
304243830Sdim  MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
305243830Sdim               !strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> {
306243830Sdim  let isCodeGenOnly=1;
307243830Sdim}
308243830Sdim
309243830Sdim//
310239310Sdim// RR-type instruction format
311239310Sdim//
312239310Sdim
313239310Sdimclass FRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> :
314239310Sdim  FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
315239310Sdim        !strconcat(asmstr, "\t$rx, $ry"), [], itin> {
316239310Sdim}
317239310Sdim
318263508Sdimclass FRRBreakNull16_ins<string asmstr, InstrItinClass itin> :
319263508Sdim  FRRBreak16<(outs), (ins), asmstr, [], itin> {
320263508Sdim  let Code=0;
321263508Sdim}
322263508Sdim
323249423Sdimclass FRR16R_ins<bits<5> f, string asmstr, InstrItinClass itin> :
324249423Sdim  FRR16<f, (outs), (ins  CPU16Regs:$rx, CPU16Regs:$ry),
325249423Sdim        !strconcat(asmstr, "\t$rx, $ry"), [], itin> {
326249423Sdim}
327243830Sdim
328249423Sdimclass FRRTR16_ins<string asmstr> :
329249423Sdim  MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
330249423Sdim               !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$rz, $$t8"), []> ;
331249423Sdim
332243830Sdim//
333243830Sdim// maybe refactor but need a $zero as a dummy first parameter
334243830Sdim//
335243830Sdimclass FRR16_div_ins<bits<5> f, string asmstr, InstrItinClass itin> :
336243830Sdim  FRR16<f, (outs ), (ins CPU16Regs:$rx, CPU16Regs:$ry),
337243830Sdim        !strconcat(asmstr, "\t$$zero, $rx, $ry"), [], itin> ;
338243830Sdim
339243830Sdimclass FUnaryRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> :
340243830Sdim  FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
341243830Sdim        !strconcat(asmstr, "\t$rx, $ry"), [], itin> ;
342243830Sdim
343243830Sdim
344243830Sdimclass FRR16_M_ins<bits<5> f, string asmstr,
345243830Sdim                  InstrItinClass itin> :
346243830Sdim  FRR16<f, (outs CPU16Regs:$rx), (ins),
347243830Sdim        !strconcat(asmstr, "\t$rx"), [], itin>;
348243830Sdim
349239310Sdimclass FRxRxRy16_ins<bits<5> f, string asmstr,
350239310Sdim                    InstrItinClass itin> :
351239310Sdim  FRR16<f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
352239310Sdim            !strconcat(asmstr, "\t$rz, $ry"),
353239310Sdim            [], itin> {
354239310Sdim  let Constraints = "$rx = $rz";
355239310Sdim}
356239310Sdim
357239310Sdimlet rx=0 in
358239310Sdimclass FRR16_JALRC_RA_only_ins<bits<1> nd_, bits<1> l_,
359239310Sdim                              string asmstr, InstrItinClass itin>:
360239310Sdim  FRR16_JALRC<nd_, l_, 1, (outs), (ins), !strconcat(asmstr, "\t $$ra"),
361239310Sdim              [], itin> ;
362239310Sdim
363243830Sdim
364243830Sdimclass FRR16_JALRC_ins<bits<1> nd, bits<1> l, bits<1> ra,
365243830Sdim                      string asmstr, InstrItinClass itin>:
366249423Sdim  FRR16_JALRC<nd, l, ra, (outs), (ins CPU16Regs:$rx),
367243830Sdim              !strconcat(asmstr, "\t $rx"), [], itin> ;
368243830Sdim
369263508Sdimclass FRR_SF16_ins
370263508Sdim  <bits<5> _funct, bits<3> _subfunc,
371263508Sdim    string asmstr, InstrItinClass itin>:
372263508Sdim  FRR_SF16<_funct, _subfunc, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_),
373263508Sdim           !strconcat(asmstr, "\t $rx"),
374263508Sdim           [], itin> {
375263508Sdim  let Constraints = "$rx_ = $rx";
376263508Sdim  }
377239310Sdim//
378243830Sdim// RRR-type instruction format
379239310Sdim//
380239310Sdim
381243830Sdimclass FRRR16_ins<bits<2> _f, string asmstr,  InstrItinClass itin> :
382243830Sdim  FRRR16<_f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
383243830Sdim         !strconcat(asmstr, "\t$rz, $rx, $ry"), [], itin>;
384239310Sdim
385243830Sdim//
386243830Sdim// These Sel patterns support the generation of conditional move
387243830Sdim// pseudo instructions.
388243830Sdim//
389243830Sdim// The nomenclature uses the components making up the pseudo and may
390243830Sdim// be a bit counter intuitive when compared with the end result we seek.
391243830Sdim// For example using a bqez in the example directly below results in the
392243830Sdim// conditional move being done if the tested register is not zero.
393243830Sdim// I considered in easier to check by keeping the pseudo consistent with
394243830Sdim// it's components but it could have been done differently.
395243830Sdim//
396243830Sdim// The simplest case is when can test and operand directly and do the
397243830Sdim// conditional move based on a simple mips16 conditional
398243830Sdim//  branch instruction.
399243830Sdim// for example:
400243830Sdim// if $op == beqz or bnez:
401243830Sdim//
402243830Sdim// $op1 $rt, .+4
403243830Sdim// move $rd, $rs
404243830Sdim//
405243830Sdim// if $op == beqz, then if $rt != 0, then the conditional assignment
406243830Sdim// $rd = $rs is done.
407239310Sdim
408243830Sdim// if $op == bnez, then if $rt == 0, then the conditional assignment
409243830Sdim// $rd = $rs is done.
410239310Sdim//
411243830Sdim// So this pseudo class only has one operand, i.e. op
412239310Sdim//
413249423Sdimclass Sel<string op>:
414249423Sdim  MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs,
415249423Sdim               CPU16Regs:$rt),
416249423Sdim               !strconcat(op, "\t$rt, .+4\n\t\n\tmove $rd, $rs"), []> {
417249423Sdim  //let isCodeGenOnly=1;
418243830Sdim  let Constraints = "$rd = $rd_";
419249423Sdim  let usesCustomInserter = 1;
420243830Sdim}
421239310Sdim
422239310Sdim//
423243830Sdim// The next two instruction classes allow for an operand which tests
424243830Sdim// two operands and returns a value in register T8 and
425243830Sdim//then does a conditional branch based on the value of T8
426243830Sdim//
427243830Sdim
428243830Sdim// op2 can be cmpi or slti/sltiu
429243830Sdim// op1 can bteqz or btnez
430243830Sdim// the operands for op2 are a register and a signed constant
431243830Sdim//
432243830Sdim// $op2 $t, $imm  ;test register t and branch conditionally
433243830Sdim// $op1 .+4       ;op1 is a conditional branch
434243830Sdim// move $rd, $rs
435243830Sdim//
436243830Sdim//
437249423Sdimclass SeliT<string op1, string op2>:
438249423Sdim  MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs,
439249423Sdim                                       CPU16Regs:$rl, simm16:$imm),
440249423Sdim               !strconcat(op2,
441249423Sdim               !strconcat("\t$rl, $imm\n\t",
442249423Sdim               !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> {
443243830Sdim  let isCodeGenOnly=1;
444243830Sdim  let Constraints = "$rd = $rd_";
445249423Sdim  let usesCustomInserter = 1;
446239310Sdim}
447239310Sdim
448239310Sdim//
449243830Sdim// op2 can be cmp or slt/sltu
450243830Sdim// op1 can be bteqz or btnez
451243830Sdim// the operands for op2 are two registers
452243830Sdim// op1 is a conditional branch
453243830Sdim//
454243830Sdim//
455243830Sdim// $op2 $rl, $rr  ;test registers rl,rr
456243830Sdim// $op1 .+4       ;op2 is a conditional branch
457243830Sdim// move $rd, $rs
458243830Sdim//
459243830Sdim//
460249423Sdimclass SelT<string op1, string op2>:
461249423Sdim  MipsPseudo16<(outs CPU16Regs:$rd_),
462249423Sdim               (ins CPU16Regs:$rd, CPU16Regs:$rs,
463243830Sdim                CPU16Regs:$rl, CPU16Regs:$rr),
464249423Sdim               !strconcat(op2,
465249423Sdim               !strconcat("\t$rl, $rr\n\t",
466249423Sdim               !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> {
467243830Sdim  let isCodeGenOnly=1;
468243830Sdim  let Constraints = "$rd = $rd_";
469249423Sdim  let usesCustomInserter = 1;
470243830Sdim}
471243830Sdim
472249423Sdim//
473249423Sdim// 32 bit constant
474249423Sdim//
475249423Sdimdef imm32: Operand<i32>;
476243830Sdim
477249423Sdimdef Constant32:
478249423Sdim  MipsPseudo16<(outs), (ins imm32:$imm), "\t.word $imm", []>;
479249423Sdim
480249423Sdimdef LwConstant32:
481263508Sdim  MipsPseudo16<(outs CPU16Regs:$rx), (ins imm32:$imm, imm32:$constid),
482249423Sdim    "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>;
483249423Sdim
484249423Sdim
485243830Sdim//
486239310Sdim// Some general instruction class info
487239310Sdim//
488239310Sdim//
489239310Sdim
490239310Sdimclass ArithLogic16Defs<bit isCom=0> {
491239310Sdim  bits<5> shamt = 0;
492239310Sdim  bit isCommutable = isCom;
493239310Sdim  bit isReMaterializable = 1;
494239310Sdim  bit neverHasSideEffects = 1;
495239310Sdim}
496239310Sdim
497243830Sdimclass branch16 {
498243830Sdim  bit isBranch = 1;
499243830Sdim  bit isTerminator = 1;
500243830Sdim  bit isBarrier = 1;
501243830Sdim}
502243830Sdim
503243830Sdimclass cbranch16 {
504243830Sdim  bit isBranch = 1;
505243830Sdim  bit isTerminator = 1;
506243830Sdim}
507243830Sdim
508243830Sdimclass MayLoad {
509243830Sdim  bit mayLoad = 1;
510243830Sdim}
511243830Sdim
512243830Sdimclass MayStore {
513243830Sdim  bit mayStore = 1;
514243830Sdim}
515239310Sdim//
516239310Sdim
517249423Sdim
518239310Sdim// Format: ADDIU rx, immediate MIPS16e
519239310Sdim// Purpose: Add Immediate Unsigned Word (2-Operand, Extended)
520239310Sdim// To add a constant to a 32-bit integer.
521239310Sdim//
522239310Sdimdef AddiuRxImmX16: FEXT_RI16_ins<0b01001, "addiu", IIAlu>;
523239310Sdim
524249423Sdimdef AddiuRxRxImm16: F2RI16_ins<0b01001, "addiu", IIAlu>,
525249423Sdim  ArithLogic16Defs<0> {
526249423Sdim  let AddedComplexity = 5;
527249423Sdim}
528239310Sdimdef AddiuRxRxImmX16: FEXT_2RI16_ins<0b01001, "addiu", IIAlu>,
529249423Sdim  ArithLogic16Defs<0> {
530249423Sdim  let isCodeGenOnly = 1;
531249423Sdim}
532239310Sdim
533243830Sdimdef AddiuRxRyOffMemX16:
534243830Sdim  FEXT_RRI_A16_mem_ins<0, "addiu", mem16_ea, IIAlu>;
535243830Sdim
536239310Sdim//
537239310Sdim
538239310Sdim// Format: ADDIU rx, pc, immediate MIPS16e
539239310Sdim// Purpose: Add Immediate Unsigned Word (3-Operand, PC-Relative, Extended)
540239310Sdim// To add a constant to the program counter.
541239310Sdim//
542239310Sdimdef AddiuRxPcImmX16: FEXT_RI16_PC_ins<0b00001, "addiu", IIAlu>;
543249423Sdim
544239310Sdim//
545249423Sdim// Format: ADDIU sp, immediate MIPS16e
546249423Sdim// Purpose: Add Immediate Unsigned Word (2-Operand, SP-Relative, Extended)
547249423Sdim// To add a constant to the stack pointer.
548249423Sdim//
549249423Sdimdef AddiuSpImm16
550249423Sdim  : FI816_SP_ins<0b011, "addiu", IIAlu> {
551249423Sdim  let Defs = [SP];
552249423Sdim  let Uses = [SP];
553249423Sdim  let AddedComplexity = 5;
554249423Sdim}
555249423Sdim
556249423Sdimdef AddiuSpImmX16
557249423Sdim  : FEXT_I816_SP_ins<0b011, "addiu", IIAlu> {
558249423Sdim  let Defs = [SP];
559249423Sdim  let Uses = [SP];
560249423Sdim}
561249423Sdim
562249423Sdim//
563239310Sdim// Format: ADDU rz, rx, ry MIPS16e
564239310Sdim// Purpose: Add Unsigned Word (3-Operand)
565239310Sdim// To add 32-bit integers.
566239310Sdim//
567239310Sdim
568239310Sdimdef AdduRxRyRz16: FRRR16_ins<01, "addu", IIAlu>, ArithLogic16Defs<1>;
569239310Sdim
570239310Sdim//
571239310Sdim// Format: AND rx, ry MIPS16e
572239310Sdim// Purpose: AND
573239310Sdim// To do a bitwise logical AND.
574239310Sdim
575239310Sdimdef AndRxRxRy16: FRxRxRy16_ins<0b01100, "and", IIAlu>, ArithLogic16Defs<1>;
576239310Sdim
577243830Sdim
578239310Sdim//
579243830Sdim// Format: BEQZ rx, offset MIPS16e
580249423Sdim// Purpose: Branch on Equal to Zero
581249423Sdim// To test a GPR then do a PC-relative conditional branch.
582249423Sdim//
583249423Sdimdef BeqzRxImm16: FRI16_B_ins<0b00100, "beqz", IIAlu>, cbranch16;
584249423Sdim
585249423Sdim
586249423Sdim//
587249423Sdim// Format: BEQZ rx, offset MIPS16e
588243830Sdim// Purpose: Branch on Equal to Zero (Extended)
589243830Sdim// To test a GPR then do a PC-relative conditional branch.
590243830Sdim//
591243830Sdimdef BeqzRxImmX16: FEXT_RI16_B_ins<0b00100, "beqz", IIAlu>, cbranch16;
592243830Sdim
593263508Sdim//
594243830Sdim// Format: B offset MIPS16e
595263508Sdim// Purpose: Unconditional Branch (Extended)
596263508Sdim// To do an unconditional PC-relative branch.
597263508Sdim//
598263508Sdim
599263508Sdimdef Bimm16: FI16_ins<0b00010, "b", IIAlu>, branch16;
600263508Sdim
601263508Sdim// Format: B offset MIPS16e
602243830Sdim// Purpose: Unconditional Branch
603243830Sdim// To do an unconditional PC-relative branch.
604243830Sdim//
605243830Sdimdef BimmX16: FEXT_I16_ins<0b00010, "b", IIAlu>, branch16;
606243830Sdim
607243830Sdim//
608243830Sdim// Format: BNEZ rx, offset MIPS16e
609249423Sdim// Purpose: Branch on Not Equal to Zero
610249423Sdim// To test a GPR then do a PC-relative conditional branch.
611249423Sdim//
612249423Sdimdef BnezRxImm16: FRI16_B_ins<0b00101, "bnez", IIAlu>, cbranch16;
613249423Sdim
614249423Sdim//
615249423Sdim// Format: BNEZ rx, offset MIPS16e
616243830Sdim// Purpose: Branch on Not Equal to Zero (Extended)
617243830Sdim// To test a GPR then do a PC-relative conditional branch.
618243830Sdim//
619243830Sdimdef BnezRxImmX16: FEXT_RI16_B_ins<0b00101, "bnez", IIAlu>, cbranch16;
620243830Sdim
621263508Sdim
622243830Sdim//
623263508Sdim//Format: BREAK immediate
624263508Sdim// Purpose: Breakpoint
625263508Sdim// To cause a Breakpoint exception.
626263508Sdim
627263508Sdimdef Break16: FRRBreakNull16_ins<"break 0", NoItinerary>; 
628263508Sdim//
629243830Sdim// Format: BTEQZ offset MIPS16e
630243830Sdim// Purpose: Branch on T Equal to Zero (Extended)
631243830Sdim// To test special register T then do a PC-relative conditional branch.
632243830Sdim//
633263508Sdimdef Bteqz16: FI816_ins<0b000, "bteqz", IIAlu>, cbranch16 {
634263508Sdim  let Uses = [T8];
635263508Sdim}
636263508Sdim
637249423Sdimdef BteqzX16: FEXT_I816_ins<0b000, "bteqz", IIAlu>, cbranch16 {
638249423Sdim  let Uses = [T8];
639249423Sdim}
640243830Sdim
641249423Sdimdef BteqzT8CmpX16: FEXT_T8I816_ins<"bteqz", "cmp">, cbranch16;
642243830Sdim
643249423Sdimdef BteqzT8CmpiX16: FEXT_T8I8I16_ins<"bteqz", "cmpi">,
644243830Sdim  cbranch16;
645243830Sdim
646249423Sdimdef BteqzT8SltX16: FEXT_T8I816_ins<"bteqz", "slt">, cbranch16;
647243830Sdim
648249423Sdimdef BteqzT8SltuX16: FEXT_T8I816_ins<"bteqz", "sltu">, cbranch16;
649243830Sdim
650249423Sdimdef BteqzT8SltiX16: FEXT_T8I8I16_ins<"bteqz", "slti">, cbranch16;
651243830Sdim
652249423Sdimdef BteqzT8SltiuX16: FEXT_T8I8I16_ins<"bteqz", "sltiu">,
653243830Sdim  cbranch16;
654243830Sdim
655243830Sdim//
656243830Sdim// Format: BTNEZ offset MIPS16e
657243830Sdim// Purpose: Branch on T Not Equal to Zero (Extended)
658243830Sdim// To test special register T then do a PC-relative conditional branch.
659243830Sdim//
660263508Sdim
661263508Sdimdef Btnez16: FI816_ins<0b001, "btnez", IIAlu>, cbranch16 {
662263508Sdim  let Uses = [T8];
663263508Sdim}
664263508Sdim
665249423Sdimdef BtnezX16: FEXT_I816_ins<0b001, "btnez", IIAlu> ,cbranch16 {
666249423Sdim  let Uses = [T8];
667249423Sdim}
668243830Sdim
669249423Sdimdef BtnezT8CmpX16: FEXT_T8I816_ins<"btnez", "cmp">, cbranch16;
670243830Sdim
671249423Sdimdef BtnezT8CmpiX16: FEXT_T8I8I16_ins<"btnez", "cmpi">, cbranch16;
672243830Sdim
673249423Sdimdef BtnezT8SltX16: FEXT_T8I816_ins<"btnez", "slt">, cbranch16;
674243830Sdim
675249423Sdimdef BtnezT8SltuX16: FEXT_T8I816_ins<"btnez", "sltu">, cbranch16;
676243830Sdim
677249423Sdimdef BtnezT8SltiX16: FEXT_T8I8I16_ins<"btnez", "slti">, cbranch16;
678243830Sdim
679249423Sdimdef BtnezT8SltiuX16: FEXT_T8I8I16_ins<"btnez", "sltiu">,
680243830Sdim  cbranch16;
681243830Sdim
682243830Sdim//
683249423Sdim// Format: CMP rx, ry MIPS16e
684249423Sdim// Purpose: Compare
685249423Sdim// To compare the contents of two GPRs.
686249423Sdim//
687249423Sdimdef CmpRxRy16: FRR16R_ins<0b01010, "cmp", IIAlu> {
688249423Sdim  let Defs = [T8];
689249423Sdim}
690249423Sdim
691249423Sdim//
692249423Sdim// Format: CMPI rx, immediate MIPS16e
693249423Sdim// Purpose: Compare Immediate
694249423Sdim// To compare a constant with the contents of a GPR.
695249423Sdim//
696249423Sdimdef CmpiRxImm16: FRI16R_ins<0b01110, "cmpi", IIAlu> {
697249423Sdim  let Defs = [T8];
698249423Sdim}
699249423Sdim
700249423Sdim//
701249423Sdim// Format: CMPI rx, immediate MIPS16e
702249423Sdim// Purpose: Compare Immediate (Extended)
703249423Sdim// To compare a constant with the contents of a GPR.
704249423Sdim//
705249423Sdimdef CmpiRxImmX16: FEXT_RI16R_ins<0b01110, "cmpi", IIAlu> {
706249423Sdim  let Defs = [T8];
707249423Sdim}
708249423Sdim
709249423Sdim
710249423Sdim//
711243830Sdim// Format: DIV rx, ry MIPS16e
712243830Sdim// Purpose: Divide Word
713243830Sdim// To divide 32-bit signed integers.
714243830Sdim//
715243830Sdimdef DivRxRy16: FRR16_div_ins<0b11010, "div", IIAlu> {
716263508Sdim  let Defs = [HI0, LO0];
717243830Sdim}
718243830Sdim
719243830Sdim//
720243830Sdim// Format: DIVU rx, ry MIPS16e
721243830Sdim// Purpose: Divide Unsigned Word
722243830Sdim// To divide 32-bit unsigned integers.
723243830Sdim//
724243830Sdimdef DivuRxRy16: FRR16_div_ins<0b11011, "divu", IIAlu> {
725263508Sdim  let Defs = [HI0, LO0];
726243830Sdim}
727249423Sdim//
728249423Sdim// Format: JAL target MIPS16e
729249423Sdim// Purpose: Jump and Link
730249423Sdim// To execute a procedure call within the current 256 MB-aligned
731249423Sdim// region and preserve the current ISA.
732249423Sdim//
733243830Sdim
734249423Sdimdef Jal16 : FJAL16_ins<0b0, "jal", IIAlu> {
735249423Sdim  let hasDelaySlot = 0;  // not true, but we add the nop for now
736263508Sdim  let isCall=1;
737249423Sdim}
738243830Sdim
739243830Sdim//
740239310Sdim// Format: JR ra MIPS16e
741239310Sdim// Purpose: Jump Register Through Register ra
742239310Sdim// To execute a branch to the instruction address in the return
743239310Sdim// address register.
744239310Sdim//
745239310Sdim
746243830Sdimdef JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu> {
747243830Sdim  let isBranch = 1;
748243830Sdim  let isIndirectBranch = 1;
749243830Sdim  let hasDelaySlot = 1;
750243830Sdim  let isTerminator=1;
751243830Sdim  let isBarrier=1;
752243830Sdim}
753239310Sdim
754249423Sdimdef JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIAlu> {
755243830Sdim  let isBranch = 1;
756243830Sdim  let isIndirectBranch = 1;
757243830Sdim  let isTerminator=1;
758243830Sdim  let isBarrier=1;
759243830Sdim}
760243830Sdim
761243830Sdimdef JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc", IIAlu> {
762243830Sdim  let isBranch = 1;
763243830Sdim  let isIndirectBranch = 1;
764243830Sdim  let isTerminator=1;
765243830Sdim  let isBarrier=1;
766243830Sdim}
767239310Sdim//
768239310Sdim// Format: LB ry, offset(rx) MIPS16e
769239310Sdim// Purpose: Load Byte (Extended)
770239310Sdim// To load a byte from memory as a signed value.
771239310Sdim//
772249423Sdimdef LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", mem16, IILoad>, MayLoad{
773249423Sdim  let isCodeGenOnly = 1;
774249423Sdim}
775239310Sdim
776239310Sdim//
777239310Sdim// Format: LBU ry, offset(rx) MIPS16e
778239310Sdim// Purpose: Load Byte Unsigned (Extended)
779239310Sdim// To load a byte from memory as a unsigned value.
780239310Sdim//
781243830Sdimdef LbuRxRyOffMemX16:
782249423Sdim  FEXT_RRI16_mem_ins<0b10100, "lbu", mem16, IILoad>, MayLoad {
783249423Sdim  let isCodeGenOnly = 1;
784249423Sdim}
785239310Sdim
786239310Sdim//
787239310Sdim// Format: LH ry, offset(rx) MIPS16e
788239310Sdim// Purpose: Load Halfword signed (Extended)
789239310Sdim// To load a halfword from memory as a signed value.
790239310Sdim//
791249423Sdimdef LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", mem16, IILoad>, MayLoad{
792249423Sdim  let isCodeGenOnly = 1;
793249423Sdim}
794239310Sdim
795239310Sdim//
796239310Sdim// Format: LHU ry, offset(rx) MIPS16e
797239310Sdim// Purpose: Load Halfword unsigned (Extended)
798239310Sdim// To load a halfword from memory as an unsigned value.
799239310Sdim//
800243830Sdimdef LhuRxRyOffMemX16:
801249423Sdim  FEXT_RRI16_mem_ins<0b10100, "lhu", mem16, IILoad>, MayLoad {
802249423Sdim  let isCodeGenOnly = 1;
803249423Sdim}
804239310Sdim
805239310Sdim//
806239310Sdim// Format: LI rx, immediate MIPS16e
807249423Sdim// Purpose: Load Immediate
808249423Sdim// To load a constant into a GPR.
809249423Sdim//
810249423Sdimdef LiRxImm16: FRI16_ins<0b01101, "li", IIAlu>;
811249423Sdim
812249423Sdim//
813249423Sdim// Format: LI rx, immediate MIPS16e
814239310Sdim// Purpose: Load Immediate (Extended)
815239310Sdim// To load a constant into a GPR.
816239310Sdim//
817239310Sdimdef LiRxImmX16: FEXT_RI16_ins<0b01101, "li", IIAlu>;
818239310Sdim
819263508Sdimdef LiRxImmAlignX16: FEXT_RI16_ins<0b01101, ".align 2\n\tli", IIAlu> {
820263508Sdim  let isCodeGenOnly = 1;
821263508Sdim}
822263508Sdim
823239310Sdim//
824239310Sdim// Format: LW ry, offset(rx) MIPS16e
825239310Sdim// Purpose: Load Word (Extended)
826239310Sdim// To load a word from memory as a signed value.
827239310Sdim//
828249423Sdimdef LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, IILoad>, MayLoad{
829249423Sdim  let isCodeGenOnly = 1;
830249423Sdim}
831239310Sdim
832243830Sdim// Format: LW rx, offset(sp) MIPS16e
833243830Sdim// Purpose: Load Word (SP-Relative, Extended)
834243830Sdim// To load an SP-relative word from memory as a signed value.
835239310Sdim//
836263508Sdimdef LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10010, "lw", IILoad>, MayLoad{
837249423Sdim  let Uses = [SP];
838249423Sdim}
839243830Sdim
840263508Sdimdef LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;
841263508Sdim
842263508Sdimdef LwRxPcTcpX16: FEXT_RI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad;
843243830Sdim//
844239310Sdim// Format: MOVE r32, rz MIPS16e
845239310Sdim// Purpose: Move
846239310Sdim// To move the contents of a GPR to a GPR.
847239310Sdim//
848243830Sdimdef Move32R16: FI8_MOV32R16_ins<"move", IIAlu>;
849239310Sdim
850239310Sdim//
851243830Sdim// Format: MOVE ry, r32 MIPS16e
852243830Sdim//Purpose: Move
853243830Sdim// To move the contents of a GPR to a GPR.
854243830Sdim//
855243830Sdimdef MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>;
856243830Sdim
857243830Sdim//
858243830Sdim// Format: MFHI rx MIPS16e
859243830Sdim// Purpose: Move From HI Register
860243830Sdim// To copy the special purpose HI register to a GPR.
861243830Sdim//
862243830Sdimdef Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> {
863263508Sdim  let Uses = [HI0];
864243830Sdim  let neverHasSideEffects = 1;
865243830Sdim}
866243830Sdim
867243830Sdim//
868243830Sdim// Format: MFLO rx MIPS16e
869243830Sdim// Purpose: Move From LO Register
870243830Sdim// To copy the special purpose LO register to a GPR.
871243830Sdim//
872243830Sdimdef Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> {
873263508Sdim  let Uses = [LO0];
874243830Sdim  let neverHasSideEffects = 1;
875243830Sdim}
876243830Sdim
877243830Sdim//
878243830Sdim// Pseudo Instruction for mult
879243830Sdim//
880243830Sdimdef MultRxRy16:  FMULT16_ins<"mult",  IIAlu> {
881243830Sdim  let isCommutable = 1;
882243830Sdim  let neverHasSideEffects = 1;
883263508Sdim  let Defs = [HI0, LO0];
884243830Sdim}
885243830Sdim
886243830Sdimdef MultuRxRy16: FMULT16_ins<"multu", IIAlu> {
887243830Sdim  let isCommutable = 1;
888243830Sdim  let neverHasSideEffects = 1;
889263508Sdim  let Defs = [HI0, LO0];
890243830Sdim}
891243830Sdim
892243830Sdim//
893243830Sdim// Format: MULT rx, ry MIPS16e
894243830Sdim// Purpose: Multiply Word
895243830Sdim// To multiply 32-bit signed integers.
896243830Sdim//
897243830Sdimdef MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> {
898243830Sdim  let isCommutable = 1;
899243830Sdim  let neverHasSideEffects = 1;
900263508Sdim  let Defs = [HI0, LO0];
901243830Sdim}
902243830Sdim
903243830Sdim//
904243830Sdim// Format: MULTU rx, ry MIPS16e
905243830Sdim// Purpose: Multiply Unsigned Word
906243830Sdim// To multiply 32-bit unsigned integers.
907243830Sdim//
908243830Sdimdef MultuRxRyRz16: FMULT16_LO_ins<"multu", IIAlu> {
909243830Sdim  let isCommutable = 1;
910243830Sdim  let neverHasSideEffects = 1;
911263508Sdim  let Defs = [HI0, LO0];
912243830Sdim}
913243830Sdim
914243830Sdim//
915239310Sdim// Format: NEG rx, ry MIPS16e
916239310Sdim// Purpose: Negate
917239310Sdim// To negate an integer value.
918239310Sdim//
919243830Sdimdef NegRxRy16: FUnaryRR16_ins<0b11101, "neg", IIAlu>;
920239310Sdim
921239310Sdim//
922239310Sdim// Format: NOT rx, ry MIPS16e
923239310Sdim// Purpose: Not
924239310Sdim// To complement an integer value
925239310Sdim//
926243830Sdimdef NotRxRy16: FUnaryRR16_ins<0b01111, "not", IIAlu>;
927239310Sdim
928239310Sdim//
929239310Sdim// Format: OR rx, ry MIPS16e
930239310Sdim// Purpose: Or
931239310Sdim// To do a bitwise logical OR.
932239310Sdim//
933239310Sdimdef OrRxRxRy16: FRxRxRy16_ins<0b01101, "or", IIAlu>, ArithLogic16Defs<1>;
934239310Sdim
935239310Sdim//
936239310Sdim// Format: RESTORE {ra,}{s0/s1/s0-1,}{framesize}
937239310Sdim// (All args are optional) MIPS16e
938239310Sdim// Purpose: Restore Registers and Deallocate Stack Frame
939239310Sdim// To deallocate a stack frame before exit from a subroutine,
940239310Sdim// restoring return address and static registers, and adjusting
941239310Sdim// stack
942239310Sdim//
943239310Sdim
944239310Sdim// fixed form for restoring RA and the frame
945239310Sdim// for direct object emitter, encoding needs to be adjusted for the
946239310Sdim// frame size
947239310Sdim//
948243830Sdimlet ra=1, s=0,s0=1,s1=1 in
949239310Sdimdef RestoreRaF16:
950239310Sdim  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
951263508Sdim             "restore\t$$ra,  $$s0, $$s1, $$s2, $frame_size", [], IILoad >, MayLoad {
952243830Sdim  let isCodeGenOnly = 1;
953263508Sdim  let Defs = [S0, S1, S2, RA, SP];
954249423Sdim  let Uses = [SP];
955243830Sdim}
956239310Sdim
957243830Sdim// Use Restore to increment SP since SP is not a Mip 16 register, this
958243830Sdim// is an easy way to do that which does not require a register.
959239310Sdim//
960243830Sdimlet ra=0, s=0,s0=0,s1=0 in
961243830Sdimdef RestoreIncSpF16:
962243830Sdim  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
963243830Sdim             "restore\t$frame_size", [], IILoad >, MayLoad {
964243830Sdim  let isCodeGenOnly = 1;
965249423Sdim  let Defs = [SP];
966249423Sdim  let Uses = [SP];
967243830Sdim}
968243830Sdim
969243830Sdim//
970239310Sdim// Format: SAVE {ra,}{s0/s1/s0-1,}{framesize} (All arguments are optional)
971239310Sdim// MIPS16e
972239310Sdim// Purpose: Save Registers and Set Up Stack Frame
973239310Sdim// To set up a stack frame on entry to a subroutine,
974239310Sdim// saving return address and static registers, and adjusting stack
975239310Sdim//
976243830Sdimlet ra=1, s=1,s0=1,s1=1 in
977239310Sdimdef SaveRaF16:
978239310Sdim  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
979263508Sdim             "save\t$$ra, $$s0, $$s1, $$s2, $frame_size", [], IIStore >, MayStore {
980243830Sdim  let isCodeGenOnly = 1;
981263508Sdim  let Uses = [RA, SP, S0, S1, S2];
982249423Sdim  let Defs = [SP];
983243830Sdim}
984239310Sdim
985239310Sdim//
986243830Sdim// Use Save to decrement the SP by a constant since SP is not
987243830Sdim// a Mips16 register.
988243830Sdim//
989243830Sdimlet ra=0, s=0,s0=0,s1=0 in
990243830Sdimdef SaveDecSpF16:
991243830Sdim  FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size),
992243830Sdim             "save\t$frame_size", [], IIStore >, MayStore {
993243830Sdim  let isCodeGenOnly = 1;
994249423Sdim  let Uses = [SP];
995249423Sdim  let Defs = [SP];
996243830Sdim}
997243830Sdim//
998239310Sdim// Format: SB ry, offset(rx) MIPS16e
999239310Sdim// Purpose: Store Byte (Extended)
1000239310Sdim// To store a byte to memory.
1001239310Sdim//
1002243830Sdimdef SbRxRyOffMemX16:
1003243830Sdim  FEXT_RRI16_mem2_ins<0b11000, "sb", mem16, IIStore>, MayStore;
1004239310Sdim
1005239310Sdim//
1006263508Sdim// Format: SEB rx MIPS16e
1007263508Sdim// Purpose: Sign-Extend Byte
1008263508Sdim// Sign-extend least significant byte in register rx.
1009263508Sdim//
1010263508Sdimdef SebRx16
1011263508Sdim  : FRR_SF16_ins<0b10001, 0b100, "seb", IIAlu>;
1012263508Sdim
1013263508Sdim//
1014263508Sdim// Format: SEH rx MIPS16e
1015263508Sdim// Purpose: Sign-Extend Halfword
1016263508Sdim// Sign-extend least significant word in register rx.
1017263508Sdim//
1018263508Sdimdef SehRx16
1019263508Sdim  : FRR_SF16_ins<0b10001, 0b101, "seh", IIAlu>;
1020263508Sdim
1021263508Sdim//
1022243830Sdim// The Sel(T) instructions are pseudos
1023243830Sdim// T means that they use T8 implicitly.
1024243830Sdim//
1025243830Sdim//
1026243830Sdim// Format: SelBeqZ rd, rs, rt
1027243830Sdim// Purpose: if rt==0, do nothing
1028243830Sdim//          else rs = rt
1029243830Sdim//
1030249423Sdimdef SelBeqZ: Sel<"beqz">;
1031243830Sdim
1032243830Sdim//
1033243830Sdim// Format:  SelTBteqZCmp rd, rs, rl, rr
1034243830Sdim// Purpose: b = Cmp rl, rr.
1035243830Sdim//          If b==0 then do nothing.
1036243830Sdim//          if b!=0 then rd = rs
1037243830Sdim//
1038249423Sdimdef SelTBteqZCmp: SelT<"bteqz", "cmp">;
1039243830Sdim
1040243830Sdim//
1041243830Sdim// Format:  SelTBteqZCmpi rd, rs, rl, rr
1042243830Sdim// Purpose: b = Cmpi rl, imm.
1043243830Sdim//          If b==0 then do nothing.
1044243830Sdim//          if b!=0 then rd = rs
1045243830Sdim//
1046249423Sdimdef SelTBteqZCmpi: SeliT<"bteqz", "cmpi">;
1047243830Sdim
1048243830Sdim//
1049243830Sdim// Format:  SelTBteqZSlt rd, rs, rl, rr
1050243830Sdim// Purpose: b = Slt rl, rr.
1051243830Sdim//          If b==0 then do nothing.
1052243830Sdim//          if b!=0 then rd = rs
1053243830Sdim//
1054249423Sdimdef SelTBteqZSlt: SelT<"bteqz", "slt">;
1055243830Sdim
1056243830Sdim//
1057243830Sdim// Format:  SelTBteqZSlti rd, rs, rl, rr
1058243830Sdim// Purpose: b = Slti rl, imm.
1059243830Sdim//          If b==0 then do nothing.
1060243830Sdim//          if b!=0 then rd = rs
1061243830Sdim//
1062249423Sdimdef SelTBteqZSlti: SeliT<"bteqz", "slti">;
1063243830Sdim
1064243830Sdim//
1065243830Sdim// Format:  SelTBteqZSltu rd, rs, rl, rr
1066243830Sdim// Purpose: b = Sltu rl, rr.
1067243830Sdim//          If b==0 then do nothing.
1068243830Sdim//          if b!=0 then rd = rs
1069243830Sdim//
1070249423Sdimdef SelTBteqZSltu: SelT<"bteqz", "sltu">;
1071243830Sdim
1072243830Sdim//
1073243830Sdim// Format:  SelTBteqZSltiu rd, rs, rl, rr
1074243830Sdim// Purpose: b = Sltiu rl, imm.
1075243830Sdim//          If b==0 then do nothing.
1076243830Sdim//          if b!=0 then rd = rs
1077243830Sdim//
1078249423Sdimdef SelTBteqZSltiu: SeliT<"bteqz", "sltiu">;
1079243830Sdim
1080243830Sdim//
1081243830Sdim// Format: SelBnez rd, rs, rt
1082243830Sdim// Purpose: if rt!=0, do nothing
1083243830Sdim//          else rs = rt
1084243830Sdim//
1085249423Sdimdef SelBneZ: Sel<"bnez">;
1086243830Sdim
1087243830Sdim//
1088243830Sdim// Format:  SelTBtneZCmp rd, rs, rl, rr
1089243830Sdim// Purpose: b = Cmp rl, rr.
1090243830Sdim//          If b!=0 then do nothing.
1091243830Sdim//          if b0=0 then rd = rs
1092243830Sdim//
1093249423Sdimdef SelTBtneZCmp: SelT<"btnez", "cmp">;
1094243830Sdim
1095243830Sdim//
1096243830Sdim// Format:  SelTBtnezCmpi rd, rs, rl, rr
1097243830Sdim// Purpose: b = Cmpi rl, imm.
1098243830Sdim//          If b!=0 then do nothing.
1099243830Sdim//          if b==0 then rd = rs
1100243830Sdim//
1101249423Sdimdef SelTBtneZCmpi: SeliT<"btnez", "cmpi">;
1102243830Sdim
1103243830Sdim//
1104243830Sdim// Format:  SelTBtneZSlt rd, rs, rl, rr
1105243830Sdim// Purpose: b = Slt rl, rr.
1106243830Sdim//          If b!=0 then do nothing.
1107243830Sdim//          if b==0 then rd = rs
1108243830Sdim//
1109249423Sdimdef SelTBtneZSlt: SelT<"btnez", "slt">;
1110243830Sdim
1111243830Sdim//
1112243830Sdim// Format:  SelTBtneZSlti rd, rs, rl, rr
1113243830Sdim// Purpose: b = Slti rl, imm.
1114243830Sdim//          If b!=0 then do nothing.
1115243830Sdim//          if b==0 then rd = rs
1116243830Sdim//
1117249423Sdimdef SelTBtneZSlti: SeliT<"btnez", "slti">;
1118243830Sdim
1119243830Sdim//
1120243830Sdim// Format:  SelTBtneZSltu rd, rs, rl, rr
1121243830Sdim// Purpose: b = Sltu rl, rr.
1122243830Sdim//          If b!=0 then do nothing.
1123243830Sdim//          if b==0 then rd = rs
1124243830Sdim//
1125249423Sdimdef SelTBtneZSltu: SelT<"btnez", "sltu">;
1126243830Sdim
1127243830Sdim//
1128243830Sdim// Format:  SelTBtneZSltiu rd, rs, rl, rr
1129243830Sdim// Purpose: b = Slti rl, imm.
1130243830Sdim//          If b!=0 then do nothing.
1131243830Sdim//          if b==0 then rd = rs
1132243830Sdim//
1133249423Sdimdef SelTBtneZSltiu: SeliT<"btnez", "sltiu">;
1134243830Sdim//
1135243830Sdim//
1136239310Sdim// Format: SH ry, offset(rx) MIPS16e
1137239310Sdim// Purpose: Store Halfword (Extended)
1138239310Sdim// To store a halfword to memory.
1139239310Sdim//
1140243830Sdimdef ShRxRyOffMemX16:
1141243830Sdim  FEXT_RRI16_mem2_ins<0b11001, "sh", mem16, IIStore>, MayStore;
1142239310Sdim
1143239310Sdim//
1144239310Sdim// Format: SLL rx, ry, sa MIPS16e
1145239310Sdim// Purpose: Shift Word Left Logical (Extended)
1146263508Sdim// To execute a left-shift of a word by a fixed number of bits-0 to 31 bits.
1147239310Sdim//
1148239310Sdimdef SllX16: FEXT_SHIFT16_ins<0b00, "sll", IIAlu>;
1149239310Sdim
1150239310Sdim//
1151239310Sdim// Format: SLLV ry, rx MIPS16e
1152239310Sdim// Purpose: Shift Word Left Logical Variable
1153239310Sdim// To execute a left-shift of a word by a variable number of bits.
1154239310Sdim//
1155239310Sdimdef SllvRxRy16 : FRxRxRy16_ins<0b00100, "sllv", IIAlu>;
1156239310Sdim
1157249423Sdim// Format: SLTI rx, immediate MIPS16e
1158249423Sdim// Purpose: Set on Less Than Immediate
1159249423Sdim// To record the result of a less-than comparison with a constant.
1160243830Sdim//
1161249423Sdim//
1162249423Sdimdef SltiRxImm16: FRI16R_ins<0b01010, "slti", IIAlu> {
1163249423Sdim  let Defs = [T8];
1164249423Sdim}
1165249423Sdim
1166249423Sdim//
1167243830Sdim// Format: SLTI rx, immediate MIPS16e
1168243830Sdim// Purpose: Set on Less Than Immediate (Extended)
1169243830Sdim// To record the result of a less-than comparison with a constant.
1170243830Sdim//
1171249423Sdim//
1172249423Sdimdef SltiRxImmX16: FEXT_RI16R_ins<0b01010, "slti", IIAlu> {
1173249423Sdim  let Defs = [T8];
1174249423Sdim}
1175239310Sdim
1176249423Sdimdef SltiCCRxImmX16: FEXT_CCRXI16_ins<"slti">;
1177249423Sdim
1178249423Sdim// Format: SLTIU rx, immediate MIPS16e
1179249423Sdim// Purpose: Set on Less Than Immediate Unsigned
1180249423Sdim// To record the result of a less-than comparison with a constant.
1181239310Sdim//
1182249423Sdim//
1183249423Sdimdef SltiuRxImm16: FRI16R_ins<0b01011, "sltiu", IIAlu> {
1184249423Sdim  let Defs = [T8];
1185249423Sdim}
1186249423Sdim
1187249423Sdim//
1188249423Sdim// Format: SLTI rx, immediate MIPS16e
1189249423Sdim// Purpose: Set on Less Than Immediate Unsigned (Extended)
1190249423Sdim// To record the result of a less-than comparison with a constant.
1191249423Sdim//
1192249423Sdim//
1193249423Sdimdef SltiuRxImmX16: FEXT_RI16R_ins<0b01011, "sltiu", IIAlu> {
1194249423Sdim  let Defs = [T8];
1195249423Sdim}
1196249423Sdim//
1197243830Sdim// Format: SLTIU rx, immediate MIPS16e
1198243830Sdim// Purpose: Set on Less Than Immediate Unsigned (Extended)
1199243830Sdim// To record the result of a less-than comparison with a constant.
1200243830Sdim//
1201249423Sdimdef SltiuCCRxImmX16: FEXT_CCRXI16_ins<"sltiu">;
1202243830Sdim
1203243830Sdim//
1204243830Sdim// Format: SLT rx, ry MIPS16e
1205243830Sdim// Purpose: Set on Less Than
1206243830Sdim// To record the result of a less-than comparison.
1207243830Sdim//
1208249423Sdimdef SltRxRy16: FRR16R_ins<0b00010, "slt", IIAlu>{
1209249423Sdim  let Defs = [T8];
1210249423Sdim}
1211243830Sdim
1212249423Sdimdef SltCCRxRy16: FCCRR16_ins<"slt">;
1213243830Sdim
1214243830Sdim// Format: SLTU rx, ry MIPS16e
1215243830Sdim// Purpose: Set on Less Than Unsigned
1216243830Sdim// To record the result of an unsigned less-than comparison.
1217243830Sdim//
1218249423Sdimdef SltuRxRy16: FRR16R_ins<0b00011, "sltu", IIAlu>{
1219249423Sdim  let Defs = [T8];
1220249423Sdim}
1221249423Sdim
1222249423Sdimdef SltuRxRyRz16: FRRTR16_ins<"sltu"> {
1223243830Sdim  let isCodeGenOnly=1;
1224249423Sdim  let Defs = [T8];
1225243830Sdim}
1226243830Sdim
1227243830Sdim
1228249423Sdimdef SltuCCRxRy16: FCCRR16_ins<"sltu">;
1229243830Sdim//
1230239310Sdim// Format: SRAV ry, rx MIPS16e
1231239310Sdim// Purpose: Shift Word Right Arithmetic Variable
1232239310Sdim// To execute an arithmetic right-shift of a word by a variable
1233239310Sdim// number of bits.
1234239310Sdim//
1235239310Sdimdef SravRxRy16: FRxRxRy16_ins<0b00111, "srav", IIAlu>;
1236239310Sdim
1237239310Sdim
1238239310Sdim//
1239239310Sdim// Format: SRA rx, ry, sa MIPS16e
1240239310Sdim// Purpose: Shift Word Right Arithmetic (Extended)
1241239310Sdim// To execute an arithmetic right-shift of a word by a fixed
1242263508Sdim// number of bits-1 to 8 bits.
1243239310Sdim//
1244239310Sdimdef SraX16: FEXT_SHIFT16_ins<0b11, "sra", IIAlu>;
1245239310Sdim
1246239310Sdim
1247239310Sdim//
1248239310Sdim// Format: SRLV ry, rx MIPS16e
1249239310Sdim// Purpose: Shift Word Right Logical Variable
1250239310Sdim// To execute a logical right-shift of a word by a variable
1251239310Sdim// number of bits.
1252239310Sdim//
1253239310Sdimdef SrlvRxRy16: FRxRxRy16_ins<0b00110, "srlv", IIAlu>;
1254239310Sdim
1255239310Sdim
1256239310Sdim//
1257239310Sdim// Format: SRL rx, ry, sa MIPS16e
1258239310Sdim// Purpose: Shift Word Right Logical (Extended)
1259239310Sdim// To execute a logical right-shift of a word by a fixed
1260263508Sdim// number of bits-1 to 31 bits.
1261239310Sdim//
1262239310Sdimdef SrlX16: FEXT_SHIFT16_ins<0b10, "srl", IIAlu>;
1263239310Sdim
1264239310Sdim//
1265239310Sdim// Format: SUBU rz, rx, ry MIPS16e
1266239310Sdim// Purpose: Subtract Unsigned Word
1267239310Sdim// To subtract 32-bit integers
1268239310Sdim//
1269239310Sdimdef SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIAlu>, ArithLogic16Defs<0>;
1270239310Sdim
1271239310Sdim//
1272239310Sdim// Format: SW ry, offset(rx) MIPS16e
1273239310Sdim// Purpose: Store Word (Extended)
1274239310Sdim// To store a word to memory.
1275239310Sdim//
1276243830Sdimdef SwRxRyOffMemX16:
1277243830Sdim  FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, IIStore>, MayStore;
1278239310Sdim
1279239310Sdim//
1280243830Sdim// Format: SW rx, offset(sp) MIPS16e
1281243830Sdim// Purpose: Store Word rx (SP-Relative)
1282243830Sdim// To store an SP-relative word to memory.
1283243830Sdim//
1284263508Sdimdef SwRxSpImmX16: FEXT_RI16_SP_Store_explicit_ins
1285263508Sdim  <0b11010, "sw", IIStore>, MayStore;
1286243830Sdim
1287243830Sdim//
1288243830Sdim//
1289239310Sdim// Format: XOR rx, ry MIPS16e
1290239310Sdim// Purpose: Xor
1291239310Sdim// To do a bitwise logical XOR.
1292239310Sdim//
1293239310Sdimdef XorRxRxRy16: FRxRxRy16_ins<0b01110, "xor", IIAlu>, ArithLogic16Defs<1>;
1294239310Sdim
1295239310Sdimclass Mips16Pat<dag pattern, dag result> : Pat<pattern, result> {
1296239310Sdim  let Predicates = [InMips16Mode];
1297239310Sdim}
1298239310Sdim
1299239310Sdim// Unary Arith/Logic
1300239310Sdim//
1301239310Sdimclass ArithLogicU_pat<PatFrag OpNode, Instruction I> :
1302239310Sdim  Mips16Pat<(OpNode CPU16Regs:$r),
1303239310Sdim            (I CPU16Regs:$r)>;
1304239310Sdim
1305239310Sdimdef: ArithLogicU_pat<not, NotRxRy16>;
1306239310Sdimdef: ArithLogicU_pat<ineg, NegRxRy16>;
1307239310Sdim
1308239310Sdimclass ArithLogic16_pat<SDNode OpNode, Instruction I> :
1309239310Sdim  Mips16Pat<(OpNode CPU16Regs:$l, CPU16Regs:$r),
1310239310Sdim            (I CPU16Regs:$l, CPU16Regs:$r)>;
1311239310Sdim
1312239310Sdimdef: ArithLogic16_pat<add, AdduRxRyRz16>;
1313239310Sdimdef: ArithLogic16_pat<and, AndRxRxRy16>;
1314243830Sdimdef: ArithLogic16_pat<mul, MultRxRyRz16>;
1315239310Sdimdef: ArithLogic16_pat<or, OrRxRxRy16>;
1316239310Sdimdef: ArithLogic16_pat<sub, SubuRxRyRz16>;
1317239310Sdimdef: ArithLogic16_pat<xor, XorRxRxRy16>;
1318239310Sdim
1319239310Sdim// Arithmetic and logical instructions with 2 register operands.
1320239310Sdim
1321239310Sdimclass ArithLogicI16_pat<SDNode OpNode, PatFrag imm_type, Instruction I> :
1322239310Sdim  Mips16Pat<(OpNode CPU16Regs:$in, imm_type:$imm),
1323239310Sdim            (I CPU16Regs:$in, imm_type:$imm)>;
1324239310Sdim
1325249423Sdimdef: ArithLogicI16_pat<add, immSExt8, AddiuRxRxImm16>;
1326239310Sdimdef: ArithLogicI16_pat<add, immSExt16, AddiuRxRxImmX16>;
1327239310Sdimdef: ArithLogicI16_pat<shl, immZExt5, SllX16>;
1328239310Sdimdef: ArithLogicI16_pat<srl, immZExt5, SrlX16>;
1329239310Sdimdef: ArithLogicI16_pat<sra, immZExt5, SraX16>;
1330239310Sdim
1331239310Sdimclass shift_rotate_reg16_pat<SDNode OpNode, Instruction I> :
1332239310Sdim  Mips16Pat<(OpNode CPU16Regs:$r, CPU16Regs:$ra),
1333239310Sdim            (I CPU16Regs:$r, CPU16Regs:$ra)>;
1334239310Sdim
1335239310Sdimdef: shift_rotate_reg16_pat<shl, SllvRxRy16>;
1336239310Sdimdef: shift_rotate_reg16_pat<sra, SravRxRy16>;
1337239310Sdimdef: shift_rotate_reg16_pat<srl, SrlvRxRy16>;
1338239310Sdim
1339239310Sdimclass LoadM16_pat<PatFrag OpNode, Instruction I> :
1340243830Sdim  Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>;
1341239310Sdim
1342239310Sdimdef: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>;
1343239310Sdimdef: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>;
1344243830Sdimdef: LoadM16_pat<sextloadi16, LhRxRyOffMemX16>;
1345243830Sdimdef: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>;
1346243830Sdimdef: LoadM16_pat<load, LwRxRyOffMemX16>;
1347239310Sdim
1348239310Sdimclass StoreM16_pat<PatFrag OpNode, Instruction I> :
1349243830Sdim  Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr),
1350243830Sdim            (I CPU16Regs:$r, addr16:$addr)>;
1351239310Sdim
1352239310Sdimdef: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>;
1353243830Sdimdef: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>;
1354243830Sdimdef: StoreM16_pat<store, SwRxRyOffMemX16>;
1355239310Sdim
1356243830Sdim// Unconditional branch
1357243830Sdimclass UncondBranch16_pat<SDNode OpNode, Instruction I>:
1358243830Sdim  Mips16Pat<(OpNode bb:$imm16), (I bb:$imm16)> {
1359249423Sdim    let Predicates = [InMips16Mode];
1360243830Sdim  }
1361239310Sdim
1362249423Sdimdef : Mips16Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
1363249423Sdim                (Jal16 tglobaladdr:$dst)>;
1364249423Sdim
1365249423Sdimdef : Mips16Pat<(MipsJmpLink (i32 texternalsym:$dst)),
1366249423Sdim                (Jal16 texternalsym:$dst)>;
1367249423Sdim
1368243830Sdim// Indirect branch
1369243830Sdimdef: Mips16Pat<
1370249423Sdim  (brind CPU16Regs:$rs),
1371249423Sdim  (JrcRx16 CPU16Regs:$rs)>;
1372243830Sdim
1373239310Sdim// Jump and Link (Call)
1374243830Sdimlet isCall=1, hasDelaySlot=0 in
1375239310Sdimdef JumpLinkReg16:
1376239310Sdim  FRR16_JALRC<0, 0, 0, (outs), (ins CPU16Regs:$rs),
1377243830Sdim              "jalrc \t$rs", [(MipsJmpLink CPU16Regs:$rs)], IIBranch>;
1378239310Sdim
1379239310Sdim// Mips16 pseudos
1380239310Sdimlet isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1,
1381239310Sdim  hasExtraSrcRegAllocReq = 1 in
1382239310Sdimdef RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>;
1383239310Sdim
1384243830Sdim
1385243830Sdim// setcc patterns
1386243830Sdim
1387243830Sdimclass SetCC_R16<PatFrag cond_op, Instruction I>:
1388243830Sdim  Mips16Pat<(cond_op CPU16Regs:$rx, CPU16Regs:$ry),
1389243830Sdim            (I CPU16Regs:$rx, CPU16Regs:$ry)>;
1390243830Sdim
1391243830Sdimclass SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>:
1392243830Sdim  Mips16Pat<(cond_op CPU16Regs:$rx, imm_type:$imm16),
1393243830Sdim            (I CPU16Regs:$rx, imm_type:$imm16)>;
1394243830Sdim
1395243830Sdim
1396243830Sdimdef: Mips16Pat<(i32  addr16:$addr),
1397243830Sdim               (AddiuRxRyOffMemX16  addr16:$addr)>;
1398243830Sdim
1399243830Sdim
1400243830Sdim// Large (>16 bit) immediate loads
1401263508Sdimdef : Mips16Pat<(i32 imm:$imm), (LwConstant32 imm:$imm, -1)>;
1402243830Sdim
1403243830Sdim// Carry MipsPatterns
1404243830Sdimdef : Mips16Pat<(subc CPU16Regs:$lhs, CPU16Regs:$rhs),
1405243830Sdim                (SubuRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>;
1406243830Sdimdef : Mips16Pat<(addc CPU16Regs:$lhs, CPU16Regs:$rhs),
1407243830Sdim                (AdduRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>;
1408243830Sdimdef : Mips16Pat<(addc  CPU16Regs:$src, immSExt16:$imm),
1409243830Sdim                (AddiuRxRxImmX16 CPU16Regs:$src, imm:$imm)>;
1410243830Sdim
1411243830Sdim//
1412243830Sdim// Some branch conditional patterns are not generated by llvm at this time.
1413243830Sdim// Some are for seemingly arbitrary reasons not used: i.e. with signed number
1414243830Sdim// comparison they are used and for unsigned a different pattern is used.
1415243830Sdim// I am pushing upstream from the full mips16 port and it seemed that I needed
1416243830Sdim// these earlier and the mips32 port has these but now I cannot create test
1417243830Sdim// cases that use these patterns. While I sort this all out I will leave these
1418243830Sdim// extra patterns commented out and if I can be sure they are really not used,
1419243830Sdim// I will delete the code. I don't want to check the code in uncommented without
1420243830Sdim// a valid test case. In some cases, the compiler is generating patterns with
1421243830Sdim// setcc instead and earlier I had implemented setcc first so may have masked
1422243830Sdim// the problem. The setcc variants are suboptimal for mips16 so I may wantto
1423243830Sdim// figure out how to enable the brcond patterns or else possibly new
1424243830Sdim// combinations of of brcond and setcc.
1425243830Sdim//
1426243830Sdim//
1427243830Sdim// bcond-seteq
1428243830Sdim//
1429243830Sdimdef: Mips16Pat
1430243830Sdim  <(brcond (i32 (seteq CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1431243830Sdim   (BteqzT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1432243830Sdim  >;
1433243830Sdim
1434243830Sdim
1435243830Sdimdef: Mips16Pat
1436243830Sdim  <(brcond (i32 (seteq CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16),
1437243830Sdim   (BteqzT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$targ16)
1438243830Sdim  >;
1439243830Sdim
1440243830Sdimdef: Mips16Pat
1441243830Sdim  <(brcond (i32 (seteq CPU16Regs:$rx, 0)), bb:$targ16),
1442263508Sdim   (BeqzRxImm16 CPU16Regs:$rx, bb:$targ16)
1443243830Sdim  >;
1444243830Sdim
1445243830Sdim//
1446243830Sdim// bcond-setgt (do we need to have this pair of setlt, setgt??)
1447243830Sdim//
1448243830Sdimdef: Mips16Pat
1449243830Sdim  <(brcond (i32 (setgt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1450243830Sdim   (BtnezT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1451243830Sdim  >;
1452243830Sdim
1453243830Sdim//
1454243830Sdim// bcond-setge
1455243830Sdim//
1456243830Sdimdef: Mips16Pat
1457243830Sdim  <(brcond (i32 (setge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1458243830Sdim   (BteqzT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1459243830Sdim  >;
1460243830Sdim
1461243830Sdim//
1462243830Sdim// never called because compiler transforms a >= k to a > (k-1)
1463243830Sdimdef: Mips16Pat
1464243830Sdim  <(brcond (i32 (setge CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16),
1465243830Sdim   (BteqzT8SltiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$imm16)
1466243830Sdim  >;
1467243830Sdim
1468243830Sdim//
1469243830Sdim// bcond-setlt
1470243830Sdim//
1471243830Sdimdef: Mips16Pat
1472243830Sdim  <(brcond (i32 (setlt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1473243830Sdim   (BtnezT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1474243830Sdim  >;
1475243830Sdim
1476243830Sdimdef: Mips16Pat
1477243830Sdim  <(brcond (i32 (setlt CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16),
1478243830Sdim   (BtnezT8SltiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$imm16)
1479243830Sdim  >;
1480243830Sdim
1481243830Sdim//
1482243830Sdim// bcond-setle
1483243830Sdim//
1484243830Sdimdef: Mips16Pat
1485243830Sdim  <(brcond (i32 (setle CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1486243830Sdim   (BteqzT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1487243830Sdim  >;
1488243830Sdim
1489243830Sdim//
1490243830Sdim// bcond-setne
1491243830Sdim//
1492243830Sdimdef: Mips16Pat
1493243830Sdim  <(brcond (i32 (setne CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1494243830Sdim   (BtnezT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1495243830Sdim  >;
1496243830Sdim
1497243830Sdimdef: Mips16Pat
1498243830Sdim  <(brcond (i32 (setne CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16),
1499243830Sdim   (BtnezT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm,  bb:$targ16)
1500243830Sdim  >;
1501243830Sdim
1502243830Sdimdef: Mips16Pat
1503243830Sdim  <(brcond (i32 (setne CPU16Regs:$rx, 0)), bb:$targ16),
1504263508Sdim   (BnezRxImm16 CPU16Regs:$rx, bb:$targ16)
1505243830Sdim  >;
1506243830Sdim
1507243830Sdim//
1508243830Sdim// This needs to be there but I forget which code will generate it
1509243830Sdim//
1510243830Sdimdef: Mips16Pat
1511243830Sdim  <(brcond CPU16Regs:$rx, bb:$targ16),
1512263508Sdim   (BnezRxImm16 CPU16Regs:$rx, bb:$targ16)
1513243830Sdim  >;
1514243830Sdim
1515243830Sdim//
1516243830Sdim
1517243830Sdim//
1518243830Sdim// bcond-setugt
1519243830Sdim//
1520243830Sdim//def: Mips16Pat
1521243830Sdim//  <(brcond (i32 (setugt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1522243830Sdim//   (BtnezT8SltuX16 CPU16Regs:$ry, CPU16Regs:$rx,  bb:$imm16)
1523243830Sdim//  >;
1524243830Sdim
1525243830Sdim//
1526243830Sdim// bcond-setuge
1527243830Sdim//
1528243830Sdim//def: Mips16Pat
1529243830Sdim//  <(brcond (i32 (setuge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1530243830Sdim//   (BteqzT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1531243830Sdim//  >;
1532243830Sdim
1533243830Sdim
1534243830Sdim//
1535243830Sdim// bcond-setult
1536243830Sdim//
1537243830Sdim//def: Mips16Pat
1538243830Sdim//  <(brcond (i32 (setult CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16),
1539243830Sdim//   (BtnezT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry,  bb:$imm16)
1540243830Sdim//  >;
1541243830Sdim
1542263508Sdimdef: UncondBranch16_pat<br, Bimm16>;
1543243830Sdim
1544239310Sdim// Small immediates
1545243830Sdimdef: Mips16Pat<(i32 immSExt16:$in),
1546243830Sdim               (AddiuRxRxImmX16 (Move32R16 ZERO), immSExt16:$in)>;
1547243830Sdim
1548239310Sdimdef: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
1549239310Sdim
1550243830Sdim//
1551243830Sdim// MipsDivRem
1552243830Sdim//
1553243830Sdimdef: Mips16Pat
1554249423Sdim  <(MipsDivRem16 CPU16Regs:$rx, CPU16Regs:$ry),
1555243830Sdim   (DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
1556243830Sdim
1557243830Sdim//
1558243830Sdim// MipsDivRemU
1559243830Sdim//
1560243830Sdimdef: Mips16Pat
1561249423Sdim  <(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry),
1562243830Sdim   (DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
1563243830Sdim
1564243830Sdim//  signed a,b
1565243830Sdim//  x = (a>=b)?x:y
1566243830Sdim//
1567243830Sdim//  if !(a < b) x = y
1568243830Sdim//
1569243830Sdimdef : Mips16Pat<(select (i32 (setge CPU16Regs:$a, CPU16Regs:$b)),
1570243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1571243830Sdim                (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y,
1572243830Sdim                 CPU16Regs:$a, CPU16Regs:$b)>;
1573243830Sdim
1574243830Sdim//  signed a,b
1575243830Sdim//  x = (a>b)?x:y
1576243830Sdim//
1577243830Sdim//  if  (b < a) x = y
1578243830Sdim//
1579243830Sdimdef : Mips16Pat<(select (i32 (setgt CPU16Regs:$a, CPU16Regs:$b)),
1580243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1581243830Sdim                (SelTBtneZSlt CPU16Regs:$x, CPU16Regs:$y,
1582243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1583243830Sdim
1584243830Sdim// unsigned a,b
1585243830Sdim// x = (a>=b)?x:y
1586243830Sdim//
1587243830Sdim// if !(a < b) x = y;
1588243830Sdim//
1589243830Sdimdef : Mips16Pat<
1590243830Sdim  (select (i32 (setuge CPU16Regs:$a, CPU16Regs:$b)),
1591243830Sdim   CPU16Regs:$x, CPU16Regs:$y),
1592243830Sdim  (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y,
1593243830Sdim   CPU16Regs:$a, CPU16Regs:$b)>;
1594243830Sdim
1595243830Sdim//  unsigned a,b
1596243830Sdim//  x = (a>b)?x:y
1597243830Sdim//
1598243830Sdim//  if (b < a) x = y
1599243830Sdim//
1600243830Sdimdef : Mips16Pat<(select (i32 (setugt CPU16Regs:$a, CPU16Regs:$b)),
1601243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1602243830Sdim                (SelTBtneZSltu CPU16Regs:$x, CPU16Regs:$y,
1603243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1604243830Sdim
1605243830Sdim// signed
1606243830Sdim// x = (a >= k)?x:y
1607243830Sdim// due to an llvm optimization, i don't think that this will ever
1608243830Sdim// be used. This is transformed into x = (a > k-1)?x:y
1609243830Sdim//
1610243830Sdim//
1611243830Sdim
1612243830Sdim//def : Mips16Pat<
1613243830Sdim//  (select (i32 (setge CPU16Regs:$lhs, immSExt16:$rhs)),
1614243830Sdim//   CPU16Regs:$T, CPU16Regs:$F),
1615243830Sdim//  (SelTBteqZSlti CPU16Regs:$T, CPU16Regs:$F,
1616243830Sdim//   CPU16Regs:$lhs, immSExt16:$rhs)>;
1617243830Sdim
1618243830Sdim//def : Mips16Pat<
1619243830Sdim//  (select (i32 (setuge CPU16Regs:$lhs, immSExt16:$rhs)),
1620243830Sdim//   CPU16Regs:$T, CPU16Regs:$F),
1621243830Sdim//  (SelTBteqZSltiu CPU16Regs:$T, CPU16Regs:$F,
1622243830Sdim//   CPU16Regs:$lhs, immSExt16:$rhs)>;
1623243830Sdim
1624243830Sdim// signed
1625243830Sdim// x = (a < k)?x:y
1626243830Sdim//
1627243830Sdim// if !(a < k) x = y;
1628243830Sdim//
1629243830Sdimdef : Mips16Pat<
1630243830Sdim  (select (i32 (setlt CPU16Regs:$a, immSExt16:$b)),
1631243830Sdim   CPU16Regs:$x, CPU16Regs:$y),
1632243830Sdim  (SelTBtneZSlti CPU16Regs:$x, CPU16Regs:$y,
1633243830Sdim   CPU16Regs:$a, immSExt16:$b)>;
1634243830Sdim
1635243830Sdim
1636243830Sdim//
1637243830Sdim//
1638243830Sdim// signed
1639243830Sdim// x = (a <= b)? x : y
1640243830Sdim//
1641243830Sdim// if  (b < a) x = y
1642243830Sdim//
1643243830Sdimdef : Mips16Pat<(select (i32 (setle CPU16Regs:$a, CPU16Regs:$b)),
1644243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1645243830Sdim                (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y,
1646243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1647243830Sdim
1648243830Sdim//
1649243830Sdim// unnsigned
1650243830Sdim// x = (a <= b)? x : y
1651243830Sdim//
1652243830Sdim// if  (b < a) x = y
1653243830Sdim//
1654243830Sdimdef : Mips16Pat<(select (i32 (setule CPU16Regs:$a, CPU16Regs:$b)),
1655243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1656243830Sdim                (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y,
1657243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1658243830Sdim
1659243830Sdim//
1660243830Sdim// signed/unsigned
1661243830Sdim// x = (a == b)? x : y
1662243830Sdim//
1663243830Sdim// if (a != b) x = y
1664243830Sdim//
1665243830Sdimdef : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, CPU16Regs:$b)),
1666243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1667243830Sdim                (SelTBteqZCmp CPU16Regs:$x, CPU16Regs:$y,
1668243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1669243830Sdim
1670243830Sdim//
1671243830Sdim// signed/unsigned
1672243830Sdim// x = (a == 0)? x : y
1673243830Sdim//
1674243830Sdim// if (a != 0) x = y
1675243830Sdim//
1676243830Sdimdef : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, 0)),
1677243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1678243830Sdim                (SelBeqZ CPU16Regs:$x, CPU16Regs:$y,
1679243830Sdim                 CPU16Regs:$a)>;
1680243830Sdim
1681243830Sdim
1682243830Sdim//
1683243830Sdim// signed/unsigned
1684243830Sdim// x = (a == k)? x : y
1685243830Sdim//
1686243830Sdim// if (a != k) x = y
1687243830Sdim//
1688243830Sdimdef : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, immZExt16:$k)),
1689243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1690243830Sdim                (SelTBteqZCmpi CPU16Regs:$x, CPU16Regs:$y,
1691243830Sdim                 CPU16Regs:$a, immZExt16:$k)>;
1692243830Sdim
1693243830Sdim
1694243830Sdim//
1695243830Sdim// signed/unsigned
1696243830Sdim// x = (a != b)? x : y
1697243830Sdim//
1698243830Sdim// if (a == b) x = y
1699243830Sdim//
1700243830Sdim//
1701243830Sdimdef : Mips16Pat<(select (i32 (setne CPU16Regs:$a, CPU16Regs:$b)),
1702243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1703243830Sdim                (SelTBtneZCmp CPU16Regs:$x, CPU16Regs:$y,
1704243830Sdim                 CPU16Regs:$b, CPU16Regs:$a)>;
1705243830Sdim
1706243830Sdim//
1707243830Sdim// signed/unsigned
1708243830Sdim// x = (a != 0)? x : y
1709243830Sdim//
1710243830Sdim// if (a == 0) x = y
1711243830Sdim//
1712243830Sdimdef : Mips16Pat<(select (i32 (setne CPU16Regs:$a, 0)),
1713243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1714243830Sdim                (SelBneZ CPU16Regs:$x, CPU16Regs:$y,
1715243830Sdim                 CPU16Regs:$a)>;
1716243830Sdim
1717243830Sdim// signed/unsigned
1718243830Sdim// x = (a)? x : y
1719243830Sdim//
1720243830Sdim// if (!a) x = y
1721243830Sdim//
1722243830Sdimdef : Mips16Pat<(select  CPU16Regs:$a,
1723243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1724243830Sdim      (SelBneZ CPU16Regs:$x, CPU16Regs:$y,
1725243830Sdim       CPU16Regs:$a)>;
1726243830Sdim
1727243830Sdim
1728243830Sdim//
1729243830Sdim// signed/unsigned
1730243830Sdim// x = (a != k)? x : y
1731243830Sdim//
1732243830Sdim// if (a == k) x = y
1733243830Sdim//
1734243830Sdimdef : Mips16Pat<(select (i32 (setne CPU16Regs:$a, immZExt16:$k)),
1735243830Sdim                 CPU16Regs:$x, CPU16Regs:$y),
1736243830Sdim                (SelTBtneZCmpi CPU16Regs:$x, CPU16Regs:$y,
1737243830Sdim                 CPU16Regs:$a, immZExt16:$k)>;
1738243830Sdim
1739243830Sdim//
1740243830Sdim// When writing C code to test setxx these patterns,
1741243830Sdim// some will be transformed into
1742243830Sdim// other things. So we test using C code but using -O3 and -O0
1743243830Sdim//
1744243830Sdim// seteq
1745243830Sdim//
1746243830Sdimdef : Mips16Pat
1747243830Sdim  <(seteq CPU16Regs:$lhs,CPU16Regs:$rhs),
1748243830Sdim   (SltiuCCRxImmX16 (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs), 1)>;
1749243830Sdim
1750243830Sdimdef : Mips16Pat
1751243830Sdim  <(seteq CPU16Regs:$lhs, 0),
1752243830Sdim   (SltiuCCRxImmX16 CPU16Regs:$lhs, 1)>;
1753243830Sdim
1754243830Sdim
1755243830Sdim//
1756243830Sdim// setge
1757243830Sdim//
1758243830Sdim
1759243830Sdimdef: Mips16Pat
1760243830Sdim  <(setge CPU16Regs:$lhs, CPU16Regs:$rhs),
1761243830Sdim   (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs),
1762243830Sdim   (LiRxImmX16 1))>;
1763243830Sdim
1764243830Sdim//
1765243830Sdim// For constants, llvm transforms this to:
1766243830Sdim// x > (k -1) and then reverses the operands to use setlt. So this pattern
1767243830Sdim// is not used now by the compiler. (Presumably checking that k-1 does not
1768243830Sdim// overflow). The compiler never uses this at a the current time, due to
1769243830Sdim// other optimizations.
1770243830Sdim//
1771243830Sdim//def: Mips16Pat
1772243830Sdim//  <(setge CPU16Regs:$lhs, immSExt16:$rhs),
1773243830Sdim//   (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, immSExt16:$rhs),
1774243830Sdim//   (LiRxImmX16 1))>;
1775243830Sdim
1776243830Sdim// This catches the x >= -32768 case by transforming it to  x > -32769
1777243830Sdim//
1778243830Sdimdef: Mips16Pat
1779243830Sdim  <(setgt CPU16Regs:$lhs, -32769),
1780243830Sdim   (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, -32768),
1781243830Sdim   (LiRxImmX16 1))>;
1782243830Sdim
1783243830Sdim//
1784243830Sdim// setgt
1785243830Sdim//
1786243830Sdim//
1787243830Sdim
1788243830Sdimdef: Mips16Pat
1789243830Sdim  <(setgt CPU16Regs:$lhs, CPU16Regs:$rhs),
1790243830Sdim   (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>;
1791243830Sdim
1792243830Sdim//
1793243830Sdim// setle
1794243830Sdim//
1795243830Sdimdef: Mips16Pat
1796243830Sdim  <(setle CPU16Regs:$lhs, CPU16Regs:$rhs),
1797249423Sdim   (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImm16 1))>;
1798243830Sdim
1799243830Sdim//
1800243830Sdim// setlt
1801243830Sdim//
1802243830Sdimdef: SetCC_R16<setlt, SltCCRxRy16>;
1803243830Sdim
1804243830Sdimdef: SetCC_I16<setlt, immSExt16, SltiCCRxImmX16>;
1805243830Sdim
1806243830Sdim//
1807243830Sdim// setne
1808243830Sdim//
1809243830Sdimdef : Mips16Pat
1810243830Sdim  <(setne CPU16Regs:$lhs,CPU16Regs:$rhs),
1811243830Sdim   (SltuCCRxRy16 (LiRxImmX16 0),
1812243830Sdim   (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs))>;
1813243830Sdim
1814243830Sdim
1815243830Sdim//
1816243830Sdim// setuge
1817243830Sdim//
1818243830Sdimdef: Mips16Pat
1819243830Sdim  <(setuge CPU16Regs:$lhs, CPU16Regs:$rhs),
1820243830Sdim   (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs),
1821243830Sdim   (LiRxImmX16 1))>;
1822243830Sdim
1823243830Sdim// this pattern will never be used because the compiler will transform
1824243830Sdim// x >= k to x > (k - 1) and then use SLT
1825243830Sdim//
1826243830Sdim//def: Mips16Pat
1827243830Sdim//  <(setuge CPU16Regs:$lhs, immZExt16:$rhs),
1828243830Sdim//   (XorRxRxRy16 (SltiuCCRxImmX16 CPU16Regs:$lhs, immZExt16:$rhs),
1829243830Sdim//   (LiRxImmX16 1))>;
1830243830Sdim
1831243830Sdim//
1832243830Sdim// setugt
1833243830Sdim//
1834243830Sdimdef: Mips16Pat
1835243830Sdim  <(setugt CPU16Regs:$lhs, CPU16Regs:$rhs),
1836243830Sdim   (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>;
1837243830Sdim
1838243830Sdim//
1839243830Sdim// setule
1840243830Sdim//
1841243830Sdimdef: Mips16Pat
1842243830Sdim  <(setule CPU16Regs:$lhs, CPU16Regs:$rhs),
1843243830Sdim   (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImmX16 1))>;
1844243830Sdim
1845243830Sdim//
1846243830Sdim// setult
1847243830Sdim//
1848243830Sdimdef: SetCC_R16<setult, SltuCCRxRy16>;
1849243830Sdim
1850243830Sdimdef: SetCC_I16<setult, immSExt16, SltiuCCRxImmX16>;
1851243830Sdim
1852239310Sdimdef: Mips16Pat<(add CPU16Regs:$hi, (MipsLo tglobaladdr:$lo)),
1853239310Sdim               (AddiuRxRxImmX16 CPU16Regs:$hi, tglobaladdr:$lo)>;
1854243830Sdim
1855243830Sdim// hi/lo relocs
1856263508Sdimdef : Mips16Pat<(MipsHi tblockaddress:$in),
1857263508Sdim                (SllX16 (LiRxImmX16 tblockaddress:$in), 16)>;
1858249423Sdimdef : Mips16Pat<(MipsHi tglobaladdr:$in),
1859249423Sdim                (SllX16 (LiRxImmX16 tglobaladdr:$in), 16)>;
1860249423Sdimdef : Mips16Pat<(MipsHi tjumptable:$in),
1861249423Sdim                (SllX16 (LiRxImmX16 tjumptable:$in), 16)>;
1862249423Sdimdef : Mips16Pat<(MipsHi tglobaltlsaddr:$in),
1863243830Sdim                (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>;
1864243830Sdim
1865263508Sdimdef : Mips16Pat<(MipsLo tblockaddress:$in), (LiRxImmX16 tblockaddress:$in)>;
1866263508Sdim
1867243830Sdim// wrapper_pic
1868243830Sdimclass Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
1869243830Sdim  Mips16Pat<(MipsWrapper RC:$gp, node:$in),
1870243830Sdim            (ADDiuOp RC:$gp, node:$in)>;
1871243830Sdim
1872243830Sdim
1873243830Sdimdef : Wrapper16Pat<tglobaladdr, AddiuRxRxImmX16, CPU16Regs>;
1874243830Sdimdef : Wrapper16Pat<tglobaltlsaddr, AddiuRxRxImmX16, CPU16Regs>;
1875243830Sdim
1876243830Sdimdef : Mips16Pat<(i32 (extloadi8   addr16:$src)),
1877243830Sdim                (LbuRxRyOffMemX16  addr16:$src)>;
1878243830Sdimdef : Mips16Pat<(i32 (extloadi16  addr16:$src)),
1879249423Sdim                (LhuRxRyOffMemX16  addr16:$src)>;
1880263508Sdim
1881263508Sdimdef: Mips16Pat<(trap), (Break16)>;
1882263508Sdim
1883263508Sdimdef : Mips16Pat<(sext_inreg CPU16Regs:$val, i8),
1884263508Sdim                (SebRx16 CPU16Regs:$val)>;
1885263508Sdim
1886263508Sdimdef : Mips16Pat<(sext_inreg CPU16Regs:$val, i16),
1887263508Sdim                (SehRx16 CPU16Regs:$val)>;
1888263508Sdim
1889263508Sdimdef GotPrologue16:   
1890263508Sdim  MipsPseudo16<
1891263508Sdim    (outs CPU16Regs:$rh, CPU16Regs:$rl),
1892263508Sdim    (ins simm16:$immHi, simm16:$immLo),
1893263508Sdim    ".align 2\n\tli\t$rh, $immHi\n\taddiu\t$rl, $$pc, $immLo\n ",[]> ;
1894263508Sdim
1895263508Sdim// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
1896263508Sdimdef cpinst_operand : Operand<i32> {
1897263508Sdim  // let PrintMethod = "printCPInstOperand";
1898263508Sdim}
1899263508Sdim
1900263508Sdim// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
1901263508Sdim// the function.  The first operand is the ID# for this instruction, the second
1902263508Sdim// is the index into the MachineConstantPool that this is, the third is the
1903263508Sdim// size in bytes of this constant pool entry.
1904263508Sdim//
1905263508Sdimlet neverHasSideEffects = 1, isNotDuplicable = 1 in
1906263508Sdimdef CONSTPOOL_ENTRY :
1907263508SdimMipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx,
1908263508Sdim                      i32imm:$size), "foo", []>;
1909263508Sdim
1910