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