(Liszt-file util "@(#)util.l 1.2 10/7/81")
;;; ---- u t i l general utility functions
;--- d-cmp :: compare two IADR values
(e-write3 'cmpl (e-cvt arg1) (e-cvt arg2)))
;--- d-handlecc :: handle g-cc
; at this point the Z condition code has been set up and if g-cc is
; non nil, we must jump on condition to the label given in g-cc
(If (car g-cc) then (e-gotot (car g-cc))
elseif (cdr g-cc) then (e-gotonil (cdr g-cc))))
;--- d-invert :: handle inverted condition codes
; this routine is called if a result has just be computed which alters
; the condition codes such that Z=1 if the result is t, and Z=0 if the
; result is nil (this is the reverse of the usual sense). The purpose
; of this routine is to handle g-cc and g-loc. That is if g-loc is
; specified, we must convert the value of the Z bit of the condition
; code to t or nil and store that in g-loc. After handling g-loc we
; must handle g-cc, that is if the part of g-cc is non nil which matches
; the inverse of the current condition code, we must jump to that.
then (If (car g-cc) then (e-gotonil (car g-cc))
elseif (cdr g-cc) then (e-gotot (cdr g-cc)))
else (let ((lab1 (d-genlab))
(lab2 (If (cdr g-cc) thenret else (d-genlab))))
; Z=1, but remember that this implies nil due to inversion
(If (car g-cc) then (e-goto (car g-cc)))
(If (null (cdr g-cc)) then (e-label lab2)))))
;--- d-noninvert :: handle g-cc and g-loc assuming cc non inverted
; like d-invert except Z=0 implies nil, and Z=1 implies t
then (If (car g-cc) then (e-gotot (car g-cc))
elseif (cdr g-cc) then (e-gotonil (cdr g-cc)))
else (let ((lab1 (d-genlab))
(lab2 (If (cdr g-cc) thenret else (d-genlab))))
(If (car g-cc) then (e-goto (car g-cc)))
(If (null (cdr g-cc)) then (e-label lab2)))))
;--- d-macroexpand :: macro expand a form as much as possible
; only macro expands the top level though.
(defun d-macroexpand (form)
(eq 'macro (d-functyp (car form))))
then (setq form (apply (car form) form))
;--- d-fullmacroexpand :: macro expand down all levels
; this is not always possible to due since it is not always clear
; if a function is a lambda or nlambda, and there are lots of special
; forms. This is just a first shot at such a function, this should
(defun d-fullmacroexpand (form)
else (setq form (d-macroexpand form)) ; do one level
(If (and (dtpr form) (symbolp (car form)))
then (let ((func (getd (car form))))
(eq 'lambda (getdisc func)))
(memq (car func) '(lambda lexpr)))
(memq (car form) '(or and)))
,@(mapcar 'd-fullmacroexpand
elseif (eq (car form) 'setq)
;--- d-setqexpand :: macro expand a setq statemant
; a setq is unusual in that alternate values are macroexpanded.
(defun d-setqexpand (form)
(If (oddp (length (cdr form)))
then (comp-err "wrong number of args to setq " form)
else (do ((xx (reverse (cdr form)) (cddr xx))
((null xx) (cons 'setq res))
,(d-fullmacroexpand (car xx))
;--- d-move :: emit instructions to move value from one place to another
(makecomment `(from ,(e-uncvt from) to ,(e-uncvt to)))
(cond ((eq 'Nil from) (e-write2 'clrl (e-cvt to)))
(t (e-write3 'movl (e-cvt from) (e-cvt to)))))
;--- d-movespec :: move from loc to loc where the first addr given is
(defun d-movespec (from to)
(makecomment `(fromspec ,from to ,(e-uncvt to)))
(e-write3 'movl from (e-cvt to)))
;--- d-tst :: test the given value (set the cc)
(e-write2 'tstl (e-cvt arg)))
;--- d-typesimp :: determine the type of the argument
(defun d-typesimp (arg val)
(let ((argloc (d-simple arg)))
(If (null argloc) then (let ((g-loc 'reg)
(e-write4 'ashl '$-9 (e-cvt argloc) 'r0)
(e-write3 'cmpb '"_typetable+1[r0]" val)
;--- d-typecmplx :: determine if arg has one of many types
; - arg : lcode argument to be evaluated and checked
; - vals : fixnum with a bit in position n if we are to check type n
(defun d-typecmplx (arg vals)
(let ((argloc (d-simple arg))
(If (null argloc) then (let ((g-loc 'reg)
(e-write4 'ashl '$-9 (e-cvt argloc) reg)
(e-write3 'cvtbl (concat "_typetable+1[" reg "]") reg)
(e-write4 'ashl reg '$1 reg)
(e-write3 'bitw vals reg)
;---- register handling routines.
;--- d-allocreg :: allocate a register
; name - the name of the register to allocate or nil if we should
; allocate the least recently used.
then (let ((av (assoc name g-reguse)))
(If av then (rplaca (cdr av) (1+ (cadr av)))) ; inc used count
else ; find smallest used count
(do ((small (car g-reguse))
(lis (cdr g-reguse) (cdr lis)))
(rplaca (cdr small) (1+ smc))
then (setq small (car lis)
;--- d-bestreg :: determine the register which is closest to what we have
; name - name of variable whose subcontents we want
; pat - list of d's and a's which tell which part we want
(defun d-bestreg (name pat)
(do ((ll g-reguse (cdr ll))
((null ll) (If best then (rplaca (cdr best) (1+ (cadr best)))
then (rplacd (nthcdr (1- bestv)
(If (and (setq val (cddar ll))
then (If (> (setq tmp (d-matchcnt pat (cdr val)))
;--- d-matchcnt :: determine how many parts of a pattern match
; want - pattern we want to achieve
; have - pattern whose value exists in a register
; we return a count of the number of parts of the pattern match.
; If this pattern will be any help at all, we return a value from
; 0 to the length of the pattern.
; If this pattern will not work at all, we return a number smaller
; For `have' to be useful for `want', `have' must be a substring of
; `want'. If it is a substring, we return the length of `have'.
(defun d-matchcnt (want have)
(If (do ((hh have (cdr hh))
(If (or (null ww) (not (eq (car ww) (car hh))))
;--- d-clearreg :: clear all values in registers or just one
; if no args are given, clear all registers.
; if an arg is given, clear that register
(mapc '(lambda (x) (rplaca (cdr x) 0)
(t (let ((av (assoc (arg 1) g-reguse)))
(If av then (rplaca (cdr av) 0)
(rplacd (cdr av) nil))))))
;--- d-clearuse :: clear all register which reference a given variable
(defun d-clearuse (varib)
(If (eq (caddr x) varib) then (rplacd (cdr x) nil)))
;--- d-inreg :: declare that a value is in a register
; value - value in a register
(defun d-inreg (name value)
(let ((av (assoc name g-reguse)))
(If av then (rplacd (cdr av) value))