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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the ARM instructions in TableGen format.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// PIC16 Specific Type Constraints.
//===----------------------------------------------------------------------===//
class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
//===----------------------------------------------------------------------===//
// PIC16 Specific Type Profiles.
//===----------------------------------------------------------------------===//
// Generic type profiles for i8/i16 unary/binary operations.
// Taking one i8 or i16 and producing void.
def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
// Taking one value and producing an output of same type.
def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
// Taking two values and producing an output of same type.
def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
SDTCisI16<2>]>;
// Node specific type profiles.
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
SDTCisI8<2>, SDTCisI8<3>]>;
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
SDTCisI8<2>, SDTCisI8<3>]>;
//===----------------------------------------------------------------------===//
// PIC16 addressing modes matching via DAG.
//===----------------------------------------------------------------------===//
def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
//===----------------------------------------------------------------------===//
// PIC16 Specific Node Definitions.
//===----------------------------------------------------------------------===//
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
// Low 8-bits of GlobalAddress.
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
// High 8-bits of GlobalAddress.
def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
// The MTHI and MTLO nodes are used only to match them in the incoming
// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
// These nodes are not used for defining any instructions.
def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
// Node to generate Bank Select for a GlobalAddress.
def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
// Node to match a direct store operation.
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
// Node to match a direct load operation.
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
// Nodes to match bitwise operatios.
def OR : SDNode<"ISD::OR", SDTI8BinOp>;
def XOR : SDNode<"ISD::XOR", SDTI8BinOp>;
def AND : SDNode<"ISD::AND", SDTI8BinOp>;
//===----------------------------------------------------------------------===//
// PIC16 Operand Definitions.
//===----------------------------------------------------------------------===//
def i8mem : Operand<i8>;
include "PIC16InstrFormats.td"
//===----------------------------------------------------------------------===//
// PIC16 Common Classes.
//===----------------------------------------------------------------------===//
// W = W Op F : Load the value from F and do Op to W
class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset, W"),
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))))]>;
// F = F Op W : Load the value from F, do op with W and store in F
class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset"),
[(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))),
diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)
)]>;
//===----------------------------------------------------------------------===//
// PIC16 Instructions.
//===----------------------------------------------------------------------===//
// Pseudo-instructions.
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
"!ADJCALLSTACKDOWN $amt",
[(PIC16callseq_start imm:$amt)]>;
def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
"!ADJCALLSTACKUP $amt",
[(PIC16callseq_end imm:$amt)]>;
//-----------------------------------
// Vaious movlw insn patterns.
//-----------------------------------
let isReMaterializable = 1 in {
// Move 8-bit literal to W.
def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw $src",
[(set GPR:$dst, (i8 imm:$src))]>;
// Move a Lo(TGA) to W.
def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw LOW(${src})",
[(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>;
// Move a Hi(TGA) to W.
def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw HIGH(${src})",
[(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>;
}
//-------------------
// FSR setting insns.
//-------------------
// These insns are matched via a DAG replacement pattern.
def set_fsrlo:
ByteFormat<0, (outs FSR16:$fsr),
(ins GPR:$val),
"movwf ${fsr}L",
[]>;
let isTwoAddress = 1 in
def set_fsrhi:
ByteFormat<0, (outs FSR16:$dst),
(ins FSR16:$src, GPR:$val),
"movwf ${dst}H",
[]>;
def copy_fsr:
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
//--------------------------
// Store to memory
//-------------------------
// Direct store.
def movwf :
ByteFormat<0, (outs),
(ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
"movwf ${ptrlo} + ${offset}",
[(PIC16Store GPR:$val, tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
def movwf_1 :
ByteFormat<0, (outs),
(ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movwf ${ptrlo} + ${offset}",
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
// Indirect store. Matched via a DAG replacement pattern.
def store_indirect :
ByteFormat<0, (outs),
(ins GPR:$val, FSR16:$fsr, i8imm:$offset),
"movwi $offset[$fsr]",
[]>;
//----------------------------
// Load from memory
//----------------------------
// Direct load.
def movf :
ByteFormat<0, (outs GPR:$dst),
(ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
"movf ${ptrlo} + ${offset}, W",
[(set GPR:$dst,
(PIC16Load tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
def movf_1 :
ByteFormat<0, (outs GPR:$dst),
(ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movf ${ptrlo} + ${offset}, W",
[(set GPR:$dst,
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
// Indirect load. Matched via a DAG replacement pattern.
def load_indirect :
ByteFormat<0, (outs GPR:$dst),
(ins FSR16:$fsr, i8imm:$offset),
"moviw $offset[$fsr]",
[]>;
//-------------------------
// Bitwise operations patterns
//--------------------------
def OrFW : BinOpFW<0, "iorwf", OR>;
def XOrFW : BinOpFW<0, "xorwf", XOR>;
def AndFW : BinOpFW<0, "andwf", AND>;
def OrWF : BinOpWF<0, "iorwf", OR>;
def XOrWF : BinOpWF<0, "xorwf", XOR>;
def AndWF : BinOpWF<0, "andwf", AND>;
//-------------------------
// Various add/sub patterns.
//-------------------------
// let isTwoAddress = 1 in {
def addfw_1: BinOpFW<0, "addwf", add>;
def addfw_2: BinOpFW<0, "addwf", addc>;
def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
// }
def addwf_1: BinOpWF<0, "addwf", add>;
def addwf_2: BinOpWF<0, "addwf", addc>;
def addwfc: BinOpWF<0, "addwfc", adde>; // With Carry.
// W -= [F] ; load from F and sub the value from W.
class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset, W"),
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)),
GPR:$src))]>;
//let isTwoAddress = 1 in {
def subfw_1: SUBFW<0, "subwf", sub>;
def subfw_2: SUBFW<0, "subwf", subc>;
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
//}
// [F] -= W ;
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset"),
[(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)),
GPR:$src), diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset))]>;
def subwf_1: SUBWF<0, "subwf", sub>;
def subwf_2: SUBWF<0, "subwf", subc>;
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
// addlw
// W += C ; add literal to W. (Without carry). May Produce a carry.
class ADDLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
LiteralFormat<opcode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$literal),
!strconcat(OpcStr, " $literal"),
[(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
// let isTwoAddress = 1 in {
def addlw_1 : ADDLW<0, "addlw", add>;
def addlw_2 : ADDLW<0, "addlw", addc>;
def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
//}
// sublw
// W = C - W ; sub W from literal. (Without borrow).
class SUBLW<bits<6> opcode, SDNode OpNode> :
LiteralFormat<opcode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$literal),
"addlw $literal",
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
//let isTwoAddress = 1 in {
def sublw_1 : SUBLW<0, sub>;
def sublw_2 : SUBLW<0, subc>;
//}
// Banksel.
let isReMaterializable = 1 in {
def banksel :
Pseudo<(outs BSR:$dst),
(ins i8mem:$ptr),
"banksel $ptr",
[(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
}
// Return insn.
def Return :
ControlFormat<0, (outs), (ins), "return", [(ret)]>;
//===----------------------------------------------------------------------===//
// PIC16 Replacment Patterns.
//===----------------------------------------------------------------------===//
// Identify an indirect store and select insns for it.
def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
imm:$offset),
(store_indirect GPR:$val,
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
imm:$offset)>;
// Identify an indirect load and select insns for it.
def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
imm:$offset),
(load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
imm:$offset)>;
|