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)
38 ("mov____%esp,%ebp")))
40 (define (i386:function-locals)
41 `(("sub____%esp,$i32" (#:immediate ,(+ (* 4 1025) (* 20 4)))))) ; sub %esp,xxx 4*1024 buf, 20 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
53 (define (i386:push-local n)
54 (or n (error "invalid value: push-local: " n))
55 (let ((n (- 0 (* 4 n))))
56 `(,(if (< (abs n) #x80) `("push___0x8(%ebp)" (#:immediate1 ,n))
57 `("push___0x32(%ebp)" (#:immediate ,n))))))
59 (define (i386:push-local-address n)
60 (or n (error "invalid value: push-local-address: " n))
61 (let ((n (- 0 (* 4 n))))
62 `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%eax" (#:immediate1 ,n))
63 `("lea____0x32(%ebp),%eax" (#:immediate ,n)))
66 (define (i386:push-byte-local-de-ref n)
67 (or n (error "invalid value: push-byte-local-de-ref: " n))
68 (let ((n (- 0 (* 4 n))))
69 `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
70 `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
71 ("movzbl_(%eax),%eax")
74 (define (i386:push-byte-local-de-de-ref n)
75 (or n (error "invalid value: push-byte-local-de-de-ref: " n))
76 (let ((n (- 0 (* 4 n))))
77 `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
78 `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
79 ("mov____(%eax),%eax")
80 ("movzbl_(%eax),%eax")
83 (define (i386:push-local-de-ref n)
84 (or n (error "invalid value: push-byte-local-de-ref: " n))
85 (let ((n (- 0 (* 4 n))))
86 `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
87 `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
88 ("mov____(%eax),%eax")
91 (define (i386:local-add n v)
92 (or n (error "invalid value: i386:local-add: " n))
93 (let ((n (- 0 (* 4 n))))
94 `(,(if (and (< (abs n) #x80)
95 (< (abs v) #x80)) `("add____$i8,0x8(%ebp)" (#:immediate1 ,n) (#:immediate1 ,v))
96 `("add____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v))))))
98 (define (i386:accu->local n)
99 (or n (error "invalid value: accu->local: " n))
100 (let ((n (- 0 (* 4 n))))
101 `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%ebp)" (#:immediate1 ,n))
102 `("mov____%eax,0x32(%ebp)" (#:immediate ,n))))))
104 (define (i386:base->local n)
105 (or n (error "invalid value: base->local: " n))
106 `(("mov____%edx,0x8(%ebp)" ,(- 0 (* 4 n))))) ; mov %edx,-<0xn>(%ebp)
108 (define (i386:base->local n)
109 (or n (error "invalid value: base->local: " n))
110 (let ((n (- 0 (* 4 n))))
111 `((if (< (abs n) #x80) `("mov____%edx,0x8(%ebp)" (#:immediate1 ,n))
112 `("mov____%edx,0x32(%ebp)" (#:immediate ,n))))))
114 (define (i386:local->accu n)
115 (or n (error "invalid value: local->accu: " n))
116 (let ((n (- 0 (* 4 n))))
117 `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
118 `("mov____0x32(%ebp),%eax" (#:immediate ,n))))))
120 (define (i386:local-address->accu n)
121 (or n (error "invalid value: ladd: " n))
122 (let ((n (- 0 (* 4 n))))
123 `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%eax" (#:immediate1 ,n))
124 `("lea____0x32(%ebp),%eax" (#:immediate ,n))))))
126 (define (i386:local-ptr->accu n)
127 (or n (error "invalid value: local-ptr->accu: " n))
128 (let ((n (- 0 (* 4 n))))
129 `(("mov____%ebp,%eax") ; mov %ebp,%eax
130 ,(if (< (abs n) #x80) `("add____$i8,%eax" (#:immediate1 ,n))
131 `("add____$i32,%eax" (#:immediate ,n))))))
133 (define (i386:byte-local->accu n)
134 (or n (error "invalid value: byte-local->accu: " n))
135 (let ((n (- 0 (* 4 n))))
136 `(,(if (< (abs n) #x80) `("movzbl_0x8(%ebp),%eax" (#:immediate1 ,n))
137 `("movzbl_0x32(%ebp),%eax" (#:immediate ,n))))))
139 (define (i386:byte-local->base n)
140 (or n (error "invalid value: byte-local->base: " n))
141 (let ((n (- 0 (* 4 n))))
142 `(,(if (< (abs n) #x80) `("movzbl_0x8(%ebp),%edx" (#:immediate1 ,n))
143 `,@(("mov_0x32(%ebp),%edx" (#:immediate ,n))
144 ("movzbl_%dl,%edx"))))))
146 (define (i386:local->base n)
147 (or n (error "invalid value: local->base: " n))
148 (let ((n (- 0 (* 4 n))))
149 `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%edx" (#:immediate1 ,n))
150 `("mov____0x32(%ebp),%edx" (#:immediate ,n))))))
152 (define (i386:local-address->base n) ;; DE-REF
153 (or n (error "invalid value: local-address->base: " n))
154 (let ((n (- 0 (* 4 n))))
155 `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%edx" (#:immediate1 ,n))
156 `("lea____0x32(%ebp),%edx" (#:immediate ,n))))))
158 (define (i386:local-ptr->base n)
159 (or n (error "invalid value: local-ptr->base: " n))
160 (let ((n (- 0 (* 4 n))))
161 `(("mov____%ebp,%edx") ; mov %ebp,%edx
162 ,(if (< (abs n) #x80) `("add____$i8,%edx" (#:immediate1 ,n))
163 `("add____$i32,%edx" (#:immediate ,n))))))
165 (define (i386:value->local n v)
166 (or n (error "invalid value: value->local: " n))
167 (let ((n (- 0 (* 4 n))))
168 `(,(if (< (abs n) #x80) `("mov____$i32,0x8(%ebp)" (#:immediate1 ,n) (#:immediate ,v))
169 `("mov____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v))))))
171 (define (i386:local-test n v)
172 (or n (error "invalid value: local-test: " n))
173 (let ((n (- 0 (* 4 n))))
174 `(,(cond ((and (< (abs n) #x80)
175 (< (abs v) #x80)) `("cmp____$i8,0x8(%ebp)" (#:immediate1 ,n) (#:immediate1 ,v)))
176 ((< (abs n) #x80) `("cmp____$i32,0x8(%ebp)" (#:immediate1 ,n) (#:immediate ,v)))
177 ((< (abs v) #x80) `("cmp____$i8,0x32(%ebp)" (#:immediate ,n) (#:immediate1 ,v)))
178 (else `("cmp____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v)))))))
180 (define (i386:pop-accu)
181 '(("pop____%eax"))) ; pop %eax
183 (define (i386:push-accu)
184 '(("push___%eax"))) ; push %eax
186 (define (i386:pop-base)
187 '(("pop____%edx"))) ; pop %edx
189 (define (i386:push-base)
190 '(("push___%edx"))) ; push %edx
196 (define (i386:accu->base)
197 '(("mov____%eax,%edx"))) ; mov %eax,%edx
199 (define (i386:accu->base-address)
200 '(("mov____%eax,(%edx)"))) ; mov %eax,(%edx)
202 (define (i386:byte-accu->base-address)
203 '(("mov____%al,(%edx)"))) ; mov %al,(%edx)
205 (define (i386:accu->base-address+n n)
206 (or n (error "invalid value: accu->base-address+n: " n))
207 `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%edx)" (#:immediate1 ,n))
208 `("mov____%eax,0x32(%edx)" (#:immediate ,n)))))
210 (define (i386:accu->label label)
211 `(("mov____%eax,0x32" (#:address ,label)))) ; mov %eax,0x<label>
213 (define (i386:accu-zero?)
214 '(("test___%eax,%eax")))
216 (define (i386:accu-shl n)
217 (or n (error "invalid value: accu:shl n: " n))
218 `(("shl____$i8,%eax" (#:immediate1 ,n)))) ; shl $0x8,%eax
220 (define (i386:accu<<base)
221 '(("xor____%ecx,%ecx") ; xor %ecx,%ecx
222 ("mov____%edx,%ecx") ; mov %edx,%ecx
223 ("shl____%cl,%eax"))) ; shl %cl,%eax
225 (define (i386:accu>>base)
226 '(("xor____%ecx,%ecx") ; xor %ecx,%ecx
227 ("mov____%edx,%ecx") ; mov %edx,%ecx
228 ("shr____%cl,%eax"))) ; shr %cl,%eax
230 (define (i386:accu-and-base)
231 '(("and____%edx,%eax"))) ; and %edx,%eax
233 (define (i386:accu-not)
234 '(("not____%eax"))) ; not %eax
236 (define (i386:accu-or-base)
237 '(("or_____%edx,%eax"))) ; or %edx,%eax
239 (define (i386:accu-xor-base)
240 '(("xor____%edx,%eax"))) ; xor %edx,%eax
242 (define (i386:accu+accu)
243 '(("add____%eax,%eax"))) ; add %eax,%eax
245 (define (i386:accu+base)
246 `(("add____%edx,%eax"))) ; add %edx,%eax
248 (define (i386:accu+value v)
249 `(,(if (< (abs v) #x80) `("add____$i8,%eax" (#:immediate1 ,v))
250 `("add____$i32,%eax" (#:immediate ,v)))))
252 (define (i386:base+value v)
253 `(,(if (< (abs v) #x80) `("add____$i8,%edx" (#:immediate1 ,v))
254 `("add____$i32,%edx" (#:immediate ,v)))))
256 (define (i386:accu-base)
257 `(("sub____%edx,%eax"))) ; sub %edx,%eax
259 (define (i386:accu*base)
260 `(("mul____%edx"))) ; mul %edx
262 (define (i386:accu/base)
263 '(("mov____%edx,%ebx") ; mov %edx,%ebx
264 ("xor____%edx,%edx") ; xor %edx,%edx
265 ("idiv___%ebx"))) ; div %ebx
267 (define (i386:accu%base)
268 '(("mov____%edx,%ebx") ; mov %edx,%ebx
269 ("xor____%edx,%edx") ; xor %edx,%edx
270 ("idiv___%ebx") ; div %ebx
271 ("mov____%edx,%eax"))) ; mov %edx,%eax
273 (define (i386:base->accu)
274 '(("mov____%edx,%eax"))) ; mov %edx,%eax
276 (define (i386:label->accu label)
277 `(("mov____$i32,%eax" (#:address ,label)))) ; mov $<n>,%eax
279 (define (i386:label->base label)
280 `(("mov____$i32,%edx" (#:address ,label)))) ; mov $<n>,%edx
282 (define (i386:label-mem->accu label)
283 `(("mov____0x32,%eax" (#:address ,label)))) ; mov 0x<n>,%eax
285 (define (i386:label-mem->base label)
286 `(("mov____0x32,%edx" (#:address ,label)))) ; mov 0x<n>,%edx
288 (define (i386:label-mem-add label v)
289 `(,(if (< (abs v) #x80) `("add____$i8,0x32" (#:address ,label) (#:immediate1 ,v))
290 `("add____$i32,0x32" (#:address ,label) (#:immediate ,v)))))
292 (define (i386:byte-base-mem->accu)
293 '(("add____%edx,%eax") ; add %edx,%eax
294 ("movzbl_(%eax),%eax"))) ; movzbl (%eax),%eax
296 (define (i386:byte-mem->accu)
297 '(("movzbl_(%eax),%eax"))) ; movzbl (%eax),%eax
299 (define (i386:byte-mem->base)
300 '(("movzbl_(%edx),%edx"))) ; movzbl (%edx),%edx
302 (define (i386:base-mem->accu)
303 '(("add___%edx,%eax") ; add %edx,%eax
304 ("mov____(%eax),%eax"))) ; mov (%eax),%eax
306 (define (i386:mem->accu)
307 '(("mov____(%eax),%eax"))) ; mov (%eax),%eax
309 (define (i386:mem->base)
310 '(("mov____(%edx),%edx"))) ; mov (%edx),%edx
312 (define (i386:mem+n->accu n)
313 `(,(if (< (abs n) #x80) `("mov____0x8(%eax),%eax" (#:immediate1 ,n))
314 `("mov____0x32(%eax),%eax" (#:immediate ,n)))))
316 (define (i386:base-mem+n->accu v)
317 (or v (error "invalid value: base-mem+n->accu: " v))
318 `(("add___%edx,%eax")
319 ,(if (< (abs v) #x80) `("mov____0x8(%eax),%eax" (#:immediate1 ,v))
320 `("mov____0x32(%eax),%eax" (#:immediate ,v)))))
322 (define (i386:value->accu v)
323 (or v (error "invalid value: i386:value->accu: " v))
324 `(("mov____$i32,%eax" (#:immediate ,v)))) ; mov $<v>,%eax
326 (define (i386:value->accu-address v)
327 `(("mov____$i32,(%eax)" (#:immediate ,v)))) ; movl $0x<v>,(%eax)
329 (define (i386:value->accu-address+n n v)
330 (or v (error "invalid value: i386:value->accu-address+n: " v))
331 `(,(if (< (abs v) #x80) `("mov____$i32,0x8(%eax)" (#:immediate1 ,n) (#:immediate ,v))
332 `("mov____$i32,0x32(%eax)" (#:immediate ,n) (#:immediate ,v)))))
334 (define (i386:base->accu-address)
335 '(("mov____%edx,(%eax)"))) ; mov %edx,(%eax)
337 (define (i386:base-address->accu-address)
338 '(("mov____(%edx),%ecx") ; mov (%edx),%ecx
339 ("mov____%ecx,(%eax)"))) ; mov %ecx,(%eax)
341 (define (i386:byte-base->accu-address)
342 '(("mov____%dl,(%eax)"))) ; mov %dl,(%eax)
344 (define (i386:byte-base->accu-address+n n)
345 (or n (error "invalid value: byte-base->accu-address+n: " n))
346 `(,(if (< (abs n) #x80) `("mov____%dl,0x8(%eax)" (#:immediate1 ,n))
347 `("mov____%dl,0x32(%eax)" (#:immediate ,n)))))
349 (define (i386:value->base v)
350 (or v (error "invalid value: i386:value->base: " v))
351 `(("mov____$i32,%edx" (#:immediate ,v)))) ; mov $<v>,%edx
353 (define (i386:accu-mem-add v)
354 `(,(if (< (abs v) #x80) `("add____$i8,(%eax)" (#:immediate1 ,v))
355 `("add____$i32,(%eax)" (#:immediate ,v)))))
357 (define (i386:value->label label v)
358 (or v (error "invalid value: value->label: " v))
359 `(("mov____$i32,0x32" (#:address ,label)
362 (define (i386:call-label label n)
363 `((call32 (#:offset ,label))
364 ("add____$i8,%esp" (#:immediate1 ,(* n 4)))))
366 (define (i386:call-accu n)
369 ("call___*%eax") ; call *%eax
370 ("add____$i8,%esp" (#:immediate1 ,(* n 4))))) ; add $00,%esp
372 (define (i386:accu-negate)
373 '(("sete___%al") ; sete %al
374 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
376 (define (i386:xor-accu v)
377 (or v (error "invalid value: i386:xor-accu: n: " v))
378 `(("xor___$i32,%eax" (#:immediate ,v)))) ;xor $0xff,%eax
380 (define (i386:xor-zf)
382 ("xor____$i8,%ah" (#:immediate1 #x40)) ; xor $0x40,%ah
385 (define (i386:accu-cmp-value v)
386 `(,(if (< (abs v) #x80) `("cmp____$i8,%eax" (#:immediate1 ,v))
387 `("cmp____$i32,%eax" (#:immediate ,v)))))
389 (define (i386:accu-test)
390 '(("test___%eax,%eax"))) ; test %eax,%eax
392 (define (i386:jump label)
393 `(("jmp32 " (#:offset ,label))))
395 (define (i386:jump-z label)
396 `(("je32 " (#:offset ,label)))) ; jz . + <n>
398 (define (i386:jump-byte-z label)
399 `(("test___%al,%al") ; test %al,%al
400 ("je32 " (#:offset ,label)))) ; je <n>
403 (define (i386:jump-g label)
404 `(("jg32 " (#:offset ,label)))) ; jg/jnle <n>
407 (define (i386:jump-ge label)
408 `(("jge32 " (#:offset ,label)))) ; jge/jnl <n>
410 (define (i386:jump-nz label)
411 `(("jne32 " (#:offset ,label)))) ; jnz . + <n>
413 (define (i386:byte-test-base)
414 '(("cmp____%al,%dl"))) ; cmp %al,%dl
416 (define (i386:test-base)
417 (("cmp____%edx,%eax"))) ; cmp %edx,%eax
419 (define (i386:byte-sub-base)
420 '(("sub____%dl,%al"))) ; sub %dl,%al
422 (define (i386:byte-base-sub)
423 `(("sub____%al,%dl"))) ; sub %al,%dl
425 (define (i386:sub-base)
426 `(("sub____%edx,%eax"))) ; sub %edx,%eax
428 (define (i386:base-sub)
429 `(("sub____%eax,%edx"))) ; sub %eax,%edx
431 (define (i386:nz->accu)
432 '(("setne__%al") ; setne %al
433 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
435 (define (i386:z->accu)
436 '(("sete___%al") ; sete %al
437 ("movzbl_%al,%eax"))) ; movzbl %al,%eax
439 (define (i386:accu<->stack)
440 '(("xchg___%eax,(%esp)"))) ; xchg %eax,(%esp)