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