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
))