1 //===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file describes the PIC16 instructions in TableGen format.
12 //===----------------------------------------------------------------------===//
14 //===----------------------------------------------------------------------===//
15 // PIC16 Specific Type Constraints.
16 //===----------------------------------------------------------------------===//
17 class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
18 class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
20 //===----------------------------------------------------------------------===//
21 // PIC16 Specific Type Profiles.
22 //===----------------------------------------------------------------------===//
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>]>;
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>]>;
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>,
38 // Node specific type profiles.
39 def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
40 SDTCisI8<2>, SDTCisI8<3>]>;
42 def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
43 SDTCisI8<2>, SDTCisI8<3>]>;
45 // PIC16ISD::CALL type prorile
46 def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
49 def SDT_PIC16Brcond: SDTypeProfile<0, 2,
50 [SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
53 def SDT_PIC16Selecticc: SDTypeProfile<1, 3,
54 [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
57 //===----------------------------------------------------------------------===//
58 // PIC16 addressing modes matching via DAG.
59 //===----------------------------------------------------------------------===//
60 def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
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]>;
70 // Low 8-bits of GlobalAddress.
71 def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
73 // High 8-bits of GlobalAddress.
74 def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
76 // The MTHI and MTLO nodes are used only to match them in the incoming
77 // DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
78 // These nodes are not used for defining any instructions.
79 def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
80 def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
82 // Node to generate Bank Select for a GlobalAddress.
83 def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
85 // Node to match a direct store operation.
86 def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
87 def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store,
88 [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
90 // Node to match a direct load operation.
91 def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
92 def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
93 [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
95 // Node to match PIC16 call
96 def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
97 [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
99 // Node to match a comparison instruction.
100 def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
102 // Node to match a conditional branch.
103 def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond,
104 [SDNPHasChain, SDNPInFlag]>;
106 def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
109 //===----------------------------------------------------------------------===//
110 // PIC16 Operand Definitions.
111 //===----------------------------------------------------------------------===//
112 def i8mem : Operand<i8>;
113 def brtarget: Operand<OtherVT>;
115 // Operand for printing out a condition code.
116 let PrintMethod = "printCCOperand" in
117 def CCOp : Operand<i8>;
119 include "PIC16InstrFormats.td"
121 //===----------------------------------------------------------------------===//
122 // PIC16 Common Classes.
123 //===----------------------------------------------------------------------===//
125 // W = W Op F : Load the value from F and do Op to W.
126 let isTwoAddress = 1 in
127 class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
128 ByteFormat<OpCode, (outs GPR:$dst),
129 (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
130 !strconcat(OpcStr, " $ptrlo + $offset, W"),
131 [(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
133 (i8 imm:$offset))))]>;
135 // F = F Op W : Load the value from F, do op with W and store in F.
136 // This insn class is not marked as TwoAddress because the reg is
137 // being used as a source operand only. (Remember a TwoAddress insn
138 // needs a copyRegToReg.)
139 class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
140 ByteFormat<OpCode, (outs),
141 (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
142 !strconcat(OpcStr, " $ptrlo + $offset"),
143 [(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
147 (i8 imm:$ptrhi), (i8 imm:$offset)
150 // W = W Op L : Do Op of L with W and place result in W.
151 let isTwoAddress = 1 in
152 class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
153 LiteralFormat<opcode, (outs GPR:$dst),
154 (ins GPR:$src, i8imm:$literal),
155 !strconcat(OpcStr, " $literal"),
156 [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
158 //===----------------------------------------------------------------------===//
159 // PIC16 Instructions.
160 //===----------------------------------------------------------------------===//
162 // Pseudo-instructions.
163 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
164 "!ADJCALLSTACKDOWN $amt",
165 [(PIC16callseq_start imm:$amt)]>;
167 def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
168 "!ADJCALLSTACKUP $amt",
169 [(PIC16callseq_end imm:$amt)]>;
171 //-----------------------------------
172 // Vaious movlw insn patterns.
173 //-----------------------------------
174 let isReMaterializable = 1 in {
175 // Move 8-bit literal to W.
176 def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
178 [(set GPR:$dst, (i8 imm:$src))]>;
180 // Move a Lo(TGA) to W.
181 def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
183 [(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>;
185 // Move a Hi(TGA) to W.
186 def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
187 "movlw HIGH(${src})",
188 [(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>;
191 //-------------------
192 // FSR setting insns.
193 //-------------------
194 // These insns are matched via a DAG replacement pattern.
196 ByteFormat<0, (outs FSR16:$fsr),
201 let isTwoAddress = 1 in
203 ByteFormat<0, (outs FSR16:$dst),
204 (ins FSR16:$src, GPR:$val),
208 //----------------------------
210 // copyRegToReg insns. These are dummy. They should always be deleted
211 // by the optimizer and never be present in the final generated code.
212 // if they are, then we have to write correct macros for these insns.
213 //----------------------------
215 Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
218 Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
220 //--------------------------
222 //-------------------------
225 // Input operands are: val = W, ptrlo = GA, offset = offset, ptrhi = banksel.
226 class MOVWF_INSN<bits<6> OpCode, SDNode OpNodeDest, SDNode Op>:
227 ByteFormat<0, (outs),
228 (ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
229 "movwf ${ptrlo} + ${offset}",
230 [(Op GPR:$val, OpNodeDest:$ptrlo, (i8 imm:$ptrhi),
233 // Store W to a Global Address.
234 def movwf : MOVWF_INSN<0, tglobaladdr, PIC16Store>;
236 // Store W to an External Symobol.
237 def movwf_1 : MOVWF_INSN<0, texternalsym, PIC16Store>;
239 // Store with InFlag and OutFlag
240 // This is same as movwf_1 but has a flag. A flag is required to
241 // order the stores while passing the params to function.
242 def movwf_2 : MOVWF_INSN<0, texternalsym, PIC16StWF>;
244 // Indirect store. Matched via a DAG replacement pattern.
246 ByteFormat<0, (outs),
247 (ins GPR:$val, FSR16:$fsr, i8imm:$offset),
248 "movwi $offset[$fsr]",
251 //----------------------------
253 //----------------------------
255 // Input Operands are: ptrlo = GA, offset = offset, ptrhi = banksel.
257 class MOVF_INSN<bits<6> OpCode, SDNode OpNodeSrc, SDNode Op>:
258 ByteFormat<0, (outs GPR:$dst),
259 (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
260 "movf ${ptrlo} + ${offset}, W",
262 (Op OpNodeSrc:$ptrlo, (i8 imm:$ptrhi),
263 (i8 imm:$offset)))]>;
266 def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
269 def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
271 // Load with InFlag and OutFlag
272 // This is same as movf_1 but has a flag. A flag is required to
273 // order the loads while copying the return value of a function.
274 def movf_2 : MOVF_INSN<0, texternalsym, PIC16LdWF>;
276 // Indirect load. Matched via a DAG replacement pattern.
278 ByteFormat<0, (outs GPR:$dst),
279 (ins FSR16:$fsr, i8imm:$offset),
280 "moviw $offset[$fsr]",
283 //-------------------------
284 // Bitwise operations patterns
285 //--------------------------
287 let Defs = [STATUS] in {
288 def OrFW : BinOpFW<0, "iorwf", or>;
289 def XOrFW : BinOpFW<0, "xorwf", xor>;
290 def AndFW : BinOpFW<0, "andwf", and>;
293 def OrWF : BinOpWF<0, "iorwf", or>;
294 def XOrWF : BinOpWF<0, "xorwf", xor>;
295 def AndWF : BinOpWF<0, "andwf", and>;
297 //-------------------------
298 // Various add/sub patterns.
299 //-------------------------
302 def addfw_1: BinOpFW<0, "addwf", add>;
303 def addfw_2: BinOpFW<0, "addwf", addc>;
305 let Uses = [STATUS] in
306 def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
309 def addwf_1: BinOpWF<0, "addwf", add>;
310 def addwf_2: BinOpWF<0, "addwf", addc>;
311 let Uses = [STATUS] in
312 def addwfc: BinOpWF<0, "addwfc", adde>; // With Carry.
315 // W -= [F] ; load from F and sub the value from W.
316 let isTwoAddress = 1 in
317 class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
318 ByteFormat<OpCode, (outs GPR:$dst),
319 (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
320 !strconcat(OpcStr, " $ptrlo + $offset, W"),
321 [(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
322 (i8 imm:$ptrhi), (i8 imm:$offset)),
324 let Defs = [STATUS] in {
325 def subfw_1: SUBFW<0, "subwf", sub>;
326 def subfw_2: SUBFW<0, "subwf", subc>;
328 let Uses = [STATUS] in
329 def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
331 def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
335 class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
336 ByteFormat<OpCode, (outs),
337 (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
338 !strconcat(OpcStr, " $ptrlo + $offset"),
339 [(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
340 (i8 imm:$ptrhi), (i8 imm:$offset)),
341 GPR:$src), diraddr:$ptrlo,
342 (i8 imm:$ptrhi), (i8 imm:$offset))]>;
344 let Defs = [STATUS] in {
345 def subwf_1: SUBWF<0, "subwf", sub>;
346 def subwf_2: SUBWF<0, "subwf", subc>;
348 let Uses = [STATUS] in
349 def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
351 def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
355 let Defs = [STATUS] in {
356 def addlw_1 : BinOpLW<0, "addlw", add>;
357 def addlw_2 : BinOpLW<0, "addlw", addc>;
359 let Uses = [STATUS] in
360 def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
362 // bitwise operations involving a literal and w.
363 def andlw : BinOpLW<0, "andlw", and>;
364 def xorlw : BinOpLW<0, "xorlw", xor>;
365 def orlw : BinOpLW<0, "iorlw", or>;
369 // W = C - W ; sub W from literal. (Without borrow).
370 let isTwoAddress = 1 in
371 class SUBLW<bits<6> opcode, SDNode OpNode> :
372 LiteralFormat<opcode, (outs GPR:$dst),
373 (ins GPR:$src, i8imm:$literal),
375 [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
377 let Defs = [STATUS] in {
378 def sublw_1 : SUBLW<0, sub>;
379 def sublw_2 : SUBLW<0, subc>;
380 def sublw_cc : SUBLW<0, PIC16Subcc>;
385 def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
387 [(PIC16call diraddr:$func)]>;
390 let Uses = [STATUS] in
391 def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
393 [(PIC16Brcond bb:$dst, imm:$cc)]>;
395 // Unconditional branch.
396 def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
400 // SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the
401 // scheduler into a branch sequence.
402 let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
403 def SELECT_CC_Int_ICC
404 : Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
405 "; SELECT_CC_Int_ICC PSEUDO!",
406 [(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
412 let isReMaterializable = 1 in {
414 Pseudo<(outs BSR:$dst),
417 [(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
422 ControlFormat<0, (outs), (ins), "return", [(ret)]>;
424 //===----------------------------------------------------------------------===//
425 // PIC16 Replacment Patterns.
426 //===----------------------------------------------------------------------===//
428 // Identify an indirect store and select insns for it.
429 def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
431 (store_indirect GPR:$val,
432 (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
435 // Identify an indirect load and select insns for it.
436 def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
438 (load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),