home *** CD-ROM | disk | FTP | other *** search
- (include-if (null (get 'chead 'version)) "../chead.l")
- (Liszt-file funb
- "$Header: funb.l,v 1.13 87/12/15 17:02:17 sklower Exp $")
-
- ;;; ---- f u n b function compilation
- ;;;
- ;;; -[Wed Aug 24 17:14:56 1983 by layer]-
-
- ;--- c-declare :: handle the "declare" form
- ; if a declare is seen inside a function definition, we just
- ; ignore it. We probably should see what it is declareing, as it
- ; might be declaring a special.
- ;
- (defun c-declare nil nil)
-
- ;--- c-do :: compile a "do" expression
- ;
- ; a do has this form:
- ; (do vrbls tst . body)
- ; we note the special case of tst being nil, in which case the loop
- ; is evaluated only once, and thus acts like a let with labels allowed.
- ; The do statement is a cross between a prog and a lambda. It is like
- ; a prog in that labels are allowed. It is like a lambda in that
- ; we stack the values of all init forms then bind to the variables, just
- ; like a lambda expression (that is the initial values of even specials
- ; are stored on the stack, and then copied into the value cell of the
- ; atom during the binding phase. From then on the stack location is
- ; not used).
- ;
- (defun c-do nil
- (let (b-vrbls b-tst b-body chklab bodylab x-repeat x-vrbs x-fst
- g-loc g-cc oldreguse (g-decls g-decls))
- (forcecomment '(beginning do))
- (setq g-loc 'reg chklab (d-genlab) bodylab (d-genlab))
-
- (if (and (cadr v-form) (atom (cadr v-form)))
- then (setq v-form (d-olddo-to-newdo (cdr v-form))))
-
- (push (cons 'do 0) g-locs) ; begin our frame
-
- (setq b-vrbls (cadr v-form)
- b-tst (caddr v-form)
- b-body (cdddr v-form))
-
- (d-scanfordecls b-body)
-
- ; push value of init forms on stack
- (d-pushargs (mapcar '(lambda (x)
- (if (atom x)
- then nil ; no init form => nil
- else (cadr x)))
- b-vrbls))
-
- ; now bind to the variables in the vrbls form
- (d-bindlamb (mapcar '(lambda (x)
- (if (atom x) then x
- else (car x)))
- b-vrbls))
-
- ; search through body for all labels and assign them gensymed labels
- (push (cons (d-genlab)
- (do ((ll b-body (cdr ll))
- (res))
- ((null ll) res)
- (if (and (car ll) (symbolp (car ll)))
- then (Push res
- (cons (car ll) (d-genlab))))))
- g-labs)
-
- ; if the test is non nil, we do the test
- ; another strange thing, a test form of (pred) will not return
- ; the value of pred if it is not nil! it will return nil -- in this
- ; way, it is not like a cond clause
- (d-clearreg)
- (if b-tst then (e-label chklab)
- (let ((g-cc (cons nil bodylab)) g-loc g-ret)
- (d-exp (car b-tst))) ; eval test
- ; if false, do body
- (if (cdr b-tst)
- then (setq oldreguse (copy g-reguse))
- (d-exps (cdr b-tst))
- (setq g-reguse oldreguse)
- else (d-move 'Nil 'reg))
- (e-goto (caar g-labs)) ; leave do
- (e-label bodylab)) ; begin body
-
- ; process body
- (do ((ll b-body (cdr ll))
- (g-cc) (g-loc)(g-ret))
- ((null ll))
- (if (or (null (car ll)) (not (symbolp (car ll))))
- then (d-exp (car ll))
- else (e-label (cdr (assoc (car ll) (cdar g-labs))))
- (d-clearreg)))
-
- (if b-tst
- then ; determine all repeat forms which must be
- ; evaluated, and all the variables affected.
- ; store the results in x-repeat and x-vrbs
- ; if there is just one repeat form, we calculate
- ; its value directly into where it is stored,
- ; if there is more than one, we stack them
- ; and then store them back at once.
- (do ((ll b-vrbls (cdr ll)))
- ((null ll))
- (if (and (dtpr (car ll)) (cddar ll))
- then (Push x-repeat (caddar ll))
- (Push x-vrbs (caar ll))))
- (if x-vrbs
- then (if (null (cdr x-vrbs)) ; if just one repeat
- then (let ((g-loc (d-locv (car x-vrbs)))
- (g-cc nil))
- (d-exp (car x-repeat)))
- else (setq x-fst (car x-repeat))
- (d-pushargs (nreverse
- (cdr x-repeat)))
- (let ((g-loc (d-locv (car x-vrbs)))
- (g-cc)
- (g-ret))
- (d-exp x-fst))
- (do ((ll (cdr x-vrbs) (cdr ll)))
- ((null ll))
- (d-move 'unstack
- (d-locv (car ll)))
- (setq g-locs (cdr g-locs))
- (decr g-loccnt))))
- (e-goto chklab))
-
- (e-label (caar g-labs)) ; end of do label
- (d-clearreg)
- (d-unbind)
- (setq g-labs (cdr g-labs))))
-
- ;--- d-olddo-to-newdo :: map old do to new do
- ;
- ; form of old do is (do var tst . body)
- ; where var is a symbol, not nil
- ;
- (defun d-olddo-to-newdo (v-l)
- `(do ((,(car v-l) ,(cadr v-l) ,(caddr v-l)))
- (,(cadddr v-l))
- ,@(cddddr v-l)))
-
- ;--- cc-dtpr :: check for dtprness
- ;
- (defun cc-dtpr nil
- (d-typesimp (cadr v-form) #.(immed-const 3)))
-
- ;--- cc-eq :: compile an "eq" expression
- ;
- (defun cc-eq nil
- (let ((arg1 (cadr v-form))
- (arg2 (caddr v-form))
- arg1loc
- arg2loc)
- (if (setq arg2loc (d-simple arg2))
- then (if (setq arg1loc (d-simple arg1))
- then ; eq <simple> <simple>
- (d-cmp arg1loc arg2loc)
- else ; eq <nonsimple> <simple>
- (let ((g-loc 'reg) ; put <nonsimple> in reg
- ; must rebind because
- ; cc->& may have modified
- (g-trueop #+(or for-vax for-tahoe) 'jneq
- #+for-68k 'jne)
- (g-falseop #+(or for-vax for-tahoe) 'jeql
- #+for-68k 'jeq)
- g-cc
- g-ret)
- (d-exp arg1))
- (d-cmp 'reg arg2loc))
- else ; since second is nonsimple, must stack first
- ; arg out of harms way
- (let ((g-loc 'stack)
- (g-trueop #+(or for-vax for-tahoe) 'jneq #+for-68k 'jne)
- (g-falseop #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq)
- g-cc
- g-ret)
- (d-exp arg1)
- (push nil g-locs)
- (incr g-loccnt)
- (setq g-loc 'reg) ; second arg to reg
- (d-exp arg2))
- (d-cmp 'unstack 'reg)
- (setq g-locs (cdr g-locs))
- (decr g-loccnt)))
- (d-invert))
-
- ;--- cc-equal :: compile `equal'
- ;
- (defun cc-equal nil
- (let ((lab1 (d-genlab))
- (lab11 (d-genlab))
- lab2)
- (d-pushargs (cdr v-form))
- (e-cmp '(-8 #.np-reg) '(-4 #.np-reg))
- (e-gotonil lab1)
- (d-calltran 'equal '2) ; not eq, try equal.
- (d-clearreg)
- #+(or for-vax for-tahoe) (e-tst (e-cvt 'reg))
- #+for-68k (e-cmpnil (e-cvt 'reg))
- (e-gotot lab11)
- (if g-loc then (d-move 'Nil g-loc))
- (if (cdr g-cc) then (e-goto (cdr g-cc))
- else (e-goto (setq lab2 (d-genlab))))
- (e-writel lab1)
- (e-dropnp 2)
- (e-writel lab11)
- (if g-loc then (d-move 'T g-loc))
- (if (car g-cc) then (e-goto (car g-cc)))
- (if lab2 then (e-writel lab2))
- (setq g-locs (cddr g-locs))
- (setq g-loccnt (- g-loccnt 2))))
-
- ;--- c-errset :: compile an errset expression
- ;
- ; the errset has this form: (errset 'value ['tag])
- ; where tag defaults to t.
- ;
- (defun c-errset nil
- (let ((g-loc 'reg)
- (g-cc nil)
- (g-ret nil)
- (finlab (d-genlab))
- (beglab (d-genlab)))
- (d-exp (if (cddr v-form) then (caddr v-form) else t))
- (d-pushframe #.F_CATCH (d-loclit 'ER%all nil) 'reg)
- (push nil g-labs) ; disallow labels
- ; If retval is non zero then an error has throw us here so we
- ; must recover the value thrown (from _lispretval) and leave
- ; If retval is zero then we shoud calculate the expression
- ; into r0 and put a cons cell around it
- (e-tst '_retval)
- (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab)
- (e-move '_lispretval (e-cvt 'reg))
- (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab)
- (e-label beglab)
- (let ((g-loc 'stack)
- (g-cc nil))
- (d-exp (cadr v-form)))
- (d-move 'Nil 'stack) ; haven't updated g-loc, g-loccnt but it
- ; shouldn't hurt (famous last words)
- (e-quick-call '_qcons)
- (e-label finlab)
- (d-popframe)
- (unpush g-locs) ; remove (catcherrset . 0)
- (unpush g-labs) ; remove nil
- (d-clearreg)))
-
- ;--- cm-fixnum-cxr :: open code a fixnum-cxr expression.
- ;
- ; fixnum-cxr is a compile only hacky function which accesses an element
- ; of a fixnum space and boxes the resulting fixnum. It can be used
- ; for rapid access to user defined structures.
- ;
- (defun cm-fixnum-cxr ()
- `(internal-fixnum-box (cxr ,@(cdr v-form))))
-
- (defun c-internal-fixnum-box ()
- (let ((g-cc nil)
- (g-ret nil)
- (g-loc '#.fixnum-reg))
- #+for-68k (d-regused '#.fixnum-reg)
- (d-exp (cadr v-form))
- (e-call-qnewint)))
-
- ;--- cc-offset-cxr
- ; return a pointer to the address of the object instead of the object.
- ;
- (defun cc-offset-cxr nil
- (d-supercxr nil t))
-
- ;--- cc-fixp :: check for a fixnum or bignum
- ;
- (defun cc-fixp nil
- (d-typecmplx (cadr v-form)
- '#.(immed-const (plus 1_2 1_9))))
-
- ;--- cc-floatp :: check for a flonum
- ;
- (defun cc-floatp nil
- (d-typesimp (cadr v-form) #.(immed-const 4)))
-
- ;--- c-funcall :: compile a funcall
- ;
- ; we open code a funcall the resulting object is a compiled lambda.
- ; We don't open code nlambda and macro funcalls since they are
- ; rarely used and it would waste space to check for them
- (defun c-funcall nil
- (if (null (cdr v-form))
- then (comp-err "funcall requires at least one argument " v-form))
- (let ((g-locs g-locs)
- (g-loccnt g-loccnt)
- (args (length (cdr v-form)))
- (g-loc nil)
- (g-ret nil)
- (g-cc nil))
- (d-pushargs (cdr v-form))
- (rplaca (nthcdr (1- args) g-locs) 'funcallfcn)
-
- (d-exp '(cond ((and (symbolp funcallfcn)
- (getd funcallfcn))
- (setq funcallfcn (getd funcallfcn)))))
-
- (d-exp `(cond ((and (bcdp funcallfcn) (eq 'lambda (getdisc funcallfcn)))
- (Internal-bcdcall ,args t))
- (t (Internal-bcdcall ,args nil))))))
-
- ;--- c-Internal-bcdcall
- ; this is a compiler internal function call. when this occurs, there
- ; are argnum objects stacked, the first of which is a function name
- ; or bcd object. If dobcdcall is t then we want to do a bcdcall of
- ; the first object stacked. If it is not true then we want to
- ; call the interpreter funcall function to handle it.
- ;
- (defun c-Internal-bcdcall nil
- (let ((argnum (cadr v-form))
- (dobcdcall (caddr v-form)))
- (cond (dobcdcall (d-bcdcall argnum))
- (t (d-calltran 'funcall argnum)))))
-
- ;--- cc-function :: compile a function function
- ;
- ; function is an nlambda, which the interpreter treats as 'quote'
- ; If the argument is a lambda expression, then Liszt will generate
- ; a new function and generate code to return the name of
- ; that function. If the argument is a symbol, then 'symbol
- ; is compiled. It would probably be better to return the function
- ; cell of the symbol, but Maclisp returns the symbol and it
- ; would cause compatibility problems.
- ;
- (defun cc-function nil
- (if (or (null (cdr v-form))
- (cddr v-form))
- then (comp-err "Wrong number of arguments to 'function': " v-form))
- (let ((arg (cadr v-form)))
- (if (symbolp arg)
- then (d-exp `',arg)
- elseif (and (dtpr arg)
- (memq (car arg) '(lambda nlambda lexpr)))
- then (let ((newname (concat "in-line-lambda:"
- (setq in-line-lambda-number
- (add1 in-line-lambda-number)))))
- (Push liszt-process-forms
- `(def ,newname ,arg))
- (d-exp `',newname))
- else (comp-err "Illegal argument to 'function': " v-form))))
-
- ;--- c-get :: do a get from the prop list
- ;
- (defun c-get nil
- (if (not (eq 2 (length (cdr v-form))))
- then (comp-err "Wrong number of args to get " v-form))
- (d-pushargs (cdr v-form)) ; there better be 2 args
- (e-quick-call '_qget)
- (d-clearreg)
- (setq g-locs (cddr g-locs))
- (setq g-loccnt (- g-loccnt 2)))
-
- ;--- cm-getaccess :: compile a getaccess instruction
- ;
- (defun cm-getaccess nil `(cdr ,(cadr v-form)))
-
- ;--- cm-getaux :: compile a getaux instruction
- ;
- (defun cm-getaux nil `(car ,(cadr v-form)))
-
- ;--- cm-getd :: compile a getd instruction
- ;
- ; the getd function is open coded to look in the third part of a symbol
- ; cell
- ;
- (defun cm-getd nil `(cxr 2 ,(cadr v-form)))
-
- ;--- cm-getdata :: compile a getdata instruction
- ;
- ; the getdata function is open coded to look in the third part of an
- ; array header.
- (defun cm-getdata nil `(cxr 2 ,(cadr v-form)))
-
- ;--- cm-getdisc :: compile a getdisc expression
- ; getdisc accessed the discipline field of a binary object.
- ;
- (defun cm-getdisc nil `(cxr 1 ,(cadr v-form)))
-
- ;--- c-go :: compile a "go" expression
- ;
- ; we only compile the (go symbol)type expression, we do not
- ; allow symbol to be anything by a non null symbol.
- ;
- (defun c-go nil
- ; find number of frames we have to go down to get to the label
- (do ((labs g-labs (cdr labs))
- (locs g-locs)
- (locals 0)
- (specials 0)
- (catcherrset 0)
- (label))
- ((null labs)
- (comp-err "go label not found for expression: " (or v-form)))
-
- (if (car labs) ; if we have a set of labels to look at...
- then (if (setq label
- (do ((lbs (cdar labs) (cdr lbs)))
- ((null lbs))
- (if (eq (caar lbs) (cadr v-form))
- then (return (cdar lbs)))))
- then (if (not (eq labs g-labs))
- then (comp-note g-fname ": non local go used : "
- (or v-form)))
- ; three stack to pop: namestack, bindstack
- ; and execution stack
- (e-pop locals)
- (if (greaterp specials 0)
- then (e-unshallowbind specials))
- (if (greaterp catcherrset 0)
- then (comp-note g-fname
- ": Go through a catch or errset "
- v-form)
- (do ((i 0 (1+ i)))
- ((=& catcherrset i))
- (d-popframe)))
- (e-goto label)
- (return)))
- ; tally all locals, specials and catcherrsets used in this frame
- (do ()
- ((dtpr (car locs))
- (if (eq 'catcherrset (caar locs))
- then (incr catcherrset)
- elseif (eq 'progv (caar locs))
- then (comp-err "Attempt to 'go' through a progv"))
- (setq specials (+ specials (cdar locs))
- locs (cdr locs)))
- (setq locs (cdr locs))
- (incr locals))))
-
- ;--- cc-ignore :: just ignore this code
- ;
- (defun cc-ignore nil
- nil)
-
- ;--- c-lambexp :: compile a lambda expression
- ;
- (defun c-lambexp nil
- (let ((g-loc (if (or g-loc g-cc) then 'reg))
- (g-cc nil)
- (g-locs (cons (cons 'lambda 0) g-locs))
- (g-labs (cons nil g-labs)))
- (d-pushargs (cdr v-form)) ; then push vals
- (d-lambbody (car v-form))
- (d-clearreg)))
-
- ;--- d-lambbody :: do a lambda body
- ; - body : body of lambda expression, eg (lambda () dld)
- ;
- (defun d-lambbody (body)
- (let ((g-decls g-decls))
- (d-scanfordecls (cddr body)) ; look for declarations
- (d-bindlamb (cadr body)) ; bind locals
- (d-clearreg)
- (d-exp (do ((ll (cddr body) (cdr ll))
- (g-loc)
- (g-cc)
- (g-ret))
- ((null (cdr ll)) (car ll))
- (d-exp (car ll))))
-
- (d-unbind))) ; unbind this frame
-
- ;--- d-bindlamb :: bind variables in lambda list
- ; - vrbs : list of lambda variables, may include nil meaning ignore
- ;
- (defun d-bindlamb (vrbs)
- (let ((res (d-bindlrec (reverse vrbs) g-locs 0 g-loccnt)))
- (if res then (e-setupbind)
- (mapc '(lambda (vrb) (e-shallowbind (car vrb) (cdr vrb)))
- res)
- (e-unsetupbind))))
-
- ;--- d-bindlrec :: recusive routine to bind lambda variables
- ; - vrb : list of variables yet to bind
- ; - locs : current location in g-loc
- ; - specs : number of specials seen so far
- ; - lev : how far up from the bottom of stack we are.
- ; returns: list of elements, one for each special, of this form:
- ; (<specialvrbname> stack <n>)
- ; where specialvrbname is the name of the special variable, and n is
- ; the distance from the top of the stack where its initial value is
- ; located
- ; also: puts the names of the local variables in the g-locs list, as well
- ; as placing the number of special variables in the lambda header.
- ;
- (defun d-bindlrec (vrb locs specs lev)
- (if vrb
- then (let ((spcflg (d-specialp (car vrb)))
- retv)
- (if spcflg then (setq specs (1+ specs)))
-
- (if (cdr vrb) ; if more vrbls to go ...
- then (setq retv (d-bindlrec (cdr vrb)
- (cdr locs)
- specs
- (1- lev)))
- else (rplacd (cadr locs)
- specs)) ; else fix up lambda hdr
-
- (if (not spcflg) then (rplaca locs (car vrb))
- else (Push retv `(,(car vrb) stack ,lev)))
-
- retv)))
-
- ;--- d-scanfordecls
- ; forms - the body of a lambda, prog or do.
- ; we look down the form for 'declare' forms. They should be at the
- ; beginning, but there are macros which may unintentionally put forms
- ; in front of user written forms. Thus we check a little further than
- ; the first form.
- (defun d-scanfordecls (forms)
- ; look for declarations in the first few forms
- (do ((count 3 (1- count)))
- ((= 0 count))
- (cond ((and (dtpr (car forms))
- (eq 'declare (caar forms))
- (apply 'liszt-declare (cdar forms)))))
- (setq forms (cdr forms))))
-
- ;--- c-list :: compile a list expression
- ;
- ; this is compiled as a bunch of conses with a nil pushed on the
- ; top for good measure
- ;
- (defun c-list nil
- (prog (nargs)
- (setq nargs (length (cdr v-form)))
- (makecomment '(list expression))
- (if (zerop nargs)
- then (d-move 'Nil 'reg) ; (list) ==> nil
- (return))
- (d-pushargs (cdr v-form))
- #+(or for-vax for-tahoe) (e-write2 'clrl '#.np-plus) ; stack one nil
- #+for-68k (L-push (e-cvt 'Nil))
-
- ; now do the consing
- (do ((i (max 1 nargs) (1- i)))
- ((zerop i))
- (e-quick-call '_qcons)
- (d-clearreg)
- (if (> i 1) then (L-push (e-cvt 'reg))))
-
- (setq g-locs (nthcdr nargs g-locs)
- g-loccnt (- g-loccnt nargs))))
-
- ;--- d-mapconvert - access : function to access parts of lists
- ; - join : function to join results
- ; - resu : function to apply to result
- ; - form : mapping form
- ; This function converts maps to an equivalent do form.
- ;
- ; in this function, the variable vrbls contains a list of forms, one form
- ; per list we are mapping over. The form of the form is
- ; (dummyvariable realarg (cdr dummyvariable))
- ; realarg may be surrounded by (setq <variable which holds result> realarg)
- ; in the case that the result is the list to be mapped over (this only occurs
- ; with the function mapc).
- ;
- (defun d-mapconvert (access join resu form )
- (prog (vrbls finvar acc accform compform
- tmp testform tempvar lastvar)
-
- (setq finvar (gensym 'X) ; holds result
-
- vrbls
- (reverse
- (maplist '(lambda (arg)
- ((lambda (temp)
- (cond ((or resu (cdr arg))
- `(,temp ,(car arg)
- (cdr ,temp)))
- (t `(,temp
- (setq ,finvar
- ,(car arg))
- (cdr ,temp)))))
- (gensym 'X)))
- (reverse (cdr form))))
-
- ; the access form will either be nil or car. If it is
- ; nil, then we are doing something like a maplist,
- ; if the access form is car, then we are doing something
- ; like a mapcar.
- acc (mapcar '(lambda (tem)
- (cond (access `(,access ,(car tem)))
- (t (car tem))))
- vrbls)
-
- accform (cond ((or (atom (setq tmp (car form)))
- (null (setq tmp (d-macroexpand tmp)))
- (not (member (car tmp) '(quote function))))
- `(funcall ,tmp ,@acc))
- (t `(,(cadr tmp) ,@acc)))
-
- ; the testform checks if any of the lists we are mapping
- ; over is nil, in which case we quit.
- testform (cond ((null (cdr vrbls)) `(null ,(caar vrbls)))
- (t `(or ,@(mapcar '(lambda (x)
- `(null ,(car x)))
- vrbls)))))
-
- ; in the case of mapcans and mapcons, you need two
- ; extra variables to simulate the nconc.
- ; testvar gets intermediate results and lastvar
- ; points to then end of the list
- (if (eq join 'nconc)
- then (setq tempvar (gensym 'X)
- lastvar (gensym 'X)
- vrbls `((,tempvar) (,lastvar) ,@vrbls)))
-
- (return
- `((lambda
- (,finvar)
- (liszt-internal-do
- ( ,@vrbls)
- (,testform)
- ,(cond ((eq join 'nconc)
- `(cond ((setq ,tempvar ,accform)
- (cond (,lastvar
- (liszt-internal-do
- ()
- ((null (cdr ,lastvar)))
- (setq ,lastvar
- (cdr ,lastvar)))
- (rplacd ,lastvar ,tempvar))
- (t (setq ,finvar
- (setq ,lastvar
- ,tempvar)))))))
- (join `(setq ,finvar (,join ,accform ,finvar)))
- (t accform)))
- ,(cond ((eq resu 'identity) finvar)
- (resu `(,resu ,finvar))
- (t finvar)))
- nil ))))
-
- ; apply to successive elements, return second arg
- (defun cm-mapc nil
- (d-mapconvert 'car nil nil (cdr v-form)))
-
- ; apply to successive elements, return list of results
- (defun cm-mapcar nil
- (d-mapconvert 'car 'cons 'nreverse (cdr v-form)))
-
- ; apply to successive elements, returned nconc of results
- (defun cm-mapcan nil
- (d-mapconvert 'car 'nconc 'identity (cdr v-form)))
-
- ; apply to successive sublists, return second arg
- (defun cm-map nil
- (d-mapconvert nil nil nil (cdr v-form)))
-
- ; apply to successive sublists, return list of results
- (defun cm-maplist nil
- (d-mapconvert nil 'cons 'reverse (cdr v-form)))
-
- ; apply to successive sublists, return nconc of results
- (defun cm-mapcon nil
- (d-mapconvert nil 'nconc 'identity (cdr v-form)))
-
- ;--- cc-memq :: compile a memq expression
- ;
- #+(or for-vax for-tahoe)
- (defun cc-memq nil
- (let ((loc1 (d-simple (cadr v-form)))
- (loc2 (d-simple (caddr v-form)))
- looploc finlab)
- (if loc2
- then (d-clearreg 'r1)
- (if loc1
- then (d-move loc1 'r1)
- else (let ((g-loc 'r1)
- g-cc
- g-ret)
- (d-exp (cadr v-form))))
- (d-move loc2 'reg)
- else (let ((g-loc 'stack)
- g-cc
- g-ret)
- (d-exp (cadr v-form)))
- (push nil g-locs)
- (incr g-loccnt)
- (let ((g-loc 'reg)
- g-cc
- g-ret)
- (d-exp (caddr v-form)))
- (L-pop 'r1)
- (d-clearreg 'r1)
- (unpush g-locs)
- (decr g-loccnt))
- ; now set up the jump addresses
- (if (null g-loc)
- then (setq loc1 (if (car g-cc) thenret else (d-genlab))
- loc2 (if (cdr g-cc) thenret else (d-genlab)))
- else (setq loc1 (d-genlab)
- loc2 (d-genlab)))
-
- (setq looploc (d-genlab))
- (e-tst 'r0)
- (e-write2 'jeql loc2)
- (e-label looploc)
- (e-cmp 'r1 '(4 r0))
- (e-write2 'jeql loc1)
- (e-move '(0 r0) 'r0)
- (e-write2 'jneq looploc)
- (if g-loc
- then (e-label loc2) ; nil result
- (d-move 'reg g-loc)
- (if (cdr g-cc)
- then (e-goto (cdr g-cc))
- else (e-goto (setq finlab (d-genlab))))
- else (if (cdr g-cc)
- then (e-goto (cdr g-cc))
- else (e-label loc2)))
- (if g-loc
- then (e-label loc1) ; non nil result
- (d-move 'reg g-loc)
- (if (car g-cc) then (e-goto (car g-cc)))
- else (if (null (car g-cc)) then (e-label loc1)))
- (if finlab then (e-label finlab))))
-
- #+for-68k
- (defun cc-memq nil
- (let ((loc1 (d-simple (cadr v-form)))
- (loc2 (d-simple (caddr v-form)))
- looploc finlab
- (tmp-data-reg (d-alloc-register 'd nil)))
- (d-clearreg tmp-data-reg)
- (d-clearreg 'a0)
- (if loc2
- then (if loc1
- then (d-move loc1 tmp-data-reg)
- else (let ((g-loc tmp-data-reg)
- g-cc
- g-ret)
- (d-exp (cadr v-form))))
- (d-move loc2 'reg)
- else (let ((g-loc 'stack)
- g-cc
- g-ret)
- (d-exp (cadr v-form)))
- (push nil g-locs)
- (incr g-loccnt)
- (let ((g-loc 'reg)
- g-cc
- g-ret)
- (d-exp (caddr v-form)))
- (L-pop tmp-data-reg)
- (unpush g-locs)
- (decr g-loccnt))
- ; now set up the jump addresses
- (if (null g-loc)
- then (setq loc1 (if (car g-cc) thenret else (d-genlab))
- loc2 (if (cdr g-cc) thenret else (d-genlab)))
- else (setq loc1 (d-genlab)
- loc2 (d-genlab)))
- (setq looploc (d-genlab))
- (e-cmpnil 'd0)
- (e-write2 'jeq loc2)
- (e-move 'd0 'a0)
- (e-label looploc)
- (e-cmp tmp-data-reg '(4 a0))
- (e-write2 'jeq loc1)
- (e-move '(0 a0) 'a0)
- (e-cmpnil 'a0)
- (e-write2 'jne looploc)
- (e-move 'a0 'd0)
- (if g-loc
- then (e-label loc2) ; nil result
- (d-move 'reg g-loc)
- (if (cdr g-cc)
- then (e-goto (cdr g-cc))
- else (e-goto (setq finlab (d-genlab))))
- else (if (cdr g-cc)
- then (e-goto (cdr g-cc))
- else (e-label loc2)))
- (if g-loc
- then (e-label loc1) ; non nil result
- (d-move 'a0 g-loc) ;a0 was cdr of non-nil result
- (if (car g-cc) then (e-goto (car g-cc)))
- else (if (null (car g-cc)) then (e-label loc1)))
- (if finlab then (e-label finlab))))
-