mescc: Naming fix.
[mes.git] / module / mes / as-i386.mes
1 ;;; -*-scheme-*-
2
3 ;;; Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;;
6 ;;; This file is part of Mes.
7 ;;;
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.
12 ;;;
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.
17 ;;;
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/>.
20
21 ;;; Commentary:
22
23 ;;; as-i386.mes defines i386 assembly
24
25 ;;; Code:
26
27 (cond-expand
28  (guile-2)
29  (guile)
30  (mes
31   (mes-use-module (mes as))))
32
33 (define (i386:nop)
34   '(("nop")))                           ; nop
35
36 (define (i386:function-preamble)
37   '(("push___%ebp")                       ; push %ebp
38     ("mov____%esp,%ebp")))                ; mov  %esp,%ebp;
39
40 (define (i386:function-locals)
41   '(("sub____%esp,$i8" (#:immediate1 #x40)))) ; sub %esp,$0x40  # 16 local vars
42
43 (define (i386:push-label label)
44   `(("push___$i32" (#:address ,label)))) ; push  $0x<label>
45
46 (define (i386:push-label-mem label)
47   `(("mov____0x32,%eax" (#:address ,label)) ; mov    0x804a000,%eax
48     ("push___%eax")))                       ; push  %eax
49
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)
53
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
58
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
64
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
70      ("push___%eax")))
71
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
77
78 (define (i386:pop-accu)
79   '(("pop____%eax")))                   ; pop %eax
80
81 (define (i386:push-accu)
82   '(("push___%eax")))                   ; push %eax
83
84 (define (i386:pop-base)
85   '(("pop____%edx")))                   ; pop %edx
86
87 (define (i386:push-base)
88   '(("push___%edx")))                   ; push %edx
89
90 (define (i386:ret)
91   '(("leave")                           ; leave
92     ("ret")))                           ; ret
93
94 (define (i386:accu->base)
95   '(("mov____%eax,%edx")))              ; mov    %eax,%edx
96
97 (define (i386:accu->base-address)
98   '(("mov____%eax,(%edx)")))            ; mov    %eax,(%edx)
99
100 (define (i386:byte-accu->base-address)
101   '(("mov____%al,(%edx)")))             ; mov    %al,(%edx)
102
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)
106
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)
110
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)
114
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)
118
119 (define (i386:accu->label label)
120   `(("mov____%eax,0x32" (#:address ,label)))) ; mov    %eax,0x<label>
121
122 (define (i386:accu-zero?)
123   '(("test___%eax,%eax")))
124
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
128
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
133
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
138
139 (define (i386:accu-and-base)
140   '(("and____%edx,%eax")))              ; and    %edx,%eax
141
142 (define (i386:accu-not)
143   '(("not____%eax")))                   ; not %eax
144
145 (define (i386:accu-or-base)
146   '(("or_____%edx,%eax")))              ; or    %edx,%eax
147
148 (define (i386:accu-xor-base)
149   '(("xor____%edx,%eax")))              ; xor    %edx,%eax
150
151 (define (i386:accu+accu)
152   '(("add____%eax,%eax")))              ; add    %eax,%eax
153
154 (define (i386:accu+base)
155   `(("add____%edx,%eax")))              ; add    %edx,%eax
156
157 (define (i386:accu+value v)
158   (or v (error "invalid value: accu+value: " v))
159   `(("add____$i32,%eax" (#:immediate ,v)))) ; add    %eax,$
160
161 (define (i386:accu-base)
162   `(("sub____%edx,%eax")))              ; sub    %edx,%eax
163
164 (define (i386:accu*base)
165   `(("mul____%edx")))                   ; mul    %edx
166
167 (define (i386:accu/base)
168   '(("mov____%edx,%ebx")                ; mov    %edx,%ebx
169     ("xor____%edx,%edx")                ; xor    %edx,%edx
170     ("div____%ebx")))                   ; div    %ebx
171
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
177
178 (define (i386:base->accu)
179   '(("mov____%edx,%eax")))              ; mov    %edx,%eax
180
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
184
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
188
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
193
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
197
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
201
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
205
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
209
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
214
215 (define (i386:label->accu label)
216   `(("mov____$i32,%eax" (#:address ,label)))) ; mov    $<n>,%eax
217
218 (define (i386:label->base label)
219   `(("mov____$i32,%edx" (#:address ,label)))) ; mov   $<n>,%edx
220
221 (define (i386:label-mem->accu label)
222   `(("mov____0x32,%eax" (#:address ,label)))) ; mov    0x<n>,%eax
223
224 (define (i386:label-mem->base label)
225   `(("mov____0x32,%edx" (#:address ,label)))) ; mov    0x<n>,%edx
226
227 (define (i386:label-mem-add label v)
228   `(("add____$i8,0x32" (#:address ,label) (#:immediate1 ,v)))) ; addl   $<v>,0x<n>
229
230 (define (i386:byte-base-mem->accu)
231   '(("add____%edx,%eax")                ; add    %edx,%eax
232     ("movzbl_(%eax),%eax")))            ; movzbl (%eax),%eax
233
234 (define (i386:byte-mem->accu)
235   '(("movzbl_(%eax),%eax")))            ; movzbl (%eax),%eax
236
237 (define (i386:byte-mem->base)
238   '(("movzbl_(%edx),%edx")))            ; movzbl (%edx),%edx
239
240 (define (i386:base-mem->accu)
241   '(("add___%edx,%eax")                 ; add    %edx,%eax
242     ("mov____(%eax),%eax")))            ; mov    (%eax),%eax
243
244 (define (i386:mem->accu)
245   '(("mov____(%eax),%eax")))            ; mov    (%eax),%eax
246
247 (define (i386:mem->base)
248   '(("mov____(%edx),%edx")))            ; mov    (%edx),%edx
249
250 (define (i386:mem+n->accu n)
251   `(("mov____0x8(%eax),%eax" (#:immediate1 ,n)))) ; mov    0x<n>(%eax),%eax
252
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
257
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
261
262 (define (i386:value->accu-address v)
263   `(("mov____$i32,(%eax)" (#:immediate ,v)))) ; movl   $0x<v>,(%eax)
264
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)
268
269 (define (i386:base->accu-address)
270   '(("mov____%edx,%(eax)")))            ; mov    %edx,(%eax)
271
272 (define (i386:base-address->accu-address)
273   '(("mov____(%edx),%ecx")              ; mov    (%edx),%ecx
274     ("mov____%ecx,%(eax)")))            ; mov    %ecx,(%eax)
275
276 (define (i386:accu+n n)
277   `(("add____$i8,%eax" (#:immediate1 ,n)))) ; add    $0x00,%eax
278
279 (define (i386:base+n n)
280   `(("add____$i8,%edx" (#:immediate1 ,n)))) ; add    $0x00,%edx
281
282 (define (i386:byte-base->accu-address)
283   '(("mov____%dl,(%eax)")))             ; mov    %dl,(%eax)
284
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)
288
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
292
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)
296
297 (define (i386:accu-mem-add v)
298   `(("add____$i8,0x8(%eax)" (#:immediate1 ,v)))) ; addl   $<v>,(%eax)
299
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>)
303      (#:immediate ,v))))
304
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)
308      (#:immediate ,v))))
309
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)
313
314 (define (i386:call-label label n)
315   `((call32 (#:offset ,label))
316     ("add____$i8,%esp" (#:immediate1 ,(* n 4)))))
317
318 (define (i386:call-accu n)
319   `(,@(i386:push-accu)
320     ,@(i386:pop-accu)
321     ("call___*%eax")                    ; call   *%eax
322     ("add____$i8,%esp" (#:immediate1  ,(* n 4))))) ; add    $00,%esp
323
324 (define (i386:accu-negate)
325   '(("sete___%al")                      ; sete %al
326     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
327
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
331
332 (define (i386:xor-zf)
333   '(("lahf")                               ; lahf
334     ("xor____$i8,%ah" (#:immediate1 #x40)) ; xor    $0x40,%ah
335     ("sahf")))                             ; sahf
336
337 (define (i386:accu-cmp-value v)
338   `(("cmp____$i8,%eax" (#:immediate1 ,v)))) ; cmp    $<v>,%eax
339
340 (define (i386:accu-test)
341   '(("test___%eax,%eax")))              ; test   %eax,%eax
342
343 (define (i386:jump label)
344   `(("jmp32 " (#:offset ,label))))
345
346 (define (i386:jump-z label)
347   `(("je32  " (#:offset ,label))))        ; jz . + <n>
348
349 (define (i386:jump-byte-z label)
350   `(("test___%al,%al")                  ; test   %al,%al
351     ("je8  " (#:offset1 ,label))))      ; je <n>
352
353 ;; signed
354 (define (i386:jump-g label)
355   `(("jg32   " (#:offset ,label))))        ; jg/jnle <n>
356
357 ;; signed
358 (define (i386:jump-ge label)
359   `(("jge32 " (#:offset ,label))))       ; jge/jnl <n>
360
361 (define (i386:jump-nz label)
362   `(("jne32 " (#:offset ,label))))       ; jnz . + <n>
363
364 (define (i386:byte-test-base)
365   '(("cmp____%al,%dl")))                ; cmp    %al,%dl
366
367 (define (i386:test-base)
368   (("cmp____%edx,%eax")))               ; cmp    %edx,%eax
369
370 (define (i386:byte-sub-base)
371   '(("sub____%dl,%al")))                ; sub    %dl,%al
372
373 (define (i386:byte-base-sub)
374   `(("sub____%al,%dl")))                ; sub    %al,%dl
375
376 (define (i386:sub-base)
377   `(("sub____%edx,%eax")))              ; sub    %edx,%eax
378
379 (define (i386:base-sub)
380   `(("sub____%eax,%edx")))              ; sub    %eax,%edx
381
382 (define (i386:nz->accu)
383   '(("setne__%al")                      ; setne   %al
384     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
385
386 (define (i386:z->accu)
387   '(("sete___%al")                      ; sete   %al
388     ("movzbl_%al,%eax")))               ; movzbl %al,%eax
389
390 (define (i386:accu<->stack)
391   '(("xchg___%eax,(%esp)")))            ; xchg   %eax,(%esp)