comparison modules/il.tp @ 185:181d8754a2ae

Initial work on IL module
author Mike Pavone <pavone@retrodev.com>
date Sun, 25 Aug 2013 14:45:00 -0700
parents
children a45e535f7742
comparison
equal deleted inserted replaced
184:ca249978ae96 185:181d8754a2ae
1 {
2 //commutative ops
3 _add <- 0
4 _and <- 1
5 _or <- 2
6 _xor <- 3
7 //non-commutative ops
8 _sub <- 4
9 _cmp <- 5
10 _not <- 6
11 _sl <- 7
12 _asr <- 8
13 _lsr <- 9
14 _rol <- 10
15 _ror <- 11
16 _mov <- 12
17 _call <- 13
18 _ret <- 14
19 _skipif <- 15
20
21 _names <- #[
22 "add"
23 "and"
24 "or"
25 "xor"
26 "sub"
27 "cmp"
28 "not"
29 "sl"
30 "asr"
31 "lsr"
32 "rol"
33 "ror"
34 "mov"
35 "call"
36 "ret"
37 "skipIf"
38 ]
39
40 op3:a:b:out:size <- :_opcode :_ina :_inb :_out :_size {
41 #{
42 opcode <- { _opcode }
43 ina <- { _ina }
44 inb <- { _inb }
45 commutative? <- { _opcode < _sub }
46 out <- { _out }
47 size <- { _size }
48 numops <- { 3 }
49 name <- { _names get: _opcode }
50 string <- { name . " " . (string: _ina) . " " . (string: _inb) . " " . (string: _out) . " " . (string: _size) }
51 }
52 }
53 op2:in:out:size <- :_opcode :_in :_out :_size {
54 #{
55 opcode <- { _opcode }
56 in <- { _in }
57 out <- { _out }
58 size <- { _size }
59 numops <- { 2 }
60 name <- { _names get: _opcode }
61 string <- { name . " " . (string: _in) . " " . (string: _out) . " " . (string: _size) }
62 }
63 }
64 op1:arg:size <- :_opcode :_arg :_size {
65 #{
66 opcode <- { _opcode }
67 arg <- { _arg }
68 size <- { _size }
69 numops <- { 1 }
70 name <- { _names get: _opcode }
71 string <- { name . " " . (string: _arg) . " " . (string: _size) }
72 }
73 }
74
75 _sizenames <- #["b" "w" "l" "q"]
76 _size <- :_num {
77 #{
78 num <- { _num }
79 string <- { _sizenames get: _num }
80 = <- :other {
81 _num = (other num)
82 }
83 <= <- :other {
84 _num <= (other num)
85 }
86 >= <- :other {
87 _num >= (other num)
88 }
89 > <- :other {
90 _num > (other num)
91 }
92 < <- :other {
93 _num < (other num)
94 }
95 }
96 }
97 byte <- _size: 0
98 word <- _size: 1
99 long <- _size: 2
100 quad <- _size: 3
101
102 _retr <- #{
103 isInteger? <- { false }
104 register? <- { true }
105 argument? <- { false }
106 return? <- { true }
107 string <- { "retr" }
108 = <- :other {
109 (not: (other isInteger?)) && (other register?) && (other return?)
110 }
111 }
112
113 _condnames <- #[
114 "eq"
115 "neq"
116 "ge"
117 "le"
118 "gr"
119 "ls"
120 "uge"
121 "ule"
122 "ugr"
123 "uls"
124 ]
125 condition <- :num {
126 #{
127 cc <- { num }
128 string <- { _condnames get: num }
129 = <- :other { num = (other cc) }
130 }
131 }
132 _eq <- condition: 0
133 _neq <- condition: 1
134 _ge <- condition: 2
135 _le <- condition: 3
136 _gr <- condition: 4
137 _ls <- condition: 5
138 _uge <- condition: 6
139 _ule <- condition: 7
140 _ugr <- condition: 8
141 _uls <- condition: 9
142
143 #{
144 b <- { byte }
145 w <- { word }
146 l <- { long }
147 q <- { quad }
148
149 eq <- { _eq }
150 neq <- { _neq }
151
152 //signed conditions
153 ge <- { _ge }
154 le <- { _le }
155 gr <- { _gr }
156 ls <- { _ls }
157
158 //unsigned conditions
159 uge <- { _uge }
160 ule <- { _ule }
161 ugr <- { _ugr }
162 uls <- { _uls }
163
164
165 reg <- :num {
166 #{
167 isInteger? <- { false }
168 register? <- { true }
169 argument? <- { false }
170 return? <- { false }
171 regnum <- { num }
172 string <- { "r" . (string: num) }
173 = <- :other {
174 (not: (other isInteger?)) && (other register?) && (not: (other argument?)) && (not: (other return?)) && num = (other regnum)
175 }
176 }
177 }
178 arg <- :num {
179 #{
180 isInteger? <- { false }
181 register? <- { true }
182 argument? <- { true }
183 return? <- { false }
184 argnum <- { num }
185 string <- { "a" . (string: num) }
186 = <- :other {
187 (not: (other isInteger?)) && (other register?) && (other argument?) && num = (other regnum)
188 }
189 }
190 }
191 retr <- { _retr }
192
193 add <- :ina inb out size {
194 op3: _add a: ina b: inb out: out size: size
195 }
196
197 sub <- :ina inb out size {
198 op3: _sub a: ina b: inb out: out size: size
199 }
200
201 cmp <- :ina inb out size {
202 op3: _cmp a: ina b: inb out: out size: size
203 }
204
205 and <- :ina inb out size {
206 op3: _and a: ina b: inb out: out size: size
207 }
208
209 or <- :ina inb out size {
210 op3: _or a: ina b: inb out: out size: size
211 }
212
213 xor <- :ina inb out size {
214 op3: _xor a: ina b: inb out: out size: size
215 }
216
217 bnot <- :in out size {
218 op2: _not in: in out: out size: size
219 }
220
221 sl <- :shift in out size {
222 op3: _sl a: shift b: in out: out size: size
223 }
224
225 asr <- :shift in out size {
226 op3: _asr a: shift b: in out: out size: size
227 }
228
229 lsr <- :shift in out size {
230 op3: _lsr a: shift b: in out: out size: size
231 }
232
233 rol <- :rot in out size {
234 op3: _rol a: rot b: in out: out size: size
235 }
236
237 ror <- :rot in out size {
238 op3: _ror a: rot b: in out: out size: size
239 }
240
241 mov <- :in out size {
242 op2: _mov in: in out: out size: size
243 }
244
245 call:withArgs <- :_target :_args {
246 #{
247 opcode <- { _call }
248 target <- { _target }
249 args <- { _args }
250 numops <- { 0 }
251 name <- { _names get: _call }
252 string <- {
253 argstr <- _args map: :el {
254 string: el
255 }
256 name . " " . (string: _target) . " " . (argstr join: " ")
257 }
258 }
259 }
260
261 return <- :val size {
262 op1: _ret arg: val size: size
263 }
264 skipIf <- :_cond _toskip {
265 #{
266 opcode <- { _skipif }
267 toskip <- { _toskip }
268 cond <- { _cond }
269 numops <- { 0 }
270 name <- { _names get: _skipif }
271 string <- {
272 block <- (_toskip map: :el { string: el }) join: "\n\t"
273 if: (_toskip length) > 0 {
274 block <- "\n\t" . block . "\n"
275 }
276 name . " " . (string: _cond) . " {" . block . "}"
277 }
278 }
279 }
280
281 //used to convert IL to a format suitable for a 2-operand architecture
282 //should be run after register allocation (I think....)
283 to2Op <- :instarr {
284 instarr fold: #[] with: :newarr inst {
285 if: (inst numops) = 3 {
286 if: (inst inb) = (inst out) {
287 newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
288 } else: {
289 if: (inst commutative?) && (inst ina) = (inst out) {
290 newarr append: (op2: (inst opcode) in: (inst inb) out: (inst out) size: (inst size))
291 } else: {
292 newarr append: (mov: (inst inb) (inst out) (inst size))
293 newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
294 }
295 }
296 } else: {
297 if: (inst numops) = 2 && (inst opcode) != _mov {
298 if: (inst in) != (inst out) {
299 newarr append: (mov: (inst in) (inst out) (inst size))
300 }
301 newarr append: (op1: (inst opcode) val: (inst out) size: (inst size))
302 } else: {
303 newarr append: inst
304 }
305 }
306 }
307 }
308
309 main <- {
310 fib <- #[
311 sub: 2 (arg: 0) (reg: 0) q
312 skipIf: ge #[
313 return: 1 q
314 ]
315 call: "fib" withArgs: #[reg: 0]
316 mov: retr (reg: 1) q
317 add: 1 (reg: 0) (reg: 2) q
318 call: "fib" withArgs: #[reg: 2]
319 add: retr (reg: 1) (reg: 3) q
320 return: (reg: 3) q
321 ]
322 print: "Original:\n\n"
323 foreach: fib :idx inst {
324 print: (string: inst) . "\n"
325 }
326 fib2 <- to2Op: fib
327 print: "\n\n2-Operand:\n\n"
328 foreach: fib2 :idx inst {
329 print: (string: inst) . "\n"
330 }
331 }
332 }
333 }