dbffb710404529a78045b1d06ce5e8c257f1a537
[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 elf-util))))
32
33 (define (i386:function-preamble)
34   '(#x55                                ; push   %ebp
35     #x89 #xe5))                         ; mov    %esp,%ebp
36
37 ;; (define (i386:function-locals)
38 ;;   '(#x83 #xec #x20))               ; sub    $0x10,%esp -- 8 local vars
39
40 (define (i386:function-locals)
41   '(#x83 #xec #x40))              ; sub    $0x10,%esp -- 16 local vars
42
43 (define (i386:push-label label)
44   `(#x68 ,label #f #f #F))              ; push  $0x<o>
45
46 (define (i386:push-label-mem label)
47   `(#xa1 ,label #f #f #f                ; mov    0x804a000,%eax
48          #x50))                         ; push  %eax
49
50 (define (i386:push-local n)
51   (or n (error "invalid value: push-local: " n))
52   `(#xff #x75 ,(- 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   `(#x8d #x45 ,(- 0 (* 4 n))            ; lea 0x<n>(%ebp),%eax
57          #x50))                         ; 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   `(#x8b #x45 ,(- 0 (* 4 n))            ; mov    -0x<n>(%ebp),%eax
62          #x0f #xb6 #x00                 ; movzbl (%eax),%eax
63          #x50))                         ; 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   `(#x8b #x45 ,(- 0 (* 4 n))            ; mov    -0x<n>(%ebp),%eax
68          #x8b #x00                      ; mov    (%eax),%eax
69          #x0f #xb6 #x00                 ; movzbl (%eax),%eax
70          #x50))
71
72 (define (i386:push-local-de-ref n)
73   (or n (error "invalid value: push-byte-local-de-ref: " n))
74   `(#x8b #x45 ,(- 0 (* 4 n))            ; mov    -0x<n>(%ebp),%eax
75          #x8b #x00                      ; mov (%eax),%eax
76          #x50))                         ; push   %eax
77
78 (define (i386:pop-accu)
79   '(#x58))                              ; pop %eax
80
81 (define (i386:push-accu)
82   '(#x50))                              ; push %eax
83
84 (define (i386:pop-base)
85   '(#x5a))                              ; pop %edx
86
87 (define (i386:push-base)
88   '(#x52))                              ; push %edx
89
90 (define (i386:ret)
91   '(#xc9                                ; leave
92     #xc3))                              ; ret
93
94 (define (i386:accu->base)
95   '(#x89 #xc2))                         ; mov    %eax,%edx
96
97 (define (i386:accu->base-address)
98   '(#x89 #x02))                         ; mov    %eax,%(edx)
99
100 (define (i386:byte-accu->base-address)
101   '(#x88 #x02))                         ; mov    %al,%(edx)
102
103 (define (i386:accu->base-address+n n)
104   (or n (error "invalid value: accu->base-address+n: " n))
105   `(#x89 #x42 ,n))                      ; mov    %eax,$0x<n>%(edx)
106
107 (define (i386:accu->local n)
108   (or n (error "invalid value: accu->local: " n))
109   `(#x89 #x45 ,(- 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   `(#x89 #x55 ,(- 0 (* 4 n))))          ; mov    %edx,-<0xn>(%ebp)
118
119 (define (i386:accu->label label)
120   `(#xa3 ,label #f #f #f))
121
122 (define (i386:accu-zero?)
123   '(#x85 #xc0))                         ; cmpl   %eax,%eax
124
125 (define (i386:accu-non-zero?)
126   (append '(#x85 #xc0)                  ; cmpl   %eax,%eax
127           (i386:xor-zf)))
128
129 (define (i386:accu-shl n)
130   (or n (error "invalid value: accu:shl n: " n))
131   `(#xc1 #xe0 ,n))                      ; shl    $0x8,%eax
132
133 (define (i386:accu<<base)
134   '(#x31 #xc9                           ; xor    %ecx,%ecx
135     #x89 #xd1                           ; mov    %edx,%ecx
136     #xd3 #xe0))                         ; shl    %cl,%eax
137
138 (define (i386:accu>>base)
139   '(#x31 #xc9                           ; xor    %ecx,%ecx
140     #x89 #xd1                           ; mov    %edx,%ecx
141     #xd3 #xe8))                         ; shr    %cl,%eax
142
143 (define (i386:accu-or-base)
144   '(#x09 #xd0))                         ; or    %edx,%eax
145
146 (define (i386:accu-and-base)
147   '(#x21 #xd0))                         ; and    %edx,%eax
148
149 (define (i386:accu-xor-base)
150   '(#x31 #xd0))                         ; and    %edx,%eax
151
152 (define (i386:accu+accu)
153   '(#x01 #xc0))                         ; add    %eax,%eax
154
155 (define (i386:accu+base)
156   `(#x01 #xd0))                         ; add    %edx,%eax
157
158 (define (i386:accu+value v)
159   (or v (error "invalid value: accu+value: " v))
160   `(#x05 ,@(int->bv32 v)))              ; add    %eax,%eax
161
162 (define (i386:accu-base)
163   `(#x29 #xd0))                         ; sub    %edx,%eax
164
165 (define (i386:accu*base)
166   `(#xf7 #xe2))                         ; mul    %edx
167
168 (define (i386:accu/base)
169   '(#x86 #xd3                           ; mov    %edx,%ebx
170     #x31 #xd2                           ; xor    %edx,%edx
171     #xf7 #xf3))                         ; div    %ebx
172
173 (define (i386:accu%base)
174   '(#x86 #xd3                           ; mov    %edx,%ebx
175     #x31 #xd2                           ; xor    %edx,%edx
176     #xf7 #xf3                           ; div    %ebx
177     #x89 #xd0))                         ; mov    %edx,%eax
178
179 (define (i386:base->accu)
180   '(#x89 #xd0))                         ; mov    %edx,%eax
181
182 (define (i386:local->accu n)
183   (or n (error "invalid value: local->accu: " n))
184   `(#x8b #x45 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%eax
185
186 (define (i386:local-address->accu n)
187   (or n (error "invalid value: ladd: " n))
188   `(#x8d #x45 ,(- 0 (* 4 n))))          ; lea 0x<n>(%ebp),%eax
189
190 (define (i386:local-ptr->accu n)
191   (or n (error "invalid value: local-ptr->accu: " n))
192   `(#x89 #xe8                           ; mov    %ebp,%eax
193          #x83 #xc0 ,(- 0 (* 4 n))))     ; add    $0x<n>,%eax
194
195 (define (i386:byte-local->accu n)
196   (or n (error "invalid value: byte-local->accu: " n))
197   `(#x0f #xb6 #x45 ,(- 0 (* 4 n))))     ; movzbl 0x<n>(%ebp),%eax
198
199 (define (i386:byte-local->base n)
200   (or n (error "invalid value: byte-local->base: " n))
201   `(#x0f #xb6 #x55 ,(- 0 (* 4 n))))     ; movzbl 0x<n>(%ebp),%edx
202
203 (define (i386:local->base n)
204   (or n (error "invalid value: local->base: " n))
205   `(#x8b #x55 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%edx
206
207 (define (i386:local-address->base n) ;; DE-REF
208   (or n (error "invalid value: local-address->base: " n))
209   `(#x8d #x55 ,(- 0 (* 4 n))))          ; lea    0x<n>(%ebp),%edx
210
211 (define (i386:local-ptr->base n)
212   (or n (error "invalid value: local-ptr->base: " n))
213   `(#x89 #xea                           ; mov    %ebp,%edx
214          #x83 #xc2 ,(- 0 (* 4 n))))     ; add    $0x<n>,%edx
215
216 (define (i386:label->accu label)
217   `(#xb8 ,label #f #f #f))              ; mov    $<>,%eax
218
219 (define (i386:label->base label)
220   `(#xba ,label #f #f #f))              ; mov   $<n>,%edx
221
222 (define (i386:label-mem->accu label)
223   `(#xa1 ,label #f #f #f))              ; mov    0x<n>,%eax
224
225 (define (i386:label-mem->base label)
226   `(#x8b #x15 ,label #f #f #f))         ; mov    0x<n>,%edx
227
228 (define (i386:label-mem-add label v)
229   `(#x83 #x05 ,label #f #f #f ,v))      ; addl   $<v>,0x<n>
230
231 (define (i386:byte-base-mem->accu)
232   '(#x01 #xd0                           ; add    %edx,%eax
233          #x0f #xb6 #x00))               ; movzbl (%eax),%eax
234
235 (define (i386:byte-mem->accu)
236   '(#x0f #xb6 #x00))                    ; movzbl (%eax),%eax
237
238 (define (i386:byte-mem->base)
239   '(#x0f #xb6 #x10))                    ; movzbl (%eax),%edx
240
241 (define (i386:base-mem->accu)
242   '(#x01 #xd0                           ; add    %edx,%eax
243          #x8b #x00))                    ; mov    (%eax),%eax
244
245 (define (i386:mem->accu)
246   '(#x8b #x00))                         ; mov    (%eax),%eax
247
248 (define (i386:mem+n->accu n)
249   `(#x8b #x40 ,n))                      ; mov    0x<n>(%eax),%eax
250
251 (define (i386:base-mem+n->accu n)
252   (or n (error "invalid value: base-mem+n->accu: " n))
253   `(#x01 #xd0                           ; add    %edx,%eax
254          #x8b #x40 ,n))                 ; mov    <n>(%eax),%eax
255
256 (define (i386:value->accu v)
257   (or v (error "invalid value: i386:value->accu: " v))
258   `(#xb8 ,@(int->bv32 v)))              ; mov    $<v>,%eax
259
260 (define (i386:value->accu-address v)
261   `(#xc7 #x00 ,@(int->bv32 v)))         ; movl   $0x<v>,(%eax)
262
263 (define (i386:value->accu-address+n n v)
264   (or v (error "invalid value: i386:value->accu-address+n: " v))
265   `(#xc7 #x40 ,n ,@(int->bv32 v)))      ; movl   $<v>,0x<n>(%eax)
266
267 (define (i386:base->accu-address)
268   '(#x89 #x10))                         ; mov    %edx,(%eax)
269
270 (define (i386:base-address->accu-address)
271   '(#x8b #x0a                           ; mov    (%edx),%ecx
272     #x89 #x08))                         ; mov    %ecx,(%eax)
273
274 (define (i386:accu+n n)
275   `(#x83 #xc0 ,n))                      ; add    $0x00,%eax
276
277 (define (i386:base+n n)
278   `(#x83 #xc2 ,n))                      ; add    $0x00,%edx
279
280 (define (i386:byte-base->accu-address)
281   '(#x88 #x10))                         ; mov    %dl,(%eax)
282
283 (define (i386:byte-base->accu-address+n n)
284   (or n (error "invalid value: byte-base->accu-address+n: " n))
285   `(#x88 #x50 ,n))                      ; mov    %dl,0x<n>(%eax)
286
287 (define (i386:value->base v)
288   (or v (error "invalid value: i386:value->base: " v))
289   `(#xba ,@(int->bv32 v)))              ; mov    $<v>,%edx
290
291 (define (i386:local-add n v)
292   (or n (error "invalid value: i386:local-add: " n))
293   `(#x83 #x45 ,(- 0 (* 4 n)) ,v))       ; addl   $<v>,0x<n>(%ebp)
294
295 (define (i386:accu-mem-add v)
296   `(#x83 #x00 ,v))                      ; addl   $<v>,(%eax)
297
298 (define (i386:value->label label v)
299   (or v (error "invalid value: value->label: " v))
300   `(#xc7 #x05 ,label #f #f #f           ; movl   $<v>,(<n>)
301          ,@(int->bv32 v)))
302
303 (define (i386:value->local n v)
304   (or n (error "invalid value: value->local: " n))
305   `(#xc7 #x45 ,(- 0 (* 4 n))            ; movl   $<v>,0x<n>(%ebp)
306          ,@(int->bv32 v)))
307
308 (define (i386:local-test n v)
309   (or n (error "invalid value: local-test: " n))
310   `(#x83 #x7d ,(- 0 (* 4 n)) ,v))       ; cmpl   $<v>,0x<n>(%ebp)
311
312 (define (i386:call-label label n)
313   `(#xe8 ,label #f #f #f                ; call   relative $00
314          #x83 #xc4 ,(* n 4)))           ; add    $00,%esp
315
316 (define (i386:call-accu n)
317   `(,@(i386:push-accu)
318     ,@(i386:pop-accu)
319     #xff #xd0                           ; call   *%eax
320     #x83 #xc4 ,(* n 4)))                ; add    $00,%esp
321
322 (define (i386:accu-not)
323   `(#x0f #x94 #xc0                      ; sete %al
324          #x0f #xb6 #xc0))               ; movzbl %al,%eax
325
326 (define (i386:xor-accu v)
327   (or v (error "invalid value: i386:xor-accu: n: " v))
328   `(#x35 ,@(int->bv32 v)))              ;xor    $0xff,%eax
329
330 (define (i386:xor-zf)
331   '(#x9f                                ; lahf   
332     #x80 #xf4 #x40                      ; xor    $0x40,%ah
333     #x9e))                              ; sahf   
334
335 (define (i386:accu-cmp-value v)
336   `(#x83 #xf8 ,v))                      ; cmp    $<v>,%eax
337
338 (define (i386:accu-test)
339   '(#x85 #xc0))                         ; test   %eax,%eax
340
341 (define (i386:jump-label label)
342   `(#xe9 ,label #f #f #f))              ; jmp . + <n>
343
344 (define (i386:jump-label-z label)
345   `(#x0f #x84 ,label #f #f #f))         ; jz . + <n>
346
347 (define (i386:jump-label-byte-z label)
348   `(#x84 #xc0                           ; test   %al,%al
349     #x74 ,label))                       ; jne <n>
350
351 ;; signed
352 (define (i386:jump-label-g label)
353   `(#x0f #x8f ,label #f #f #f))         ; jg/jnle <n>
354
355 ;; signed
356 (define (i386:jump-label-ge label)
357   `(#x0f #x8d ,label #f #f #f))         ; jge/jnl <n>
358
359 (define (i386:jump-label-nz label)
360   `(#x0f #x85 ,label #f #f #f))         ; jnz . + <n>
361
362 (define (i386:jump-label-z label)
363   `(#x0f #x84 ,label #f #f #f))         ; jz . + <n>
364
365 (define (i386:byte-test-base)
366   `(#x38 #xc2))                         ; cmp    %al,%dl
367
368 (define (i386:test-base)
369   `(#x39 #xd0))                         ; cmp    %edx,%eax
370
371 (define (i386:byte-sub-base)
372   `(#x28 #xd0))                         ; sub    %dl,%al
373
374 (define (i386:byte-base-sub)
375   `(#x28 #xd0))                         ; sub    %al,%dl
376
377 (define (i386:sub-base)
378   `(#x29 #xd0))                         ; sub    %edx,%eax
379
380 (define (i386:base-sub)
381   `(#x29 #xc2))                         ; sub    %eax,%edx
382
383 (define (i386:nz->accu)
384   '(#x0f #x95 #xc0                      ; setne   %al
385          #x0f #xb6 #xc0))               ; movzbl %al,%eax
386
387 (define (i386:z->accu)
388   '(#x0f #x94 #xc0                      ; sete   %al
389          #x0f #xb6 #xc0))               ; movzbl %al,%eax
390
391 (define (i386:accu<->stack)
392   '(#x87 #x04 #x24))                    ; xchg   %eax,(%esp)
393