home *** CD-ROM | disk | FTP | other *** search
- (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))
-