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