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 (+ (* 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-byte-29 positive-fixnum any-reg)
329 (def-full-data-vector-frobs simple-array-signed-byte-30 tagged-num any-reg)
331 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num
334 ;; Integer vectors whos elements are smaller than a byte. I.e. bit,
335 ;; 2-bit, and 4-bit vectors.
336 (def-small-data-vector-frobs simple-bit-vector 1)
337 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
338 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
340 ;;; and the float variants..
342 (define-vop (data-vector-ref/simple-array-single-float)
343 (:note "inline array access")
344 (:translate data-vector-ref)
346 (:args (object :scs (descriptor-reg))
347 (index :scs (any-reg)))
348 (:arg-types simple-array-single-float positive-fixnum)
349 (:results (value :scs (single-reg)))
350 (:result-types single-float)
351 (:temporary (:scs (interior-reg)) lip)
353 (inst addq object index lip)
355 (- (* vector-data-offset n-word-bytes)
356 other-pointer-lowtag)
359 (define-vop (data-vector-set/simple-array-single-float)
360 (:note "inline array store")
361 (:translate data-vector-set)
363 (:args (object :scs (descriptor-reg))
364 (index :scs (any-reg))
365 (value :scs (single-reg) :target result))
366 (:arg-types simple-array-single-float positive-fixnum single-float)
367 (:results (result :scs (single-reg)))
368 (:result-types single-float)
369 (:temporary (:scs (interior-reg)) lip)
371 (inst addq object index lip)
373 (- (* vector-data-offset n-word-bytes)
374 other-pointer-lowtag)
376 (unless (location= result value)
377 (inst fmove value result))))
379 (define-vop (data-vector-ref/simple-array-double-float)
380 (:note "inline array access")
381 (:translate data-vector-ref)
383 (:args (object :scs (descriptor-reg))
384 (index :scs (any-reg)))
385 (:arg-types simple-array-double-float positive-fixnum)
386 (:results (value :scs (double-reg)))
387 (:result-types double-float)
388 (:temporary (:scs (interior-reg)) lip)
390 (inst addq object index lip)
391 (inst addq lip index lip)
393 (- (* vector-data-offset n-word-bytes)
394 other-pointer-lowtag)
397 (define-vop (data-vector-set/simple-array-double-float)
398 (:note "inline array store")
399 (:translate data-vector-set)
401 (:args (object :scs (descriptor-reg))
402 (index :scs (any-reg))
403 (value :scs (double-reg) :target result))
404 (:arg-types simple-array-double-float positive-fixnum double-float)
405 (:results (result :scs (double-reg)))
406 (:result-types double-float)
407 (:temporary (:scs (interior-reg)) lip)
409 (inst addq object index lip)
410 (inst addq lip index lip)
412 (- (* vector-data-offset n-word-bytes)
413 other-pointer-lowtag) lip)
414 (unless (location= result value)
415 (inst fmove value result))))
417 ;;; complex float arrays
419 (define-vop (data-vector-ref/simple-array-complex-single-float)
420 (:note "inline array access")
421 (:translate data-vector-ref)
423 (:args (object :scs (descriptor-reg))
424 (index :scs (any-reg)))
425 (:arg-types simple-array-complex-single-float positive-fixnum)
426 (:results (value :scs (complex-single-reg)))
427 (:temporary (:scs (interior-reg)) lip)
428 (:result-types complex-single-float)
430 (let ((real-tn (complex-single-reg-real-tn value)))
431 (inst addq object index lip)
432 (inst addq lip index lip)
434 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
436 (let ((imag-tn (complex-single-reg-imag-tn value)))
438 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
441 (define-vop (data-vector-set/simple-array-complex-single-float)
442 (:note "inline array store")
443 (:translate data-vector-set)
445 (:args (object :scs (descriptor-reg))
446 (index :scs (any-reg))
447 (value :scs (complex-single-reg) :target result))
448 (:arg-types simple-array-complex-single-float positive-fixnum
449 complex-single-float)
450 (:results (result :scs (complex-single-reg)))
451 (:result-types complex-single-float)
452 (:temporary (:scs (interior-reg)) lip)
454 (let ((value-real (complex-single-reg-real-tn value))
455 (result-real (complex-single-reg-real-tn result)))
456 (inst addq object index lip)
457 (inst addq lip index lip)
459 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
461 (unless (location= result-real value-real)
462 (inst fmove value-real result-real)))
463 (let ((value-imag (complex-single-reg-imag-tn value))
464 (result-imag (complex-single-reg-imag-tn result)))
466 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
468 (unless (location= result-imag value-imag)
469 (inst fmove value-imag result-imag)))))
471 (define-vop (data-vector-ref/simple-array-complex-double-float)
472 (:note "inline array access")
473 (:translate data-vector-ref)
475 (:args (object :scs (descriptor-reg))
476 (index :scs (any-reg)))
477 (:arg-types simple-array-complex-double-float positive-fixnum)
478 (:results (value :scs (complex-double-reg)))
479 (:result-types complex-double-float)
480 (:temporary (:scs (interior-reg)) lip)
482 (let ((real-tn (complex-double-reg-real-tn value)))
483 (inst addq object index lip)
484 (inst addq lip index lip)
485 (inst addq lip index lip)
486 (inst addq lip index lip)
488 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
490 (let ((imag-tn (complex-double-reg-imag-tn value)))
492 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
495 (define-vop (data-vector-set/simple-array-complex-double-float)
496 (:note "inline array store")
497 (:translate data-vector-set)
499 (:args (object :scs (descriptor-reg))
500 (index :scs (any-reg))
501 (value :scs (complex-double-reg) :target result))
502 (:arg-types simple-array-complex-double-float positive-fixnum
503 complex-double-float)
504 (:results (result :scs (complex-double-reg)))
505 (:result-types complex-double-float)
506 (:temporary (:scs (interior-reg)) lip)
508 (let ((value-real (complex-double-reg-real-tn value))
509 (result-real (complex-double-reg-real-tn result)))
510 (inst addq object index lip)
511 (inst addq lip index lip)
512 (inst addq lip index lip)
513 (inst addq lip index lip)
515 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
517 (unless (location= result-real value-real)
518 (inst fmove value-real result-real)))
519 (let ((value-imag (complex-double-reg-imag-tn value))
520 (result-imag (complex-double-reg-imag-tn result)))
522 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
524 (unless (location= result-imag value-imag)
525 (inst fmove value-imag result-imag)))))
528 ;;; These vops are useful for accessing the bits of a vector irrespective of
529 ;;; what type of vector it is.
531 (define-full-reffer raw-bits * 0 other-pointer-lowtag (unsigned-reg) unsigned-num
533 (define-full-setter set-raw-bits * 0 other-pointer-lowtag (unsigned-reg)
534 unsigned-num %set-raw-bits)
535 (define-full-reffer vector-raw-bits * vector-data-offset other-pointer-lowtag
536 (unsigned-reg) unsigned-num %vector-raw-bits)
537 (define-full-setter set-vector-raw-bits * vector-data-offset other-pointer-lowtag
538 (unsigned-reg) unsigned-num %set-vector-raw-bits)
541 ;;;; misc. array VOPs
543 (define-vop (get-vector-subtype get-header-data))
544 (define-vop (set-vector-subtype set-header-data))