1 ;;; -*- Package: ALPHA -*-
3 ;;; **********************************************************************
4 ;;; This code was written as part of the CMU Common Lisp project at
5 ;;; Carnegie Mellon University, and has been placed in the public domain.
9 ;;; **********************************************************************
11 ;;; This file contains the Alpha definitions for array operations.
13 ;;; Written by William Lott
14 ;;; Conversion by Sean Hallgren
15 ;;; Complex-float support by Douglas Crosher 1998.
21 ;;;; Allocator for the array header.
23 (define-vop (make-array-header)
25 (:translate make-array-header)
26 (:args (type :scs (any-reg))
27 (rank :scs (any-reg)))
28 (:arg-types positive-fixnum positive-fixnum)
29 (:temporary (:scs (any-reg)) bytes)
30 (:temporary (:scs (non-descriptor-reg)) header)
31 (:results (result :scs (descriptor-reg)))
33 (inst addq rank (+ (* array-dimensions-offset word-bytes)
36 (inst li (lognot lowtag-mask) header)
37 (inst and bytes header bytes)
38 (inst addq rank (fixnumize (1- array-dimensions-offset)) header)
39 (inst sll header type-bits header)
40 (inst bis header type header)
41 (inst srl header 2 header)
43 (inst bis alloc-tn other-pointer-type result)
44 (storew header result 0 other-pointer-type)
45 (inst addq alloc-tn bytes alloc-tn))))
49 ;;;; Additional accessors and setters for the array header.
51 (defknown sb!impl::%array-dimension (t index) index
53 (defknown sb!impl::%set-array-dimension (t index index) index
56 (define-full-reffer %array-dimension *
57 array-dimensions-offset other-pointer-type
58 (any-reg) positive-fixnum sb!impl::%array-dimension)
60 (define-full-setter %set-array-dimension *
61 array-dimensions-offset other-pointer-type
62 (any-reg) positive-fixnum sb!impl::%set-array-dimension #+gengc nil)
65 (defknown sb!impl::%array-rank (t) index (flushable))
67 (define-vop (array-rank-vop)
68 (:translate sb!impl::%array-rank)
70 (:args (x :scs (descriptor-reg)))
71 (:temporary (:scs (non-descriptor-reg)) temp)
72 (:results (res :scs (any-reg descriptor-reg)))
74 (loadw temp x 0 other-pointer-type)
75 (inst sra temp type-bits temp)
76 (inst subq temp (1- array-dimensions-offset) temp)
77 (inst sll temp 2 res)))
81 ;;;; Bounds checking routine.
84 (define-vop (check-bound)
85 (:translate %check-bound)
87 (:args (array :scs (descriptor-reg))
88 (bound :scs (any-reg descriptor-reg))
89 (index :scs (any-reg descriptor-reg) :target result))
90 (:results (result :scs (any-reg descriptor-reg)))
91 (:temporary (:scs (non-descriptor-reg)) temp)
93 (:save-p :compute-only)
95 (let ((error (generate-error-code vop invalid-array-index-error
97 (inst cmpult index bound temp)
99 (move index result))))
103 ;;;; Accessors/Setters
105 ;;; Variants built on top of word-index-ref, etc. I.e. those vectors whos
106 ;;; elements are represented in integer registers and are built out of
107 ;;; 8, 16, or 32 bit elements.
109 (macrolet ((def-full-data-vector-frobs (type element-type &rest scs)
111 (define-full-reffer ,(symbolicate "DATA-VECTOR-REF/" type) ,type
112 vector-data-offset other-pointer-type
113 ,(remove-if #'(lambda (x) (member x '(null zero))) scs)
116 (define-full-setter ,(symbolicate "DATA-VECTOR-SET/" type) ,type
117 vector-data-offset other-pointer-type ,scs ,element-type
118 data-vector-set #+gengc ,(if (member 'descriptor-reg scs) t nil))))
120 (def-partial-data-vector-frobs
121 (type element-type size signed &rest scs)
123 (define-partial-reffer ,(symbolicate "DATA-VECTOR-REF/" type) ,type
124 ,size ,signed vector-data-offset other-pointer-type ,scs
125 ,element-type data-vector-ref)
126 (define-partial-setter ,(symbolicate "DATA-VECTOR-SET/" type) ,type
127 ,size vector-data-offset other-pointer-type ,scs
128 ,element-type data-vector-set)))
129 (def-small-data-vector-frobs (type bits)
130 (let* ((elements-per-word (floor word-bits bits))
131 (bit-shift (1- (integer-length elements-per-word))))
133 (define-vop (,(symbolicate 'data-vector-ref/ type))
134 (:note "inline array access")
135 (:translate data-vector-ref)
137 (:args (object :scs (descriptor-reg))
138 (index :scs (unsigned-reg)))
139 (:arg-types ,type positive-fixnum)
140 (:results (value :scs (any-reg)))
141 (:result-types positive-fixnum)
142 (:temporary (:scs (interior-reg)) lip)
143 (:temporary (:scs (non-descriptor-reg) :to (:result 0)) temp result)
145 (inst srl index ,bit-shift temp)
146 (inst sll temp 2 temp)
147 (inst addq object temp lip)
149 (- (* vector-data-offset word-bytes)
152 (inst and index ,(1- elements-per-word) temp)
154 `((inst sll temp ,(1- (integer-length bits)) temp)))
155 (inst srl result temp result)
156 (inst and result ,(1- (ash 1 bits)) result)
157 (inst sll result 2 value)))
158 (define-vop (,(symbolicate 'data-vector-ref-c/ type))
159 (:translate data-vector-ref)
161 (:args (object :scs (descriptor-reg)))
165 ,(1- (* (1+ (- (floor (+ #x7fff
169 elements-per-word)))))
171 (:results (result :scs (unsigned-reg)))
172 (:result-types positive-fixnum)
174 (multiple-value-bind (word extra) (floor index ,elements-per-word)
175 (loadw result object (+ word vector-data-offset)
177 (unless (zerop extra)
178 (inst srl result (* extra ,bits) result))
179 (unless (= extra ,(1- elements-per-word))
180 (inst and result ,(1- (ash 1 bits)) result)))))
181 (define-vop (,(symbolicate 'data-vector-set/ type))
182 (:note "inline array store")
183 (:translate data-vector-set)
185 (:args (object :scs (descriptor-reg))
186 (index :scs (unsigned-reg) :target shift)
187 (value :scs (unsigned-reg zero immediate) :target result))
188 (:arg-types ,type positive-fixnum positive-fixnum)
189 (:results (result :scs (unsigned-reg)))
190 (:result-types positive-fixnum)
191 (:temporary (:scs (interior-reg)) lip)
192 (:temporary (:scs (non-descriptor-reg)) temp old)
193 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) shift)
195 (inst srl index ,bit-shift temp)
196 (inst sll temp 2 temp)
197 (inst addq object temp lip)
199 (- (* vector-data-offset word-bytes)
202 (inst and index ,(1- elements-per-word) shift)
204 `((inst sll shift ,(1- (integer-length bits)) shift)))
205 (unless (and (sc-is value immediate)
206 (= (tn-value value) ,(1- (ash 1 bits))))
207 (inst li ,(1- (ash 1 bits)) temp)
208 (inst sll temp shift temp)
210 (inst and old temp old))
211 (unless (sc-is value zero)
214 (inst li (logand (tn-value value) ,(1- (ash 1 bits))) temp))
216 (inst and value ,(1- (ash 1 bits)) temp)))
217 (inst sll temp shift temp)
218 (inst bis old temp old))
220 (- (* vector-data-offset word-bytes)
225 (inst li (tn-value value) result))
227 (move zero-tn result))
229 (move value result)))))
230 (define-vop (,(symbolicate 'data-vector-set-c/ type))
231 (:translate data-vector-set)
233 (:args (object :scs (descriptor-reg))
234 (value :scs (unsigned-reg zero immediate) :target result))
238 ,(1- (* (1+ (- (floor (+ #x7fff
242 elements-per-word))))
245 (:results (result :scs (unsigned-reg)))
246 (:result-types positive-fixnum)
247 (:temporary (:scs (non-descriptor-reg)) temp old)
249 (multiple-value-bind (word extra) (floor index ,elements-per-word)
251 (- (* (+ word vector-data-offset) word-bytes)
254 (unless (and (sc-is value immediate)
255 (= (tn-value value) ,(1- (ash 1 bits))))
256 (cond ((= extra ,(1- elements-per-word))
257 (inst sll old ,bits old)
258 (inst srl old ,bits old))
261 (lognot (ash ,(1- (ash 1 bits)) (* extra ,bits)))
263 (inst and old temp old))))
267 (let ((value (ash (logand (tn-value value) ,(1- (ash 1 bits)))
269 (cond ((< value #x10000)
270 (inst bis old value old))
273 (inst bis old temp old)))))
275 (inst sll value (* extra ,bits) temp)
276 (inst bis old temp old)))
278 (- (* (+ word vector-data-offset) word-bytes)
283 (inst li (tn-value value) result))
285 (move zero-tn result))
287 (move value result))))))))))
288 (def-full-data-vector-frobs simple-vector *
289 descriptor-reg any-reg null zero)
291 (def-partial-data-vector-frobs simple-string base-char :byte nil
294 (def-partial-data-vector-frobs simple-array-unsigned-byte-8 positive-fixnum
295 :byte nil unsigned-reg signed-reg)
297 (def-partial-data-vector-frobs simple-array-unsigned-byte-16 positive-fixnum
298 :short nil unsigned-reg signed-reg)
300 (def-full-data-vector-frobs simple-array-unsigned-byte-32 unsigned-num
303 (def-partial-data-vector-frobs simple-array-signed-byte-8 tagged-num
306 (def-partial-data-vector-frobs simple-array-signed-byte-16 tagged-num
309 (def-full-data-vector-frobs simple-array-signed-byte-30 tagged-num any-reg)
311 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num signed-reg)
313 ;; Integer vectors whos elements are smaller than a byte. I.e. bit, 2-bit,
314 ;; and 4-bit vectors.
317 (def-small-data-vector-frobs simple-bit-vector 1)
318 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
319 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
322 ;;; And the float variants.
325 (define-vop (data-vector-ref/simple-array-single-float)
326 (:note "inline array access")
327 (:translate data-vector-ref)
329 (:args (object :scs (descriptor-reg))
330 (index :scs (any-reg)))
331 (:arg-types simple-array-single-float positive-fixnum)
332 (:results (value :scs (single-reg)))
333 (:result-types single-float)
334 (:temporary (:scs (interior-reg)) lip)
336 (inst addq object index lip)
338 (- (* vector-data-offset word-bytes)
342 (define-vop (data-vector-set/simple-array-single-float)
343 (:note "inline array store")
344 (:translate data-vector-set)
346 (:args (object :scs (descriptor-reg))
347 (index :scs (any-reg))
348 (value :scs (single-reg) :target result))
349 (:arg-types simple-array-single-float positive-fixnum single-float)
350 (:results (result :scs (single-reg)))
351 (:result-types single-float)
352 (:temporary (:scs (interior-reg)) lip)
354 (inst addq object index lip)
356 (- (* vector-data-offset word-bytes)
359 (unless (location= result value)
360 (inst fmove value result))))
362 (define-vop (data-vector-ref/simple-array-double-float)
363 (:note "inline array access")
364 (:translate data-vector-ref)
366 (:args (object :scs (descriptor-reg))
367 (index :scs (any-reg)))
368 (:arg-types simple-array-double-float positive-fixnum)
369 (:results (value :scs (double-reg)))
370 (:result-types double-float)
371 (:temporary (:scs (interior-reg)) lip)
373 (inst addq object index lip)
374 (inst addq lip index lip)
376 (- (* vector-data-offset word-bytes)
380 (define-vop (data-vector-set/simple-array-double-float)
381 (:note "inline array store")
382 (:translate data-vector-set)
384 (:args (object :scs (descriptor-reg))
385 (index :scs (any-reg))
386 (value :scs (double-reg) :target result))
387 (:arg-types simple-array-double-float positive-fixnum double-float)
388 (:results (result :scs (double-reg)))
389 (:result-types double-float)
390 (:temporary (:scs (interior-reg)) lip)
392 (inst addq object index lip)
393 (inst addq lip index lip)
395 (- (* vector-data-offset word-bytes)
396 other-pointer-type) lip)
397 (unless (location= result value)
398 (inst fmove value result))))
401 ;;; Complex float arrays.
403 (define-vop (data-vector-ref/simple-array-complex-single-float)
404 (:note "inline array access")
405 (:translate data-vector-ref)
407 (:args (object :scs (descriptor-reg))
408 (index :scs (any-reg)))
409 (:arg-types simple-array-complex-single-float positive-fixnum)
410 (:results (value :scs (complex-single-reg)))
411 (:temporary (:scs (interior-reg)) lip)
412 (:result-types complex-single-float)
414 (let ((real-tn (complex-single-reg-real-tn value)))
415 (inst addq object index lip)
416 (inst addq lip index lip)
418 (- (* vector-data-offset word-bytes) other-pointer-type)
420 (let ((imag-tn (complex-single-reg-imag-tn value)))
422 (- (* (1+ vector-data-offset) word-bytes) other-pointer-type)
425 (define-vop (data-vector-set/simple-array-complex-single-float)
426 (:note "inline array store")
427 (:translate data-vector-set)
429 (:args (object :scs (descriptor-reg))
430 (index :scs (any-reg))
431 (value :scs (complex-single-reg) :target result))
432 (:arg-types simple-array-complex-single-float positive-fixnum
433 complex-single-float)
434 (:results (result :scs (complex-single-reg)))
435 (:result-types complex-single-float)
436 (:temporary (:scs (interior-reg)) lip)
438 (let ((value-real (complex-single-reg-real-tn value))
439 (result-real (complex-single-reg-real-tn result)))
440 (inst addq object index lip)
441 (inst addq lip index lip)
443 (- (* vector-data-offset word-bytes) other-pointer-type)
445 (unless (location= result-real value-real)
446 (inst fmove value-real result-real)))
447 (let ((value-imag (complex-single-reg-imag-tn value))
448 (result-imag (complex-single-reg-imag-tn result)))
450 (- (* (1+ vector-data-offset) word-bytes) other-pointer-type)
452 (unless (location= result-imag value-imag)
453 (inst fmove value-imag result-imag)))))
455 (define-vop (data-vector-ref/simple-array-complex-double-float)
456 (:note "inline array access")
457 (:translate data-vector-ref)
459 (:args (object :scs (descriptor-reg))
460 (index :scs (any-reg)))
461 (:arg-types simple-array-complex-double-float positive-fixnum)
462 (:results (value :scs (complex-double-reg)))
463 (:result-types complex-double-float)
464 (:temporary (:scs (interior-reg)) lip)
466 (let ((real-tn (complex-double-reg-real-tn value)))
467 (inst addq object index lip)
468 (inst addq lip index lip)
469 (inst addq lip index lip)
470 (inst addq lip index lip)
472 (- (* vector-data-offset word-bytes) other-pointer-type)
474 (let ((imag-tn (complex-double-reg-imag-tn value)))
476 (- (* (+ vector-data-offset 2) word-bytes) other-pointer-type)
479 (define-vop (data-vector-set/simple-array-complex-double-float)
480 (:note "inline array store")
481 (:translate data-vector-set)
483 (:args (object :scs (descriptor-reg))
484 (index :scs (any-reg))
485 (value :scs (complex-double-reg) :target result))
486 (:arg-types simple-array-complex-double-float positive-fixnum
487 complex-double-float)
488 (:results (result :scs (complex-double-reg)))
489 (:result-types complex-double-float)
490 (:temporary (:scs (interior-reg)) lip)
492 (let ((value-real (complex-double-reg-real-tn value))
493 (result-real (complex-double-reg-real-tn result)))
494 (inst addq object index lip)
495 (inst addq lip index lip)
496 (inst addq lip index lip)
497 (inst addq lip index lip)
499 (- (* vector-data-offset word-bytes) other-pointer-type)
501 (unless (location= result-real value-real)
502 (inst fmove value-real result-real)))
503 (let ((value-imag (complex-double-reg-imag-tn value))
504 (result-imag (complex-double-reg-imag-tn result)))
506 (- (* (+ vector-data-offset 2) word-bytes) other-pointer-type)
508 (unless (location= result-imag value-imag)
509 (inst fmove value-imag result-imag)))))
512 ;;; These VOPs are used for implementing float slots in structures (whose raw
513 ;;; data is an unsigned-32 vector.
515 (define-vop (raw-ref-single data-vector-ref/simple-array-single-float)
516 (:translate %raw-ref-single)
517 (:arg-types simple-array-unsigned-byte-32 positive-fixnum))
519 (define-vop (raw-set-single data-vector-set/simple-array-single-float)
520 (:translate %raw-set-single)
521 (:arg-types simple-array-unsigned-byte-32 positive-fixnum single-float))
523 (define-vop (raw-ref-double data-vector-ref/simple-array-double-float)
524 (:translate %raw-ref-double)
525 (:arg-types simple-array-unsigned-byte-32 positive-fixnum))
527 (define-vop (raw-set-double data-vector-set/simple-array-double-float)
528 (:translate %raw-set-double)
529 (:arg-types simple-array-unsigned-byte-32 positive-fixnum double-float))
531 (define-vop (raw-ref-complex-single
532 data-vector-ref/simple-array-complex-single-float)
533 (:translate %raw-ref-complex-single)
534 (:arg-types simple-array-unsigned-byte-32 positive-fixnum))
536 (define-vop (raw-set-complex-single
537 data-vector-set/simple-array-complex-single-float)
538 (:translate %raw-set-complex-single)
539 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
540 complex-single-float))
542 (define-vop (raw-ref-complex-double
543 data-vector-ref/simple-array-complex-double-float)
544 (:translate %raw-ref-complex-double)
545 (:arg-types simple-array-unsigned-byte-32 positive-fixnum))
547 (define-vop (raw-set-complex-double
548 data-vector-set/simple-array-complex-double-float)
549 (:translate %raw-set-complex-double)
550 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
551 complex-double-float))
554 ;;; These vops are useful for accessing the bits of a vector irrespective of
555 ;;; what type of vector it is.
558 (define-full-reffer raw-bits * 0 other-pointer-type (unsigned-reg) unsigned-num
560 (define-full-setter set-raw-bits * 0 other-pointer-type (unsigned-reg)
561 unsigned-num %set-raw-bits #+gengc nil)
565 ;;;; Misc. Array VOPs.
567 (define-vop (get-vector-subtype get-header-data))
568 (define-vop (set-vector-subtype set-header-data))