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 i386 assembly
31 (mes-use-module (mes elf))))
33 (define (i386:function-preamble)
35 #x89 #xe5)) ; mov %esp,%ebp
37 ;; (define (i386:function-locals)
38 ;; '(#x83 #xec #x20)) ; sub $0x10,%esp -- 8 local vars
40 (define (i386:function-locals)
41 '(#x83 #xec #x40)) ; sub $0x10,%esp -- 16 local vars
43 (define (i386:push-global-address o)
44 (or o push-global-address)
45 `(#x68 ,@(int->bv32 o))) ; push $0x<o>
47 (define (i386:push-global o)
49 `(#xa1 ,@(int->bv32 o) ; mov 0x804a000,%eax
52 (define (i386:push-local n)
54 `(#xff #x75 ,(- 0 (* 4 n)))) ; pushl 0x<n>(%ebp)
56 (define (i386:push-local-address n)
57 (or n push-local-address)
58 `(#x8d #x45 ,(- 0 (* 4 n)) ; lea 0x<n>(%ebp),%eax
61 (define (i386:push-local-de-ref n)
62 (or n push-local-de-ref)
63 `(#x8b #x45 ,(- 0 (* 4 n)) ; mov -0x<n>(%ebp),%eax
64 #x0f #xb6 #x00 ; movzbl (%eax),%eax
65 ;;#x0f #xbe #xc0 ; movsbl %al,%eax ***FIXME BYTE****
68 (define (i386:pop-accu)
71 (define (i386:push-accu)
74 (define (i386:pop-base)
77 (define (i386:push-base)
84 (define (i386:accu->base)
85 '(#x89 #xc2)) ; mov %eax,%edx
87 (define (i386:accu->base-address)
88 '(#x89 #x02)) ; mov %eax,%(edx)
90 (define (i386:byte-accu->base-address)
91 '(#x88 #x02)) ; mov %al,%(edx)
93 (define (i386:accu->base-address+n n)
94 (or n accu->base-address+n)
95 `(#x89 #x42 ,n)) ; mov %eax,$0x<n>%(edx)
97 (define (i386:accu->local n)
99 `(#x89 #x45 ,(- 0 (* 4 n)))) ; mov %eax,-<0xn>(%ebp)
101 (define (i386:base->local n)
103 `(#x89 #x55 ,(- 0 (* 4 n)))) ; mov %edx,-<0xn>(%ebp)
105 (define (i386:base->global n)
107 `(#x89 #x15 ,@(int->bv32 n))) ; mov %edx,0x0
109 (define (i386:accu->global n)
111 `(#xa3 ,@(int->bv32 n))) ; mov %eax,0x0
113 (define (i386:accu->global-address n)
114 (or n accu->global-address)
115 `(#x8b #x15 ,@(int->bv32 n) ; mov 0x<n>,%edx
116 #x89 #x02 )) ; mov %eax,(%edx)
118 (define (i386:accu-zero?)
119 '(#x85 #xc0)) ; cmpl %eax,%eax
121 (define (i386:accu-non-zero?)
122 (append '(#x85 #xc0) ; cmpl %eax,%eax
125 (define (i386:accu-shl n)
127 `(#xc1 #xe0 ,n)) ; shl $0x8,%eax
129 (define (i386:accu<<base)
130 '(#x31 #xc9 ; xor %ecx,%ecx
131 #x89 #xd1 ; mov %edx,%ecx
132 #xd3 #xe0)) ; shl %cl,%eax
134 (define (i386:accu>>base)
135 '(#x31 #xc9 ; xor %ecx,%ecx
136 #x89 #xd1 ; mov %edx,%ecx
137 #xd3 #xe8)) ; shr %cl,%eax
139 (define (i386:accu-or-base)
140 '(#x09 #xd0)) ; or %edx,%eax
142 (define (i386:accu+accu)
143 '(#x01 #xc0)) ; add %eax,%eax
145 (define (i386:accu+base)
146 `(#x01 #xd0)) ; add %edx,%eax
148 (define (i386:accu+value v)
150 `(#x05 ,@(int->bv32 v))) ; add %eax,%eax
152 (define (i386:accu-base)
153 `(#x29 #xd0)) ; sub %edx,%eax
155 (define (i386:accu*base)
156 `(#xf7 #xe2)) ; mul %edx
158 (define (i386:accu/base)
159 '(#x86 #xd3 ; mov %edx,%ebx
160 #x31 #xd2 ; xor %edx,%edx
161 #xf7 #xf3)) ; div %ebx
163 (define (i386:accu%base)
164 '(#x86 #xd3 ; mov %edx,%ebx
165 #x31 #xd2 ; xor %edx,%edx
167 #x89 #xd0)) ; mov %edx,%eax
169 (define (i386:base->accu)
170 '(#x89 #xd0)) ; mov %edx,%eax
172 (define (i386:local->accu n)
174 `(#x8b #x45 ,(- 0 (* 4 n)))) ; mov -<0xn>(%ebp),%eax
176 (define (i386:local-address->accu n)
178 `(#x8d #x45 ,(- 0 (* 4 n)))) ; lea 0x<n>(%ebp),%eax
180 (define (i386:local-ptr->accu n)
181 (or n local-ptr->accu)
182 `(#x89 #xe8 ; mov %ebp,%eax
183 #x83 #xc0 ,(- 0 (* 4 n)))) ; add $0x<n>,%eax
185 (define (i386:byte-local->accu n)
186 (or n byte-local->accu)
187 `(#x0f #xb6 #x45 ,(- 0 (* 4 n)))) ; movzbl 0x<n>(%ebp),%eax
189 (define (i386:local->base n)
191 `(#x8b #x55 ,(- 0 (* 4 n)))) ; mov -<0xn>(%ebp),%edx
193 (define (i386:local-address->base n) ;; DE-REF
194 (or n local-address->base)
195 `(#x8d #x55 ,(- 0 (* 4 n)))) ; lea 0x<n>(%ebp),%edx
197 (define (i386:local-ptr->base n)
198 (or n local-ptr->base)
199 `(#x89 #xea ; mov %ebp,%edx
200 #x83 #xc2 ,(- 0 (* 4 n)))) ; add $0x<n>,%edx
202 (define (i386:global->base n)
204 `(#xba ,@(int->bv32 n))) ; mov $<n>,%edx
206 (define (i386:global-address->accu n)
207 (or n global-address->accu)
208 `(#xa1 ,@(int->bv32 n))) ; mov 0x<n>,%eax
210 (define (i386:global-address->base n)
211 (or n global-address->base)
212 `(#x8b #x15 ,@(int->bv32 n))) ; mov 0x<n>,%edx
214 (define (i386:byte-base-mem->accu)
215 '(#x01 #xd0 ; add %edx,%eax
216 #x0f #xb6 #x00)) ; movzbl (%eax),%eax
218 (define (i386:byte-mem->accu)
219 '(#x0f #xb6 #x00)) ; movzbl (%eax),%eax
221 (define (i386:byte-mem->base)
222 '(#x0f #xb6 #x10)) ; movzbl (%eax),%edx
224 (define (i386:base-mem->accu)
225 '(#x01 #xd0 ; add %edx,%eax
226 #x8b #x00)) ; mov (%eax),%eax
228 (define (i386:mem->accu)
229 '(#x8b #x00)) ; mov (%eax),%eax
231 (define (i386:mem+n->accu n)
232 `(#x8b #x40 ,n)) ; mov 0x<n>(%eax),%eax
234 (define (i386:base-mem+n->accu n)
235 (or n base-mem+n->accu)
236 `(#x01 #xd0 ; add %edx,%eax
237 #x8b #x40 ,n)) ; mov <n>(%eax),%eax
239 (define (i386:value->accu v)
240 (or v urg:value->accu)
241 `(#xb8 ,@(int->bv32 v))) ; mov $<v>,%eax
243 (define (i386:value->accu-address v)
244 `(#xc7 #x00 ,@(int->bv32 v))) ; movl $0x<v>,(%eax)
246 (define (i386:value->accu-address+n n v)
247 (or v urg:value->accu-address+n)
248 `(#xc7 #x40 ,n ,@(int->bv32 v))) ; movl $<v>,0x<n>(%eax)
250 (define (i386:base->accu-address)
251 '(#x89 #x10)) ; mov %edx,(%eax)
253 (define (i386:base-address->accu-address)
254 '(#x8b #x0a ; mov (%edx),%ecx
255 #x89 #x08)) ; mov %ecx,(%eax)
257 (define (i386:accu+n n)
258 `(#x83 #xc0 ,n)) ; add $0x00,%eax
260 (define (i386:base+n n)
261 `(#x83 #xc2 ,n)) ; add $0x00,%edx
263 (define (i386:byte-base->accu-address)
264 '(#x88 #x10)) ; mov %dl,(%eax)
266 (define (i386:byte-base->accu-address+n n)
267 (or n byte-base->accu-address+n)
268 `(#x88 #x50 ,n)) ; mov %dl,0x<n>(%eax)
270 (define (i386:value->base v)
271 (or v urg:value->base)
272 `(#xba ,@(int->bv32 v))) ; mov $<v>,%edx
274 (define (i386:local-add n v)
276 `(#x83 #x45 ,(- 0 (* 4 n)) ,v)) ; addl $<v>,0x<n>(%ebp)
278 (define (i386:global-add n v)
279 (or n urg:global-add)
280 `(#x83 #x05 ,@(int->bv32 n) ,v)) ; addl $<v>,0x<n>
282 (define (i386:global->accu o)
283 (or o urg:global->accu)
284 `(#xb8 ,@(int->bv32 o))) ; mov $<>,%eax
286 (define (i386:value->global n v)
288 `(#xc7 #x05 ,@(int->bv32 n) ; movl $<v>,(<n>)
291 (define (i386:value->local n v)
293 `(#xc7 #x45 ,(- 0 (* 4 n)) ; movl $<v>,0x<n>(%ebp)
296 (define (i386:local-test n v)
298 `(#x83 #x7d ,(- 0 (* 4 n)) ,v)) ; cmpl $<v>,0x<n>(%ebp)
300 (define (i386:call f g ta t d address n)
301 (or address urg:call)
302 `(#xe8 ,@(int->bv32 (- address 5)) ; call relative $00
303 #x83 #xc4 ,(* n 4))) ; add $00,%esp
305 (define (i386:call-accu f g ta t d n)
308 #xff #xd0 ; call *%eax
309 #x83 #xc4 ,(* n 4))) ; add $00,%esp
311 (define (i386:accu-not)
312 `(#x0f #x94 #xc0 ; sete %al
313 #x0f #xb6 #xc0)) ; movzbl %al,%eax
315 (define (i386:xor-accu v)
317 `(#x35 ,@(int->bv32 v))) ;xor $0xff,%eax
319 (define (i386:xor-zf)
321 #x80 #xf4 #x40 ; xor $0x40,%ah
324 (define (i386:accu-cmp-value v)
325 `(#x83 #xf8 ,v)) ; cmp $<v>,%eax
327 (define (i386:accu-test)
328 '(#x85 #xc0)) ; test %eax,%eax
330 (define (i386:Xjump n)
332 `(#xe9 ,@(int->bv32 (if (>= n 0) n (- n 5))))) ; jmp . + <n>
334 (define (i386:XXjump n)
336 `(#xe9 ,@(int->bv32 n))) ; jmp . + <n>
338 (define (i386:Xjump-nz n)
340 `(#x0f #x85 ,@(int->bv32 n))) ; jnz . + <n>
342 (define (i386:Xjump-z n)
344 `(#x0f #x84 ,@(int->bv32 n))) ; jz . + <n>
346 (define (i386:jump n) ;;FIXME: NEED THIS WEIRDNESS for t.c
347 (when (or (> n #x80) (< n #x-80))
348 (format (current-error-port) "JUMP n=~a\n" n)
350 `(#xeb ,(if (>= n 0) (- n 2) (- n 2)))) ; jmp <n>
352 (define (i386:jump-c n)
353 (when (or (> n #x80) (< n #x-80))
354 (format (current-error-port) "JUMP n=~a\n" n)
356 `(#x72 ,(if (>= n 0) n (- n 2)))) ; jc <n>
358 (define (i386:jump-cz n)
359 (when (or (> n #x80) (< n #x-80))
360 (format (current-error-port) "JUMP n=~a\n" n)
362 `(#x76 ,(if (>= n 0) n (- n 2)))) ; jbe <n>
364 (define (i386:jump-ncz n)
365 (when (or (> n #x80) (< n #x-80))
366 (format (current-error-port) "JUMP-ncz n=~a\n" n)
368 `(#x77 ,(if (>= n 0) n (- n 2)))) ; ja <n>
370 (define (i386:jump-nc n)
371 (when (or (> n #x80) (< n #x-80))
372 (format (current-error-port) "JUMP-nc n=~a\n" n)
374 `(#x73 ,(if (>= n 0) n (- n 2)))) ; jnc <n>
377 (define (i386:Xjump-nc n)
379 `(#x0f #x83 ,@(int->bv32 n))) ; jnc <n>
382 (define (i386:Xjump-ncz n)
384 `(#x0f #x87 ,@(int->bv32 n))) ; ja <n>
387 ;; (define (i386:Xjump-c n)
388 ;; (or n urg:Xjump-c)
389 ;; `(#x0f #x82 ,@(int->bv32 n))) ; jc <n>
392 ;; (define (i386:Xjump-cz n)
393 ;; (or n urg:Xjump-cz)
394 ;; `(#x0f #x86 ,@(int->bv32 n))) ; jbe <n>
397 (define (i386:Xjump-g n)
399 `(#x0f #x8f ,@(int->bv32 n))) ; jg/jnle <n>
402 (define (i386:Xjump-ge n)
404 `(#x0f #x8d ,@(int->bv32 n))) ; jge/jnl <n>
407 ;; (define (i386:Xjump-l n)
408 ;; (or n urg:Xjump-l)
409 ;; `(#x0f #x8c ,@(int->bv32 n))) ; jl/jnge <n>
412 ;; (define (i386:Xjump-le n)
413 ;; (or n urg:Xjump-le)
414 ;; `(#x0f #x8e ,@(int->bv32 n))) ; jle/jgn <n>
416 (define (i386:jump-z n)
417 (when (or (> n #x80) (< n #x-80))
418 (format (current-error-port) "JUMP-z n=~a\n" n)
420 `(#x74 ,(if (>= n 0) n (- n 2)))) ; jz <n>
422 (define (i386:jump-nz n)
423 (when (or (> n #x80) (< n #x-80))
424 (format (current-error-port) "JUMP-nz n=~a\n" n)
426 `(#x75 ,(if (>= n 0) n (- n 2)))) ; jnz <n>
428 (define (i386:test-jump-z n)
429 (when (or (> n #x80) (< n #x-80))
430 (format (current-error-port) "JUMP-z n=~a\n" n)
432 `(#x85 #xc0 ; test %eax,%eax
433 #x74 ,(if (>= n 0) n (- n 4)))) ; jz <n>
435 (define (i386:jump-byte-nz n)
436 (when (or (> n #x80) (< n #x-80))
437 (format (current-error-port) "JUMP-byte-nz n=~a\n" n)
439 `(#x84 #xc0 ; test %al,%al
440 #x75 ,(if (>= n 0) n (- n 4)))) ; jne <n>
442 (define (i386:jump-byte-z n)
443 (when (or (> n #x80) (< n #x-80))
444 (format (current-error-port) "JUMP-byte-z n=~a\n" n)
446 `(#x84 #xc0 ; test %al,%al
447 #x74 ,(if (>= n 0) n (- n 4)))) ; jne <n>
449 (define (i386:byte-test-base)
450 `(#x38 #xc2)) ; cmp %al,%dl
452 (define (i386:test-base)
453 `(#x39 #xd0)) ; cmp %edx,%eax
455 (define (i386:byte-sub-base)
456 `(#x28 #xd0)) ; sub %dl,%al
458 (define (i386:byte-base-sub)
459 `(#x28 #xd0)) ; sub %al,%dl
461 (define (i386:sub-base)
462 `(#x29 #xd0)) ; sub %edx,%eax
464 (define (i386:base-sub)
465 `(#x29 #xc2)) ; sub %eax,%edx