3 ;;; Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;; This file is part of Mes.
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.
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.
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/>.
23 ;;; libc-i386.mes defines C library routines
27 (define (i386:function-preamble)
29 #x89 #xe5)) ; mov %esp,%ebp
31 (define (i386:function-locals)
32 '(#x83 #xec #x20)) ; sub $0x10,%esp -- 8 local vars
34 (define (i386:push-global-address o)
35 (or o push-global-address)
36 `(#x68 ,@(int->bv32 o))) ; push $0x<o>
38 (define (i386:push-global o)
40 `(#xa1 ,@(int->bv32 o) ; mov 0x804a000,%eax
43 (define (i386:push-local n)
45 `(#xff #x75 ,(- 0 (* 4 n)))) ; pushl 0x<n>(%ebp)
47 (define (i386:push-local-address n)
48 (or n push-local-address)
49 `(#x8d #x45 ,(- 0 (* 4 n)) ; lea 0x<n>(%ebp),%eax
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****
59 (define (i386:pop-accu)
62 (define (i386:push-accu)
65 (define (i386:pop-base)
68 (define (i386:push-base)
71 (define (i386:push-arg f g ta t d)
75 `(#x68 ,@(int->bv32 o))) ; push $<o>
76 ((and (pair? o) (procedure? (car o)))
77 (append-map (lambda (p) (p f g ta t d)) o))
79 ((procedure? o) (o f g ta t d))
82 (define (i386:ret . rest)
85 ,@(cond ((null? rest) '())
87 `(#xb8 ; mov $<>,%eaxx
88 ,@(int->bv32 (car rest))))
89 ((pair? (car rest)) (car rest))
90 ((procedure? (car rest))
91 ((car rest) f g ta t d)))
96 (define (i386:accu->base)
97 '(#x89 #xc2)) ; mov %eax,%edx
99 (define (i386:accu->base-address)
100 '(#x89 #x02)) ; mov %eax,%(edx)
102 (define (i386:byte-accu->base-address)
103 '(#x88 #x02)) ; mov %al,%(edx)
105 (define (i386:accu->base-address+n n)
106 (or n accu->base-address+n)
107 `(#x89 #x42 ,n)) ; mov %eax,$0x<n>%(edx)
109 (define (i386:accu->local n)
111 `(#x89 #x45 ,(- 0 (* 4 n)))) ; mov %eax,-<0xn>(%ebp)
113 (define (i386:base->local n)
115 `(#x89 #x55 ,(- 0 (* 4 n)))) ; mov %edx,-<0xn>(%ebp)
117 (define (i386:base->global n)
119 `(#x89 #x15 ,@(int->bv32 n))) ; mov %edx,0x0
121 (define (i386:accu->global n)
123 `(#xa3 ,@(int->bv32 n))) ; mov %eax,0x0
125 (define (i386:accu->global-address n)
126 (or n accu->global-address)
127 `(#x8b #x15 ,@(int->bv32 n) ; mov 0x<n>,%edx
128 #x89 #x02 )) ; mov %eax,(%edx)
130 (define (i386:accu-zero?)
131 '(#x85 #xc0)) ; cmpl %eax,%eax
133 (define (i386:accu-non-zero?)
134 (append '(#x85 #xc0) ; cmpl %eax,%eax
137 (define (i386:accu-shl n)
139 `(#xc1 #xe0 ,n)) ; shl $0x8,%eax
141 (define (i386:accu+accu)
142 '(#x01 #xc0)) ; add %eax,%eax
144 (define (i386:accu+base)
145 `(#x01 #xd0)) ; add %edx,%eax
147 (define (i386:accu+value v)
149 `(#x05 ,@(int->bv32 v))) ; add %eax,%eax
151 (define (i386:accu-base)
152 `(#x29 #xd0)) ; sub %edx,%eax
154 ;; (define (i386:accu/base)
155 ;; '(#xf7 #xf2)) ; div %edx,%eax
157 (define (i386:accu/base)
158 '(#x86 #xd3 ; mov %edx,%ebx
159 #x31 #xd2 ; xor %edx,%edx
160 #xf7 #xf3)) ; div %ebx
162 (define (i386:base->accu)
163 '(#x89 #xd0)) ; mov %edx,%eax
165 (define (i386:local->accu n)
167 `(#x8b #x45 ,(- 0 (* 4 n)))) ; mov -<0xn>(%ebp),%eax
169 (define (i386:local-address->accu n)
171 `(#x8d #x45 ,(- 0 (* 4 n)))) ; lea 0x<n>(%ebp),%eax
173 (define (i386:local-ptr->accu n)
174 (or n local-ptr->accu)
175 `(#x89 #xe8 ; mov %ebp,%eax
176 #x83 #xc0 ,(- 0 (* 4 n)))) ; add $0x<n>,%eax
178 (define (i386:byte-local->accu n)
179 (or n byte-local->accu)
180 `(#x0f #xb6 #x45 ,(- 0 (* 4 n)))) ; movzbl 0x<n>(%ebp),%eax
182 (define (i386:local->base n)
184 `(#x8b #x55 ,(- 0 (* 4 n)))) ; mov -<0xn>(%ebp),%edx
186 (define (i386:local-address->base n) ;; DE-REF
187 (or n local-address->base)
188 `(#x8d #x55 ,(- 0 (* 4 n)))) ; lea 0x<n>(%ebp),%edx
190 (define (i386:local-ptr->base n)
191 (or n local-ptr->base)
192 `(#x89 #xea ; mov %ebp,%edx
193 #x83 #xc2 ,(- 0 (* 4 n)))) ; add $0x<n>,%edx
195 (define (i386:global->base n)
197 `(#xba ,@(int->bv32 n))) ; mov $<n>,%edx
199 (define (i386:global-address->accu n)
200 (or n global-address->accu)
201 `(#xa1 ,@(int->bv32 n))) ; mov 0x<n>,%eax
203 (define (i386:global-address->base n)
204 (or n global-address->base)
205 `(#x8b #x15 ,@(int->bv32 n))) ; mov 0x<n>,%edx
207 (define (i386:byte-base-mem->accu)
208 '(#x01 #xd0 ; add %edx,%eax
209 #x0f #xb6 #x00)) ; movzbl (%eax),%eax
211 (define (i386:byte-mem->accu)
212 '(#x0f #xb6 #x00)) ; movzbl (%eax),%eax
214 (define (i386:byte-mem->base)
215 '(#x0f #xb6 #x10)) ; movzbl (%eax),%edx
217 (define (i386:base-mem->accu)
218 '(#x01 #xd0 ; add %edx,%eax
219 #x8b #x00)) ; mov (%eax),%eax
221 (define (i386:mem->accu)
222 '(#x8b #x00)) ; mov (%eax),%eax
224 (define (i386:mem+n->accu n)
225 `(#x8b #x40 ,n)) ; mov 0x<n>(%eax),%eax
227 (define (i386:base-mem+n->accu n)
228 (or n base-mem+n->accu)
229 `(#x01 #xd0 ; add %edx,%eax
230 #x8b #x40 ,n)) ; mov <n>(%eax),%eax
232 (define (i386:value->accu v)
233 (or v urg:value->accu)
234 `(#xb8 ,@(int->bv32 v))) ; mov $<v>,%eax
236 (define (i386:value->accu-address v)
237 `(#xc7 #x00 ,@(int->bv32 v))) ; movl $0x<v>,(%eax)
239 (define (i386:value->accu-address+n n v)
240 (or v urg:value->accu-address+n)
241 `(#xc7 #x40 ,n ,@(int->bv32 v))) ; movl $<v>,0x<n>(%eax)
243 (define (i386:base->accu-address)
244 '(#x89 #x10)) ; mov %edx,(%eax)
246 (define (i386:byte-base->accu-address)
247 '(#x88 #x10)) ; mov %dl,(%eax)
249 (define (i386:byte-base->accu-address+n n)
250 (or n byte-base->accu-address+n)
251 `(#x88 #x50 ,n)) ; mov %dl,0x<n>(%eax)
253 (define (i386:value->base v)
254 (or v urg:value->base)
255 `(#xba ,@(int->bv32 v))) ; mov $<v>,%edx
257 (define (i386:local-add n v)
259 `(#x83 #x45 ,(- 0 (* 4 n)) ,v)) ; addl $<v>,0x<n>(%ebp)
261 (define (i386:global-add n v)
262 (or n urg:global-add)
263 `(#x83 #x05 ,@(int->bv32 n) ,v)) ; addl $<v>,0x<n>
265 (define (i386:global->accu o)
266 (or o urg:global->accu)
267 `(#xb8 ,@(int->bv32 o))) ; mov $<>,%eax
269 (define (i386:value->global n v)
271 `(#xc7 #x05 ,@(int->bv32 n) ; movl $<v>,(<n>)
274 (define (i386:value->local n v)
276 `(#xc7 #x45 ,(- 0 (* 4 n)) ; movl $<v>,0x<n>(%ebp)
279 (define (i386:local-test n v)
281 `(#x83 #x7d ,(- 0 (* 4 n)) ,v)) ; cmpl $<v>,0x<n>(%ebp)
283 (define (i386:call f g ta t d address . arguments)
284 (or address urg:call)
285 (let* ((pushes (append-map (i386:push-arg f g ta t d) (reverse arguments)))
287 (n (length arguments)))
290 #xe8 ,@(int->bv32 (- address 5 s)) ; call relative
291 #x83 #xc4 ,(* n 4) ; add $00,%esp
294 (define (i386:call-accu f g ta t d . arguments)
295 ;;(or address urg:call)
296 (let* ((pushes (append-map (i386:push-arg f g ta t d) (reverse arguments)))
298 (n (length arguments)))
302 ;;#xe8 ,@(int->bv32 (- address 5 s)) ; call relative
303 ;; FIXME: add t?/address
307 ;; #x05 ,@(int->bv32 t) ; add <t>,%eax
308 ;; #x05 ,@(int->bv32 ta) ; add <ta>,%eax
309 #xff #xd0 ; call *%eax
310 #x83 #xc4 ,(* n 4) ; add $00,%esp
313 (define (i386:accu-not)
314 `(#x0f #x94 #xc0 ; sete %al
315 #x0f #xb6 #xc0)) ; movzbl %al,%eax
317 (define (i386:xor-accu v)
319 `(#x35 ,@(int->bv32 v))) ;xor $0xff,%eax
321 (define (i386:xor-zf)
323 #x80 #xf4 #x40 ; xor $0x40,%ah
326 (define (i386:accu-cmp-value v)
327 `(#x83 #xf8 ,v)) ; cmp $<v>,%eax
329 (define (i386:accu-test)
330 '(#x85 #xc0)) ; test %eax,%eax
332 (define (i386:Xjump n)
334 `(#xe9 ,@(int->bv32 (if (>= n 0) n (- n 5))))) ; jmp . + <n>
336 (define (i386:Xjump-nz n)
338 `(#x0f #x85 ,@(int->bv32 n))) ; jnz . + <n>
340 (define (i386:jump n) ;;FIXME: NEED THIS WEIRDNESS for t.c
341 (when (or (> n #x80) (< n #x-80))
342 (format (current-error-port) "JUMP n=~a\n" n)
344 `(#xeb ,(if (>= n 0) (- n 2) (- n 2)))) ; jmp <n>
346 (define (i386:jump-c n)
348 `(#x72 ,(if (>= n 0) n (- n 2)))) ; jc <n>
350 (define (i386:jump-cz n)
352 `(#x76 ,(if (>= n 0) n (- n 2)))) ; jna <n>
354 (define (i386:jump-ncz n)
356 `(#x77 ,(if (>= n 0) n (- n 2)))) ; ja <n>
358 (define (i386:jump-nc n)
360 `(#x73 ,(if (>= n 0) n (- n 2)))) ; jnc <n>
362 (define (i386:jump-z n)
364 `(#x74 ,(if (>= n 0) n (- n 2)))) ; jz <n>
366 (define (i386:jump-nz n)
368 `(#x75 ,(if (>= n 0) n (- n 2)))) ; jnz <n>
370 (define (i386:test-jump-z n)
372 `(#x85 #xc0 ; test %eax,%eax
373 #x74 ,(if (>= n 0) n (- n 4)))) ; jz <n>
375 (define (i386:jump-byte-nz n)
377 `(#x84 #xc0 ; test %al,%al
378 #x75 ,(if (>= n 0) n (- n 4)))) ; jne <n>
380 (define (i386:jump-byte-z n)
382 `(#x84 #xc0 ; test %al,%al
383 #x74 ,(if (>= n 0) n (- n 4)))) ; jne <n>
385 (define (i386:byte-test-base)
386 `(#x38 #xc2)) ; cmp %al,%dl
388 (define (i386:test-base)
389 `(#x39 #xd0)) ; cmp %edx,%eax
391 (define (i386:byte-sub-base)
392 `(#x28 #xd0)) ; sub %dl,%al
394 (define (i386:byte-base-sub)
395 `(#x28 #xd0)) ; sub %al,%dl
397 (define (i386:sub-base)
398 `(#x29 #xd0)) ; sub %edx,%eax
400 (define (i386:base-sub)
401 `(#x29 #xc2)) ; sub %eax,%edx
404 (define (i386:exit f g ta t d)
408 #xb8 #x01 #x00 #x00 #x00 ; mov $0x1,%eax
409 #xcd #x80 ; int $0x80
412 (define (i386:open f g ta t d)
415 #x89 #xe5 ; mov %esp,%ebp
417 #x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
418 #x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
420 #xb8 #x05 #x00 #x00 #x00 ; mov $0x5,%eax
421 #xcd #x80 ; int $0x80
427 (define (i386:read f g ta t d)
430 #x89 #xe5 ; mov %esp,%ebp
432 #x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
433 #x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
434 #x8b #x55 #x10 ; mov 0x10(%ebp),%edx
436 #xb8 #x03 #x00 #x00 #x00 ; mov $0x3,%eax
437 #xcd #x80 ; int $0x80
443 (define (i386:write f g ta t d)
446 #x89 #xe5 ; mov %esp,%ebp
448 #x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
449 #x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
450 #x8b #x55 #x10 ; mov 0x10(%ebp),%edx
452 #xb8 #x04 #x00 #x00 #x00 ; mov $0x4,%eax
453 #xcd #x80 ; int $0x80
461 8048121: 55 push %ebp
462 8048122: 89 e5 mov %esp,%ebp
463 8048124: 83 ec 10 sub $0x10,%esp
464 8048127: eb 08 jmp 8048131 <strcmp+0x10>
467 8048129: 83 45 08 01 addl $0x1,0x8(%ebp)
468 804812d: 83 45 0c 01 addl $0x1,0xc(%ebp)
471 8048131: 8b 45 08 mov 0x8(%ebp),%eax
472 8048134: 0f b6 00 movzbl (%eax),%eax
473 8048137: 84 c0 test %al,%al
474 8048139: 74 08 je 8048143 <strcmp+0x22>
477 804813b: 8b 45 0c mov 0xc(%ebp),%eax
478 804813e: 0f b6 00 movzbl (%eax),%eax
479 8048141: 84 c0 test %al,%al
480 8048143: 74 10 je 8048155 <strcmp+0x34>
483 8048145: 8b 45 08 mov 0x8(%ebp),%eax
484 8048148: 0f b6 10 movzbl (%eax),%edx
485 804814b: 8b 45 0c mov 0xc(%ebp),%eax
486 804814e: 0f b6 00 movzbl (%eax),%eax
487 8048151: 38 c2 cmp %al,%dl
488 8048153: 84 c0 test %al,%al
489 8048155: 75 d2 jne 8048129 <strcmp+0x8>
492 8048157: 8b 45 08 mov 0x8(%ebp),%eax
493 804815a: 0f b6 10 movzbl (%eax),%edx
494 804815d: 8b 45 0c mov 0xc(%ebp),%eax
495 8048160: 0f b6 00 movzbl (%eax),%eax
496 8048163: 28 d0 sub %dl,%al