aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/PIC16/PIC16InstrInfo.td
blob: 34c9f06dea6635195bc374de834e8b65ec8ab9c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source 
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Instruction format superclass
//===----------------------------------------------------------------------===//

include "PIC16InstrFormats.td"

//===----------------------------------------------------------------------===//
// PIC16 profiles and nodes
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// PIC16 addressing mode. 
//===----------------------------------------------------------------------===//
// It matches address of globals as well as the stack slots
// that are created for locals and temporaries. This addressing mode
// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress
// and TargetFrameIndex nodes.
def diraddrmode : ComplexPattern<i16, 2, "SelectDirectAM", [frameindex], []>;
def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>;
def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>;


// Address operand.
def mem : Operand<i16> {
  let PrintMethod = "printAddrModeOperand";
  let MIOperandInfo = (ops i16imm, PTRRegs);
}

// Instruction operand types
def simm8      : Operand<i8>;


// These are target-independent nodes, but have target-specific formats.
def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>;
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq,
                           [SDNPHasChain, SDNPOutFlag]>;
def callseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_PIC16CallSeq,
                           [SDNPHasChain, SDNPOutFlag]>;

def PIC16Wrapper       : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>;

// so_imm_XFORM - Return a so_imm value packed into the format described for
// so_imm def below.
def so_imm_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant((int8_t)N->getValue(), MVT::i32);
}]>;

def so_imm : Operand<i8>,
             PatLeaf<(imm), [{}]> {
  let PrintMethod = "printSOImmOperand";
}



// PIC16 Address Mode! SDNode frameindex could possibily be a match 
// since load and store instructions from stack used it.
def addr : Operand<i16>;

// Arithmetic 2 register operands
class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
             Operand Od> :
  LiteralFormat< op,
      (outs CPURegs:$dst),
      (ins CPURegs:$b, Od:$c),
      !strconcat(instr_asm, " $c"),
      [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>;

// Memory Load/Store 
class LoadDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
  ByteFormat< op,
      (outs CPURegs:$dst),
      (ins mem:$addr),
      !strconcat(instr_asm, " $addr"),
      [(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>;

class LoadInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
  ByteFormat< op,
      (outs PTRRegs:$dst),
      (ins mem:$addr),
      !strconcat(instr_asm, " $addr, $dst"),
      [(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>;

class StoreDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
  ByteFormat< op,
      (outs),
      (ins CPURegs:$src, mem:$addr),
      !strconcat(instr_asm, " $addr"),
      [(OpNode CPURegs:$src, diraddrmode:$addr)]>;

class StoreInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
  ByteFormat< op,
      (outs),
      (ins CPURegs:$src, PTRRegs:$fsr),
      !strconcat(instr_asm, " $fsr"),
      [(OpNode CPURegs:$src, PTRRegs:$fsr)]>;

// Move 
class MovLit<bits<6> op, string instr_asm>:
  LiteralFormat< op,
      (outs CPURegs:$dst),
      (ins i8imm:$src),
      !strconcat(instr_asm, " $src"),
      [(set CPURegs:$dst, imm:$src)]>;


// Arithmetic with memory store.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith1M<bits<6> op, string instr_asm, SDNode OpNode>:
  ByteFormat< op,
      (outs),
      (ins CPURegs:$b, mem:$dst),
      !strconcat(instr_asm, " $dst"),
      [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst),
       (store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>;

// Arithmetic with memory load.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith1R<bits<6> op, string instr_asm, SDNode OpNode>:
  ByteFormat< op,
      (outs CPURegs:$dst),
      (ins mem:$src1, CPURegs:$src2),
      !strconcat(instr_asm, " $src1"),
      [(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>;

// Arithmetic with memory load.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith2R<bits<6> op, string instr_asm, SDNode OpNode>:
  ByteFormat< op,
      (outs CPURegs:$dst),
      (ins mem:$src1, CPURegs:$src2),
      !strconcat(instr_asm, " $src1"),
      [(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>;

//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// PIC16I Instructions
//===----------------------------------------------------------------------===//

// Arithmetic

// ADDiu just accept 16-bit immediates but we handle this on Pat's.
// immZExt32 is used here so it can match GlobalAddress immediates.
// def ADDLW   : ArithI<0x09, "addlw", add, so_imm>;

let isReMaterializable = 1 in {
def MOVLW : MovLit<0x24, "movlw">;
}

// Load/Store
def LFSR1      : LoadInDirect	<0x4, "lfsr",  load>;

let isReMaterializable = 1 in {
def MOVF      : LoadDirect <0x23, "movf",  load>;
}

def MOVWF     : StoreDirect <0x2b, "movwf", store>;

def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>;

def RETURN    : ControlFormat<0x03, (outs), (ins), "return", []>;

def ADDWF     : Arith1M<0x01, "addwf", add>; 
def ADDFW     : Arith1R<0x02, "addfw", add>; 

def ADDWFE    : Arith1M<0x03, "addwfe", adde>; 
def ADDFWE    : Arith1R<0x04, "addfwe", adde>; 

def ADDWFC    : Arith1M<0x05, "addwfc", addc>; 
def ADDFWC    : Arith1R<0x06, "addfwc", addc>; 

def SUBWF     : Arith1M<0x07, "subwf", sub>; 
def SUBFW     : Arith1R<0x08, "subfw", sub>; 

def SUBWFE    : Arith1M<0x09, "subwfe", sube>; 
def SUBFWE    : Arith1R<0x0a, "subfwe", sube>; 

def SUBWFC    : Arith1M<0x0b, "subwfc", subc>; 
def SUBFWC    : Arith1R<0x0d, "subfwc", subc>; 

def SUBRFW    : Arith2R<0x08, "subfw", sub>; 

def SUBRFWE   : Arith2R<0x0a, "subfwe", sube>; 

def SUBRFWC   : Arith2R<0x0d, "subfwc", subc>; 

def brtarget  : Operand<OtherVT>;

class UncondJump< bits<4> op, string instr_asm>:
  BitFormat< op,
	     (outs),
	     (ins brtarget:$target),
	     !strconcat(instr_asm, " $target"),
	     [(br bb:$target)]>;

def GOTO : UncondJump<0x1, "goto">;

class LogicM<bits<6> op, string instr_asm, SDNode OpNode> :
  ByteFormat< op,
      (outs),
      (ins CPURegs:$b, mem:$dst),
      !strconcat(instr_asm, " $dst"),
      [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>;

class LogicR<bits<6> op, string instr_asm, SDNode OpNode> :
  ByteFormat< op,
      (outs CPURegs:$dst),
      (ins CPURegs:$b, mem:$c),
      !strconcat(instr_asm, " $c"),
      [(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>;

class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> :
  LiteralFormat< op,
      (outs CPURegs:$dst),
      (ins CPURegs:$b, Od:$c),
      !strconcat(instr_asm, " $c"),
      [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>;

def XORWF : LogicM<0x1,"xorwf",xor>; 
def XORFW : LogicR<0x1,"xorfw",xor>; 
def XORLW : LogicI<0x1,"xorlw",xor, so_imm>;

def ANDWF : LogicM<0x1,"andwf",and>; 
def ANDFW : LogicR<0x1,"andfw",and>; 
def ANDLW : LogicI<0x1,"andlw",and, so_imm>;

def IORWF : LogicM<0x1,"iorwf",or>; 
def IORFW : LogicR<0x1,"iorfw",or>; 
def IORLW : LogicI<0x1,"iorlw",or, so_imm>;


/* For comparison before branch */
def SDT_PIC16Cmp  : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>;
def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, 
				     SDTCisSameAs<1,2>, SDTCisInt<1>]>;

def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>; 
def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; 
def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; 

def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>; 
def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>; 
def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>; 
def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>; 


/* For branch conditions */
def SDT_PIC16Branch  : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, 
				     SDTCisVT<1,i8>, SDTCisVT<2,i8>]>;

def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch, 
			 [SDNPHasChain, SDNPInFlag]>; 

def PIC16BTFSS  : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch, 
			 [SDNPHasChain, SDNPInFlag]>; 

def PIC16BTFSC  : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch, 
			 [SDNPHasChain, SDNPInFlag]>; 

class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>:
  BitFormat< op,
	     (outs),
	     (ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ),
      	     !strconcat(instr_asm, " $s, $i, $target"),
      	     [(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>;

def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;


//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//

let Defs = [STKPTR], Uses = [STKPTR] in {
def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt),
                               "!ADJCALLSTACKDOWN $amt",
                               [(callseq_start imm:$amt)]>;
def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt),
                            "!ADJCALLSTACKUP $amt",
                            [(callseq_end imm:$amt)]>;
}


//===----------------------------------------------------------------------===//
//  Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
def : Pat<(ret), (RETURN)>;