0.9.4.5:
[sbcl.git] / src / compiler / x86-64 / cell.lisp
1 ;;;; various primitive memory access VOPs for the x86 VM
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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.
11
12 (in-package "SB!VM")
13 \f
14 ;;;; data object ref/set stuff
15
16 (define-vop (slot)
17   (:args (object :scs (descriptor-reg)))
18   (:info name offset lowtag)
19   (:ignore name)
20   (:results (result :scs (descriptor-reg any-reg)))
21   (:generator 1
22     (loadw result object offset lowtag)))
23
24 (define-vop (set-slot)
25   (:args (object :scs (descriptor-reg))
26          (value :scs (descriptor-reg any-reg immediate)))
27   (:temporary (:sc descriptor-reg) temp)
28   (:info name offset lowtag)
29   (:ignore name)
30   (:results)
31   (:generator 1
32     (if (sc-is value immediate)
33         (let ((val (tn-value value)))
34           (move-immediate (make-ea :qword
35                                    :base object
36                                    :disp (- (* offset n-word-bytes)
37                                             lowtag))
38                           (etypecase val
39                             (integer
40                              (fixnumize val))
41                             (symbol
42                              (+ nil-value (static-symbol-offset val)))
43                             (character
44                              (logior (ash (char-code val) n-widetag-bits)
45                                      character-widetag)))
46                           temp))
47         ;; Else, value not immediate.
48         (storew value object offset lowtag))))
49 \f
50
51
52 ;;;; symbol hacking VOPs
53
54 ;;; these next two cf the sparc version, by jrd.
55 ;;; FIXME: Deref this ^ reference.
56
57
58 ;;; The compiler likes to be able to directly SET symbols.
59 #!+sb-thread
60 (define-vop (set)
61   (:args (symbol :scs (descriptor-reg))
62          (value :scs (descriptor-reg any-reg)))
63   (:temporary (:sc descriptor-reg) tls)
64   ;;(:policy :fast-safe)
65   (:generator 4
66     (let ((global-val (gen-label))
67           (done (gen-label)))
68       (loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
69       (inst or tls tls)
70       (inst jmp :z global-val)
71       (inst cmp (make-ea :qword :base thread-base-tn :scale 1 :index tls)
72             no-tls-value-marker-widetag)
73       (inst jmp :z global-val)
74       (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls)
75             value)
76       (inst jmp done)
77       (emit-label global-val)
78       (storew value symbol symbol-value-slot other-pointer-lowtag)
79       (emit-label done))))
80
81 ;; unithreaded it's a lot simpler ...
82 #!-sb-thread
83 (define-vop (set cell-set)
84   (:variant symbol-value-slot other-pointer-lowtag))
85
86 ;;; Do a cell ref with an error check for being unbound.
87 ;;; XXX stil used? I can't see where -dan
88 (define-vop (checked-cell-ref)
89   (:args (object :scs (descriptor-reg) :target obj-temp))
90   (:results (value :scs (descriptor-reg any-reg)))
91   (:policy :fast-safe)
92   (:vop-var vop)
93   (:save-p :compute-only)
94   (:temporary (:sc descriptor-reg :from (:argument 0)) obj-temp))
95
96 ;;; With Symbol-Value, we check that the value isn't the trap object. So
97 ;;; Symbol-Value of NIL is NIL.
98 #!+sb-thread
99 (define-vop (symbol-value)
100   (:translate symbol-value)
101   (:policy :fast-safe)
102   (:args (object :scs (descriptor-reg) :to (:result 1)))
103   (:results (value :scs (descriptor-reg any-reg)))
104   (:vop-var vop)
105   (:save-p :compute-only)
106   (:generator 9
107     (let* ((check-unbound-label (gen-label))
108            (err-lab (generate-error-code vop unbound-symbol-error object))
109            (ret-lab (gen-label)))
110       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
111       (inst mov value (make-ea :qword :base thread-base-tn
112                                :index value :scale 1))
113       (inst cmp value no-tls-value-marker-widetag)
114       (inst jmp :ne check-unbound-label)
115       (loadw value object symbol-value-slot other-pointer-lowtag)
116       (emit-label check-unbound-label)
117       (inst cmp value unbound-marker-widetag)
118       (inst jmp :e err-lab)
119       (emit-label ret-lab))))
120
121 #!+sb-thread
122 (define-vop (fast-symbol-value symbol-value)
123   ;; KLUDGE: not really fast, in fact, because we're going to have to
124   ;; do a full lookup of the thread-local area anyway.  But half of
125   ;; the meaning of FAST-SYMBOL-VALUE is "do not signal an error if
126   ;; unbound", which is used in the implementation of COPY-SYMBOL.  --
127   ;; CSR, 2003-04-22
128   (:policy :fast)
129   (:translate symbol-value)
130   (:generator 8
131     (let ((ret-lab (gen-label)))
132       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
133       (inst mov value
134             (make-ea :qword :base thread-base-tn :index value :scale 1))
135       (inst cmp value no-tls-value-marker-widetag)
136       (inst jmp :ne ret-lab)
137       (loadw value object symbol-value-slot other-pointer-lowtag)
138       (emit-label ret-lab))))
139
140 #!-sb-thread
141 (define-vop (symbol-value)
142   (:translate symbol-value)
143   (:policy :fast-safe)
144   (:args (object :scs (descriptor-reg) :to (:result 1)))
145   (:results (value :scs (descriptor-reg any-reg)))
146   (:vop-var vop)
147   (:save-p :compute-only)
148   (:generator 9
149     (let ((err-lab (generate-error-code vop unbound-symbol-error object)))
150       (loadw value object symbol-value-slot other-pointer-lowtag)
151       (inst cmp value unbound-marker-widetag)
152       (inst jmp :e err-lab))))
153
154 #!-sb-thread
155 (define-vop (fast-symbol-value cell-ref)
156   (:variant symbol-value-slot other-pointer-lowtag)
157   (:policy :fast)
158   (:translate symbol-value))
159
160 (defknown locked-symbol-global-value-add (symbol fixnum) fixnum ())
161
162 (define-vop (locked-symbol-global-value-add)
163     (:args (object :scs (descriptor-reg) :to :result)
164            (value :scs (any-reg) :target result))
165   (:arg-types * tagged-num)
166   (:results (result :scs (any-reg) :from (:argument 1)))
167   (:policy :fast)
168   (:translate locked-symbol-global-value-add)
169   (:result-types tagged-num)
170   (:policy :fast-safe)
171   (:generator 4
172     (move result value)
173     (inst lock)
174     (inst add (make-ea :qword :base object
175                        :disp (- (* symbol-value-slot n-word-bytes)
176                                 other-pointer-lowtag))
177           value)))
178
179 #!+sb-thread
180 (define-vop (boundp)
181   (:translate boundp)
182   (:policy :fast-safe)
183   (:args (object :scs (descriptor-reg)))
184   (:conditional)
185   (:info target not-p)
186   (:temporary (:sc descriptor-reg #+nil(:from (:argument 0))) value)
187   (:generator 9
188     (let ((check-unbound-label (gen-label)))
189       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
190       (inst mov value
191             (make-ea :qword :base thread-base-tn :index value :scale 1))
192       (inst cmp value no-tls-value-marker-widetag)
193       (inst jmp :ne check-unbound-label)
194       (loadw value object symbol-value-slot other-pointer-lowtag)
195       (emit-label check-unbound-label)
196       (inst cmp value unbound-marker-widetag)
197       (inst jmp (if not-p :e :ne) target))))
198
199 #!-sb-thread
200 (define-vop (boundp)
201   (:translate boundp)
202   (:policy :fast-safe)
203   (:args (object :scs (descriptor-reg)))
204   (:conditional)
205   (:info target not-p)
206   (:temporary (:sc descriptor-reg :from (:argument 0)) value)
207   (:generator 9
208     (loadw value object symbol-value-slot other-pointer-lowtag)
209     (inst cmp value unbound-marker-widetag)
210     (inst jmp (if not-p :e :ne) target)))
211
212
213 (define-vop (symbol-hash)
214   (:policy :fast-safe)
215   (:translate symbol-hash)
216   (:args (symbol :scs (descriptor-reg)))
217   (:results (res :scs (any-reg)))
218   (:result-types positive-fixnum)
219   (:generator 2
220     ;; The symbol-hash slot of NIL holds NIL because it is also the
221     ;; cdr slot, so we have to strip off the three low bits to make sure
222     ;; it is a fixnum.  The lowtag selection magic that is required to
223     ;; ensure this is explained in the comment in objdef.lisp
224     (loadw res symbol symbol-hash-slot other-pointer-lowtag)
225     (inst and res (lognot #b111))))
226 \f
227 ;;;; fdefinition (FDEFN) objects
228
229 (define-vop (fdefn-fun cell-ref)        ; /pfw - alpha
230   (:variant fdefn-fun-slot other-pointer-lowtag))
231
232 (define-vop (safe-fdefn-fun)
233   (:args (object :scs (descriptor-reg) :to (:result 1)))
234   (:results (value :scs (descriptor-reg any-reg)))
235   (:vop-var vop)
236   (:save-p :compute-only)
237   (:generator 10
238     (loadw value object fdefn-fun-slot other-pointer-lowtag)
239     (inst cmp value nil-value)
240     (let ((err-lab (generate-error-code vop undefined-fun-error object)))
241       (inst jmp :e err-lab))))
242
243 (define-vop (set-fdefn-fun)
244   (:policy :fast-safe)
245   (:translate (setf fdefn-fun))
246   (:args (function :scs (descriptor-reg) :target result)
247          (fdefn :scs (descriptor-reg)))
248   (:temporary (:sc unsigned-reg) raw)
249   (:temporary (:sc byte-reg) type)
250   (:results (result :scs (descriptor-reg)))
251   (:generator 38
252     (load-type type function (- fun-pointer-lowtag))
253     (inst lea raw
254           (make-ea :byte :base function
255                    :disp (- (* simple-fun-code-offset n-word-bytes)
256                             fun-pointer-lowtag)))
257     (inst cmp type simple-fun-header-widetag)
258     (inst jmp :e NORMAL-FUN)
259     (inst lea raw (make-fixup "closure_tramp" :foreign))
260     NORMAL-FUN
261     (storew function fdefn fdefn-fun-slot other-pointer-lowtag)
262     (storew raw fdefn fdefn-raw-addr-slot other-pointer-lowtag)
263     (move result function)))
264
265 (define-vop (fdefn-makunbound)
266   (:policy :fast-safe)
267   (:translate fdefn-makunbound)
268   (:args (fdefn :scs (descriptor-reg) :target result))
269   (:results (result :scs (descriptor-reg)))
270   (:generator 38
271     (storew nil-value fdefn fdefn-fun-slot other-pointer-lowtag)
272     (storew (make-fixup "undefined_tramp" :foreign)
273             fdefn fdefn-raw-addr-slot other-pointer-lowtag)
274     (move result fdefn)))
275 \f
276 ;;;; binding and unbinding
277
278 ;;; BIND -- Establish VAL as a binding for SYMBOL. Save the old value and
279 ;;; the symbol on the binding stack and stuff the new value into the
280 ;;; symbol.
281
282 #!+sb-thread
283 (define-vop (bind)
284   (:args (val :scs (any-reg descriptor-reg))
285          (symbol :scs (descriptor-reg)))
286   (:temporary (:sc unsigned-reg) tls-index temp bsp)
287   (:generator 5
288     (let ((tls-index-valid (gen-label)))
289       (load-tl-symbol-value bsp *binding-stack-pointer*)
290       (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
291       (inst add bsp (* binding-size n-word-bytes))
292       (store-tl-symbol-value bsp *binding-stack-pointer* temp)
293
294       (inst or tls-index tls-index)
295       (inst jmp :ne tls-index-valid)
296       ;; allocate a new tls-index
297       (load-symbol-value tls-index *free-tls-index*)
298       (inst add tls-index 8)            ;XXX surely we can do this more
299       (store-symbol-value tls-index *free-tls-index*) ;succintly
300       (inst sub tls-index 8)
301       (storew tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
302       (emit-label tls-index-valid)
303       (inst mov temp
304             (make-ea :qword :base thread-base-tn :scale 1 :index tls-index))
305       (storew temp bsp (- binding-value-slot binding-size))
306       (storew symbol bsp (- binding-symbol-slot binding-size))
307       (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
308             val))))
309
310 #!-sb-thread
311 (define-vop (bind)
312   (:args (val :scs (any-reg descriptor-reg))
313          (symbol :scs (descriptor-reg)))
314   (:temporary (:sc unsigned-reg) temp bsp)
315   (:generator 5
316     (load-symbol-value bsp *binding-stack-pointer*)
317     (loadw temp symbol symbol-value-slot other-pointer-lowtag)
318     (inst add bsp (* binding-size n-word-bytes))
319     (store-symbol-value bsp *binding-stack-pointer*)
320     (storew temp bsp (- binding-value-slot binding-size))
321     (storew symbol bsp (- binding-symbol-slot binding-size))
322     (storew val symbol symbol-value-slot other-pointer-lowtag)))
323
324
325 #!+sb-thread
326 (define-vop (unbind)
327     ;; four temporaries?
328   (:temporary (:sc unsigned-reg) symbol value bsp tls-index)
329   (:generator 0
330     (load-tl-symbol-value bsp *binding-stack-pointer*)
331     (loadw symbol bsp (- binding-symbol-slot binding-size))
332     (loadw value bsp (- binding-value-slot binding-size))
333
334     (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
335     (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
336           value)
337
338     (storew 0 bsp (- binding-symbol-slot binding-size))
339     (inst sub bsp (* binding-size n-word-bytes))
340     ;; we're done with value, so we can use it as a temp here
341     (store-tl-symbol-value bsp *binding-stack-pointer* value)))
342
343 #!-sb-thread
344 (define-vop (unbind)
345   (:temporary (:sc unsigned-reg) symbol value bsp)
346   (:generator 0
347     (load-symbol-value bsp *binding-stack-pointer*)
348     (loadw symbol bsp (- binding-symbol-slot binding-size))
349     (loadw value bsp (- binding-value-slot binding-size))
350     (storew value symbol symbol-value-slot other-pointer-lowtag)
351     (storew 0 bsp (- binding-symbol-slot binding-size))
352     (inst sub bsp (* binding-size n-word-bytes))
353     (store-symbol-value bsp *binding-stack-pointer*)))
354
355
356 (define-vop (unbind-to-here)
357   (:args (where :scs (descriptor-reg any-reg)))
358   (:temporary (:sc unsigned-reg) symbol value bsp #!+sb-thread tls-index)
359   (:generator 0
360     (load-tl-symbol-value bsp *binding-stack-pointer*)
361     (inst cmp where bsp)
362     (inst jmp :e DONE)
363
364     LOOP
365     (loadw symbol bsp (- binding-symbol-slot binding-size))
366     (inst or symbol symbol)
367     (inst jmp :z SKIP)
368     (loadw value bsp (- binding-value-slot binding-size))
369     #!-sb-thread
370     (storew value symbol symbol-value-slot other-pointer-lowtag)
371     #!+sb-thread
372     (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
373     #!+sb-thread
374     (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
375           value)
376     (storew 0 bsp (- binding-symbol-slot binding-size))
377
378     SKIP
379     (inst sub bsp (* binding-size n-word-bytes))
380     (inst cmp where bsp)
381     (inst jmp :ne LOOP)
382     ;; we're done with value, so can use it as a temporary
383     (store-tl-symbol-value bsp *binding-stack-pointer* value)
384
385     DONE))
386 \f
387
388 \f
389 ;;;; closure indexing
390
391 (define-full-reffer closure-index-ref *
392   closure-info-offset fun-pointer-lowtag
393   (any-reg descriptor-reg) * %closure-index-ref)
394
395 (define-full-setter set-funcallable-instance-info *
396   funcallable-instance-info-offset fun-pointer-lowtag
397   (any-reg descriptor-reg) * %set-funcallable-instance-info)
398
399 (define-full-reffer funcallable-instance-info *
400   funcallable-instance-info-offset fun-pointer-lowtag
401   (descriptor-reg any-reg) * %funcallable-instance-info)
402
403 (define-vop (funcallable-instance-lexenv cell-ref)
404   (:variant funcallable-instance-lexenv-slot fun-pointer-lowtag))
405
406 (define-vop (closure-ref slot-ref)
407   (:variant closure-info-offset fun-pointer-lowtag))
408
409 (define-vop (closure-init slot-set)
410   (:variant closure-info-offset fun-pointer-lowtag))
411 \f
412 ;;;; value cell hackery
413
414 (define-vop (value-cell-ref cell-ref)
415   (:variant value-cell-value-slot other-pointer-lowtag))
416
417 (define-vop (value-cell-set cell-set)
418   (:variant value-cell-value-slot other-pointer-lowtag))
419 \f
420 ;;;; structure hackery
421
422 (define-vop (instance-length)
423   (:policy :fast-safe)
424   (:translate %instance-length)
425   (:args (struct :scs (descriptor-reg)))
426   (:results (res :scs (unsigned-reg)))
427   (:result-types positive-fixnum)
428   (:generator 4
429     (loadw res struct 0 instance-pointer-lowtag)
430     (inst shr res n-widetag-bits)))
431
432 (define-vop (instance-ref slot-ref)
433   (:variant instance-slots-offset instance-pointer-lowtag)
434   (:policy :fast-safe)
435   (:translate %instance-ref)
436   (:arg-types instance (:constant index)))
437
438 (define-vop (instance-set slot-set)
439   (:policy :fast-safe)
440   (:translate %instance-set)
441   (:variant instance-slots-offset instance-pointer-lowtag)
442   (:arg-types instance (:constant index) *))
443
444 (define-full-reffer instance-index-ref * instance-slots-offset
445   instance-pointer-lowtag (any-reg descriptor-reg) * %instance-ref)
446
447 (define-full-setter instance-index-set * instance-slots-offset
448   instance-pointer-lowtag (any-reg descriptor-reg) * %instance-set)
449
450
451 (defknown %instance-set-conditional (instance index t t) t
452           (unsafe))
453
454 (define-vop (instance-set-conditional)
455   (:translate %instance-set-conditional)
456   (:args (object :scs (descriptor-reg) :to :eval)
457          (slot :scs (any-reg) :to :result)
458          (old-value :scs (descriptor-reg any-reg) :target rax)
459          (new-value :scs (descriptor-reg any-reg)))
460   (:arg-types instance positive-fixnum * *)
461   (:temporary (:sc descriptor-reg :offset rax-offset
462                    :from (:argument 2) :to :result :target result)  rax)
463   (:results (result :scs (descriptor-reg any-reg)))
464   ;(:guard (backend-featurep :i486))
465   (:policy :fast-safe)
466   (:generator 5
467     (move rax old-value)
468     (inst lock)
469     (inst cmpxchg (make-ea :qword :base object :index slot :scale 1
470                            :disp (- (* instance-slots-offset n-word-bytes)
471                                     instance-pointer-lowtag))
472           new-value)
473     (move result rax)))
474
475
476 \f
477 ;;;; code object frobbing
478
479 (define-full-reffer code-header-ref * 0 other-pointer-lowtag
480   (any-reg descriptor-reg) * code-header-ref)
481
482 (define-full-setter code-header-set * 0 other-pointer-lowtag
483   (any-reg descriptor-reg) * code-header-set)
484
485
486 \f
487 ;;;; raw instance slot accessors
488
489 (define-vop (raw-instance-ref/word)
490   (:translate %raw-instance-ref/word)
491   (:policy :fast-safe)
492   (:args (object :scs (descriptor-reg)) (index :scs (any-reg)))
493   (:arg-types * tagged-num)
494   (:temporary (:sc unsigned-reg) tmp)
495   (:results (value :scs (unsigned-reg)))
496   (:result-types unsigned-num)
497   (:generator 5
498     (loadw tmp object 0 instance-pointer-lowtag)
499     (inst shr tmp n-widetag-bits)
500     (inst shl tmp 3)
501     (inst sub tmp index)
502     (inst mov
503           value
504           (make-ea :qword
505                    :base object
506                    :index tmp
507                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
508                             instance-pointer-lowtag)))))
509
510 (define-vop (raw-instance-set/word)
511   (:translate %raw-instance-set/word)
512   (:policy :fast-safe)
513   (:args (object :scs (descriptor-reg))
514          (index :scs (any-reg))
515          (value :scs (unsigned-reg) :target result))
516   (:arg-types * tagged-num unsigned-num)
517   (:temporary (:sc unsigned-reg) tmp)
518   (:results (result :scs (unsigned-reg)))
519   (:result-types unsigned-num)
520   (:generator 5
521     (loadw tmp object 0 instance-pointer-lowtag)
522     (inst shr tmp n-widetag-bits)
523     (inst shl tmp 3)
524     (inst sub tmp index)
525     (inst mov
526           (make-ea :qword
527                    :base object
528                    :index tmp
529                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
530                             instance-pointer-lowtag))
531           value)
532     (move result value)))
533
534 (define-vop (raw-instance-ref/single)
535   (:translate %raw-instance-ref/single)
536   (:policy :fast-safe)
537   (:args (object :scs (descriptor-reg))
538          (index :scs (any-reg)))
539   (:arg-types * positive-fixnum)
540   (:temporary (:sc unsigned-reg) tmp)
541   (:results (value :scs (single-reg)))
542   (:result-types single-float)
543   (:generator 5
544     (loadw tmp object 0 instance-pointer-lowtag)
545     (inst shr tmp n-widetag-bits)
546     (inst shl tmp 3)
547     (inst sub tmp index)
548     (inst movss
549           value
550           (make-ea :dword
551                    :base object
552                    :index tmp
553                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
554                             instance-pointer-lowtag)))))
555
556 (define-vop (raw-instance-set/single)
557   (:translate %raw-instance-set/single)
558   (:policy :fast-safe)
559   (:args (object :scs (descriptor-reg))
560          (index :scs (any-reg))
561          (value :scs (single-reg) :target result))
562   (:arg-types * positive-fixnum single-float)
563   (:temporary (:sc unsigned-reg) tmp)
564   (:results (result :scs (single-reg)))
565   (:result-types single-float)
566   (:generator 5
567     (loadw tmp object 0 instance-pointer-lowtag)
568     (inst shr tmp n-widetag-bits)
569     (inst shl tmp 3)
570     (inst sub tmp index)
571     (inst movss
572           (make-ea :dword
573                    :base object
574                    :index tmp
575                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
576                             instance-pointer-lowtag))
577           value)
578    (unless (location= result value)
579      (inst movss result value))))
580
581 (define-vop (raw-instance-ref/double)
582   (:translate %raw-instance-ref/double)
583   (:policy :fast-safe)
584   (:args (object :scs (descriptor-reg))
585          (index :scs (any-reg)))
586   (:arg-types * positive-fixnum)
587   (:temporary (:sc unsigned-reg) tmp)
588   (:results (value :scs (double-reg)))
589   (:result-types double-float)
590   (:generator 5
591     (loadw tmp object 0 instance-pointer-lowtag)
592     (inst shr tmp n-widetag-bits)
593     (inst shl tmp 3)
594     (inst sub tmp index)
595     (inst movsd
596           value
597           (make-ea :dword
598                    :base object
599                    :index tmp
600                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
601                             instance-pointer-lowtag)))))
602
603 (define-vop (raw-instance-set/double)
604   (:translate %raw-instance-set/double)
605   (:policy :fast-safe)
606   (:args (object :scs (descriptor-reg))
607          (index :scs (any-reg))
608          (value :scs (double-reg) :target result))
609   (:arg-types * positive-fixnum double-float)
610   (:temporary (:sc unsigned-reg) tmp)
611   (:results (result :scs (double-reg)))
612   (:result-types double-float)
613   (:generator 5
614     (loadw tmp object 0 instance-pointer-lowtag)
615     (inst shr tmp n-widetag-bits)
616     (inst shl tmp 3)
617     (inst sub tmp index)
618     (inst movsd
619           (make-ea :dword
620                    :base object
621                    :index tmp
622                    :disp (- (* (1- instance-slots-offset) n-word-bytes)
623                             instance-pointer-lowtag))
624           value)
625    (unless (location= result value)
626      (inst movsd result value))))
627
628 (define-vop (raw-instance-ref/complex-single)
629   (:translate %raw-instance-ref/complex-single)
630   (:policy :fast-safe)
631   (:args (object :scs (descriptor-reg))
632          (index :scs (any-reg)))
633   (:arg-types * positive-fixnum)
634   (:temporary (:sc unsigned-reg) tmp)
635   (:results (value :scs (complex-single-reg)))
636   (:result-types complex-single-float)
637   (:generator 5
638     (loadw tmp object 0 instance-pointer-lowtag)
639     (inst shr tmp n-widetag-bits)
640     (inst shl tmp 3)
641     (inst sub tmp index)
642     (let ((real-tn (complex-single-reg-real-tn value)))
643       (inst movss
644             real-tn
645             (make-ea :dword
646                      :base object
647                      :index tmp
648                      :disp (- (* (1- instance-slots-offset) n-word-bytes)
649                               instance-pointer-lowtag))))
650     (let ((imag-tn (complex-single-reg-imag-tn value)))
651       (inst movss
652             imag-tn
653             (make-ea :dword
654                      :base object
655                      :index tmp
656                      :disp (+ (* (1- instance-slots-offset) n-word-bytes)
657                               4
658                               (- instance-pointer-lowtag)))))))
659
660 (define-vop (raw-instance-set/complex-single)
661   (:translate %raw-instance-set/complex-single)
662   (:policy :fast-safe)
663   (:args (object :scs (descriptor-reg))
664          (index :scs (any-reg))
665          (value :scs (complex-single-reg) :target result))
666   (:arg-types * positive-fixnum complex-single-float)
667   (:temporary (:sc unsigned-reg) tmp)
668   (:results (result :scs (complex-single-reg)))
669   (:result-types complex-single-float)
670   (:generator 5
671     (loadw tmp object 0 instance-pointer-lowtag)
672     (inst shr tmp n-widetag-bits)
673     (inst shl tmp 3)
674     (inst sub tmp index)
675     (let ((value-real (complex-single-reg-real-tn value))
676           (result-real (complex-single-reg-real-tn result)))
677       (inst movss (make-ea :dword
678                            :base object
679                            :index tmp
680                            :disp (- (* (1- instance-slots-offset) n-word-bytes)
681                                     instance-pointer-lowtag))
682             value-real)
683       (unless (location= value-real result-real)
684         (inst movss result-real value-real)))
685     (let ((value-imag (complex-single-reg-imag-tn value))
686           (result-imag (complex-single-reg-imag-tn result)))
687       (inst movss (make-ea :dword
688                            :base object
689                            :index tmp
690                            :disp (+ (* (1- instance-slots-offset) n-word-bytes)
691                                     4
692                                     (- instance-pointer-lowtag)))
693             value-imag)
694       (unless (location= value-imag result-imag)
695         (inst movss result-imag value-imag)))))
696
697 (define-vop (raw-instance-ref/complex-double)
698   (:translate %raw-instance-ref/complex-double)
699   (:policy :fast-safe)
700   (:args (object :scs (descriptor-reg))
701          (index :scs (any-reg)))
702   (:arg-types * positive-fixnum)
703   (:temporary (:sc unsigned-reg) tmp)
704   (:results (value :scs (complex-double-reg)))
705   (:result-types complex-double-float)
706   (:generator 5
707     (loadw tmp object 0 instance-pointer-lowtag)
708     (inst shr tmp n-widetag-bits)
709     (inst shl tmp 3)
710     (inst sub tmp index)
711     (let ((real-tn (complex-double-reg-real-tn value)))
712       (inst movsd
713             real-tn
714             (make-ea :dword
715                      :base object
716                      :index tmp
717                      :disp (- (* (- instance-slots-offset 2) n-word-bytes)
718                               instance-pointer-lowtag))))
719     (let ((imag-tn (complex-double-reg-imag-tn value)))
720       (inst movsd
721             imag-tn
722             (make-ea :dword
723                      :base object
724                      :index tmp
725                      :disp (- (* (1- instance-slots-offset) n-word-bytes)
726                               instance-pointer-lowtag))))))
727
728 (define-vop (raw-instance-set/complex-double)
729   (:translate %raw-instance-set/complex-double)
730   (:policy :fast-safe)
731   (:args (object :scs (descriptor-reg))
732          (index :scs (any-reg))
733          (value :scs (complex-double-reg) :target result))
734   (:arg-types * positive-fixnum complex-double-float)
735   (:temporary (:sc unsigned-reg) tmp)
736   (:results (result :scs (complex-double-reg)))
737   (:result-types complex-double-float)
738   (:generator 5
739     (loadw tmp object 0 instance-pointer-lowtag)
740     (inst shr tmp n-widetag-bits)
741     (inst shl tmp 3)
742     (inst sub tmp index)
743     (let ((value-real (complex-double-reg-real-tn value))
744           (result-real (complex-double-reg-real-tn result)))
745       (inst movsd (make-ea :dword
746                            :base object
747                            :index tmp
748                            :disp (- (* (- instance-slots-offset 2) n-word-bytes)
749                                     instance-pointer-lowtag))
750             value-real)
751       (unless (location= value-real result-real)
752         (inst movsd result-real value-real)))
753     (let ((value-imag (complex-double-reg-imag-tn value))
754           (result-imag (complex-double-reg-imag-tn result)))
755       (inst movsd (make-ea :dword
756                            :base object
757                            :index tmp
758                            :disp (- (* (1- instance-slots-offset) n-word-bytes)
759                                     instance-pointer-lowtag))
760             value-imag)
761       (unless (location= value-imag result-imag)
762         (inst movsd result-imag value-imag)))))