(setq sectioncddrid "@(#)cddr.l 5.4 11/11/80") ; id for SCCS
; cc-not :: compile a "not" or "null" expression = cc-not =
(makecomment '(beginning not))
then (let ((g-cc (cons (cdr g-cc) (car g-cc)))
else (let ((finlab (d-genlab))
; eval arg and jump to finlab if nil
(let ((g-cc (cons finlab nil))
; didn't jump, answer must be t
(If (car g-cc) then (e-goto (car g-cc))
(If (cdr g-cc) then (e-goto (cdr g-cc)))
;--- cc-numberp :: check for numberness = cc-numberp =
(d-typecmplx (cadr v-form)
'#.(concat '$ (plus 1_2 1_4 1_9))))
;--- cc-or :: compile an "or" expression = cc-or =
(let ((finlab (d-genlab))
(exps (If (cdr v-form) thenret else '(nil)))) ; (or) => nil
then (d-exp (do ((g-cc (cons finlab nil))
(g-loc (If g-loc then 'reg))
((null (cdr ll)) (car ll))
(If g-loc then (setq finlab2 (d-genlab))
else (If (null g-loc) then (setq finlab (car g-cc)))
(d-exp (do ((g-cc (cons finlab nil))
(g-loc (If g-loc then 'reg))
((null (cdr ll)) (car ll))
(If g-loc then (setq finlab2 (d-genlab))
(e-goto (car g-cc)) ; result is t
(d-clearreg))) ; we are not sure of the state due to possible branches.
;--- c-prog :: compile a "prog" expression = c-prog =
; for interlisp compatibility, we allow the formal variable list to
; contain objects of this form (vrbl init) which gives the initial value
; for that variable (instead of nil)
(let (g-loc g-cc seeninit initf ((spcs locs initsv . initsn)
(d-classify (cadr v-form)))
(p-rettrue g-ret) (g-ret nil))
(e-pushnil (length locs)) ; locals initially nil
(d-bindprg spcs locs) ; bind locs and specs
(cond (initsv (d-pushargs initsv)
(d-move 'unstack (d-loc x))
; determine all possible labels
(do ((ll (cddr v-form) (cdr ll))
((null ll) (setq g-labs `((,(d-genlab) ,@labs)
(If (and (car ll) (symbolp (car ll)))
then (If (assq (car ll) labs)
then (comp-err "label is mulitiply defined " (car ll))
else (setq labs (cons (cons (car ll) (d-genlab))
; compile each form which is not a label
(d-clearreg) ; unknown state after binding
(do ((ll (cddr v-form) (cdr ll)))
(If (or (null (car ll)) (not (symbolp (car ll))))
else (e-label (cdr (assq (car ll) (cdar g-labs))))
(d-clearreg)))) ; dont know state after label
; result is nil if fall out and care about value
(If (or g-cc g-loc) then (d-move 'Nil 'reg))
(e-label (caar g-labs)) ; return to label
(setq g-labs (cdr g-labs))
(d-unbind)) ; unbind our frame
;--- d-bindprg :: do binding for a prog expression
; - spcs : list of special variables
; - locs : list of local variables
; - specinit : init values for specs (or nil if all are nil)
(defun d-bindprg (spcs locs)
; place the local vrbls and prog frame entry on the stack
(setq g-loccnt (+ g-loccnt (length locs))
g-locs (nconc locs `((prog . ,(length spcs)) ,@g-locs)))
; now bind the specials, if any, to nil
(If spcs then (e-setupbind)
(e-shallowbind vrb 'Nil))
;--- d-unbind :: remove one frame from g-locs
(do ((count 0 (1+ count)))
(If (not (zerop (cdar g-locs)))
then (e-unshallowbind (cdar g-locs)))
(cond ((not (zerop count))
(setq g-loccnt (- g-loccnt count))))
(setq g-locs (cdr g-locs)))
(setq g-locs (cdr g-locs))))
;--- d-classify :: seperate variable list into special and non-special
; - lst : list of variables
; returns ( xxx yyy zzz . aaa)
; where xxx is the list of special variables and
; yyy is the list of local variables
; zzz are the non nil initial values for prog variables
; aaa are the names corresponding to the values in zzz
(locs) (spcs) (init) (initsv) (initsn)
((null ll) (cons spcs (cons locs (cons initsv initsn))))
(If (atom (car ll)) then (setq name (car ll))
else (setq name (caar ll))
(Push initsv (cadar ll)))
; cm-progn :: compile a "progn" expression = cm-progn =
`((lambda nil ,@(cdr v-form))))
; cm-prog1 :: compile a "prog1" expression = cm-prog1 =
; cm-prog2 :: compile a "prog2" expression = cm-prog2 =
`((lambda (,gl) ,(cadr v-form)
(setq ,gl ,(caddr v-form))
;--- cc-quote : compile a "quote" expression = cc-quote =
; if we are just looking to set the ; cc, we just make sure
; we set the cc depending on whether the expression quoted is
(let ((arg (cadr v-form))
then (If (and (null arg) (cdr g-cc)
elseif (and arg (car g-cc))
then (e-goto (car g-cc)))
then (comp-warn "losing the value of this expression " (or v-form)))
else (d-move (d-loclit arg nil) g-loc)
;--- d-loc :: return the location of the variable or value in IADR form
; - form : form whose value we are to locate
; if we are given a xxx as form, we check yyy;
; nil Nil is always returned
; symbol return the location of the symbols value, first looking
; in the registers, then on the stack, then the bind list.
; If g-ingorereg is t then we don't check the registers.
; We would want to do this if we were interested in storing
; something in the symbol's value location.
; number always return the location of the number on the bind
; other always return the location of the other on the bind
(If (null form) then 'Nil
elseif (numberp form) then
(If (and (fixp form) (greaterp form -1025) (lessp form 1024))
then `(fixnum ,form) ; small fixnum
else (d-loclit form nil))
then (If (and (null g-ignorereg) (car (d-bestreg form nil))) thenret
else (If (d-specialp form) then (d-loclit form t)
(do ((ll g-locs (cdr ll)) ; check stack
(comp-warn (or form) " declared special by compiler")
then (If (eq form (car ll))
then (return `(stack ,n))
else (setq n (1- n)))))))
else (d-loclit form nil)))
;--- d-loclit :: locate or add litteral to bind list
; - form : form to check for and add if not present
; - flag : if t then if we are given a symbol, return the location of
; its value, else return the location of the symbol itself
; scheme: we share the locations of atom (symbols,numbers,string) but always
; create a fresh copy of anything else.
(defun d-loclit (form flag)
(prog (loc onplist symboltype)
(cond ((setq loc (get form g-bindloc))
then (do ((ll g-lits (cdr ll)) ; search for atom on list
then (setq loc n) ; found it
(setq g-litcnt (1+ g-litcnt)
(cond ((and symboltype (null onplist))
(putprop form loc g-bindloc))))
(return (If (and flag symboltype) then `(bind ,loc)
;--- d-locv :: find the location of a value cell, and dont return a register
;--- c-setarg :: set a lexpr's arg = cc-setarg =
; form is (setarg index value)
(If (not (eq 'lexpr g-ftype))
then (comp-err "setarg only allowed in lexprs"))
(If (and fl-inter (eq (length (cdr v-form)) 3)) ; interlisp setarg
then (If (not (eq (cadr v-form) (car g-args)))
then (comp-err "setarg: can only compile local setargs " v-form)
else (setq v-form (cdr v-form))))
(d-pushargs (list (cadr v-form))) ; stack index
(d-clearreg 'r1) ; indicate we are clobbering r1
(e-write3 'movl `(* -4 #.Np-reg) 'r1) ; actual number to r1
(e-write3 'movl 'r0 "*-4(fp)[r1]") ; store value in
;--- cc-stringp :: check for string ness = cc-stringp =
(d-typesimp (cadr v-form) '$0))
;--- cc-symbolp :: check for symbolness = cc-symbolp =
(d-typesimp (cadr v-form) '$1))
;--- c-return :: compile a "return" statement = c-return =
; value is always put in r0
; if we are doing a non local return, compute number of specials to unbind
(If (car g-labs) then (e-goto (caar g-labs))
((null ll) (comp-err "return used not within a prog or do"))
(If (car ll) then (comp-warn " non local return used ")
; unbind down to but not including
then (e-unshallowbind speccnt))
else ; determine number of locals and special on
; stack for this frame, add to running
(setq speccnt (+ speccnt (cdar locs))
(setq locs (cdr locs)))))))
; c-rplaca :: compile a "rplaca" expression = c-rplaca =
(let ((ssimp (d-simple (caddr v-form)))
(let ((g-loc (If ssimp then 'reg else 'stack))
(If (null ssimp) then (Push g-locs nil)
else (e-move (e-cvt ssimp) '(4 r0)))
(d-clearreg))) ; cant tell what we are clobbering
; c-rplacd :: compile a "rplacd" expression = c-rplacd =
(let ((ssimp (d-simple (caddr v-form)))
(let ((g-loc (If ssimp then 'reg else 'stack))
(If (null ssimp) then (Push g-locs nil)
else (e-move (e-cvt ssimp) '(0 r0)))
; c-set :: compile a "set" expression = c-set =
;--- cc-setq :: compile a "setq" expression = c-setq =
(If (oddp (length (cdr v-form)))
then (comp-err "wrong number of args to setq "
elseif (cdddr v-form) ; if multiple setq's
then (do ((ll (cdr v-form) (cddr ll))
((null (cddr ll)) (setq tmp ll))
(setq g-loc (d-locv (car ll)))
else (setq tmp (cdr v-form)))
(let ((g-loc (d-locv (car tmp)))
(g-cc (If g-loc then nil else g-cc))
(If g-loc then (d-move (d-locv (car tmp)) g-loc)
(If g-cc then (d-handlecc)))))
; cc-typep :: compile a "typep" expression = cc-typep =
; this returns the type of the expression, it is always non nil
(let ((argloc (d-simple (cadr v-form)))
(If (null argloc) then (let ((g-loc 'reg) g-cc)
(If g-loc then (e-write4 'ashl '$-9 (e-cvt argloc) 'r0)
(e-write3 'cvtbl "_typetable+1[r0]" 'r0)
(e-write3 'movl "_tynames+4[r0]" 'r0)
(e-write3 'movl "(r0)" (e-cvt g-loc)))
(If (car g-cc) then (e-goto (car g-cc)))))
; cm-symeval :: compile a symeval expression.
; the symbol cell in franz lisp is just the cdr.
; c-*throw :: compile a "*throw" expression =c-*throw =
; the form of *throw is (*throw 'tag 'val) .
; we calculate and stack the value of tag, then calculate val
; we call Idothrow to do the actual work, and only return if the
(let ((arg2loc (d-simple (caddr v-form)))
(If arg2loc then (If (setq arg1loc (d-simple (cadr v-form)))
then (e-write2 'pushl (e-cvt arg2loc))
(e-write2 'pushl (e-cvt arg1loc))
(d-exp (cadr v-form)) ; calc tag
(e-write2 'pushl (e-cvt arg2loc))
(e-write2 'pushl (e-cvt 'reg))))
else (let ((g-loc 'stack))
(d-exp (cadr v-form)) ; calc tag to stack
(d-exp (caddr v-form)) ; calc value into r0
(e-write2 'pushl (e-cvt 'reg))
(e-write2 'pushl (e-cvt 'unstack))
(e-write3 'calls '$0 '_Idothrow)
(e-write2 'clrl '"-(sp)") ; non contuable error
(e-write2 'pushab '__erthrow) ; string to print
(e-write3 'calls '$2 '_error)))
;--- cm-zerop :: convert zerop to a quick test = cm-zerop =
; zerop is only allowed on fixnum and flonum arguments. In both cases,
; if the value of the first 32 bits is zero, then we have a zero.
; thus we can define it as a macro:
(cond ((atom (cadr v-form))
`(and (null (cdr ,(cadr v-form))) (not (bigp ,(cadr v-form)))))
(t (let ((gnsy (gensym)))
;------- FIXNUM arithmetic section ---------
; beware all ye who read this section
(declare (localf d-upordown d-fixop))
;--- c-1+ :: fixnum add1 function
;--- c-1- :: fixnum sub1 function
(defun d-upordown (opcode)
(let ((arg (cadr v-form))
(If (setq argloc (d-simple `(cdr ,arg)))
then (e-write4 opcode '$1 (e-cvt argloc) 'r5)
(e-write4 opcode '$1 "(r0)" 'r5))
(e-write2 "jsb" "_qnewint")
;--- c-+ :: fixnum add = c-+ =
(d-fixop 'subl3 'difference))
(d-fixop 'divl3 'quotient))
(d-fixop 'ediv 'remainder))
(defun d-fixop (opcode lispopcode)
(prog (op1 op2 rop1 rop2 simpleop1)
(If (not (eq 3 (length v-form))) ; only handle two ops for now
then (d-callbig lispopcode (cdr v-form))
else (setq op1 (cadr v-form)
then (setq rop1 (concat '$ op1) ; simple int
else (If (setq rop1 (d-simple `(cdr ,op1)))
then (setq rop1 (e-cvt rop1))
else (let ((g-loc 'reg) g-cc g-ret)
then (setq rop2 (concat '$ op2))
else (If (setq rop2 (d-simple `(cdr ,op2)))
then (setq rop2 (e-cvt rop2))
else (e-write3 'movl rop1 "-(sp)")
then (If (not simpleop1) then (e-write3 'movl rop1 'r2) ; need quad
(e-write4 'ashq '$-32 'r1 'r1)
(setq rop1 'r1)) ; word div.
(e-write5 'ediv rop2 rop1 'r0 'r5)
else (e-write4 opcode rop2 rop1 'r5))
(e-write2 'jsb "_qnewint")
;---- d routines (general ones, others are near function using them)
;--- 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
(defun d-macroexpand (form)
(eq 'macro (d-functyp (car form))))
then (setq form (apply (car form) form))
;--- d-makespec :: declare a variable to be special
;--- 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-simple :: see of arg can be addresses in one instruction
; we define simple and really simple as follows
(If (d-rsimple arg) thenret
elseif (symbolp arg) then (d-loc arg)
elseif (and (memq (car arg) '(cdr car cddr cdar))
(setq tmp (d-rsimple (cadr arg))))
then (If (eq 'Nil tmp) then tmp
then (If (eq 'car (car arg)) then `(racc 4 ,tmp)
elseif (eq 'cdr (car arg)) then `(racc 0 ,tmp)
elseif (eq 'cddr (car arg)) then `(racc * 0 ,tmp)
elseif (eq 'cdar (car arg)) then `(racc * 4 ,tmp))
elseif (not (eq 'cdr (car arg))) then nil
elseif (eq 'lbind (car tmp)) then `(bind ,(cadr tmp))
elseif (eq 'stack (car tmp)) then `(vstack ,(cadr tmp))
elseif (eq 'fixnum (car tmp)) then `(immed ,(cadr tmp))
elseif (atom (car tmp)) then `(0 ,(cadr tmp))
else (comp-err "bad arg to d-simple: " (or arg))))))
elseif (eq t arg) then 'T
else (car (d-bestreg arg nil)))
elseif (eq 'quote (car arg)) then (d-loclit (cadr arg) nil)))
;--- 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-specialp :: check if a variable is special
; a varible is special if it has been declared as such, or if
; the variable special is t
(or special (get vrb g-spec)))
;--- 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))
(If (eq 'reg arg) then 'r0
elseif (eq 'Nil arg) then '$0
elseif (eq 'T arg) then (If g-trueloc thenret
else (setq g-trueloc (e-cvt (d-loclit t nil))))
elseif (eq 'stack arg) then '(+ #.Np-reg)
elseif (eq 'unstack arg) then '(- #.Np-reg)
elseif (atom arg) then arg
elseif (dtpr arg) then (If (eq 'stack (car arg))
then `(,(* 4 (1- (cadr arg))) #.oLbot-reg)
elseif (eq 'vstack (car arg))
then `(* ,(* 4 (1- (cadr arg))) #.oLbot-reg)
elseif (eq 'bind (car arg))
then `(* ,(* 4 (1- (cadr arg))) #.bind-reg)
elseif (eq 'lbind (car arg))
then `( ,(* 4 (1- (cadr arg))) #.bind-reg)
elseif (eq 'fixnum (car arg))
elseif (eq 'immed (car arg))
elseif (eq 'racc (car arg))
else (comp-err " bad arg to e-cvt : "
else (comp-warn "bad arg to e-cvt : " (or arg))))
;--- e-uncvt :: inverse of e-cvt, used for making comments pretty
(If (atom arg) then (If (eq 'Nil arg) then nil
elseif (eq 'stack (car arg))
((and (equal i (cadr arg)) (atom (car ll))) (car ll))
(If (atom (car ll)) then (setq ll (cdr ll)
else (setq ll (cdr ll))))
elseif (or (eq 'bind (car arg)) (eq 'lbind (car arg)))
then (do ((i g-litcnt (1- i))
((equal i (cadr arg)) (cond ((eq 'lbind (car arg))
;--- e-cvtas :: convert an EIADR to vax unix assembler fmt and print it
else (If (eq '* (car form)) then (If (eq '\# (cadr form))
then (setq form `($ ,(caddr form)))
then (sfilewrite (car form))
(sfilewrite (caddr form))
elseif (eq '+ (car form))
elseif (eq '- (car form))
elseif (eq '\# (car form)) ; 5120 is base of small fixnums
then (sfilewrite (concat "$" (+ (* (cadr form) 4) 5120)))
elseif (eq '$ (car form))
(sfilewrite (cadr form)))))
;--- e-cmp :: emit code to compare the two given args
(e-write3 'cmpl arg1 arg2))
;--- e-docomment :: print any comment lines
then (do ((ll (nreverse g-comments) (cdr ll)))
;--- e-goto :: emit code to jump to the location given
;--- e-gotonil :: emit code to jump if nil was last computed
;--- e-gotot :: emit code to jump if t was last computed
;--- e-label :: emit a label
;--- e-move :: move value from one place to anther
; this corresponds to d-move except the args are EIADRS
(If (equal 0 from) then (e-write2 'clrl to)
else (e-write3 'movl from to)))
;--- e-pop :: pop the given number of args from the stack
;--- e-pushnil :: push a given number of nils on the stack
(If (greaterp i 1) then (e-write2 'clrq np-plus)
elseif (equal i 1) then (e-write2 'clrl np-plus)
;--- e-tst :: test a value, arg is an EIADR
;--- e-setupbind :: setup for shallow binding
(e-write3 'movl '#.Bnp-val '#.bNp-reg))
;--- e-unsetupbind :: restore temp value of bnp to real loc
(e-write3 'movl '#.bNp-reg '#.Bnp-val))
;--- e-shallowbind :: shallow bind value of variable and initialize it
; - val : IADR value for variable
(defun e-shallowbind (name val)
(let ((vloc (d-loclit name t)))
(e-write3 'movl (e-cvt vloc) '(+ #.bNp-reg)) ; store old val
(e-write3 'movl (e-cvt `(lbind ,@(cdr vloc)))
'(+ #.bNp-reg)) ; now name
;--- e-unshallowbind :: un shallow bind n variable from top of stack
(defun e-unshallowbind (n)
(e-setupbind) ; set up binding register
(e-write3 'movl `(,(* -8 i) ,bNp-reg) `(* ,(+ 4 (* -8 i)) ,bNp-reg)))
(e-write4 'subl3 `($ ,(* 8 n)) bNp-reg Bnp-val))
;----------- very low level routines
; all output to the assembler file goes through these routines.
; They filter out obviously extraneous instructions as well as
; combine sequential drops of np.
;--- e-dropnp :: unstack n values from np.
; rather than output the instruction now, we just remember that it
; must be done before any other instructions are done. This will
; enable us to catch sequential e-dropnp's
then (setq g-dropnpcnt (+ n (If g-dropnpcnt thenret else 0)))))
;--- em-checknpdrop :: check if we have a pending npdrop
(defmacro em-checknpdrop nil
`(If g-dropnpcnt then (let ((dr g-dropnpcnt))
(e-write3 'subl2 `($ ,(* dr 4)) Np-reg))))
;--- em-checkskip :: check if we are skipping this code due to jump
(defmacro em-checkskip nil
'(If g-skipcode then (sfilewrite "# ")))
;--- e-jump :: jump to given label
; and set g-skipcode so that all code following until the next label
;--- e-return :: do return, and dont check for np drop
(setq g-dropnpcnt nil) ; we dont need to worry about nps
;--- e-writel :: write out a label
;--- e-write1 :: write out one litteral
;--- e-write2 :: write one one litteral, and one operand
(defun e-write2 (lit frm)
;--- e-write3 :: write one one litteral, and two operands
(defun e-write3 (lit frm1 frm2)
;--- e-write4 :: write one one litteral, and three operands
(defun e-write4 (lit frm1 frm2 frm3)
;--- e-write5 :: write one one litteral, and four operands
(defun e-write5 (lit frm1 frm2 frm3 frm4)