Mercurial > repos > tabletprog
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 } |