4.4BSD/usr/src/old/lisp/liszt/vector.l
(include-if (null (get 'chead 'version)) "../chead.l")
(Liszt-file vector
"$Header: vector.l,v 1.12 87/12/15 17:10:04 sklower Exp $")
;;; ---- v e c t o r vector referencing
;;;
;;; -[Fri Nov 11 22:35:50 1983 by jkf]-
(defun cc-vset ()
;; Set a vector created via 'vector'.
(d-vset 'lisp))
(defun cc-vref ()
;; Reference a vector created via 'vector'.
(d-vref 'lisp))
(defun cc-vseti-byte ()
;; Set a vector created via 'vectori-byte'.
(d-vset 'byte))
(defun cc-vrefi-byte ()
;; Reference a vector created via 'vectori-byte'.
(d-vref 'byte))
(defun cc-vseti-word ()
;; Set a vector created via 'vectori-word'.
(d-vset 'word))
(defun cc-vrefi-word ()
;; Reference a vector created via 'vectori-word'.
(d-vref 'word))
(defun cc-vseti-long ()
;; Set a vector created via 'vectori-long'.
(d-vset 'long))
(defun cc-vrefi-long ()
;; Reference a vector created via 'vectori-long'.
(d-vref 'long))
;--- d-vset :: handle all types of vset's
(defun d-vset (type)
;; Generic vector store. Type is either 'lisp', 'byte', 'word',
;; or 'long'.
(let ((vect (cadr v-form))
(index (caddr v-form))
(val (cadddr v-form))
(vect-addr) (index-addr)
(vect-val) (fetchval)
(temp) (size)
(vec-reg #+(or for-vax for-tahoe) 'r0 #+for-68k 'a0)
(val-reg #+(or for-vax for-tahoe) 'r1 #+for-68k 'd1)
(index-reg '#.fixnum-reg)
(temp-reg #+(or for-vax for-tahoe) 'r4 #+for-68k 'd0)
(temp-areg #+(or for-vax for-tahoe) 'bogus! #+for-68k 'a1)
(oklab (d-genlab))
(needlowcheck t)) ; t if must check lower index bounds
#+for-68k (d-regused '#.fixnum-reg)
(makecomment `(doing vec set type ,type))
(if (fixp index)
then (if (<& index 0)
then (comp-err "vector index less than 0 " v-form))
(setq needlowcheck nil))
; Compute the value to be stored...
;
; If we are doing an immediate vector, then get the value
; instead of the boxed fixnum (in the case of byte), or
; word/long.
(if (null (eq 'lisp type)) then (setq val `(cdr ,val)))
(if (null (setq vect-val (d-simple val)))
then (let ((g-loc val-reg) g-cc g-ret)
(d-exp val))
(setq vect-val val-reg)
else (setq vect-val (e-cvt vect-val)))
; make sure that we are not going to clobber val-reg...
(if (not (and (d-simple vect) (d-simple index)))
then ; val-reg could be clobbered when we do the
; fetching of the vector or index values
(setq fetchval t)
(e-move vect-val (e-cvt 'stack)))
; Compute the index...
;
(if (setq index-addr (d-simple index))
then (let ((g-loc vec-reg) g-cc g-ret)
(d-exp vect))
(setq vect-addr vec-reg) ; the vector op is in vec-reg
; we really want the cdr of index (the actual number).
; if we can do that simply, great. otherwise we
; bring the index into index-reg and then do the cdr ourselves
(if (setq temp (d-simple `(cdr ,index)))
then (d-move temp index-reg)
else (d-move index-addr index-reg)
#+(or for-vax for-tahoe)
(e-move `(0 ,index-reg) index-reg)
#+for-68k
(progn
(e-move index-reg 'a5)
(e-move '(0 a5) index-reg)))
(setq index-addr index-reg)
else ; the index isn't computable simply, so we must
; stack the vector location to keep it safe
(let ((g-loc 'stack) g-cc g-ret)
(d-exp vect))
(push nil g-locs)
(incr g-loccnt)
; compute index's value into index-reg
(d-fixnumexp index)
; now put vector address into vec-reg
(d-move 'unstack vec-reg)
(decr g-loccnt)
(pop g-locs)
(setq vect-addr vec-reg
index-addr index-reg)
; must be sure that the cc's reflect the value of index-reg
(e-tst index-reg))
; At this point, vect-addr (always vec-reg) contains the location of
; the start of the vector, index-addr (always index-reg) contains
; the index value.
; The condition codes reflect the value of the index.
; First we insure that the index is non negative
; test must use a jmp in case the object file is large
;
(if needlowcheck
then (e-write2 #+(or for-vax for-tahoe) 'jgeq #+for-68k 'jpl oklab)
(e-write2 'jmp 'vecindexerr)
(e-label oklab)
(setq oklab (d-genlab)))
;; now, we compare against the size of the vector
;; the size of the vector is in bytes, we may want to shift this
;; to reflect the size in words or longwords, depending on the
;; type of reference
(if (eq type 'byte)
then ; can compare right away
(e-cmp index-addr `(-8 ,vect-addr))
else ; shift size into temp-reg
(setq size (if (eq type 'word) then 1 else 2))
#+for-vax
(e-write4 'ashl (concat '$- size)
`(-8 ,vect-addr) temp-reg)
#+for-tahoe
(e-write4 'shar (concat '$ size)
`(-8 ,vect-addr) temp-reg)
#+for-68k
(progn
(e-move `(-8 ,vect-addr) temp-reg)
(e-write3 'asrl `($ ,size) temp-reg))
(e-cmp index-addr temp-reg)
(d-clearreg temp-reg))
;; size is the number of objects, the index is 0 based so
;; it must be less than the vector size
(e-write2 #+(or for-vax for-tahoe) 'jlss #+for-68k 'jmi oklab)
(e-write2 'jmp 'vecindexerr)
(e-label oklab)
(if fetchval
then ; unstack the value to store...
(e-move (e-cvt 'unstack) val-reg)
(setq vect-val val-reg))
;; if we get here then the access is in bounds
(if (eq type 'lisp)
then #+(or for-vax for-tahoe)
(e-move vect-val `(0 ,vect-addr ,index-addr))
#+for-68k
(progn
(e-move index-addr temp-reg)
(e-write3 'asll '($ 2) temp-reg)
(e-add vect-addr temp-reg)
(e-move temp-reg temp-areg)
(e-move vect-val `(0 ,temp-areg)))
(if g-loc (e-move vect-val (e-cvt g-loc)))
(if g-cc then (d-handlecc))
else (setq temp (cadr (assq type '((byte movb)
(word movw)
(long movl)))))
#+(or for-vax for-tahoe)
(e-write3 temp vect-val `(0 ,vect-addr ,index-addr))
#+for-68k
(progn
(e-move index-addr temp-reg)
(caseq type
(word (e-write3 'asll '($ 1) temp-reg))
(long (e-write3 'asll '($ 2) temp-reg)))
(e-write3 'lea `(% 0 ,vec-reg ,temp-reg) temp-areg)
(if (eq type 'long)
then (e-write3 temp vect-val `(0 ,temp-areg))
else (e-move vect-val 'd1)
(e-write3 temp 'd1 `(0 ,temp-areg))))
(if g-loc
then (if (eq type 'byte)
then ; all bytes values are within the fixnum
; range, we convert them to immediate
; fixum with ease.
#+for-vax
(progn
(e-write4 'ashl '($ 2)
index-reg index-reg)
(e-write3 'movab
`(5120 ,index-reg)
(e-cvt g-loc)))
#+for-tahoe
(progn
(e-write4 'shal '($ 2)
index-reg index-reg)
(e-write3 'movab
`(5120 ,index-reg)
(e-cvt g-loc)))
#+for-68k
(progn
(e-move index-reg temp-reg)
(e-write3 'asll '($ 2) temp-reg)
(e-move temp-reg temp-areg)
(e-move
(e-cvt '(fixnum 0))
temp-reg)
(e-write3 'lea
`(% 0 ,temp-areg ,temp-reg)
temp-areg)
(e-move
temp-areg
(e-cvt g-loc)))
else ; must convert the hard way
(e-call-qnewint)
(d-clearreg)
(if (not (eq g-loc 'reg))
then (d-move 'reg g-loc)))
; result is always non nil
(if (car g-cc) then (e-goto (car g-cc)))
elseif (car g-cc) then (e-goto (car g-cc))))
(d-vectorindexcode)))
;--- d-vref :: handle all types of vref's
(defun d-vref (type)
;; Generic vector reference. Type is either 'lisp', 'byte', 'word',
;; or 'long'.
(let ((vect (cadr v-form))
(index (caddr v-form))
(vect-addr) (index-addr) (temp) (size)
(vec-reg #+(or for-vax for-tahoe) 'r0 #+for-68k 'a0)
(index-reg '#.fixnum-reg)
(temp-reg #+(or for-vax for-tahoe) 'r4 #+for-68k 'd0)
(temp-areg #+(or for-vax for-tahoe) 'rX #+for-68k 'a1)
(oklab (d-genlab))
(needlowcheck t)) ; t if must check lower index bounds
#+for-68k (d-regused '#.fixnum-reg)
(makecomment `(doing vec ref type ,type))
(if (fixp index)
then (if (<& index 0)
then (comp-err "vector index less than 0 " v-form))
(setq needlowcheck nil))
(if (setq index-addr (d-simple index))
then (let ((g-loc vec-reg) g-cc g-ret)
(d-exp vect))
(setq vect-addr vec-reg) ; the vector op is in vec-reg
; we really want the cdr of index (the actual number).
; if we can do that simply, great. otherwise we
; bring the index into index-reg and then do the cdr ourselves
(if (setq temp (d-simple `(cdr ,index)))
then (d-move temp index-reg)
else (d-move index-addr index-reg)
#+(or for-vax for-tahoe)
(e-move `(0 ,index-reg) index-reg)
#+for-68k
(progn
(e-move index-reg 'a5)
(e-move '(0 a5) index-reg)))
(setq index-addr index-reg)
else ; the index isn't computable simply, so we must
; stack the vector location to keep it safe
(let ((g-loc 'stack) g-cc g-ret)
(d-exp vect))
(push nil g-locs)
(incr g-loccnt)
; compute index's value into index-reg
(d-fixnumexp index)
; now put vector address into vec-reg
(d-move 'unstack vec-reg)
(decr g-loccnt)
(pop g-locs)
(setq vect-addr vec-reg
index-addr index-reg)
; must be sure that the cc's reflect the value of index-reg
(e-tst index-reg))
; at this point, vect-addr (always vec-reg) contains the location of
; the start of the vector, index-addr (always index-reg) contains
; the index value. the condition codes reflect the value of
; the index
; First we insure that the index is non negative
; test must use a jmp in case the object file is large
(if needlowcheck
then (e-write2 #+(or for-vax for-tahoe) 'jgeq #+for-68k 'jpl oklab)
(e-write2 'jmp 'vecindexerr)
(e-label oklab)
(setq oklab (d-genlab)))
; now, we compare against the size of the vector
; the size of the vector is in bytes, we may want to shift this
; to reflect the size in words or longwords, depending on the
; type of reference
(if (eq type 'byte)
then ; can compare right away
(e-cmp index-addr `(-8 ,vect-addr))
else ; shift size into temp-reg
(setq size (if (eq type 'word) then 1 else 2))
#+for-vax
(e-write4 'ashl (concat '$- size) `(-8 ,vect-addr) temp-reg)
#+for-tahoe
(e-write4 'shar (concat '$ size) `(-8 ,vect-addr) temp-reg)
#+for-68k
(progn
(e-move `(-8 ,vect-addr) temp-reg)
(e-write3 'asrl `($ ,size) temp-reg))
(e-cmp index-addr temp-reg)
(d-clearreg temp-reg))
; size is the number of objects, the index is 0 based so
; it must be less than the vector size
(e-write2 #+(or for-vax for-tahoe) 'jlss #+for-68k 'jmi oklab)
(e-write2 'jmp 'vecindexerr)
(e-label oklab)
;; if we get here then the access is in bounds
(if g-loc
then ; we care about the value.
; if the value is one of the fixnum types, then we
; move the value to index-reg so it can be fixnum converted
(if (eq type 'lisp)
then #+(or for-vax for-tahoe)
(e-move `(0 ,vect-addr ,index-addr)
(e-cvt g-loc))
#+for-68k
(progn
(e-move index-addr temp-reg)
(e-write3 'asll '($ 2) temp-reg)
(e-add vect-addr temp-reg)
(e-move temp-reg temp-areg)
(e-move `(0 ,temp-areg) (e-cvt g-loc)))
(if g-cc then (d-handlecc))
else #+(or for-vax for-tahoe)
(progn
(setq temp (cadr (assq type '((byte cvtbl)
(word cvtwl)
(long movl)))))
(e-write3 temp
`(0 ,vect-addr ,index-addr)
index-reg))
#+for-68k
(progn
(setq temp
(cadr (assq type '((byte movb)
(word movw)
(long movl)))))
(caseq type
(word (e-write3 'asll '($ 1) index-reg))
(long (e-write3 'asll '($ 2) index-reg)))
(e-write3 'lea `(% 0 ,vec-reg ,index-reg)
temp-areg)
(if (memq type '(byte word))
then (e-write2 'clrl index-reg))
(e-write3 temp `(0 ,temp-areg) index-reg))
(if (eq type 'byte)
then ; all bytes values are within the fixnum
; range, we convert them to immediate
; fixum with ease.
#+for-vax
(progn
(e-write4 'ashl '($ 2)
index-reg index-reg)
(e-write3 'movab
`(5120 ,index-reg)
(e-cvt g-loc)))
#+for-tahoe
(progn
(e-write4 'shal '($ 2)
index-reg index-reg)
(e-write3 'movab
`(5120 ,index-reg)
(e-cvt g-loc)))
#+for-68k
(progn
(e-write3 'asll '($ 2) index-reg)
(e-move index-reg temp-areg)
(e-move
'($ _nilatom+0x1400)
temp-reg)
(e-write3 'lea
`(% 0 ,temp-areg ,temp-reg)
temp-areg)
(e-move
temp-areg
(e-cvt g-loc)))
else ; must convert the hard way
(e-call-qnewint)
(d-clearreg)
(if (not (eq g-loc 'reg))
then (d-move 'reg g-loc)))
; result is always non nil
(if (car g-cc) then (e-goto (car g-cc))))
elseif g-cc
; we dont care about the value, just whether it nil
then (if (eq type 'lisp)
then #+(or for-vax for-tahoe)
(e-tst `(0 ,vect-addr ,index-addr))
#+for-68k
(progn
(e-move index-addr temp-reg)
(e-write3 'asll '($ 2) temp-reg)
(e-add vect-addr temp-reg)
(e-move temp-reg temp-areg)
(e-cmpnil `(0 ,temp-areg)))
(d-handlecc)
else ; if fixnum, then it is always true
(if (car g-cc) then (e-goto (car g-cc)))))
(d-vectorindexcode)))
;--- d-vectorindexcode :: put out code to call the vector range error.
; At this point the vector is in r0, the index an immediate fixnum in r5
; we call the function int:vector-range-error with two arguments, the
; vector and the index.
;
(defun d-vectorindexcode ()
(if (null g-didvectorcode)
then (let ((afterlab (d-genlab)))
(e-goto afterlab)
(e-label 'vecindexerr)
(d-move #+(or for-vax for-tahoe) 'r0 #+for-68k 'a0 'stack)
(e-call-qnewint)
(d-move 'reg 'stack)
(d-calltran 'int:vector-range-error 2)
; never returns
(e-label afterlab))
(setq g-didvectorcode t)))
;------------------------ vector access functions
;--- cc-vectorp :: check for vectorness
;
(defun cc-vectorp nil
(d-typesimp (cadr v-form) #.(immed-const 18)))
;--- cc-vectorip :: check for vectoriness
;
(defun cc-vectorip nil
(d-typesimp (cadr v-form) #.(immed-const 19)))
;--- c-vsize :: extract vsize
;
(defun c-vsize nil
(d-vectorsize (cadr v-form) '2))
(defun c-vsize-byte nil
(d-vectorsize (cadr v-form) '0))
(defun c-vsize-word nil
(d-vectorsize (cadr v-form) '1))
(defun d-vectorsize (form shift)
(let ((g-loc #+(or for-vax for-tahoe) 'reg #+for-68k 'a0)
g-cc
g-ret)
(d-exp form))
; get size into `fixnum-reg' for fixnum boxing
(if (zerop shift)
then (e-move '(-8 #+(or for-vax for-tahoe) r0 #+for-68k a0) '#.fixnum-reg)
else #+for-vax
(e-write4 'ashl (concat '$- shift) '(-8 r0) '#.fixnum-reg)
#+for-tahoe
(e-write4 'shar (concat '$ shift) '(-8 r0) '#.fixnum-reg)
#+for-68k
(progn
(e-move '(-8 a0) '#.fixnum-reg)
(e-write3 'asrl `($ ,shift) '#.fixnum-reg)))
(e-call-qnewint))