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)
255 (cond ((= extra ,(1- elements-per-word))
256 (inst sll old ,bits old)
257 (inst srl old ,bits old))
260 (lognot (ash ,(1- (ash 1
264 (inst and old temp old))))
269 (ash (logand (tn-value
275 (cond ((< value #x100)
276 (inst bis old value old))
279 (inst bis old temp old)))))
281 (inst sll value (* extra ,bits)
283 (inst bis old temp old)))
285 (- (* (+ word vector-data-offset)
287 other-pointer-lowtag)
291 (inst li (tn-value value) result))
293 (move zero-tn result))
295 (move value result))))))))))
296 (def-full-data-vector-frobs simple-vector *
297 descriptor-reg any-reg null zero)
299 (def-partial-data-vector-frobs simple-base-string character :byte nil
301 #!+sb-unicode ; FIXME: what about when a word is 64 bits?
302 (def-full-data-vector-frobs simple-character-string character character-reg)
304 (def-partial-data-vector-frobs simple-array-unsigned-byte-7 positive-fixnum
305 :byte nil unsigned-reg signed-reg)
306 (def-partial-data-vector-frobs simple-array-unsigned-byte-8 positive-fixnum
307 :byte nil unsigned-reg signed-reg)
309 (def-partial-data-vector-frobs simple-array-unsigned-byte-15 positive-fixnum
310 :short nil unsigned-reg signed-reg)
311 (def-partial-data-vector-frobs simple-array-unsigned-byte-16 positive-fixnum
312 :short nil unsigned-reg signed-reg)
314 (def-full-data-vector-frobs simple-array-unsigned-byte-31 unsigned-num
316 (def-full-data-vector-frobs simple-array-unsigned-byte-32 unsigned-num
319 (def-partial-data-vector-frobs simple-array-signed-byte-8 tagged-num
322 (def-partial-data-vector-frobs simple-array-signed-byte-16 tagged-num
325 (def-full-data-vector-frobs simple-array-unsigned-byte-29 positive-fixnum any-reg)
326 (def-full-data-vector-frobs simple-array-signed-byte-30 tagged-num any-reg)
328 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num
331 ;; Integer vectors whos elements are smaller than a byte. I.e. bit,
332 ;; 2-bit, and 4-bit vectors.
333 (def-small-data-vector-frobs simple-bit-vector 1)
334 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
335 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
337 ;;; and the float variants..
339 (define-vop (data-vector-ref/simple-array-single-float)
340 (:note "inline array access")
341 (:translate data-vector-ref)
343 (:args (object :scs (descriptor-reg))
344 (index :scs (any-reg)))
345 (:arg-types simple-array-single-float positive-fixnum)
346 (:results (value :scs (single-reg)))
347 (:result-types single-float)
348 (:temporary (:scs (interior-reg)) lip)
350 (inst addq object index lip)
352 (- (* vector-data-offset n-word-bytes)
353 other-pointer-lowtag)
356 (define-vop (data-vector-set/simple-array-single-float)
357 (:note "inline array store")
358 (:translate data-vector-set)
360 (:args (object :scs (descriptor-reg))
361 (index :scs (any-reg))
362 (value :scs (single-reg) :target result))
363 (:arg-types simple-array-single-float positive-fixnum single-float)
364 (:results (result :scs (single-reg)))
365 (:result-types single-float)
366 (:temporary (:scs (interior-reg)) lip)
368 (inst addq object index lip)
370 (- (* vector-data-offset n-word-bytes)
371 other-pointer-lowtag)
373 (unless (location= result value)
374 (inst fmove value result))))
376 (define-vop (data-vector-ref/simple-array-double-float)
377 (:note "inline array access")
378 (:translate data-vector-ref)
380 (:args (object :scs (descriptor-reg))
381 (index :scs (any-reg)))
382 (:arg-types simple-array-double-float positive-fixnum)
383 (:results (value :scs (double-reg)))
384 (:result-types double-float)
385 (:temporary (:scs (interior-reg)) lip)
387 (inst addq object index lip)
388 (inst addq lip index lip)
390 (- (* vector-data-offset n-word-bytes)
391 other-pointer-lowtag)
394 (define-vop (data-vector-set/simple-array-double-float)
395 (:note "inline array store")
396 (:translate data-vector-set)
398 (:args (object :scs (descriptor-reg))
399 (index :scs (any-reg))
400 (value :scs (double-reg) :target result))
401 (:arg-types simple-array-double-float positive-fixnum double-float)
402 (:results (result :scs (double-reg)))
403 (:result-types double-float)
404 (:temporary (:scs (interior-reg)) lip)
406 (inst addq object index lip)
407 (inst addq lip index lip)
409 (- (* vector-data-offset n-word-bytes)
410 other-pointer-lowtag) lip)
411 (unless (location= result value)
412 (inst fmove value result))))
414 ;;; complex float arrays
416 (define-vop (data-vector-ref/simple-array-complex-single-float)
417 (:note "inline array access")
418 (:translate data-vector-ref)
420 (:args (object :scs (descriptor-reg))
421 (index :scs (any-reg)))
422 (:arg-types simple-array-complex-single-float positive-fixnum)
423 (:results (value :scs (complex-single-reg)))
424 (:temporary (:scs (interior-reg)) lip)
425 (:result-types complex-single-float)
427 (let ((real-tn (complex-single-reg-real-tn value)))
428 (inst addq object index lip)
429 (inst addq lip index lip)
431 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
433 (let ((imag-tn (complex-single-reg-imag-tn value)))
435 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
438 (define-vop (data-vector-set/simple-array-complex-single-float)
439 (:note "inline array store")
440 (:translate data-vector-set)
442 (:args (object :scs (descriptor-reg))
443 (index :scs (any-reg))
444 (value :scs (complex-single-reg) :target result))
445 (:arg-types simple-array-complex-single-float positive-fixnum
446 complex-single-float)
447 (:results (result :scs (complex-single-reg)))
448 (:result-types complex-single-float)
449 (:temporary (:scs (interior-reg)) lip)
451 (let ((value-real (complex-single-reg-real-tn value))
452 (result-real (complex-single-reg-real-tn result)))
453 (inst addq object index lip)
454 (inst addq lip index lip)
456 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
458 (unless (location= result-real value-real)
459 (inst fmove value-real result-real)))
460 (let ((value-imag (complex-single-reg-imag-tn value))
461 (result-imag (complex-single-reg-imag-tn result)))
463 (- (* (1+ vector-data-offset) n-word-bytes) other-pointer-lowtag)
465 (unless (location= result-imag value-imag)
466 (inst fmove value-imag result-imag)))))
468 (define-vop (data-vector-ref/simple-array-complex-double-float)
469 (:note "inline array access")
470 (:translate data-vector-ref)
472 (:args (object :scs (descriptor-reg))
473 (index :scs (any-reg)))
474 (:arg-types simple-array-complex-double-float positive-fixnum)
475 (:results (value :scs (complex-double-reg)))
476 (:result-types complex-double-float)
477 (:temporary (:scs (interior-reg)) lip)
479 (let ((real-tn (complex-double-reg-real-tn value)))
480 (inst addq object index lip)
481 (inst addq lip index lip)
482 (inst addq lip index lip)
483 (inst addq lip index lip)
485 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
487 (let ((imag-tn (complex-double-reg-imag-tn value)))
489 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
492 (define-vop (data-vector-set/simple-array-complex-double-float)
493 (:note "inline array store")
494 (:translate data-vector-set)
496 (:args (object :scs (descriptor-reg))
497 (index :scs (any-reg))
498 (value :scs (complex-double-reg) :target result))
499 (:arg-types simple-array-complex-double-float positive-fixnum
500 complex-double-float)
501 (:results (result :scs (complex-double-reg)))
502 (:result-types complex-double-float)
503 (:temporary (:scs (interior-reg)) lip)
505 (let ((value-real (complex-double-reg-real-tn value))
506 (result-real (complex-double-reg-real-tn result)))
507 (inst addq object index lip)
508 (inst addq lip index lip)
509 (inst addq lip index lip)
510 (inst addq lip index lip)
512 (- (* vector-data-offset n-word-bytes) other-pointer-lowtag)
514 (unless (location= result-real value-real)
515 (inst fmove value-real result-real)))
516 (let ((value-imag (complex-double-reg-imag-tn value))
517 (result-imag (complex-double-reg-imag-tn result)))
519 (- (* (+ vector-data-offset 2) n-word-bytes) other-pointer-lowtag)
521 (unless (location= result-imag value-imag)
522 (inst fmove value-imag result-imag)))))
525 ;;; These VOPs are used for implementing float slots in structures
526 ;;; (whose raw data is an unsigned-32 vector).
528 (define-vop (raw-ref-single data-vector-ref/simple-array-single-float)
529 (:translate %raw-ref-single)
530 (:arg-types sb!c::raw-vector positive-fixnum))
532 (define-vop (raw-set-single data-vector-set/simple-array-single-float)
533 (:translate %raw-set-single)
534 (:arg-types sb!c::raw-vector positive-fixnum single-float))
536 (define-vop (raw-ref-double data-vector-ref/simple-array-double-float)
537 (:translate %raw-ref-double)
538 (:arg-types sb!c::raw-vector positive-fixnum))
540 (define-vop (raw-set-double data-vector-set/simple-array-double-float)
541 (:translate %raw-set-double)
542 (:arg-types sb!c::raw-vector positive-fixnum double-float))
544 (define-vop (raw-ref-complex-single
545 data-vector-ref/simple-array-complex-single-float)
546 (:translate %raw-ref-complex-single)
547 (:arg-types sb!c::raw-vector positive-fixnum))
549 (define-vop (raw-set-complex-single
550 data-vector-set/simple-array-complex-single-float)
551 (:translate %raw-set-complex-single)
552 (:arg-types sb!c::raw-vector positive-fixnum complex-single-float))
554 (define-vop (raw-ref-complex-double
555 data-vector-ref/simple-array-complex-double-float)
556 (:translate %raw-ref-complex-double)
557 (:arg-types sb!c::raw-vector positive-fixnum))
559 (define-vop (raw-set-complex-double
560 data-vector-set/simple-array-complex-double-float)
561 (:translate %raw-set-complex-double)
562 (:arg-types sb!c::raw-vector positive-fixnum complex-double-float))
564 ;;; These vops are useful for accessing the bits of a vector irrespective of
565 ;;; what type of vector it is.
567 (define-full-reffer raw-bits * 0 other-pointer-lowtag (unsigned-reg) unsigned-num
569 (define-full-setter set-raw-bits * 0 other-pointer-lowtag (unsigned-reg)
570 unsigned-num %set-raw-bits #+gengc nil)
573 ;;;; misc. array VOPs
575 (define-vop (get-vector-subtype get-header-data))
576 (define-vop (set-vector-subtype set-header-data))