185
|
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 }
|