home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / lisp / liszt / funa.l < prev    next >
Encoding:
Text File  |  1987-12-15  |  31.0 KB  |  934 lines

  1. (include-if (null (get 'chead 'version)) "../chead.l")
  2. (Liszt-file funa
  3.    "$Header: funa.l,v 1.12 87/12/15 17:02:01 sklower Exp $")
  4.  
  5. ;;; ----    f u n a                function compilation
  6. ;;;
  7. ;;;                -[Mon Aug 22 22:01:01 1983 by layer]-
  8.  
  9.  
  10. ;--- cc-and :: compile an and expression
  11. ; We evaluate forms from left to right as long as they evaluate to
  12. ; a non nil value.  We only have to worry about storing the value of
  13. ; the last expression in g-loc.
  14. ;
  15. (defun cc-and nil
  16.   (let ((finlab (d-genlab))
  17.     (finlab2)
  18.     (exps (if (cdr v-form) thenret else '(t))))    ; (and) ==> t
  19.        (if (null (cdr g-cc))
  20.        then (d-exp (do ((g-cc (cons nil finlab))
  21.                 (g-loc)
  22.                 (g-ret)
  23.                 (ll exps (cdr ll)))
  24.                ((null (cdr ll)) (car ll))
  25.                (d-exp (car ll))))
  26.         (if g-loc
  27.             then (setq finlab2 (d-genlab))
  28.              (e-goto finlab2)
  29.              (e-label finlab)
  30.              (d-move 'Nil g-loc)
  31.              (e-label finlab2)
  32.             else (e-label finlab))
  33.        else ;--- cdr g-cc is non nil, thus there is
  34.         ; a quick escape possible if one of the
  35.         ; expressions evals to nil
  36.  
  37.         (if (null g-loc) then (setq finlab (cdr g-cc)))
  38.             (d-exp (do ((g-cc (cons nil finlab))
  39.                 (g-loc)
  40.                 (g-ret)
  41.                 (ll exps (cdr ll)))
  42.                ((null (cdr ll)) (car ll))
  43.                (d-exp (car ll))))
  44.         ; if g-loc is non nil, then we have evaled the and
  45.         ; expression to yield nil, which we must store in
  46.         ; g-loc and then jump to where the cdr of g-cc takes us
  47.         (if g-loc
  48.             then (setq finlab2 (d-genlab))
  49.              (e-goto finlab2)
  50.              (e-label finlab)
  51.              (d-move 'Nil g-loc)
  52.              (e-goto (cdr g-cc))
  53.              (e-label finlab2))))
  54.   (d-clearreg))     ; we cannot predict the state of the registers
  55.  
  56. ;--- cc-arg  :: get the nth arg from the current lexpr
  57. ;
  58. ; the syntax for Franz lisp is (arg i)
  59. ; for interlisp the syntax is (arg x i) where x is not evaluated and is
  60. ; the name of the variable bound to the number of args.  We can only handle
  61. ; the case of x being the variable for the current lexpr we are compiling
  62. ;
  63. (defun cc-arg nil
  64.    (prog (nillab finlab)
  65.        (setq nillab (d-genlab)
  66.          finlab (d-genlab))
  67.        (if (not (eq 'lexpr g-ftype)) 
  68.        then (comp-err " arg only allowed in lexprs"))
  69.        (if (and (eq (length (cdr v-form)) 2) fl-inter)
  70.        then (if (not (eq (car g-args) (cadr v-form)))
  71.             then (comp-err " arg expression is for non local lexpr "
  72.                    v-form)
  73.             else (setq v-form (cdr v-form))))
  74.        (if (and (null g-loc) (null g-cc))
  75.        then ;bye bye, wouldn't do anything
  76.         (return nil))
  77.        (if (and (fixp (cadr v-form)) (>& (cadr v-form) 0))
  78.        then ; simple case (arg n) for positive n
  79.         (d-move `(fixnum ,(cadr v-form)) 'reg)
  80.         #+for-68k
  81.         (progn
  82.             (e-sub `(-4 #.olbot-reg) 'd0)
  83.             (if g-loc
  84.             then (e-move '(% -8 #.olbot-reg d0) (e-cvt g-loc)))
  85.             (if g-cc then (e-cmpnil '(% -8 #.olbot-reg d0))))
  86.         #+(or for-vax for-tahoe)
  87.         (progn
  88.             (e-sub3 '(* -4 #.olbot-reg) '(0 r0) 'r0)
  89.             (if g-loc
  90.             then (e-move '(-8 #.olbot-reg r0) (e-cvt g-loc))
  91.              elseif g-cc
  92.             then (e-tst '(-8 #.olbot-reg r0))))
  93.         (d-handlecc)
  94.     elseif (or (null (cadr v-form))
  95.            (and (fixp (cadr v-form)) (=& 0 (cadr v-form))))
  96.        then ;---the form is: (arg nil) or (arg) or (arg 0).
  97.         ;   We have a private copy of the number of args right
  98.         ; above the arguments on the name stack, so that
  99.         ; the user can't clobber it... (0 olbot) points
  100.         ; to the user setable copy, and (-4 olbot) to our
  101.         ; copy.
  102.         (if g-loc then (e-move '(-4 #.olbot-reg) (e-cvt g-loc)))
  103.         ;   Will always return a non nil value, so
  104.         ; don't even test it.
  105.         (if (car g-cc) then (e-goto (car g-cc)))
  106.        else ; general (arg <form>)
  107.         (let ((g-loc 'reg)
  108.               (g-cc (cons nil nillab))
  109.               (g-ret))
  110.             (d-exp (cadr v-form)))  ;boxed fixnum or nil
  111.         ; (arg 0) returns nargs (compiler only!)
  112.         (d-cmp 'reg '(fixnum 0))
  113.         (e-gotonil nillab)
  114.         
  115.         ; ... here we are doing (arg <number>), <number> != 0
  116.         #+for-68k
  117.         (progn
  118.             (e-sub '(-4 #.olbot-reg) 'd0)
  119.             (if g-loc
  120.             then (e-move '(% -8 #.olbot-reg d0) (e-cvt g-loc)))
  121.             (if g-cc then (e-cmpnil '(% -8 #.olbot-reg d0))))
  122.         #+(or for-vax for-tahoe)
  123.         (progn
  124.             (e-sub3 `(* -4 #.olbot-reg) '(0 r0) 'r0)
  125.             (if g-loc
  126.             then (e-move '(-8 #.olbot-reg r0) (e-cvt g-loc))
  127.              elseif g-cc
  128.             then (e-tst '(-8 #.olbot-reg r0))))
  129.         (d-handlecc)
  130.         (e-goto finlab)
  131.         (e-label nillab)
  132.         ; here we are doing (arg nil) which
  133.         ; returns the number of args
  134.         ; which is always true if anyone is testing
  135.         (if g-loc
  136.             then (e-move '(-4 #.olbot-reg) (e-cvt g-loc))
  137.              #+for-68k (if g-cc then (e-cmpnil '(-4 #.olbot-reg)))
  138.              (d-handlecc)
  139.          elseif (car g-cc)
  140.             then (e-goto (car g-cc))) ;always true
  141.         (e-label finlab))))
  142.  
  143. ;--- c-assembler-code
  144. ; the args to assembler-code are a list of assembler language 
  145. ; statements.  This statements are put directly in the code
  146. ; stream produced by the compiler.  Beware: The interpreter cannot
  147. ; interpret the assembler-code function.
  148. ;
  149. (defun c-assembler-code nil
  150.   (setq g-skipcode nil)        ; turn off code skipping
  151.   (makecomment '(assembler code start))
  152.   (do ((xx (cdr v-form) (cdr xx)))
  153.       ((null xx))
  154.       (e-write1 (car xx)))
  155.   (makecomment '(assembler code end)))
  156.  
  157. ;--- cm-assq :: assoc with eq for testing
  158. ;
  159. ; form: (assq val list)
  160. ;
  161. (defun cm-assq nil
  162.   `(do ((xx-val ,(cadr v-form))
  163.     (xx-lis ,(caddr v-form) (cdr xx-lis)))
  164.        ((null xx-lis))
  165.        (cond ((eq xx-val (caar xx-lis)) (return (car xx-lis))))))
  166.  
  167. ;--- cc-atom :: test for atomness
  168. ;
  169. (defun cc-atom nil
  170.   (d-typecmplx (cadr v-form)
  171.            #.(immed-const (plus 1_0 1_1 1_2 1_4 1_5 1_6 1_7 1_9 1_10))))
  172.  
  173. ;--- c-bcdcall :: do a bcd call
  174. ;
  175. ; a bcdcall is the franz equivalent of the maclisp subrcall.
  176. ; it is called with
  177. ; (bcdcall 'b_obj 'arg1 ...)
  178. ;  where b_obj must be a binary object. no type checking is done.
  179. ;
  180. (defun c-bcdcall nil
  181.   (d-callbig 1 (cdr v-form) t))
  182.  
  183. ;--- cc-bcdp :: check for bcdpness
  184. ;
  185. (defun cc-bcdp nil
  186.   (d-typesimp (cadr v-form) #.(immed-const 5)))
  187.  
  188. ;--- cc-bigp :: check for bignumness
  189. ;
  190. (defun cc-bigp nil
  191.   (d-typesimp (cadr v-form) #.(immed-const 9)))
  192.  
  193. ;--- c-boole :: compile
  194. ;
  195. #+(or for-vax for-tahoe)
  196. (progn 'compile
  197. (defun c-boole nil
  198.    (cond ((fixp (cadr v-form))
  199.       (setq v-form (d-boolexlate (d-booleexpand v-form)))))
  200.    (cond ((eq 'boole (car v-form))     ;; avoid recursive calls to d-exp
  201.       (d-callbig 'boole (cdr v-form) nil))
  202.      (t (let ((g-loc 'reg) (g-cc nil) (g-ret nil))  ; eval answer
  203.            (d-exp v-form)))))
  204.  
  205. ;--- d-booleexpand :: make sure boole only has three args
  206. ;  we use the identity (boole k x y z) == (boole k (boole k x y) z)
  207. ; to make sure that there are exactly three args to a call to boole
  208. ;
  209. (defun d-booleexpand (form)
  210.    (if (and (dtpr form) (eq 'boole (car form)))
  211.        then (if (< (length form) 4)
  212.         then (comp-err "Too few args to boole : " form)
  213.          elseif (= (length form) 4)
  214.         then form
  215.         else (d-booleexpand
  216.              `(boole ,(cadr form)
  217.                   (boole ,(cadr form)
  218.                       ,(caddr form)
  219.                       ,(cadddr form))
  220.                   ,@(cddddr form))))
  221.        else form))
  222.  
  223. (declare (special x y))
  224. (defun d-boolexlate (form)
  225.    (if (atom form)
  226.        then form
  227.     elseif (and (eq 'boole (car form))
  228.         (fixp (cadr form)))
  229.        then (let ((key (cadr form))
  230.           (x (d-boolexlate (caddr form)))
  231.           (y (d-boolexlate (cadddr form)))
  232.           (res))
  233.         (makecomment `(boole key = ,key))
  234.         (if (eq key 0)         ;; 0
  235.             then `(progn ,x ,y 0)
  236.          elseif (eq key 1)     ;; x * y
  237.             then #+for-vax `(fixnum-BitAndNot ,x (fixnum-BitXor ,y -1))
  238.                  #+for-tahoe `(fixnum-BitAnd ,x ,y)
  239.          elseif (eq key 2)     ;; !x * y
  240.             then #+for-vax `(fixnum-BitAndNot (fixnum-BitXor ,x -1)
  241.                         (fixnum-BitXor ,y -1))
  242.                  #+for-tahoe `(fixnum-BitAnd (fixnum-BitXor ,x -1) ,y)
  243.          elseif (eq key 3)     ;; y
  244.             then `(progn ,x ,y)
  245.          elseif (eq key 4)    ;; x * !y
  246.             then #+for-vax `(fixnum-BitAndNot ,x ,y)
  247.              #+for-tahoe `(fixnum-BitAnd ,x (fixnum-BitXor ,y -1))
  248.          elseif (eq key 5)     ;; x
  249.             then `(prog1 ,x ,y)
  250.          elseif (eq key 6)        ;; x xor y
  251.             then `(fixnum-BitXor ,x ,y)
  252.          elseif (eq key 7)     ;; x + y
  253.             then `(fixnum-BitOr ,x ,y)
  254.          elseif (eq key 8)    ;; !(x xor y)
  255.             then `(fixnum-BitXor (fixnum-BitOr ,x ,y) -1)
  256.          elseif (eq key 9)     ;; !(x xor y)
  257.             then `(fixnum-BitXor (fixnum-BitXor ,x ,y) -1)
  258.          elseif (eq key 10)     ;; !x
  259.             then `(prog1 (fixnum-BitXor ,x -1) ,y)
  260.          elseif (eq key 11)     ;; !x + y
  261.             then `(fixnum-BitOr (fixnum-BitXor ,x -1) ,y)
  262.          elseif (eq key 12)     ;; !y
  263.             then `(progn ,x (fixnum-BitXor ,y -1))
  264.          elseif (eq key 13)     ;; x + !y
  265.             then `(fixnum-BitOr ,x (fixnum-BitXor ,y -1))
  266.          elseif (eq key 14)     ;; !x + !y
  267.             then `(fixnum-BitOr (fixnum-BitXor ,x -1)
  268.                     (fixnum-BitXor ,y -1))
  269.          elseif (eq key 15)     ;; -1
  270.             then `(progn ,x ,y -1)
  271.             else form))
  272.        else form))
  273.  
  274. (declare (unspecial x y))
  275. ) ;; end for-vax
  276.  
  277.  
  278. ;--- c-*catch :: compile a *catch expression
  279. ;
  280. ; the form of *catch is (*catch 'tag 'val)
  281. ; we evaluate 'tag and set up a catch frame, and then eval 'val
  282. ;
  283. (defun c-*catch nil
  284.    (let ((g-loc 'reg)
  285.      (g-cc nil)
  286.      (g-ret nil)
  287.      (finlab (d-genlab))
  288.      (beglab (d-genlab)))
  289.        (d-exp (cadr v-form))        ; calculate tag into 'reg
  290.        (d-pushframe #.F_CATCH 'reg 'Nil) ; the Nil is a don't care
  291.        (push nil g-labs)        ; disallow labels
  292.        ; retval will be non 0 if we were thrown to, in which case the value
  293.        ; thrown is in _lispretval.
  294.        ; If we weren't thrown-to the value should be calculated in r0.
  295.        (e-tst '_retval)
  296.        (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab)
  297.        (e-move '_lispretval (e-cvt 'reg))
  298.        (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab)
  299.        (e-label beglab)
  300.        (d-exp (caddr v-form))
  301.        (e-label finlab)
  302.        (d-popframe)    ; remove catch frame from stack
  303.        (unpush g-locs)    ; remove (catcherrset . 0)
  304.        (unpush g-labs)  ; allow labels again
  305.        (d-clearreg)))
  306.  
  307. ;--- d-pushframe :: put an evaluation frame on the stack
  308. ;
  309. ; This is equivalant in the C system to 'errp = Pushframe(class,arg1,arg2);'
  310. ; We stack a frame which describes the class (will always be F_CATCH)
  311. ; and the other option args.
  312. ; 2/10/82 - it is a bad idea to stack a variable number of arguments, since
  313. ; this makes it more complicated to unstack frames.  Thus we will always
  314. ; stack the maximum --jkf
  315. (defun d-pushframe (class arg1 arg2)
  316.   (C-push (e-cvt arg2))
  317.   (C-push (e-cvt arg1))
  318.   (C-push `($ ,class))
  319.   (if (null $global-reg$)
  320.       then (e-move '#.np-reg '#.np-sym)
  321.        (e-move '#.np-reg '#.lbot-sym))
  322.   (e-quick-call '_qpushframe)
  323.   (e-move (e-cvt 'reg) '_errp)
  324.   (push '(catcherrset . 0) g-locs))
  325.  
  326. ;--- d-popframe :: remove an evaluation frame from the stack
  327. ;
  328. ; This is equivalent in the C system to 'errp = Popframe();'
  329. ;  n is the number of arguments given to the pushframe which
  330. ; created this frame.  We have to totally remove this frame from
  331. ; the stack only if we are in a local function, but for now, we just
  332. ; do it all the time.
  333. ;
  334. (defun d-popframe ()
  335.    (let ((treg #+(or for-vax for-tahoe) 'r1 #+for-68k 'a5))
  336.        (e-move '_errp treg)
  337.        (e-move `(#.OF_olderrp ,treg) '_errp)
  338.        ; there are always 3 arguments pushed, and the frame contains 5
  339.        ; longwords.  We should make these parameters into manifest
  340.        ; constants --jkf
  341.        (e-add3 `($ ,(+ (* 3 4) (* 5 4))) treg 'sp)))
  342.  
  343. ;--- c-cond :: compile a "cond" expression
  344. ;
  345. ; not that this version of cond is a 'c' rather than a 'cc' . 
  346. ; this was done to make coding this routine easier and because
  347. ; it is believed that it wont harm things much if at all
  348. ;
  349. (defun c-cond nil
  350.   (makecomment '(beginning cond))
  351.   (do ((clau (cdr v-form) (cdr clau))
  352.        (finlab (d-genlab))
  353.        (nxtlab)
  354.        (save-reguse)
  355.        (seent))
  356.       ((or (null clau) seent)
  357.        ; end of cond
  358.        ; if haven't seen a t must store a nil in `reg'
  359.        (if (null seent)  then (d-move 'Nil 'reg))
  360.        (e-label finlab))
  361.  
  362.       ; case 1 - expr
  363.       (if (atom (car clau))
  364.       then (comp-err "bad cond clause " (car clau))
  365.       ; case 2 - (expr)
  366.        elseif (null (cdar clau))
  367.       then (let ((g-loc (if (or g-cc g-loc) then 'reg))
  368.              (g-cc (cons finlab nil))
  369.              (g-ret (and g-ret (null (cdr clau)))))
  370.             (d-exp (caar clau)))
  371.       ; case 3 - (t expr1 expr2 ...)
  372.        elseif (or (eq t (caar clau))
  373.           (equal ''t (caar clau)))
  374.       then (let ((g-loc (if (or g-cc g-loc) then 'reg))
  375.              g-cc)
  376.             (d-exps (cdar clau)))
  377.            (setq seent t)
  378.       ; case 4 - (expr1 expr2 ...)
  379.        else (let ((g-loc nil)
  380.           (g-cc (cons nil (setq nxtlab (d-genlab))))
  381.           (g-ret nil))
  382.          (d-exp (caar clau)))
  383.         (setq save-reguse (copy g-reguse))
  384.         (let ((g-loc (if (or g-cc g-loc) then 'reg))
  385.           g-cc)
  386.          (d-exps (cdar clau)))
  387.         (if (or (cdr clau) (null seent)) then (e-goto finlab))
  388.         (e-label nxtlab)
  389.         (setq g-reguse save-reguse)))
  390.   
  391.   (d-clearreg))
  392.           
  393. ;--- c-cons :: do a cons instruction quickly
  394. ;
  395. (defun c-cons nil
  396.   (d-pushargs (cdr v-form))        ; there better be 2 args
  397.   (e-quick-call '_qcons)
  398.   (setq g-locs (cddr g-locs))
  399.   (setq g-loccnt (- g-loccnt 2))
  400.   (d-clearreg))
  401.  
  402. ;--- c-cxr :: compile a cxr instruction
  403. ;
  404. (defun cc-cxr nil
  405.   (d-supercxr t nil))
  406.  
  407. ;--- d-supercxr :: do a general struture reference
  408. ;      type - one of fixnum-block,flonum-block,<other-symbol>
  409. ; the type is that of an array, so <other-symbol> could be t, nil
  410. ; or anything else, since anything except *-block is treated the same
  411. ;
  412. ; the form of a cxr is (cxr index hunk) but supercxr will handle
  413. ; arrays too, so hunk could be (getdata (getd 'arrayname))
  414. ;
  415. ; offsetonly is t if we only care about the offset of this element from
  416. ; the beginning of the data structure.  If offsetonly is t then type
  417. ; will be nil.
  418. ;
  419. ; Note: this takes care of g-loc and g-cc 
  420.  
  421. #+(or for-vax for-tahoe)
  422. (defun d-supercxr (type offsetonly)
  423.   (let ((arg1 (cadr v-form))
  424.     (arg2 (caddr v-form))
  425.     lop rop semisimple)
  426.  
  427.        (if (fixp arg1) then (setq lop `(immed ,arg1))
  428.        else (d-fixnumexp arg1)    ; calculate index into r5
  429.         (setq lop 'r5))        ; and remember that it is there
  430.  
  431.        ; before we calculate the second expression, we may have to save
  432.        ; the value just calculated into r5.  To be safe we stack away
  433.        ; r5 if the expression is not simple or semisimple.
  434.        (if (not (setq rop (d-simple arg2)))    
  435.        then (if (and (eq lop 'r5) 
  436.              (not (setq semisimple (d-semisimple arg2))))
  437.             then (C-push (e-cvt lop)))
  438.             (let ((g-loc 'reg) g-cc)
  439.              (d-exp arg2))
  440.             (setq rop 'r0)
  441.  
  442.         (if (and (eq lop 'r5) (not semisimple))
  443.             then (C-pop (e-cvt lop))))
  444.  
  445.        (if (eq type 'flonum-block)
  446.       then (setq lop (d-structgen lop rop 8))
  447.            (e-write3 'movq lop 'r4)
  448.            (e-quick-call '_qnewdoub)    ; box number
  449.            (d-clearreg)            ; clobbers all regs
  450.            (if (and g-loc (not (eq g-loc 'reg)))
  451.           then (d-move 'reg g-loc))
  452.            (if (car g-cc) then (e-goto (car g-cc)))
  453.       else (setq lop (d-structgen lop rop 4)
  454.              rop (if g-loc then
  455.                  (if (eq type 'fixnum-block) then 'r5 
  456.                 else (e-cvt g-loc))))
  457.            (if rop 
  458.           then (if offsetonly
  459.               then (e-write3 'moval lop rop)
  460.               else (e-move lop rop))
  461.                (if (eq type 'fixnum-block) 
  462.                then (e-call-qnewint)
  463.                 (d-clearreg)
  464.                 (if (not (eq g-loc 'reg))
  465.                     then (d-move 'reg g-loc))
  466.                 ; result is always non nil.
  467.                 (if (car g-cc) then (e-goto (car g-cc)))
  468.                else (d-handlecc))
  469.         elseif g-cc 
  470.           then (if (eq type 'fixnum-block)
  471.               then (if (car g-cc) 
  472.                   then (e-goto (car g-cc)))
  473.               else (e-tst lop)
  474.                 (d-handlecc))))))
  475.  
  476. #+for-68k
  477. (defun d-supercxr (type offsetonly)
  478.    (let ((arg1 (cadr v-form))
  479.      (arg2 (caddr v-form))
  480.      lop rop semisimple)
  481.        (makecomment `(Starting d-supercxr: vform: ,v-form))
  482.        (if (fixp arg1) then (setq lop `(immed ,arg1))
  483.        else (d-fixnumexp arg1)      ; calculate index into fixnum-reg
  484.         (d-regused '#.fixnum-reg)
  485.         (setq lop '#.fixnum-reg)) ; and remember that it is there
  486.        ;
  487.        ; before we calculate the second expression, we may have to save
  488.        ; the value just calculated into fixnum-reg. To be safe we stack away
  489.        ; fixnum-reg if the expression is not simple or semisimple.
  490.        (if (not (setq rop (d-simple arg2)))    
  491.        then (if (and (eq lop '#.fixnum-reg)
  492.              (not (setq semisimple (d-semisimple arg2))))
  493.             then (C-push (e-cvt lop)))
  494.         (let ((g-loc 'areg) g-cc)
  495.             (d-exp arg2))
  496.         (setq rop 'a0)
  497.         ;
  498.         (if (and (eq lop '#.fixnum-reg) (not semisimple))
  499.             then (C-pop (e-cvt lop))))
  500.        ;
  501.        (if (eq type 'flonum-block)
  502.        then (setq lop (d-structgen lop rop 8))
  503.         (break " d-supercxr : flonum stuff not done.")
  504.         (e-write3 'movq lop 'r4)
  505.         (e-quick-call '_qnewdoub)    ; box number
  506.         (d-clearreg)            ; clobbers all regs
  507.         (if (and g-loc (not (eq g-loc 'areg)))
  508.             then (d-move 'areg g-loc))
  509.         (if (car g-cc) then (e-goto (car g-cc)))
  510.        else (if (and (dtpr rop) (eq 'stack (car rop)))
  511.             then (e-move (e-cvt rop) 'a1)
  512.              (setq rop 'a1))
  513.         (setq lop (d-structgen lop rop 4)
  514.               rop (if g-loc then
  515.                   (if (eq type 'fixnum-block)
  516.                   then '#.fixnum-reg 
  517.                   else (e-cvt g-loc))))
  518.         (if rop 
  519.             then (if offsetonly
  520.                  then (e-write3 'lea lop 'a5)
  521.                   (e-move 'a5 rop)
  522.                  else (e-move lop rop))
  523.              (if (eq type 'fixnum-block) 
  524.                  then (e-call-qnewint)
  525.                   (d-clearreg)
  526.                   (if (not (eq g-loc 'areg))
  527.                       then (d-move 'areg g-loc))
  528.                   ; result is always non nil.
  529.                   (if (car g-cc) then (e-goto (car g-cc)))
  530.                  else (e-cmpnil lop)
  531.                   (d-handlecc))
  532.          elseif g-cc 
  533.             then (if (eq type 'fixnum-block)
  534.                  then (if (car g-cc) 
  535.                       then (e-goto (car g-cc)))
  536.                  else (if g-cc
  537.                       then (e-cmpnil lop)
  538.                        (d-handlecc)))))
  539.        (makecomment "Done with d-supercxr")))
  540.  
  541. ;--- d-semisimple :: check if result is simple enough not to clobber r5
  542. ; currently we look for the case of (getdata (getd 'foo))
  543. ; since we know that this will only be references to r0.
  544. ; More knowledge can be added to this routine.
  545. ;
  546. (defun d-semisimple (form)
  547.   (or (d-simple form)
  548.       (and (dtpr form) 
  549.        (eq 'getdata (car form))
  550.        (dtpr (cadr form))
  551.        (eq 'getd (caadr form))
  552.        (dtpr (cadadr form))
  553.        (eq 'quote (caadadr form)))))
  554.  
  555. ;--- d-structgen :: generate appropriate address for indexed access
  556. ;    index - index address, must be (immed n) or r5 (which contains int)
  557. ;    base  - address of base
  558. ;    width - width of data element
  559. ; want to calculate appropriate address for base[index]
  560. ; may require emitting instructions to set up registers
  561. ; returns the address of the base[index] suitable for setting or reading
  562. ;
  563. ; the code sees the base as a stack value as a special case since it
  564. ; can generate (perhaps) better code for that case.
  565.  
  566. #+(or for-vax for-tahoe)
  567. (defun d-structgen (index base width)
  568.   (if (and (dtpr base) (eq (car base) 'stack))
  569.       then (if (dtpr index)    ; i.e if index = (immed n)
  570.            then (d-move index 'r5))    ; get immed in register
  571.        ;  the result is always *n(r6)[r5]
  572.        (append (e-cvt `(vstack ,(cadr base))) '(r5))
  573.       else (if (not (atom base))    ; i.e if base is not register
  574.            then (d-move base 'r0)    ; (if nil gets here we will fail)
  575.             (d-clearreg 'r0)
  576.             (setq base 'r0))
  577.        (if (dtpr index) then `(,(* width (cadr index)) ;immed index
  578.                     ,base)
  579.                 else `(0 ,base r5))))
  580.  
  581. #+for-68k
  582. (defun d-structgen (index base width)
  583.    (if (and (dtpr base) (eq (car base) 'stack))
  584.        then (break "d-structgen: bad args(1)")
  585.        else (if (not (atom base))    ; i.e if base is not register
  586.         then (d-move base 'a0)    ; (if nil gets here we will fail)
  587.              (d-clearreg 'a0)
  588.              (setq base 'a0))
  589.         (if (dtpr index)
  590.         then `(,(* width (cadr index)) ,base)
  591.         else (d-regused 'd6)
  592.              (e-move index 'd6)
  593.              (e-write3 'asll '($ 2) 'd6)
  594.              `(% 0 ,base d6))))
  595.  
  596. ;--- c-rplacx :: complile a rplacx expression
  597. ;
  598. ;  This simple calls the general structure hacking function, d-superrplacx
  599. ;  The argument, hunk, means that the elements stored in the hunk are not
  600. ;  fixum-block or flonum-block arrays.
  601. (defun c-rplacx nil
  602.   (d-superrplacx 'hunk))
  603.  
  604. ;--- d-superrplacx :: handle general setting of things in structures
  605. ;    type - one of fixnum-block, flonum-block, hunk
  606. ; see d-supercxr for comments
  607. ; form of rplacx is (rplacx index hunk valuetostore)
  608. #+(or for-vax for-tahoe)
  609. (defun d-superrplacx (type)
  610.      (let ((arg1 (cadr v-form))
  611.            (arg2 (caddr v-form))
  612.            (arg3 (cadddr v-form))
  613.            lop rop semisimple)
  614.           
  615.           ; calulate index and put it in r5 if it is not an immediate
  616.           ; set lop to the location of the index
  617.           (if (fixp arg1) then (setq lop `(immed ,arg1))
  618.           else (d-fixnumexp arg1)
  619.                (setq lop 'r5))    
  620.           
  621.           ; set rop to the location of the hunk.  If we have to 
  622.           ; calculate the hunk, we may have to save r5.
  623.           ; If we are doing a rplacx (type equals hunk) then we must
  624.           ; return the hunk in r0.
  625.           (if (or (eq type 'hunk) (not (setq rop (d-simple arg2))))
  626.           then (if (and (eq lop 'r5) 
  627.                 (not (setq semisimple (d-semisimple arg2))))
  628.                then (d-move lop '#.Cstack))
  629.                (let ((g-loc 'r0) g-cc)
  630.                 (d-exp arg2))
  631.                (setq rop 'r0)
  632.           
  633.                (if (and (eq lop 'r5) (not semisimple))
  634.                then (d-move '#.unCstack lop)))
  635.  
  636.           ; now that the index and data block locations are known, we 
  637.           ; caclulate the location of the index'th element of hunk
  638.           (setq rop
  639.             (d-structgen lop rop
  640.                  (if (eq type 'flonum-block) then 8 else 4)))
  641.  
  642.           ; the code to calculate the value to store and the actual
  643.           ; storing depends on the type of data block we are storing in.
  644.           (if (eq type 'flonum-block) 
  645.           then (if (setq lop (d-simple `(cdr ,arg3)))
  646.                then (e-write3 'movq (e-cvt lop) rop)
  647.                else ; preserve rop since it may be destroyed
  648.                 ; when arg3 is calculated
  649.                 (e-write3 'movaq rop '#.Cstack)
  650.                 (let ((g-loc 'r0) g-cc)
  651.                      (d-exp arg3))
  652.                 (d-clearreg 'r0)
  653.                 (e-write3 'movq '(0 r0) "*(sp)+"))
  654.            elseif (and (eq type 'fixnum-block)
  655.                (setq arg3 `(cdr ,arg3))
  656.                nil)
  657.               ; fixnum-block is like hunk except we must grab the
  658.               ; fixnum value out of its box, hence the (cdr arg3)
  659.            thenret
  660.            else (if (setq lop (d-simple arg3))
  661.             then (e-move (e-cvt lop) rop)
  662.             else ; if we are dealing with hunks, we must save
  663.                  ; r0 since that contains the value we want to
  664.                  ; return.
  665.                  (if (eq type 'hunk) then (d-move 'reg 'stack)
  666.                               (Push g-locs nil)
  667.                               (incr g-loccnt))
  668.                  (e-write3 'moval rop '#.Cstack)
  669.                  (let ((g-loc "*(sp)+") g-cc)
  670.                   (d-exp arg3))
  671.                  (if (eq type 'hunk) then (d-move 'unstack 'reg)
  672.                               (unpush g-locs)
  673.                               (decr g-loccnt))
  674.                  (d-clearreg 'r0)))))
  675.  
  676. #+for-68k
  677. (defun d-superrplacx (type)
  678.    (let ((arg1 (cadr v-form))
  679.      (arg2 (caddr v-form))
  680.      (arg3 (cadddr v-form))
  681.      lop rop semisimple)
  682.        (makecomment `(starting d-superrplacx ,type :: v-form = ,v-form))
  683.        ;
  684.        ; calulate index and put it in '#.fixnum-reg if it is not an immediate
  685.        ; set lop to the location of the index
  686.        (if (fixp arg1) then (setq lop `(immed ,arg1))
  687.        else (d-fixnumexp arg1)
  688.         (d-regused '#.fixnum-reg)
  689.         (setq lop '#.fixnum-reg))
  690.        ;
  691.        ; set rop to the location of the hunk.  If we have to
  692.        ; calculate the hunk, we may have to save '#.fixnum-reg.
  693.        ; If we are doing a rplacx (type equals hunk) then we must
  694.        ; return the hunk in d0.
  695.        (if (or (eq type 'hunk) (not (setq rop (d-simple arg2))))
  696.        then (if (and (eq lop '#.fixnum-reg)
  697.              (not (setq semisimple (d-semisimple arg2))))
  698.             then (d-move lop '#.Cstack))
  699.         (let ((g-loc 'a0) g-cc)
  700.             (d-exp arg2))
  701.         (setq rop 'a0)
  702.         (if (and (eq lop '#.fixnum-reg) (not semisimple))
  703.             then (d-move '#.unCstack lop)))
  704.        ;
  705.        ; now that the index and data block locations are known, we
  706.        ; caclulate the location of the index'th element of hunk
  707.        (setq rop
  708.          (d-structgen lop rop
  709.               (if (eq type 'flonum-block) then 8 else 4)))
  710.        ;
  711.        ; the code to calculate the value to store and the actual
  712.        ; storing depends on the type of data block we are storing in.
  713.        (if (eq type 'flonum-block) 
  714.        then (break "flonum stuff not in yet")
  715.         (if (setq lop (d-simple `(cdr ,arg3)))
  716.             then (e-write3 'movq (e-cvt lop) rop)
  717.             else ; preserve rop since it may be destroyed
  718.              ; when arg3 is calculated
  719.              (e-write3 'movaq rop '#.Cstack)
  720.              (let ((g-loc 'd0) g-cc)
  721.                  (d-exp arg3))
  722.              (d-clearreg 'd0)
  723.              (e-write3 'movq '(0 d0) "*(sp)+"))
  724.     elseif (and (eq type 'fixnum-block)
  725.             (setq arg3 `(cdr ,arg3))
  726.             nil)
  727.          ; fixnum-block is like hunk except we must grab the
  728.          ; fixnum value out of its box, hence the (cdr arg3)
  729.        thenret
  730.        else (if (setq lop (d-simple arg3))
  731.             then (e-move (e-cvt lop) rop)
  732.             else ; if we are dealing with hunks, we must save
  733.              ; d0 since that contains the value we want to
  734.              ; return.
  735.              (if (eq type 'hunk)
  736.                  then (L-push 'a0)
  737.                   (push nil g-locs)
  738.                   (incr g-loccnt))
  739.              (e-write3 'lea rop 'a5)
  740.              (C-push 'a5)
  741.              (let ((g-loc '(racc * 0 sp)) g-cc)
  742.                  (d-exp arg3))
  743.              (if (eq type 'hunk)
  744.                  then (L-pop 'd0)
  745.                   (unpush g-locs)
  746.                   (decr g-loccnt))))
  747.        (makecomment '(d-superrplacx done))))
  748.                 
  749. ;--- cc-cxxr :: compile a "c*r" instr where *
  750. ;        is any sequence of a's and d's
  751. ;    - arg : argument of the cxxr function
  752. ;    - pat : a list of a's and d's in the reverse order of that
  753. ;            which appeared between the c and r
  754. ;
  755. #+(or for-vax for-tahoe)
  756. (defun cc-cxxr (arg pat)
  757.   (prog (resloc loc qloc sofar togo keeptrack)
  758.     ; check for the special case of nil, since car's and cdr's
  759.     ; are nil anyway
  760.     (if (null arg)
  761.         then (if g-loc then (d-move 'Nil g-loc)
  762.              (d-handlecc)
  763.           elseif (cdr g-cc) then (e-goto (cdr g-cc)))
  764.          (return))
  765.                       
  766.     (if (and (symbolp arg) (setq qloc (d-bestreg arg pat)))
  767.         then (setq resloc (car qloc)
  768.                loc   resloc
  769.                sofar  (cadr qloc)
  770.                togo   (caddr qloc))
  771.         else (setq resloc
  772.                (if (d-simple arg)
  773.                thenret
  774.                else (let ((g-loc 'reg)
  775.                       (g-cc nil)
  776.                       (g-ret nil))
  777.                     (d-exp arg))
  778.                 'r0))
  779.            (setq sofar nil togo pat))
  780.  
  781.     (if (and arg (symbolp arg)) then (setq keeptrack t))
  782.  
  783.        ; if resloc is a global variable, we must move it into a register
  784.        ; right away to be able to do car's and cdr's
  785.        (if (and (dtpr resloc) (or (eq (car resloc) 'bind)
  786.                   (eq (car resloc) 'vstack)))
  787.        then (d-move resloc 'reg)
  788.         (setq resloc 'r0))
  789.  
  790.        ; now do car's and cdr's .  Values are placed in r0. We stop when
  791.        ; we can get the result in one machine instruction.  At that point
  792.        ; we see whether we want the value or just want to set the cc's.
  793.        ; If the intermediate value is in a register, 
  794.        ; we can do : car cdr cddr cdar
  795.        ; If the intermediate value is on the local vrbl stack or lbind
  796.        ; we can do : cdr
  797.        (do ((curp togo newp)
  798.         (newp))
  799.        ((null curp) (if g-loc then (d-movespec loc g-loc)
  800.                 elseif g-cc then (e-tst loc))
  801.                     (d-handlecc))
  802.        (if (symbolp resloc)
  803.            then (if (eq 'd (car curp))
  804.             then (if (or (null (cdr curp))
  805.                      (eq 'a (cadr curp)))
  806.                  then (setq newp (cdr curp)   ; cdr
  807.                         loc `(0 ,resloc)
  808.                         sofar (append sofar (list 'd)))
  809.                  else (setq newp (cddr curp)  ; cddr
  810.                         loc `(* 0 ,resloc)
  811.                         sofar (append sofar
  812.                               (list 'd 'd))))
  813.             else (if (or (null (cdr curp))
  814.                      (eq 'a (cadr curp)))
  815.                  then (setq newp (cdr curp)   ; car
  816.                         loc `(4 ,resloc)
  817.                         sofar (append sofar (list 'a)))
  818.                  else (setq newp (cddr curp)  ; cdar
  819.                         loc `(* 4 ,resloc)
  820.                         sofar (append sofar
  821.                               (list 'a 'd)))))
  822.            elseif (and (eq 'd (car curp))
  823.                (not (eq '* (car (setq loc (e-cvt resloc))))))
  824.          then (setq newp (cdr curp)    ; (cdr <local>)
  825.                 loc (cons '* loc)
  826.                 sofar (append sofar (list 'd)))
  827.            else  (setq loc (e-cvt resloc)
  828.                newp curp))
  829.        (if newp            ; if this is not the last move
  830.            then (setq resloc
  831.               (d-allocreg (if keeptrack then nil else 'r0)))
  832.             (d-movespec loc resloc)
  833.             (if keeptrack then (d-inreg resloc (cons arg sofar)))))))
  834.  
  835. #+for-68k
  836. (defun cc-cxxr (arg pat)
  837.    (prog (resloc loc qloc sofar togo keeptrack)
  838.        (makecomment '(starting cc-cxxr))
  839.        ; check for the special case of nil, since car's and cdr's
  840.        ; are nil anyway
  841.        (if (null arg)
  842.        then (if g-loc then (d-move 'Nil g-loc))
  843.         (if (cdr g-cc) then (e-goto (cdr g-cc)))
  844.         (return))
  845.        (if (and (symbolp arg) (setq qloc (d-bestreg arg pat)))
  846.        then (setq resloc (car qloc)
  847.               loc   resloc
  848.               sofar  (cadr qloc)
  849.               togo   (caddr qloc))
  850.        else (setq resloc
  851.               (if (d-simple arg) thenret
  852.               else (d-clearreg 'a0)
  853.                    (let ((g-loc 'areg)
  854.                      (g-cc nil)
  855.                      (g-ret nil))
  856.                    (d-exp arg))
  857.                    'a0))
  858.         (setq sofar nil togo  pat))
  859.        (if (and arg (symbolp arg)) then (setq keeptrack t))
  860.        ;
  861.        ; if resloc is a global variable, we must move it into a register
  862.        ; right away to be able to do car's and cdr's
  863.        (if (and (dtpr resloc) (or (eq (car resloc) 'bind)
  864.                   (eq (car resloc) 'vstack)))
  865.        then (d-move resloc 'areg)
  866.         (setq resloc 'a0))
  867.        ; now do car's and cdr's .  Values are placed in a0. We stop when
  868.        ; we can get the result in one machine instruction.  At that point
  869.        ; we see whether we want the value or just want to set the cc's.
  870.        ; If the intermediate value is in a register,
  871.        ; we can do : car cdr cddr cdar
  872.        ; If the intermediate value is on the local vrbl stack or lbind
  873.        ; we can do : cdr
  874.        (do ((curp togo newp)
  875.         (newp))
  876.        ((null curp)
  877.         (if g-loc then (d-movespec loc g-loc))
  878.         ;
  879.         ;;;important: the below kludge is needed!!
  880.         ;;;consider the compilation of the following:
  881.         ;
  882.         ;;; (cond ((setq c (cdr c)) ...))
  883.         ;;; the following instructions are generated:
  884.         ;;; movl  a4@(N),a5    ; the setq
  885.         ;;; movl  a5@,a4@(N)
  886.         ;;; movl  a4@,a5       ; the last two are generated if g-cc
  887.         ;;; cmpl  a5@,d7       ; is non-nil
  888.         ;
  889.         ;;; observe that the original value the is supposed to set
  890.         ;;; the cc's is clobered in the operation!!
  891.         ;(msg "g-loc: " (e-cvt g-loc) N "loc: " loc N)
  892.         (if g-cc
  893.         then (if (and (eq '* (car loc))
  894.                   (equal (caddr loc) (cadr (e-cvt g-loc))))
  895.              then (e-cmpnil '(0 a5))
  896.              else (e-cmpnil loc)))
  897.         (d-handlecc))
  898.        (if (symbolp resloc)
  899.            then (if (eq 'd (car curp))
  900.             then (if (or (null (cdr curp))
  901.                      (eq 'a (cadr curp)))
  902.                  then (setq newp (cdr curp)   ; cdr
  903.                         loc `(0 ,resloc)
  904.                         sofar (append sofar (list 'd)))
  905.                  else (setq newp (cddr curp)  ; cddr
  906.                         loc `(* 0 ,resloc)
  907.                         sofar (append sofar
  908.                               (list 'd 'd))))
  909.             else (if (or (null (cdr curp))
  910.                      (eq 'a (cadr curp)))
  911.                  then (setq newp (cdr curp)   ; car
  912.                         loc `(4 ,resloc)
  913.                         sofar (append sofar (list 'a)))
  914.                  else (setq newp (cddr curp)  ; cdar
  915.                         loc `(* 4 ,resloc)
  916.                         sofar (append sofar
  917.                               (list 'a 'd)))))
  918.         elseif (and (eq 'd (car curp))
  919.             (not (eq '* (car (setq loc (e-cvt resloc))))))
  920.            then (setq newp (cdr curp)    ; (cdr <local>)
  921.               loc (cons '* loc)
  922.               sofar (append sofar (list 'd)))
  923.            else  (setq loc (e-cvt resloc)
  924.                newp curp))
  925.        (if newp            ; if this is not the last move
  926.            then (setq resloc
  927.               (d-alloc-register 'a
  928.                         (if keeptrack then nil else 'a1)))
  929.             (d-movespec loc resloc)
  930.             ;(if keeptrack then (d-inreg resloc (cons arg sofar)))
  931.             ))
  932.        (makecomment '(done with cc-cxxr))))
  933.