54f2b337e035f1654f4953105d6e3a17e3b7ee43
[oota-llvm.git] / lib / Target / PIC16 / PIC16InstrInfo.td
1 //===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source 
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file describes the PIC16 instructions in TableGen format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 // PIC16 Specific Type Constraints.
16 //===----------------------------------------------------------------------===//
17 class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
18 class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
19
20 //===----------------------------------------------------------------------===//
21 // PIC16 Specific Type Profiles.
22 //===----------------------------------------------------------------------===//
23
24 // Generic type profiles for i8/i16 unary/binary operations.
25 // Taking one i8 or i16 and producing void.
26 def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
27 def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
28
29 // Taking one value and producing an output of same type.
30 def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
31 def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
32
33 // Taking two values and producing an output of same type.
34 def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
35 def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>, 
36                                        SDTCisI16<2>]>;
37
38 // Node specific type profiles.
39 def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>, 
40                                           SDTCisI8<2>, SDTCisI8<3>]>;
41
42 def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>, 
43                                           SDTCisI8<2>, SDTCisI8<3>]>;
44
45 def SDT_PIC16Connect : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>,
46                                             SDTCisI8<2>]>;
47
48 // PIC16ISD::CALL type prorile
49 def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
50 def SDT_PIC16callw : SDTypeProfile<1, -1, [SDTCisInt<0>]>;
51
52 // PIC16ISD::BRCOND
53 def SDT_PIC16Brcond: SDTypeProfile<0, 2, 
54                                    [SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
55
56 // PIC16ISD::BRCOND
57 def SDT_PIC16Selecticc: SDTypeProfile<1, 3, 
58                                    [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
59                                     SDTCisI8<3>]>;
60
61 //===----------------------------------------------------------------------===//
62 // PIC16 addressing modes matching via DAG.
63 //===----------------------------------------------------------------------===//
64 def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
65
66 //===----------------------------------------------------------------------===//
67 // PIC16 Specific Node Definitions.
68 //===----------------------------------------------------------------------===//
69 def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
70                                 [SDNPHasChain, SDNPOutFlag]>;
71 def PIC16callseq_end   : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp, 
72                                 [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
73
74 // Low 8-bits of GlobalAddress.
75 def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8BinOp>;  
76
77 // High 8-bits of GlobalAddress.
78 def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8BinOp>;
79
80 // The MTHI and MTLO nodes are used only to match them in the incoming 
81 // DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
82 // These nodes are not used for defining any instructions.
83 def MTLO     : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
84 def MTHI     : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
85 def MTPCLATH : SDNode<"PIC16ISD::MTPCLATH", SDTI8UnaryOp>;
86
87 // Node to generate Bank Select for a GlobalAddress.
88 def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
89
90 // Node to match a direct store operation.
91 def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
92 def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store, 
93                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
94
95 // Node to match a direct load operation.
96 def PIC16Load  : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
97 def PIC16LdArg  : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
98 def PIC16LdWF  : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load, 
99                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
100 def PIC16Connect: SDNode<"PIC16ISD::PIC16Connect", SDT_PIC16Connect, []>;
101
102 // Node to match PIC16 call
103 def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
104                               [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
105 def PIC16callw : SDNode<"PIC16ISD::CALLW", SDT_PIC16callw,
106                               [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
107
108 // Node to match a comparison instruction.
109 def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
110
111 // Node to match a conditional branch.
112 def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond, 
113                          [SDNPHasChain, SDNPInFlag]>;
114
115 def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc, 
116                          [SDNPInFlag]>;
117
118 //===----------------------------------------------------------------------===//
119 // PIC16 Operand Definitions.
120 //===----------------------------------------------------------------------===//
121 def i8mem : Operand<i8>;
122 def brtarget: Operand<OtherVT>;
123
124 // Operand for printing out a condition code.
125 let PrintMethod = "printCCOperand" in
126   def CCOp : Operand<i8>;
127
128 include "PIC16InstrFormats.td"
129
130 //===----------------------------------------------------------------------===//
131 // PIC16 Common Classes.
132 //===----------------------------------------------------------------------===//
133
134 // W = W Op F : Load the value from F and do Op to W.
135 let isTwoAddress = 1, mayLoad = 1 in
136 class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
137   ByteFormat<OpCode, (outs GPR:$dst),
138              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
139               !strconcat(OpcStr, " $ptrlo + $offset, W"),
140              [(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
141                                              (i8 imm:$ptrhi),
142                                              (i8 imm:$offset))))]>;
143
144 // F = F Op W : Load the value from F, do op with W and store in F.
145 // This insn class is not marked as TwoAddress because the reg is
146 // being used as a source operand only. (Remember a TwoAddress insn
147 // needs a copyRegToReg.)
148 let mayStore = 1 in
149 class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
150   ByteFormat<OpCode, (outs),
151              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
152               !strconcat(OpcStr, " $ptrlo + $offset"),
153              [(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
154                                              (i8 imm:$ptrhi),
155                                              (i8 imm:$offset))),
156                                              diraddr:$ptrlo,
157                                              (i8 imm:$ptrhi), (i8 imm:$offset)
158                                              )]>;
159
160 // W = W Op L : Do Op of L with W and place result in W.
161 let isTwoAddress = 1 in
162 class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
163   LiteralFormat<opcode, (outs GPR:$dst),
164                 (ins GPR:$src, i8imm:$literal),
165                 !strconcat(OpcStr, " $literal"),
166                 [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
167
168 //===----------------------------------------------------------------------===//
169 // PIC16 Instructions.
170 //===----------------------------------------------------------------------===//
171
172 // Pseudo-instructions.
173 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
174                        "!ADJCALLSTACKDOWN $amt",
175                        [(PIC16callseq_start imm:$amt)]>;
176
177 def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
178                        "!ADJCALLSTACKUP $amt", 
179                        [(PIC16callseq_end imm:$amt)]>;
180
181 //-----------------------------------
182 // Vaious movlw insn patterns.
183 //-----------------------------------
184 let isReMaterializable = 1 in {
185 // Move 8-bit literal to W.
186 def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
187                       "movlw $src",
188                       [(set GPR:$dst, (i8 imm:$src))]>;
189
190 // Move a Lo(TGA) to W.
191 def movlw_lo_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
192                       "movlw LOW(${src} + ${src2})",
193                       [(set GPR:$dst, (PIC16Lo tglobaladdr:$src, imm:$src2 ))]>;
194
195 // Move a Lo(TES) to W.
196 def movlw_lo_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
197                       "movlw LOW(${src} + ${src2})",
198                       [(set GPR:$dst, (PIC16Lo texternalsym:$src, imm:$src2 ))]>;
199
200 // Move a Hi(TGA) to W.
201 def movlw_hi_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
202                       "movlw HIGH(${src} + ${src2})",
203                       [(set GPR:$dst, (PIC16Hi tglobaladdr:$src, imm:$src2))]>;
204
205 // Move a Hi(TES) to W.
206 def movlw_hi_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
207                       "movlw HIGH(${src} + ${src2})",
208                       [(set GPR:$dst, (PIC16Hi texternalsym:$src, imm:$src2))]>;
209 }
210
211 //-------------------
212 // FSR setting insns. 
213 //-------------------
214 // These insns are matched via a DAG replacement pattern.
215 def set_fsrlo:
216   ByteFormat<0, (outs FSR16:$fsr), 
217              (ins GPR:$val),
218              "movwf ${fsr}L",
219              []>;
220
221 let isTwoAddress = 1 in
222 def set_fsrhi:
223   ByteFormat<0, (outs FSR16:$dst), 
224              (ins FSR16:$src, GPR:$val),
225              "movwf ${dst}H",
226              []>;
227
228 def set_pclath:
229   ByteFormat<0, (outs PCLATHR:$dst), 
230              (ins GPR:$val),
231              "movwf ${dst}",
232              [(set PCLATHR:$dst , (MTPCLATH GPR:$val))]>;
233
234 //----------------------------
235 // copyRegToReg 
236 // copyRegToReg insns. These are dummy. They should always be deleted
237 // by the optimizer and never be present in the final generated code.
238 // if they are, then we have to write correct macros for these insns.
239 //----------------------------
240 def copy_fsr:
241   Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
242
243 def copy_w:
244   Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
245
246 class SAVE_FSR<string OpcStr>:
247   Pseudo<(outs), 
248          (ins FSR16:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), 
249          !strconcat(OpcStr, " $ptrlo, $offset"),
250          []>; 
251  
252 def save_fsr0: SAVE_FSR<"save_fsr0">;
253 def save_fsr1: SAVE_FSR<"save_fsr1">;
254
255 class RESTORE_FSR<string OpcStr>:
256   Pseudo<(outs FSR16:$dst), 
257          (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), 
258          !strconcat(OpcStr, " $ptrlo, $offset"),
259          []>; 
260
261 def restore_fsr0: RESTORE_FSR<"restore_fsr0">;
262 def restore_fsr1: RESTORE_FSR<"restore_fsr1">;
263
264 //--------------------------
265 // Store to memory
266 //-------------------------
267
268 // Direct store.
269 // Input operands are: val = W, ptrlo = GA, offset = offset, ptrhi = banksel.
270 let mayStore = 1 in
271 class MOVWF_INSN<bits<6> OpCode, SDNode OpNodeDest, SDNode Op>:
272   ByteFormat<0, (outs), 
273              (ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
274              "movwf ${ptrlo} + ${offset}",
275              [(Op GPR:$val, OpNodeDest:$ptrlo, (i8 imm:$ptrhi), 
276                (i8 imm:$offset))]>;
277
278 // Store W to a Global Address.
279 def movwf : MOVWF_INSN<0, tglobaladdr, PIC16Store>;
280
281 // Store W to an External Symobol.
282 def movwf_1 : MOVWF_INSN<0, texternalsym, PIC16Store>;
283
284 // Store with InFlag and OutFlag
285 // This is same as movwf_1 but has a flag. A flag is required to 
286 // order the stores while passing the params to function.
287 def movwf_2 : MOVWF_INSN<0, texternalsym, PIC16StWF>;
288
289 // Indirect store. Matched via a DAG replacement pattern.
290 def store_indirect : 
291   ByteFormat<0, (outs), 
292              (ins GPR:$val, FSR16:$fsr, i8imm:$offset),
293              "movwi $offset[$fsr]",
294              []>;
295
296 //----------------------------
297 // Load from memory
298 //----------------------------
299 // Direct load.
300 // Input Operands are: ptrlo = GA, offset = offset, ptrhi = banksel.
301 // Output: dst = W
302 let Defs = [STATUS], mayLoad = 1 in
303 class MOVF_INSN<bits<6> OpCode, SDNode OpNodeSrc, SDNode Op>:
304   ByteFormat<0, (outs GPR:$dst), 
305              (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
306              "movf ${ptrlo} + ${offset}, W",
307              [(set GPR:$dst, 
308                (Op OpNodeSrc:$ptrlo, (i8 imm:$ptrhi),
309                (i8 imm:$offset)))]>;
310
311 // Load from a GA.
312 def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
313
314 // Load from an ES.
315 def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
316 def movf_1_1 : MOVF_INSN<0, texternalsym, PIC16LdArg>;
317
318 // Load with InFlag and OutFlag
319 // This is same as movf_1 but has a flag. A flag is required to 
320 // order the loads while copying the return value of a function.
321 def movf_2 : MOVF_INSN<0, texternalsym, PIC16LdWF>;
322
323 // Indirect load. Matched via a DAG replacement pattern.
324 def load_indirect : 
325   ByteFormat<0, (outs GPR:$dst), 
326              (ins FSR16:$fsr, i8imm:$offset),
327              "moviw $offset[$fsr]",
328              []>;
329
330 //-------------------------
331 // Bitwise operations patterns
332 //--------------------------
333 // W = W op [F]
334 let Defs = [STATUS] in {
335 def OrFW :  BinOpFW<0, "iorwf", or>;
336 def XOrFW : BinOpFW<0, "xorwf", xor>;
337 def AndFW : BinOpFW<0, "andwf", and>;
338
339 // F = W op [F]
340 def OrWF :  BinOpWF<0, "iorwf", or>;
341 def XOrWF : BinOpWF<0, "xorwf", xor>;
342 def AndWF : BinOpWF<0, "andwf", and>;
343
344 //-------------------------
345 // Various add/sub patterns.
346 //-------------------------
347
348 // W = W + [F]
349 def addfw_1: BinOpFW<0, "addwf", add>;
350 def addfw_2: BinOpFW<0, "addwf", addc>;
351
352 let Uses = [STATUS] in
353 def addfwc: BinOpFW<0, "addwfc", adde>;  // With Carry.
354
355 // F = W + [F]
356 def addwf_1: BinOpWF<0, "addwf", add>;
357 def addwf_2: BinOpWF<0, "addwf", addc>;
358 let Uses = [STATUS] in
359 def addwfc: BinOpWF<0, "addwfc", adde>;  // With Carry.
360 }
361
362 // W -= [F] ; load from F and sub the value from W.
363 let isTwoAddress = 1, mayLoad = 1 in
364 class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
365   ByteFormat<OpCode, (outs GPR:$dst),
366              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
367               !strconcat(OpcStr, " $ptrlo + $offset, W"),
368              [(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
369                                       (i8 imm:$ptrhi), (i8 imm:$offset)),
370                                       GPR:$src))]>;
371 let Defs = [STATUS] in {
372 def subfw_1: SUBFW<0, "subwf", sub>;
373 def subfw_2: SUBFW<0, "subwf", subc>;
374
375 let Uses = [STATUS] in
376 def subfwb: SUBFW<0, "subwfb", sube>;  // With Borrow.
377
378 }
379 let Defs = [STATUS], isTerminator = 1 in
380 def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
381
382 // [F] -= W ; 
383 let mayStore = 1 in
384 class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
385   ByteFormat<OpCode, (outs),
386              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
387               !strconcat(OpcStr, " $ptrlo + $offset"),
388              [(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
389                                       (i8 imm:$ptrhi), (i8 imm:$offset)),
390                                       GPR:$src), diraddr:$ptrlo,
391                                       (i8 imm:$ptrhi), (i8 imm:$offset))]>;
392
393 let Defs = [STATUS] in {
394 def subwf_1: SUBWF<0, "subwf", sub>;
395 def subwf_2: SUBWF<0, "subwf", subc>;
396
397 let Uses = [STATUS] in
398   def subwfb: SUBWF<0, "subwfb", sube>;  // With Borrow.
399
400 def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
401 }
402
403 // addlw 
404 let Defs = [STATUS] in {
405 def addlw_1 : BinOpLW<0, "addlw", add>;
406 def addlw_2 : BinOpLW<0, "addlw", addc>;
407
408 let Uses = [STATUS] in
409 def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
410
411 // bitwise operations involving a literal and w.
412 def andlw : BinOpLW<0, "andlw", and>;
413 def xorlw : BinOpLW<0, "xorlw", xor>;
414 def orlw  : BinOpLW<0, "iorlw", or>;
415 }
416
417 // sublw 
418 // W = C - W ; sub W from literal. (Without borrow).
419 let isTwoAddress = 1 in
420 class SUBLW<bits<6> opcode, SDNode OpNode> :
421   LiteralFormat<opcode, (outs GPR:$dst),
422                 (ins GPR:$src, i8imm:$literal),
423                 "sublw $literal",
424                 [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
425
426 let Defs = [STATUS] in {
427 def sublw_1 : SUBLW<0, sub>;
428 def sublw_2 : SUBLW<0, subc>;
429 }
430 let Defs = [STATUS], isTerminator = 1 in 
431 def sublw_cc : SUBLW<0, PIC16Subcc>;
432
433 // Call instruction.
434 let isCall = 1,
435     Defs = [W, FSR0, FSR1] in {
436     def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
437             //"call ${func} + 2",
438             "call ${func}",
439             [(PIC16call diraddr:$func)]>;
440 }
441
442 let isCall = 1,
443     Defs = [W, FSR0, FSR1] in {
444     def CALL_1: LiteralFormat<0x1, (outs), (ins GPR:$func, PCLATHR:$pc),
445             "callw",
446             [(PIC16call (PIC16Connect GPR:$func, PCLATHR:$pc))]>;
447 }
448
449 let isCall = 1,
450     Defs = [FSR0, FSR1] in {
451     def CALLW: LiteralFormat<0x1, (outs GPR:$dest), 
452                                   (ins GPR:$func, PCLATHR:$pc),
453             "callw",
454             [(set GPR:$dest, (PIC16callw (PIC16Connect GPR:$func, PCLATHR:$pc)))]>;
455 }
456
457 let Uses = [STATUS], isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
458 def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
459                           "b$cc $dst",
460                           [(PIC16Brcond bb:$dst, imm:$cc)]>;
461
462 // Unconditional branch.
463 let isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
464 def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
465                           "goto $dst",
466                           [(br bb:$dst)]>;
467
468 // SELECT_CC_* - Used to implement the SELECT_CC DAG operation.  Expanded by the
469 // scheduler into a branch sequence.
470 let usesCustomDAGSchedInserter = 1 in {   // Expanded by the scheduler.
471   def SELECT_CC_Int_ICC
472    : Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
473             "; SELECT_CC_Int_ICC PSEUDO!",
474             [(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
475                                              imm:$Cond))]>;
476 }
477
478
479 // Banksel.
480 def banksel : 
481   Pseudo<(outs),
482          (ins i8mem:$ptr),
483          "banksel $ptr",
484          []>;
485
486 def pagesel : 
487   Pseudo<(outs),
488          (ins i8mem:$ptr),
489          "movlp $ptr",
490          []>;
491
492
493 // Return insn.
494 def Return : 
495   ControlFormat<0, (outs), (ins), "return", [(ret)]>;
496
497 //===----------------------------------------------------------------------===//
498 // PIC16 Replacment Patterns.
499 //===----------------------------------------------------------------------===//
500
501 // Identify an indirect store and select insns for it.
502 def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
503            imm:$offset),
504           (store_indirect GPR:$val, 
505            (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
506            imm:$offset)>;
507
508 def : Pat<(PIC16StWF GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
509            imm:$offset),
510           (store_indirect GPR:$val, 
511            (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
512            imm:$offset)>;
513
514 // Identify an indirect load and select insns for it.
515 def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
516            imm:$offset),
517           (load_indirect  (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
518            imm:$offset)>;
519
520 def : Pat<(PIC16LdWF (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
521            imm:$offset),
522           (load_indirect  (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
523            imm:$offset)>;
524