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