(include-if (null (get 'chead 'version)) "../chead.l")
"$Header: io.l,v 1.17 87/12/15 17:03:20 sklower Exp $")
;;; ---- i o input output
;;; -[Fri Sep 2 21:37:05 1983 by layer]-
;--- d-prelude :: emit code common to beginning of all functions
(let ((loada-op #+(or for-vax for-tahoe) 'movab #+for-68k 'lea)
(sub2-op #+(or for-vax for-tahoe) 'subl2 #+for-68k 'subl)
(add2-op #+(or for-vax for-tahoe) 'addl2 #+for-68k 'addl)
(temp-reg #+(or for-vax for-tahoe) '#.fixnum-reg #+for-68k 'a5))
#+for-68k (setq g-stackspace (d-genlab) g-masklab (d-genlab))
then #+for-tahoe (e-write2 '".word" '0x0)
`(,(* -4 g-currentargs) #.np-reg) '#.olbot-reg)
else #+(or for-vax for-tahoe) (e-write2 '".word" '0x5c0)
(e-write3 'link 'a6 (concat "#-" g-stackspace))
(e-write2 'tstb '(-132 sp))
(e-write3 'moveml `($ ,g-masklab)
(concat "a6@(-" g-stackspace ")"))
(e-move '#.Nilatom '#.nil-reg))
then (e-write3 loada-op 'mcnts
#+(or for-vax for-tahoe) 'r0 #+for-68k 'a0)
(e-write3 loada-op 'linker '#.bind-reg)
then ; Here is the method:
; We push the number of arguments, nargs,
; on the name stack twice, setting olbot-reg
; to point to the second one, so that the user
; has a copy that he can set, and we have
; one that we can use for address calcs.
; So, the stack will look like this, after
then (e-move '#.np-sym '#.np-reg))
(e-move '#.np-reg temp-reg)
else '#.lbot-sym) temp-reg)
(e-write3 add2-op (e-cvt '(fixnum 0)) temp-reg)
(e-move '#.np-reg '#.olbot-reg)
else ; Set up old lbot register, base reg for variable
; references, and make sure the np points where
; it should since the caller might
; have given too few or too many args.
`(,(* 4 g-currentargs) #.olbot-reg)
;--- d-fini :: emit code at end of function
then (C-pop '#.olbot-reg)
(e-write1 #+for-vax 'rsb #+for-tahoe 'ret #+for-68k 'rts)
(e-write3 'moveml (concat "a6@(-" g-stackspace ")")
;--- d-bindtab :: emit binder table when all functions compiled
(setq g-skipcode nil) ; make sure this isnt ignored
(e-write2 ".set linker_size," (length g-lits))
(e-write2 ".set trans_size," (length g-tran)))
(e-write2 "linker_size = " (length g-lits))
(e-write2 "trans_size = " (length g-tran)))
(do ((ll (setq g-funcs (nreverse g-funcs)) (cdr ll)))
(if (memq (caar ll) '(lambda nlambda macro eval))
'((lambda . 0) (nlambda . 1)
(macro . 2) (eval . 99)))))
else (comp-err " bad type in lit list " (car ll))))
(d-asciiout (nreverse g-lits))
(if g-tran then (d-asciiout (nreverse g-tran)))
(d-asciiout (mapcar '(lambda (x) (if (eq (car x) 'eval)
;--- d-asciiout :: print a list of asciz strings
(do ((lits args (cdr lits))
(setq form (explode (car lits))
(if (greaterp remsiz 60) then (sfilewrite '".ascii \"")
else (sfilewrite '".asciz \""))
(setq thissiz (min 60 remsiz))
(do ((count thissiz (1- count)))
(sfilewrite (concat '\" (ascii 10)))
(setq remsiz (difference remsiz thissiz)))
(if (eq '#.ch-newline (car curform))
else (if (or (eq '\\ (car curform))
(sfilewrite (car curform)))
(setq curform (cdr curform))))))
; Here is the C program to generate the assembly language:
; (after some cleaning up)
; *--argv = "/usr/ucb/lisp";
; execve("/usr/ucb/lisp",argv,arge);
(defun d-printautorun nil
(let ((readtable (makereadtable t)) ; in raw readtable
(setsyntax #/; 'vsplicing-macro 'zapline)
(setq ar-file (concat lisp-library-directory
#+for-tahoe "/autorun/tahoe"
#+for-68k "/autorun/68k"))
(if (null (errset (setq tport (infile ar-file))))
then (comp-err "Can't open autorun header file " ar-file))
(do ((x (read tport '<eof>) (read tport '<eof>)))
((eq '<eof> x) (close tport))
(if (eq 'reg arg) then #+(or for-vax for-tahoe) 'r0 #+for-68k 'd0
elseif (eq 'areg arg) then #+(or for-vax for-tahoe) 'r0 #+for-68k 'a0
elseif (eq 'Nil arg) then #+(or for-vax for-tahoe) '($ 0)
else (setq g-trueloc (e-cvt (d-loclit t nil))))
elseif (eq 'stack arg) then '(+ #.np-reg)
elseif (eq 'unstack arg) then (progn #+for-tahoe (e-sub '($ 4) '#.np-reg)
elseif (or (atom arg) (symbolp arg)) then arg
(stack `(,(* 4 (1- (cadr arg))) #.olbot-reg))
(vstack `(* ,(* 4 (1- (cadr arg))) #.olbot-reg))
(bind `(* ,(* 4 (1- (cadr arg))) #.bind-reg))
(lbind `(,(* 4 (1- (cadr arg))) #.bind-reg))
(fixnum `(\# ,(cadr arg)))
(t (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
elseif (eq 'stack (car arg))
((and (equal i (cadr arg)) (atom (car ll))) (car ll))
else (setq ll (cdr ll))))
elseif (or (eq 'bind (car arg)) (eq 'lbind (car arg)))
then (do ((i g-litcnt (1- i))
(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))
#-for-tahoe (sfilewrite '"+")
elseif (eq '- (car form))
then #-for-tahoe (sfilewrite '"-")
elseif (eq '\# (car form)) ; 5120 is base of small fixnums
then (sfilewrite (concat "$" (+ (* (cadr form) 4) 5120)))
elseif (eq '$ (car form))
(sfilewrite (cadr form)))))
else (if (eq '* (car form))
then (if (eq '\# (cadr form))
then (setq form `($ ,(caddr form)))))
then (sfilewrite (cadr form))
(if (not (zerop (car form)))
elseif (eq '% (car form))
then (setq form (cdr form))
(sfilewrite (caddr form))
elseif (eq '+ (car form))
then (sfilewrite (cadr form))
elseif (eq '- (car form))
then (sfilewrite (cadr form))
elseif (eq '\# (car form))
then (sfilewrite (concat '#.Nilatom "+0x1400"
(if (null (signp l (cadr form)))
elseif (eq '$ (car form))
else (comp-err " bad arg to e-cvtas : " (or form)))))
;--- e-postinc :: handle postincrement for the tahoe machine
(if (and (dtpr addr) (eq (car addr) '+))
(e-add '($ 4) (cadr addr))))
;--- e-docomment :: print any comment lines
then (do ((ll (nreverse g-comments) (cdr ll)))
(sfilewrite #.comment-char)
(do ((ll (exploden (car ll)) (cdr ll)))
(cond ((eq #\newline (car ll))
(sfilewrite #.comment-char))))
;--- e-goto :: emit code to jump to the location given
;--- e-gotonil :: emit code to jump if nil was last computed
(e-write2 g-falseop lbl))
;--- e-gotot :: emit code to jump if t was last computed
;--- e-label :: emit a label
;--- e-pop :: pop the given number of args from the stack
;--- e-pushnil :: push a given number of nils on the stack
then (e-write2 'clrq '#.np-plus)
then (e-write2 'clrl '#.np-plus)
(e-write2 'clrl '#.np-plus)
;--- e-setupbind :: setup for shallow binding
(e-move '#.bnp-sym '#.bnp-reg))
;--- e-unsetupbind :: restore temp value of bnp to real loc
(e-move '#.bnp-reg '#.bnp-sym))
;--- 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-move (e-cvt vloc) '(+ #.bnp-reg)) ; store old val
(e-move (e-cvt `(lbind ,@(cdr vloc)))
'(+ #.bnp-reg)) ; now name
(defun e-shallowbind (name val)
(let ((vloc (d-loclit name t)))
(e-move (e-cvt vloc) '(0 #.bnp-reg)) ; store old val
(e-add '($ 4) '#.bnp-reg)
(e-move (e-cvt `(lbind ,@(cdr vloc)))
'(0 #.bnp-reg)) ; now name
(e-add '($ 4) '#.bnp-reg)
;--- e-unshallowbind :: un shallow bind n variable from top of stack
(defun e-unshallowbind (n)
(e-setupbind) ; set up binding register
(e-move `(,(* -8 i) #.bnp-reg) `(* ,(+ 4 (* -8 i)) #.bnp-reg)))
(e-sub3 `($ ,(* 8 n)) '#.bnp-reg '#.bnp-sym))
(defun e-unshallowbind (n)
(makecomment "e-unshallowbind begin...")
(e-setupbind) ; set up binding register
(e-move `(,(* -8 i) #.bnp-reg) `(* ,(+ 4 (* -8 i)) #.bnp-reg)))
(e-move '#.bnp-reg '#.bnp-sym)
(e-sub `($ ,(* 8 n)) '#.bnp-sym)
(makecomment "...end e-unshallowbind"))
;----------- 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
then (let ((dr g-dropnpcnt))
(e-sub `($ ,(* 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 #.comment-char)))
;--- e-jump :: jump to given label
; and set g-skipcode so that all code following until the next label
(e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra l)
;--- e-return :: do return, and dont check for np drop
(setq g-dropnpcnt nil) ; we dont need to worry about nps
#+(or for-vax for-tahoe) (e-write1 'ret)
#+for-68k (progn (e-write1 'rts)
(concat g-masklab " = " (d-makemask) '#.ch-newline))
(concat g-stackspace " = "
(Cstackspace) '#.ch-newline))))
;--- 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)
#+for-tahoe (e-postinc frm))
(defun e-write2 (lit frm)
(if (and (dtpr frm) (eq (car frm) '*))
then (e-move (cdr frm) 'a5)
;--- e-write3 :: write one one litteral, and two operands
(defun e-write3 (lit frm1 frm2)
#+for-tahoe (e-postinc frm1)
#+for-tahoe (e-postinc frm2))
(defun e-write3 (lit frm1 frm2)
(if (and (dtpr frm1) (eq (car frm1) '*)
(not (and (dtpr frm2) (eq (car frm2) '*))))
then (e-move (cdr frm1) 'a5)
elseif (and (not (and (dtpr frm1) (eq (car frm1) '*)))
(dtpr frm2) (eq (car frm2) '*))
then (e-move (cdr frm2) 'a5)
elseif (and (dtpr frm1) (eq (car frm1) '*)
(dtpr frm2) (eq (car frm2) '*))
;--- e-write4 :: write one one litteral, and three operands
(defun e-write4 (lit frm1 frm2 frm3)
#+for-tahoe (e-postinc frm1)
#+for-tahoe (e-postinc frm2)
#+for-tahoe (e-postinc frm3))
;--- e-write5 :: write one one litteral, and four operands
(defun e-write5 (lit frm1 frm2 frm3 frm4)
#+for-tahoe (e-postinc frm1)
#+for-tahoe (e-postinc frm2)
#+for-tahoe (e-postinc frm3)
#+for-tahoe (e-postinc frm4))
(defun d-printdocstuff nil
(sfilewrite (concat ".data "
" this is just for documentation "))
(sfilewrite (concat ".asciz \"@(#)Compiled by " compiler-name
" on " (status ctime) '\"))
(do ((xx Liszt-file-names (cdr xx)))
(sfilewrite (concat ".asciz \"" (car xx) '\"))