To convert the StopPoint insn into an assembler directive by ISel, we need to have...
[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 // PIC16ISD::CALL type prorile
46 def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
47
48 // PIC16ISD::BRCOND
49 def SDT_PIC16Brcond: SDTypeProfile<0, 2, 
50                                    [SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
51
52 // PIC16ISD::BRCOND
53 def SDT_PIC16Selecticc: SDTypeProfile<1, 3, 
54                                    [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
55                                     SDTCisI8<3>]>;
56
57 //===----------------------------------------------------------------------===//
58 // PIC16 addressing modes matching via DAG.
59 //===----------------------------------------------------------------------===//
60 def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
61
62 //===----------------------------------------------------------------------===//
63 // PIC16 Specific Node Definitions.
64 //===----------------------------------------------------------------------===//
65 def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
66                                 [SDNPHasChain, SDNPOutFlag]>;
67 def PIC16callseq_end   : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp, 
68                                 [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
69
70 def PIC16StopPoint : SDNode<"PIC16ISD::PIC16StopPoint", SDTI8VoidOp,
71                              [SDNPHasChain]>;
72
73 // Low 8-bits of GlobalAddress.
74 def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;  
75
76 // High 8-bits of GlobalAddress.
77 def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
78
79 // The MTHI and MTLO nodes are used only to match them in the incoming 
80 // DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
81 // These nodes are not used for defining any instructions.
82 def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
83 def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
84
85 // Node to generate Bank Select for a GlobalAddress.
86 def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
87
88 // Node to match a direct store operation.
89 def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
90 def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store, 
91                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
92
93 // Node to match a direct load operation.
94 def PIC16Load  : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
95 def PIC16LdArg  : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
96 def PIC16LdWF  : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load, 
97                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
98
99 // Node to match PIC16 call
100 def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
101                               [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
102
103 // Node to match a comparison instruction.
104 def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
105
106 // Node to match a conditional branch.
107 def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond, 
108                          [SDNPHasChain, SDNPInFlag]>;
109
110 def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc, 
111                          [SDNPInFlag]>;
112
113 //===----------------------------------------------------------------------===//
114 // PIC16 Operand Definitions.
115 //===----------------------------------------------------------------------===//
116 def i8mem : Operand<i8>;
117 def brtarget: Operand<OtherVT>;
118
119 // Operand for printing out a condition code.
120 let PrintMethod = "printCCOperand" in
121   def CCOp : Operand<i8>;
122
123 include "PIC16InstrFormats.td"
124
125 //===----------------------------------------------------------------------===//
126 // PIC16 Common Classes.
127 //===----------------------------------------------------------------------===//
128
129 // W = W Op F : Load the value from F and do Op to W.
130 let isTwoAddress = 1 in
131 class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
132   ByteFormat<OpCode, (outs GPR:$dst),
133              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
134               !strconcat(OpcStr, " $ptrlo + $offset, W"),
135              [(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
136                                              (i8 imm:$ptrhi),
137                                              (i8 imm:$offset))))]>;
138
139 // F = F Op W : Load the value from F, do op with W and store in F.
140 // This insn class is not marked as TwoAddress because the reg is
141 // being used as a source operand only. (Remember a TwoAddress insn
142 // needs a copyRegToReg.)
143 class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
144   ByteFormat<OpCode, (outs),
145              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
146               !strconcat(OpcStr, " $ptrlo + $offset"),
147              [(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
148                                              (i8 imm:$ptrhi),
149                                              (i8 imm:$offset))),
150                                              diraddr:$ptrlo,
151                                              (i8 imm:$ptrhi), (i8 imm:$offset)
152                                              )]>;
153
154 // W = W Op L : Do Op of L with W and place result in W.
155 let isTwoAddress = 1 in
156 class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
157   LiteralFormat<opcode, (outs GPR:$dst),
158                 (ins GPR:$src, i8imm:$literal),
159                 !strconcat(OpcStr, " $literal"),
160                 [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
161
162 //===----------------------------------------------------------------------===//
163 // PIC16 Instructions.
164 //===----------------------------------------------------------------------===//
165
166 def line_directive : ByteFormat<0, (outs), (ins i8imm:$src),
167                                ".line $src",
168                                [(PIC16StopPoint (i8 imm:$src))]>;
169
170 // Pseudo-instructions.
171 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
172                        "!ADJCALLSTACKDOWN $amt",
173                        [(PIC16callseq_start imm:$amt)]>;
174
175 def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
176                        "!ADJCALLSTACKUP $amt", 
177                        [(PIC16callseq_end imm:$amt)]>;
178
179 //-----------------------------------
180 // Vaious movlw insn patterns.
181 //-----------------------------------
182 let isReMaterializable = 1 in {
183 // Move 8-bit literal to W.
184 def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
185                       "movlw $src",
186                       [(set GPR:$dst, (i8 imm:$src))]>;
187
188 // Move a Lo(TGA) to W.
189 def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
190                       "movlw LOW(${src})",
191                       [(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>;
192
193 // Move a Hi(TGA) to W.
194 def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
195                       "movlw HIGH(${src})",
196                       [(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>;
197 }
198
199 //-------------------
200 // FSR setting insns. 
201 //-------------------
202 // These insns are matched via a DAG replacement pattern.
203 def set_fsrlo:
204   ByteFormat<0, (outs FSR16:$fsr), 
205              (ins GPR:$val),
206              "movwf ${fsr}L",
207              []>;
208
209 let isTwoAddress = 1 in
210 def set_fsrhi:
211   ByteFormat<0, (outs FSR16:$dst), 
212              (ins FSR16:$src, GPR:$val),
213              "movwf ${dst}H",
214              []>;
215
216 //----------------------------
217 // copyRegToReg 
218 // copyRegToReg insns. These are dummy. They should always be deleted
219 // by the optimizer and never be present in the final generated code.
220 // if they are, then we have to write correct macros for these insns.
221 //----------------------------
222 def copy_fsr:
223   Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
224
225 def copy_w:
226   Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
227
228 //--------------------------
229 // Store to memory
230 //-------------------------
231
232 // Direct store.
233 // Input operands are: val = W, ptrlo = GA, offset = offset, ptrhi = banksel.
234 class MOVWF_INSN<bits<6> OpCode, SDNode OpNodeDest, SDNode Op>:
235   ByteFormat<0, (outs), 
236              (ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
237              "movwf ${ptrlo} + ${offset}",
238              [(Op GPR:$val, OpNodeDest:$ptrlo, (i8 imm:$ptrhi), 
239                (i8 imm:$offset))]>;
240
241 // Store W to a Global Address.
242 def movwf : MOVWF_INSN<0, tglobaladdr, PIC16Store>;
243
244 // Store W to an External Symobol.
245 def movwf_1 : MOVWF_INSN<0, texternalsym, PIC16Store>;
246
247 // Store with InFlag and OutFlag
248 // This is same as movwf_1 but has a flag. A flag is required to 
249 // order the stores while passing the params to function.
250 def movwf_2 : MOVWF_INSN<0, texternalsym, PIC16StWF>;
251
252 // Indirect store. Matched via a DAG replacement pattern.
253 def store_indirect : 
254   ByteFormat<0, (outs), 
255              (ins GPR:$val, FSR16:$fsr, i8imm:$offset),
256              "movwi $offset[$fsr]",
257              []>;
258
259 //----------------------------
260 // Load from memory
261 //----------------------------
262 // Direct load.
263 // Input Operands are: ptrlo = GA, offset = offset, ptrhi = banksel.
264 // Output: dst = W
265 class MOVF_INSN<bits<6> OpCode, SDNode OpNodeSrc, SDNode Op>:
266   ByteFormat<0, (outs GPR:$dst), 
267              (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
268              "movf ${ptrlo} + ${offset}, W",
269              [(set GPR:$dst, 
270                (Op OpNodeSrc:$ptrlo, (i8 imm:$ptrhi),
271                (i8 imm:$offset)))]>;
272
273 // Load from a GA.
274 def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
275
276 // Load from an ES.
277 def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
278 def movf_1_1 : MOVF_INSN<0, texternalsym, PIC16LdArg>;
279
280 // Load with InFlag and OutFlag
281 // This is same as movf_1 but has a flag. A flag is required to 
282 // order the loads while copying the return value of a function.
283 def movf_2 : MOVF_INSN<0, texternalsym, PIC16LdWF>;
284
285 // Indirect load. Matched via a DAG replacement pattern.
286 def load_indirect : 
287   ByteFormat<0, (outs GPR:$dst), 
288              (ins FSR16:$fsr, i8imm:$offset),
289              "moviw $offset[$fsr]",
290              []>;
291
292 //-------------------------
293 // Bitwise operations patterns
294 //--------------------------
295 // W = W op [F]
296 let Defs = [STATUS] in {
297 def OrFW :  BinOpFW<0, "iorwf", or>;
298 def XOrFW : BinOpFW<0, "xorwf", xor>;
299 def AndFW : BinOpFW<0, "andwf", and>;
300
301 // F = W op [F]
302 def OrWF :  BinOpWF<0, "iorwf", or>;
303 def XOrWF : BinOpWF<0, "xorwf", xor>;
304 def AndWF : BinOpWF<0, "andwf", and>;
305
306 //-------------------------
307 // Various add/sub patterns.
308 //-------------------------
309
310 // W = W + [F]
311 def addfw_1: BinOpFW<0, "addwf", add>;
312 def addfw_2: BinOpFW<0, "addwf", addc>;
313
314 let Uses = [STATUS] in
315 def addfwc: BinOpFW<0, "addwfc", adde>;  // With Carry.
316
317 // F = W + [F]
318 def addwf_1: BinOpWF<0, "addwf", add>;
319 def addwf_2: BinOpWF<0, "addwf", addc>;
320 let Uses = [STATUS] in
321 def addwfc: BinOpWF<0, "addwfc", adde>;  // With Carry.
322 }
323
324 // W -= [F] ; load from F and sub the value from W.
325 let isTwoAddress = 1 in
326 class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
327   ByteFormat<OpCode, (outs GPR:$dst),
328              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
329               !strconcat(OpcStr, " $ptrlo + $offset, W"),
330              [(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
331                                       (i8 imm:$ptrhi), (i8 imm:$offset)),
332                                       GPR:$src))]>;
333 let Defs = [STATUS] in {
334 def subfw_1: SUBFW<0, "subwf", sub>;
335 def subfw_2: SUBFW<0, "subwf", subc>;
336
337 let Uses = [STATUS] in
338 def subfwb: SUBFW<0, "subwfb", sube>;  // With Borrow.
339
340 def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
341 }
342
343 // [F] -= W ; 
344 class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
345   ByteFormat<OpCode, (outs),
346              (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
347               !strconcat(OpcStr, " $ptrlo + $offset"),
348              [(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
349                                       (i8 imm:$ptrhi), (i8 imm:$offset)),
350                                       GPR:$src), diraddr:$ptrlo,
351                                       (i8 imm:$ptrhi), (i8 imm:$offset))]>;
352
353 let Defs = [STATUS] in {
354 def subwf_1: SUBWF<0, "subwf", sub>;
355 def subwf_2: SUBWF<0, "subwf", subc>;
356
357 let Uses = [STATUS] in
358   def subwfb: SUBWF<0, "subwfb", sube>;  // With Borrow.
359
360 def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
361 }
362
363 // addlw 
364 let Defs = [STATUS] in {
365 def addlw_1 : BinOpLW<0, "addlw", add>;
366 def addlw_2 : BinOpLW<0, "addlw", addc>;
367
368 let Uses = [STATUS] in
369 def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
370
371 // bitwise operations involving a literal and w.
372 def andlw : BinOpLW<0, "andlw", and>;
373 def xorlw : BinOpLW<0, "xorlw", xor>;
374 def orlw  : BinOpLW<0, "iorlw", or>;
375 }
376
377 // sublw 
378 // W = C - W ; sub W from literal. (Without borrow).
379 let isTwoAddress = 1 in
380 class SUBLW<bits<6> opcode, SDNode OpNode> :
381   LiteralFormat<opcode, (outs GPR:$dst),
382                 (ins GPR:$src, i8imm:$literal),
383                 "sublw $literal",
384                 [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
385
386 let Defs = [STATUS] in {
387 def sublw_1 : SUBLW<0, sub>;
388 def sublw_2 : SUBLW<0, subc>;
389 def sublw_cc : SUBLW<0, PIC16Subcc>;
390 }
391
392 // Call instruction.
393 let isCall = 1 in {
394     def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
395             "call ${func}",
396             [(PIC16call diraddr:$func)]>;
397 }
398
399 let Uses = [STATUS] in
400 def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
401                           "b$cc $dst",
402                           [(PIC16Brcond bb:$dst, imm:$cc)]>;
403
404 // Unconditional branch.
405 def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
406                           "goto $dst",
407                           [(br bb:$dst)]>;
408
409 // SELECT_CC_* - Used to implement the SELECT_CC DAG operation.  Expanded by the
410 // scheduler into a branch sequence.
411 let usesCustomDAGSchedInserter = 1 in {   // Expanded by the scheduler.
412   def SELECT_CC_Int_ICC
413    : Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
414             "; SELECT_CC_Int_ICC PSEUDO!",
415             [(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
416                                              imm:$Cond))]>;
417 }
418
419
420 // Banksel.
421 let isReMaterializable = 1 in {
422 def banksel : 
423   Pseudo<(outs BSR:$dst),
424          (ins i8mem:$ptr),
425          "banksel $ptr",
426          [(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
427 }
428
429 // Return insn.
430 def Return : 
431   ControlFormat<0, (outs), (ins), "return", [(ret)]>;
432                       
433 //===----------------------------------------------------------------------===//
434 // PIC16 Replacment Patterns.
435 //===----------------------------------------------------------------------===//
436
437 // Identify an indirect store and select insns for it.
438 def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
439            imm:$offset),
440           (store_indirect GPR:$val, 
441            (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
442            imm:$offset)>;
443
444 // Identify an indirect load and select insns for it.
445 def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
446            imm:$offset),
447           (load_indirect  (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
448            imm:$offset)>;
449