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