1 ;;;; the Alpha definitions for array operations
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;;; allocator for the array header
15 (define-vop (make-array-header)
17 (:translate make-array-header)
18 (:args (type :scs (any-reg))
19 (rank :scs (any-reg)))
20 (:arg-types positive-fixnum positive-fixnum)
21 (:temporary (:scs (any-reg)) bytes)
22 (:temporary (:scs (non-descriptor-reg)) header)
23 (:results (result :scs (descriptor-reg)))
25 (inst addq rank (+ (* (1+ array-dimensions-offset) n-word-bytes)
28 (inst li (lognot lowtag-mask) header)
29 (inst and bytes header bytes)
30 (inst addq rank (fixnumize (1- array-dimensions-offset)) header)
31 (inst sll header n-widetag-bits header)
32 (inst bis header type header)
33 (inst srl header n-fixnum-tag-bits header)
35 (inst bis alloc-tn other-pointer-lowtag result)
36 (storew header result 0 other-pointer-lowtag)
37 (inst addq alloc-tn bytes alloc-tn))))
39 ;;;; additional accessors and setters for the array header
40 (define-full-reffer %array-dimension *
41 array-dimensions-offset other-pointer-lowtag
42 (any-reg) positive-fixnum sb!kernel:%array-dimension)
44 (define-full-setter %set-array-dimension *
45 array-dimensions-offset other-pointer-lowtag
46 (any-reg) positive-fixnum sb!kernel:%set-array-dimension #!+gengc nil)
48 (define-vop (array-rank-vop)
49 (:translate sb!kernel:%array-rank)
51 (:args (x :scs (descriptor-reg)))
52 (:temporary (:scs (non-descriptor-reg)) temp)
53 (:results (res :scs (any-reg descriptor-reg)))
55 (loadw temp x 0 other-pointer-lowtag)
56 (inst sra temp n-widetag-bits temp)
57 (inst subq temp (1- array-dimensions-offset) temp)
58 (inst sll temp n-fixnum-tag-bits res)))
60 ;;;; bounds checking routine
61 (define-vop (check-bound)
62 (:translate %check-bound)
64 (:args (array :scs (descriptor-reg))
65 (bound :scs (any-reg descriptor-reg))
66 (index :scs (any-reg descriptor-reg) :target result))
67 (:results (result :scs (any-reg descriptor-reg)))
68 (:temporary (:scs (non-descriptor-reg)) temp)
70 (:save-p :compute-only)
72 (let ((error (generate-error-code vop invalid-array-index-error
74 (inst cmpult index bound temp)
76 (move index result))))
78 ;;;; accessors/setters
80 ;;; Variants built on top of word-index-ref, etc. I.e. those vectors
81 ;;; whose elements are represented in integer registers and are built
82 ;;; out of 8, 16, or 32 bit elements.
83 (macrolet ((def-full-data-vector-frobs (type element-type &rest scs)
85 (define-full-reffer ,(symbolicate "DATA-VECTOR-REF/" type)
87 vector-data-offset other-pointer-lowtag
88 ,(remove-if (lambda (x) (member x '(null zero))) scs)
91 (define-full-setter ,(symbolicate "DATA-VECTOR-SET/" type)
93 vector-data-offset other-pointer-lowtag ,scs ,element-type
94 data-vector-set #+gengc ,(if (member 'descriptor-reg scs)
98 (def-partial-data-vector-frobs
99 (type element-type size signed &rest scs)
101 (define-partial-reffer ,(symbolicate "DATA-VECTOR-REF/" type)
103 ,size ,signed vector-data-offset other-pointer-lowtag ,scs
104 ,element-type data-vector-ref)
105 (define-partial-setter ,(symbolicate "DATA-VECTOR-SET/" type)
107 ,size vector-data-offset other-pointer-lowtag ,scs
108 ,element-type data-vector-set)))
109 (def-small-data-vector-frobs (type bits)
110 (let* ((elements-per-word (floor n-word-bits bits))
111 (bit-shift (1- (integer-length elements-per-word))))
113 (define-vop (,(symbolicate 'data-vector-ref/ type))
114 (:note "inline array access")
115 (:translate data-vector-ref)
117 (:args (object :scs (descriptor-reg))
118 (index :scs (unsigned-reg)))
119 (:arg-types ,type positive-fixnum)
120 (:results (value :scs (any-reg)))
121 (:result-types positive-fixnum)
122 (:temporary (:scs (interior-reg)) lip)
123 (:temporary (:scs (non-descriptor-reg) :to (:result 0))
126 (inst srl index ,bit-shift temp)
127 (inst sll temp n-fixnum-tag-bits temp)
128 (inst addq object temp lip)
130 (- (* vector-data-offset n-word-bytes)
131 other-pointer-lowtag)
133 (inst and index ,(1- elements-per-word) temp)
136 ,(1- (integer-length bits)) temp)))
137 (inst srl result temp result)
138 (inst and result ,(1- (ash 1 bits)) result)
139 (inst sll result n-fixnum-tag-bits value)))
140 (define-vop (,(symbolicate 'data-vector-ref-c/ type))
141 (:translate data-vector-ref)
143 (:args (object :scs (descriptor-reg)))
147 ,(1- (* (1+ (- (floor (+ #x7fff
148 other-pointer-lowtag)
151 elements-per-word)))))
153 (:results (result :scs (unsigned-reg)))
154 (:result-types positive-fixnum)
156 (multiple-value-bind (word extra)
157 (floor index ,elements-per-word)
158 (loadw result object (+ word
160 other-pointer-lowtag)
161 (unless (zerop extra)
162 (inst srl result (* extra ,bits) result))
163 (unless (= extra ,(1- elements-per-word))
164 (inst and result ,(1- (ash 1 bits))
166 (define-vop (,(symbolicate 'data-vector-set/ type))
167 (:note "inline array store")
168 (:translate data-vector-set)
170 (:args (object :scs (descriptor-reg))
171 (index :scs (unsigned-reg) :target shift)
172 (value :scs (unsigned-reg zero immediate)
174 (:arg-types ,type positive-fixnum positive-fixnum)
175 (:results (result :scs (unsigned-reg)))
176 (:result-types positive-fixnum)
177 (:temporary (:scs (interior-reg)) lip)
178 (:temporary (:scs (non-descriptor-reg)) temp old)
179 (:temporary (:scs (non-descriptor-reg)
180 :from (:argument 1)) shift)
182 (inst srl index ,bit-shift temp)
183 (inst sll temp n-fixnum-tag-bits temp)
184 (inst addq object temp lip)
186 (- (* vector-data-offset n-word-bytes)
187 other-pointer-lowtag)
189 (inst and index ,(1- elements-per-word) shift)
191 `((inst sll shift ,(1- (integer-length
194 (unless (and (sc-is value immediate)
197 (inst li ,(1- (ash 1 bits)) temp)
198 (inst sll temp shift temp)
200 (inst and old temp old))
201 (unless (sc-is value zero)
205 (logand (tn-value value)
212 (inst sll temp shift temp)
213 (inst bis old temp old))
215 (- (* vector-data-offset n-word-bytes)
216 other-pointer-lowtag)
220 (inst li (tn-value value) result))
222 (move zero-tn result))
224 (move value result)))))
225 (define-vop (,(symbolicate 'data-vector-set-c/ type))
226 (:translate data-vector-set)
228 (:args (object :scs (descriptor-reg))
229 (value :scs (unsigned-reg zero immediate)
234 ,(1- (* (1+ (- (floor (+ #x7fff
235 other-pointer-lowtag)
238 elements-per-word))))
241 (:results (result :scs (unsigned-reg)))
242 (:result-types positive-fixnum)
243 (:temporary (:scs (non-descriptor-reg)) temp old)
245 (multiple-value-bind (word extra)
246 (floor index ,elements-per-word)
248 (- (* (+ word vector-data-offset)
250 other-pointer-lowtag)
252 (unless (and (sc-is value immediate)
256 (cl:= sb-vm:n-word-bits sb-vm:n-machine-word-bits)
258 ((= extra ,(1- elements-per-word))
259 (inst sll old ,bits old)
260 (inst srl old ,bits old))
263 (lognot (ash ,(1- (ash 1
267 (inst and old temp old))))
272 (ash (logand (tn-value
278 (cond ((< value #x100)
279 (inst bis old value old))
282 (inst bis old temp old)))))
284 (inst sll value (* extra ,bits)
286 (inst bis old temp old)))
288 (- (* (+ word vector-data-offset)
290 other-pointer-lowtag)
294 (inst li (tn-value value) result))
296 (move zero-tn result))
298 (move value result))))))))))
299 (def-full-data-vector-frobs simple-vector *
300 descriptor-reg any-reg null zero)
302 (def-partial-data-vector-frobs simple-base-string character :byte nil
304 #!+sb-unicode ; FIXME: what about when a word is 64 bits?
305 (def-full-data-vector-frobs simple-character-string character character-reg)
307 (def-partial-data-vector-frobs simple-array-unsigned-byte-7 positive-fixnum
308 :byte nil unsigned-reg signed-reg)
309 (def-partial-data-vector-frobs simple-array-unsigned-byte-8 positive-fixnum
310 :byte nil unsigned-reg signed-reg)
312 (def-partial-data-vector-frobs simple-array-unsigned-byte-15 positive-fixnum
313 :short nil unsigned-reg signed-reg)
314 (def-partial-data-vector-frobs simple-array-unsigned-byte-16 positive-fixnum
315 :short nil unsigned-reg signed-reg)
317 (def-full-data-vector-frobs simple-array-unsigned-byte-31 unsigned-num
319 (def-full-data-vector-frobs simple-array-unsigned-byte-32 unsigned-num
322 (def-partial-data-vector-frobs simple-array-signed-byte-8 tagged-num
325 (def-partial-data-vector-frobs simple-array-signed-byte-16 tagged-num
328 (def-full-data-vector-frobs simple-array-unsigned-fixnum positive-fixnum
330 (def-full-data-vector-frobs simple-array-fixnum tagged-num any-reg)
332 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num
335 ;; Integer vectors whos elements are smaller than a byte. I.e. bit,
336 ;; 2-bit, and 4-bit vectors.
337 (def-small-data-vector-frobs simple-bit-vector 1)
338 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
339 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
341 ;;; and the float variants..
343 (define-vop (data-vector-ref/simple-array-single-float)
344 (:note "inline array access")
345 (:translate data-vector-ref)
347 (:args (object :scs (descriptor-reg))
348 (index :scs (any-reg)))
349 (:arg-types simple-array-single-float positive-fixnum)
350 (:results (value :scs (single-reg)))
351 (:result-types single-float)
352 (:temporary (:scs (interior-reg)) lip)
354 (inst addq object index lip)
356 (- (* vector-data-offset n-word-bytes)
357 other-pointer-lowtag)
360 (define-vop (data-vector-set/simple-array-single-float)
361 (:note "inline array store")
362 (:translate data-vector-set)
364 (:args (object :scs (descriptor-reg))
365 (index :scs (any-reg))
366 (value :scs (single-reg) :target result))
367 (:arg-types simple-array-single-float positive-fixnum single-float)
368 (:results (result :scs (single-reg)))
369 (:result-types single-float)
370 (:temporary (:scs (interior-reg)) lip)
372 (inst addq object index lip)
374 (- (* vector-data-offset n-word-bytes)
375 other-pointer-lowtag)
377 (unless (location= result value)
378 (inst fmove value result))))
380 (define-vop (data-vector-ref/simple-array-double-float)
381 (:note "inline array access")
382 (:translate data-vector-ref)
384 (:args (object :scs (descriptor-reg))
385 (index :scs (any-reg)))
386 (:arg-types simple-array-double-float positive-fixnum)
387 (:results (value :scs (double-reg)))
388 (:result-types double-float)
389 (:temporary (:scs (interior-reg)) lip)
391 (inst addq object index lip)
392 (inst addq lip index lip)
394 (- (* vector-data-offset n-word-bytes)
395 other-pointer-lowtag)
398 (define-vop (data-vector-set/simple-array-double-float)
399 (:note "inline array store")
400 (:translate data-vector-set)
402 (:args (object :scs (descriptor-reg))
403 (index :scs (any-reg))
404 (value :scs (double-reg) :target result))
405 (:arg-types simple-array-double-float positive-fixnum double-float)
406 (:results (result :scs (double-reg)))
407 (:result-types double-float)
408 (:temporary (:scs (interior-reg)) lip)
410 (inst addq object index lip)
411 (inst addq lip index lip)
413 (- (* vector-data-offset n-word-bytes)
414 other-pointer-lowtag) lip)
415 (unless (location= result value)
416 (inst fmove value result))))
418 ;;; complex float arrays
420 (define-vop (data-vector-ref/simple-array-complex-single-float)
421 (:note "inline array access")
422 (:translate data-vector-ref)
424 (:args (object :scs (descriptor-reg))
425 (index :scs (any-reg)))
426 (:arg-types simple-array-complex-single-float positive-fixnum)
427 (:results (value :scs (complex-single-reg)))
428 (:temporary (:scs (interior-reg)) lip)
429 (:result-types complex-single-float)
431 (let ((real-tn (complex-single-reg-real-tn value)))
432 (inst addq object index lip)
433 (inst addq lip index lip)
435 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
437 (let ((imag-tn (complex-single-reg-imag-tn value)))
439 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
442 (define-vop (data-vector-set/simple-array-complex-single-float)
443 (:note "inline array store")
444 (:translate data-vector-set)
446 (:args (object :scs (descriptor-reg))
447 (index :scs (any-reg))
448 (value :scs (complex-single-reg) :target result))
449 (:arg-types simple-array-complex-single-float positive-fixnum
450 complex-single-float)
451 (:results (result :scs (complex-single-reg)))
452 (:result-types complex-single-float)
453 (:temporary (:scs (interior-reg)) lip)
455 (let ((value-real (complex-single-reg-real-tn value))
456 (result-real (complex-single-reg-real-tn result)))
457 (inst addq object index lip)
458 (inst addq lip index lip)
460 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
462 (unless (location= result-real value-real)
463 (inst fmove value-real result-real)))
464 (let ((value-imag (complex-single-reg-imag-tn value))
465 (result-imag (complex-single-reg-imag-tn result)))
467 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
469 (unless (location= result-imag value-imag)
470 (inst fmove value-imag result-imag)))))
472 (define-vop (data-vector-ref/simple-array-complex-double-float)
473 (:note "inline array access")
474 (:translate data-vector-ref)
476 (:args (object :scs (descriptor-reg))
477 (index :scs (any-reg)))
478 (:arg-types simple-array-complex-double-float positive-fixnum)
479 (:results (value :scs (complex-double-reg)))
480 (:result-types complex-double-float)
481 (:temporary (:scs (interior-reg)) lip)
483 (let ((real-tn (complex-double-reg-real-tn value)))
484 (inst addq object index lip)
485 (inst addq lip index lip)
486 (inst addq lip index lip)
487 (inst addq lip index lip)
489 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
491 (let ((imag-tn (complex-double-reg-imag-tn value)))
493 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
496 (define-vop (data-vector-set/simple-array-complex-double-float)
497 (:note "inline array store")
498 (:translate data-vector-set)
500 (:args (object :scs (descriptor-reg))
501 (index :scs (any-reg))
502 (value :scs (complex-double-reg) :target result))
503 (:arg-types simple-array-complex-double-float positive-fixnum
504 complex-double-float)
505 (:results (result :scs (complex-double-reg)))
506 (:result-types complex-double-float)
507 (:temporary (:scs (interior-reg)) lip)
509 (let ((value-real (complex-double-reg-real-tn value))
510 (result-real (complex-double-reg-real-tn result)))
511 (inst addq object index lip)
512 (inst addq lip index lip)
513 (inst addq lip index lip)
514 (inst addq lip index lip)
516 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
518 (unless (location= result-real value-real)
519 (inst fmove value-real result-real)))
520 (let ((value-imag (complex-double-reg-imag-tn value))
521 (result-imag (complex-double-reg-imag-tn result)))
523 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
525 (unless (location= result-imag value-imag)
526 (inst fmove value-imag result-imag)))))
529 ;;; These vops are useful for accessing the bits of a vector irrespective of
530 ;;; what type of vector it is.
532 (define-full-reffer vector-raw-bits * vector-data-offset other-pointer-lowtag
533 (unsigned-reg) unsigned-num %vector-raw-bits)
534 (define-full-setter set-vector-raw-bits * vector-data-offset other-pointer-lowtag
535 (unsigned-reg) unsigned-num %set-vector-raw-bits)
538 ;;;; misc. array VOPs
540 (define-vop (get-vector-subtype get-header-data))
541 (define-vop (set-vector-subtype set-header-data))