home *** CD-ROM | disk | FTP | other *** search
- (herald marchas)
-
- (lset *deferred-loads?* t)
-
- (define risc/sub
- (object nil
- ((read-registers self r1 r2 r3)
- (read-registers risc/add r1 r2 r3))
- ((write-register self r1 r2 r3)
- (write-register risc/add r1 r2 r3))))
-
- (define risc/load
- (object nil
- ((read-registers self l ro d)
- (read-registers mips/load l ro d))
- ((write-register self l ro d)
- (write-register mips/load l ro d))))
-
- (define maybe-pushfr 'maybe-pushfr)
- (define maybe-popfr 'maybe-popfr)
-
- (define (emit-jump 1tag)
- (cond ((and (node? 1tag)
- (lambda-node? 1tag)
- (eq? (lambda-strategy 1tag) strategy/heap))
- (push (ib-instructions *current-ib*)
- (list jbr-inst nil (list jump-op/jabs)
- (cons 'template (maybe-cons-an-ib 1tag))))
- (push (ib-instructions *current-ib*)
- (list mips/noop nil)))
- (else
- (set (ib-cc *current-ib*) (list jump-op/jabs))
- (let ((1next (maybe-cons-an-ib 1tag)))
- (set (ib-1next *current-ib*) 1next)
- (push (ib-previous 1next) *current-ib*)))))
-
- (define (emit-branch-and-link l)
- (push (ib-instructions *current-ib*)
- (list jbr-inst nil (list jump-op/jl)
- (cond ((fixnum? l) l)
- ((and (node? l) (eq? (lambda-strategy l) strategy/heap))
- (cons 'template (maybe-cons-an-ib l)))
- (else
- (cons 'label (maybe-cons-an-ib l)))))))
-
-
- (define (emit-avoid-jump 1tag)
- (set (ib-avoid-jump? *current-ib*) '#t)
- (emit-jump 1tag))
-
- (define (emit-compare cc reg1 reg2 1tag 0tag)
- (receive (cc-list inst) (branch-pseudo-op cc reg1 reg2)
- (set (ib-cc *current-ib*) cc-list)
- (if inst (push (ib-instructions *current-ib*) inst))
- (let ((1next (maybe-cons-an-ib 1tag)))
- (set (ib-1next *current-ib*) 1next)
- (push (ib-previous 1next) *current-ib*))
- (and 0tag
- (let ((0next (maybe-cons-an-ib 0tag)))
- (set (ib-0next *current-ib*) 0next)
- (push (ib-previous 0next) *current-ib*)))))
-
-
- ;; Note that the slt arguments are reversed to be compatible with add etc.
-
- (define (branch-pseudo-op cc reg1 reg2)
- (xselect cc
- ((jump-op/jn= jump-op/j=)
- (cond ((fixnum? reg2) (return (list cc reg1 reg2) nil))
- (else
- (return (list cc reg1 ass-reg)
- (list risc/add nil reg2 zero ass-reg)))))
- ((jump-op/j<)
- (cond ((eq? reg2 zero) (return (list cc reg1) nil))
- ((eq? reg1 zero) (return (list (reverse-jump-ops cc) reg2) nil))
- (else
- (return (list jump-op/jn= ass-reg zero)
- (list mips/slt nil reg2 reg1 ass-reg)))))
- ((jump-op/j>=)
- (cond ((eq? reg2 zero) (return (list cc reg1) nil))
- ((eq? reg1 zero) (return (list (reverse-jump-ops cc) reg2) nil))
- (else
- (return (list jump-op/j= ass-reg zero)
- (list mips/slt nil reg2 reg1 ass-reg)))))
- ((jump-op/j<=)
- (cond ((eq? reg2 zero) (return (list cc reg1) nil))
- ((eq? reg1 zero) (return (list (reverse-jump-ops cc) reg2) nil))
- ((fixnum? reg2)
- (return (list jump-op/j= ass-reg zero)
- (list mips/slt nil reg1 reg2 ass-reg)))
- (else
- (return (list jump-op/jn= ass-reg zero)
- (list mips/slt nil `(lit . ,(fx+ (cdr reg2) 1)) reg1 ass-reg)))))
- ((jump-op/j>)
- (cond ((eq? reg2 zero) (return (list cc reg1) nil))
- ((eq? reg1 zero) (return (list (reverse-jump-ops cc) reg2) nil))
- ((fixnum? reg2)
- (return (list jump-op/jn= ass-reg zero)
- (list mips/slt nil reg1 reg2 ass-reg)))
- (else
- (return (list jump-op/j= ass-reg zero)
- (list mips/slt nil `(lit . ,(fx+ (cdr reg2) 1)) reg1 ass-reg)))))
- ((jump-op/uj<)
- (return (list jump-op/jn= ass-reg zero)
- (list mips/sltu nil reg2 reg1 ass-reg)))
- ((jump-op/uj<=)
- (return (list jump-op/j= ass-reg zero)
- (list mips/sltu nil reg1 reg2 ass-reg)))
- ((jump-op/uj>)
- (return (list jump-op/jn= ass-reg zero)
- (list mips/sltu nil reg1 reg2 ass-reg)))
- ((jump-op/uj>=)
- (return (list jump-op/j= ass-reg zero)
- (list mips/sltu nil reg2 reg1 ass-reg)))))
-
- (define (assembly-list is bv)
- (do ((is is (cdr is))
- (i 0 (fx+ i CELL)))
- ((null? is) repl-wont-print)
- (format t "~&~d:~8t" i)
- (write-i-bytes bv i)
- (destructure (((op comment . args) (car is)))
- (format t "~20t~a~40t" (apply instruction-as-string op i args))
- (if comment
- (apply format t (car comment) (cdr comment))))))
-
- (define (assemble-bits size is)
- (let ((code (make-bytev size)))
- (set *is* is)
- (set *bits* code)
- (do ((is is (cdr is))
- (i 0 (fx+ i CELL)))
- ((null? is)
- (format t "~&; assembled ~d bytes~%" size)
- code)
- (destructure (((op comment . args) (car is)))
- (apply op code i args)))))
-
-
- (define (add-to-front block)
- (cond ((or (not block) (ib-address block)))
- ((fx> (length (ib-previous block)) 1)
- (push *blocks-pending* block))
- (else
- (modify *blocks-pending* (lambda (x) (append! x (list block)))))))
-
-
- (define (linearize-code-blocks i is)
- (if (null? *blocks-pending*)
- (return i is)
- (let ((ib (pop *blocks-pending*)))
- (cond ((ib-address ib) (linearize-code-blocks i is))
- (else
- (set (ib-address ib) i)
- (iterate loop ((i i) (ib ib) (newis (ib-instructions ib)) (is is))
- (cond ((null? newis)
- (let ((0next (ib-0next ib))
- (1next (ib-1next ib)))
- (cond ((not 0next)
- (cond ((null? 1next)
- (linearize-code-blocks i is))
- ((and (not (ib-avoid-jump? ib))
- (any? ib-avoid-jump?
- (ib-previous 1next))
- (not (ib-address 1next)))
- (add-to-front (ib-0next 1next))
- (add-to-front (ib-1next 1next))
- (add-jump-no-return 1next i is))
- ((not (ib-address 1next))
- (set (ib-address 1next) i)
- (loop i 1next (ib-instructions 1next) is))
- (else
- (add-jump-no-return 1next i is))))
- ((not (ib-address 1next))
- (add-to-front 0next)
- (modify (car (ib-cc ib)) reverse-branch)
- (receive (i is) (add-jump 0next i is (ib-cc ib))
- (set (ib-address 1next) i)
- (loop i 1next (ib-instructions 1next) is)))
- ((not (ib-address 0next))
- (receive (i is) (add-jump 1next i is (ib-cc ib))
- (set (ib-address 0next) i)
- (loop i 0next (ib-instructions 0next) is)))
- ((preferred-arm? 0next 1next)
- (modify (car (ib-cc ib)) reverse-branch)
- (receive (i is) (add-jump 0next i is (ib-cc ib))
- (add-jump-no-return 1next i is)))
- (else
- (receive (i is) (add-jump 1next i is (ib-cc ib))
- (add-jump-no-return 0next i is))))))
- (else
- (let ((inst (caar newis)))
- (select (cond (*deferred-loads?* inst)
- ((eq? inst risc/load) nil)
- (else inst))
- ((risc/load)
- (set (caar newis) mips/load)
- (if (need-to-delay? (car newis) (cdr newis))
- (loop (fx+ i (fx* CELL 2)) ib (cdr newis)
- (cons noop-inst (cons (car newis) is)))
- (loop (fx+ i CELL) ib (cdr newis) (cons (car newis) is))))
- ((maybe-pushfr)
- (receive (is incr)
- (figure-pushfr is (lambda-max-temps (caddr (car newis))))
- (loop (fx+ i incr) ib (cdr newis) is)))
- ((maybe-popfr)
- (receive (is incr)
- (figure-popfr is (lambda-max-temps (caddr (car newis))))
- (loop (fx+ i incr) ib (cdr newis) is)))
- ((risc/sub)
- (destructure (((op #f lit?) (car newis)))
- (cond ((not (fixnum? lit?))
- (set (car (car newis)) risc/add)
- (modify (cdr (caddr (car newis))) -))
- (else
- (set (caar newis) mips/subu)))
- (loop (fx+ i CELL) ib (cdr newis) (cons (car newis) is))))
- (else
- (loop (fx+ i CELL) ib (cdr newis) (cons (car newis) is)))))))))))))
-
-
- (define (preferred-arm? ib1 ib2)
- (let ((node1 (ib-node ib1))
- (node2 (ib-node ib2)))
- (and (node? node1)
- (node? node2)
- (fx< (lambda-trace node1) (lambda-trace node2)))))
-
-
- (define (reverse-branch cc)
- (select cc
- ((jump-op/jabs jump-op/jl) cc)
- (else (- cc))))
-
-
- (define (figure-pushfr is n)
- (cond ((fx= n 0) (return is 0))
- ((fx= n 1)
- (return
- `((,risc/store () l ,LINK-REG (reg-offset ,SP 0))
- (,risc/add () (lit . -4) ,SP ,SP)
- ,@is)
- (fx* CELL 2)))
- (else
- (let ((bump (* (fx+ (fx- n *real-registers*) 2) 4)))
- (return
- `((,risc/store () l ,LINK-REG (reg-offset ,SP ,(fx- bump 4)))
- (,risc/add () (lit . ,(- bump)) ,SP ,SP)
- ,@is)
- (fx* CELL 2))))))
-
- (define (figure-popfr is n)
- (cond ((fx= n 0) (return is 0))
- ((fx= n 1)
- (return
- `((,risc/add () (lit . 4) ,SP ,SP)
- (,mips/load () l (reg-offset ,SP 0) ,LINK-REG)
- ,@is)
- (fx* CELL 2)))
- (else
- (let ((bump (* (fx+ (fx- n *real-registers*) 2) 4)))
- (return
- `((,risc/add () (lit . ,bump) ,SP ,SP)
- (,mips/load () l (reg-offset ,SP ,(fx- bump 4)) ,LINK-REG)
- ,@is)
- (fx* CELL 2))))))
-
- (define (add-jump-no-return next i is)
- (receive (i is) (add-jump next i is (cons jump-op/jabs 0))
- (linearize-code-blocks i is)))
-
- (define (add-jump next i is cc)
- (let ((insts (ib-instructions next)))
- (cond ((or (null? insts)
- (fxn= (car cc) jump-op/jabs)
- (branch-instruction? (car insts)))
- (return (fx+ i (fx* CELL 2))
- (cons noop-inst
- (cons (list jbr-inst nil cc (cons 'label next))
- is))))
- (else
- (return (fx+ i (fx* CELL 2))
- (cons (car insts)
- (cons (list jbr-inst nil cc (cons 'label+1 next))
- is)))))))
-
-
- (define (branch-instruction? x)
- (or (eq? (car x) mips/jalr)
- (eq? (car x) mips/jr)
- (eq? (car x) jbr-inst)
- (eq? (car x) maybe-popfr)
- (eq? (car x) maybe-pushfr)))
-
-
- (define (need-to-delay? load rest)
- (if (null? rest)
- '#t
- (let ((write (apply write-register mips/load (cddr load))));flush comment
- (destructure (((op #f . args) (car rest)))
- (select op
- ((maybe-pushfr maybe-popfr)
- (fx= (lambda-max-temps (car args)) 0))
- (else
- (receive (r1 r2) (apply read-registers op args)
- (or (fx= write r1) (fx= write r2)))))))))
-
-