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