1.0.20.8: ATOMIC-INCF implementation
[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   (if (integerp instance-length)
507       ;; For RAW-INSTANCE-INIT/* VOPs, which know the exact instance length
508       ;; at compile time.
509       (make-ea :dword
510                :base object
511                :disp (- (* (- instance-length instance-slots-offset index (1- n-words))
512                            n-word-bytes)
513                         instance-pointer-lowtag))
514       (flet ((make-ea-using-value (value)
515                (make-ea :dword :base object
516                         :index instance-length
517                         :scale 4
518                         :disp (- (* (- instance-slots-offset n-words)
519                                     n-word-bytes)
520                                  instance-pointer-lowtag
521                                  (* value n-word-bytes)))))
522         (if (typep index 'tn)
523             (sc-case index
524               (any-reg (make-ea :dword
525                                 :base object
526                                 :index instance-length
527                                 :disp (- (* (- instance-slots-offset n-words)
528                                             n-word-bytes)
529                                          instance-pointer-lowtag)))
530               (immediate (make-ea-using-value (tn-value index))))
531             (make-ea-using-value index)))))
532
533 (define-vop (raw-instance-ref/word)
534   (:translate %raw-instance-ref/word)
535   (:policy :fast-safe)
536   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
537   (:arg-types * tagged-num)
538   (:temporary (:sc unsigned-reg) tmp)
539   (:results (value :scs (unsigned-reg)))
540   (:result-types unsigned-num)
541   (:generator 5
542     (loadw tmp object 0 instance-pointer-lowtag)
543     (inst shr tmp n-widetag-bits)
544     (when (sc-is index any-reg)
545       (inst shl tmp 2)
546       (inst sub tmp index))
547     (inst mov value (make-ea-for-raw-slot object index tmp 1))))
548
549 (define-vop (raw-instance-set/word)
550   (:translate %raw-instance-set/word)
551   (:policy :fast-safe)
552   (:args (object :scs (descriptor-reg))
553          (index :scs (any-reg immediate))
554          (value :scs (unsigned-reg) :target result))
555   (:arg-types * tagged-num unsigned-num)
556   (:temporary (:sc unsigned-reg) tmp)
557   (:results (result :scs (unsigned-reg)))
558   (:result-types unsigned-num)
559   (:generator 5
560     (loadw tmp object 0 instance-pointer-lowtag)
561     (inst shr tmp n-widetag-bits)
562     (when (sc-is index any-reg)
563       (inst shl tmp 2)
564       (inst sub tmp index))
565     (inst mov (make-ea-for-raw-slot object index tmp 1) value)
566     (move result value)))
567
568 (define-vop (raw-instance-init/word)
569   (:args (object :scs (descriptor-reg))
570          (value :scs (unsigned-reg)))
571   (:arg-types * unsigned-num)
572   (:info instance-length index)
573   (:generator 5
574     (inst mov (make-ea-for-raw-slot object index instance-length 1) value)))
575
576 (define-vop (raw-instance-atomic-incf/word)
577   (:translate %raw-instance-atomic-incf/word)
578   (:policy :fast-safe)
579   (:args (object :scs (descriptor-reg))
580          (index :scs (any-reg immediate))
581          (diff :scs (signed-reg) :target result))
582   (:arg-types * tagged-num signed-num)
583   (:temporary (:sc unsigned-reg) tmp)
584   (:results (result :scs (unsigned-reg)))
585   (:result-types unsigned-num)
586   (:generator 5
587     (loadw tmp object 0 instance-pointer-lowtag)
588     (inst shr tmp n-widetag-bits)
589     (when (sc-is index any-reg)
590       (inst shl tmp 2)
591       (inst sub tmp index))
592     #!+sb-thread
593     (inst lock)
594     (inst xadd (make-ea-for-raw-slot object index tmp 1) diff)
595     (move result diff)))
596
597 (define-vop (raw-instance-ref/single)
598   (:translate %raw-instance-ref/single)
599   (:policy :fast-safe)
600   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
601   (:arg-types * tagged-num)
602   (:temporary (:sc unsigned-reg) tmp)
603   (:results (value :scs (single-reg)))
604   (:result-types single-float)
605   (:generator 5
606     (loadw tmp object 0 instance-pointer-lowtag)
607     (inst shr tmp n-widetag-bits)
608     (when (sc-is index any-reg)
609       (inst shl tmp 2)
610       (inst sub tmp index))
611     (with-empty-tn@fp-top(value)
612       (inst fld (make-ea-for-raw-slot object index tmp 1)))))
613
614 (define-vop (raw-instance-set/single)
615   (:translate %raw-instance-set/single)
616   (:policy :fast-safe)
617   (:args (object :scs (descriptor-reg))
618          (index :scs (any-reg immediate))
619          (value :scs (single-reg) :target result))
620   (:arg-types * tagged-num single-float)
621   (:temporary (:sc unsigned-reg) tmp)
622   (:results (result :scs (single-reg)))
623   (:result-types single-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     (unless (zerop (tn-offset value))
631       (inst fxch value))
632     (inst fst (make-ea-for-raw-slot object index tmp 1))
633     (cond
634       ((zerop (tn-offset value))
635         (unless (zerop (tn-offset result))
636           (inst fst result)))
637       ((zerop (tn-offset result))
638         (inst fst value))
639       (t
640         (unless (location= value result)
641           (inst fst result))
642         (inst fxch value)))))
643
644 (define-vop (raw-instance-init/single)
645   (:args (object :scs (descriptor-reg))
646          (value :scs (single-reg)))
647   (:arg-types * single-float)
648   (:info instance-length index)
649   (:generator 5
650     (with-tn@fp-top (value)
651       (inst fst (make-ea-for-raw-slot object index instance-length 1)))))
652
653 (define-vop (raw-instance-ref/double)
654   (:translate %raw-instance-ref/double)
655   (:policy :fast-safe)
656   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
657   (:arg-types * tagged-num)
658   (:temporary (:sc unsigned-reg) tmp)
659   (:results (value :scs (double-reg)))
660   (:result-types double-float)
661   (:generator 5
662     (loadw tmp object 0 instance-pointer-lowtag)
663     (inst shr tmp n-widetag-bits)
664     (when (sc-is index any-reg)
665       (inst shl tmp 2)
666       (inst sub tmp index))
667     (with-empty-tn@fp-top(value)
668       (inst fldd (make-ea-for-raw-slot object index tmp 2)))))
669
670 (define-vop (raw-instance-set/double)
671   (:translate %raw-instance-set/double)
672   (:policy :fast-safe)
673   (:args (object :scs (descriptor-reg))
674          (index :scs (any-reg immediate))
675          (value :scs (double-reg) :target result))
676   (:arg-types * tagged-num double-float)
677   (:temporary (:sc unsigned-reg) tmp)
678   (:results (result :scs (double-reg)))
679   (:result-types double-float)
680   (:generator 5
681     (loadw tmp object 0 instance-pointer-lowtag)
682     (inst shr tmp n-widetag-bits)
683     (when (sc-is index any-reg)
684       (inst shl tmp 2)
685       (inst sub tmp index))
686     (unless (zerop (tn-offset value))
687       (inst fxch value))
688     (inst fstd (make-ea-for-raw-slot object index tmp 2))
689     (cond
690       ((zerop (tn-offset value))
691         (unless (zerop (tn-offset result))
692           (inst fstd result)))
693       ((zerop (tn-offset result))
694         (inst fstd value))
695       (t
696         (unless (location= value result)
697           (inst fstd result))
698         (inst fxch value)))))
699
700 (define-vop (raw-instance-init/double)
701   (:args (object :scs (descriptor-reg))
702          (value :scs (double-reg)))
703   (:arg-types * double-float)
704   (:info instance-length index)
705   (:generator 5
706     (with-tn@fp-top (value)
707       (inst fstd (make-ea-for-raw-slot object index instance-length 2)))))
708
709 (define-vop (raw-instance-ref/complex-single)
710   (:translate %raw-instance-ref/complex-single)
711   (:policy :fast-safe)
712   (:args (object :scs (descriptor-reg))
713          (index :scs (any-reg immediate)))
714   (:arg-types * positive-fixnum)
715   (:temporary (:sc unsigned-reg) tmp)
716   (:results (value :scs (complex-single-reg)))
717   (:result-types complex-single-float)
718   (:generator 5
719     (loadw tmp object 0 instance-pointer-lowtag)
720     (inst shr tmp n-widetag-bits)
721     (when (sc-is index any-reg)
722       (inst shl tmp 2)
723       (inst sub tmp index))
724     (let ((real-tn (complex-single-reg-real-tn value)))
725       (with-empty-tn@fp-top (real-tn)
726         (inst fld (make-ea-for-raw-slot object index tmp 2))))
727     (let ((imag-tn (complex-single-reg-imag-tn value)))
728       (with-empty-tn@fp-top (imag-tn)
729         (inst fld (make-ea-for-raw-slot object index tmp 1))))))
730
731 (define-vop (raw-instance-set/complex-single)
732   (:translate %raw-instance-set/complex-single)
733   (:policy :fast-safe)
734   (:args (object :scs (descriptor-reg))
735          (index :scs (any-reg immediate))
736          (value :scs (complex-single-reg) :target result))
737   (:arg-types * positive-fixnum complex-single-float)
738   (:temporary (:sc unsigned-reg) tmp)
739   (:results (result :scs (complex-single-reg)))
740   (:result-types complex-single-float)
741   (:generator 5
742     (loadw tmp object 0 instance-pointer-lowtag)
743     (inst shr tmp n-widetag-bits)
744     (when (sc-is index any-reg)
745       (inst shl tmp 2)
746       (inst sub tmp index))
747     (let ((value-real (complex-single-reg-real-tn value))
748           (result-real (complex-single-reg-real-tn result)))
749       (cond ((zerop (tn-offset value-real))
750              ;; Value is in ST0.
751              (inst fst (make-ea-for-raw-slot object index tmp 2))
752              (unless (zerop (tn-offset result-real))
753                ;; Value is in ST0 but not result.
754                (inst fst result-real)))
755             (t
756              ;; Value is not in ST0.
757              (inst fxch value-real)
758              (inst fst (make-ea-for-raw-slot object index tmp 2))
759              (cond ((zerop (tn-offset result-real))
760                     ;; The result is in ST0.
761                     (inst fst value-real))
762                    (t
763                     ;; Neither value or result are in ST0
764                     (unless (location= value-real result-real)
765                       (inst fst result-real))
766                     (inst fxch value-real))))))
767     (let ((value-imag (complex-single-reg-imag-tn value))
768           (result-imag (complex-single-reg-imag-tn result)))
769       (inst fxch value-imag)
770       (inst fst (make-ea-for-raw-slot object index tmp 1))
771       (unless (location= value-imag result-imag)
772         (inst fst result-imag))
773       (inst fxch value-imag))))
774
775 (define-vop (raw-instance-init/complex-single)
776   (:args (object :scs (descriptor-reg))
777          (value :scs (complex-single-reg)))
778   (:arg-types * complex-single-float)
779   (:info instance-length index)
780   (:generator 5
781     (let ((value-real (complex-single-reg-real-tn value)))
782       (with-tn@fp-top (value-real)
783         (inst fst (make-ea-for-raw-slot object index instance-length 2))))
784     (let ((value-imag (complex-single-reg-imag-tn value)))
785       (with-tn@fp-top (value-imag)
786         (inst fst (make-ea-for-raw-slot object index instance-length 1))))))
787
788 (define-vop (raw-instance-ref/complex-double)
789   (:translate %raw-instance-ref/complex-double)
790   (:policy :fast-safe)
791   (:args (object :scs (descriptor-reg))
792          (index :scs (any-reg immediate)))
793   (:arg-types * positive-fixnum)
794   (:temporary (:sc unsigned-reg) tmp)
795   (:results (value :scs (complex-double-reg)))
796   (:result-types complex-double-float)
797   (:generator 7
798     (loadw tmp object 0 instance-pointer-lowtag)
799     (inst shr tmp n-widetag-bits)
800     (when (sc-is index any-reg)
801       (inst shl tmp 2)
802       (inst sub tmp index))
803     (let ((real-tn (complex-double-reg-real-tn value)))
804       (with-empty-tn@fp-top (real-tn)
805         (inst fldd (make-ea-for-raw-slot object index tmp 4))))
806     (let ((imag-tn (complex-double-reg-imag-tn value)))
807       (with-empty-tn@fp-top (imag-tn)
808         (inst fldd (make-ea-for-raw-slot object index tmp 2))))))
809
810 (define-vop (raw-instance-set/complex-double)
811   (:translate %raw-instance-set/complex-double)
812   (:policy :fast-safe)
813   (:args (object :scs (descriptor-reg))
814          (index :scs (any-reg immediate))
815          (value :scs (complex-double-reg) :target result))
816   (:arg-types * positive-fixnum complex-double-float)
817   (:temporary (:sc unsigned-reg) tmp)
818   (:results (result :scs (complex-double-reg)))
819   (:result-types complex-double-float)
820   (:generator 20
821     (loadw tmp object 0 instance-pointer-lowtag)
822     (inst shr tmp n-widetag-bits)
823     (when (sc-is index any-reg)
824       (inst shl tmp 2)
825       (inst sub tmp index))
826     (let ((value-real (complex-double-reg-real-tn value))
827           (result-real (complex-double-reg-real-tn result)))
828       (cond ((zerop (tn-offset value-real))
829              ;; Value is in ST0.
830              (inst fstd (make-ea-for-raw-slot object index tmp 4))
831              (unless (zerop (tn-offset result-real))
832                ;; Value is in ST0 but not result.
833                (inst fstd result-real)))
834             (t
835              ;; Value is not in ST0.
836              (inst fxch value-real)
837              (inst fstd (make-ea-for-raw-slot object index tmp 4))
838              (cond ((zerop (tn-offset result-real))
839                     ;; The result is in ST0.
840                     (inst fstd value-real))
841                    (t
842                     ;; Neither value or result are in ST0
843                     (unless (location= value-real result-real)
844                       (inst fstd result-real))
845                     (inst fxch value-real))))))
846     (let ((value-imag (complex-double-reg-imag-tn value))
847           (result-imag (complex-double-reg-imag-tn result)))
848       (inst fxch value-imag)
849       (inst fstd (make-ea-for-raw-slot object index tmp 2))
850       (unless (location= value-imag result-imag)
851         (inst fstd result-imag))
852       (inst fxch value-imag))))
853
854 (define-vop (raw-instance-init/complex-double)
855   (:args (object :scs (descriptor-reg))
856          (value :scs (complex-double-reg)))
857   (:arg-types * complex-double-float)
858   (:info instance-length index)
859   (:generator 20
860     (let ((value-real (complex-double-reg-real-tn value)))
861       (with-tn@fp-top (value-real)
862         (inst fstd (make-ea-for-raw-slot object index instance-length 4))))
863     (let ((value-imag (complex-double-reg-imag-tn value)))
864       (with-tn@fp-top (value-imag)
865         (inst fstd (make-ea-for-raw-slot object index instance-length 2))))))