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.
14 ;;;; allocator for the array header
16 (define-vop (make-array-header)
17 (:translate make-array-header)
19 (:args (type :scs (any-reg))
20 (rank :scs (any-reg)))
21 (:arg-types positive-fixnum positive-fixnum)
22 (:temporary (:sc any-reg :to :eval) bytes)
23 (:temporary (:sc any-reg :to :result) header)
24 (:results (result :scs (descriptor-reg) :from :eval))
28 (make-ea :dword :base rank
29 :disp (+ (* (1+ array-dimensions-offset) n-word-bytes)
31 (inst and bytes (lognot lowtag-mask))
32 (inst lea header (make-ea :dword :base rank
33 :disp (fixnumize (1- array-dimensions-offset))))
34 (inst shl header n-widetag-bits)
38 (allocation result bytes node)
39 (inst lea result (make-ea :dword :base result :disp other-pointer-lowtag))
40 (storew header result 0 other-pointer-lowtag))))
42 ;;;; additional accessors and setters for the array header
43 (define-full-reffer %array-dimension *
44 array-dimensions-offset other-pointer-lowtag
45 (any-reg) positive-fixnum sb!kernel:%array-dimension)
47 (define-full-setter %set-array-dimension *
48 array-dimensions-offset other-pointer-lowtag
49 (any-reg) positive-fixnum sb!kernel:%set-array-dimension)
51 (define-vop (array-rank-vop)
52 (:translate sb!kernel:%array-rank)
54 (:args (x :scs (descriptor-reg)))
55 (:results (res :scs (unsigned-reg)))
56 (:result-types positive-fixnum)
58 (loadw res x 0 other-pointer-lowtag)
59 (inst shr res n-widetag-bits)
60 (inst sub res (1- array-dimensions-offset))))
62 ;;;; bounds checking routine
64 ;;; Note that the immediate SC for the index argument is disabled
65 ;;; because it is not possible to generate a valid error code SC for
66 ;;; an immediate value.
68 ;;; FIXME: As per the KLUDGE note explaining the :IGNORE-FAILURE-P
69 ;;; flag in build-order.lisp-expr, compiling this file causes warnings
70 ;;; Argument FOO to VOP CHECK-BOUND has SC restriction
71 ;;; DESCRIPTOR-REG which is not allowed by the operand type:
72 ;;; (:OR POSITIVE-FIXNUM)
73 ;;; CSR's message "format ~/ /" on sbcl-devel 2002-03-12 contained
74 ;;; a possible patch, described as
75 ;;; Another patch is included more for information than anything --
76 ;;; removing the descriptor-reg SCs from the CHECK-BOUND vop in
77 ;;; x86/array.lisp seems to allow that file to compile without error[*],
78 ;;; and build; I haven't tested rebuilding capability, but I'd be
79 ;;; surprised if there were a problem. I'm not certain that this is the
80 ;;; correct fix, though, as the restrictions on the arguments to the VOP
81 ;;; aren't the same as in the sparc and alpha ports, where, incidentally,
82 ;;; the corresponding file builds without error currently.
83 ;;; Since neither of us (CSR or WHN) was quite sure that this is the
84 ;;; right thing, I've just recorded the patch here in hopes it might
85 ;;; help when someone attacks this problem again:
86 ;;; diff -u -r1.7 array.lisp
87 ;;; --- src/compiler/x86/array.lisp 11 Oct 2001 14:05:26 -0000 1.7
88 ;;; +++ src/compiler/x86/array.lisp 12 Mar 2002 12:23:37 -0000
89 ;;; @@ -76,10 +76,10 @@
90 ;;; (:translate %check-bound)
91 ;;; (:policy :fast-safe)
92 ;;; (:args (array :scs (descriptor-reg))
93 ;;; - (bound :scs (any-reg descriptor-reg))
94 ;;; - (index :scs (any-reg descriptor-reg #+nil immediate) :target result))
95 ;;; + (bound :scs (any-reg))
96 ;;; + (index :scs (any-reg #+nil immediate) :target result))
97 ;;; (:arg-types * positive-fixnum tagged-num)
98 ;;; - (:results (result :scs (any-reg descriptor-reg)))
99 ;;; + (:results (result :scs (any-reg)))
100 ;;; (:result-types positive-fixnum)
102 ;;; (:save-p :compute-only)
103 (define-vop (check-bound)
104 (:translate %check-bound)
106 (:args (array :scs (descriptor-reg))
107 (bound :scs (any-reg))
108 (index :scs (any-reg #+nil immediate) :target result))
109 (:arg-types * positive-fixnum tagged-num)
110 (:results (result :scs (any-reg)))
111 (:result-types positive-fixnum)
113 (:save-p :compute-only)
115 (let ((error (generate-error-code vop invalid-array-index-error
117 (index (if (sc-is index immediate)
118 (fixnumize (tn-value index))
120 (inst cmp bound index)
121 ;; We use below-or-equal even though it's an unsigned test,
122 ;; because negative indexes appear as large unsigned numbers.
123 ;; Therefore, we get the <0 and >=bound test all rolled into one.
125 (unless (and (tn-p index) (location= result index))
126 (inst mov result index)))))
128 ;;;; accessors/setters
130 ;;; variants built on top of WORD-INDEX-REF, etc. I.e., those vectors
131 ;;; whose elements are represented in integer registers and are built
132 ;;; out of 8, 16, or 32 bit elements.
133 (macrolet ((def-full-data-vector-frobs (type element-type &rest scs)
135 (define-full-reffer ,(symbolicate "DATA-VECTOR-REF/" type)
136 ,type vector-data-offset other-pointer-lowtag ,scs
137 ,element-type data-vector-ref)
138 (define-full-setter ,(symbolicate "DATA-VECTOR-SET/" type)
139 ,type vector-data-offset other-pointer-lowtag ,scs
140 ,element-type data-vector-set))))
141 (def-full-data-vector-frobs simple-vector * descriptor-reg any-reg)
142 (def-full-data-vector-frobs simple-array-unsigned-byte-32 unsigned-num
144 (def-full-data-vector-frobs simple-array-signed-byte-30 tagged-num any-reg)
145 (def-full-data-vector-frobs simple-array-unsigned-byte-29 positive-fixnum any-reg)
146 (def-full-data-vector-frobs simple-array-signed-byte-32 signed-num
148 (def-full-data-vector-frobs simple-array-unsigned-byte-31 unsigned-num
151 ;;;; integer vectors whose elements are smaller than a byte, i.e.,
152 ;;;; bit, 2-bit, and 4-bit vectors
154 (macrolet ((def-small-data-vector-frobs (type bits)
155 (let* ((elements-per-word (floor n-word-bits bits))
156 (bit-shift (1- (integer-length elements-per-word))))
158 (define-vop (,(symbolicate 'data-vector-ref/ type))
159 (:note "inline array access")
160 (:translate data-vector-ref)
162 (:args (object :scs (descriptor-reg))
163 (index :scs (unsigned-reg)))
164 (:arg-types ,type positive-fixnum)
165 (:results (result :scs (unsigned-reg) :from (:argument 0)))
166 (:result-types positive-fixnum)
167 (:temporary (:sc unsigned-reg :offset ecx-offset) ecx)
170 (inst shr ecx ,bit-shift)
172 (make-ea :dword :base object :index ecx :scale 4
173 :disp (- (* vector-data-offset n-word-bytes)
174 other-pointer-lowtag)))
176 ;; We used to mask ECX for all values of ELEMENT-PER-WORD,
177 ;; but since Intel's documentation says that the chip will
178 ;; mask shift and rotate counts by 31 automatically, we can
179 ;; safely move the masking operation under the protection of
180 ;; this UNLESS in the bit-vector case. --njf, 2006-07-14
181 ,@(unless (= elements-per-word n-word-bits)
182 `((inst and ecx ,(1- elements-per-word))
183 (inst shl ecx ,(1- (integer-length bits)))))
184 (inst shr result :cl)
185 (inst and result ,(1- (ash 1 bits)))))
186 (define-vop (,(symbolicate 'data-vector-ref-c/ type))
187 (:translate data-vector-ref)
189 (:args (object :scs (descriptor-reg)))
190 (:arg-types ,type (:constant index))
192 (:results (result :scs (unsigned-reg)))
193 (:result-types positive-fixnum)
195 (multiple-value-bind (word extra) (floor index ,elements-per-word)
196 (loadw result object (+ word vector-data-offset)
197 other-pointer-lowtag)
198 (unless (zerop extra)
199 (inst shr result (* extra ,bits)))
200 (unless (= extra ,(1- elements-per-word))
201 (inst and result ,(1- (ash 1 bits)))))))
202 (define-vop (,(symbolicate 'data-vector-set/ type))
203 (:note "inline array store")
204 (:translate data-vector-set)
206 (:args (object :scs (descriptor-reg))
207 (index :scs (unsigned-reg) :target ecx)
208 (value :scs (unsigned-reg immediate) :target result))
209 (:arg-types ,type positive-fixnum positive-fixnum)
210 (:results (result :scs (unsigned-reg)))
211 (:result-types positive-fixnum)
212 (:temporary (:sc unsigned-reg) word-index)
213 (:temporary (:sc unsigned-reg) old)
214 (:temporary (:sc unsigned-reg :offset ecx-offset) ecx)
216 (move word-index index)
217 (inst shr word-index ,bit-shift)
219 (make-ea :dword :base object :index word-index :scale 4
220 :disp (- (* vector-data-offset n-word-bytes)
221 other-pointer-lowtag)))
223 ;; We used to mask ECX for all values of ELEMENT-PER-WORD,
224 ;; but since Intel's documentation says that the chip will
225 ;; mask shift and rotate counts by 31 automatically, we can
226 ;; safely move the masking operation under the protection of
227 ;; this UNLESS in the bit-vector case. --njf, 2006-07-14
228 ,@(unless (= elements-per-word n-word-bits)
229 `((inst and ecx ,(1- elements-per-word))
230 (inst shl ecx ,(1- (integer-length bits)))))
232 (unless (and (sc-is value immediate)
233 (= (tn-value value) ,(1- (ash 1 bits))))
234 (inst and old ,(lognot (1- (ash 1 bits)))))
237 (unless (zerop (tn-value value))
238 (inst or old (logand (tn-value value) ,(1- (ash 1 bits))))))
240 (inst or old value)))
242 (inst mov (make-ea :dword :base object :index word-index :scale 4
243 :disp (- (* vector-data-offset n-word-bytes)
244 other-pointer-lowtag))
248 (inst mov result (tn-value value)))
250 (move result value)))))
251 (define-vop (,(symbolicate 'data-vector-set-c/ type))
252 (:translate data-vector-set)
254 (:args (object :scs (descriptor-reg))
255 (value :scs (unsigned-reg immediate) :target result))
256 (:arg-types ,type (:constant index) positive-fixnum)
258 (:results (result :scs (unsigned-reg)))
259 (:result-types positive-fixnum)
260 (:temporary (:sc unsigned-reg :to (:result 0)) old)
262 (multiple-value-bind (word extra) (floor index ,elements-per-word)
264 (make-ea :dword :base object
265 :disp (- (* (+ word vector-data-offset)
267 other-pointer-lowtag)))
270 (let* ((value (tn-value value))
271 (mask ,(1- (ash 1 bits)))
272 (shift (* extra ,bits)))
273 (unless (= value mask)
274 (inst and old (ldb (byte n-word-bits 0)
275 (lognot (ash mask shift)))))
276 (unless (zerop value)
277 (inst or old (ash value shift)))))
279 (let ((shift (* extra ,bits)))
280 (unless (zerop shift)
281 (inst ror old shift))
282 (inst and old (lognot ,(1- (ash 1 bits))))
284 (unless (zerop shift)
285 (inst rol old shift)))))
286 (inst mov (make-ea :dword :base object
287 :disp (- (* (+ word vector-data-offset)
289 other-pointer-lowtag))
293 (inst mov result (tn-value value)))
295 (move result value))))))))))
296 (def-small-data-vector-frobs simple-bit-vector 1)
297 (def-small-data-vector-frobs simple-array-unsigned-byte-2 2)
298 (def-small-data-vector-frobs simple-array-unsigned-byte-4 4))
300 ;;; And the float variants.
302 (define-vop (data-vector-ref/simple-array-single-float)
303 (:note "inline array access")
304 (:translate data-vector-ref)
306 (:args (object :scs (descriptor-reg))
307 (index :scs (any-reg)))
308 (:arg-types simple-array-single-float positive-fixnum)
309 (:results (value :scs (single-reg)))
310 (:result-types single-float)
312 (with-empty-tn@fp-top(value)
313 (inst fld (make-ea :dword :base object :index index :scale 1
314 :disp (- (* vector-data-offset
316 other-pointer-lowtag))))))
318 (define-vop (data-vector-ref-c/simple-array-single-float)
319 (:note "inline array access")
320 (:translate data-vector-ref)
322 (:args (object :scs (descriptor-reg)))
324 (:arg-types simple-array-single-float (:constant (signed-byte 30)))
325 (:results (value :scs (single-reg)))
326 (:result-types single-float)
328 (with-empty-tn@fp-top(value)
329 (inst fld (make-ea :dword :base object
330 :disp (- (+ (* vector-data-offset
333 other-pointer-lowtag))))))
335 (define-vop (data-vector-set/simple-array-single-float)
336 (:note "inline array store")
337 (:translate data-vector-set)
339 (:args (object :scs (descriptor-reg))
340 (index :scs (any-reg))
341 (value :scs (single-reg) :target result))
342 (:arg-types simple-array-single-float positive-fixnum single-float)
343 (:results (result :scs (single-reg)))
344 (:result-types single-float)
346 (cond ((zerop (tn-offset value))
348 (inst fst (make-ea :dword :base object :index index :scale 1
349 :disp (- (* vector-data-offset
351 other-pointer-lowtag)))
352 (unless (zerop (tn-offset result))
353 ;; Value is in ST0 but not result.
356 ;; Value is not in ST0.
358 (inst fst (make-ea :dword :base object :index index :scale 1
359 :disp (- (* vector-data-offset
361 other-pointer-lowtag)))
362 (cond ((zerop (tn-offset result))
363 ;; The result is in ST0.
366 ;; Neither value or result are in ST0
367 (unless (location= value result)
369 (inst fxch value)))))))
371 (define-vop (data-vector-set-c/simple-array-single-float)
372 (:note "inline array store")
373 (:translate data-vector-set)
375 (:args (object :scs (descriptor-reg))
376 (value :scs (single-reg) :target result))
378 (:arg-types simple-array-single-float (:constant (signed-byte 30))
380 (:results (result :scs (single-reg)))
381 (:result-types single-float)
383 (cond ((zerop (tn-offset value))
385 (inst fst (make-ea :dword :base object
386 :disp (- (+ (* vector-data-offset
389 other-pointer-lowtag)))
390 (unless (zerop (tn-offset result))
391 ;; Value is in ST0 but not result.
394 ;; Value is not in ST0.
396 (inst fst (make-ea :dword :base object
397 :disp (- (+ (* vector-data-offset
400 other-pointer-lowtag)))
401 (cond ((zerop (tn-offset result))
402 ;; The result is in ST0.
405 ;; Neither value or result are in ST0
406 (unless (location= value result)
408 (inst fxch value)))))))
410 (define-vop (data-vector-ref/simple-array-double-float)
411 (:note "inline array access")
412 (:translate data-vector-ref)
414 (:args (object :scs (descriptor-reg))
415 (index :scs (any-reg)))
416 (:arg-types simple-array-double-float positive-fixnum)
417 (:results (value :scs (double-reg)))
418 (:result-types double-float)
420 (with-empty-tn@fp-top(value)
421 (inst fldd (make-ea :dword :base object :index index :scale 2
422 :disp (- (* vector-data-offset
424 other-pointer-lowtag))))))
426 (define-vop (data-vector-ref-c/simple-array-double-float)
427 (:note "inline array access")
428 (:translate data-vector-ref)
430 (:args (object :scs (descriptor-reg)))
432 (:arg-types simple-array-double-float (:constant (signed-byte 30)))
433 (:results (value :scs (double-reg)))
434 (:result-types double-float)
436 (with-empty-tn@fp-top(value)
437 (inst fldd (make-ea :dword :base object
438 :disp (- (+ (* vector-data-offset
441 other-pointer-lowtag))))))
443 (define-vop (data-vector-set/simple-array-double-float)
444 (:note "inline array store")
445 (:translate data-vector-set)
447 (:args (object :scs (descriptor-reg))
448 (index :scs (any-reg))
449 (value :scs (double-reg) :target result))
450 (:arg-types simple-array-double-float positive-fixnum double-float)
451 (:results (result :scs (double-reg)))
452 (:result-types double-float)
454 (cond ((zerop (tn-offset value))
456 (inst fstd (make-ea :dword :base object :index index :scale 2
457 :disp (- (* vector-data-offset
459 other-pointer-lowtag)))
460 (unless (zerop (tn-offset result))
461 ;; Value is in ST0 but not result.
464 ;; Value is not in ST0.
466 (inst fstd (make-ea :dword :base object :index index :scale 2
467 :disp (- (* vector-data-offset
469 other-pointer-lowtag)))
470 (cond ((zerop (tn-offset result))
471 ;; The result is in ST0.
474 ;; Neither value or result are in ST0
475 (unless (location= value result)
477 (inst fxch value)))))))
479 (define-vop (data-vector-set-c/simple-array-double-float)
480 (:note "inline array store")
481 (:translate data-vector-set)
483 (:args (object :scs (descriptor-reg))
484 (value :scs (double-reg) :target result))
486 (:arg-types simple-array-double-float (:constant (signed-byte 30))
488 (:results (result :scs (double-reg)))
489 (:result-types double-float)
491 (cond ((zerop (tn-offset value))
493 (inst fstd (make-ea :dword :base object
494 :disp (- (+ (* vector-data-offset
497 other-pointer-lowtag)))
498 (unless (zerop (tn-offset result))
499 ;; Value is in ST0 but not result.
502 ;; Value is not in ST0.
504 (inst fstd (make-ea :dword :base object
505 :disp (- (+ (* vector-data-offset
508 other-pointer-lowtag)))
509 (cond ((zerop (tn-offset result))
510 ;; The result is in ST0.
513 ;; Neither value or result are in ST0
514 (unless (location= value result)
516 (inst fxch value)))))))
520 ;;; complex float variants
522 (define-vop (data-vector-ref/simple-array-complex-single-float)
523 (:note "inline array access")
524 (:translate data-vector-ref)
526 (:args (object :scs (descriptor-reg))
527 (index :scs (any-reg)))
528 (:arg-types simple-array-complex-single-float positive-fixnum)
529 (:results (value :scs (complex-single-reg)))
530 (:result-types complex-single-float)
532 (let ((real-tn (complex-single-reg-real-tn value)))
533 (with-empty-tn@fp-top (real-tn)
534 (inst fld (make-ea :dword :base object :index index :scale 2
535 :disp (- (* vector-data-offset
537 other-pointer-lowtag)))))
538 (let ((imag-tn (complex-single-reg-imag-tn value)))
539 (with-empty-tn@fp-top (imag-tn)
540 (inst fld (make-ea :dword :base object :index index :scale 2
541 :disp (- (* (1+ vector-data-offset)
543 other-pointer-lowtag)))))))
545 (define-vop (data-vector-ref-c/simple-array-complex-single-float)
546 (:note "inline array access")
547 (:translate data-vector-ref)
549 (:args (object :scs (descriptor-reg)))
551 (:arg-types simple-array-complex-single-float (:constant (signed-byte 30)))
552 (:results (value :scs (complex-single-reg)))
553 (:result-types complex-single-float)
555 (let ((real-tn (complex-single-reg-real-tn value)))
556 (with-empty-tn@fp-top (real-tn)
557 (inst fld (make-ea :dword :base object
558 :disp (- (+ (* vector-data-offset
561 other-pointer-lowtag)))))
562 (let ((imag-tn (complex-single-reg-imag-tn value)))
563 (with-empty-tn@fp-top (imag-tn)
564 (inst fld (make-ea :dword :base object
565 :disp (- (+ (* vector-data-offset
568 other-pointer-lowtag)))))))
570 (define-vop (data-vector-set/simple-array-complex-single-float)
571 (:note "inline array store")
572 (:translate data-vector-set)
574 (:args (object :scs (descriptor-reg))
575 (index :scs (any-reg))
576 (value :scs (complex-single-reg) :target result))
577 (:arg-types simple-array-complex-single-float positive-fixnum
578 complex-single-float)
579 (:results (result :scs (complex-single-reg)))
580 (:result-types complex-single-float)
582 (let ((value-real (complex-single-reg-real-tn value))
583 (result-real (complex-single-reg-real-tn result)))
584 (cond ((zerop (tn-offset value-real))
586 (inst fst (make-ea :dword :base object :index index :scale 2
587 :disp (- (* vector-data-offset
589 other-pointer-lowtag)))
590 (unless (zerop (tn-offset result-real))
591 ;; Value is in ST0 but not result.
592 (inst fst result-real)))
594 ;; Value is not in ST0.
595 (inst fxch value-real)
596 (inst fst (make-ea :dword :base object :index index :scale 2
597 :disp (- (* vector-data-offset
599 other-pointer-lowtag)))
600 (cond ((zerop (tn-offset result-real))
601 ;; The result is in ST0.
602 (inst fst value-real))
604 ;; Neither value or result are in ST0
605 (unless (location= value-real result-real)
606 (inst fst result-real))
607 (inst fxch value-real))))))
608 (let ((value-imag (complex-single-reg-imag-tn value))
609 (result-imag (complex-single-reg-imag-tn result)))
610 (inst fxch value-imag)
611 (inst fst (make-ea :dword :base object :index index :scale 2
612 :disp (- (+ (* vector-data-offset
615 other-pointer-lowtag)))
616 (unless (location= value-imag result-imag)
617 (inst fst result-imag))
618 (inst fxch value-imag))))
620 (define-vop (data-vector-set-c/simple-array-complex-single-float)
621 (:note "inline array store")
622 (:translate data-vector-set)
624 (:args (object :scs (descriptor-reg))
625 (value :scs (complex-single-reg) :target result))
627 (:arg-types simple-array-complex-single-float (:constant (signed-byte 30))
628 complex-single-float)
629 (:results (result :scs (complex-single-reg)))
630 (:result-types complex-single-float)
632 (let ((value-real (complex-single-reg-real-tn value))
633 (result-real (complex-single-reg-real-tn result)))
634 (cond ((zerop (tn-offset value-real))
636 (inst fst (make-ea :dword :base object
637 :disp (- (+ (* vector-data-offset
640 other-pointer-lowtag)))
641 (unless (zerop (tn-offset result-real))
642 ;; Value is in ST0 but not result.
643 (inst fst result-real)))
645 ;; Value is not in ST0.
646 (inst fxch value-real)
647 (inst fst (make-ea :dword :base object
648 :disp (- (+ (* vector-data-offset
651 other-pointer-lowtag)))
652 (cond ((zerop (tn-offset result-real))
653 ;; The result is in ST0.
654 (inst fst value-real))
656 ;; Neither value or result are in ST0
657 (unless (location= value-real result-real)
658 (inst fst result-real))
659 (inst fxch value-real))))))
660 (let ((value-imag (complex-single-reg-imag-tn value))
661 (result-imag (complex-single-reg-imag-tn result)))
662 (inst fxch value-imag)
663 (inst fst (make-ea :dword :base object
664 :disp (- (+ (* vector-data-offset
667 other-pointer-lowtag)))
668 (unless (location= value-imag result-imag)
669 (inst fst result-imag))
670 (inst fxch value-imag))))
673 (define-vop (data-vector-ref/simple-array-complex-double-float)
674 (:note "inline array access")
675 (:translate data-vector-ref)
677 (:args (object :scs (descriptor-reg))
678 (index :scs (any-reg)))
679 (:arg-types simple-array-complex-double-float positive-fixnum)
680 (:results (value :scs (complex-double-reg)))
681 (:result-types complex-double-float)
683 (let ((real-tn (complex-double-reg-real-tn value)))
684 (with-empty-tn@fp-top (real-tn)
685 (inst fldd (make-ea :dword :base object :index index :scale 4
686 :disp (- (* vector-data-offset
688 other-pointer-lowtag)))))
689 (let ((imag-tn (complex-double-reg-imag-tn value)))
690 (with-empty-tn@fp-top (imag-tn)
691 (inst fldd (make-ea :dword :base object :index index :scale 4
692 :disp (- (+ (* vector-data-offset
695 other-pointer-lowtag)))))))
697 (define-vop (data-vector-ref-c/simple-array-complex-double-float)
698 (:note "inline array access")
699 (:translate data-vector-ref)
701 (:args (object :scs (descriptor-reg)))
703 (:arg-types simple-array-complex-double-float (:constant (signed-byte 30)))
704 (:results (value :scs (complex-double-reg)))
705 (:result-types complex-double-float)
707 (let ((real-tn (complex-double-reg-real-tn value)))
708 (with-empty-tn@fp-top (real-tn)
709 (inst fldd (make-ea :dword :base object
710 :disp (- (+ (* vector-data-offset
713 other-pointer-lowtag)))))
714 (let ((imag-tn (complex-double-reg-imag-tn value)))
715 (with-empty-tn@fp-top (imag-tn)
716 (inst fldd (make-ea :dword :base object
717 :disp (- (+ (* vector-data-offset
720 other-pointer-lowtag)))))))
722 (define-vop (data-vector-set/simple-array-complex-double-float)
723 (:note "inline array store")
724 (:translate data-vector-set)
726 (:args (object :scs (descriptor-reg))
727 (index :scs (any-reg))
728 (value :scs (complex-double-reg) :target result))
729 (:arg-types simple-array-complex-double-float positive-fixnum
730 complex-double-float)
731 (:results (result :scs (complex-double-reg)))
732 (:result-types complex-double-float)
734 (let ((value-real (complex-double-reg-real-tn value))
735 (result-real (complex-double-reg-real-tn result)))
736 (cond ((zerop (tn-offset value-real))
738 (inst fstd (make-ea :dword :base object :index index :scale 4
739 :disp (- (* vector-data-offset
741 other-pointer-lowtag)))
742 (unless (zerop (tn-offset result-real))
743 ;; Value is in ST0 but not result.
744 (inst fstd result-real)))
746 ;; Value is not in ST0.
747 (inst fxch value-real)
748 (inst fstd (make-ea :dword :base object :index index :scale 4
749 :disp (- (* vector-data-offset
751 other-pointer-lowtag)))
752 (cond ((zerop (tn-offset result-real))
753 ;; The result is in ST0.
754 (inst fstd value-real))
756 ;; Neither value or result are in ST0
757 (unless (location= value-real result-real)
758 (inst fstd result-real))
759 (inst fxch value-real))))))
760 (let ((value-imag (complex-double-reg-imag-tn value))
761 (result-imag (complex-double-reg-imag-tn result)))
762 (inst fxch value-imag)
763 (inst fstd (make-ea :dword :base object :index index :scale 4
764 :disp (- (+ (* vector-data-offset
767 other-pointer-lowtag)))
768 (unless (location= value-imag result-imag)
769 (inst fstd result-imag))
770 (inst fxch value-imag))))
772 (define-vop (data-vector-set-c/simple-array-complex-double-float)
773 (:note "inline array store")
774 (:translate data-vector-set)
776 (:args (object :scs (descriptor-reg))
777 (value :scs (complex-double-reg) :target result))
779 (:arg-types simple-array-complex-double-float (:constant (signed-byte 30))
780 complex-double-float)
781 (:results (result :scs (complex-double-reg)))
782 (:result-types complex-double-float)
784 (let ((value-real (complex-double-reg-real-tn value))
785 (result-real (complex-double-reg-real-tn result)))
786 (cond ((zerop (tn-offset value-real))
788 (inst fstd (make-ea :dword :base object
789 :disp (- (+ (* vector-data-offset
792 other-pointer-lowtag)))
793 (unless (zerop (tn-offset result-real))
794 ;; Value is in ST0 but not result.
795 (inst fstd result-real)))
797 ;; Value is not in ST0.
798 (inst fxch value-real)
799 (inst fstd (make-ea :dword :base object
800 :disp (- (+ (* vector-data-offset
803 other-pointer-lowtag)))
804 (cond ((zerop (tn-offset result-real))
805 ;; The result is in ST0.
806 (inst fstd value-real))
808 ;; Neither value or result are in ST0
809 (unless (location= value-real result-real)
810 (inst fstd result-real))
811 (inst fxch value-real))))))
812 (let ((value-imag (complex-double-reg-imag-tn value))
813 (result-imag (complex-double-reg-imag-tn result)))
814 (inst fxch value-imag)
815 (inst fstd (make-ea :dword :base object
816 :disp (- (+ (* vector-data-offset
819 other-pointer-lowtag)))
820 (unless (location= value-imag result-imag)
821 (inst fstd result-imag))
822 (inst fxch value-imag))))
828 (macrolet ((define-data-vector-frobs (ptype)
830 (define-vop (,(symbolicate "DATA-VECTOR-REF/" ptype))
831 (:translate data-vector-ref)
833 (:args (object :scs (descriptor-reg))
834 (index :scs (unsigned-reg)))
835 (:arg-types ,ptype positive-fixnum)
836 (:results (value :scs (unsigned-reg signed-reg)))
837 (:result-types positive-fixnum)
840 (make-ea :byte :base object :index index :scale 1
841 :disp (- (* vector-data-offset n-word-bytes)
842 other-pointer-lowtag)))))
843 (define-vop (,(symbolicate "DATA-VECTOR-REF-C/" ptype))
844 (:translate data-vector-ref)
846 (:args (object :scs (descriptor-reg)))
848 (:arg-types ,ptype (:constant (signed-byte 30)))
849 (:results (value :scs (unsigned-reg signed-reg)))
850 (:result-types positive-fixnum)
853 (make-ea :byte :base object
854 :disp (- (+ (* vector-data-offset n-word-bytes) index)
855 other-pointer-lowtag)))))
856 (define-vop (,(symbolicate "DATA-VECTOR-SET/" ptype))
857 (:translate data-vector-set)
859 (:args (object :scs (descriptor-reg) :to (:eval 0))
860 (index :scs (unsigned-reg) :to (:eval 0))
861 (value :scs (unsigned-reg signed-reg) :target eax))
862 (:arg-types ,ptype positive-fixnum positive-fixnum)
863 (:temporary (:sc unsigned-reg :offset eax-offset :target result
864 :from (:argument 2) :to (:result 0))
866 (:results (result :scs (unsigned-reg signed-reg)))
867 (:result-types positive-fixnum)
870 (inst mov (make-ea :byte :base object :index index :scale 1
871 :disp (- (* vector-data-offset n-word-bytes)
872 other-pointer-lowtag))
875 (define-vop (,(symbolicate "DATA-VECTOR-SET-C/" ptype))
876 (:translate data-vector-set)
878 (:args (object :scs (descriptor-reg) :to (:eval 0))
879 (value :scs (unsigned-reg signed-reg) :target eax))
881 (:arg-types ,ptype (:constant (signed-byte 30))
883 (:temporary (:sc unsigned-reg :offset eax-offset :target result
884 :from (:argument 1) :to (:result 0))
886 (:results (result :scs (unsigned-reg signed-reg)))
887 (:result-types positive-fixnum)
890 (inst mov (make-ea :byte :base object
891 :disp (- (+ (* vector-data-offset n-word-bytes) index)
892 other-pointer-lowtag))
894 (move result eax))))))
895 (define-data-vector-frobs simple-array-unsigned-byte-7)
896 (define-data-vector-frobs simple-array-unsigned-byte-8))
899 (macrolet ((define-data-vector-frobs (ptype)
901 (define-vop (,(symbolicate "DATA-VECTOR-REF/" ptype))
902 (:translate data-vector-ref)
904 (:args (object :scs (descriptor-reg))
905 (index :scs (unsigned-reg)))
906 (:arg-types ,ptype positive-fixnum)
907 (:results (value :scs (unsigned-reg signed-reg)))
908 (:result-types positive-fixnum)
911 (make-ea :word :base object :index index :scale 2
912 :disp (- (* vector-data-offset n-word-bytes)
913 other-pointer-lowtag)))))
914 (define-vop (,(symbolicate "DATA-VECTOR-REF-C/" ptype))
915 (:translate data-vector-ref)
917 (:args (object :scs (descriptor-reg)))
919 (:arg-types ,ptype (:constant (signed-byte 30)))
920 (:results (value :scs (unsigned-reg signed-reg)))
921 (:result-types positive-fixnum)
924 (make-ea :word :base object
925 :disp (- (+ (* vector-data-offset n-word-bytes) (* 2 index))
926 other-pointer-lowtag)))))
927 (define-vop (,(symbolicate "DATA-VECTOR-SET/" ptype))
928 (:translate data-vector-set)
930 (:args (object :scs (descriptor-reg) :to (:eval 0))
931 (index :scs (unsigned-reg) :to (:eval 0))
932 (value :scs (unsigned-reg signed-reg) :target eax))
933 (:arg-types ,ptype positive-fixnum positive-fixnum)
934 (:temporary (:sc unsigned-reg :offset eax-offset :target result
935 :from (:argument 2) :to (:result 0))
937 (:results (result :scs (unsigned-reg signed-reg)))
938 (:result-types positive-fixnum)
941 (inst mov (make-ea :word :base object :index index :scale 2
942 :disp (- (* vector-data-offset n-word-bytes)
943 other-pointer-lowtag))
947 (define-vop (,(symbolicate "DATA-VECTOR-SET-C/" ptype))
948 (:translate data-vector-set)
950 (:args (object :scs (descriptor-reg) :to (:eval 0))
951 (value :scs (unsigned-reg signed-reg) :target eax))
953 (:arg-types ,ptype (:constant (signed-byte 30))
955 (:temporary (:sc unsigned-reg :offset eax-offset :target result
956 :from (:argument 1) :to (:result 0))
958 (:results (result :scs (unsigned-reg signed-reg)))
959 (:result-types positive-fixnum)
962 (inst mov (make-ea :word :base object
963 :disp (- (+ (* vector-data-offset n-word-bytes)
965 other-pointer-lowtag))
967 (move result eax))))))
968 (define-data-vector-frobs simple-array-unsigned-byte-15)
969 (define-data-vector-frobs simple-array-unsigned-byte-16))
975 (define-vop (data-vector-ref/simple-base-string)
976 (:translate data-vector-ref)
978 (:args (object :scs (descriptor-reg))
979 (index :scs (unsigned-reg)))
980 (:arg-types simple-base-string positive-fixnum)
981 (:results (value :scs (character-reg)))
982 (:result-types character)
985 (make-ea :byte :base object :index index :scale 1
986 :disp (- (* vector-data-offset n-word-bytes)
987 other-pointer-lowtag)))))
989 (define-vop (data-vector-ref-c/simple-base-string)
990 (:translate data-vector-ref)
992 (:args (object :scs (descriptor-reg)))
994 (:arg-types simple-base-string (:constant (signed-byte 30)))
995 (:results (value :scs (character-reg)))
996 (:result-types character)
999 (make-ea :byte :base object
1000 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1001 other-pointer-lowtag)))))
1003 (define-vop (data-vector-set/simple-base-string)
1004 (:translate data-vector-set)
1005 (:policy :fast-safe)
1006 (:args (object :scs (descriptor-reg) :to (:eval 0))
1007 (index :scs (unsigned-reg) :to (:eval 0))
1008 (value :scs (character-reg) :target eax))
1009 (:arg-types simple-base-string positive-fixnum character)
1010 (:temporary (:sc character-reg :offset eax-offset :target result
1011 :from (:argument 2) :to (:result 0))
1013 (:results (result :scs (character-reg)))
1014 (:result-types character)
1017 (inst mov (make-ea :byte :base object :index index :scale 1
1018 :disp (- (* vector-data-offset n-word-bytes)
1019 other-pointer-lowtag))
1023 (define-vop (data-vector-set-c/simple-base-string)
1024 (:translate data-vector-set)
1025 (:policy :fast-safe)
1026 (:args (object :scs (descriptor-reg) :to (:eval 0))
1027 (value :scs (character-reg)))
1029 (:arg-types simple-base-string (:constant (signed-byte 30)) character)
1030 (:temporary (:sc unsigned-reg :offset eax-offset :target result
1031 :from (:argument 1) :to (:result 0))
1033 (:results (result :scs (character-reg)))
1034 (:result-types character)
1037 (inst mov (make-ea :byte :base object
1038 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1039 other-pointer-lowtag))
1046 (define-vop (data-vector-ref/simple-base-string)
1047 (:translate data-vector-ref)
1048 (:policy :fast-safe)
1049 (:args (object :scs (descriptor-reg))
1050 (index :scs (unsigned-reg)))
1051 (:arg-types simple-base-string positive-fixnum)
1052 (:results (value :scs (character-reg)))
1053 (:result-types character)
1056 (make-ea :byte :base object :index index :scale 1
1057 :disp (- (* vector-data-offset n-word-bytes)
1058 other-pointer-lowtag)))))
1060 (define-vop (data-vector-ref-c/simple-base-string)
1061 (:translate data-vector-ref)
1062 (:policy :fast-safe)
1063 (:args (object :scs (descriptor-reg)))
1065 (:arg-types simple-base-string (:constant (signed-byte 30)))
1066 (:results (value :scs (character-reg)))
1067 (:result-types character)
1070 (make-ea :byte :base object
1071 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1072 other-pointer-lowtag)))))
1074 (define-vop (data-vector-set/simple-base-string)
1075 (:translate data-vector-set)
1076 (:policy :fast-safe)
1077 (:args (object :scs (descriptor-reg) :to (:eval 0))
1078 (index :scs (unsigned-reg) :to (:eval 0))
1079 (value :scs (character-reg) :target result))
1080 (:arg-types simple-base-string positive-fixnum character)
1081 (:results (result :scs (character-reg)))
1082 (:result-types character)
1084 (inst mov (make-ea :byte :base object :index index :scale 1
1085 :disp (- (* vector-data-offset n-word-bytes)
1086 other-pointer-lowtag))
1088 (move result value)))
1090 (define-vop (data-vector-set-c/simple-base-string)
1091 (:translate data-vector-set)
1092 (:policy :fast-safe)
1093 (:args (object :scs (descriptor-reg) :to (:eval 0))
1094 (value :scs (character-reg)))
1096 (:arg-types simple-base-string (:constant (signed-byte 30)) character)
1097 (:results (result :scs (character-reg)))
1098 (:result-types character)
1100 (inst mov (make-ea :byte :base object
1101 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1102 other-pointer-lowtag))
1104 (move result value)))
1108 (define-full-reffer data-vector-ref/simple-character-string
1109 simple-character-string vector-data-offset other-pointer-lowtag
1110 (character-reg) character data-vector-ref)
1112 (define-full-setter data-vector-set/simple-character-string
1113 simple-character-string vector-data-offset other-pointer-lowtag
1114 (character-reg) character data-vector-set)
1118 (define-vop (data-vector-ref/simple-array-signed-byte-8)
1119 (:translate data-vector-ref)
1120 (:policy :fast-safe)
1121 (:args (object :scs (descriptor-reg))
1122 (index :scs (unsigned-reg)))
1123 (:arg-types simple-array-signed-byte-8 positive-fixnum)
1124 (:results (value :scs (signed-reg)))
1125 (:result-types tagged-num)
1128 (make-ea :byte :base object :index index :scale 1
1129 :disp (- (* vector-data-offset n-word-bytes)
1130 other-pointer-lowtag)))))
1132 (define-vop (data-vector-ref-c/simple-array-signed-byte-8)
1133 (:translate data-vector-ref)
1134 (:policy :fast-safe)
1135 (:args (object :scs (descriptor-reg)))
1137 (:arg-types simple-array-signed-byte-8 (:constant (signed-byte 30)))
1138 (:results (value :scs (signed-reg)))
1139 (:result-types tagged-num)
1142 (make-ea :byte :base object
1143 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1144 other-pointer-lowtag)))))
1146 (define-vop (data-vector-set/simple-array-signed-byte-8)
1147 (:translate data-vector-set)
1148 (:policy :fast-safe)
1149 (:args (object :scs (descriptor-reg) :to (:eval 0))
1150 (index :scs (unsigned-reg) :to (:eval 0))
1151 (value :scs (signed-reg) :target eax))
1152 (:arg-types simple-array-signed-byte-8 positive-fixnum tagged-num)
1153 (:temporary (:sc unsigned-reg :offset eax-offset :target result
1154 :from (:argument 2) :to (:result 0))
1156 (:results (result :scs (signed-reg)))
1157 (:result-types tagged-num)
1160 (inst mov (make-ea :byte :base object :index index :scale 1
1161 :disp (- (* vector-data-offset n-word-bytes)
1162 other-pointer-lowtag))
1166 (define-vop (data-vector-set-c/simple-array-signed-byte-8)
1167 (:translate data-vector-set)
1168 (:policy :fast-safe)
1169 (:args (object :scs (descriptor-reg) :to (:eval 0))
1170 (value :scs (signed-reg) :target eax))
1172 (:arg-types simple-array-signed-byte-8 (:constant (signed-byte 30))
1174 (:temporary (:sc unsigned-reg :offset eax-offset :target result
1175 :from (:argument 1) :to (:result 0))
1177 (:results (result :scs (signed-reg)))
1178 (:result-types tagged-num)
1181 (inst mov (make-ea :byte :base object
1182 :disp (- (+ (* vector-data-offset n-word-bytes) index)
1183 other-pointer-lowtag))
1189 (define-vop (data-vector-ref/simple-array-signed-byte-16)
1190 (:translate data-vector-ref)
1191 (:policy :fast-safe)
1192 (:args (object :scs (descriptor-reg))
1193 (index :scs (unsigned-reg)))
1194 (:arg-types simple-array-signed-byte-16 positive-fixnum)
1195 (:results (value :scs (signed-reg)))
1196 (:result-types tagged-num)
1199 (make-ea :word :base object :index index :scale 2
1200 :disp (- (* vector-data-offset n-word-bytes)
1201 other-pointer-lowtag)))))
1203 (define-vop (data-vector-ref-c/simple-array-signed-byte-16)
1204 (:translate data-vector-ref)
1205 (:policy :fast-safe)
1206 (:args (object :scs (descriptor-reg)))
1208 (:arg-types simple-array-signed-byte-16 (:constant (signed-byte 30)))
1209 (:results (value :scs (signed-reg)))
1210 (:result-types tagged-num)
1213 (make-ea :word :base object
1214 :disp (- (+ (* vector-data-offset n-word-bytes)
1216 other-pointer-lowtag)))))
1218 (define-vop (data-vector-set/simple-array-signed-byte-16)
1219 (:translate data-vector-set)
1220 (:policy :fast-safe)
1221 (:args (object :scs (descriptor-reg) :to (:eval 0))
1222 (index :scs (unsigned-reg) :to (:eval 0))
1223 (value :scs (signed-reg) :target eax))
1224 (:arg-types simple-array-signed-byte-16 positive-fixnum tagged-num)
1225 (:temporary (:sc signed-reg :offset eax-offset :target result
1226 :from (:argument 2) :to (:result 0))
1228 (:results (result :scs (signed-reg)))
1229 (:result-types tagged-num)
1232 (inst mov (make-ea :word :base object :index index :scale 2
1233 :disp (- (* vector-data-offset n-word-bytes)
1234 other-pointer-lowtag))
1238 (define-vop (data-vector-set-c/simple-array-signed-byte-16)
1239 (:translate data-vector-set)
1240 (:policy :fast-safe)
1241 (:args (object :scs (descriptor-reg) :to (:eval 0))
1242 (value :scs (signed-reg) :target eax))
1244 (:arg-types simple-array-signed-byte-16 (:constant (signed-byte 30)) tagged-num)
1245 (:temporary (:sc signed-reg :offset eax-offset :target result
1246 :from (:argument 1) :to (:result 0))
1248 (:results (result :scs (signed-reg)))
1249 (:result-types tagged-num)
1253 (make-ea :word :base object
1254 :disp (- (+ (* vector-data-offset n-word-bytes)
1256 other-pointer-lowtag))
1260 ;;; These vops are useful for accessing the bits of a vector
1261 ;;; irrespective of what type of vector it is.
1262 (define-full-reffer raw-bits * 0 other-pointer-lowtag (unsigned-reg)
1263 unsigned-num %raw-bits)
1264 (define-full-setter set-raw-bits * 0 other-pointer-lowtag (unsigned-reg)
1265 unsigned-num %set-raw-bits)
1266 (define-full-reffer vector-raw-bits * vector-data-offset other-pointer-lowtag
1267 (unsigned-reg) unsigned-num %vector-raw-bits)
1268 (define-full-setter set-vector-raw-bits * vector-data-offset other-pointer-lowtag
1269 (unsigned-reg) unsigned-num %set-vector-raw-bits)
1271 ;;;; miscellaneous array VOPs
1273 (define-vop (get-vector-subtype get-header-data))
1274 (define-vop (set-vector-subtype set-header-data))