3 ;;; Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;; This file is part of Mes.
8 ;;; Mes is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; Mes is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
23 ;;; as-i386.mes defines i386 assembly
31 (mes-use-module (mes as))))
36 (define (i386:function-preamble)
37 '(("push___%ebp") ; push %ebp
38 ("mov____%esp,%ebp"))) ; mov %esp,%ebp;
40 (define (i386:function-locals)
41 '(("sub____%esp,$i8" (#:immediate1 #x40)))) ; sub %esp,$0x40 # 16 local vars
43 (define (i386:push-label label)
44 `(("push___$i32" (#:address ,label)))) ; push $0x<label>
46 (define (i386:push-label-mem label)
47 `(("mov____0x32,%eax" (#:address ,label)) ; mov 0x804a000,%eax
48 ("push___%eax"))) ; push %eax
50 (define (i386:push-local n)
51 (or n (error "invalid value: push-local: " n))
52 `(("push___0x8(%ebp)" (#:immediate1 ,(- 0 (* 4 n)))))) ; pushl 0x<n>(%ebp)
54 (define (i386:push-local-address n)
55 (or n (error "invalid value: push-local-address: " n))
56 `(("lea____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))) ; lea 0x<n>(%ebp),%eax
57 ("push___%eax"))) ; push %eax
59 (define (i386:push-byte-local-de-ref n)
60 (or n (error "invalid value: push-byte-local-de-ref: " n))
61 `(("mov____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))) ; mov -0x<n>(%ebp),%eax
62 ("movzbl_(%eax),%eax") ; movzbl (%eax),%eax
63 ("push___%eax"))) ; push %eax
65 (define (i386:push-byte-local-de-de-ref n)
66 (or n (error "invalid value: push-byte-local-de-de-ref: " n))
67 `(("mov____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))) ; mov -0x<n>(%ebp),%eax
68 ("mov____(%eax),%eax") ; mov (%eax),%eax
69 ("movzbl_(%eax),%eax") ; movzbl (%eax),%eax
72 (define (i386:push-local-de-ref n)
73 (or n (error "invalid value: push-byte-local-de-ref: " n))
74 `(("mov____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))) ; mov -0x<n>(%ebp),%eax
75 ("mov____(%eax),%eax") ; mov (%eax),%eax
76 ("push___%eax"))) ; push %eax
78 (define (i386:pop-accu)
79 '(("pop____%eax"))) ; pop %eax
81 (define (i386:push-accu)
82 '(("push___%eax"))) ; push %eax
84 (define (i386:pop-base)
85 '(("pop____%edx"))) ; pop %edx
87 (define (i386:push-base)
88 '(("push___%edx"))) ; push %edx
94 (define (i386:accu->base)
95 '(("mov____%eax,%edx"))) ; mov %eax,%edx
97 (define (i386:accu->base-address)
98 '(("mov____%eax,(%edx)"))) ; mov %eax,(%edx)
100 (define (i386:byte-accu->base-address)
101 '(("mov____%al,(%edx)"))) ; mov %al,(%edx)
103 (define (i386:accu->base-address+n n)
104 (or n (error "invalid value: accu->base-address+n: " n))
105 `(("mov____%eax,0x8(%edx)" (#:immediate1 ,n)))) ; mov %eax,$0x<n>%(edx)
107 (define (i386:accu->local n)
108 (or n (error "invalid value: accu->local: " n))
109 `(("mov____%eax,0x8(%ebp)" (#:immediate1 ,(- 0 (* 4 n)))))) ; mov %eax,-<0xn>(%ebp)
111 ;; (define (i386:accu->local-address n)
112 ;; (or n (error "invalid value: accu->local: " n))
113 ;; `(#x89 #x45 ,(- 0 (* 4 n)))) ; mov %eax,-<0xn>(%ebp)
115 (define (i386:base->local n)
116 (or n (error "invalid value: base->local: " n))
117 `(("mov____%edx,0x8(%ebp)" ,(- 0 (* 4 n))))) ; mov %edx,-<0xn>(%ebp)
119 (define (i386:accu->label label)
120 `(("mov____%eax,0x32" (#:address ,label)))) ; mov %eax,0x<label>
122 (define (i386:accu-zero?)
123 '(("test___%eax,%eax")))
125 (define (i386:accu-shl n)
126 (or n (error "invalid value: accu:shl n: " n))
127 `(("shl____$i8,%eax" (#:immediate1 ,n)))) ; shl $0x8,%eax
129 (define (i386:accu<<base)
130 '(("xor____%ecx,%ecx") ; xor %ecx,%ecx
131 ("mov____%edx,%ecx") ; mov %edx,%ecx
132 ("shl____%cl,%eax"))) ; shl %cl,%eax
134 (define (i386:accu>>base)
135 '(("xor____%ecx,%ecx") ; xor %ecx,%ecx
136 ("mov____%edx,%ecx") ; mov %edx,%ecx
137 ("shr____%cl,%eax"))) ; shr %cl,%eax
139 (define (i386:accu-and-base)
140 '(("and____%edx,%eax"))) ; and %edx,%eax
142 (define (i386:accu-not)
143 '(("not____%eax"))) ; not %eax
145 (define (i386:accu-or-base)
146 '(("or_____%edx,%eax"))) ; or %edx,%eax
148 (define (i386:accu-xor-base)
149 '(("xor____%edx,%eax"))) ; xor %edx,%eax
151 (define (i386:accu+accu)
152 '(("add____%eax,%eax"))) ; add %eax,%eax
154 (define (i386:accu+base)
155 `(("add____%edx,%eax"))) ; add %edx,%eax
157 (define (i386:accu+value v)
158 (or v (error "invalid value: accu+value: " v))
159 `(("add____$i32,%eax" (#:immediate ,v)))) ; add %eax,$
161 (define (i386:accu-base)
162 `(("sub____%edx,%eax"))) ; sub %edx,%eax
164 (define (i386:accu*base)
165 `(("mul____%edx"))) ; mul %edx
167 (define (i386:accu/base)
168 '(("mov____%edx,%ebx") ; mov %edx,%ebx
169 ("xor____%edx,%edx") ; xor %edx,%edx
170 ("div____%ebx"))) ; div %ebx
172 (define (i386:accu%base)
173 '(("mov____%edx,%ebx") ; mov %edx,%ebx
174 ("xor____%edx,%edx") ; xor %edx,%edx
175 ("div____%ebx") ; div %ebx
176 ("mov____%edx,%eax"))) ; mov %edx,%eax
178 (define (i386:base->accu)
179 '(("mov____%edx,%eax"))) ; mov %edx,%eax
181 (define (i386:local->accu n)
182 (or n (error "invalid value: local->accu: " n))
183 `(("mov____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))))) ; mov -<0xn>(%ebp),%eax
185 (define (i386:local-address->accu n)
186 (or n (error "invalid value: ladd: " n))
187 `(("lea____0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))))) ; lea 0x<n>(%ebp),%eax
189 (define (i386:local-ptr->accu n)
190 (or n (error "invalid value: local-ptr->accu: " n))
191 `(("mov____%ebp,%eax") ; mov %ebp,%eax
192 ("add____$i8,%eax" (#:immediate1 ,(- 0 (* 4 n)))))) ; add $0x<n>,%eax
194 (define (i386:byte-local->accu n)
195 (or n (error "invalid value: byte-local->accu: " n))
196 `(("movzbl_0x8(%ebp),%eax" (#:immediate1 ,(- 0 (* 4 n)))))) ; movzbl 0x<n>(%ebp),%eax
198 (define (i386:byte-local->base n)
199 (or n (error "invalid value: byte-local->base: " n))
200 `(("movzbl_0x8(%ebp),%edx" (#:immediate1 ,(- 0 (* 4 n)))))) ; movzbl 0x<n>(%ebp),%edx
202 (define (i386:local->base n)
203 (or n (error "invalid value: local->base: " n))
204 `(("mov____0x8(%ebp),%edx" (#:immediate1 ,(- 0 (* 4 n)))))) ; mov -<0xn>(%ebp),%edx
206 (define (i386:local-address->base n) ;; DE-REF
207 (or n (error "invalid value: local-address->base: " n))
208 `(("lea____0x8(%ebp),%edx" (#:immediate1 ,(- 0 (* 4 n)))))) ; lea 0x<n>(%ebp),%edx
210 (define (i386:local-ptr->base n)
211 (or n (error "invalid value: local-ptr->base: " n))
212 `(("mov____%ebp,%edx") ; mov %ebp,%edx
213 ("add____$i8,%edx" (#:immediate1 ,(- 0 (* 4 n)))))) ; add $0x<n>,%edx
215 (define (i386:label->accu label)
216 `(("mov____$i32,%eax" (#:address ,label)))) ; mov $<n>,%eax
218 (define (i386:label->base label)
219 `(("mov____$i32,%edx" (#:address ,label)))) ; mov $<n>,%edx
221 (define (i386:label-mem->accu label)
222 `(("mov____0x32,%eax" (#:address ,label)))) ; mov 0x<n>,%eax
224 (define (i386:label-mem->base label)
225 `(("mov____0x32,%edx" (#:address ,label)))) ; mov 0x<n>,%edx
227 (define (i386:label-mem-add label v)
228 `(("add____$i8,0x32" (#:address ,label) (#:immediate1 ,v)))) ; addl $<v>,0x<n>
230 (define (i386:byte-base-mem->accu)
231 '(("add____%edx,%eax") ; add %edx,%eax
232 ("movzbl_(%eax),%eax"))) ; movzbl (%eax),%eax
234 (define (i386:byte-mem->accu)
235 '(("movzbl_(%eax),%eax"))) ; movzbl (%eax),%eax
237 (define (i386:byte-mem->base)
238 '(("movzbl_(%edx),%edx"))) ; movzbl (%edx),%edx
240 (define (i386:base-mem->accu)
241 '(("add___%edx,%eax") ; add %edx,%eax
242 ("mov____(%eax),%eax"))) ; mov (%eax),%eax
244 (define (i386:mem->accu)
245 '(("mov____(%eax),%eax"))) ; mov (%eax),%eax
247 (define (i386:mem->base)
248 '(("mov____(%edx),%edx"))) ; mov (%edx),%edx
250 (define (i386:mem+n->accu n)
251 `(("mov____0x8(%eax),%eax" (#:immediate1 ,n)))) ; mov 0x<n>(%eax),%eax
253 (define (i386:base-mem+n->accu n)
254 (or n (error "invalid value: base-mem+n->accu: " n))
255 `(("add___%edx,%eax") ; add %edx,%eax
256 ("mov____0x8(%eax),%eax" (#:immediate1 ,n)))) ; mov <n>(%eax),%eax
258 (define (i386:value->accu v)
259 (or v (error "invalid value: i386:value->accu: " v))
260 `(("mov____$i32,%eax" (#:immediate ,v)))) ; mov $<v>,%eax
262 (define (i386:value->accu-address v)
263 `(("mov____$i32,(%eax)" (#:immediate ,v)))) ; movl $0x<v>,(%eax)
265 (define (i386:value->accu-address+n n v)
266 (or v (error "invalid value: i386:value->accu-address+n: " v))
267 `(("mov____$i32,0x8(%eax)" (#:immediate1 ,n) (#:immediate ,v)))) ; movl $<v>,0x<n>(%eax)
269 (define (i386:base->accu-address)
270 '(("mov____%edx,%(eax)"))) ; mov %edx,(%eax)
272 (define (i386:base-address->accu-address)
273 '(("mov____(%edx),%ecx") ; mov (%edx),%ecx
274 ("mov____%ecx,%(eax)"))) ; mov %ecx,(%eax)
276 (define (i386:accu+n n)
277 `(("add____$i8,%eax" (#:immediate1 ,n)))) ; add $0x00,%eax
279 (define (i386:base+n n)
280 `(("add____$i8,%edx" (#:immediate1 ,n)))) ; add $0x00,%edx
282 (define (i386:byte-base->accu-address)
283 '(("mov____%dl,(%eax)"))) ; mov %dl,(%eax)
285 (define (i386:byte-base->accu-address+n n)
286 (or n (error "invalid value: byte-base->accu-address+n: " n))
287 `(("mov____%dl,0x8(%eax)" (#:immediate1 ,n)))) ; mov %dl,0x<n>(%eax)
289 (define (i386:value->base v)
290 (or v (error "invalid value: i386:value->base: " v))
291 `(("mov____$i32,%edx" (#:immediate ,v)))) ; mov $<v>,%edx
293 (define (i386:local-add n v)
294 (or n (error "invalid value: i386:local-add: " n))
295 `(("add____$i8,0x8(%ebp)" (#:immediate1 ,(- 0 (* 4 n))) (#:immediate1 ,v)))) ; addl $<v>,0x<n>(%ebp)
297 (define (i386:accu-mem-add v)
298 `(("add____$i8,0x8(%eax)" (#:immediate1 ,v)))) ; addl $<v>,(%eax)
300 (define (i386:value->label label v)
301 (or v (error "invalid value: value->label: " v))
302 `(("mov____$i32,0x32" (#:address ,label) ; movl $<v>,(<n>)
305 (define (i386:value->local n v)
306 (or n (error "invalid value: value->local: " n))
307 `(("mov____$i32,0x8(%ebp)" (#:immediate1 ,(- 0 (* 4 n))) ; movl $<v>,0x<n>(%ebp)
310 (define (i386:local-test n v)
311 (or n (error "invalid value: local-test: " n))
312 `(("cmp____$i8,0x8(%ebp)" (#:immediate1 ,(- 0 (* 4 n))) (#:immediate1 ,v)))) ; cmpl $<v>,0x<n>(%ebp)
314 (define (i386:call-label label n)
315 `((call32 (#:offset ,label))
316 ("add____$i8,%esp" (#:immediate1 ,(* n 4)))))
318 (define (i386:call-accu n)
321 ("call___*%eax") ; call *%eax
322 ("add____$i8,%esp" (#:immediate1 ,(* n 4))))) ; add $00,%esp
324 (define (i386:accu-negate)
325 '(("sete___%al") ; sete %al
326 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
328 (define (i386:xor-accu v)
329 (or v (error "invalid value: i386:xor-accu: n: " v))
330 `(("xor___$i32,%eax" (#:immediate ,v)))) ;xor $0xff,%eax
332 (define (i386:xor-zf)
334 ("xor____$i8,%ah" (#:immediate1 #x40)) ; xor $0x40,%ah
337 (define (i386:accu-cmp-value v)
338 `(("cmp____$i8,%eax" (#:immediate1 ,v)))) ; cmp $<v>,%eax
340 (define (i386:accu-test)
341 '(("test___%eax,%eax"))) ; test %eax,%eax
343 (define (i386:jump label)
344 `(("jmp32 " (#:offset ,label))))
346 (define (i386:jump-z label)
347 `(("je32 " (#:offset ,label)))) ; jz . + <n>
349 (define (i386:jump-byte-z label)
350 `(("test___%al,%al") ; test %al,%al
351 ("je8 " (#:offset1 ,label)))) ; je <n>
354 (define (i386:jump-g label)
355 `(("jg32 " (#:offset ,label)))) ; jg/jnle <n>
358 (define (i386:jump-ge label)
359 `(("jge32 " (#:offset ,label)))) ; jge/jnl <n>
361 (define (i386:jump-nz label)
362 `(("jne32 " (#:offset ,label)))) ; jnz . + <n>
364 (define (i386:byte-test-base)
365 '(("cmp____%al,%dl"))) ; cmp %al,%dl
367 (define (i386:test-base)
368 (("cmp____%edx,%eax"))) ; cmp %edx,%eax
370 (define (i386:byte-sub-base)
371 '(("sub____%dl,%al"))) ; sub %dl,%al
373 (define (i386:byte-base-sub)
374 `(("sub____%al,%dl"))) ; sub %al,%dl
376 (define (i386:sub-base)
377 `(("sub____%edx,%eax"))) ; sub %edx,%eax
379 (define (i386:base-sub)
380 `(("sub____%eax,%edx"))) ; sub %eax,%edx
382 (define (i386:nz->accu)
383 '(("setne__%al") ; setne %al
384 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
386 (define (i386:z->accu)
387 '(("sete___%al") ; sete %al
388 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
390 (define (i386:accu<->stack)
391 '(("xchg___%eax,(%esp)"))) ; xchg %eax,(%esp)