mescc: Refactor ret.
[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:function-locals)
35   '(#x83 #xec #x40))              ; sub    $0x10,%esp -- 16 local vars
36
37 (define (i386:push-global-address o)
38   (or o push-global-address)
39   `(#x68 ,@(int->bv32 o)))              ; push  $0x<o>
40
41 (define (i386:push-global o)
42   (or o push-global)
43   `(#xa1 ,@(int->bv32 o)                ; mov    0x804a000,%eax
44          #x50))                         ; push  %eax
45
46 (define (i386:push-local n)
47   (or n push-local)
48   `(#xff #x75 ,(- 0 (* 4 n))))          ; pushl  0x<n>(%ebp)
49
50 (define (i386:push-local-address n)
51   (or n push-local-address)
52   `(#x8d #x45 ,(- 0 (* 4 n))            ; lea 0x<n>(%ebp),%eax
53          #x50))                         ; push %eax
54
55 (define (i386:push-local-de-ref n)
56   (or n push-local-de-ref)
57   `(#x8b #x45 ,(- 0 (* 4 n))            ; mov    -0x<n>(%ebp),%eax
58          #x0f #xb6 #x00                 ; movzbl (%eax),%eax
59          ;;#x0f #xbe #xc0                 ; movsbl %al,%eax ***FIXME BYTE****
60          #x50))                         ; push   %eax
61
62 (define (i386:pop-accu)
63   '(#x58))                              ; pop %eax
64
65 (define (i386:push-accu)
66   '(#x50))                              ; push %eax
67
68 (define (i386:pop-base)
69   '(#x5a))                              ; pop %eax
70
71 (define (i386:push-base)
72   '(#x52))                              ; push %eax
73
74 (define (i386:ret)
75   '(#xc9                                ; leave
76     #xc3))                              ; ret
77
78 (define (i386:accu->base)
79   '(#x89 #xc2))                         ; mov    %eax,%edx
80
81 (define (i386:accu->base-address)
82   '(#x89 #x02))                         ; mov    %eax,%(edx)
83
84 (define (i386:byte-accu->base-address)
85   '(#x88 #x02))                         ; mov    %al,%(edx)
86
87 (define (i386:accu->base-address+n n)
88   (or n accu->base-address+n)
89   `(#x89 #x42 ,n))                      ; mov    %eax,$0x<n>%(edx)
90
91 (define (i386:accu->local n)
92   (or n accu->local)
93   `(#x89 #x45 ,(- 0 (* 4 n))))          ; mov    %eax,-<0xn>(%ebp)
94
95 (define (i386:base->local n)
96   (or n base->local)
97   `(#x89 #x55 ,(- 0 (* 4 n))))          ; mov    %edx,-<0xn>(%ebp)
98
99 (define (i386:base->global n)
100   (or n base->global)
101   `(#x89 #x15 ,@(int->bv32 n)))         ; mov    %edx,0x0
102
103 (define (i386:accu->global n)
104   (or n accu->global)
105   `(#xa3 ,@(int->bv32 n)))              ; mov    %eax,0x0
106
107 (define (i386:accu->global-address n)
108   (or n accu->global-address)
109   `(#x8b #x15 ,@(int->bv32 n)           ; mov    0x<n>,%edx
110          #x89 #x02 ))                   ; mov    %eax,(%edx)
111
112 (define (i386:accu-zero?)
113   '(#x85 #xc0))                         ; cmpl   %eax,%eax
114
115 (define (i386:accu-non-zero?)
116   (append '(#x85 #xc0)                  ; cmpl   %eax,%eax
117           (i386:xor-zf)))
118
119 (define (i386:accu-shl n)
120   (or n accu:shl n)
121   `(#xc1 #xe0 ,n))                      ; shl    $0x8,%eax
122
123 (define (i386:accu+accu)
124   '(#x01 #xc0))                         ; add    %eax,%eax
125
126 (define (i386:accu+base)
127   `(#x01 #xd0))                         ; add    %edx,%eax
128
129 (define (i386:accu+value v)
130   (or v accu+value)
131   `(#x05 ,@(int->bv32 v)))              ; add    %eax,%eax
132
133 (define (i386:accu-base)
134   `(#x29 #xd0))                         ; sub    %edx,%eax
135
136 (define (i386:accu/base)
137   '(#x86 #xd3                           ; mov    %edx,%ebx
138     #x31 #xd2                           ; xor    %edx,%edx
139     #xf7 #xf3))                         ; div    %ebx
140
141 (define (i386:accu%base)
142   '(#x86 #xd3                           ; mov    %edx,%ebx
143     #x31 #xd2                           ; xor    %edx,%edx
144     #xf7 #xf3                           ; div    %ebx
145     #x89 #xd0))                         ; mov    %edx,%eax
146
147 (define (i386:base->accu)
148   '(#x89 #xd0))                         ; mov    %edx,%eax
149
150 (define (i386:local->accu n)
151   (or n local->accu)
152   `(#x8b #x45 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%eax
153
154 (define (i386:local-address->accu n)
155   (or n ladd)
156   `(#x8d #x45 ,(- 0 (* 4 n))))          ; lea 0x<n>(%ebp),%eax
157
158 (define (i386:local-ptr->accu n)
159   (or n local-ptr->accu)
160   `(#x89 #xe8                           ; mov    %ebp,%eax
161          #x83 #xc0 ,(- 0 (* 4 n))))     ; add    $0x<n>,%eax
162
163 (define (i386:byte-local->accu n)
164   (or n byte-local->accu)
165   `(#x0f #xb6 #x45 ,(- 0 (* 4 n))))     ; movzbl 0x<n>(%ebp),%eax
166
167 (define (i386:local->base n)
168   (or n local->base)
169   `(#x8b #x55 ,(- 0 (* 4 n))))          ; mov    -<0xn>(%ebp),%edx
170
171 (define (i386:local-address->base n) ;; DE-REF
172   (or n local-address->base)
173   `(#x8d #x55 ,(- 0 (* 4 n))))          ; lea    0x<n>(%ebp),%edx
174
175 (define (i386:local-ptr->base n)
176   (or n local-ptr->base)
177   `(#x89 #xea                           ; mov    %ebp,%edx
178          #x83 #xc2 ,(- 0 (* 4 n))))     ; add    $0x<n>,%edx
179
180 (define (i386:global->base n)
181   (or n global->base)
182   `(#xba ,@(int->bv32 n)))              ; mov   $<n>,%edx
183
184 (define (i386:global-address->accu n)
185   (or n global-address->accu)
186   `(#xa1 ,@(int->bv32 n)))              ; mov    0x<n>,%eax
187
188 (define (i386:global-address->base n)
189   (or n global-address->base)
190   `(#x8b #x15 ,@(int->bv32 n)))         ; mov    0x<n>,%edx
191
192 (define (i386:byte-base-mem->accu)
193   '(#x01 #xd0                           ; add    %edx,%eax
194          #x0f #xb6 #x00))               ; movzbl (%eax),%eax
195
196 (define (i386:byte-mem->accu)
197   '(#x0f #xb6 #x00))                    ; movzbl (%eax),%eax
198
199 (define (i386:byte-mem->base)
200   '(#x0f #xb6 #x10))                    ; movzbl (%eax),%edx
201
202 (define (i386:base-mem->accu)
203   '(#x01 #xd0                           ; add    %edx,%eax
204          #x8b #x00))                    ; mov    (%eax),%eax
205
206 (define (i386:mem->accu)
207   '(#x8b #x00))                         ; mov    (%eax),%eax
208
209 (define (i386:mem+n->accu n)
210   `(#x8b #x40 ,n))                      ; mov    0x<n>(%eax),%eax
211
212 (define (i386:base-mem+n->accu n)
213   (or n base-mem+n->accu)
214   `(#x01 #xd0                           ; add    %edx,%eax
215          #x8b #x40 ,n))                 ; mov    <n>(%eax),%eax
216
217 (define (i386:value->accu v)
218   (or v urg:value->accu)
219   `(#xb8 ,@(int->bv32 v)))              ; mov    $<v>,%eax
220
221 (define (i386:value->accu-address v)
222   `(#xc7 #x00 ,@(int->bv32 v)))         ; movl   $0x<v>,(%eax)
223
224 (define (i386:value->accu-address+n n v)
225   (or v urg:value->accu-address+n)
226   `(#xc7 #x40 ,n ,@(int->bv32 v)))      ; movl   $<v>,0x<n>(%eax)
227
228 (define (i386:base->accu-address)
229   '(#x89 #x10))                         ; mov    %edx,(%eax)
230
231 (define (i386:base-address->accu-address)
232   '(#x8b #x0a                           ; mov    (%edx),%ecx
233     #x89 #x08))                         ; mov    %ecx,(%eax)
234
235 (define (i386:accu+n n)
236   `(#x83 #xc0 ,n))                      ; add    $0x00,%eax
237
238 (define (i386:base+n n)
239   `(#x83 #xc2 ,n))                      ; add    $0x00,%edx
240
241 (define (i386:byte-base->accu-address)
242   '(#x88 #x10))                         ; mov    %dl,(%eax)
243
244 (define (i386:byte-base->accu-address+n n)
245   (or n byte-base->accu-address+n)
246   `(#x88 #x50 ,n))                      ; mov    %dl,0x<n>(%eax)
247
248 (define (i386:value->base v)
249   (or v urg:value->base)
250   `(#xba ,@(int->bv32 v)))              ; mov    $<v>,%edx
251
252 (define (i386:local-add n v)
253   (or n urg:local-add)
254   `(#x83 #x45 ,(- 0 (* 4 n)) ,v))       ; addl   $<v>,0x<n>(%ebp)
255
256 (define (i386:global-add n v)
257   (or n urg:global-add)
258   `(#x83 #x05 ,@(int->bv32 n) ,v))      ; addl   $<v>,0x<n>
259
260 (define (i386:global->accu o)
261   (or o urg:global->accu)
262   `(#xb8 ,@(int->bv32 o)))              ; mov    $<>,%eax
263
264 (define (i386:value->global n v)
265   (or n value->global)
266   `(#xc7 #x05 ,@(int->bv32 n)           ; movl   $<v>,(<n>)
267          ,@(int->bv32 v)))
268
269 (define (i386:value->local n v)
270   (or n value->local)
271   `(#xc7 #x45 ,(- 0 (* 4 n))            ; movl   $<v>,0x<n>(%ebp)
272          ,@(int->bv32 v)))
273
274 (define (i386:local-test n v)
275   (or n local-test)
276   `(#x83 #x7d ,(- 0 (* 4 n)) ,v))       ; cmpl   $<v>,0x<n>(%ebp)
277
278 (define (i386:call f g ta t d address n)
279   (or address urg:call)
280   `(#xe8 ,@(int->bv32 (- address 5))    ; call   relative $00
281          #x83 #xc4 ,(* n 4)))           ; add    $00,%esp
282
283 (define (i386:call-accu f g ta t d n)
284   `(,@(i386:push-accu)
285     ,@(i386:pop-accu)
286     #xff #xd0                           ; call   *%eax
287     #x83 #xc4 ,(* n 4)))                ; add    $00,%esp
288
289 (define (i386:accu-not)
290   `(#x0f #x94 #xc0                      ; sete %al
291          #x0f #xb6 #xc0))               ; movzbl %al,%eax
292
293 (define (i386:xor-accu v)
294   (or n urg:xor-accu)
295   `(#x35 ,@(int->bv32 v)))              ;xor    $0xff,%eax
296
297 (define (i386:xor-zf)
298   '(#x9f                                ; lahf   
299     #x80 #xf4 #x40                      ; xor    $0x40,%ah
300     #x9e))                              ; sahf   
301
302 (define (i386:accu-cmp-value v)
303   `(#x83 #xf8 ,v))                      ; cmp    $<v>,%eax
304
305 (define (i386:accu-test)
306   '(#x85 #xc0))                         ; test   %eax,%eax
307
308 (define (i386:Xjump n)
309   (or n urg:Xjump)
310   `(#xe9 ,@(int->bv32 (if (>= n 0) n (- n 5))))) ; jmp . + <n>
311
312 (define (i386:XXjump n)
313   (or n urg:XXjump)
314   `(#xe9 ,@(int->bv32 n)))              ; jmp . + <n>
315
316 (define (i386:Xjump-nz n)
317   (or n urg:Xjump-nz)
318   `(#x0f #x85 ,@(int->bv32 n)))         ; jnz . + <n>
319
320 (define (i386:Xjump-z n)
321   (or n urg:Xjump-z)
322   `(#x0f #x84 ,@(int->bv32 n)))         ; jz . + <n>
323
324 (define (i386:jump n) ;;FIXME: NEED THIS WEIRDNESS for t.c
325   (when (or (> n #x80) (< n #x-80))
326     (format (current-error-port) "JUMP n=~a\n" n)
327     barf)
328   `(#xeb ,(if (>= n 0) (- n 2) (- n 2)))) ; jmp <n>
329
330 (define (i386:jump-c n)
331   (when (or (> n #x80) (< n #x-80))
332     (format (current-error-port) "JUMP n=~a\n" n)
333     barf)
334   `(#x72 ,(if (>= n 0) n (- n 2))))     ; jc <n>
335
336 (define (i386:Xjump-c n)
337   (or n urg:Xjump-c)
338   `(#x0f #x82 ,@(int->bv32 n)))     ; jc <n>
339
340 (define (i386:jump-cz n)
341   (when (or (> n #x80) (< n #x-80))
342     (format (current-error-port) "JUMP n=~a\n" n)
343     barf)
344   `(#x76 ,(if (>= n 0) n (- n 2))))     ; jna <n>
345
346 (define (i386:jump-ncz n)
347   (when (or (> n #x80) (< n #x-80))
348     (format (current-error-port) "JUMP-ncz n=~a\n" n)
349     barf)
350   `(#x77 ,(if (>= n 0) n (- n 2))))     ; ja <n>
351
352 (define (i386:jump-nc n)
353   (when (or (> n #x80) (< n #x-80))
354     (format (current-error-port) "JUMP-nc n=~a\n" n)
355     barf)
356   `(#x73 ,(if (>= n 0) n (- n 2))))     ; jnc <n>
357
358 (define (i386:Xjump-nc n)
359   (or n urg:Xjump-nc)
360   `(#x0f #x83 ,@(int->bv32 n)))         ; jnc <n>
361
362 (define (i386:jump-z n)
363   (when (or (> n #x80) (< n #x-80))
364     (format (current-error-port) "JUMP-z n=~a\n" n)
365     barf)
366   `(#x74 ,(if (>= n 0) n (- n 2)))) ; jz <n>
367
368 (define (i386:jump-nz n)
369   (when (or (> n #x80) (< n #x-80))
370     (format (current-error-port) "JUMP-nz n=~a\n" n)
371     barf)
372   `(#x75 ,(if (>= n 0) n (- n 2)))) ; jnz <n>
373
374 (define (i386:test-jump-z n)
375   (when (or (> n #x80) (< n #x-80))
376     (format (current-error-port) "JUMP-z n=~a\n" n)
377     barf)
378   `(#x85 #xc0                           ; test   %eax,%eax
379     #x74 ,(if (>= n 0) n (- n 4))))     ; jz <n>
380
381 (define (i386:jump-byte-nz n)
382   (when (or (> n #x80) (< n #x-80))
383     (format (current-error-port) "JUMP-byte-nz n=~a\n" n)
384     barf)
385   `(#x84 #xc0                           ; test   %al,%al
386     #x75 ,(if (>= n 0) n (- n 4))))     ; jne <n>
387
388 (define (i386:jump-byte-z n)
389   (when (or (> n #x80) (< n #x-80))
390     (format (current-error-port) "JUMP-byte-z n=~a\n" n)
391     barf)
392   `(#x84 #xc0                           ; test   %al,%al
393     #x74 ,(if (>= n 0) n (- n 4))))     ; jne <n>
394
395 (define (i386:byte-test-base)
396   `(#x38 #xc2))                         ; cmp    %al,%dl
397
398 (define (i386:test-base)
399   `(#x39 #xd0))                         ; cmp    %edx,%eax
400
401 (define (i386:byte-sub-base)
402   `(#x28 #xd0))                         ; sub    %dl,%al
403
404 (define (i386:byte-base-sub)
405   `(#x28 #xd0))                         ; sub    %al,%dl
406
407 (define (i386:sub-base)
408   `(#x29 #xd0))                         ; sub    %edx,%eax
409
410 (define (i386:base-sub)
411   `(#x29 #xc2))                         ; sub    %eax,%edx
412
413 ;;;\f libc bits
414 (define (i386:exit f g ta t d)
415   `(
416     #x5b                                ; pop    %ebx
417     #x5b                                ; pop    %ebx
418     #xb8 #x01 #x00 #x00 #x00            ; mov    $0x1,%eax
419     #xcd #x80                           ; int    $0x80
420     ))
421
422 (define (i386:open f g ta t d)
423   `(
424     #x55                                ; push   %ebp
425     #x89 #xe5                           ; mov    %esp,%ebp
426
427     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
428     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
429
430     #xb8 #x05 #x00 #x00 #x00            ; mov    $0x5,%eax
431     #xcd #x80                           ; int    $0x80
432
433     #xc9                                ; leave
434     #xc3                                ; ret
435     ))
436
437 (define (i386:read f g ta t d)
438   `(
439     #x55                                ; push   %ebp
440     #x89 #xe5                           ; mov    %esp,%ebp
441
442     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
443     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
444     #x8b #x55 #x10                      ; mov    0x10(%ebp),%edx
445
446     #xb8 #x03 #x00 #x00 #x00            ; mov    $0x3,%eax
447     #xcd #x80                           ; int    $0x80
448
449     #xc9                                ; leave
450     #xc3                                ; ret
451     ))
452
453 (define (i386:write f g ta t d)
454   `(
455     #x55                                ; push   %ebp
456     #x89 #xe5                           ; mov    %esp,%ebp
457
458     #x8b #x5d #x08                      ; mov    0x8(%ebp),%ebx
459     #x8b #x4d #x0c                      ; mov    0xc(%ebp),%ecx
460     #x8b #x55 #x10                      ; mov    0x10(%ebp),%edx
461
462     #xb8 #x04 #x00 #x00 #x00            ; mov    $0x4,%eax
463     #xcd #x80                           ; int    $0x80
464
465     #xc9                                ; leave
466     #xc3                                ; ret
467     ))
468
469 #!
470 08048121 <strcmp>:
471  8048121:       55                      push   %ebp
472  8048122:       89 e5                   mov    %esp,%ebp
473  8048124:       83 ec 10                sub    $0x10,%esp
474  8048127:       eb 08                   jmp    8048131 <strcmp+0x10>
475
476 <body>
477  8048129:       83 45 08 01             addl   $0x1,0x8(%ebp)
478  804812d:       83 45 0c 01             addl   $0x1,0xc(%ebp)
479
480 <test> *a
481  8048131:       8b 45 08                mov    0x8(%ebp),%eax
482  8048134:       0f b6 00                movzbl (%eax),%eax
483  8048137:       84 c0                   test   %al,%al
484  8048139:       74 08                   je     8048143 <strcmp+0x22>
485
486 <test1> *b
487  804813b:       8b 45 0c                mov    0xc(%ebp),%eax
488  804813e:       0f b6 00                movzbl (%eax),%eax
489  8048141:       84 c0                   test   %al,%al
490  8048143:       74 10                   je     8048155 <strcmp+0x34>
491
492 <test2> *a == *b
493  8048145:       8b 45 08                mov    0x8(%ebp),%eax
494  8048148:       0f b6 10                movzbl (%eax),%edx
495  804814b:       8b 45 0c                mov    0xc(%ebp),%eax
496  804814e:       0f b6 00                movzbl (%eax),%eax
497  8048151:       38 c2                   cmp    %al,%dl
498  8048153:       84 c0                   test   %al,%al
499  8048155:       75 d2                   jne    8048129 <strcmp+0x8>
500
501
502  8048157:       8b 45 08                mov    0x8(%ebp),%eax
503  804815a:       0f b6 10                movzbl (%eax),%edx
504  804815d:       8b 45 0c                mov    0xc(%ebp),%eax
505  8048160:       0f b6 00                movzbl (%eax),%eax
506  8048163:       28 d0                   sub    %dl,%al
507  8048165:       c9                      leave
508  8048166:       c3                      ret  
509 !#