mescc: Posixify interface.
[mes.git] / module / mescc / i386 / as.scm
1 ;;; Mes --- Maxwell Equations of Software
2 ;;; Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
3 ;;;
4 ;;; This file is part of Mes.
5 ;;;
6 ;;; Mes is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
10 ;;;
11 ;;; Mes is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;; GNU General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with Mes.  If not, see <http://www.gnu.org/licenses/>.
18
19 ;;; Commentary:
20
21 ;;; define i386 assembly
22
23 ;;; Code:
24
25 (define-module (mescc i386 as)
26   #:use-module (mes guile)
27   #:use-module (mescc as)
28   #:export (
29             i386:accu%base
30             i386:accu*base
31             i386:accu*n->label
32             i386:accu*n->local
33             i386:accu+accu
34             i386:accu+base
35             i386:accu+value
36             i386:accu->base
37             i386:accu->base-mem
38             i386:byte-accu->base-mem
39             i386:word-accu->base-mem
40             i386:accu->base-mem+n
41             i386:byte-accu->base-mem+n
42             i386:word-accu->base-mem+n
43             i386:accu->label
44             i386:accu->local
45             i386:accu->local+n
46             i386:accu->local+n
47             i386:accu-and
48             i386:accu-and-base
49             i386:accu-and-base-mem
50             i386:accu-base
51             i386:accu-cmp-value
52             i386:accu-mem-add
53             i386:accu-mem->base-mem
54             i386:accu-negate
55             i386:accu-not
56             i386:accu-or-base
57             i386:accu-or-base-mem
58             i386:accu-shl
59             i386:accu-test
60             i386:accu-xor-base
61             i386:accu-zero?
62             i386:accu/base
63             i386:accu<->stack
64             i386:accu<<base
65             i386:accu>>base
66             i386:base+value
67             i386:base->accu
68             i386:base->accu-mem
69             i386:base->label
70             i386:base-mem->accu-mem
71             i386:base-mem+n->accu
72             i386:base-mem->accu
73             i386:base-sub
74             i386:byte-accu->base-mem
75             i386:word-accu->base-mem
76             i386:byte-base->accu-mem
77             i386:byte-base->accu-mem+n
78             i386:byte-base-mem->accu
79             i386:byte-base-sub
80             i386:byte-local->base
81             i386:byte-mem->accu
82             i386:word-mem->accu
83             i386:byte-mem->base
84             i386:byte-sub-base
85             i386:byte-test-base
86             i386:call-accu
87             i386:call-label
88             i386:formal
89             i386:function-locals
90             i386:function-preamble
91             i386:jump
92             i386:jump
93             i386:jump-a
94             i386:jump-ae
95             i386:jump-b
96             i386:jump-be
97             i386:jump-byte-z
98             i386:jump-g
99             i386:jump-ge
100             i386:jump-l
101             i386:jump-le
102             i386:jump-nz
103             i386:jump-z
104             i386:label->accu
105             i386:label->base
106             i386:label-mem->accu
107             i386:label-mem->base
108             i386:label-mem-add
109             i386:local->accu
110             i386:local->base
111             i386:local-add
112             i386:local-address->accu
113             i386:local-address->accu
114             i386:local-address->base
115             i386:local-ptr->accu
116             i386:local-ptr->base
117             i386:local-test
118             i386:mem+n->accu
119             i386:byte-mem+n->accu
120             i386:word-mem+n->accu
121             i386:mem->accu
122             i386:mem->base
123             i386:nop
124             i386:nz->accu
125             i386:pop-accu
126             i386:pop-base
127             i386:push-accu
128             i386:push-base
129             i386:push-byte-local-de-de-ref
130             i386:push-byte-local-de-ref
131             i386:push-word-local-de-ref
132             i386:push-label
133             i386:push-label-mem
134             i386:push-local
135             i386:push-local-address
136             i386:push-local-de-ref
137             i386:ret
138             i386:ret-local
139             i386:sub-base
140             i386:test-base
141             i386:value->accu
142             i386:value->accu-mem
143             i386:value->accu-mem+n
144             i386:value->base
145             i386:value->label
146             i386:value->local
147             i386:xor-accu
148             i386:xor-zf
149             i386:g?->accu
150             i386:ge?->accu
151             i386:l?->accu
152             i386:le?->accu
153             i386:a?->accu
154             i386:ae?->accu
155             i386:b?->accu
156             i386:be?->accu
157             i386:z->accu
158             i386:byte-accu
159             i386:signed-byte-accu
160             i386:word-accu
161             i386:signed-word-accu
162             ))
163
164 (define (i386:nop)
165   '(("nop")))
166
167 (define (i386:function-preamble)
168   '(("push___%ebp")
169     ("mov____%esp,%ebp")))
170
171 (define (i386:function-locals)
172   `(("sub____%esp,$i32" (#:immediate ,(+ (* 4 1025) (* 20 4)))))) ; sub %esp,xxx 4*1024 buf, 20 local vars
173
174 (define (i386:push-label label)
175   `(("push___$i32" (#:address ,label)))) ; push  $0x<label>
176
177 (define (i386:push-label-mem label)
178   `(("mov____0x32,%eax" (#:address ,label)) ; mov    0x804a000,%eax
179     ("push___%eax")))                       ; push  %eax
180
181
182 ;;; \f locals
183
184 (define (i386:push-local n)
185   (or n (error "invalid value: push-local: " n))
186   (let ((n (- 0 (* 4 n))))
187     `(,(if (< (abs n) #x80) `("push___0x8(%ebp)" (#:immediate1 ,n))
188            `("push___0x32(%ebp)" (#:immediate ,n))))))
189
190 (define (i386:push-local-address n)
191   (or n (error "invalid value: push-local-address: " n))
192   (let ((n (- 0 (* 4 n))))
193     `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%eax" (#:immediate1 ,n))
194            `("lea____0x32(%ebp),%eax" (#:immediate ,n)))
195       ("push___%eax"))))
196
197 (define (i386:push-byte-local-de-ref n)
198   (or n (error "invalid value: push-byte-local-de-ref: " n))
199   (let ((n (- 0 (* 4 n))))
200     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
201            `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
202       ("movzbl_(%eax),%eax")
203       ("push___%eax"))))
204
205 (define (i386:push-word-local-de-ref n)
206   (or n (error "invalid value: push-word-local-de-ref: " n))
207   (let ((n (- 0 (* 4 n))))
208     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
209            `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
210       ("movzwl_(%eax),%eax")
211       ("push___%eax"))))
212
213 (define (i386:push-byte-local-de-de-ref n)
214   (or n (error "invalid value: push-byte-local-de-de-ref: " n))
215   (let ((n (- 0 (* 4 n))))
216     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
217            `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
218       ("mov____(%eax),%eax")
219       ("movzbl_(%eax),%eax")
220       ("push___%eax"))))
221
222 (define (i386:push-local-de-ref n)
223   (or n (error "invalid value: push-byte-local-de-ref: " n))
224   (let ((n (- 0 (* 4 n))))
225     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
226            `("mov____0x32(%ebp),%eax" (#:immediate ,n)))
227       ("mov____(%eax),%eax")
228       ("push___%eax"))))
229
230 (define (i386:local-add n v)
231   (or n (error "invalid value: i386:local-add: " n))
232   (let ((n (- 0 (* 4 n))))
233     `(,(if (and (< (abs n) #x80)
234                 (< (abs v) #x80)) `("add____$i8,0x8(%ebp)" (#:immediate1 ,n) (#:immediate1 ,v))
235                 `("add____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v))))))
236
237 (define (i386:accu->local n)
238   (or n (error "invalid value: accu->local: " n))
239   (let ((n (- 0 (* 4 n))))
240     `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%ebp)" (#:immediate1 ,n))
241            `("mov____%eax,0x32(%ebp)" (#:immediate ,n))))))
242
243 (define (i386:accu->local+n id n)
244   (let ((n (+ (- 0 (* 4 id)) n)))
245     `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%ebp)" (#:immediate1 ,n))
246            `("mov____%eax,0x32(%ebp)" (#:immediate ,n))))))
247
248 (define (i386:accu*n->local i n)
249   (or n (error "invalid value: accu->local: " n))
250   (let ((o (- 0 (* 4 i))))
251     (let loop ((i 0))
252       (if (>= i n) '()  ;; FIXME: byte, word-sized
253           (let ((o (+ o i)))
254             (append
255              (if (< (abs o) #x80) `(("mov____0x8(%eax),%ebx" (#:immediate1 ,i))
256                                     ("mov____%ebx,0x8(%ebp)" (#:immediate1 ,o)))
257                  `(("mov____0x8(%eax),%ebx" (#:immediate1 ,i))
258                    ("mov____%ebx,0x32(%ebp)" (#:immediate ,o))))
259              (loop (+ i 4))))))))
260
261 (define (i386:local->accu n)
262   (or n (error "invalid value: local->accu: " n))
263   (let ((n (- 0 (* 4 n))))
264     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%eax" (#:immediate1 ,n))
265            `("mov____0x32(%ebp),%eax" (#:immediate ,n))))))
266
267 (define (i386:local-address->accu n)
268   (or n (error "invalid value: ladd: " n))
269   (let ((n (- 0 (* 4 n))))
270     `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%eax" (#:immediate1 ,n))
271            `("lea____0x32(%ebp),%eax" (#:immediate ,n))))))
272
273 (define (i386:local-ptr->accu n)
274   (or n (error "invalid value: local-ptr->accu: " n))
275   (let ((n (- 0 (* 4 n))))
276   `(("mov____%ebp,%eax")                ; mov    %ebp,%eax
277     ,(if (< (abs n) #x80) `("add____$i8,%eax" (#:immediate1 ,n))
278          `("add____$i32,%eax" (#:immediate ,n))))))
279
280 (define (i386:byte-local->base n)
281   (or n (error "invalid value: byte-local->base: " n))
282   (let ((n (- 0 (* 4 n))))
283     `(,(if (< (abs n) #x80) `("movzbl_0x8(%ebp),%edx" (#:immediate1 ,n))
284            `,@(("mov_0x32(%ebp),%edx" (#:immediate ,n))
285                ("movzbl_%dl,%edx"))))))
286
287 (define (i386:local->base n)
288   (or n (error "invalid value: local->base: " n))
289   (let ((n (- 0 (* 4 n))))
290     `(,(if (< (abs n) #x80) `("mov____0x8(%ebp),%edx" (#:immediate1 ,n))
291            `("mov____0x32(%ebp),%edx" (#:immediate ,n))))))
292
293 (define (i386:local-address->base n) ;; DE-REF
294   (or n (error "invalid value: local-address->base: " n))
295   (let ((n (- 0 (* 4 n))))
296     `(,(if (< (abs n) #x80) `("lea____0x8(%ebp),%edx" (#:immediate1 ,n))
297            `("lea____0x32(%ebp),%edx" (#:immediate ,n))))))
298
299 (define (i386:local-ptr->base n)
300   (or n (error "invalid value: local-ptr->base: " n))
301   (let ((n (- 0 (* 4 n))))
302     `(("mov____%ebp,%edx")                ; mov    %ebp,%edx
303       ,(if (< (abs n) #x80) `("add____$i8,%edx" (#:immediate1 ,n))
304            `("add____$i32,%edx" (#:immediate ,n))))))
305
306 (define (i386:value->local n v)
307   (or n (error "invalid value: value->local: " n))
308   (let ((n (- 0 (* 4 n))))
309     `(,(if (< (abs n) #x80) `("mov____$i32,0x8(%ebp)" (#:immediate1 ,n) (#:immediate ,v))
310            `("mov____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v))))))
311
312 (define (i386:local-test n v)
313   (or n (error "invalid value: local-test: " n))
314   (let ((n (- 0 (* 4 n))))
315     `(,(cond ((and (< (abs n) #x80)
316                    (< (abs v) #x80)) `("cmp____$i8,0x8(%ebp)" (#:immediate1 ,n) (#:immediate1 ,v)))
317              ((< (abs n) #x80) `("cmp____$i32,0x8(%ebp)" (#:immediate1 ,n) (#:immediate ,v)))
318              ((< (abs v) #x80) `("cmp____$i8,0x32(%ebp)" (#:immediate ,n) (#:immediate1 ,v)))
319              (else `("cmp____$i32,0x32(%ebp)" (#:immediate ,n) (#:immediate ,v)))))))
320
321 (define (i386:pop-accu)
322   '(("pop____%eax")))                   ; pop %eax
323
324 (define (i386:push-accu)
325   '(("push___%eax")))                   ; push %eax
326
327 (define (i386:pop-base)
328   '(("pop____%edx")))                   ; pop %edx
329
330 (define (i386:push-base)
331   '(("push___%edx")))                   ; push %edx
332
333 (define (i386:ret)
334   '(("leave")                           ; leave
335     ("ret")))                           ; ret
336
337 (define (i386:accu->base)
338   '(("mov____%eax,%edx")))              ; mov    %eax,%edx
339
340 (define (i386:accu->base-mem)
341   '(("mov____%eax,(%edx)")))            ; mov    %eax,(%edx)
342
343 (define (i386:byte-accu->base-mem)
344   '(("mov____%al,(%edx)")))             ; mov    %al,(%edx)
345
346 (define (i386:word-accu->base-mem)
347   '(("mov____%ax,(%edx)")))             ; mov    %ax,(%edx)
348
349 (define (i386:accu->base-mem+n n)
350   (or n (error "invalid value: accu->base-mem+n: " n))
351   `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%edx)" (#:immediate1 ,n))
352          `("mov____%eax,0x32(%edx)" (#:immediate ,n)))))
353
354 (define (i386:byte-accu->base-mem+n n)
355   (or n (error "invalid value: accu->base-mem+n: " n))
356   `(,(if (< (abs n) #x80) `("mov____%al,0x8(%edx)" (#:immediate1 ,n))
357          `("mov____%al,0x32(%edx)" (#:immediate ,n)))))
358
359 (define (i386:word-accu->base-mem+n n)
360   (or n (error "invalid value: accu->base-mem+n: " n))
361   `(,(if (< (abs n) #x80) `("mov____%ax,0x8(%edx)" (#:immediate1 ,n))
362          `("mov____%ax,0x32(%edx)" (#:immediate ,n)))))
363
364 (define (i386:accu->label label)
365   `(("mov____%eax,0x32" (#:address ,label)))) ; mov    %eax,0x<label>
366
367 (define (i386:accu*n->label label n)
368   (append
369    '(("push___%edx"))
370    (let loop ((i 0))
371      (if (>= i n) '() ;; FIXME: byte, word-sized
372          (append
373           `(("mov____$i32,%edx" (#:address ,label))
374             ("mov____0x8(%eax),%ebx" (#:immediate1 ,i))
375             ("mov____%ebx,0x8(%edx)" (#:immediate1 ,i)))
376           (loop (+ i 4)))))
377    '(("pop____%edx"))))
378
379 (define (i386:accu-shl n)
380   (or n (error "invalid value: accu:shl n: " n))
381   `(("shl____$i8,%eax" (#:immediate1 ,n)))) ; shl    $0x8,%eax
382
383 (define (i386:accu<<base)
384   '(("xor____%ecx,%ecx")                ; xor    %ecx,%ecx
385     ("mov____%edx,%ecx")                ; mov    %edx,%ecx
386     ("shl____%cl,%eax")))               ; shl    %cl,%eax
387
388 (define (i386:accu>>base)
389   '(("xor____%ecx,%ecx")                ; xor    %ecx,%ecx
390     ("mov____%edx,%ecx")                ; mov    %edx,%ecx
391     ("shr____%cl,%eax")))               ; shr    %cl,%eax
392
393 (define (i386:accu-and-base)
394   '(("and____%edx,%eax")))
395
396 (define (i386:accu-and v)
397   `(("and____$i32,%eax" (#:immediate ,v))))
398
399 (define (i386:accu-and-base-mem)
400   '(("and____(%edx),%eax")))
401
402 (define (i386:accu-or-base-mem)
403   '(("or_____(%edx),%eax")))
404
405 (define (i386:accu-not)
406   '(("not____%eax")))                   ; not %eax
407
408 (define (i386:accu-or-base)
409   '(("or_____%edx,%eax")))              ; or    %edx,%eax
410
411 (define (i386:accu-xor-base)
412   '(("xor____%edx,%eax")))              ; xor    %edx,%eax
413
414 (define (i386:accu+accu)
415   '(("add____%eax,%eax")))              ; add    %eax,%eax
416
417 (define (i386:accu+base)
418   `(("add____%edx,%eax")))              ; add    %edx,%eax
419
420 (define (i386:accu+value v)
421   `(,(if (< (abs v) #x80) `("add____$i8,%eax" (#:immediate1 ,v))
422          `("add____$i32,%eax" (#:immediate ,v)))))
423
424 (define (i386:base+value v)
425   `(,(if (< (abs v) #x80) `("add____$i8,%edx" (#:immediate1 ,v))
426          `("add____$i32,%edx" (#:immediate ,v)))))
427
428 (define (i386:accu-base)
429   `(("sub____%edx,%eax")))              ; sub    %edx,%eax
430
431 (define (i386:accu*base)
432   `(("mul____%edx")))                   ; mul    %edx
433
434 (define (i386:accu/base)
435   '(("mov____%edx,%ebx")                ; mov    %edx,%ebx
436     ("xor____%edx,%edx")                ; xor    %edx,%edx
437     ("idiv___%ebx")))                   ; div    %ebx
438
439 (define (i386:accu%base)
440   '(("mov____%edx,%ebx")                ; mov    %edx,%ebx
441     ("xor____%edx,%edx")                ; xor    %edx,%edx
442     ("idiv___%ebx")                     ; div    %ebx
443     ("mov____%edx,%eax")))              ; mov    %edx,%eax
444
445 (define (i386:base->accu)
446   '(("mov____%edx,%eax")))              ; mov    %edx,%eax
447
448 (define (i386:label->accu label)
449   `(("mov____$i32,%eax" (#:address ,label)))) ; mov    $<n>,%eax
450
451 (define (i386:label->base label)
452   `(("mov____$i32,%edx" (#:address ,label)))) ; mov   $<n>,%edx
453
454 (define (i386:label-mem->accu label)
455   `(("mov____0x32,%eax" (#:address ,label)))) ; mov    0x<n>,%eax
456
457 (define (i386:label-mem->base label)
458   `(("mov____0x32,%edx" (#:address ,label)))) ; mov    0x<n>,%edx
459
460 (define (i386:label-mem-add label v)
461   `(,(if (< (abs v) #x80) `("add____$i8,0x32" (#:address ,label) (#:immediate1 ,v))
462          `("add____$i32,0x32" (#:address ,label) (#:immediate ,v)))))
463
464 (define (i386:byte-base-mem->accu)
465   '(("add____%edx,%eax")                ; add    %edx,%eax
466     ("movzbl_(%eax),%eax")))            ; movzbl (%eax),%eax
467
468 (define (i386:byte-mem->accu)
469   '(("movzbl_(%eax),%eax")))            ; movzbl (%eax),%eax
470
471 (define (i386:word-mem->accu)
472   '(("movzwl_(%eax),%eax")))
473
474 (define (i386:byte-mem->base)
475   '(("movzbl_(%edx),%edx")))            ; movzbl (%edx),%edx
476
477 (define (i386:base-mem->accu)
478   '(("mov____(%edx),%eax")))
479
480 (define (i386:mem->accu)
481   '(("mov____(%eax),%eax")))
482
483 (define (i386:mem->base)
484   '(("mov____(%edx),%edx")))
485
486 (define (i386:mem+n->accu n)
487   `(,(if (< (abs n) #x80) `("mov____0x8(%eax),%eax" (#:immediate1 ,n))
488          `("mov____0x32(%eax),%eax" (#:immediate ,n)))))
489
490 (define (i386:byte-mem+n->accu n)
491   `(,(if (< (abs n) #x80) `("movzbl_0x8(%eax),%eax" (#:immediate1 ,n))
492          `("movzbl_0x32(%eax),%eax" (#:immediate ,n)))))
493
494 (define (i386:word-mem+n->accu n)
495   `(,(if (< (abs n) #x80) `("movzwl_0x8(%eax),%eax" (#:immediate1 ,n))
496          `("movzwl_xb0x32(%eax),%eax" (#:immediate ,n)))))
497
498 (define (i386:base-mem+n->accu v)
499   (or v (error "invalid value: base-mem+n->accu: " v))
500   `(("add___%edx,%eax")
501     ,(if (< (abs v) #x80) `("mov____0x8(%eax),%eax" (#:immediate1 ,v))
502          `("mov____0x32(%eax),%eax" (#:immediate ,v)))))
503
504 (define (i386:value->accu v)
505   (or v (error "invalid value: i386:value->accu: " v))
506   `(("mov____$i32,%eax" (#:immediate ,v)))) ; mov    $<v>,%eax
507
508 (define (i386:value->accu-mem v)
509   `(("mov____$i32,(%eax)" (#:immediate ,v)))) ; movl   $0x<v>,(%eax)
510
511 (define (i386:value->accu-mem+n n v)
512   (or v (error "invalid value: i386:value->accu-mem+n: " v))
513   `(,(if (< (abs v) #x80) `("mov____$i32,0x8(%eax)" (#:immediate1 ,n) (#:immediate ,v))
514          `("mov____$i32,0x32(%eax)" (#:immediate ,n) (#:immediate ,v)))))
515
516 (define (i386:base->accu-mem)
517   '(("mov____%edx,(%eax)")))            ; mov    %edx,(%eax)
518
519 (define (i386:accu-mem->base-mem)
520   '(("mov____(%eax),%ecx")
521     ("mov____%ecx,(%edx)")))
522
523 (define (i386:base-mem->accu-mem)
524   '(("mov____(%edx),%ecx")              ; mov    (%edx),%ecx
525     ("mov____%ecx,(%eax)")))            ; mov    %ecx,(%eax)
526
527 (define (i386:byte-base->accu-mem)
528   '(("mov____%dl,(%eax)")))             ; mov    %dl,(%eax)
529
530 (define (i386:byte-base->accu-mem+n n)
531   (or n (error "invalid value: byte-base->accu-mem+n: " n))
532   `(,(if (< (abs n) #x80) `("mov____%dl,0x8(%eax)" (#:immediate1 ,n))
533          `("mov____%dl,0x32(%eax)" (#:immediate ,n)))))
534
535 (define (i386:value->base v)
536   (or v (error "invalid value: i386:value->base: " v))
537   `(("mov____$i32,%edx" (#:immediate ,v)))) ; mov    $<v>,%edx
538
539 (define (i386:accu-mem-add v)
540   `(,(if (< (abs v) #x80) `("add____$i8,(%eax)" (#:immediate1 ,v))
541          `("add____$i32,(%eax)" (#:immediate ,v)))))
542
543 (define (i386:value->label label v)
544   (or v (error "invalid value: value->label: " v))
545   `(("mov____$i32,0x32" (#:address ,label)
546      (#:immediate ,v))))
547
548 (define (i386:call-label label n)
549   `((call32 (#:offset ,label))
550     ("add____$i8,%esp" (#:immediate1 ,(* n 4)))))
551
552 (define (i386:call-accu n)
553   `(,@(i386:push-accu)
554     ,@(i386:pop-accu)
555     ("call___*%eax")                    ; call   *%eax
556     ("add____$i8,%esp" (#:immediate1  ,(* n 4))))) ; add    $00,%esp
557
558 (define (i386:accu-zero?)
559   '(("test___%eax,%eax")))
560
561 (define (i386:accu-negate)
562   '(("sete___%al")                      ; sete %al
563     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
564
565 (define (i386:xor-accu v)
566   (or v (error "invalid value: i386:xor-accu: n: " v))
567   `(("xor___$i32,%eax" (#:immediate ,v)))) ;xor    $0xff,%eax
568
569 (define (i386:xor-zf)
570   '(("lahf")                               ; lahf
571     ("xor____$i8,%ah" (#:immediate1 #x40)) ; xor    $0x40,%ah
572     ("sahf")))                             ; sahf
573
574 (define (i386:accu-cmp-value v)
575   `(,(if (< (abs v) #x80) `("cmp____$i8,%eax" (#:immediate1 ,v))
576          `("cmp____$i32,%eax" (#:immediate ,v)))))
577
578 (define (i386:accu-test)
579   '(("test___%eax,%eax")))              ; test   %eax,%eax
580
581 (define (i386:jump label)
582   `(("jmp32 " (#:offset ,label))))
583
584 (define (i386:jump-z label)
585   `(("je32  " (#:offset ,label))))        ; jz . + <n>
586
587 (define (i386:jump-byte-z label)
588   `(("test___%al,%al")                  ; test   %al,%al
589     ("je32  " (#:offset ,label))))      ; je <n>
590
591 ;; signed
592 (define (i386:jump-g label)
593   `(("jg32  " (#:offset ,label))))
594
595 (define (i386:jump-ge label)
596   `(("jge32 " (#:offset ,label))))
597
598 (define (i386:jump-l label)
599   `(("jl32  " (#:offset ,label))))
600
601 (define (i386:jump-le label)
602   `(("jle32 " (#:offset ,label))))
603
604 (define (i386:g?->accu)
605   '(("setg___%al")
606     ("movzbl_%al,%eax")))
607
608 (define (i386:ge?->accu)
609   '(("setge__%al")
610     ("movzbl_%al,%eax")))
611
612 (define (i386:l?->accu)
613   '(("setl___%al")
614     ("movzbl_%al,%eax")))
615
616 (define (i386:le?->accu)
617   '(("setle__%al")
618     ("movzbl_%al,%eax")))
619
620 ;; unsigned
621 (define (i386:jump-a label)
622   `(("ja32  " (#:offset ,label))))
623
624 (define (i386:jump-ae label)
625   `(("jae32 " (#:offset ,label))))
626
627 (define (i386:jump-b label)
628   `(("jb32  " (#:offset ,label))))
629
630 (define (i386:jump-be label)
631   `(("jbe32 " (#:offset ,label))))
632
633 (define (i386:a?->accu)
634   '(("seta___%al")
635     ("movzbl_%al,%eax")))
636
637 (define (i386:ae?->accu)
638   '(("setae__%al")
639     ("movzbl_%al,%eax")))
640
641 (define (i386:b?->accu)
642   '(("setb___%al")
643     ("movzbl_%al,%eax")))
644
645 (define (i386:be?->accu)
646   '(("setbe__%al")
647     ("movzbl_%al,%eax")))
648
649 (define (i386:jump-nz label)
650   `(("jne32 " (#:offset ,label))))       ; jnz . + <n>
651
652 (define (i386:byte-test-base)
653   '(("cmp____%al,%dl")))                ; cmp    %al,%dl
654
655 (define (i386:test-base)
656   (("cmp____%edx,%eax")))               ; cmp    %edx,%eax
657
658 (define (i386:byte-sub-base)
659   '(("sub____%dl,%al")))                ; sub    %dl,%al
660
661 (define (i386:byte-base-sub)
662   `(("sub____%al,%dl")))                ; sub    %al,%dl
663
664 (define (i386:sub-base)
665   `(("sub____%edx,%eax")))              ; sub    %edx,%eax
666
667 (define (i386:base-sub)
668   `(("sub____%eax,%edx")))              ; sub    %eax,%edx
669
670 (define (i386:nz->accu)
671   '(("setne__%al")                      ; setne   %al
672     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
673
674 (define (i386:z->accu)
675   '(("sete___%al")                      ; sete   %al
676     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
677
678 (define (i386:accu<->stack)
679   '(("xchg___%eax,(%esp)")))            ; xchg   %eax,(%esp)
680
681 (define (i386:byte-accu)
682   '(("movzbl_%al,%eax")))
683
684 (define (i386:signed-byte-accu)
685   '(("movsbl_%al,%eax")))
686
687 (define (i386:word-accu)
688   '(("movzwl_%ax,%eax")))
689
690 (define (i386:signed-word-accu)
691   '(("movswl_%ax,%eax")))