mescc: Read and display sexp dumped by mes.
[mes.git] / module / mes / libc-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 ;;; libc-i386.mes defines C library routines
24
25 ;;; Code:
26
27 (define (i386:function-preamble)
28   '(#x55                                ; push   %ebp
29     #x89 #xe5))                         ; mov    %esp,%ebp
30
31 (define (i386:function-locals)
32   '(#x83 #xec #x20))               ; sub    $0x10,%esp -- 8 local vars
33
34 (define (i386:push-global-ref o)
35   (or o push-global-ref)
36   `(#x68 ,@(int->bv32 o)))              ; push  $0x<o>
37
38 (define (i386:push-global o)
39   (or o push-global)
40   `(#xa1 ,@(int->bv32 o)                ; mov    0x804a000,%eax
41          #x50))                         ; push  %eax
42
43 (define (i386:push-local n)
44   (or n push-local)
45   `(#xff #x75 ,(- 0 (* 4 n))))          ; pushl  0x<n>(%ebp)
46
47 (define (i386:push-local-ref n)
48   (or n push-local-ref)
49   `(#x8d #x45 ,(- 0 (* 4 n))            ; lea 0x<n>(%ebp),%eax
50          #x50))                         ; push %eax
51
52 (define (i386:push-local-de-ref n)
53   (or n push-local-de-ref)
54   `(#x8b #x45 ,(- 0 (* 4 n))            ; mov    -0x<n>(%ebp),%eax
55          #x0f #xb6 #x00                 ; movzbl (%eax),%eax
56          ;;#x0f #xbe #xc0                 ; movsbl %al,%eax ***FIXME BYTE****
57          #x50))                         ; push   %eax
58
59 (define (i386:push-accu)
60   `(#x50))                              ; push %eax
61
62 (define (i386:push-arg f g t d)
63   (lambda (o)
64     (or o push-arg)
65     (cond ((number? o)
66            `(#x68 ,@(int->bv32 o)))     ; push $<o>
67           ((and (pair? o) (procedure? (car o)))
68            (append-map (lambda (p) (p f g t d)) o))
69           ((pair? o) o)
70           ((procedure? o) (o f g t d))
71           (_ barf))))
72
73 (define (i386:ret . rest)
74   (lambda (f g t d)
75     `(
76       ,@(cond ((null? rest) '())
77               ((number? (car rest))
78                `(#xb8                     ; mov    $<>,%eax
79                  ,@(int->bv32 (car rest))))
80               ((pair? (car rest)) (car rest))
81               ((procedure? (car rest))
82                ((car rest) f g t d)))
83     #xc9                                ; leave
84     #xc3                                ; ret
85     )))
86
87 (define (i386:accu->base)
88   '(#x89 #xc2))                         ; mov    %eax,%edx
89
90 (define (i386:accu->local n)
91   (or n accu->local)
92   `(#x89 #x45 ,(- 0 (* 4 n))))          ; mov    %eax,-<0xn>(%ebp)
93
94 (define (i386:accu->global n)
95   (or n accu->global)
96   `(#xa3 ,@(int->bv32 n)))              ; mov    %eax,0x0
97
98 (define (i386:accu-zero?)
99   '(#x85 #xc0))                         ; cmpl   %eax,%eax
100
101 (define (i386:accu-non-zero?)
102   (append '(#x85 #xc0)                  ; cmpl   %eax,%eax
103           (i386:xor-zf)))
104
105 (define (i386:accu-shl n)
106   `(#xc1 #xe0 ,n))                      ; shl    $0x8,%eax
107
108 (define (i386:accu+accu)
109   '(#x01 #xc0))                         ; add    %eax,%eax
110
111 (define (i386:accu+base)
112   `(#x01 #xd0))                         ; add    %edx,%eax
113
114 (define (i386:base->accu)
115   '(#x89 #xd0))                         ; mov    %edx,%eax
116
117 (define (i386:local->accu n)
118   (or n local->accu)
119   `(#x8b #x45 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%eax
120
121 (define (i386:byte-local->accu n)
122   (or n byte-local->accu)
123   `(#x0f #xb6 #x45 ,(- 0 (* 4 n))))     ; movzbl 0x<n>(%ebp),%eax
124
125 (define (i386:local->base n)
126   (or n local->base)
127   `(#x8b #x55 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%edx
128
129 ;; (define (i386:local-ref->base n)
130 ;;   (or n local-ref->base)
131 ;;   `(#x8b #x15 ,@(int->bv32 (- 0 (* 4 n))))) ; mov    0x<n>,%edx
132
133 (define (i386:local-ref->base n)
134   (or n local-ref->base)
135   `(#x8d #x55 ,(- 0 (* 4 n))))          ; lea    0x<n>(%ebp),%edx
136
137 (define (i386:global-ref->base n)
138   (or n global->base)
139   `(#x8b #x15 ,@(int->bv32 n)))         ; mov    0x<n>,%edx
140
141 (define (i386:global->base n)
142   (or n global->base)
143   `(#xba ,@(int->bv32 n)))              ; mov    $<n>,%edx
144
145 (define (i386:byte-base-mem->accu)
146   '(#x01 #xd0                           ; add    %edx,%eax
147          #x0f #xb6 #x00))               ; movzbl (%eax),%eax
148
149 (define (i386:byte-mem->accu)
150   '(#x0f #xb6 #x00))                    ; movzbl (%eax),%eax
151
152 (define (i386:byte-mem->base)
153   '(#x0f #xb6 #x10))                    ; movzbl (%eax),%edx
154
155 (define (i386:base-mem->accu)
156   '(#x01 #xd0                           ; add    %edx,%eax
157          #x8b #x00))                    ; mov    (%eax),%eax
158
159 (define (i386:mem->accu)
160   '(#x8b #x00))                         ; mov    (%eax),%eax
161
162 (define (i386:mem+n->accu n)
163   `(#x8b #x40 ,n))                      ; mov    0x<n>(%eax),%eax
164
165 (define (i386:base-mem+n->accu n)
166   `(#x01 #xd0                           ; add    %edx,%eax
167          #x8b #x40 ,n))                 ; mov    <n>(%eax),%eax
168
169 (define (i386:global->accu o)
170   (or o global->accu)
171   `(#xb8 ,@(int->bv32 o)))              ; mov    $<>,%eax
172
173 (define (i386:value->accu v)
174   (or v value->accu)
175   `(#xb8 ,@(int->bv32 v)))              ; mov    $<v>,%eax
176
177 (define (i386:value->accu-ref v)
178   (or v value->accu-ref)
179   `(#xc7 #x00 ,@(int->bv32 v)))         ; movl   $0x<v>,(%eax)
180
181 (define (i386:value->accu-ref+n n v)
182   `(#xc7 #x40 ,n ,@(int->bv32 v)))      ; movl   $<v>,0x<n>(%eax)
183
184 (define (i386:base->accu-ref)
185   '(#x89 #x10))                         ; mov    %edx,(%eax)
186
187 (define (i386:byte-base->accu-ref)
188   '(#x88 #x10))                         ; mov    %dl,(%eax)
189
190 (define (i386:value->base v)
191   `(#xba ,@(int->bv32 v)))              ; mov    $<v>,%edx
192
193 (define (i386:local-add n v)
194   (or n ladd)
195   `(#x83 #x45 ,(- 0 (* 4 n)) ,v))       ; addl   $<v>,0x<n>(%ebp)
196
197 (define (i386:local-address->accu n)
198   (or n ladd)
199   `(#x8d #x45 ,(- 0 (* 4 n))))          ; lea 0x<n>(%ebp),%eax
200
201 (define (i386:local-address->accu n)
202   (or n ladd)
203   `(#x8d #x45 ,(- 0 (* 4 n))))          ; lea 0x<n>(%ebp),%eax
204
205 (define (i386:value->global n v)
206   (or n value->global)
207   `(#xc7 #x05 ,@(int->bv32 n)           ; movl   $<v>,(<n>)
208          ,@(int->bv32 v)))
209
210 (define (i386:value->local n v)
211   (or n value->local)
212   `(#xc7 #x45 ,(- 0 (* 4 n))            ; movl   $<v>,0x<n>(%ebp)
213          ,@(int->bv32 v)))
214
215 (define (i386:local-test n v)
216   (or n lt)
217   `(#x83 #x7d ,(- 0 (* 4 n)) ,v))       ; cmpl   $<v>,0x<n>(%ebp)
218
219 (define (i386:call f g t d address . arguments)
220   (let* ((pushes (append-map (i386:push-arg f g t d) (reverse arguments)))
221          (s (length pushes))
222          (n (length arguments)))
223    `(
224      ,@pushes                           ; push args
225      #xe8 ,@(int->bv32 (- address 5 s)) ; call relative
226      #x83 #xc4 ,(* n 4)                 ; add    $00,%esp
227      )))
228  
229 (define (i386:accu-not)
230   `(#x0f #x94 #xc0                      ; sete %al
231          #x0f #xb6 #xc0))               ; movzbl %al,%eax
232
233 (define (i386:xor-accu v)
234   `(#x35 ,@(int->bv32 v)))              ;xor    $0xff,%eax
235
236 (define (i386:xor-zf)
237   '(#x9f                                ; lahf   
238     #x80 #xf4 #x40                      ; xor    $0x40,%ah
239     #x9e))                              ; sahf   
240
241 (define (i386:accu-cmp-value v)
242   `(#x83 #xf8 ,v))                      ; cmp    $<v>,%eax
243
244 (define (i386:accu-test)
245   '(#x85 #xc0))                         ; test   %eax,%eax
246
247 (define (i386:Xjump n)
248   `(#xe9 ,@(int->bv32 n)))              ; jmp . + <n>
249
250 (define (i386:Xjump-nz n)
251   `(#x0f #x85 ,@(int->bv32 n)))         ; jnz . + <n>
252
253 (define (i386:jump n)  ;;FIXME: NEED THIS WEIRDNESS for t.c
254   `(#xeb ,(if (>= n 0) (- n 2) (- n 2))))   ; jmp <n>
255
256 ;; (define (i386:jump n)
257 ;;   `(#xeb ,(if (>= n 0) n (- n 2))))     ; jmp <n>
258
259 (define (i386:jump-c n)
260   `(#x72 ,(if (>= n 0) n (- n 2))))     ; jc <n>
261
262 (define (i386:jump-cz n)
263   `(#x76 ,(if (>= n 0) n (- n 2))))     ; jna <n>
264
265 (define (i386:jump-ncz n)
266   `(#x77 ,(if (>= n 0) n (- n 2))))     ; ja <n>
267
268 (define (i386:jump-nc n)
269   `(#x73 ,(if (>= n 0) n (- n 2))))     ; jnc <n>
270
271 (define (i386:jump-z n)
272   `(#x74 ,(if (>= n 0) n (- n 2)))) ; jz <n>
273
274 (define (i386:jump-nz n)
275   `(#x75 ,(if (>= n 0) n (- n 2)))) ; jnz <n>
276
277 (define (i386:test-jump-z n)
278   `(#x85 #xc0                           ; test   %eax,%eax
279     #x74 ,(if (>= n 0) n (- n 4))))     ; jz <n>
280
281 (define (i386:jump-byte-nz n)
282   `(#x84 #xc0                           ; test   %al,%al
283     #x75 ,(if (>= n 0) n (- n 4))))     ; jne <n>
284
285 (define (i386:jump-byte-z n)
286   `(#x84 #xc0                           ; test   %al,%al
287     #x74 ,(if (>= n 0) n (- n 4))))     ; jne <n>
288
289 (define (i386:byte-test-base)
290   `(#x38 #xc2))                         ; cmp    %al,%dl
291
292 (define (i386:test-base)
293   `(#x39 #xd0))                         ; cmp    %edx,%eax
294
295 (define (i386:byte-sub-base)
296   `(#x28 #xd0))                         ; sub    %dl,%al
297
298 (define (i386:byte-base-sub)
299   `(#x28 #xd0))                         ; sub    %al,%dl
300
301 (define (i386:sub-base)
302   `(#x29 #xd0))                         ; sub    %edx,%eax
303
304 (define (i386:base-sub)
305   `(#x29 #xc2))                         ; sub    %eax,%edx
306
307 ;;;\f libc bits
308 (define (i386:exit f g t d)
309   `(
310     #x5b                                ; pop    %ebx
311     #x5b                                ; pop    %ebx
312     #xb8 #x01 #x00 #x00 #x00            ; mov    $0x1,%eax
313     #xcd #x80                           ; int    $0x80
314     ))
315
316 (define (i386:open f g t d)
317   `(
318     #x55                                ; push   %ebp
319     #x89 #xe5                           ; mov    %esp,%ebp
320
321     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
322     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
323
324     #xb8 #x05 #x00 #x00 #x00            ; mov    $0x5,%eax
325     #xcd #x80                           ; int    $0x80
326
327     #xc9                                ; leave
328     #xc3                                ; ret
329     ))
330
331 (define (i386:read f g t d)
332   `(
333     #x55                                ; push   %ebp
334     #x89 #xe5                           ; mov    %esp,%ebp
335
336     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
337     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
338     #x8b #x55 #x10                      ; mov    0x10(%ebp),%edx
339
340     #xb8 #x03 #x00 #x00 #x00            ; mov    $0x3,%eax
341     #xcd #x80                           ; int    $0x80
342
343     #xc9                                ; leave
344     #xc3                                ; ret
345     ))
346
347 (define (i386:write f g t d)
348   `(
349     #x55                                ; push   %ebp
350     #x89 #xe5                           ; mov    %esp,%ebp
351
352     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
353     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
354     #x8b #x55 #x10                      ; mov    0x10(%ebp),%edx
355
356     #xb8 #x04 #x00 #x00 #x00            ; mov    $0x4,%eax
357     #xcd #x80                           ; int    $0x80
358
359     #xc9                                ; leave
360     #xc3                                ; ret
361     ))
362
363 #!
364 08048121 <strcmp>:
365  8048121:       55                      push   %ebp
366  8048122:       89 e5                   mov    %esp,%ebp
367  8048124:       83 ec 10                sub    $0x10,%esp
368  8048127:       eb 08                   jmp    8048131 <strcmp+0x10>
369
370 <body>
371  8048129:       83 45 08 01             addl   $0x1,0x8(%ebp)
372  804812d:       83 45 0c 01             addl   $0x1,0xc(%ebp)
373
374 <test> *a
375  8048131:       8b 45 08                mov    0x8(%ebp),%eax
376  8048134:       0f b6 00                movzbl (%eax),%eax
377  8048137:       84 c0                   test   %al,%al
378  8048139:       74 08                   je     8048143 <strcmp+0x22>
379
380 <test1> *b
381  804813b:       8b 45 0c                mov    0xc(%ebp),%eax
382  804813e:       0f b6 00                movzbl (%eax),%eax
383  8048141:       84 c0                   test   %al,%al
384  8048143:       74 10                   je     8048155 <strcmp+0x34>
385
386 <test2> *a == *b
387  8048145:       8b 45 08                mov    0x8(%ebp),%eax
388  8048148:       0f b6 10                movzbl (%eax),%edx
389  804814b:       8b 45 0c                mov    0xc(%ebp),%eax
390  804814e:       0f b6 00                movzbl (%eax),%eax
391  8048151:       38 c2                   cmp    %al,%dl
392  8048153:       84 c0                   test   %al,%al
393  8048155:       75 d2                   jne    8048129 <strcmp+0x8>
394
395
396  8048157:       8b 45 08                mov    0x8(%ebp),%eax
397  804815a:       0f b6 10                movzbl (%eax),%edx
398  804815d:       8b 45 0c                mov    0xc(%ebp),%eax
399  8048160:       0f b6 00                movzbl (%eax),%eax
400  8048163:       28 d0                   sub    %dl,%al
401  8048165:       c9                      leave
402  8048166:       c3                      ret  
403 !#