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

  1. (include-if (null (get 'chead 'version)) "../chead.l")
  2. (Liszt-file util
  3.    "$Header: util.l,v 1.15 87/12/15 17:09:21 sklower Exp $")
  4.  
  5. ;;; ----    u t i l            general utility functions
  6. ;;;
  7. ;;;                -[Tue Aug 16 17:17:32 1983 by layer]-
  8.  
  9.  
  10. ;--- d-handlecc :: handle g-cc
  11. ; at this point the Z condition code has been set up and if g-cc is
  12. ; non nil, we must jump on condition to the label given in g-cc
  13. ;
  14. (defun d-handlecc nil
  15.    (if (car g-cc)
  16.        then (e-gotot (car g-cc))
  17.     elseif (cdr g-cc)
  18.        then (e-gotonil (cdr g-cc))))
  19.  
  20. ;--- d-invert :: handle inverted condition codes
  21. ; this routine is called if a result has just be computed which alters
  22. ; the condition codes such that Z=1 if the result is t, and Z=0 if the
  23. ; result is nil (this is the reverse of the usual sense).  The purpose
  24. ; of this routine is to handle g-cc and g-loc.  That is if g-loc is 
  25. ; specified, we must convert the value of the Z bit of the condition 
  26. ; code to t or nil and store that in g-loc.  After handling g-loc we
  27. ; must handle g-cc, that is if the part of g-cc is non nil which matches
  28. ; the inverse of the current condition code, we must jump to that.
  29. ;
  30. (defun d-invert nil
  31.   (if (null g-loc) 
  32.       then (if (car g-cc) then (e-gotonil (car g-cc))
  33.         elseif (cdr g-cc) then  (e-gotot (cdr g-cc)))
  34.       else (let ((lab1 (d-genlab))
  35.          (lab2 (if (cdr g-cc) thenret else (d-genlab))))
  36.         (e-gotonil lab1)
  37.         ; Z=1, but remember that this implies nil due to inversion
  38.         (d-move 'Nil g-loc)
  39.         (e-goto lab2)
  40.         (e-label lab1)
  41.         ; Z=0, which means t
  42.         (d-move 'T g-loc)
  43.         (if (car g-cc) then (e-goto (car g-cc)))
  44.         (if (null (cdr g-cc)) then (e-label lab2)))))
  45.             
  46. ;--- d-noninvert :: handle g-cc and g-loc assuming cc non inverted
  47. ; like d-invert except Z=0 implies nil, and Z=1 implies t
  48. ;
  49. (defun d-noninvert nil
  50.   (if (null g-loc) 
  51.       then (if (car g-cc) then (e-gotot (car g-cc))
  52.         elseif (cdr g-cc) then  (e-gotonil (cdr g-cc)))
  53.       else (let ((lab1 (d-genlab))
  54.          (lab2 (if (cdr g-cc) thenret else (d-genlab))))
  55.         (e-gotot lab1)
  56.         ; Z=0, this implies nil
  57.         (d-move 'Nil g-loc)
  58.         (e-goto lab2)
  59.         (e-label lab1)
  60.         ; Z=1, which means t
  61.         (d-move 'T g-loc)
  62.         (if (car g-cc) then (e-goto (car g-cc)))
  63.         (if (null (cdr g-cc)) then (e-label lab2)))))
  64.  
  65. ;--- d-macroexpand :: macro expand a form as much as possible
  66. ;
  67. ; only macro expands the top level though.
  68. (defun d-macroexpand (i)
  69.    (prog (first type)
  70.       loop
  71.       (if (and (dtpr i) (symbolp (setq first (car i))))
  72.      then (if (eq 'macro (setq type (d-functyp first 'macro-ok)))
  73.          then (setq i (apply first i))
  74.               (go loop)
  75.            elseif (eq 'cmacro type)
  76.          then (setq i (apply (get first 'cmacro) i))
  77.               (go loop)))
  78.       (return i)))
  79.  
  80. ;--- d-fullmacroexpand :: macro expand down all levels
  81. ; this is not always possible to due since it is not always clear
  82. ; if a function is a lambda or nlambda, and there are lots of special
  83. ; forms.  This is just a first shot at such a function, this should
  84. ; be improved upon.
  85. ;
  86. (defun d-fullmacroexpand (form)
  87.    (if (not (dtpr form))
  88.        then form
  89.        else (setq form (d-macroexpand form))    ; do one level
  90.             (if (and (dtpr form) (symbolp (car form)))
  91.         then (let ((func (getd (car form))))
  92.               (if (or (and (bcdp func)
  93.                        (eq 'lambda (getdisc func)))
  94.                   (and (dtpr func)
  95.                        (memq (car func) '(lambda lexpr)))
  96.                   (memq (car form) '(or and)))
  97.                   then `(,(car form)
  98.                       ,@(mapcar 'd-fullmacroexpand
  99.                         (cdr form)))
  100.                 elseif (eq (car form) 'setq)
  101.                   then (d-setqexpand form)
  102.                 else form))
  103.         else form)))
  104.  
  105. ;--- d-setqexpand :: macro expand a setq statemant
  106. ; a setq is unusual in that alternate values are macroexpanded.
  107. ;
  108. (defun d-setqexpand (form)
  109.    (if (oddp (length (cdr form)))
  110.        then (comp-err "wrong number of args to setq " form)
  111.        else (do ((xx (reverse (cdr form)) (cddr xx))
  112.          (res))
  113.         ((null xx) (cons 'setq res))
  114.         (setq res `(,(cadr xx)
  115.                  ,(d-fullmacroexpand (car xx))
  116.                  ,@res)))))
  117.    
  118. ;--- d-typesimp ::  determine the type of the argument 
  119. ;
  120. #+(or for-vax for-tahoe)
  121. (defun d-typesimp (arg val)
  122.   (let ((argloc (d-simple arg)))
  123.     (if (null argloc)
  124.         then (let ((g-loc 'reg)
  125.                g-cc g-ret)
  126.              (d-exp arg))
  127.          (setq argloc 'reg))
  128.     #+for-vax (e-write4 'ashl '$-9 (e-cvt argloc) 'r0)
  129.     #+for-tahoe (e-write4 'shar '$9 (e-cvt argloc) 'r0)
  130.     (e-write3 'cmpb '"_typetable+1[r0]" val)
  131.     (d-invert)))
  132.  
  133. #+for-68k
  134. (defun d-typesimp (arg val)
  135.    (let ((argloc (d-simple arg)))
  136.        (if (null argloc)
  137.        then (let ((g-loc 'reg)
  138.               g-cc g-ret)
  139.             (d-exp arg))
  140.         (setq argloc 'reg)
  141.        else (e-move (e-cvt argloc) 'd0))
  142.        (e-sub '#.nil-reg 'd0)
  143.        (e-write3 'moveq '($ 9) 'd1)
  144.        (e-write3 'asrl 'd1 'd0)
  145.        (e-write3 'lea '"_typetable+1" 'a5)
  146.        (e-write3 'cmpb val '(% 0 a5 d0))
  147.        (d-invert)))
  148.  
  149. ;--- d-typecmplx  :: determine if arg has one of many types
  150. ;    - arg : lcode argument to be evaluated and checked
  151. ;    - vals : fixnum with a bit in position n if we are to check type n
  152. ;
  153. #+(or for-vax for-tahoe)
  154. (defun d-typecmplx (arg vals)
  155.   (let ((argloc (d-simple arg))
  156.     (reg))
  157.        (if (null argloc) then (let ((g-loc 'reg)
  158.                     g-cc g-ret)
  159.                    (d-exp arg))
  160.                   (setq argloc 'reg))
  161.        (setq reg 'r0)
  162.        #+for-vax (e-write4 'ashl '$-9 (e-cvt argloc) reg)
  163.        #+for-tahoe (e-write4 'shar '$9 (e-cvt argloc) reg)
  164.        (e-write3 'cvtbl (concat "_typetable+1[" reg "]") reg)
  165.        (e-write4 #+for-vax 'ashl #+for-tahoe 'shal reg '$1 reg)
  166.        (e-write3 'bitw vals reg)
  167.        (d-noninvert)))
  168.  
  169. #+for-68k
  170. (defun d-typecmplx (arg vals)
  171.    (let ((argloc (d-simple arg))
  172.      (l1 (d-genlab))
  173.      (l2 (d-genlab)))
  174.        (makecomment '(d-typecmplx: type check))
  175.        (if (null argloc)
  176.        then (let ((g-loc 'reg)
  177.               g-cc g-ret)
  178.             (d-exp arg))
  179.         (setq argloc 'reg)
  180.        else (e-move (e-cvt argloc) 'd0))
  181.        (e-sub '#.nil-reg 'd0)
  182.        (e-write3 'moveq '($ 9) 'd1)
  183.        (e-write3 'asrl 'd1 'd0)
  184.        (e-write3 'lea '"_typetable+1" 'a5)
  185.        (e-add 'd0 'a5)
  186.        (e-write3 'movb '(0 a5) 'd0)
  187.        (e-write2 'extw 'd0)
  188.        (e-write2 'extl 'd0)
  189.        (e-write3 'moveq '($ 1) 'd1)
  190.        (e-write3 'asll 'd0 'd1)
  191.        (e-move 'd1 'd0)
  192.        (e-write3 'andw vals 'd0)
  193.        (d-noninvert)
  194.        (makecomment '(d-typecmplx: end))))
  195.  
  196. ;---- register handling routines.
  197.  
  198. ;--- d-allocreg :: allocate a register 
  199. ;  name - the name of the register to allocate or nil if we should
  200. ;      allocate the least recently used.
  201. ;
  202. (defun d-allocreg (name)
  203.   (if name 
  204.       then (let ((av (assoc name g-reguse)))
  205.         (if av then (rplaca (cdr av) (1+ (cadr av)))) ; inc used count
  206.         name)
  207.       else ; find smallest used count
  208.        (do ((small (car g-reguse))
  209.         (smc (cadar g-reguse))
  210.         (lis (cdr g-reguse) (cdr lis)))
  211.            ((null lis)
  212.         (rplaca (cdr small) (1+ smc))
  213.         (car small))
  214.            (if (< (cadar lis) smc)
  215.            then (setq small (car lis)
  216.                   smc   (cadr small))))))
  217.  
  218.  
  219. ;--- d-bestreg :: determine the register which is closest to what we have
  220. ;  name - name of variable whose subcontents we want
  221. ;  pat  - list of d's and a's which tell which part we want
  222. ;
  223. (defun d-bestreg (name pat)
  224.   (do ((ll g-reguse (cdr ll))
  225.        (val)
  226.        (best)
  227.        (tmp)
  228.        (bestv -1))
  229.       ((null ll)
  230.        (if best
  231.        then (rplaca (cdr best) (1+ (cadr best)))
  232.         (list (car best)
  233.               (if (> bestv 0) 
  234.               then (rplacd (nthcdr (1- bestv)
  235.                            (setq tmp
  236.                              (copy pat)))
  237.                        nil)
  238.                    tmp
  239.               else nil)
  240.               (nthcdr bestv pat))))
  241.       (if (and (setq val (cddar ll))
  242.            (eq name (car val)))
  243.       then (if (> (setq tmp (d-matchcnt pat (cdr val)))
  244.               bestv)
  245.            then (setq bestv tmp
  246.                   best  (car ll))))))
  247.  
  248. ;--- d-matchcnt :: determine how many parts of a pattern match
  249. ; want - pattern we want to achieve
  250. ; have - pattern whose value exists in a register
  251. ; we return a count of the number of parts of the pattern match.
  252. ; If this pattern will be any help at all, we return a value from 
  253. ; 0 to the length of the pattern.
  254. ; If this pattern will not work at all, we return a number smaller
  255. ; than -1.  
  256. ; For `have' to be useful for `want', `have' must be a substring of 
  257. ; `want'.  If it is a substring, we return the length of `have'.
  258. (defun d-matchcnt (want have)
  259.   (let ((length 0))
  260.        (if (do ((hh have (cdr hh))
  261.         (ww want (cdr ww)))
  262.            ((null hh) t)
  263.            (if (or (null ww) (not (eq (car ww) (car hh))))
  264.            then (return nil)
  265.            else (incr length)))
  266.        then  length
  267.        else  -2)))
  268.  
  269. ;--- d-clearreg :: clear all values in registers or just one
  270. ; if no args are given, clear all registers.
  271. ; if an arg is given, clear that register
  272. ;
  273. (defun d-clearreg n
  274.   (cond ((zerop n) 
  275.      (mapc '(lambda (x) (rplaca (cdr x) 0)
  276.              (rplacd (cdr x) nil))
  277.            g-reguse))
  278.     (t (let ((av (assoc (arg 1) g-reguse)))
  279.         (if av
  280.            then
  281.             #+for-68k (d-regused (car av))
  282.             (rplaca (cdr av) 0)
  283.             (rplacd (cdr av) nil)
  284.            else nil)))))
  285.  
  286. ;--- d-clearuse :: clear all register which reference a given variable
  287. ;
  288. (defun d-clearuse (varib)
  289.   (mapc '(lambda (x)
  290.          (if (eq (caddr x) varib) then (rplacd (cdr x) nil)))
  291.     g-reguse))
  292.  
  293. ;--- d-inreg :: declare that a value is in a register
  294. ; name - register name
  295. ; value - value in a register
  296. ;
  297. (defun d-inreg (name value)
  298.   (let ((av (assoc name g-reguse)))
  299.        (if av then (rplacd (cdr av) value))
  300.        name))
  301.  
  302. (defun e-setup-np-lbot nil
  303.    (e-move '#.np-reg '#.np-sym)
  304.    (e-move '#.lbot-reg '#.lbot-sym))
  305.  
  306. ;---------------MC68000 only routines
  307. #+for-68k
  308. (progn 'compile
  309.  
  310. ;--- d-regtype :: find out what type of register the operand goes
  311. ;          in.
  312. ; eiadr - an EIADR
  313. ;
  314. (defun d-regtype (eiadr)
  315.    (if (symbolp eiadr)
  316.        then (if (memq eiadr '(d0 d1 d2 d3 d4 d5 d6 d7 reg)) then 'd
  317.          elseif (memq eiadr '(a0 a1 a2 a3 a4 a5 a6 a7 sp areg)) then 'a)
  318.     elseif (or (eq '\# (car eiadr))
  319.            (eq '$ (car eiadr))
  320.            (and (eq '* (car eiadr))
  321.             (eq '\# (cadr eiadr))))
  322.        then 'd
  323.        else 'a))
  324.  
  325. ;--- d-regused :: declare that a reg is used in a function
  326. ;    regname - name of the register that is going to be used
  327. ;          (ie, 'd0 'a2...)
  328. ;
  329. (defun d-regused (regname)
  330.    (let ((regnum (diff (cadr (exploden regname)) 48))
  331.      (regtype (car (explode regname))))
  332.        (if (memq regname '(a0 a1 d0 d1))
  333.        thenret
  334.     elseif (equal 'd regtype)
  335.        then (rplacx regnum g-regmaskvec t) regname
  336.        else (rplacx (plus regnum 8) g-regmaskvec t) regname)))
  337.  
  338. ;--- d-makemask :: make register mask for moveml instr
  339. ;
  340. (defun d-makemask ()
  341.    (do ((ii 0 (1+ ii))
  342.     (mask 0))
  343.        ((greaterp ii 15) mask)
  344.        (if (cxr ii g-regmaskvec)
  345.        then (setq mask (plus mask (expt 2 ii))))))
  346.  
  347. ;--- init-regmaskvec :: initalize hunk structure to all default
  348. ;            save mask.
  349. ;
  350. ; nil means don't save it, and t means save the register upon function entry.
  351. ; order in vector: d0 .. d7, a0 .. a7.
  352. ; d3 : lbot (if $global-reg$ is t then save)
  353. ; d7 : _nilatom
  354. ; a2 : _np
  355. ; a3 : literal table ptr
  356. ; a4 : old _lbot (if $global-reg$ is t don't save)
  357. ; a5 : intermediate address calc
  358. ;
  359. (defun init-regmaskvec ()
  360.    (setq g-regmaskvec
  361.      (makhunk
  362.          (if $global-reg$
  363.          then (quote (nil nil nil t   nil nil nil t
  364.                   nil nil t   t   t   t   nil nil))
  365.          else (quote (nil nil nil nil nil nil nil t
  366.                   nil nil t   t   t   t   nil nil))))))
  367.  
  368. ;--- Cstackspace :: calc local space on C stack
  369. ; space = 4 * (no. of register variables saved on stack)
  370. ;
  371. (defun Cstackspace ()
  372.    (do ((ii 0 (1+ ii))
  373.     (retval 0))
  374.        ((greaterp ii 15) (* 4 retval))
  375.        (if (cxr ii g-regmaskvec) then (setq retval (1+ retval)))))
  376.  
  377. ;--- d-alloc-register :: allocate a register
  378. ;  type - type of register (a or d)
  379. ;  name - the name of the register to allocate or nil if we should
  380. ;      allocate the least recently used.
  381. ;
  382. (defun d-alloc-register (type name)
  383.    (if name 
  384.        then (let ((av (assoc name g-reguse)))
  385.         (d-regused name)
  386.         (if av then (rplaca (cdr av) (1+ (cadr av)))) ; inc used count
  387.         name)
  388.        else ; find smallest used count
  389.         (let ((reguse))
  390.         (do ((cur g-reguse (cdr cur)))
  391.             ((null cur))
  392.             (if (eq type (car (explode (caar cur))))
  393.             then (setq reguse (cons (car cur) reguse))))
  394.         (do ((small (car reguse))
  395.              (smc (cadar reguse))
  396.              (lis (cdr reguse) (cdr lis)))
  397.             ((null lis)
  398.              (rplaca (cdr small) (1+ smc))
  399.              (d-regused (car small))
  400.              (car small))
  401.             (if (< (cadar lis) smc)
  402.             then (setq small (car lis)
  403.                    smc   (cadr small)))))))
  404.  
  405. ); end 68000 only routines
  406.