1 ;;;; the Sparc 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)
16 (:translate make-array-header)
18 (:args (type :scs (any-reg))
19 (rank :scs (any-reg)))
20 (:arg-types tagged-num tagged-num)
21 (:temporary (:scs (descriptor-reg) :to (:result 0) :target result) header)
22 (:temporary (:scs (non-descriptor-reg)) ndescr)
23 (:temporary (:scs (non-descriptor-reg)) gencgc-temp)
24 (:results (result :scs (descriptor-reg)))
27 (inst add ndescr rank (+ (* (1+ array-dimensions-offset) n-word-bytes)
29 (inst andn ndescr lowtag-mask)
30 (allocation header ndescr other-pointer-lowtag :temp-tn gencgc-temp)
31 (inst add ndescr rank (fixnumize (1- array-dimensions-offset)))
32 (inst sll ndescr ndescr n-widetag-bits)
33 (inst or ndescr ndescr type)
34 ;; Remove the extraneous fixnum tag bits because TYPE and RANK
36 (inst srl ndescr ndescr n-fixnum-tag-bits)
37 (storew ndescr header 0 other-pointer-lowtag))
38 (move result header)))
40 ;;;; Additional accessors and setters for the array header.
41 (define-vop (%array-dimension word-index-ref)
42 (:translate sb!kernel:%array-dimension)
44 (:variant array-dimensions-offset other-pointer-lowtag))
46 (define-vop (%set-array-dimension word-index-set)
47 (:translate sb!kernel:%set-array-dimension)
49 (:variant array-dimensions-offset other-pointer-lowtag))
51 (define-vop (array-rank-vop)
52 (:translate sb!kernel:%array-rank)
54 (:args (x :scs (descriptor-reg)))
55 (:temporary (:scs (non-descriptor-reg)) temp)
56 (:results (res :scs (any-reg descriptor-reg)))
58 (loadw temp x 0 other-pointer-lowtag)
59 (inst sra temp n-widetag-bits)
60 (inst sub temp (1- array-dimensions-offset))
61 (inst sll res temp n-fixnum-tag-bits)))
63 ;;;; Bounds checking routine.
64 (define-vop (check-bound)
65 (:translate %check-bound)
67 (:args (array :scs (descriptor-reg))
68 (bound :scs (any-reg descriptor-reg))
69 (index :scs (any-reg descriptor-reg) :target result))
70 (:results (result :scs (any-reg descriptor-reg)))
72 (:save-p :compute-only)
74 (let ((error (generate-error-code vop invalid-array-index-error
76 (inst cmp index bound)
79 (move result index))))
81 ;;;; Accessors/Setters
83 ;;; Variants built on top of word-index-ref, etc. I.e. those vectors whos
84 ;;; elements are represented in integer registers and are built out of
85 ;;; 8, 16, or 32 bit elements.
86 (macrolet ((def-data-vector-frobs (type variant element-type &rest scs)
88 (define-vop (,(symbolicate "DATA-VECTOR-REF/" (string type))
89 ,(symbolicate (string variant) "-REF"))
90 (:note "inline array access")
91 (:variant vector-data-offset other-pointer-lowtag)
92 (:translate data-vector-ref)
93 (:arg-types ,type positive-fixnum)
94 (:results (value :scs ,scs))
95 (:result-types ,element-type))
96 (define-vop (,(symbolicate "DATA-VECTOR-SET/" (string type))
97 ,(symbolicate (string variant) "-SET"))
98 (:note "inline array store")
99 (:variant vector-data-offset other-pointer-lowtag)
100 (:translate data-vector-set)
101 (:arg-types ,type positive-fixnum ,element-type)
102 (:args (object :scs (descriptor-reg))
103 (index :scs (any-reg zero immediate))
105 (:results (result :scs ,scs))
106 (:result-types ,element-type)))))
108 (def-data-vector-frobs simple-base-string byte-index
109 character character-reg)
111 (def-data-vector-frobs simple-character-string word-index
112 character character-reg)
113 (def-data-vector-frobs simple-vector word-index
114 * descriptor-reg any-reg)
116 (def-data-vector-frobs simple-array-unsigned-byte-7 byte-index
117 positive-fixnum unsigned-reg)
118 (def-data-vector-frobs simple-array-unsigned-byte-8 byte-index
119 positive-fixnum unsigned-reg)
120 (def-data-vector-frobs simple-array-unsigned-byte-15 halfword-index
121 positive-fixnum unsigned-reg)
122 (def-data-vector-frobs simple-array-unsigned-byte-16 halfword-index
123 positive-fixnum unsigned-reg)
124 (def-data-vector-frobs simple-array-unsigned-byte-31 word-index
125 unsigned-num unsigned-reg)
126 (def-data-vector-frobs simple-array-unsigned-byte-32 word-index
127 unsigned-num unsigned-reg)
129 (def-data-vector-frobs simple-array-unsigned-fixnum word-index
130 positive-fixnum any-reg)
131 (def-data-vector-frobs simple-array-fixnum word-index
133 (def-data-vector-frobs simple-array-signed-byte-32 word-index
134 signed-num signed-reg))
136 ;;; Integer vectors whose elements are smaller than a byte. I.e. bit, 2-bit,
137 ;;; and 4-bit vectors.
138 (macrolet ((def-small-data-vector-frobs (type bits)
139 (let* ((elements-per-word (floor n-word-bits bits))
140 (bit-shift (1- (integer-length elements-per-word))))
142 (define-vop (,(symbolicate "DATA-VECTOR-REF/" type))
143 (:note "inline array access")
144 (:translate data-vector-ref)
146 (:args (object :scs (descriptor-reg))
147 (index :scs (unsigned-reg)))
148 (:arg-types ,type positive-fixnum)
149 (:results (value :scs (any-reg)))
150 (:result-types positive-fixnum)
151 (:temporary (:scs (non-descriptor-reg) :to (:result 0)) temp result)
153 (inst srl temp index ,bit-shift)
154 (inst sll temp n-fixnum-tag-bits)
155 (inst add temp (- (* vector-data-offset n-word-bytes)
156 other-pointer-lowtag))
157 (inst ld result object temp)
158 (inst and temp index ,(1- elements-per-word))
159 (inst xor temp ,(1- elements-per-word))
161 `((inst sll temp ,(1- (integer-length bits)))))
162 (inst srl result temp)
163 (inst and result ,(1- (ash 1 bits)))
164 (inst sll value result 2)))
165 (define-vop (,(symbolicate "DATA-VECTOR-REF-C/" type))
166 (:translate data-vector-ref)
168 (:args (object :scs (descriptor-reg)))
169 (:arg-types ,type (:constant index))
171 (:results (result :scs (unsigned-reg)))
172 (:result-types positive-fixnum)
173 (:temporary (:scs (non-descriptor-reg)) temp)
175 (multiple-value-bind (word extra)
176 (floor index ,elements-per-word)
177 (setf extra (logxor extra (1- ,elements-per-word)))
178 (let ((offset (- (* (+ word vector-data-offset) n-word-bytes)
179 other-pointer-lowtag)))
180 (cond ((typep offset '(signed-byte 13))
181 (inst ld result object offset))
183 (inst li temp offset)
184 (inst ld result object temp))))
185 (unless (zerop extra)
186 (inst srl result (* extra ,bits)))
187 (unless (= extra ,(1- elements-per-word))
188 (inst and result ,(1- (ash 1 bits)))))))
189 (define-vop (,(symbolicate "DATA-VECTOR-SET/" type))
190 (:note "inline array store")
191 (:translate data-vector-set)
193 (:args (object :scs (descriptor-reg))
194 (index :scs (unsigned-reg) :target shift)
195 (value :scs (unsigned-reg zero immediate) :target result))
196 (:arg-types ,type positive-fixnum positive-fixnum)
197 (:results (result :scs (unsigned-reg)))
198 (:result-types positive-fixnum)
199 (:temporary (:scs (non-descriptor-reg)) temp old offset)
200 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) shift)
202 (inst srl offset index ,bit-shift)
203 (inst sll offset n-fixnum-tag-bits)
204 (inst add offset (- (* vector-data-offset n-word-bytes)
205 other-pointer-lowtag))
206 (inst ld old object offset)
207 (inst and shift index ,(1- elements-per-word))
208 (inst xor shift ,(1- elements-per-word))
210 `((inst sll shift ,(1- (integer-length bits)))))
211 (unless (and (sc-is value immediate)
212 (= (tn-value value) ,(1- (ash 1 bits))))
213 (inst li temp ,(1- (ash 1 bits)))
214 (inst sll temp shift)
217 (unless (sc-is value zero)
220 (inst li temp (logand (tn-value value) ,(1- (ash 1 bits)))))
222 (inst and temp value ,(1- (ash 1 bits)))))
223 (inst sll temp shift)
225 (inst st old object offset)
228 (inst li result (tn-value value)))
230 (move result value)))))
231 (define-vop (,(symbolicate "DATA-VECTOR-SET-C/" type))
232 (:translate data-vector-set)
234 (:args (object :scs (descriptor-reg))
235 (value :scs (unsigned-reg zero immediate) :target result))
240 (:results (result :scs (unsigned-reg)))
241 (:result-types positive-fixnum)
242 (:temporary (:scs (non-descriptor-reg)) offset-reg temp old)
244 (multiple-value-bind (word extra) (floor index ,elements-per-word)
245 (let ((offset (- (* (+ word vector-data-offset) n-word-bytes)
246 other-pointer-lowtag)))
247 (cond ((typep offset '(signed-byte 13))
248 (inst ld old object offset))
250 (inst li offset-reg offset)
251 (inst ld old object offset-reg)))
252 (unless (and (sc-is value immediate)
253 (= (tn-value value) ,(1- (ash 1 bits))))
256 (inst srl old ,bits))
259 (lognot (ash ,(1- (ash 1 bits))
261 ,(1- elements-per-word))
263 (inst and old temp))))
267 (let ((value (ash (logand (tn-value value)
270 ,(1- elements-per-word))
272 (cond ((typep value '(signed-byte 13))
276 (inst or old temp)))))
279 (* (logxor extra ,(1- elements-per-word)) ,bits))
281 (if (typep offset '(signed-byte 13))
282 (inst st old object offset)
283 (inst st old object offset-reg)))
286 (inst li result (tn-value value)))
288 (move result value))))))))))
290 (def-small-data-vector-frobs simple-bit-vector 1)
291 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
292 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
294 ;;; And the float variants.
295 (define-vop (data-vector-ref/simple-array-single-float)
296 (:note "inline array access")
297 (:translate data-vector-ref)
299 (:args (object :scs (descriptor-reg))
300 (index :scs (any-reg)))
301 (:arg-types simple-array-single-float positive-fixnum)
302 (:results (value :scs (single-reg)))
303 (:temporary (:scs (non-descriptor-reg)) offset)
304 (:result-types single-float)
306 (inst add offset index (- (* vector-data-offset n-word-bytes)
307 other-pointer-lowtag))
308 (inst ldf value object offset)))
311 (define-vop (data-vector-set/simple-array-single-float)
312 (:note "inline array store")
313 (:translate data-vector-set)
315 (:args (object :scs (descriptor-reg))
316 (index :scs (any-reg))
317 (value :scs (single-reg) :target result))
318 (:arg-types simple-array-single-float positive-fixnum single-float)
319 (:results (result :scs (single-reg)))
320 (:result-types single-float)
321 (:temporary (:scs (non-descriptor-reg)) offset)
323 (inst add offset index
324 (- (* vector-data-offset n-word-bytes)
325 other-pointer-lowtag))
326 (inst stf value object offset)
327 (unless (location= result value)
328 (inst fmovs result value))))
330 (define-vop (data-vector-ref/simple-array-double-float)
331 (:note "inline array access")
332 (:translate data-vector-ref)
334 (:args (object :scs (descriptor-reg))
335 (index :scs (any-reg)))
336 (:arg-types simple-array-double-float positive-fixnum)
337 (:results (value :scs (double-reg)))
338 (:result-types double-float)
339 (:temporary (:scs (non-descriptor-reg)) offset)
341 (inst sll offset index 1)
342 (inst add offset (- (* vector-data-offset n-word-bytes)
343 other-pointer-lowtag))
344 (inst lddf value object offset)))
346 (define-vop (data-vector-set/simple-array-double-float)
347 (:note "inline array store")
348 (:translate data-vector-set)
350 (:args (object :scs (descriptor-reg))
351 (index :scs (any-reg))
352 (value :scs (double-reg) :target result))
353 (:arg-types simple-array-double-float positive-fixnum double-float)
354 (:results (result :scs (double-reg)))
355 (:result-types double-float)
356 (:temporary (:scs (non-descriptor-reg)) offset)
358 (inst sll offset index 1)
359 (inst add offset (- (* vector-data-offset n-word-bytes)
360 other-pointer-lowtag))
361 (inst stdf value object offset)
362 (unless (location= result value)
363 (move-double-reg result value))))
366 (define-vop (data-vector-ref/simple-array-long-float)
367 (:note "inline array access")
368 (:translate data-vector-ref)
370 (:args (object :scs (descriptor-reg))
371 (index :scs (any-reg)))
372 (:arg-types simple-array-long-float positive-fixnum)
373 (:results (value :scs (long-reg)))
374 (:result-types long-float)
375 (:temporary (:scs (non-descriptor-reg)) offset)
377 (inst sll offset index 2)
378 (inst add offset (- (* vector-data-offset n-word-bytes)
379 other-pointer-lowtag))
380 (load-long-reg value object offset nil)))
383 (define-vop (data-vector-set/simple-array-long-float)
384 (:note "inline array store")
385 (:translate data-vector-set)
387 (:args (object :scs (descriptor-reg))
388 (index :scs (any-reg))
389 (value :scs (long-reg) :target result))
390 (:arg-types simple-array-long-float positive-fixnum long-float)
391 (:results (result :scs (long-reg)))
392 (:result-types long-float)
393 (:temporary (:scs (non-descriptor-reg)) offset)
395 (inst sll offset index 2)
396 (inst add offset (- (* vector-data-offset n-word-bytes)
397 other-pointer-lowtag))
398 (store-long-reg value object offset nil)
399 (unless (location= result value)
400 (move-long-reg result value))))
403 ;;;; Misc. Array VOPs.
407 (define-vop (vector-word-length)
408 (:args (vec :scs (descriptor-reg)))
409 (:results (res :scs (any-reg descriptor-reg)))
411 (loadw res vec clc::g-vector-header-words)
412 (inst niuo res res clc::g-vector-words-mask-16)))
414 (define-vop (get-vector-subtype get-header-data))
415 (define-vop (set-vector-subtype set-header-data))
418 ;;; XXX FIXME: Don't we have these above, in DEF-DATA-VECTOR-FROBS?
419 (define-vop (data-vector-ref/simple-array-signed-byte-8 signed-byte-index-ref)
420 (:note "inline array access")
421 (:variant vector-data-offset other-pointer-lowtag)
422 (:translate data-vector-ref)
423 (:arg-types simple-array-signed-byte-8 positive-fixnum)
424 (:results (value :scs (signed-reg)))
425 (:result-types tagged-num))
427 (define-vop (data-vector-set/simple-array-signed-byte-8 byte-index-set)
428 (:note "inline array store")
429 (:variant vector-data-offset other-pointer-lowtag)
430 (:translate data-vector-set)
431 (:arg-types simple-array-signed-byte-8 positive-fixnum tagged-num)
432 (:args (object :scs (descriptor-reg))
433 (index :scs (any-reg zero immediate))
434 (value :scs (signed-reg)))
435 (:results (result :scs (signed-reg)))
436 (:result-types tagged-num))
439 (define-vop (data-vector-ref/simple-array-signed-byte-16
440 signed-halfword-index-ref)
441 (:note "inline array access")
442 (:variant vector-data-offset other-pointer-lowtag)
443 (:translate data-vector-ref)
444 (:arg-types simple-array-signed-byte-16 positive-fixnum)
445 (:results (value :scs (signed-reg)))
446 (:result-types tagged-num))
448 (define-vop (data-vector-set/simple-array-signed-byte-16 halfword-index-set)
449 (:note "inline array store")
450 (:variant vector-data-offset other-pointer-lowtag)
451 (:translate data-vector-set)
452 (:arg-types simple-array-signed-byte-16 positive-fixnum tagged-num)
453 (:args (object :scs (descriptor-reg))
454 (index :scs (any-reg zero immediate))
455 (value :scs (signed-reg)))
456 (:results (result :scs (signed-reg)))
457 (:result-types tagged-num))
460 ;;; Complex float arrays.
462 (define-vop (data-vector-ref/simple-array-complex-single-float)
463 (:note "inline array access")
464 (:translate data-vector-ref)
466 (:args (object :scs (descriptor-reg) :to :result)
467 (index :scs (any-reg)))
468 (:arg-types simple-array-complex-single-float positive-fixnum)
469 (:results (value :scs (complex-single-reg)))
470 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
471 (:result-types complex-single-float)
473 (let ((real-tn (complex-single-reg-real-tn value)))
474 (inst sll offset index 1)
475 (inst add offset (- (* vector-data-offset n-word-bytes)
476 other-pointer-lowtag))
477 (inst ldf real-tn object offset))
478 (let ((imag-tn (complex-single-reg-imag-tn value)))
479 (inst add offset n-word-bytes)
480 (inst ldf imag-tn object offset))))
482 (define-vop (data-vector-set/simple-array-complex-single-float)
483 (:note "inline array store")
484 (:translate data-vector-set)
486 (:args (object :scs (descriptor-reg) :to :result)
487 (index :scs (any-reg))
488 (value :scs (complex-single-reg) :target result))
489 (:arg-types simple-array-complex-single-float positive-fixnum
490 complex-single-float)
491 (:results (result :scs (complex-single-reg)))
492 (:result-types complex-single-float)
493 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
495 (let ((value-real (complex-single-reg-real-tn value))
496 (result-real (complex-single-reg-real-tn result)))
497 (inst sll offset index 1)
498 (inst add offset (- (* vector-data-offset n-word-bytes)
499 other-pointer-lowtag))
500 (inst stf value-real object offset)
501 (unless (location= result-real value-real)
502 (inst fmovs result-real value-real)))
503 (let ((value-imag (complex-single-reg-imag-tn value))
504 (result-imag (complex-single-reg-imag-tn result)))
505 (inst add offset n-word-bytes)
506 (inst stf value-imag object offset)
507 (unless (location= result-imag value-imag)
508 (inst fmovs result-imag value-imag)))))
510 (define-vop (data-vector-ref/simple-array-complex-double-float)
511 (:note "inline array access")
512 (:translate data-vector-ref)
514 (:args (object :scs (descriptor-reg) :to :result)
515 (index :scs (any-reg)))
516 (:arg-types simple-array-complex-double-float positive-fixnum)
517 (:results (value :scs (complex-double-reg)))
518 (:result-types complex-double-float)
519 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
521 (let ((real-tn (complex-double-reg-real-tn value)))
522 (inst sll offset index 2)
523 (inst add offset (- (* vector-data-offset n-word-bytes)
524 other-pointer-lowtag))
525 (inst lddf real-tn object offset))
526 (let ((imag-tn (complex-double-reg-imag-tn value)))
527 (inst add offset (* 2 n-word-bytes))
528 (inst lddf imag-tn object offset))))
530 (define-vop (data-vector-set/simple-array-complex-double-float)
531 (:note "inline array store")
532 (:translate data-vector-set)
534 (:args (object :scs (descriptor-reg) :to :result)
535 (index :scs (any-reg))
536 (value :scs (complex-double-reg) :target result))
537 (:arg-types simple-array-complex-double-float positive-fixnum
538 complex-double-float)
539 (:results (result :scs (complex-double-reg)))
540 (:result-types complex-double-float)
541 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
543 (let ((value-real (complex-double-reg-real-tn value))
544 (result-real (complex-double-reg-real-tn result)))
545 (inst sll offset index 2)
546 (inst add offset (- (* vector-data-offset n-word-bytes)
547 other-pointer-lowtag))
548 (inst stdf value-real object offset)
549 (unless (location= result-real value-real)
550 (move-double-reg result-real value-real)))
551 (let ((value-imag (complex-double-reg-imag-tn value))
552 (result-imag (complex-double-reg-imag-tn result)))
553 (inst add offset (* 2 n-word-bytes))
554 (inst stdf value-imag object offset)
555 (unless (location= result-imag value-imag)
556 (move-double-reg result-imag value-imag)))))
559 (define-vop (data-vector-ref/simple-array-complex-long-float)
560 (:note "inline array access")
561 (:translate data-vector-ref)
563 (:args (object :scs (descriptor-reg) :to :result)
564 (index :scs (any-reg)))
565 (:arg-types simple-array-complex-long-float positive-fixnum)
566 (:results (value :scs (complex-long-reg)))
567 (:result-types complex-long-float)
568 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
570 (let ((real-tn (complex-long-reg-real-tn value)))
571 (inst sll offset index 3)
572 (inst add offset (- (* vector-data-offset n-word-bytes)
573 other-pointer-lowtag))
574 (load-long-reg real-tn object offset nil))
575 (let ((imag-tn (complex-long-reg-imag-tn value)))
576 (inst add offset (* 4 n-word-bytes))
577 (load-long-reg imag-tn object offset nil))))
580 (define-vop (data-vector-set/simple-array-complex-long-float)
581 (:note "inline array store")
582 (:translate data-vector-set)
584 (:args (object :scs (descriptor-reg) :to :result)
585 (index :scs (any-reg))
586 (value :scs (complex-long-reg) :target result))
587 (:arg-types simple-array-complex-long-float positive-fixnum
589 (:results (result :scs (complex-long-reg)))
590 (:result-types complex-long-float)
591 (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) offset)
593 (let ((value-real (complex-long-reg-real-tn value))
594 (result-real (complex-long-reg-real-tn result)))
595 (inst sll offset index 3)
596 (inst add offset (- (* vector-data-offset n-word-bytes)
597 other-pointer-lowtag))
598 (store-long-reg value-real object offset nil)
599 (unless (location= result-real value-real)
600 (move-long-reg result-real value-real)))
601 (let ((value-imag (complex-long-reg-imag-tn value))
602 (result-imag (complex-long-reg-imag-tn result)))
603 (inst add offset (* 4 n-word-bytes))
604 (store-long-reg value-imag object offset nil)
605 (unless (location= result-imag value-imag)
606 (move-long-reg result-imag value-imag)))))
609 ;;; These vops are useful for accessing the bits of a vector irrespective of
610 ;;; what type of vector it is.
611 (define-vop (vector-raw-bits word-index-ref)
612 (:note "vector-raw-bits VOP")
613 (:translate %vector-raw-bits)
614 (:results (value :scs (unsigned-reg)))
615 (:result-types unsigned-num)
616 (:variant vector-data-offset other-pointer-lowtag))
618 (define-vop (set-vector-raw-bits word-index-set)
619 (:note "setf vector-raw-bits VOP")
620 (:translate %set-vector-raw-bits)
621 (:args (object :scs (descriptor-reg))
622 (index :scs (any-reg zero immediate))
623 (value :scs (unsigned-reg)))
624 (:arg-types * tagged-num unsigned-num)
625 (:results (result :scs (unsigned-reg)))
626 (:result-types unsigned-num)
627 (:variant vector-data-offset other-pointer-lowtag))