1 ;;;; array operations for the x86 VM
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 ;; For use in constant indexing; we can't use INDEX since the displacement
16 ;; field of an EA can't contain 64 bit values.
17 (def!type low-index
() '(signed-byte 29))
19 ;;;; allocator for the array header
21 (define-vop (make-array-header)
22 (:translate make-array-header
)
24 (:args
(type :scs
(any-reg))
25 (rank :scs
(any-reg)))
26 (:arg-types positive-fixnum positive-fixnum
)
27 (:temporary
(:sc any-reg
:to
:eval
) bytes
)
28 (:temporary
(:sc any-reg
:to
:result
) header
)
29 (:results
(result :scs
(descriptor-reg) :from
:eval
))
34 :index rank
:scale
(ash 1 (- word-shift n-fixnum-tag-bits
))
35 :disp
(+ (* array-dimensions-offset n-word-bytes
)
37 (inst and bytes
(lognot lowtag-mask
))
38 (inst lea header
(make-ea :qword
:base rank
39 :disp
(fixnumize (1- array-dimensions-offset
))))
40 (inst shl header n-widetag-bits
)
42 (inst shr header n-fixnum-tag-bits
)
44 (allocation result bytes node nil other-pointer-lowtag
)
45 (storew header result
0 other-pointer-lowtag
))))
47 (define-vop (make-array-header/c
)
48 (:translate make-array-header
)
50 (:arg-types
(:constant t
) (:constant t
))
52 (:results
(result :scs
(descriptor-reg) :from
:eval
))
55 (let* ((header-size (+ rank
56 (1- array-dimensions-offset
)))
57 (bytes (logandc2 (+ (* (1+ header-size
) n-word-bytes
)
60 (header (logior (ash header-size
64 (allocation result bytes node nil other-pointer-lowtag
)
65 (storew header result
0 other-pointer-lowtag
)))))
68 ;;;; additional accessors and setters for the array header
69 (define-full-reffer %array-dimension
*
70 array-dimensions-offset other-pointer-lowtag
71 (any-reg) positive-fixnum %array-dimension
)
73 (define-full-setter %set-array-dimension
*
74 array-dimensions-offset other-pointer-lowtag
75 (any-reg) positive-fixnum %set-array-dimension
)
77 (define-vop (array-rank-vop)
78 (:translate %array-rank
)
80 (:args
(x :scs
(descriptor-reg)))
81 (:results
(res :scs
(unsigned-reg)))
82 (:result-types positive-fixnum
)
84 ;; An unaligned dword read not spanning a 16-byte boundary is as fast as
85 ;; and shorter by 5 bytes than a qword read and right-shift by 8.
86 (inst mov
(reg-in-size res
:dword
)
87 (make-ea :dword
:base x
:disp
(1+ (- other-pointer-lowtag
))))
88 (inst sub
(reg-in-size res
:dword
) (1- array-dimensions-offset
))))
90 (define-vop (array-rank-vop=>fixnum
)
91 (:translate %array-rank
)
93 (:args
(x :scs
(descriptor-reg)))
94 (:results
(res :scs
(any-reg)))
95 (:result-types positive-fixnum
)
97 (inst mov
(reg-in-size res
:dword
)
98 (make-ea :dword
:base x
:disp
(1+ (- other-pointer-lowtag
))))
99 (inst lea
(reg-in-size res
:dword
)
100 (let ((scale (ash 1 n-fixnum-tag-bits
)))
101 ;; Compute [res*N-disp]. for N=2 use [res+res-disp]
103 :scale
(if (= scale
2) 1 scale
)
105 :base
(if (= scale
2) res nil
)
106 :disp
(- (* scale
(1- array-dimensions-offset
))))))))
108 ;;;; bounds checking routine
110 ;;; Note that the immediate SC for the index argument is disabled
111 ;;; because it is not possible to generate a valid error code SC for
112 ;;; an immediate value.
114 ;;; FIXME: As per the KLUDGE note explaining the :IGNORE-FAILURE-P
115 ;;; flag in build-order.lisp-expr, compiling this file causes warnings
116 ;;; Argument FOO to VOP CHECK-BOUND has SC restriction
117 ;;; DESCRIPTOR-REG which is not allowed by the operand type:
118 ;;; (:OR POSITIVE-FIXNUM)
119 ;;; CSR's message "format ~/ /" on sbcl-devel 2002-03-12 contained
120 ;;; a possible patch, described as
121 ;;; Another patch is included more for information than anything --
122 ;;; removing the descriptor-reg SCs from the CHECK-BOUND vop in
123 ;;; x86/array.lisp seems to allow that file to compile without error[*],
124 ;;; and build; I haven't tested rebuilding capability, but I'd be
125 ;;; surprised if there were a problem. I'm not certain that this is the
126 ;;; correct fix, though, as the restrictions on the arguments to the VOP
127 ;;; aren't the same as in the sparc and alpha ports, where, incidentally,
128 ;;; the corresponding file builds without error currently.
129 ;;; Since neither of us (CSR or WHN) was quite sure that this is the
130 ;;; right thing, I've just recorded the patch here in hopes it might
131 ;;; help when someone attacks this problem again:
132 ;;; diff -u -r1.7 array.lisp
133 ;;; --- src/compiler/x86/array.lisp 11 Oct 2001 14:05:26 -0000 1.7
134 ;;; +++ src/compiler/x86/array.lisp 12 Mar 2002 12:23:37 -0000
135 ;;; @@ -76,10 +76,10 @@
136 ;;; (:translate %check-bound)
137 ;;; (:policy :fast-safe)
138 ;;; (:args (array :scs (descriptor-reg))
139 ;;; - (bound :scs (any-reg descriptor-reg))
140 ;;; - (index :scs (any-reg descriptor-reg #+nil immediate) :target result))
141 ;;; + (bound :scs (any-reg))
142 ;;; + (index :scs (any-reg #+nil immediate) :target result))
143 ;;; (:arg-types * positive-fixnum tagged-num)
144 ;;; - (:results (result :scs (any-reg descriptor-reg)))
145 ;;; + (:results (result :scs (any-reg)))
146 ;;; (:result-types positive-fixnum)
148 ;;; (:save-p :compute-only)
149 (define-vop (check-bound)
150 (:translate %check-bound
)
152 (:args
(array :scs
(descriptor-reg))
153 (bound :scs
(any-reg descriptor-reg
))
154 (index :scs
(any-reg descriptor-reg
)))
155 ;(:arg-types * positive-fixnum *)
156 (:variant-vars %test-fixnum
)
159 (:save-p
:compute-only
)
161 (let ((error (generate-error-code vop
'invalid-array-index-error
163 (index (if (sc-is index immediate
)
164 (fixnumize (tn-value index
))
166 (when (and %test-fixnum
(not (integerp index
)))
167 (%test-fixnum index error t
))
168 (inst cmp bound index
)
169 ;; We use below-or-equal even though it's an unsigned test,
170 ;; because negative indexes appear as large unsigned numbers.
171 ;; Therefore, we get the <0 and >=bound test all rolled into one.
172 (inst jmp
:be error
))))
173 (define-vop (check-bound/fast check-bound
)
178 ;;;; accessors/setters
180 ;;; variants built on top of WORD-INDEX-REF, etc. I.e., those vectors
181 ;;; whose elements are represented in integer registers and are built
182 ;;; out of 8, 16, or 32 bit elements.
183 (macrolet ((def-full-data-vector-frobs (type element-type
&rest scs
)
185 (define-full-reffer+offset
186 ,(symbolicate "DATA-VECTOR-REF-WITH-OFFSET/" type
)
187 ,type vector-data-offset other-pointer-lowtag
,scs
188 ,element-type data-vector-ref-with-offset
)
189 (define-full-setter+offset
190 ,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" type
)
191 ,type vector-data-offset other-pointer-lowtag
,scs
192 ,element-type data-vector-set-with-offset
)))
194 (def-full-data-vector-frobs simple-vector
* descriptor-reg any-reg
)
195 (def-full-data-vector-frobs simple-array-unsigned-byte-64 unsigned-num
197 (def-full-data-vector-frobs simple-array-fixnum tagged-num any-reg
)
198 (def-full-data-vector-frobs simple-array-unsigned-fixnum
199 positive-fixnum any-reg
)
200 (def-full-data-vector-frobs simple-array-signed-byte-64
201 signed-num signed-reg
)
202 (def-full-data-vector-frobs simple-array-unsigned-byte-63 unsigned-num
205 (define-full-compare-and-swap %compare-and-swap-svref simple-vector
206 vector-data-offset other-pointer-lowtag
207 (descriptor-reg any-reg
) *
208 %compare-and-swap-svref
)
210 ;;;; integer vectors whose elements are smaller than a byte, i.e.,
211 ;;;; bit, 2-bit, and 4-bit vectors
213 (define-vop (data-vector-ref-with-offset/simple-bit-vector-c
)
214 (:translate data-vector-ref-with-offset
)
216 (:args
(object :scs
(descriptor-reg)))
217 (:arg-types simple-bit-vector
218 ;; this constant is possibly off by something
219 ;; but (sbit n <huge-constant>) is unlikely to appear in code
220 (:constant
(integer 0 #x3ffffffff
)) (:constant
(integer 0 0)))
223 (:results
(result :scs
(any-reg)))
224 (:result-types positive-fixnum
)
226 ;; using 32-bit operand size might elide the REX prefix on mov + shift
227 (multiple-value-bind (dword-index bit
) (floor index
32)
228 (inst mov
(reg-in-size result
:dword
)
229 (make-ea :dword
:base object
230 :disp
(+ (* dword-index
4)
231 (- (* vector-data-offset n-word-bytes
)
232 other-pointer-lowtag
))))
233 (let ((right-shift (- bit n-fixnum-tag-bits
)))
234 (cond ((plusp right-shift
)
235 (inst shr
(reg-in-size result
:dword
) right-shift
))
236 ((minusp right-shift
) ; = left shift
237 (inst shl
(reg-in-size result
:dword
) (- right-shift
))))))
238 (inst and
(reg-in-size result
:dword
) (fixnumize 1))))
240 (define-vop (data-vector-ref-with-offset/simple-bit-vector
)
241 (:translate data-vector-ref-with-offset
)
243 (:args
(object :scs
(descriptor-reg))
244 (index :scs
(unsigned-reg)))
247 (:arg-types simple-bit-vector positive-fixnum
(:constant
(integer 0 0)))
248 (:results
(result :scs
(any-reg)))
249 (:result-types positive-fixnum
)
251 (inst bt
(make-ea :qword
:base object
252 :disp
(- (* vector-data-offset n-word-bytes
)
253 other-pointer-lowtag
))
255 (inst sbb
(reg-in-size result
:dword
) (reg-in-size result
:dword
))
256 (inst and
(reg-in-size result
:dword
) (fixnumize 1))))
258 (macrolet ((def-small-data-vector-frobs (type bits
)
259 (let* ((elements-per-word (floor n-word-bits bits
))
260 (bit-shift (1- (integer-length elements-per-word
))))
263 `((define-vop (,(symbolicate 'data-vector-ref-with-offset
/ type
))
264 (:note
"inline array access")
265 (:translate data-vector-ref-with-offset
)
267 (:args
(object :scs
(descriptor-reg))
268 (index :scs
(unsigned-reg)))
270 (:arg-types
,type positive-fixnum
(:constant
(integer 0 0)))
271 (:results
(result :scs
(unsigned-reg) :from
(:argument
0)))
272 (:result-types positive-fixnum
)
273 (:temporary
(:sc unsigned-reg
:offset ecx-offset
) ecx
)
275 (aver (zerop offset
))
277 (inst shr ecx
,bit-shift
)
279 (make-ea :qword
:base object
:index ecx
:scale n-word-bytes
280 :disp
(- (* vector-data-offset n-word-bytes
)
281 other-pointer-lowtag
)))
283 ;; We used to mask ECX for all values of BITS, but since
284 ;; Intel's documentation says that the chip will mask shift
285 ;; and rotate counts by 63 automatically, we can safely move
286 ;; the masking operation under the protection of this UNLESS
287 ;; in the bit-vector case. --njf, 2006-07-14
289 `((inst and ecx
,(1- elements-per-word
))
290 (inst shl ecx
,(1- (integer-length bits
)))))
291 (inst shr result
:cl
)
292 (inst and result
,(1- (ash 1 bits
)))))
293 (define-vop (,(symbolicate 'data-vector-ref-with-offset
/ type
"-C"))
294 (:translate data-vector-ref-with-offset
)
296 (:args
(object :scs
(descriptor-reg)))
297 (:arg-types
,type
(:constant low-index
) (:constant
(integer 0 0)))
299 (:results
(result :scs
(unsigned-reg)))
300 (:result-types positive-fixnum
)
302 (aver (zerop offset
))
303 (multiple-value-bind (word extra
) (floor index
,elements-per-word
)
304 (loadw result object
(+ word vector-data-offset
)
305 other-pointer-lowtag
)
306 (unless (zerop extra
)
307 (inst shr result
(* extra
,bits
)))
308 (unless (= extra
,(1- elements-per-word
))
309 (inst and result
,(1- (ash 1 bits
)))))))))
310 (define-vop (,(symbolicate 'data-vector-set-with-offset
/ type
))
311 (:note
"inline array store")
312 (:translate data-vector-set-with-offset
)
314 (:args
(object :scs
(descriptor-reg))
315 (index :scs
(unsigned-reg) :target ecx
)
316 (value :scs
(unsigned-reg immediate
) :target result
))
318 (:arg-types
,type positive-fixnum
(:constant
(integer 0 0))
320 (:results
(result :scs
(unsigned-reg)))
321 (:result-types positive-fixnum
)
322 (:temporary
(:sc unsigned-reg
) word-index
)
323 (:temporary
(:sc unsigned-reg
) old
)
324 (:temporary
(:sc unsigned-reg
:offset ecx-offset
) ecx
)
326 (aver (zerop offset
))
327 (move word-index index
)
328 (inst shr word-index
,bit-shift
)
330 (make-ea :qword
:base object
:index word-index
332 :disp
(- (* vector-data-offset n-word-bytes
)
333 other-pointer-lowtag
)))
335 ;; We used to mask ECX for all values of BITS, but since
336 ;; Intel's documentation says that the chip will mask shift
337 ;; and rotate counts by 63 automatically, we can safely move
338 ;; the masking operation under the protection of this UNLESS
339 ;; in the bit-vector case. --njf, 2006-07-14
341 `((inst and ecx
,(1- elements-per-word
))
342 (inst shl ecx
,(1- (integer-length bits
)))))
344 (unless (and (sc-is value immediate
)
345 (= (tn-value value
) ,(1- (ash 1 bits
))))
346 (inst and old
,(lognot (1- (ash 1 bits
)))))
349 (unless (zerop (tn-value value
))
350 (inst or old
(logand (tn-value value
) ,(1- (ash 1 bits
))))))
352 (inst or old value
)))
354 (inst mov
(make-ea :qword
:base object
:index word-index
356 :disp
(- (* vector-data-offset n-word-bytes
)
357 other-pointer-lowtag
))
361 (inst mov result
(tn-value value
)))
363 (move result value
)))))
364 (define-vop (,(symbolicate 'data-vector-set-with-offset
/ type
"-C"))
365 (:translate data-vector-set-with-offset
)
367 (:args
(object :scs
(descriptor-reg))
368 (value :scs
(unsigned-reg immediate
) :target result
))
369 (:arg-types
,type
(:constant low-index
)
370 (:constant
(integer 0 0)) positive-fixnum
)
371 (:temporary
(:sc unsigned-reg
) mask-tn
)
373 (:results
(result :scs
(unsigned-reg)))
374 (:result-types positive-fixnum
)
375 (:temporary
(:sc unsigned-reg
:to
(:result
0)) old
)
377 (aver (zerop offset
))
378 (multiple-value-bind (word extra
) (floor index
,elements-per-word
)
380 (make-ea :qword
:base object
381 :disp
(- (* (+ word vector-data-offset
)
383 other-pointer-lowtag
)))
386 (let* ((value (tn-value value
))
387 (mask ,(1- (ash 1 bits
)))
388 (shift (* extra
,bits
)))
389 (unless (= value mask
)
390 (inst mov mask-tn
(ldb (byte 64 0)
391 (lognot (ash mask shift
))))
392 (inst and old mask-tn
))
393 (unless (zerop value
)
394 (inst mov mask-tn
(ash value shift
))
395 (inst or old mask-tn
))))
397 (let ((shift (* extra
,bits
)))
398 (unless (zerop shift
)
399 (inst ror old shift
))
400 (inst mov mask-tn
(lognot ,(1- (ash 1 bits
))))
401 (inst and old mask-tn
)
403 (unless (zerop shift
)
404 (inst rol old shift
)))))
405 (inst mov
(make-ea :qword
:base object
406 :disp
(- (* (+ word vector-data-offset
)
408 other-pointer-lowtag
))
412 (inst mov result
(tn-value value
)))
414 (move result value
))))))))))
415 (def-small-data-vector-frobs simple-bit-vector
1)
416 (def-small-data-vector-frobs simple-array-unsigned-byte-2
2)
417 (def-small-data-vector-frobs simple-array-unsigned-byte-4
4))
418 ;;; And the float variants.
420 (defun make-ea-for-float-ref (object index offset element-size
421 &key
(scale 1) (complex-offset 0))
422 (let ((ea-size (if (= element-size
4) :dword
:qword
)))
425 (make-ea ea-size
:base object
426 :disp
(- (+ (* vector-data-offset n-word-bytes
)
427 (* (+ index offset
) element-size
)
429 other-pointer-lowtag
)))
431 (make-ea ea-size
:base object
:index index
:scale scale
432 :disp
(- (+ (* vector-data-offset n-word-bytes
)
433 (* offset element-size
)
435 other-pointer-lowtag
))))))
438 (let ((use-temp (<= word-shift n-fixnum-tag-bits
)))
439 `(define-vop (data-vector-ref-with-offset/simple-array-single-float
)
440 (:note
"inline array access")
441 (:translate data-vector-ref-with-offset
)
443 (:args
(object :scs
(descriptor-reg))
444 (index :scs
(any-reg)))
446 (:arg-types simple-array-single-float tagged-num
447 (:constant
(constant-displacement other-pointer-lowtag
448 4 vector-data-offset
)))
449 ,@(when use-temp
'((:temporary
(:sc unsigned-reg
) dword-index
)))
450 (:results
(value :scs
(single-reg)))
451 (:result-types single-float
)
454 '((move dword-index index
)
455 (inst shr dword-index
(1+ (- n-fixnum-tag-bits word-shift
)))
456 (inst movss value
(make-ea-for-float-ref object dword-index offset
4)))
457 '((inst movss value
(make-ea-for-float-ref object index offset
4
458 :scale
(ash 4 (- n-fixnum-tag-bits
)))))))))
460 (define-vop (data-vector-ref-with-offset/simple-array-single-float-c
)
461 (:note
"inline array access")
462 (:translate data-vector-ref-with-offset
)
464 (:args
(object :scs
(descriptor-reg)))
466 (:arg-types simple-array-single-float
(:constant low-index
)
467 (:constant
(constant-displacement other-pointer-lowtag
468 4 vector-data-offset
)))
469 (:results
(value :scs
(single-reg)))
470 (:result-types single-float
)
472 (inst movss value
(make-ea-for-float-ref object index offset
4))))
475 (let ((use-temp (<= word-shift n-fixnum-tag-bits
)))
476 `(define-vop (data-vector-set-with-offset/simple-array-single-float
)
477 (:note
"inline array store")
478 (:translate data-vector-set-with-offset
)
480 (:args
(object :scs
(descriptor-reg))
481 (index :scs
(any-reg))
482 (value :scs
(single-reg) :target result
))
484 (:arg-types simple-array-single-float tagged-num
485 (:constant
(constant-displacement other-pointer-lowtag
486 4 vector-data-offset
))
488 ,@(when use-temp
'((:temporary
(:sc unsigned-reg
) dword-index
)))
489 (:results
(result :scs
(single-reg)))
490 (:result-types single-float
)
493 '((move dword-index index
)
494 (inst shr dword-index
(1+ (- n-fixnum-tag-bits word-shift
)))
495 (inst movss
(make-ea-for-float-ref object dword-index offset
4) value
))
496 '((inst movss
(make-ea-for-float-ref object index offset
4
497 :scale
(ash 4 (- n-fixnum-tag-bits
))) value
)))
498 (move result value
))))
500 (define-vop (data-vector-set-with-offset/simple-array-single-float-c
)
501 (:note
"inline array store")
502 (:translate data-vector-set-with-offset
)
504 (:args
(object :scs
(descriptor-reg))
505 (value :scs
(single-reg) :target result
))
507 (:arg-types simple-array-single-float
(:constant low-index
)
508 (:constant
(constant-displacement other-pointer-lowtag
509 4 vector-data-offset
))
511 (:results
(result :scs
(single-reg)))
512 (:result-types single-float
)
514 (inst movss
(make-ea-for-float-ref object index offset
4) value
)
515 (move result value
)))
517 (define-vop (data-vector-ref-with-offset/simple-array-double-float
)
518 (:note
"inline array access")
519 (:translate data-vector-ref-with-offset
)
521 (:args
(object :scs
(descriptor-reg))
522 (index :scs
(any-reg)))
524 (:arg-types simple-array-double-float tagged-num
525 (:constant
(constant-displacement other-pointer-lowtag
526 8 vector-data-offset
)))
527 (:results
(value :scs
(double-reg)))
528 (:result-types double-float
)
530 (inst movsd value
(make-ea-for-float-ref object index offset
8
531 :scale
(ash 1 (- word-shift n-fixnum-tag-bits
))))))
533 (define-vop (data-vector-ref-c/simple-array-double-float
)
534 (:note
"inline array access")
535 (:translate data-vector-ref-with-offset
)
537 (:args
(object :scs
(descriptor-reg)))
539 (:arg-types simple-array-double-float
(:constant low-index
)
540 (:constant
(constant-displacement other-pointer-lowtag
541 8 vector-data-offset
)))
542 (:results
(value :scs
(double-reg)))
543 (:result-types double-float
)
545 (inst movsd value
(make-ea-for-float-ref object index offset
8))))
547 (define-vop (data-vector-set-with-offset/simple-array-double-float
)
548 (:note
"inline array store")
549 (:translate data-vector-set-with-offset
)
551 (:args
(object :scs
(descriptor-reg))
552 (index :scs
(any-reg))
553 (value :scs
(double-reg) :target result
))
555 (:arg-types simple-array-double-float tagged-num
556 (:constant
(constant-displacement other-pointer-lowtag
557 8 vector-data-offset
))
559 (:results
(result :scs
(double-reg)))
560 (:result-types double-float
)
562 (inst movsd
(make-ea-for-float-ref object index offset
8
563 :scale
(ash 1 (- word-shift n-fixnum-tag-bits
)))
565 (move result value
)))
567 (define-vop (data-vector-set-with-offset/simple-array-double-float-c
)
568 (:note
"inline array store")
569 (:translate data-vector-set-with-offset
)
571 (:args
(object :scs
(descriptor-reg))
572 (value :scs
(double-reg) :target result
))
574 (:arg-types simple-array-double-float
(:constant low-index
)
575 (:constant
(constant-displacement other-pointer-lowtag
576 8 vector-data-offset
))
578 (:results
(result :scs
(double-reg)))
579 (:result-types double-float
)
581 (inst movsd
(make-ea-for-float-ref object index offset
8) value
)
582 (move result value
)))
585 ;;; complex float variants
587 (define-vop (data-vector-ref-with-offset/simple-array-complex-single-float
)
588 (:note
"inline array access")
589 (:translate data-vector-ref-with-offset
)
591 (:args
(object :scs
(descriptor-reg))
592 (index :scs
(any-reg)))
594 (:arg-types simple-array-complex-single-float tagged-num
595 (:constant
(constant-displacement other-pointer-lowtag
596 8 vector-data-offset
)))
597 (:results
(value :scs
(complex-single-reg)))
598 (:result-types complex-single-float
)
600 (inst movq value
(make-ea-for-float-ref object index offset
8
601 :scale
(ash 1 (- word-shift n-fixnum-tag-bits
))))))
603 (define-vop (data-vector-ref-with-offset/simple-array-complex-single-float-c
)
604 (:note
"inline array access")
605 (:translate data-vector-ref-with-offset
)
607 (:args
(object :scs
(descriptor-reg)))
609 (:arg-types simple-array-complex-single-float
(:constant low-index
)
610 (:constant
(constant-displacement other-pointer-lowtag
611 8 vector-data-offset
)))
612 (:results
(value :scs
(complex-single-reg)))
613 (:result-types complex-single-float
)
615 (inst movq value
(make-ea-for-float-ref object index offset
8))))
617 (define-vop (data-vector-set-with-offset/simple-array-complex-single-float
)
618 (:note
"inline array store")
619 (:translate data-vector-set-with-offset
)
621 (:args
(object :scs
(descriptor-reg))
622 (index :scs
(any-reg))
623 (value :scs
(complex-single-reg) :target result
))
625 (:arg-types simple-array-complex-single-float tagged-num
626 (:constant
(constant-displacement other-pointer-lowtag
627 8 vector-data-offset
))
628 complex-single-float
)
629 (:results
(result :scs
(complex-single-reg)))
630 (:result-types complex-single-float
)
633 (inst movq
(make-ea-for-float-ref object index offset
8
634 :scale
(ash 1 (- word-shift n-fixnum-tag-bits
)))
637 (define-vop (data-vector-set-with-offset/simple-array-complex-single-float-c
)
638 (:note
"inline array store")
639 (:translate data-vector-set-with-offset
)
641 (:args
(object :scs
(descriptor-reg))
642 (value :scs
(complex-single-reg) :target result
))
644 (:arg-types simple-array-complex-single-float
(:constant low-index
)
645 (:constant
(constant-displacement other-pointer-lowtag
646 8 vector-data-offset
))
647 complex-single-float
)
648 (:results
(result :scs
(complex-single-reg)))
649 (:result-types complex-single-float
)
652 (inst movq
(make-ea-for-float-ref object index offset
8) value
)))
654 (define-vop (data-vector-ref-with-offset/simple-array-complex-double-float
)
655 (:note
"inline array access")
656 (:translate data-vector-ref-with-offset
)
658 (:args
(object :scs
(descriptor-reg))
659 (index :scs
(any-reg)))
661 (:arg-types simple-array-complex-double-float tagged-num
662 (:constant
(constant-displacement other-pointer-lowtag
663 16 vector-data-offset
)))
664 (:results
(value :scs
(complex-double-reg)))
665 (:result-types complex-double-float
)
667 (inst movapd value
(make-ea-for-float-ref object index offset
16
668 :scale
(ash 2 (- word-shift n-fixnum-tag-bits
))))))
670 (define-vop (data-vector-ref-with-offset/simple-array-complex-double-float-c
)
671 (:note
"inline array access")
672 (:translate data-vector-ref-with-offset
)
674 (:args
(object :scs
(descriptor-reg)))
676 (:arg-types simple-array-complex-double-float
(:constant low-index
)
677 (:constant
(constant-displacement other-pointer-lowtag
678 16 vector-data-offset
)))
679 (:results
(value :scs
(complex-double-reg)))
680 (:result-types complex-double-float
)
682 (inst movapd value
(make-ea-for-float-ref object index offset
16))))
684 (define-vop (data-vector-set-with-offset/simple-array-complex-double-float
)
685 (:note
"inline array store")
686 (:translate data-vector-set-with-offset
)
688 (:args
(object :scs
(descriptor-reg))
689 (index :scs
(any-reg))
690 (value :scs
(complex-double-reg) :target result
))
692 (:arg-types simple-array-complex-double-float tagged-num
693 (:constant
(constant-displacement other-pointer-lowtag
694 16 vector-data-offset
))
695 complex-double-float
)
696 (:results
(result :scs
(complex-double-reg)))
697 (:result-types complex-double-float
)
699 (inst movapd
(make-ea-for-float-ref object index offset
16
700 :scale
(ash 2 (- word-shift n-fixnum-tag-bits
)))
702 (move result value
)))
704 (define-vop (data-vector-set-with-offset/simple-array-complex-double-float-c
)
705 (:note
"inline array store")
706 (:translate data-vector-set-with-offset
)
708 (:args
(object :scs
(descriptor-reg))
709 (value :scs
(complex-double-reg) :target result
))
711 (:arg-types simple-array-complex-double-float
(:constant low-index
)
712 (:constant
(constant-displacement other-pointer-lowtag
713 16 vector-data-offset
))
714 complex-double-float
)
715 (:results
(result :scs
(complex-double-reg)))
716 (:result-types complex-double-float
)
718 (inst movapd
(make-ea-for-float-ref object index offset
16) value
)
719 (move result value
)))
723 ;;; {un,}signed-byte-{8,16,32} and characters
724 (macrolet ((define-data-vector-frobs (ptype mov-inst operand-size
726 (let ((n-bytes (ecase operand-size
730 (multiple-value-bind (index-sc scale
)
731 (if (>= n-bytes
(ash 1 n-fixnum-tag-bits
))
732 (values 'any-reg
(ash n-bytes
(- n-fixnum-tag-bits
)))
733 (values 'signed-reg n-bytes
))
735 (define-vop (,(symbolicate "DATA-VECTOR-REF-WITH-OFFSET/" ptype
))
736 (:translate data-vector-ref-with-offset
)
738 (:args
(object :scs
(descriptor-reg))
739 (index :scs
(,index-sc
)))
741 (:arg-types
,ptype tagged-num
742 (:constant
(constant-displacement other-pointer-lowtag
743 ,n-bytes vector-data-offset
)))
744 (:results
(value :scs
,scs
))
745 (:result-types
,type
)
747 (inst ,mov-inst value
748 (make-ea ,operand-size
:base object
:index index
:scale
,scale
749 :disp
(- (+ (* vector-data-offset n-word-bytes
)
751 other-pointer-lowtag
)))))
752 (define-vop (,(symbolicate "DATA-VECTOR-REF-WITH-OFFSET/" ptype
"-C"))
753 (:translate data-vector-ref-with-offset
)
755 (:args
(object :scs
(descriptor-reg)))
757 (:arg-types
,ptype
(:constant low-index
)
758 (:constant
(constant-displacement other-pointer-lowtag
759 ,n-bytes vector-data-offset
)))
760 (:results
(value :scs
,scs
))
761 (:result-types
,type
)
763 (inst ,mov-inst value
764 (make-ea ,operand-size
:base object
765 :disp
(- (+ (* vector-data-offset n-word-bytes
)
768 other-pointer-lowtag
)))))
769 (define-vop (,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" ptype
))
770 (:translate data-vector-set-with-offset
)
772 (:args
(object :scs
(descriptor-reg) :to
(:eval
0))
773 (index :scs
(,index-sc
) :to
(:eval
0))
774 (value :scs
,scs
:target result
))
776 (:arg-types
,ptype tagged-num
777 (:constant
(constant-displacement other-pointer-lowtag
778 ,n-bytes vector-data-offset
))
780 (:results
(result :scs
,scs
))
781 (:result-types
,type
)
783 (inst mov
(make-ea ,operand-size
:base object
:index index
:scale
,scale
784 :disp
(- (+ (* vector-data-offset n-word-bytes
)
786 other-pointer-lowtag
))
787 (reg-in-size value
,operand-size
))
788 (move result value
)))
790 (define-vop (,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" ptype
"-C"))
791 (:translate data-vector-set-with-offset
)
793 (:args
(object :scs
(descriptor-reg) :to
(:eval
0))
794 (value :scs
,scs
:target result
))
796 (:arg-types
,ptype
(:constant low-index
)
797 (:constant
(constant-displacement other-pointer-lowtag
798 ,n-bytes vector-data-offset
))
800 (:results
(result :scs
,scs
))
801 (:result-types
,type
)
803 (inst mov
(make-ea ,operand-size
:base object
804 :disp
(- (+ (* vector-data-offset n-word-bytes
)
807 other-pointer-lowtag
))
808 (reg-in-size value
,operand-size
))
809 (move result value
))))))))
810 (define-data-vector-frobs simple-array-unsigned-byte-7 movzx
:byte
811 positive-fixnum unsigned-reg signed-reg
)
812 (define-data-vector-frobs simple-array-unsigned-byte-8 movzx
:byte
813 positive-fixnum unsigned-reg signed-reg
)
814 (define-data-vector-frobs simple-array-signed-byte-8 movsx
:byte
815 tagged-num signed-reg
)
816 (define-data-vector-frobs simple-base-string
817 #!+sb-unicode movzx
#!-sb-unicode mov
:byte
818 character character-reg
)
819 (define-data-vector-frobs simple-array-unsigned-byte-15 movzx
:word
820 positive-fixnum unsigned-reg signed-reg
)
821 (define-data-vector-frobs simple-array-unsigned-byte-16 movzx
:word
822 positive-fixnum unsigned-reg signed-reg
)
823 (define-data-vector-frobs simple-array-signed-byte-16 movsx
:word
824 tagged-num signed-reg
)
825 (define-data-vector-frobs simple-array-unsigned-byte-32 movzxd
:dword
826 positive-fixnum unsigned-reg signed-reg
)
827 (define-data-vector-frobs simple-array-unsigned-byte-31 movzxd
:dword
828 positive-fixnum unsigned-reg signed-reg
)
829 (define-data-vector-frobs simple-array-signed-byte-32 movsxd
:dword
830 tagged-num signed-reg
)
832 (define-data-vector-frobs simple-character-string movzxd
:dword
833 character character-reg
))
836 ;;; These vops are useful for accessing the bits of a vector
837 ;;; irrespective of what type of vector it is.
838 (define-full-reffer vector-raw-bits
* vector-data-offset other-pointer-lowtag
839 (unsigned-reg) unsigned-num %vector-raw-bits
)
840 (define-full-setter set-vector-raw-bits
* vector-data-offset other-pointer-lowtag
841 (unsigned-reg) unsigned-num %set-vector-raw-bits
)
843 ;;;; ATOMIC-INCF for arrays
845 (define-vop (array-atomic-incf/word
)
846 (:translate %array-atomic-incf
/word
)
848 (:args
(array :scs
(descriptor-reg))
849 (index :scs
(any-reg))
850 (diff :scs
(unsigned-reg) :target result
))
851 (:arg-types
* positive-fixnum unsigned-num
)
852 (:results
(result :scs
(unsigned-reg)))
853 (:result-types unsigned-num
)
855 (inst xadd
(make-ea :qword
:base array
856 :scale
(ash 1 (- word-shift n-fixnum-tag-bits
))
858 :disp
(- (* vector-data-offset n-word-bytes
)
859 other-pointer-lowtag
))