1 ;;;; the HPPA 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.
15 ;;;; Allocator for the array header.
17 (define-vop (make-array-header)
18 (:translate make-array-header
)
20 (:args
(type :scs
(any-reg))
21 (rank :scs
(any-reg)))
22 (:arg-types tagged-num tagged-num
)
23 (:temporary
(:scs
(descriptor-reg) :to
(:result
0) :target result
) header
)
24 (:temporary
(:scs
(non-descriptor-reg) :type random
) ndescr
)
25 (:results
(result :scs
(descriptor-reg)))
28 (inst move alloc-tn header
)
29 (inst dep other-pointer-lowtag
31 3 header
)
30 (inst addi
(* (1+ array-dimensions-offset
) n-word-bytes
) rank ndescr
)
31 (inst dep
0 31 3 ndescr
)
32 (inst add alloc-tn ndescr alloc-tn
)
33 (inst addi
(fixnumize (1- array-dimensions-offset
)) rank ndescr
)
34 (inst sll ndescr n-widetag-bits ndescr
)
35 (inst or ndescr type ndescr
)
36 (inst srl ndescr
2 ndescr
)
37 (storew ndescr header
0 other-pointer-lowtag
))
38 (move header result
)))
41 ;;;; Additional accessors and setters for the array header.
42 (define-full-reffer %array-dimension
*
43 array-dimensions-offset other-pointer-lowtag
44 (any-reg) positive-fixnum sb
!kernel
:%array-dimension
)
46 (define-full-setter %set-array-dimension
*
47 array-dimensions-offset other-pointer-lowtag
48 (any-reg) positive-fixnum sb
!kernel
:%set-array-dimension
)
50 (define-vop (array-rank-vop)
51 (:translate sb
!kernel
:%array-rank
)
53 (:args
(x :scs
(descriptor-reg)))
54 (:results
(res :scs
(unsigned-reg)))
55 (:result-types positive-fixnum
)
57 (loadw res x
0 other-pointer-lowtag
)
58 (inst srl res n-widetag-bits res
)
59 (inst addi
(- (1- array-dimensions-offset
)) res res
)))
63 ;;;; Bounds checking routine.
66 (define-vop (check-bound)
67 (:translate %check-bound
)
69 (:args
(array :scs
(descriptor-reg))
70 (bound :scs
(any-reg descriptor-reg
))
71 (index :scs
(any-reg descriptor-reg
) :target result
))
72 (:results
(result :scs
(any-reg descriptor-reg
)))
74 (:save-p
:compute-only
)
76 (let ((error (generate-error-code vop invalid-array-index-error
78 (inst bc
:>= nil index bound error
))
82 ;;;; Accessors/Setters
84 ;;; Variants built on top of word-index-ref, etc. I.e. those vectors whos
85 ;;; elements are represented in integer registers and are built out of
86 ;;; 8, 16, or 32 bit elements.
88 (macrolet ((def-full-data-vector-frobs (type element-type
&rest scs
)
90 (define-full-reffer ,(symbolicate "DATA-VECTOR-REF/" type
) ,type
91 vector-data-offset other-pointer-lowtag
,scs
,element-type
93 (define-full-setter ,(symbolicate "DATA-VECTOR-SET/" type
) ,type
94 vector-data-offset other-pointer-lowtag
,scs
,element-type
97 (def-partial-data-vector-frobs
98 (type element-type size signed
&rest scs
)
100 (define-partial-reffer ,(symbolicate "DATA-VECTOR-REF/" type
) ,type
101 ,size
,signed vector-data-offset other-pointer-lowtag
,scs
102 ,element-type data-vector-ref
)
103 (define-partial-setter ,(symbolicate "DATA-VECTOR-SET/" type
) ,type
104 ,size vector-data-offset other-pointer-lowtag
,scs
105 ,element-type data-vector-set
))))
107 (def-full-data-vector-frobs simple-vector
* descriptor-reg any-reg
)
109 (def-partial-data-vector-frobs simple-base-string base-char
:byte nil base-char-reg
)
111 (def-partial-data-vector-frobs simple-array-unsigned-byte-7 positive-fixnum
112 :byte nil unsigned-reg signed-reg
)
113 (def-partial-data-vector-frobs simple-array-unsigned-byte-8 positive-fixnum
114 :byte nil unsigned-reg signed-reg
)
116 (def-partial-data-vector-frobs simple-array-unsigned-byte-15 positive-fixnum
117 :short nil unsigned-reg signed-reg
)
118 (def-partial-data-vector-frobs simple-array-unsigned-byte-16 positive-fixnum
119 :short nil unsigned-reg signed-reg
)
121 (def-full-data-vector-frobs simple-array-unsigned-byte-31 unsigned-num
123 (def-full-data-vector-frobs simple-array-unsigned-byte-32 unsigned-num
126 (def-partial-data-vector-frobs simple-array-signed-byte-8 tagged-num
129 (def-partial-data-vector-frobs simple-array-signed-byte-16 tagged-num
132 (def-full-data-vector-frobs simple-array-unsigned-byte-29 positive-fixnum any-reg
)
133 (def-full-data-vector-frobs simple-array-signed-byte-30 tagged-num any-reg
)
135 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num signed-reg
))
138 ;;; Integer vectors whos elements are smaller than a byte. I.e. bit, 2-bit,
139 ;;; and 4-bit vectors.
142 (macrolet ((def-small-data-vector-frobs (type bits
)
143 (let* ((elements-per-word (floor n-word-bits bits
))
144 (bit-shift (1- (integer-length elements-per-word
))))
146 (define-vop (,(symbolicate 'data-vector-ref
/ type
))
147 (:note
"inline array access")
148 (:translate data-vector-ref
)
150 (:args
(object :scs
(descriptor-reg))
151 (index :scs
(unsigned-reg)))
152 (:arg-types
,type positive-fixnum
)
153 (:results
(result :scs
(unsigned-reg) :from
(:argument
0)))
154 (:result-types positive-fixnum
)
155 (:temporary
(:scs
(non-descriptor-reg)) temp
)
156 (:temporary
(:scs
(interior-reg)) lip
)
158 (inst srl index
,bit-shift temp
)
159 (inst sh2add temp object lip
)
160 (loadw result lip vector-data-offset other-pointer-lowtag
)
161 (inst zdep index
,(- 32 (integer-length bits
)) ,bit-shift temp
)
163 `((inst addi
,(1- bits
) temp temp
)))
164 (inst mtctl temp
:sar
)
165 (inst extru result
:variable
,bits result
)))
166 (define-vop (,(symbolicate 'data-vector-ref-c
/ type
))
167 (:translate data-vector-ref
)
169 (:args
(object :scs
(descriptor-reg)))
170 (:arg-types
,type
(:constant index
))
172 (:results
(result :scs
(unsigned-reg)))
173 (:result-types positive-fixnum
)
174 (:temporary
(:scs
(non-descriptor-reg)) temp
)
176 (multiple-value-bind (word extra
) (floor index
,elements-per-word
)
177 (let ((offset (- (* (+ word vector-data-offset
) n-word-bytes
)
178 other-pointer-lowtag
)))
179 (cond ((typep offset
'(signed-byte 14))
180 (inst ldw offset object result
))
182 (inst ldil
(ldb (byte 21 11) offset
) temp
)
183 (inst ldw
(ldb (byte 11 0) offset
) temp result
))))
184 (inst extru result
(+ (* extra
,bits
) ,(1- bits
)) ,bits result
))))
185 (define-vop (,(symbolicate 'data-vector-set
/ type
))
186 (:note
"inline array store")
187 (:translate data-vector-set
)
189 (:args
(object :scs
(descriptor-reg))
190 (index :scs
(unsigned-reg))
191 (value :scs
(unsigned-reg zero immediate
) :target result
))
192 (:arg-types
,type positive-fixnum positive-fixnum
)
193 (:results
(result :scs
(unsigned-reg)))
194 (:result-types positive-fixnum
)
195 (:temporary
(:scs
(non-descriptor-reg)) temp old
)
196 (:temporary
(:scs
(interior-reg)) lip
)
198 (inst srl index
,bit-shift temp
)
199 (inst sh2add temp object lip
)
200 (loadw old lip vector-data-offset other-pointer-lowtag
)
201 (inst zdep index
,(- 32 (integer-length bits
)) ,bit-shift temp
)
203 `((inst addi
,(1- bits
) temp temp
)))
204 (inst mtctl temp
:sar
)
205 (inst dep
(sc-case value
(immediate (tn-value value
)) (t value
))
207 (storew old lip vector-data-offset other-pointer-lowtag
)
210 (inst li
(tn-value value
) result
))
212 (move value result
)))))
213 (define-vop (,(symbolicate 'data-vector-set-c
/ type
))
214 (:translate data-vector-set
)
216 (:args
(object :scs
(descriptor-reg))
217 (value :scs
(unsigned-reg zero immediate
) :target result
))
222 (:results
(result :scs
(unsigned-reg)))
223 (:result-types positive-fixnum
)
224 (:temporary
(:scs
(non-descriptor-reg)) old
)
225 (:temporary
(:scs
(interior-reg)) lip
)
227 (multiple-value-bind (word extra
) (floor index
,elements-per-word
)
228 (let ((offset (- (* (+ word vector-data-offset
) n-word-bytes
)
229 other-pointer-lowtag
)))
230 (cond ((typep offset
'(signed-byte 14))
231 (inst ldw offset object old
))
233 (inst move object lip
)
234 (inst addil
(ldb (byte 21 11) offset
) lip
)
235 (inst ldw
(ldb (byte 11 0) offset
) lip old
)))
236 (inst dep
(sc-case value
237 (immediate (tn-value value
))
239 (+ (* extra
,bits
) ,(1- bits
))
242 (if (typep offset
'(signed-byte 14))
243 (inst stw old offset object
)
244 (inst stw old
(ldb (byte 11 0) offset
) lip
)))
247 (inst li
(tn-value value
) result
))
249 (move value result
))))))))))
250 (def-small-data-vector-frobs simple-bit-vector
1)
251 (def-small-data-vector-frobs simple-array-unsigned-byte-2
2)
252 (def-small-data-vector-frobs simple-array-unsigned-byte-4
4))
254 ;;; And the float variants.
257 (define-vop (data-vector-ref/simple-array-single-float
)
258 (:note
"inline array access")
259 (:translate data-vector-ref
)
261 (:args
(object :scs
(descriptor-reg) :to
(:argument
1))
262 (index :scs
(any-reg) :to
(:argument
0) :target offset
))
263 (:arg-types simple-array-single-float positive-fixnum
)
264 (:results
(value :scs
(single-reg)))
265 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) offset
)
266 (:result-types single-float
)
268 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
270 (inst fldx offset object value
)))
272 (define-vop (data-vector-set/simple-array-single-float
)
273 (:note
"inline array store")
274 (:translate data-vector-set
)
276 (:args
(object :scs
(descriptor-reg) :to
(:argument
1))
277 (index :scs
(any-reg) :to
(:argument
0) :target offset
)
278 (value :scs
(single-reg) :target result
))
279 (:arg-types simple-array-single-float positive-fixnum single-float
)
280 (:results
(result :scs
(single-reg)))
281 (:result-types single-float
)
282 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) offset
)
284 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
286 (inst fstx value offset object
)
287 (unless (location= result value
)
288 (inst funop
:copy value result
))))
290 (define-vop (data-vector-ref/simple-array-double-float
)
291 (:note
"inline array access")
292 (:translate data-vector-ref
)
294 (:args
(object :scs
(descriptor-reg) :to
(:argument
1))
295 (index :scs
(any-reg) :to
(:argument
0) :target offset
))
296 (:arg-types simple-array-double-float positive-fixnum
)
297 (:results
(value :scs
(double-reg)))
298 (:result-types double-float
)
299 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) offset
)
301 (inst sll index
1 offset
)
302 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
304 (inst fldx offset object value
)))
306 (define-vop (data-vector-set/simple-array-double-float
)
307 (:note
"inline array store")
308 (:translate data-vector-set
)
310 (:args
(object :scs
(descriptor-reg) :to
(:argument
1))
311 (index :scs
(any-reg) :to
(:argument
0) :target offset
)
312 (value :scs
(double-reg) :target result
))
313 (:arg-types simple-array-double-float positive-fixnum double-float
)
314 (:results
(result :scs
(double-reg)))
315 (:result-types double-float
)
316 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) offset
)
318 (inst sll index
1 offset
)
319 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
321 (inst fstx value offset object
)
322 (unless (location= result value
)
323 (inst funop
:copy value result
))))
326 ;;; Complex float arrays.
328 (define-vop (data-vector-ref/simple-array-complex-single-float
)
329 (:note
"inline array access")
330 (:translate data-vector-ref
)
332 (:args
(object :scs
(descriptor-reg) :to
:result
)
333 (index :scs
(any-reg)))
334 (:arg-types simple-array-complex-single-float positive-fixnum
)
335 (:results
(value :scs
(complex-single-reg)))
336 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
1)) offset
)
337 (:result-types complex-single-float
)
339 (inst sll index
1 offset
)
340 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
342 (let ((real-tn (complex-single-reg-real-tn value
)))
343 (inst fldx offset object real-tn
))
344 (let ((imag-tn (complex-single-reg-imag-tn value
)))
345 (inst addi n-word-bytes offset offset
)
346 (inst fldx offset object imag-tn
))))
348 (define-vop (data-vector-set/simple-array-complex-single-float
)
349 (:note
"inline array store")
350 (:translate data-vector-set
)
352 (:args
(object :scs
(descriptor-reg) :to
:result
)
353 (index :scs
(any-reg))
354 (value :scs
(complex-single-reg) :target result
))
355 (:arg-types simple-array-complex-single-float positive-fixnum
356 complex-single-float
)
357 (:results
(result :scs
(complex-single-reg)))
358 (:result-types complex-single-float
)
359 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
1)) offset
)
361 (inst sll index
1 offset
)
362 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
364 (let ((value-real (complex-single-reg-real-tn value
))
365 (result-real (complex-single-reg-real-tn result
)))
366 (inst fstx value-real offset object
)
367 (unless (location= result-real value-real
)
368 (inst funop
:copy value-real result-real
)))
369 (let ((value-imag (complex-single-reg-imag-tn value
))
370 (result-imag (complex-single-reg-imag-tn result
)))
371 (inst addi n-word-bytes offset offset
)
372 (inst fstx value-imag offset object
)
373 (unless (location= result-imag value-imag
)
374 (inst funop
:copy value-imag result-imag
)))))
376 (define-vop (data-vector-ref/simple-array-complex-double-float
)
377 (:note
"inline array access")
378 (:translate data-vector-ref
)
380 (:args
(object :scs
(descriptor-reg) :to
:result
)
381 (index :scs
(any-reg)))
382 (:arg-types simple-array-complex-double-float positive-fixnum
)
383 (:results
(value :scs
(complex-double-reg)))
384 (:result-types complex-double-float
)
385 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
1)) offset
)
387 (inst sll index
2 offset
)
388 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
390 (let ((real-tn (complex-double-reg-real-tn value
)))
391 (inst fldx offset object real-tn
))
392 (let ((imag-tn (complex-double-reg-imag-tn value
)))
393 (inst addi
(* 2 n-word-bytes
) offset offset
)
394 (inst fldx offset object imag-tn
))))
396 (define-vop (data-vector-set/simple-array-complex-double-float
)
397 (:note
"inline array store")
398 (:translate data-vector-set
)
400 (:args
(object :scs
(descriptor-reg) :to
:result
)
401 (index :scs
(any-reg))
402 (value :scs
(complex-double-reg) :target result
))
403 (:arg-types simple-array-complex-double-float positive-fixnum
404 complex-double-float
)
405 (:results
(result :scs
(complex-double-reg)))
406 (:result-types complex-double-float
)
407 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
1)) offset
)
409 (inst sll index
2 offset
)
410 (inst addi
(- (* vector-data-offset n-word-bytes
) other-pointer-lowtag
)
412 (let ((value-real (complex-double-reg-real-tn value
))
413 (result-real (complex-double-reg-real-tn result
)))
414 (inst fstx value-real offset object
)
415 (unless (location= result-real value-real
)
416 (inst funop
:copy value-real result-real
)))
417 (let ((value-imag (complex-double-reg-imag-tn value
))
418 (result-imag (complex-double-reg-imag-tn result
)))
419 (inst addi
(* 2 n-word-bytes
) offset offset
)
420 (inst fstx value-imag offset object
)
421 (unless (location= result-imag value-imag
)
422 (inst funop
:copy value-imag result-imag
)))))
425 ;;; These VOPs are used for implementing float slots in structures (whose raw
426 ;;; data is an unsigned-32 vector.
428 (define-vop (raw-ref-single data-vector-ref
/simple-array-single-float
)
429 (:translate %raw-ref-single
)
430 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
))
432 (define-vop (raw-set-single data-vector-set
/simple-array-single-float
)
433 (:translate %raw-set-single
)
434 (:arg-types simple-array-unsigned-byte-32 positive-fixnum single-float
))
436 (define-vop (raw-ref-double data-vector-ref
/simple-array-double-float
)
437 (:translate %raw-ref-double
)
438 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
))
440 (define-vop (raw-set-double data-vector-set
/simple-array-double-float
)
441 (:translate %raw-set-double
)
442 (:arg-types simple-array-unsigned-byte-32 positive-fixnum double-float
))
444 (define-vop (raw-ref-complex-single
445 data-vector-ref
/simple-array-complex-single-float
)
446 (:translate %raw-ref-complex-single
)
447 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
))
449 (define-vop (raw-set-complex-single
450 data-vector-set
/simple-array-complex-single-float
)
451 (:translate %raw-set-complex-single
)
452 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
453 complex-single-float
))
455 (define-vop (raw-ref-complex-double
456 data-vector-ref
/simple-array-complex-double-float
)
457 (:translate %raw-ref-complex-double
)
458 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
))
460 (define-vop (raw-set-complex-double
461 data-vector-set
/simple-array-complex-double-float
)
462 (:translate %raw-set-complex-double
)
463 (:arg-types simple-array-unsigned-byte-32 positive-fixnum
464 complex-double-float
))
466 ;;; These vops are useful for accessing the bits of a vector irrespective of
467 ;;; what type of vector it is.
470 (define-full-reffer raw-bits
* 0 other-pointer-lowtag
(unsigned-reg) unsigned-num
472 (define-full-setter set-raw-bits
* 0 other-pointer-lowtag
(unsigned-reg)
473 unsigned-num %set-raw-bits
)
477 ;;;; Misc. Array VOPs.
479 (define-vop (get-vector-subtype get-header-data
))
480 (define-vop (set-vector-subtype set-header-data
))