2007-10-25 16:27:34 -04:00
|
|
|
;;; Ikarus Scheme -- A compiler for R6RS Scheme.
|
|
|
|
;;; Copyright (C) 2006,2007 Abdulaziz Ghuloum
|
|
|
|
;;;
|
|
|
|
;;; This program is free software: you can redistribute it and/or modify
|
|
|
|
;;; it under the terms of the GNU General Public License version 3 as
|
|
|
|
;;; published by the Free Software Foundation.
|
|
|
|
;;;
|
|
|
|
;;; This program is distributed in the hope that it will be useful, but
|
|
|
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
;;; General Public License for more details.
|
|
|
|
;;;
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
|
|
|
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
2007-05-15 10:18:58 -04:00
|
|
|
(library (ikarus intel-assembler)
|
2007-09-04 19:16:43 -04:00
|
|
|
(export assemble-sources code-entry-adjustment)
|
2007-05-06 18:24:25 -04:00
|
|
|
(import
|
|
|
|
(ikarus)
|
2007-10-12 00:33:19 -04:00
|
|
|
(rnrs bytevectors)
|
2007-09-04 20:18:11 -04:00
|
|
|
(except (ikarus code-objects) procedure-annotation)
|
2007-05-06 18:24:25 -04:00
|
|
|
(ikarus system $pairs))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define fold
|
|
|
|
(lambda (f init ls)
|
|
|
|
(cond
|
|
|
|
[(null? ls) init]
|
|
|
|
[else
|
|
|
|
(f (car ls) (fold f init (cdr ls)))])))
|
|
|
|
|
|
|
|
(define convert-instructions
|
|
|
|
(lambda (ls)
|
|
|
|
(fold convert-instruction '() ls)))
|
|
|
|
|
|
|
|
(define register-mapping
|
|
|
|
'([%eax 32 0]
|
|
|
|
[%ecx 32 1]
|
|
|
|
[%edx 32 2]
|
|
|
|
[%ebx 32 3]
|
|
|
|
[%esp 32 4]
|
|
|
|
[%ebp 32 5]
|
|
|
|
[%esi 32 6]
|
|
|
|
[%edi 32 7]
|
|
|
|
[%al 8 0]
|
|
|
|
[%cl 8 1]
|
|
|
|
[%dl 8 2]
|
|
|
|
[%bl 8 3]
|
|
|
|
[%ah 8 4]
|
|
|
|
[%ch 8 5]
|
|
|
|
[%dh 8 6]
|
|
|
|
[%bh 8 7]
|
2007-02-13 17:24:00 -05:00
|
|
|
[/0 0 0]
|
|
|
|
[/1 0 1]
|
|
|
|
[/2 0 2]
|
|
|
|
[/3 0 3]
|
|
|
|
[/4 0 4]
|
|
|
|
[/5 0 5]
|
|
|
|
[/6 0 6]
|
|
|
|
[/7 0 7]
|
2007-06-15 01:53:34 -04:00
|
|
|
[xmm0 xmm 0]
|
|
|
|
[xmm1 xmm 1]
|
|
|
|
[xmm2 xmm 2]
|
|
|
|
[xmm3 xmm 3]
|
|
|
|
[xmm4 xmm 4]
|
|
|
|
[xmm5 xmm 5]
|
|
|
|
[xmm6 xmm 6]
|
|
|
|
[xmm7 xmm 7]
|
2006-11-23 19:44:29 -05:00
|
|
|
))
|
|
|
|
|
|
|
|
(define register-index
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(assq x register-mapping) => caddr]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'register-index "not a register" x)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define reg32?
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(assq x register-mapping) =>
|
2007-06-15 01:53:34 -04:00
|
|
|
(lambda (x) (eqv? (cadr x) 32))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[else #f])))
|
|
|
|
|
|
|
|
(define reg8?
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(assq x register-mapping) =>
|
2007-06-15 01:53:34 -04:00
|
|
|
(lambda (x) (eqv? (cadr x) 8))]
|
|
|
|
[else #f])))
|
|
|
|
|
|
|
|
(define xmmreg?
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(assq x register-mapping) =>
|
|
|
|
(lambda (x) (eqv? (cadr x) 'xmm))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[else #f])))
|
|
|
|
|
|
|
|
(define reg?
|
|
|
|
(lambda (x)
|
|
|
|
(assq x register-mapping)))
|
|
|
|
|
|
|
|
|
|
|
|
;(define with-args
|
|
|
|
; (lambda (ls f)
|
|
|
|
; (apply f (cdr ls))))
|
|
|
|
|
|
|
|
(define-syntax with-args
|
|
|
|
(syntax-rules (lambda)
|
|
|
|
[(_ x (lambda (a0 a1) b b* ...))
|
|
|
|
(let ([t x])
|
|
|
|
(if (pair? t)
|
|
|
|
(let ([t ($cdr t)])
|
|
|
|
(if (pair? t)
|
|
|
|
(let ([a0 ($car t)] [t ($cdr t)])
|
|
|
|
(if (pair? t)
|
|
|
|
(let ([a1 ($car t)])
|
|
|
|
(if (null? ($cdr t))
|
|
|
|
(let () b b* ...)
|
|
|
|
(error 'with-args "too many args")))
|
|
|
|
(error 'with-args "too few args")))
|
|
|
|
(error 'with-args "too few args")))
|
|
|
|
(error 'with-args "too few args")))]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax byte
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ x) (fxlogand x 255)]))
|
|
|
|
|
|
|
|
|
|
|
|
(define word
|
|
|
|
(lambda (x)
|
|
|
|
(cons 'word x)))
|
|
|
|
|
|
|
|
(define reloc-word
|
|
|
|
(lambda (x)
|
|
|
|
(cons 'reloc-word x)))
|
|
|
|
|
|
|
|
(define reloc-word+
|
|
|
|
(lambda (x d)
|
2007-09-09 23:41:12 -04:00
|
|
|
(cons* 'reloc-word+ x d)))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define byte?
|
|
|
|
(lambda (x)
|
|
|
|
(and (fixnum? x)
|
|
|
|
(fx<= x 127)
|
|
|
|
(fx<= -128 x))))
|
|
|
|
|
|
|
|
(define mem?
|
|
|
|
(lambda (x)
|
2007-01-09 01:24:07 -05:00
|
|
|
(and (pair? x)
|
2007-02-25 21:29:28 -05:00
|
|
|
(eq? (car x) 'disp))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define small-disp?
|
|
|
|
(lambda (x)
|
|
|
|
(and (mem? x)
|
|
|
|
(byte? (cadr x)))))
|
|
|
|
|
|
|
|
|
|
|
|
(define CODE
|
|
|
|
(lambda (n ac)
|
|
|
|
(cons (byte n) ac)))
|
|
|
|
|
|
|
|
(define CODE+r
|
|
|
|
(lambda (n r ac)
|
|
|
|
(cons (byte (fxlogor n (register-index r))) ac)))
|
|
|
|
|
|
|
|
(define ModRM
|
|
|
|
(lambda (mod reg r/m ac)
|
|
|
|
(cons (byte (fxlogor
|
|
|
|
(register-index r/m)
|
|
|
|
(fxlogor
|
|
|
|
(fxsll (register-index reg) 3)
|
|
|
|
(fxsll mod 6))))
|
|
|
|
(if (and (not (fx= mod 3)) (eq? r/m '%esp))
|
|
|
|
(cons (byte #x24) ac)
|
|
|
|
ac))))
|
|
|
|
|
2007-01-09 01:24:07 -05:00
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
(define IMM32
|
|
|
|
(lambda (n ac)
|
|
|
|
(cond
|
|
|
|
[(int? n)
|
2007-02-05 14:30:42 -05:00
|
|
|
(if (fixnum? n)
|
2007-09-09 23:41:12 -04:00
|
|
|
(cons*
|
2007-02-05 22:35:38 -05:00
|
|
|
(byte n)
|
2007-02-05 14:30:42 -05:00
|
|
|
(byte (fxsra n 8))
|
|
|
|
(byte (fxsra n 16))
|
|
|
|
(byte (fxsra n 24))
|
|
|
|
ac)
|
2007-02-05 22:35:38 -05:00
|
|
|
(let* ([lo (remainder n 256)]
|
|
|
|
[hi (quotient (if (< n 0) (- n 255) n) 256)])
|
2007-09-09 23:41:12 -04:00
|
|
|
(cons*
|
2007-02-05 22:35:38 -05:00
|
|
|
(byte lo)
|
2007-02-05 14:30:42 -05:00
|
|
|
(byte hi)
|
|
|
|
(byte (fxsra hi 8))
|
|
|
|
(byte (fxsra hi 16))
|
2007-02-05 22:35:38 -05:00
|
|
|
ac)))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(obj? n)
|
|
|
|
(let ([v (cadr n)])
|
|
|
|
(if (immediate? v)
|
|
|
|
(cons (word v) ac)
|
|
|
|
(cons (reloc-word v) ac)))]
|
|
|
|
[(obj+? n)
|
|
|
|
(let ([v (cadr n)] [d (caddr n)])
|
|
|
|
(cons (reloc-word+ v d) ac))]
|
|
|
|
[(label-address? n)
|
|
|
|
(cons (cons 'label-addr (label-name n)) ac)]
|
|
|
|
[(foreign? n)
|
|
|
|
(cons (cons 'foreign-label (label-name n)) ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'IMM32 "invalid" n)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
(define IMM8
|
|
|
|
(lambda (n ac)
|
|
|
|
(cond
|
|
|
|
[(int? n)
|
2007-09-09 23:41:12 -04:00
|
|
|
(cons* (byte n) ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'IMM8 "invalid" n)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
(define imm?
|
|
|
|
(lambda (x)
|
|
|
|
(or (int? x)
|
|
|
|
(obj? x)
|
|
|
|
(obj+? x)
|
|
|
|
(label-address? x)
|
|
|
|
(foreign? x))))
|
|
|
|
|
|
|
|
(define foreign?
|
|
|
|
(lambda (x)
|
|
|
|
(and (pair? x) (eq? (car x) 'foreign-label))))
|
|
|
|
|
|
|
|
|
|
|
|
(define imm8?
|
|
|
|
(lambda (x)
|
2007-01-09 01:44:00 -05:00
|
|
|
(and (int? x) (byte? x))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define label?
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(and (pair? x) (eq? (car x) 'label))
|
|
|
|
(let ([d (cdr x)])
|
|
|
|
(unless (and (null? (cdr d))
|
|
|
|
(symbol? (car d)))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'assemble "invalid label" x)))
|
2006-11-23 19:44:29 -05:00
|
|
|
#t]
|
|
|
|
[else #f])))
|
|
|
|
|
|
|
|
(define label-address?
|
|
|
|
(lambda (x)
|
|
|
|
(cond
|
|
|
|
[(and (pair? x) (eq? (car x) 'label-address))
|
|
|
|
(let ([d (cdr x)])
|
|
|
|
(unless (and (null? (cdr d))
|
|
|
|
(or (symbol? (car d))
|
|
|
|
(string? (car d))))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'assemble "invalid label-address" x)))
|
2006-11-23 19:44:29 -05:00
|
|
|
#t]
|
|
|
|
[else #f])))
|
|
|
|
|
|
|
|
(define label-name
|
|
|
|
(lambda (x) (cadr x)))
|
|
|
|
|
2007-02-05 14:19:03 -05:00
|
|
|
(define int? integer?)
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define obj?
|
|
|
|
(lambda (x)
|
|
|
|
(and (pair? x) (eq? (car x) 'obj))))
|
|
|
|
|
|
|
|
(define obj+?
|
|
|
|
(lambda (x)
|
|
|
|
(and (pair? x) (eq? (car x) 'obj+))))
|
|
|
|
|
|
|
|
(define CODErri
|
|
|
|
(lambda (c d s i ac)
|
|
|
|
(cond
|
|
|
|
[(imm8? i)
|
|
|
|
(CODE c (ModRM 1 d s (IMM8 i ac)))]
|
|
|
|
[(imm? i)
|
|
|
|
(CODE c (ModRM 2 d s (IMM32 i ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'CODErri "invalid i" i)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define CODErr
|
|
|
|
(lambda (c d s ac)
|
|
|
|
(CODE c (ModRM 3 d s ac))))
|
|
|
|
|
|
|
|
(define CODEri
|
|
|
|
(lambda (c d i ac)
|
|
|
|
(CODE+r c d (IMM32 i ac))))
|
|
|
|
|
|
|
|
|
|
|
|
(define RegReg
|
|
|
|
(lambda (r1 r2 r3 ac)
|
|
|
|
(cond
|
|
|
|
[(eq? r3 '%esp) (error 'assembler "BUG: invalid src %esp")]
|
|
|
|
[(eq? r1 '%ebp) (error 'assembler "BUG: invalid src %ebp")]
|
|
|
|
[else
|
2007-09-09 23:41:12 -04:00
|
|
|
(cons*
|
2006-11-23 19:44:29 -05:00
|
|
|
(byte (fxlogor 4 (fxsll (register-index r1) 3)))
|
|
|
|
(byte (fxlogor (register-index r2)
|
|
|
|
(fxsll (register-index r3) 3)))
|
|
|
|
ac)])))
|
|
|
|
|
|
|
|
|
|
|
|
(define IMM32*2
|
|
|
|
(lambda (i1 i2 ac)
|
|
|
|
(cond
|
|
|
|
[(and (int? i1) (obj? i2))
|
2007-01-09 01:44:00 -05:00
|
|
|
(let ([d i1] [v (cadr i2)])
|
2006-11-23 19:44:29 -05:00
|
|
|
(cons (reloc-word+ v d) ac))]
|
2007-02-11 04:12:09 -05:00
|
|
|
[(and (int? i2) (obj? i1)) (IMM32*2 i2 i1 ac)]
|
2007-10-23 23:55:57 -04:00
|
|
|
[(and (int? i1) (int? i2))
|
2007-10-25 14:32:26 -04:00
|
|
|
;FIXME
|
2007-10-23 23:55:57 -04:00
|
|
|
(IMM32 i1 (IMM32 i2 ac))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'assemble "invalid IMM32*2" i1 i2)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define CODErd
|
|
|
|
(lambda (c r1 disp ac)
|
|
|
|
(with-args disp
|
|
|
|
(lambda (a1 a2)
|
|
|
|
(cond
|
|
|
|
[(and (reg? a1) (reg? a2))
|
|
|
|
(CODE c (RegReg r1 a1 a2 ac))]
|
|
|
|
[(and (imm? a1) (reg? a2))
|
|
|
|
(CODErri c r1 a2 a1 ac)]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(and (imm? a2) (reg? a1))
|
|
|
|
(CODErri c r1 a1 a2 ac)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (imm? a1) (imm? a2))
|
|
|
|
(CODE c
|
|
|
|
(ModRM 0 r1 '/5
|
|
|
|
(IMM32*2 a1 a2 ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'CODErd "unhandled" disp)])))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define CODEdi
|
2007-02-12 17:59:58 -05:00
|
|
|
(lambda (c /? disp n ac)
|
2006-11-23 19:44:29 -05:00
|
|
|
(with-args disp
|
|
|
|
(lambda (a1 a2)
|
|
|
|
(cond
|
|
|
|
[(and (reg? a1) (reg? a2))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'CODEdi "unsupported1" disp)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (imm? a1) (reg? a2))
|
2007-02-12 17:59:58 -05:00
|
|
|
(CODErri c /? a2 a1 (IMM32 n ac))]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(and (imm? a2) (reg? a1))
|
2007-02-12 17:59:58 -05:00
|
|
|
(CODErri c /? a1 a2 (IMM32 n ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (imm? a1) (imm? a2))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'CODEdi "unsupported2" disp)]
|
|
|
|
[else (error 'CODEdi "unhandled" disp)])))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
2007-02-14 15:50:34 -05:00
|
|
|
(define (SIB s i b ac)
|
|
|
|
(cons (byte
|
|
|
|
(fxlogor
|
|
|
|
(register-index b)
|
|
|
|
(fxlogor
|
|
|
|
(fxsll (register-index i) 3)
|
|
|
|
(fxsll s 6))))
|
|
|
|
ac))
|
2007-02-13 17:24:00 -05:00
|
|
|
; 81 /0 id ADD r/m32,imm32 Valid Add imm32 to
|
|
|
|
(define (CODE/digit c /d)
|
2007-02-13 02:05:58 -05:00
|
|
|
(lambda (dst ac)
|
|
|
|
(cond
|
|
|
|
[(mem? dst)
|
|
|
|
(with-args dst
|
|
|
|
(lambda (a0 a1)
|
|
|
|
(cond
|
|
|
|
[(and (imm8? a0) (reg? a1))
|
2007-02-13 17:24:00 -05:00
|
|
|
(CODE c (ModRM 1 /d a1 (IMM8 a0 ac)))]
|
2007-02-15 23:54:39 -05:00
|
|
|
[(and (imm? a0) (reg? a1))
|
|
|
|
(CODE c (ModRM 2 /d a1 (IMM32 a0 ac)))]
|
2007-02-14 19:42:36 -05:00
|
|
|
[(and (imm8? a1) (reg? a0))
|
|
|
|
(CODE c (ModRM 1 /d a0 (IMM8 a1 ac)))]
|
2007-06-02 21:55:40 -04:00
|
|
|
[(and (imm? a1) (reg? a0))
|
|
|
|
(CODE c (ModRM 2 /d a0 (IMM32 a1 ac)))]
|
2007-02-14 15:50:34 -05:00
|
|
|
[(and (reg? a0) (reg? a1))
|
|
|
|
(CODE c (ModRM 1 /d '/4 (SIB 0 a0 a1 (IMM8 0 ac))))]
|
2007-06-16 05:08:38 -04:00
|
|
|
[(and (imm? a0) (imm? a1))
|
|
|
|
(CODE c (ModRM 0 /d '/5 (IMM32*2 a0 a1 ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'CODE/digit "unhandled" a0 a1)])))]
|
|
|
|
[else (error 'CODE/digit "unhandled" dst)])))
|
2007-02-13 17:24:00 -05:00
|
|
|
|
2007-02-13 02:05:58 -05:00
|
|
|
(define CODEid
|
|
|
|
(lambda (c /? n disp ac)
|
|
|
|
(with-args disp
|
|
|
|
(lambda (a1 a2)
|
|
|
|
(cond
|
|
|
|
[(and (reg? a1) (reg? a2))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'CODEid "unsupported1" disp)]
|
2007-02-13 02:05:58 -05:00
|
|
|
[(and (imm? a1) (reg? a2))
|
|
|
|
(error 'CODEid "unsupported2")
|
|
|
|
(CODErri c /? a2 a1 (IMM32 n ac))]
|
|
|
|
[(and (imm? a2) (reg? a1))
|
|
|
|
(error 'CODEid "unsupported3")
|
|
|
|
(CODErri c /? a1 a2 (IMM32 n ac))]
|
|
|
|
[(and (imm? a1) (imm? a2))
|
|
|
|
(error 'CODEid "unsupported4")]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'CODEid "unhandled" disp)])))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define CODEdi8
|
2007-02-13 02:05:58 -05:00
|
|
|
(lambda (c /? disp n ac)
|
2006-11-23 19:44:29 -05:00
|
|
|
(with-args disp
|
|
|
|
(lambda (i r)
|
2007-02-13 02:05:58 -05:00
|
|
|
(CODErri c /? r i (IMM8 n ac))))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define *cogen* (gensym "*cogen*"))
|
|
|
|
|
|
|
|
(define-syntax add-instruction
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ (name instr ac args ...) b b* ...)
|
|
|
|
(putprop 'name *cogen*
|
|
|
|
(cons (length '(args ...))
|
|
|
|
(lambda (instr ac args ...) b b* ...)))]))
|
|
|
|
|
|
|
|
(define-syntax add-instructions
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ instr ac [(name* arg** ...) b* b** ...] ...)
|
|
|
|
(begin
|
|
|
|
(add-instruction (name* instr ac arg** ...) b* b** ...) ...)]))
|
|
|
|
|
|
|
|
(define (convert-instruction a ac)
|
|
|
|
(cond
|
|
|
|
[(getprop (car a) *cogen*) =>
|
|
|
|
(lambda (p)
|
|
|
|
(let ([n (car p)] [proc (cdr p)] [args (cdr a)])
|
|
|
|
(cond
|
|
|
|
[(fx= n 2)
|
|
|
|
(if (fx= (length args) 2)
|
|
|
|
(proc a ac (car args) (cadr args))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'convert-instruction "incorrect args" a))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(fx= n 1)
|
|
|
|
(if (fx= (length args) 1)
|
|
|
|
(proc a ac (car args))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'convert-instruction "incorrect args" a))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(fx= n 0)
|
|
|
|
(if (fx= (length args) 0)
|
|
|
|
(proc a ac)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'convert-instruction "incorrect args" a))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[else
|
|
|
|
(if (fx= (length args) n)
|
|
|
|
(apply proc a ac args)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'convert-instruction "incorrect args" a))])))]
|
|
|
|
[else (error 'convert-instruction "unknown instruction" a)]))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (instr/2 arg1 arg2 ac ircode imcode rrcode rmcode mrcode)
|
|
|
|
(cond
|
|
|
|
[(imm? arg1)
|
|
|
|
(cond
|
|
|
|
[(reg? arg2) (CODEri ircode arg2 arg1 ac)]
|
2007-02-12 17:59:58 -05:00
|
|
|
[(mem? arg2) (CODEdi imcode '/0 arg2 arg1 ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'instr/2 "invalid args" arg1 arg2)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(reg? arg1)
|
|
|
|
(cond
|
|
|
|
[(reg? arg2) (CODErr rrcode arg1 arg2 ac)]
|
|
|
|
[(mem? arg2) (CODErd rmcode arg1 arg2 ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'instr/2 "invalid args" arg1 arg2)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(mem? arg1)
|
|
|
|
(cond
|
|
|
|
[(reg? arg2) (CODErd mrcode arg2 arg1 ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'instr/2 "invalid args" arg1 arg2)])]
|
|
|
|
[else (error 'instr/2 "invalid args" arg1 arg2)]))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(module ()
|
|
|
|
(define who 'assembler)
|
|
|
|
|
|
|
|
(define (conditional-set c dst ac)
|
|
|
|
(cond
|
|
|
|
[(reg8? dst)
|
|
|
|
(CODE #x0F (CODE c (ModRM 3 '/0 dst ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid condition-set" dst)]))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define (conditional-jump c dst ac)
|
|
|
|
(cond
|
|
|
|
[(imm? dst)
|
|
|
|
(CODE #x0F (CODE c (IMM32 dst ac)))]
|
|
|
|
[(label? dst)
|
|
|
|
(CODE #x0F (CODE c (cons (cons 'relative (label-name dst)) ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid conditional jump target" dst)]))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(add-instructions instr ac
|
|
|
|
[(ret) (CODE #xC3 ac)]
|
|
|
|
[(cltd) (CODE #x99 ac)]
|
2007-02-12 17:59:58 -05:00
|
|
|
; ircode imcode rrcode rmcode mrcode)
|
2006-11-23 19:44:29 -05:00
|
|
|
[(movl src dst) (instr/2 src dst ac #xB8 #xC7 #x89 #x89 #x8B)]
|
|
|
|
[(movb src dst)
|
|
|
|
(cond
|
2007-02-14 15:50:34 -05:00
|
|
|
[(and (imm8? src) (mem? dst))
|
|
|
|
((CODE/digit #xC6 '/0) dst (IMM8 src ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (reg8? src) (mem? dst)) (CODErd #x88 src dst ac)]
|
2007-02-14 15:50:34 -05:00
|
|
|
[(and (mem? src) (reg8? dst)) (CODErd #x8A dst src ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 01:53:34 -04:00
|
|
|
[(movsd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x10 dst) src ac)))]
|
|
|
|
[(and (xmmreg? src) (or (xmmreg? dst) (mem? dst)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x11 src) dst ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-18 07:29:39 -04:00
|
|
|
[(cvtsi2sd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (reg? src))
|
|
|
|
(CODE #xF2 (CODE #x0F (CODE #x2A (ModRM 3 src dst ac))))]
|
|
|
|
[(and (xmmreg? dst) (mem? src))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x2A dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 01:53:34 -04:00
|
|
|
[(addsd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x58 dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 01:53:34 -04:00
|
|
|
[(subsd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x5C dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 01:53:34 -04:00
|
|
|
[(mulsd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x59 dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 01:53:34 -04:00
|
|
|
[(divsd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #xF2 (CODE #x0F ((CODE/digit #x5E dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-06-15 05:19:28 -04:00
|
|
|
[(ucomisd src dst)
|
|
|
|
(cond
|
|
|
|
[(and (xmmreg? dst) (or (xmmreg? src) (mem? src)))
|
|
|
|
(CODE #x66 (CODE #x0F ((CODE/digit #x2E dst) src ac)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(addl src dst)
|
|
|
|
(cond
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/0 dst (IMM8 src ac)))]
|
2007-02-05 22:35:38 -05:00
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODE #x05 (IMM32 src ac))]
|
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x81 (ModRM 3 '/0 dst (IMM32 src ac)))]
|
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x01 (ModRM 3 src dst ac))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x03 dst src ac)]
|
2006-12-21 09:16:33 -05:00
|
|
|
[(and (imm? src) (mem? dst))
|
2007-02-13 17:24:00 -05:00
|
|
|
((CODE/digit #x81 '/0) dst (IMM32 src ac))]
|
2007-02-13 02:05:58 -05:00
|
|
|
[(and (reg? src) (mem? dst))
|
2007-02-13 17:24:00 -05:00
|
|
|
((CODE/digit #x01 src) dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(subl src dst)
|
|
|
|
(cond
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/5 dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
|
|
|
(CODE #x2D (IMM32 src ac))]
|
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x81 (ModRM 3 '/5 dst (IMM32 src ac)))]
|
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x29 (ModRM 3 src dst ac))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x2B dst src ac)]
|
2007-02-19 23:33:29 -05:00
|
|
|
[(and (imm? src) (mem? dst))
|
|
|
|
((CODE/digit #x81 '/5) dst (IMM32 src ac))]
|
2007-02-14 19:42:36 -05:00
|
|
|
[(and (reg? src) (mem? dst))
|
|
|
|
((CODE/digit #x29 src) dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(sall src dst)
|
|
|
|
(cond
|
2007-01-09 01:44:00 -05:00
|
|
|
[(and (equal? 1 src) (reg? dst))
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODE #xD1 (ModRM 3 '/4 dst ac))]
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #xC1 (ModRM 3 '/4 dst (IMM8 src ac)))]
|
2007-02-13 02:05:58 -05:00
|
|
|
[(and (imm8? src) (mem? dst))
|
2007-02-13 17:24:00 -05:00
|
|
|
((CODE/digit #xC1 '/4) dst (IMM8 src ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (eq? src '%cl) (reg? dst))
|
|
|
|
(CODE #xD3 (ModRM 3 '/4 dst ac))]
|
2007-03-10 19:50:24 -05:00
|
|
|
[(and (eq? src '%cl) (mem? dst))
|
|
|
|
((CODE/digit #xD3 '/4) dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(shrl src dst)
|
|
|
|
(cond
|
2007-01-09 01:44:00 -05:00
|
|
|
[(and (equal? 1 src) (reg? dst))
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODE #xD1 (ModRM 3 '/5 dst ac))]
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #xC1 (ModRM 3 '/5 dst (IMM8 src ac)))]
|
|
|
|
[(and (eq? src '%cl) (reg? dst))
|
|
|
|
(CODE #xD3 (ModRM 3 '/5 dst ac))]
|
2007-02-22 21:58:38 -05:00
|
|
|
[(and (imm8? src) (mem? dst))
|
|
|
|
((CODE/digit #xC1 '/5) dst (IMM8 src ac))]
|
2007-03-10 19:50:24 -05:00
|
|
|
[(and (eq? src '%cl) (mem? dst))
|
|
|
|
((CODE/digit #xD3 '/5) dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(sarl src dst)
|
|
|
|
(cond
|
2007-01-09 01:44:00 -05:00
|
|
|
[(and (equal? 1 src) (reg? dst))
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODE #xD1 (ModRM 3 '/7 dst ac))]
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #xC1 (ModRM 3 '/7 dst (IMM8 src ac)))]
|
2007-02-13 02:05:58 -05:00
|
|
|
[(and (imm8? src) (mem? dst))
|
2007-02-13 17:24:00 -05:00
|
|
|
((CODE/digit #xC1 '/7) dst (IMM8 src ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (eq? src '%cl) (reg? dst))
|
|
|
|
(CODE #xD3 (ModRM 3 '/7 dst ac))]
|
2007-03-10 19:50:24 -05:00
|
|
|
[(and (eq? src '%cl) (mem? dst))
|
|
|
|
((CODE/digit #xD3 '/7) dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(andl src dst)
|
|
|
|
(cond
|
2007-02-14 15:50:34 -05:00
|
|
|
[(and (imm? src) (mem? dst))
|
|
|
|
((CODE/digit #x81 '/4) dst (IMM32 src ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/4 dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
|
|
|
(CODE #x25 (IMM32 src ac))]
|
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x81 (ModRM 3 '/4 dst (IMM32 src ac)))]
|
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x21 (ModRM 3 src dst ac))]
|
2007-02-16 10:11:21 -05:00
|
|
|
[(and (reg? src) (mem? dst))
|
|
|
|
((CODE/digit #x21 src) dst ac)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x23 dst src ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(orl src dst)
|
|
|
|
(cond
|
2007-02-14 15:50:34 -05:00
|
|
|
[(and (imm? src) (mem? dst))
|
|
|
|
((CODE/digit #x81 '/1) dst (IMM32 src ac))]
|
2007-03-10 19:50:24 -05:00
|
|
|
[(and (reg? src) (mem? dst))
|
|
|
|
((CODE/digit #x09 src) dst ac)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
|
|
|
(CODE #x0D (IMM32 src ac))]
|
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))]
|
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x09 (ModRM 3 src dst ac))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x0B dst src ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(xorl src dst)
|
|
|
|
(cond
|
2007-02-05 17:09:50 -05:00
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/6 dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
|
|
|
(CODE #x35 (IMM32 src ac))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x31 (ModRM 3 src dst ac))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x33 dst src ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2007-01-09 01:24:07 -05:00
|
|
|
[(leal src dst)
|
|
|
|
(cond
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x8D dst src ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(cmpl src dst)
|
|
|
|
(cond
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x83 (ModRM 3 '/7 dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (eq? dst '%eax))
|
|
|
|
(CODE #x3D (IMM32 src ac))]
|
2006-11-23 19:48:14 -05:00
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x81 (ModRM 3 '/7 dst (IMM32 src ac)))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x39 (ModRM 3 src dst ac))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODErd #x3B dst src ac)]
|
|
|
|
[(and (imm8? src) (mem? dst))
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #x83 '/7 dst (IMM8 src ac))]
|
|
|
|
[(and (imm? src) (mem? dst))
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #x81 '/7 dst (IMM32 src ac))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(imull src dst)
|
|
|
|
(cond
|
|
|
|
[(and (imm8? src) (reg? dst))
|
|
|
|
(CODE #x6B (ModRM 3 dst dst (IMM8 src ac)))]
|
|
|
|
[(and (imm? src) (reg? dst))
|
|
|
|
(CODE #x69 (ModRM 3 dst dst (IMM32 src ac)))]
|
|
|
|
[(and (reg? src) (reg? dst))
|
|
|
|
(CODE #x0F (CODE #xAF (ModRM 3 dst src ac)))]
|
|
|
|
[(and (mem? src) (reg? dst))
|
|
|
|
(CODE #x0F (CODErd #xAF dst src ac))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(idivl dst)
|
|
|
|
(cond
|
|
|
|
[(reg? dst)
|
|
|
|
(CODErr #xF7 '/7 dst ac)]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #xF7 '/7 dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(pushl dst)
|
|
|
|
(cond
|
|
|
|
[(imm8? dst)
|
|
|
|
(CODE #x6A (IMM8 dst ac))]
|
|
|
|
[(imm? dst)
|
|
|
|
(CODE #x68 (IMM32 dst ac))]
|
|
|
|
[(reg? dst)
|
|
|
|
(CODE+r #x50 dst ac)]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #xFF '/6 dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(popl dst)
|
|
|
|
(cond
|
|
|
|
[(reg? dst)
|
|
|
|
(CODE+r #x58 dst ac)]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #x8F '/0 dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(notl dst)
|
|
|
|
(cond
|
|
|
|
[(reg? dst)
|
|
|
|
(CODE #xF7 (ModRM 3 '/2 dst ac))]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #xF7 '/7 dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(negl dst)
|
|
|
|
(cond
|
|
|
|
[(reg? dst)
|
|
|
|
(CODE #xF7 (ModRM 3 '/3 dst ac))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid" instr)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(jmp dst)
|
|
|
|
(cond
|
|
|
|
[(label? dst)
|
|
|
|
(CODE #xE9 (cons (cons 'relative (label-name dst)) ac))]
|
|
|
|
[(imm? dst)
|
|
|
|
(CODE #xE9 (IMM32 dst ac))]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #xFF '/4 dst ac)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid jmp target" dst)])]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(call dst)
|
|
|
|
(cond
|
|
|
|
[(imm? dst)
|
|
|
|
(CODE #xE8 (IMM32 dst ac))]
|
|
|
|
[(label? dst)
|
|
|
|
(CODE #xE8 (cons (cons 'relative (label-name dst)) ac))]
|
|
|
|
[(mem? dst)
|
2007-03-02 00:41:28 -05:00
|
|
|
;;; maybe error
|
2006-11-23 19:44:29 -05:00
|
|
|
(CODErd #xFF '/2 dst ac)]
|
|
|
|
[(reg? dst)
|
|
|
|
(CODE #xFF (ModRM 3 '/2 dst ac))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid jmp target" dst)])]
|
2007-02-13 17:24:00 -05:00
|
|
|
[(seta dst) (conditional-set #x97 dst ac)]
|
|
|
|
[(setae dst) (conditional-set #x93 dst ac)]
|
|
|
|
[(setb dst) (conditional-set #x92 dst ac)]
|
|
|
|
[(setbe dst) (conditional-set #x96 dst ac)]
|
|
|
|
[(setg dst) (conditional-set #x9F dst ac)]
|
|
|
|
[(setge dst) (conditional-set #x9D dst ac)]
|
|
|
|
[(setl dst) (conditional-set #x9C dst ac)]
|
|
|
|
[(setle dst) (conditional-set #x9E dst ac)]
|
|
|
|
[(sete dst) (conditional-set #x94 dst ac)]
|
|
|
|
[(setna dst) (conditional-set #x96 dst ac)]
|
|
|
|
[(setnae dst) (conditional-set #x92 dst ac)]
|
|
|
|
[(setnb dst) (conditional-set #x93 dst ac)]
|
|
|
|
[(setnbe dst) (conditional-set #x97 dst ac)]
|
|
|
|
[(setng dst) (conditional-set #x9E dst ac)]
|
|
|
|
[(setnge dst) (conditional-set #x9C dst ac)]
|
|
|
|
[(setnl dst) (conditional-set #x9D dst ac)]
|
|
|
|
[(setnle dst) (conditional-set #x9F dst ac)]
|
|
|
|
[(setne dst) (conditional-set #x95 dst ac)]
|
|
|
|
[(ja dst) (conditional-jump #x87 dst ac)]
|
|
|
|
[(jae dst) (conditional-jump #x83 dst ac)]
|
|
|
|
[(jb dst) (conditional-jump #x82 dst ac)]
|
|
|
|
[(jbe dst) (conditional-jump #x86 dst ac)]
|
|
|
|
[(jg dst) (conditional-jump #x8F dst ac)]
|
|
|
|
[(jge dst) (conditional-jump #x8D dst ac)]
|
|
|
|
[(jl dst) (conditional-jump #x8C dst ac)]
|
|
|
|
[(jle dst) (conditional-jump #x8E dst ac)]
|
|
|
|
[(je dst) (conditional-jump #x84 dst ac)]
|
|
|
|
[(jna dst) (conditional-jump #x86 dst ac)]
|
|
|
|
[(jnae dst) (conditional-jump #x82 dst ac)]
|
|
|
|
[(jnb dst) (conditional-jump #x83 dst ac)]
|
|
|
|
[(jnbe dst) (conditional-jump #x87 dst ac)]
|
|
|
|
[(jng dst) (conditional-jump #x8E dst ac)]
|
|
|
|
[(jnge dst) (conditional-jump #x8C dst ac)]
|
|
|
|
[(jnl dst) (conditional-jump #x8D dst ac)]
|
|
|
|
[(jnle dst) (conditional-jump #x8F dst ac)]
|
|
|
|
[(jne dst) (conditional-jump #x85 dst ac)]
|
|
|
|
[(jo dst) (conditional-jump #x80 dst ac)]
|
2007-09-12 00:57:04 -04:00
|
|
|
[(jp dst) (conditional-jump #x8A dst ac)]
|
|
|
|
[(jnp dst) (conditional-jump #x8B dst ac)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(byte x)
|
2007-10-25 14:32:26 -04:00
|
|
|
(unless (byte? x) (error who "not a byte" x))
|
2006-11-23 19:44:29 -05:00
|
|
|
(cons (byte x) ac)]
|
|
|
|
[(byte-vector x) (append (map (lambda (x) (byte x)) (vector->list x)) ac)]
|
2007-01-09 01:44:00 -05:00
|
|
|
[(int a) (IMM32 a ac)]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(label L)
|
2007-10-25 14:32:26 -04:00
|
|
|
(unless (symbol? L) (error who "label is not a symbol" L))
|
2006-11-23 19:44:29 -05:00
|
|
|
(cons (cons 'label L) ac)]
|
|
|
|
[(label-address L)
|
2007-10-25 14:32:26 -04:00
|
|
|
(unless (symbol? L) (error who "label-address is not a symbol" L))
|
2006-11-23 19:44:29 -05:00
|
|
|
(cons (cons 'label-addr L) ac)]
|
|
|
|
[(current-frame-offset)
|
|
|
|
(cons '(current-frame-offset) ac)]
|
|
|
|
[(nop) ac]
|
2007-01-09 01:24:07 -05:00
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
(define compute-code-size
|
|
|
|
(lambda (ls)
|
|
|
|
(fold (lambda (x ac)
|
|
|
|
(if (fixnum? x)
|
|
|
|
(fx+ ac 1)
|
|
|
|
(case (car x)
|
|
|
|
[(byte) (fx+ ac 1)]
|
|
|
|
[(word reloc-word reloc-word+ label-addr foreign-label
|
|
|
|
relative local-relative current-frame-offset)
|
|
|
|
(fx+ ac 4)]
|
|
|
|
[(label) ac]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'compute-code-size "unknown instr" x)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
0
|
|
|
|
ls)))
|
|
|
|
|
|
|
|
|
|
|
|
(define set-label-loc!
|
|
|
|
(lambda (x loc)
|
|
|
|
(when (getprop x '*label-loc*)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'compile "label is already defined" x))
|
2006-11-23 19:44:29 -05:00
|
|
|
(putprop x '*label-loc* loc)))
|
|
|
|
|
|
|
|
(define label-loc
|
|
|
|
(lambda (x)
|
|
|
|
(or (getprop x '*label-loc*)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'compile "undefined label" x))))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
(define unset-label-loc!
|
|
|
|
(lambda (x)
|
|
|
|
(remprop x '*label-loc*)))
|
|
|
|
|
|
|
|
|
|
|
|
(define set-code-word!
|
|
|
|
(lambda (code idx x)
|
|
|
|
(cond
|
|
|
|
[(fixnum? x)
|
|
|
|
(code-set! code (fx+ idx 0) (fxsll (fxlogand x #x3F) 2))
|
|
|
|
(code-set! code (fx+ idx 1) (fxlogand (fxsra x 6) #xFF))
|
|
|
|
(code-set! code (fx+ idx 2) (fxlogand (fxsra x 14) #xFF))
|
|
|
|
(code-set! code (fx+ idx 3) (fxlogand (fxsra x 22) #xFF))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'set-code-word! "unhandled" x)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
|
|
|
|
(define (optimize-local-jumps ls)
|
|
|
|
(define locals '())
|
|
|
|
(define g (gensym))
|
|
|
|
(for-each
|
|
|
|
(lambda (x)
|
|
|
|
(when (and (pair? x) (eq? (car x) 'label))
|
|
|
|
(putprop (cdr x) g 'local)
|
|
|
|
(set! locals (cons (cdr x) locals))))
|
|
|
|
ls)
|
|
|
|
(for-each
|
|
|
|
(lambda (x)
|
|
|
|
(when (and (pair? x)
|
|
|
|
(eq? (car x) 'relative)
|
|
|
|
(eq? (getprop (cdr x) g) 'local))
|
|
|
|
(set-car! x 'local-relative)))
|
|
|
|
ls)
|
|
|
|
(for-each (lambda (x) (remprop x g)) locals)
|
|
|
|
ls)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define whack-instructions
|
|
|
|
(lambda (x ls)
|
|
|
|
(define f
|
|
|
|
(lambda (ls idx reloc)
|
|
|
|
(cond
|
|
|
|
[(null? ls) reloc]
|
|
|
|
[else
|
|
|
|
(let ([a (car ls)])
|
|
|
|
(if (fixnum? a)
|
|
|
|
(begin
|
|
|
|
(code-set! x idx a)
|
|
|
|
(f (cdr ls) (fxadd1 idx) reloc))
|
|
|
|
(case (car a)
|
|
|
|
[(byte)
|
|
|
|
(code-set! x idx (cdr a))
|
|
|
|
(f (cdr ls) (fx+ idx 1) reloc)]
|
|
|
|
[(reloc-word reloc-word+)
|
|
|
|
(f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))]
|
|
|
|
[(local-relative relative label-addr foreign-label)
|
|
|
|
(f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))]
|
|
|
|
[(word)
|
|
|
|
(let ([v (cdr a)])
|
|
|
|
(set-code-word! x idx v)
|
|
|
|
(f (cdr ls) (fx+ idx 4) reloc))]
|
|
|
|
[(current-frame-offset)
|
|
|
|
(set-code-word! x idx idx)
|
|
|
|
(f (cdr ls) (fx+ idx 4) reloc)]
|
|
|
|
[(label)
|
2006-12-04 10:20:59 -05:00
|
|
|
(set-label-loc! (cdr a) (list x idx))
|
2006-11-23 19:44:29 -05:00
|
|
|
(f (cdr ls) idx reloc)]
|
|
|
|
[else
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'whack-instructions "unknown instr" a)])))])))
|
2006-11-23 19:44:29 -05:00
|
|
|
(f ls 0 '())))
|
|
|
|
|
|
|
|
(define wordsize 4)
|
|
|
|
|
|
|
|
|
|
|
|
(define compute-reloc-size
|
|
|
|
(lambda (ls)
|
|
|
|
(fold (lambda (x ac)
|
|
|
|
(if (fixnum? x)
|
|
|
|
ac
|
|
|
|
(case (car x)
|
|
|
|
[(reloc-word foreign-label) (fx+ ac 2)]
|
|
|
|
[(relative reloc-word+ label-addr) (fx+ ac 3)]
|
2007-02-22 21:58:38 -05:00
|
|
|
[(word byte label current-frame-offset local-relative) ac]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'compute-reloc-size "unknown instr" x)])))
|
2006-11-23 19:44:29 -05:00
|
|
|
0
|
|
|
|
ls)))
|
|
|
|
|
2007-05-22 17:56:15 -04:00
|
|
|
(define foreign-string->bytevector
|
|
|
|
(let ([mem '()])
|
|
|
|
(lambda (x)
|
|
|
|
(let f ([ls mem])
|
|
|
|
(cond
|
|
|
|
[(null? ls)
|
2007-10-12 00:33:19 -04:00
|
|
|
(let ([bv (string->utf8 x)])
|
2007-05-22 17:56:15 -04:00
|
|
|
(set! mem (cons (cons x bv) mem))
|
|
|
|
bv)]
|
|
|
|
[(string=? x (caar ls)) (cdar ls)]
|
|
|
|
[else (f (cdr ls))])))))
|
|
|
|
|
|
|
|
|
2007-09-04 19:16:43 -04:00
|
|
|
(define code-entry-adjustment
|
|
|
|
(let ([v #f])
|
|
|
|
(case-lambda
|
|
|
|
[() (or v (error 'code-entry-adjustment "uninitialized"))]
|
|
|
|
[(x) (set! v x)])))
|
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
(define whack-reloc
|
2006-12-04 10:20:59 -05:00
|
|
|
(lambda (thunk?-label code vec)
|
2006-11-23 19:44:29 -05:00
|
|
|
(define reloc-idx 0)
|
|
|
|
(lambda (r)
|
2006-12-04 10:20:59 -05:00
|
|
|
(let ([idx (car r)] [type (cadr r)]
|
|
|
|
[v
|
|
|
|
(let ([v (cddr r)])
|
|
|
|
(cond
|
|
|
|
[(thunk?-label v) =>
|
|
|
|
(lambda (label)
|
|
|
|
(let ([p (label-loc label)])
|
|
|
|
(cond
|
|
|
|
[(fx= (length p) 2)
|
|
|
|
(let ([code (car p)] [idx (cadr p)])
|
|
|
|
(unless (fx= idx 0)
|
|
|
|
(error 'whack-reloc
|
2007-10-25 14:32:26 -04:00
|
|
|
"cannot create a thunk pointing"
|
2006-12-04 10:20:59 -05:00
|
|
|
idx))
|
2007-05-06 22:48:10 -04:00
|
|
|
(let ([thunk (code->thunk code)])
|
2006-12-04 10:20:59 -05:00
|
|
|
(set-cdr! (cdr p) (list thunk))
|
|
|
|
thunk))]
|
|
|
|
[else (caddr p)])))]
|
|
|
|
[else v]))])
|
2006-11-23 19:44:29 -05:00
|
|
|
(case type
|
|
|
|
[(reloc-word)
|
|
|
|
(vector-set! vec reloc-idx (fxsll idx 2))
|
|
|
|
(vector-set! vec (fx+ reloc-idx 1) v)
|
|
|
|
(set! reloc-idx (fx+ reloc-idx 2))]
|
|
|
|
[(foreign-label)
|
2007-05-18 20:18:55 -04:00
|
|
|
;;; FIXME: converted strings should be memoized.
|
|
|
|
;;; wait for equal? hash tables.
|
2007-05-18 18:55:20 -04:00
|
|
|
(let ([name
|
|
|
|
(if (string? v)
|
2007-05-22 17:56:15 -04:00
|
|
|
(foreign-string->bytevector v)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'whack-reloc "not a string" v))])
|
2007-05-18 18:55:20 -04:00
|
|
|
(vector-set! vec reloc-idx (fxlogor 1 (fxsll idx 2)))
|
|
|
|
(vector-set! vec (fx+ reloc-idx 1) name)
|
|
|
|
(set! reloc-idx (fx+ reloc-idx 2)))]
|
2006-11-23 19:44:29 -05:00
|
|
|
[(reloc-word+)
|
|
|
|
(let ([obj (car v)] [disp (cdr v)])
|
|
|
|
(vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2)))
|
|
|
|
(vector-set! vec (fx+ reloc-idx 1) disp)
|
|
|
|
(vector-set! vec (fx+ reloc-idx 2) obj)
|
|
|
|
(set! reloc-idx (fx+ reloc-idx 3)))]
|
|
|
|
[(label-addr)
|
|
|
|
(let ([loc (label-loc v)])
|
2006-12-04 10:20:59 -05:00
|
|
|
(let ([obj (car loc)] [disp (cadr loc)])
|
2006-11-23 19:44:29 -05:00
|
|
|
(vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2)))
|
2007-09-04 19:16:43 -04:00
|
|
|
(vector-set! vec (fx+ reloc-idx 1)
|
|
|
|
(fx+ disp (code-entry-adjustment)))
|
2006-11-23 19:44:29 -05:00
|
|
|
(vector-set! vec (fx+ reloc-idx 2) obj)))
|
|
|
|
(set! reloc-idx (fx+ reloc-idx 3))]
|
|
|
|
[(local-relative)
|
|
|
|
(let ([loc (label-loc v)])
|
2006-12-04 10:20:59 -05:00
|
|
|
(let ([obj (car loc)] [disp (cadr loc)])
|
2006-11-23 19:44:29 -05:00
|
|
|
(unless (eq? obj code)
|
|
|
|
(error 'whack-reloc "local-relative differ"))
|
|
|
|
(let ([rel (fx- disp (fx+ idx 4))])
|
|
|
|
(code-set! code (fx+ idx 0) (fxlogand rel #xFF))
|
|
|
|
(code-set! code (fx+ idx 1) (fxlogand (fxsra rel 8) #xFF))
|
|
|
|
(code-set! code (fx+ idx 2) (fxlogand (fxsra rel 16) #xFF))
|
|
|
|
(code-set! code (fx+ idx 3) (fxlogand (fxsra rel 24) #xFF)))))]
|
|
|
|
[(relative)
|
|
|
|
(let ([loc (label-loc v)])
|
2006-12-04 10:20:59 -05:00
|
|
|
(let ([obj (car loc)] [disp (cadr loc)])
|
2007-02-22 21:58:38 -05:00
|
|
|
(unless (and (code? obj) (fixnum? disp))
|
2007-10-25 14:32:26 -04:00
|
|
|
(error 'whack-reloc "invalid relative jump obj/disp" obj disp))
|
2006-11-23 19:44:29 -05:00
|
|
|
(vector-set! vec reloc-idx (fxlogor 3 (fxsll idx 2)))
|
2007-09-04 19:16:43 -04:00
|
|
|
(vector-set! vec (fx+ reloc-idx 1)
|
|
|
|
(fx+ disp (code-entry-adjustment)))
|
2006-11-23 19:44:29 -05:00
|
|
|
(vector-set! vec (fx+ reloc-idx 2) obj)))
|
|
|
|
(set! reloc-idx (fx+ reloc-idx 3))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'whack-reloc "invalid reloc type" type)]))
|
2006-11-23 19:44:29 -05:00
|
|
|
)))
|
|
|
|
|
|
|
|
|
|
|
|
;;; (define list->code
|
|
|
|
;;; (lambda (ls)
|
|
|
|
;;; (let ([ls (convert-instructions ls)])
|
|
|
|
;;; (let ([n (compute-code-size ls)]
|
|
|
|
;;; [m (compute-reloc-size ls)])
|
|
|
|
;;; (let ([x (make-code n m 1)])
|
|
|
|
;;; (let ([reloc* (whack-instructions x ls)])
|
|
|
|
;;; (for-each (whack-reloc x) reloc*))
|
|
|
|
;;; (make-code-executable! x)
|
|
|
|
;;; x)))))
|
|
|
|
|
2007-05-03 03:58:43 -04:00
|
|
|
(define assemble-sources
|
2007-05-01 04:36:53 -04:00
|
|
|
(lambda (thunk?-label ls*)
|
2007-10-10 04:41:11 -04:00
|
|
|
(define (code-list ls)
|
|
|
|
(if (let ([a (cadr ls)])
|
|
|
|
(and (pair? a) (eq? (car a) 'name)))
|
|
|
|
(cddr ls)
|
|
|
|
(cdr ls)))
|
|
|
|
(define (code-name ls)
|
|
|
|
(let ([a (cadr ls)])
|
|
|
|
(and (pair? a)
|
|
|
|
(eq? (car a) 'name))
|
|
|
|
(cadr a)))
|
2007-05-01 04:36:53 -04:00
|
|
|
(let ([closure-size* (map car ls*)]
|
2007-10-10 04:41:11 -04:00
|
|
|
[code-name* (map code-name ls*)]
|
|
|
|
[ls* (map code-list ls*)])
|
2007-05-01 04:36:53 -04:00
|
|
|
(let* ([ls* (map convert-instructions ls*)]
|
|
|
|
[ls* (map optimize-local-jumps ls*)])
|
|
|
|
(let ([n* (map compute-code-size ls*)]
|
|
|
|
[m* (map compute-reloc-size ls*)])
|
|
|
|
(let ([code* (map make-code n* closure-size*)]
|
|
|
|
[relv* (map make-vector m*)])
|
|
|
|
(let ([reloc** (map whack-instructions code* ls*)])
|
|
|
|
(for-each
|
|
|
|
(lambda (foo reloc*)
|
|
|
|
(for-each (whack-reloc thunk?-label (car foo) (cdr foo)) reloc*))
|
|
|
|
(map cons code* relv*) reloc**)
|
|
|
|
(for-each set-code-reloc-vector! code* relv*)
|
2007-10-10 04:41:11 -04:00
|
|
|
(for-each (lambda (code name)
|
|
|
|
(when name
|
|
|
|
(set-code-annotation! code name)))
|
|
|
|
code* code-name*)
|
2007-05-01 04:36:53 -04:00
|
|
|
code*)))))))
|
|
|
|
|
2007-02-13 05:08:48 -05:00
|
|
|
|
2006-11-23 19:44:29 -05:00
|
|
|
)
|
2007-02-13 05:08:48 -05:00
|
|
|
|