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 (+ (* (1+ 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)
45 (inst lea result (make-ea :qword :base result :disp other-pointer-lowtag))
46 (storew header result 0 other-pointer-lowtag))))
48 ;;;; additional accessors and setters for the array header
49 (define-full-reffer %array-dimension *
50 array-dimensions-offset other-pointer-lowtag
51 (any-reg) positive-fixnum sb!kernel:%array-dimension)
53 (define-full-setter %set-array-dimension *
54 array-dimensions-offset other-pointer-lowtag
55 (any-reg) positive-fixnum sb!kernel:%set-array-dimension)
57 (define-vop (array-rank-vop)
58 (:translate sb!kernel:%array-rank)
60 (:args (x :scs (descriptor-reg)))
61 (:results (res :scs (unsigned-reg)))
62 (:result-types positive-fixnum)
64 (loadw res x 0 other-pointer-lowtag)
65 (inst shr res n-widetag-bits)
66 (inst sub res (1- array-dimensions-offset))))
68 ;;;; bounds checking routine
70 ;;; Note that the immediate SC for the index argument is disabled
71 ;;; because it is not possible to generate a valid error code SC for
72 ;;; an immediate value.
74 ;;; FIXME: As per the KLUDGE note explaining the :IGNORE-FAILURE-P
75 ;;; flag in build-order.lisp-expr, compiling this file causes warnings
76 ;;; Argument FOO to VOP CHECK-BOUND has SC restriction
77 ;;; DESCRIPTOR-REG which is not allowed by the operand type:
78 ;;; (:OR POSITIVE-FIXNUM)
79 ;;; CSR's message "format ~/ /" on sbcl-devel 2002-03-12 contained
80 ;;; a possible patch, described as
81 ;;; Another patch is included more for information than anything --
82 ;;; removing the descriptor-reg SCs from the CHECK-BOUND vop in
83 ;;; x86/array.lisp seems to allow that file to compile without error[*],
84 ;;; and build; I haven't tested rebuilding capability, but I'd be
85 ;;; surprised if there were a problem. I'm not certain that this is the
86 ;;; correct fix, though, as the restrictions on the arguments to the VOP
87 ;;; aren't the same as in the sparc and alpha ports, where, incidentally,
88 ;;; the corresponding file builds without error currently.
89 ;;; Since neither of us (CSR or WHN) was quite sure that this is the
90 ;;; right thing, I've just recorded the patch here in hopes it might
91 ;;; help when someone attacks this problem again:
92 ;;; diff -u -r1.7 array.lisp
93 ;;; --- src/compiler/x86/array.lisp 11 Oct 2001 14:05:26 -0000 1.7
94 ;;; +++ src/compiler/x86/array.lisp 12 Mar 2002 12:23:37 -0000
95 ;;; @@ -76,10 +76,10 @@
96 ;;; (:translate %check-bound)
97 ;;; (:policy :fast-safe)
98 ;;; (:args (array :scs (descriptor-reg))
99 ;;; - (bound :scs (any-reg descriptor-reg))
100 ;;; - (index :scs (any-reg descriptor-reg #+nil immediate) :target result))
101 ;;; + (bound :scs (any-reg))
102 ;;; + (index :scs (any-reg #+nil immediate) :target result))
103 ;;; (:arg-types * positive-fixnum tagged-num)
104 ;;; - (:results (result :scs (any-reg descriptor-reg)))
105 ;;; + (:results (result :scs (any-reg)))
106 ;;; (:result-types positive-fixnum)
108 ;;; (:save-p :compute-only)
109 (define-vop (check-bound)
110 (:translate %check-bound)
112 (:args (array :scs (descriptor-reg))
113 (bound :scs (any-reg descriptor-reg))
114 (index :scs (any-reg descriptor-reg) :target result))
115 ; (:arg-types * positive-fixnum tagged-num)
116 (:results (result :scs (any-reg descriptor-reg)))
117 ; (:result-types positive-fixnum)
119 (:save-p :compute-only)
121 (let ((error (generate-error-code vop 'invalid-array-index-error
123 (index (if (sc-is index immediate)
124 (fixnumize (tn-value index))
126 (inst cmp bound index)
127 ;; We use below-or-equal even though it's an unsigned test,
128 ;; because negative indexes appear as large unsigned numbers.
129 ;; Therefore, we get the <0 and >=bound test all rolled into one.
131 (unless (and (tn-p index) (location= result index))
132 (inst mov result index)))))
134 ;;;; accessors/setters
136 ;;; variants built on top of WORD-INDEX-REF, etc. I.e., those vectors
137 ;;; whose elements are represented in integer registers and are built
138 ;;; out of 8, 16, or 32 bit elements.
139 (macrolet ((def-full-data-vector-frobs (type element-type &rest scs)
141 (define-full-reffer+offset
142 ,(symbolicate "DATA-VECTOR-REF-WITH-OFFSET/" type)
143 ,type vector-data-offset other-pointer-lowtag ,scs
144 ,element-type data-vector-ref-with-offset)
145 (define-full-setter+offset
146 ,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" type)
147 ,type vector-data-offset other-pointer-lowtag ,scs
148 ,element-type data-vector-set-with-offset)))
150 (def-full-data-vector-frobs simple-vector * descriptor-reg any-reg)
151 (def-full-data-vector-frobs simple-array-unsigned-byte-64 unsigned-num
153 (def-full-data-vector-frobs simple-array-fixnum tagged-num any-reg)
154 (def-full-data-vector-frobs simple-array-unsigned-fixnum
155 positive-fixnum any-reg)
156 (def-full-data-vector-frobs simple-array-signed-byte-64
157 signed-num signed-reg)
158 (def-full-data-vector-frobs simple-array-unsigned-byte-63 unsigned-num
161 (define-full-compare-and-swap %compare-and-swap-svref simple-vector
162 vector-data-offset other-pointer-lowtag
163 (descriptor-reg any-reg) *
164 %compare-and-swap-svref)
166 ;;;; integer vectors whose elements are smaller than a byte, i.e.,
167 ;;;; bit, 2-bit, and 4-bit vectors
169 (macrolet ((def-small-data-vector-frobs (type bits)
170 (let* ((elements-per-word (floor n-word-bits bits))
171 (bit-shift (1- (integer-length elements-per-word))))
173 (define-vop (,(symbolicate 'data-vector-ref-with-offset/ type))
174 (:note "inline array access")
175 (:translate data-vector-ref-with-offset)
177 (:args (object :scs (descriptor-reg))
178 (index :scs (unsigned-reg)))
180 (:arg-types ,type positive-fixnum (:constant (integer 0 0)))
181 (:results (result :scs (unsigned-reg) :from (:argument 0)))
182 (:result-types positive-fixnum)
183 (:temporary (:sc unsigned-reg :offset ecx-offset) ecx)
185 (aver (zerop offset))
187 (inst shr ecx ,bit-shift)
189 (make-ea :qword :base object :index ecx :scale n-word-bytes
190 :disp (- (* vector-data-offset n-word-bytes)
191 other-pointer-lowtag)))
193 ;; We used to mask ECX for all values of BITS, but since
194 ;; Intel's documentation says that the chip will mask shift
195 ;; and rotate counts by 63 automatically, we can safely move
196 ;; the masking operation under the protection of this UNLESS
197 ;; in the bit-vector case. --njf, 2006-07-14
199 `((inst and ecx ,(1- elements-per-word))
200 (inst shl ecx ,(1- (integer-length bits)))))
201 (inst shr result :cl)
202 (inst and result ,(1- (ash 1 bits)))))
203 (define-vop (,(symbolicate 'data-vector-ref-c-with-offset/ type))
204 (:translate data-vector-ref-with-offset)
206 (:args (object :scs (descriptor-reg)))
207 (:arg-types ,type (:constant low-index) (:constant (integer 0 0)))
209 (:results (result :scs (unsigned-reg)))
210 (:result-types positive-fixnum)
212 (aver (zerop offset))
213 (multiple-value-bind (word extra) (floor index ,elements-per-word)
214 (loadw result object (+ word vector-data-offset)
215 other-pointer-lowtag)
216 (unless (zerop extra)
217 (inst shr result (* extra ,bits)))
218 (unless (= extra ,(1- elements-per-word))
219 (inst and result ,(1- (ash 1 bits)))))))
220 (define-vop (,(symbolicate 'data-vector-set-with-offset/ type))
221 (:note "inline array store")
222 (:translate data-vector-set-with-offset)
224 (:args (object :scs (descriptor-reg))
225 (index :scs (unsigned-reg) :target ecx)
226 (value :scs (unsigned-reg immediate) :target result))
228 (:arg-types ,type positive-fixnum (:constant (integer 0 0))
230 (:results (result :scs (unsigned-reg)))
231 (:result-types positive-fixnum)
232 (:temporary (:sc unsigned-reg) word-index)
233 (:temporary (:sc unsigned-reg) old)
234 (:temporary (:sc unsigned-reg :offset ecx-offset) ecx)
236 (aver (zerop offset))
237 (move word-index index)
238 (inst shr word-index ,bit-shift)
240 (make-ea :qword :base object :index word-index
242 :disp (- (* vector-data-offset n-word-bytes)
243 other-pointer-lowtag)))
245 ;; We used to mask ECX for all values of BITS, but since
246 ;; Intel's documentation says that the chip will mask shift
247 ;; and rotate counts by 63 automatically, we can safely move
248 ;; the masking operation under the protection of this UNLESS
249 ;; in the bit-vector case. --njf, 2006-07-14
251 `((inst and ecx ,(1- elements-per-word))
252 (inst shl ecx ,(1- (integer-length bits)))))
254 (unless (and (sc-is value immediate)
255 (= (tn-value value) ,(1- (ash 1 bits))))
256 (inst and old ,(lognot (1- (ash 1 bits)))))
259 (unless (zerop (tn-value value))
260 (inst or old (logand (tn-value value) ,(1- (ash 1 bits))))))
262 (inst or old value)))
264 (inst mov (make-ea :qword :base object :index word-index
266 :disp (- (* vector-data-offset n-word-bytes)
267 other-pointer-lowtag))
271 (inst mov result (tn-value value)))
273 (move result value)))))
274 (define-vop (,(symbolicate 'data-vector-set-c-with-offset/ type))
275 (:translate data-vector-set-with-offset)
277 (:args (object :scs (descriptor-reg))
278 (value :scs (unsigned-reg immediate) :target result))
279 (:arg-types ,type (:constant low-index)
280 (:constant (integer 0 0)) positive-fixnum)
281 (:temporary (:sc unsigned-reg) mask-tn)
283 (:results (result :scs (unsigned-reg)))
284 (:result-types positive-fixnum)
285 (:temporary (:sc unsigned-reg :to (:result 0)) old)
287 (aver (zerop offset))
288 (multiple-value-bind (word extra) (floor index ,elements-per-word)
290 (make-ea :qword :base object
291 :disp (- (* (+ word vector-data-offset)
293 other-pointer-lowtag)))
296 (let* ((value (tn-value value))
297 (mask ,(1- (ash 1 bits)))
298 (shift (* extra ,bits)))
299 (unless (= value mask)
300 (inst mov mask-tn (ldb (byte 64 0)
301 (lognot (ash mask shift))))
302 (inst and old mask-tn))
303 (unless (zerop value)
304 (inst mov mask-tn (ash value shift))
305 (inst or old mask-tn))))
307 (let ((shift (* extra ,bits)))
308 (unless (zerop shift)
309 (inst ror old shift))
310 (inst mov mask-tn (lognot ,(1- (ash 1 bits))))
311 (inst and old mask-tn)
313 (unless (zerop shift)
314 (inst rol old shift)))))
315 (inst mov (make-ea :qword :base object
316 :disp (- (* (+ word vector-data-offset)
318 other-pointer-lowtag))
322 (inst mov result (tn-value value)))
324 (move result value))))))))))
325 (def-small-data-vector-frobs simple-bit-vector 1)
326 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
327 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
328 ;;; And the float variants.
330 (defun make-ea-for-float-ref (object index offset element-size
331 &key (scale 1) (complex-offset 0))
332 (let ((ea-size (if (= element-size 4) :dword :qword)))
335 (make-ea ea-size :base object
336 :disp (- (+ (* vector-data-offset n-word-bytes)
337 (* (+ index offset) element-size)
339 other-pointer-lowtag)))
341 (make-ea ea-size :base object :index index :scale scale
342 :disp (- (+ (* vector-data-offset n-word-bytes)
343 (* offset element-size)
345 other-pointer-lowtag))))))
348 (let ((use-temp (<= word-shift n-fixnum-tag-bits)))
349 `(define-vop (data-vector-ref-with-offset/simple-array-single-float)
350 (:note "inline array access")
351 (:translate data-vector-ref-with-offset)
353 (:args (object :scs (descriptor-reg))
354 (index :scs (any-reg)))
356 (:arg-types simple-array-single-float positive-fixnum
357 (:constant (constant-displacement other-pointer-lowtag
358 4 vector-data-offset)))
359 ,@(when use-temp '((:temporary (:sc unsigned-reg) dword-index)))
360 (:results (value :scs (single-reg)))
361 (:result-types single-float)
364 '((move dword-index index)
365 (inst shr dword-index (1+ (- n-fixnum-tag-bits word-shift)))
366 (inst movss value (make-ea-for-float-ref object dword-index offset 4)))
367 '((inst movss value (make-ea-for-float-ref object index offset 4
368 :scale (ash 4 (- n-fixnum-tag-bits)))))))))
370 (define-vop (data-vector-ref-c-with-offset/simple-array-single-float)
371 (:note "inline array access")
372 (:translate data-vector-ref-with-offset)
374 (:args (object :scs (descriptor-reg)))
376 (:arg-types simple-array-single-float (:constant low-index)
377 (:constant (constant-displacement other-pointer-lowtag
378 4 vector-data-offset)))
379 (:results (value :scs (single-reg)))
380 (:result-types single-float)
382 (inst movss value (make-ea-for-float-ref object index offset 4))))
385 (let ((use-temp (<= word-shift n-fixnum-tag-bits)))
386 `(define-vop (data-vector-set-with-offset/simple-array-single-float)
387 (:note "inline array store")
388 (:translate data-vector-set-with-offset)
390 (:args (object :scs (descriptor-reg))
391 (index :scs (any-reg))
392 (value :scs (single-reg) :target result))
394 (:arg-types simple-array-single-float positive-fixnum
395 (:constant (constant-displacement other-pointer-lowtag
396 4 vector-data-offset))
398 ,@(when use-temp '((:temporary (:sc unsigned-reg) dword-index)))
399 (:results (result :scs (single-reg)))
400 (:result-types single-float)
403 '((move dword-index index)
404 (inst shr dword-index (1+ (- n-fixnum-tag-bits word-shift)))
405 (inst movss (make-ea-for-float-ref object dword-index offset 4) value))
406 '((inst movss (make-ea-for-float-ref object index offset 4
407 :scale (ash 4 (- n-fixnum-tag-bits))) value)))
408 (move result value))))
410 (define-vop (data-vector-set-c-with-offset/simple-array-single-float)
411 (:note "inline array store")
412 (:translate data-vector-set-with-offset)
414 (:args (object :scs (descriptor-reg))
415 (value :scs (single-reg) :target result))
417 (:arg-types simple-array-single-float (:constant low-index)
418 (:constant (constant-displacement other-pointer-lowtag
419 4 vector-data-offset))
421 (:results (result :scs (single-reg)))
422 (:result-types single-float)
424 (inst movss (make-ea-for-float-ref object index offset 4) value)
425 (move result value)))
427 (define-vop (data-vector-ref-with-offset/simple-array-double-float)
428 (:note "inline array access")
429 (:translate data-vector-ref-with-offset)
431 (:args (object :scs (descriptor-reg))
432 (index :scs (any-reg)))
434 (:arg-types simple-array-double-float positive-fixnum
435 (:constant (constant-displacement other-pointer-lowtag
436 8 vector-data-offset)))
437 (:results (value :scs (double-reg)))
438 (:result-types double-float)
440 (inst movsd value (make-ea-for-float-ref object index offset 8
441 :scale (ash 1 (- word-shift n-fixnum-tag-bits))))))
443 (define-vop (data-vector-ref-c/simple-array-double-float)
444 (:note "inline array access")
445 (:translate data-vector-ref-with-offset)
447 (:args (object :scs (descriptor-reg)))
449 (:arg-types simple-array-double-float (:constant low-index)
450 (:constant (constant-displacement other-pointer-lowtag
451 8 vector-data-offset)))
452 (:results (value :scs (double-reg)))
453 (:result-types double-float)
455 (inst movsd value (make-ea-for-float-ref object index offset 8))))
457 (define-vop (data-vector-set-with-offset/simple-array-double-float)
458 (:note "inline array store")
459 (:translate data-vector-set-with-offset)
461 (:args (object :scs (descriptor-reg))
462 (index :scs (any-reg))
463 (value :scs (double-reg) :target result))
465 (:arg-types simple-array-double-float positive-fixnum
466 (:constant (constant-displacement other-pointer-lowtag
467 8 vector-data-offset))
469 (:results (result :scs (double-reg)))
470 (:result-types double-float)
472 (inst movsd (make-ea-for-float-ref object index offset 8
473 :scale (ash 1 (- word-shift n-fixnum-tag-bits)))
475 (move result value)))
477 (define-vop (data-vector-set-c-with-offset/simple-array-double-float)
478 (:note "inline array store")
479 (:translate data-vector-set-with-offset)
481 (:args (object :scs (descriptor-reg))
482 (value :scs (double-reg) :target result))
484 (:arg-types simple-array-double-float (:constant low-index)
485 (:constant (constant-displacement other-pointer-lowtag
486 8 vector-data-offset))
488 (:results (result :scs (double-reg)))
489 (:result-types double-float)
491 (inst movsd (make-ea-for-float-ref object index offset 8) value)
492 (move result value)))
495 ;;; complex float variants
497 (define-vop (data-vector-ref-with-offset/simple-array-complex-single-float)
498 (:note "inline array access")
499 (:translate data-vector-ref-with-offset)
501 (:args (object :scs (descriptor-reg))
502 (index :scs (any-reg)))
504 (:arg-types simple-array-complex-single-float positive-fixnum
505 (:constant (constant-displacement other-pointer-lowtag
506 8 vector-data-offset)))
507 (:results (value :scs (complex-single-reg)))
508 (:result-types complex-single-float)
510 (inst movq value (make-ea-for-float-ref object index offset 8
511 :scale (ash 1 (- word-shift n-fixnum-tag-bits))))))
513 (define-vop (data-vector-ref-c-with-offset/simple-array-complex-single-float)
514 (:note "inline array access")
515 (:translate data-vector-ref-with-offset)
517 (:args (object :scs (descriptor-reg)))
519 (:arg-types simple-array-complex-single-float (:constant low-index)
520 (:constant (constant-displacement other-pointer-lowtag
521 8 vector-data-offset)))
522 (:results (value :scs (complex-single-reg)))
523 (:result-types complex-single-float)
525 (inst movq value (make-ea-for-float-ref object index offset 8))))
527 (define-vop (data-vector-set-with-offset/simple-array-complex-single-float)
528 (:note "inline array store")
529 (:translate data-vector-set-with-offset)
531 (:args (object :scs (descriptor-reg))
532 (index :scs (any-reg))
533 (value :scs (complex-single-reg) :target result))
535 (:arg-types simple-array-complex-single-float positive-fixnum
536 (:constant (constant-displacement other-pointer-lowtag
537 8 vector-data-offset))
538 complex-single-float)
539 (:results (result :scs (complex-single-reg)))
540 (:result-types complex-single-float)
543 (inst movq (make-ea-for-float-ref object index offset 8
544 :scale (ash 1 (- word-shift n-fixnum-tag-bits)))
547 (define-vop (data-vector-set-c-with-offset/simple-array-complex-single-float)
548 (:note "inline array store")
549 (:translate data-vector-set-with-offset)
551 (:args (object :scs (descriptor-reg))
552 (value :scs (complex-single-reg) :target result))
554 (:arg-types simple-array-complex-single-float (:constant low-index)
555 (:constant (constant-displacement other-pointer-lowtag
556 8 vector-data-offset))
557 complex-single-float)
558 (:results (result :scs (complex-single-reg)))
559 (:result-types complex-single-float)
562 (inst movq (make-ea-for-float-ref object index offset 8) value)))
564 (define-vop (data-vector-ref-with-offset/simple-array-complex-double-float)
565 (:note "inline array access")
566 (:translate data-vector-ref-with-offset)
568 (:args (object :scs (descriptor-reg))
569 (index :scs (any-reg)))
571 (:arg-types simple-array-complex-double-float positive-fixnum
572 (:constant (constant-displacement other-pointer-lowtag
573 16 vector-data-offset)))
574 (:results (value :scs (complex-double-reg)))
575 (:result-types complex-double-float)
577 (inst movapd value (make-ea-for-float-ref object index offset 16
578 :scale (ash 2 (- word-shift n-fixnum-tag-bits))))))
580 (define-vop (data-vector-ref-c-with-offset/simple-array-complex-double-float)
581 (:note "inline array access")
582 (:translate data-vector-ref-with-offset)
584 (:args (object :scs (descriptor-reg)))
586 (:arg-types simple-array-complex-double-float (:constant low-index)
587 (:constant (constant-displacement other-pointer-lowtag
588 16 vector-data-offset)))
589 (:results (value :scs (complex-double-reg)))
590 (:result-types complex-double-float)
592 (inst movapd value (make-ea-for-float-ref object index offset 16))))
594 (define-vop (data-vector-set-with-offset/simple-array-complex-double-float)
595 (:note "inline array store")
596 (:translate data-vector-set-with-offset)
598 (:args (object :scs (descriptor-reg))
599 (index :scs (any-reg))
600 (value :scs (complex-double-reg) :target result))
602 (:arg-types simple-array-complex-double-float positive-fixnum
603 (:constant (constant-displacement other-pointer-lowtag
604 16 vector-data-offset))
605 complex-double-float)
606 (:results (result :scs (complex-double-reg)))
607 (:result-types complex-double-float)
609 (inst movapd (make-ea-for-float-ref object index offset 16
610 :scale (ash 2 (- word-shift n-fixnum-tag-bits)))
612 (move result value)))
614 (define-vop (data-vector-set-c-with-offset/simple-array-complex-double-float)
615 (:note "inline array store")
616 (:translate data-vector-set-with-offset)
618 (:args (object :scs (descriptor-reg))
619 (value :scs (complex-double-reg) :target result))
621 (:arg-types simple-array-complex-double-float (:constant low-index)
622 (:constant (constant-displacement other-pointer-lowtag
623 16 vector-data-offset))
624 complex-double-float)
625 (:results (result :scs (complex-double-reg)))
626 (:result-types complex-double-float)
628 (inst movapd (make-ea-for-float-ref object index offset 16) value)
629 (move result value)))
633 ;;; {un,}signed-byte-{8,16,32} and characters
634 (macrolet ((define-data-vector-frobs (ptype mov-inst operand-size
636 (let ((n-bytes (ecase operand-size
640 (multiple-value-bind (index-sc scale)
641 (if (>= n-bytes (ash 1 n-fixnum-tag-bits))
642 (values 'any-reg (ash n-bytes (- n-fixnum-tag-bits)))
643 (values 'unsigned-reg n-bytes))
645 (define-vop (,(symbolicate "DATA-VECTOR-REF-WITH-OFFSET/" ptype))
646 (:translate data-vector-ref-with-offset)
648 (:args (object :scs (descriptor-reg))
649 (index :scs (,index-sc)))
651 (:arg-types ,ptype positive-fixnum
652 (:constant (constant-displacement other-pointer-lowtag
653 ,n-bytes vector-data-offset)))
654 (:results (value :scs ,scs))
655 (:result-types ,type)
657 (inst ,mov-inst value
658 (make-ea ,operand-size :base object :index index :scale ,scale
659 :disp (- (+ (* vector-data-offset n-word-bytes)
661 other-pointer-lowtag)))))
662 (define-vop (,(symbolicate "DATA-VECTOR-REF-C-WITH-OFFSET/" ptype))
663 (:translate data-vector-ref-with-offset)
665 (:args (object :scs (descriptor-reg)))
667 (:arg-types ,ptype (:constant low-index)
668 (:constant (constant-displacement other-pointer-lowtag
669 ,n-bytes vector-data-offset)))
670 (:results (value :scs ,scs))
671 (:result-types ,type)
673 (inst ,mov-inst value
674 (make-ea ,operand-size :base object
675 :disp (- (+ (* vector-data-offset n-word-bytes)
678 other-pointer-lowtag)))))
679 (define-vop (,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" ptype))
680 (:translate data-vector-set-with-offset)
682 (:args (object :scs (descriptor-reg) :to (:eval 0))
683 (index :scs (,index-sc) :to (:eval 0))
684 (value :scs ,scs :target result))
686 (:arg-types ,ptype positive-fixnum
687 (:constant (constant-displacement other-pointer-lowtag
688 ,n-bytes vector-data-offset))
690 (:results (result :scs ,scs))
691 (:result-types ,type)
693 (inst mov (make-ea ,operand-size :base object :index index :scale ,scale
694 :disp (- (+ (* vector-data-offset n-word-bytes)
696 other-pointer-lowtag))
697 (reg-in-size value ,operand-size))
698 (move result value)))
700 (define-vop (,(symbolicate "DATA-VECTOR-SET-C-WITH-OFFSET/" ptype))
701 (:translate data-vector-set-with-offset)
703 (:args (object :scs (descriptor-reg) :to (:eval 0))
704 (value :scs ,scs :target result))
706 (:arg-types ,ptype (:constant low-index)
707 (:constant (constant-displacement other-pointer-lowtag
708 ,n-bytes vector-data-offset))
710 (:results (result :scs ,scs))
711 (:result-types ,type)
713 (inst mov (make-ea ,operand-size :base object
714 :disp (- (+ (* vector-data-offset n-word-bytes)
717 other-pointer-lowtag))
718 (reg-in-size value ,operand-size))
719 (move result value))))))))
720 (define-data-vector-frobs simple-array-unsigned-byte-7 movzx :byte
721 positive-fixnum unsigned-reg signed-reg)
722 (define-data-vector-frobs simple-array-unsigned-byte-8 movzx :byte
723 positive-fixnum unsigned-reg signed-reg)
724 (define-data-vector-frobs simple-array-signed-byte-8 movsx :byte
725 tagged-num signed-reg)
726 (define-data-vector-frobs simple-base-string
727 #!+sb-unicode movzx #!-sb-unicode mov :byte
728 character character-reg)
729 (define-data-vector-frobs simple-array-unsigned-byte-15 movzx :word
730 positive-fixnum unsigned-reg signed-reg)
731 (define-data-vector-frobs simple-array-unsigned-byte-16 movzx :word
732 positive-fixnum unsigned-reg signed-reg)
733 (define-data-vector-frobs simple-array-signed-byte-16 movsx :word
734 tagged-num signed-reg)
735 (define-data-vector-frobs simple-array-unsigned-byte-32 movzxd :dword
736 positive-fixnum unsigned-reg signed-reg)
737 (define-data-vector-frobs simple-array-unsigned-byte-31 movzxd :dword
738 positive-fixnum unsigned-reg signed-reg)
739 (define-data-vector-frobs simple-array-signed-byte-32 movsxd :dword
740 tagged-num signed-reg)
742 (define-data-vector-frobs simple-character-string movzxd :dword
743 character character-reg))
746 ;;; These vops are useful for accessing the bits of a vector
747 ;;; irrespective of what type of vector it is.
748 (define-full-reffer vector-raw-bits * vector-data-offset other-pointer-lowtag
749 (unsigned-reg) unsigned-num %vector-raw-bits)
750 (define-full-setter set-vector-raw-bits * vector-data-offset other-pointer-lowtag
751 (unsigned-reg) unsigned-num %set-vector-raw-bits)
753 ;;;; miscellaneous array VOPs
755 (define-vop (get-vector-subtype get-header-data))
756 (define-vop (set-vector-subtype set-header-data))
758 ;;;; ATOMIC-INCF for arrays
760 (define-vop (array-atomic-incf/word)
761 (:translate %array-atomic-incf/word)
763 (:args (array :scs (descriptor-reg))
764 (index :scs (any-reg))
765 (diff :scs (unsigned-reg) :target result))
766 (:arg-types * positive-fixnum unsigned-num)
767 (:results (result :scs (unsigned-reg)))
768 (:result-types unsigned-num)
770 (inst xadd (make-ea :qword :base array
771 :scale (ash 1 (- word-shift n-fixnum-tag-bits))
773 :disp (- (* vector-data-offset n-word-bytes)
774 other-pointer-lowtag))