1.0.20.8: ATOMIC-INCF implementation
[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 two 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, no 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 cmp (make-ea :qword :base thread-base-tn :scale 1 :index tls)
126             no-tls-value-marker-widetag)
127       (inst jmp :z global-val)
128       (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls)
129             value)
130       (inst jmp done)
131       (emit-label global-val)
132       (storew value symbol symbol-value-slot other-pointer-lowtag)
133       (emit-label done))))
134
135 ;; unithreaded it's a lot simpler ...
136 #!-sb-thread
137 (define-vop (set cell-set)
138   (:variant symbol-value-slot other-pointer-lowtag))
139
140 ;;; With Symbol-Value, we check that the value isn't the trap object. So
141 ;;; Symbol-Value of NIL is NIL.
142 #!+sb-thread
143 (define-vop (symbol-value)
144   (:translate symbol-value)
145   (:policy :fast-safe)
146   (:args (object :scs (descriptor-reg) :to (:result 1)))
147   (:results (value :scs (descriptor-reg any-reg)))
148   (:vop-var vop)
149   (:save-p :compute-only)
150   (:generator 9
151     (let* ((check-unbound-label (gen-label))
152            (err-lab (generate-error-code vop 'unbound-symbol-error object))
153            (ret-lab (gen-label)))
154       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
155       (inst mov value (make-ea :qword :base thread-base-tn
156                                :index value :scale 1))
157       (inst cmp value no-tls-value-marker-widetag)
158       (inst jmp :ne check-unbound-label)
159       (loadw value object symbol-value-slot other-pointer-lowtag)
160       (emit-label check-unbound-label)
161       (inst cmp value unbound-marker-widetag)
162       (inst jmp :e err-lab)
163       (emit-label ret-lab))))
164
165 #!+sb-thread
166 (define-vop (fast-symbol-value symbol-value)
167   ;; KLUDGE: not really fast, in fact, because we're going to have to
168   ;; do a full lookup of the thread-local area anyway.  But half of
169   ;; the meaning of FAST-SYMBOL-VALUE is "do not signal an error if
170   ;; unbound", which is used in the implementation of COPY-SYMBOL.  --
171   ;; CSR, 2003-04-22
172   (:policy :fast)
173   (:translate symbol-value)
174   (:generator 8
175     (let ((ret-lab (gen-label)))
176       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
177       (inst mov value
178             (make-ea :qword :base thread-base-tn :index value :scale 1))
179       (inst cmp value no-tls-value-marker-widetag)
180       (inst jmp :ne ret-lab)
181       (loadw value object symbol-value-slot other-pointer-lowtag)
182       (emit-label ret-lab))))
183
184 #!-sb-thread
185 (define-vop (symbol-value)
186   (:translate symbol-value)
187   (:policy :fast-safe)
188   (:args (object :scs (descriptor-reg) :to (:result 1)))
189   (:results (value :scs (descriptor-reg any-reg)))
190   (:vop-var vop)
191   (:save-p :compute-only)
192   (:generator 9
193     (let ((err-lab (generate-error-code vop 'unbound-symbol-error object)))
194       (loadw value object symbol-value-slot other-pointer-lowtag)
195       (inst cmp value unbound-marker-widetag)
196       (inst jmp :e err-lab))))
197
198 #!-sb-thread
199 (define-vop (fast-symbol-value cell-ref)
200   (:variant symbol-value-slot other-pointer-lowtag)
201   (:policy :fast)
202   (:translate symbol-value))
203
204 (defknown locked-symbol-global-value-add (symbol fixnum) fixnum ())
205
206 (define-vop (locked-symbol-global-value-add)
207     (:args (object :scs (descriptor-reg) :to :result)
208            (value :scs (any-reg) :target result))
209   (:arg-types * tagged-num)
210   (:results (result :scs (any-reg) :from (:argument 1)))
211   (:policy :fast)
212   (:translate locked-symbol-global-value-add)
213   (:result-types tagged-num)
214   (:policy :fast-safe)
215   (:generator 4
216     (move result value)
217     (inst lock)
218     (inst add (make-ea :qword :base object
219                        :disp (- (* symbol-value-slot n-word-bytes)
220                                 other-pointer-lowtag))
221           value)))
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   (:temporary (:sc descriptor-reg #+nil(:from (:argument 0))) value)
231   (:generator 9
232     (let ((check-unbound-label (gen-label)))
233       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
234       (inst mov value
235             (make-ea :qword :base thread-base-tn :index value :scale 1))
236       (inst cmp value no-tls-value-marker-widetag)
237       (inst jmp :ne check-unbound-label)
238       (loadw value object symbol-value-slot other-pointer-lowtag)
239       (emit-label check-unbound-label)
240       (inst cmp value unbound-marker-widetag)
241       (inst jmp (if not-p :e :ne) target))))
242
243 #!-sb-thread
244 (define-vop (boundp)
245   (:translate boundp)
246   (:policy :fast-safe)
247   (:args (object :scs (descriptor-reg)))
248   (:conditional)
249   (:info target not-p)
250   (:generator 9
251     (inst cmp (make-ea-for-object-slot object symbol-value-slot
252                                        other-pointer-lowtag)
253           unbound-marker-widetag)
254     (inst jmp (if not-p :e :ne) target)))
255
256
257 (define-vop (symbol-hash)
258   (:policy :fast-safe)
259   (:translate symbol-hash)
260   (:args (symbol :scs (descriptor-reg)))
261   (:results (res :scs (any-reg)))
262   (:result-types positive-fixnum)
263   (:generator 2
264     ;; The symbol-hash slot of NIL holds NIL because it is also the
265     ;; cdr slot, so we have to strip off the three low bits to make sure
266     ;; it is a fixnum.  The lowtag selection magic that is required to
267     ;; ensure this is explained in the comment in objdef.lisp
268     (loadw res symbol symbol-hash-slot other-pointer-lowtag)
269     (inst and res (lognot #b111))))
270 \f
271 ;;;; fdefinition (FDEFN) objects
272
273 (define-vop (fdefn-fun cell-ref)        ; /pfw - alpha
274   (:variant fdefn-fun-slot other-pointer-lowtag))
275
276 (define-vop (safe-fdefn-fun)
277   (:args (object :scs (descriptor-reg) :to (:result 1)))
278   (:results (value :scs (descriptor-reg any-reg)))
279   (:vop-var vop)
280   (:save-p :compute-only)
281   (:generator 10
282     (loadw value object fdefn-fun-slot other-pointer-lowtag)
283     (inst cmp value nil-value)
284     (let ((err-lab (generate-error-code vop 'undefined-fun-error object)))
285       (inst jmp :e err-lab))))
286
287 (define-vop (set-fdefn-fun)
288   (:policy :fast-safe)
289   (:translate (setf fdefn-fun))
290   (:args (function :scs (descriptor-reg) :target result)
291          (fdefn :scs (descriptor-reg)))
292   (:temporary (:sc unsigned-reg) raw)
293   (:temporary (:sc byte-reg) type)
294   (:results (result :scs (descriptor-reg)))
295   (:generator 38
296     (load-type type function (- fun-pointer-lowtag))
297     (inst lea raw
298           (make-ea :byte :base function
299                    :disp (- (* simple-fun-code-offset n-word-bytes)
300                             fun-pointer-lowtag)))
301     (inst cmp type simple-fun-header-widetag)
302     (inst jmp :e NORMAL-FUN)
303     (inst lea raw (make-fixup "closure_tramp" :foreign))
304     NORMAL-FUN
305     (storew function fdefn fdefn-fun-slot other-pointer-lowtag)
306     (storew raw fdefn fdefn-raw-addr-slot other-pointer-lowtag)
307     (move result function)))
308
309 (define-vop (fdefn-makunbound)
310   (:policy :fast-safe)
311   (:translate fdefn-makunbound)
312   (:args (fdefn :scs (descriptor-reg) :target result))
313   (:results (result :scs (descriptor-reg)))
314   (:generator 38
315     (storew nil-value fdefn fdefn-fun-slot other-pointer-lowtag)
316     (storew (make-fixup "undefined_tramp" :foreign)
317             fdefn fdefn-raw-addr-slot other-pointer-lowtag)
318     (move result fdefn)))
319 \f
320 ;;;; binding and unbinding
321
322 ;;; BIND -- Establish VAL as a binding for SYMBOL. Save the old value and
323 ;;; the symbol on the binding stack and stuff the new value into the
324 ;;; symbol.
325
326 #!+sb-thread
327 (define-vop (bind)
328   (:args (val :scs (any-reg descriptor-reg))
329          (symbol :scs (descriptor-reg)))
330   (:temporary (:sc unsigned-reg) tls-index bsp)
331   (:generator 10
332     (let ((tls-index-valid (gen-label)))
333       (load-binding-stack-pointer bsp)
334       (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
335       (inst add bsp (* binding-size n-word-bytes))
336       (store-binding-stack-pointer bsp)
337       (inst or tls-index tls-index)
338       (inst jmp :ne tls-index-valid)
339       (inst mov tls-index symbol)
340       (inst lea temp-reg-tn
341             (make-ea :qword :disp
342                      (make-fixup (ecase (tn-offset tls-index)
343                                    (#.rax-offset 'alloc-tls-index-in-rax)
344                                    (#.rcx-offset 'alloc-tls-index-in-rcx)
345                                    (#.rdx-offset 'alloc-tls-index-in-rdx)
346                                    (#.rbx-offset 'alloc-tls-index-in-rbx)
347                                    (#.rsi-offset 'alloc-tls-index-in-rsi)
348                                    (#.rdi-offset 'alloc-tls-index-in-rdi)
349                                    (#.r8-offset  'alloc-tls-index-in-r8)
350                                    (#.r9-offset  'alloc-tls-index-in-r9)
351                                    (#.r10-offset 'alloc-tls-index-in-r10)
352                                    (#.r12-offset 'alloc-tls-index-in-r12)
353                                    (#.r13-offset 'alloc-tls-index-in-r13)
354                                    (#.r14-offset 'alloc-tls-index-in-r14)
355                                    (#.r15-offset 'alloc-tls-index-in-r15))
356                                  :assembly-routine)))
357       (inst call temp-reg-tn)
358       (emit-label tls-index-valid)
359       (inst push (make-ea :qword :base thread-base-tn :scale 1 :index tls-index))
360       (popw bsp (- binding-value-slot binding-size))
361       (storew symbol bsp (- binding-symbol-slot binding-size))
362       (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
363             val))))
364
365 #!-sb-thread
366 (define-vop (bind)
367   (:args (val :scs (any-reg descriptor-reg))
368          (symbol :scs (descriptor-reg)))
369   (:temporary (:sc unsigned-reg) temp bsp)
370   (:generator 5
371     (load-symbol-value bsp *binding-stack-pointer*)
372     (loadw temp symbol symbol-value-slot other-pointer-lowtag)
373     (inst add bsp (* binding-size n-word-bytes))
374     (store-symbol-value bsp *binding-stack-pointer*)
375     (storew temp bsp (- binding-value-slot binding-size))
376     (storew symbol bsp (- binding-symbol-slot binding-size))
377     (storew val symbol symbol-value-slot other-pointer-lowtag)))
378
379 #!+sb-thread
380 (define-vop (unbind)
381   (:temporary (:sc unsigned-reg) temp bsp tls-index)
382   (:generator 0
383     (load-binding-stack-pointer bsp)
384     ;; Load SYMBOL from stack, and get the TLS-INDEX
385     (loadw temp bsp (- binding-symbol-slot binding-size))
386     (loadw tls-index temp symbol-tls-index-slot other-pointer-lowtag)
387     ;; Load VALUE from stack, the restore it to the TLS area.
388     (loadw temp bsp (- binding-value-slot binding-size))
389     (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
390           temp)
391     ;; Zero out the stack.
392     (storew 0 bsp (- binding-symbol-slot binding-size))
393     (storew 0 bsp (- binding-value-slot binding-size))
394     (inst sub bsp (* binding-size n-word-bytes))
395     (store-binding-stack-pointer bsp)))
396
397 #!-sb-thread
398 (define-vop (unbind)
399   (:temporary (:sc unsigned-reg) symbol value bsp)
400   (:generator 0
401     (load-symbol-value bsp *binding-stack-pointer*)
402     (loadw symbol bsp (- binding-symbol-slot binding-size))
403     (loadw value bsp (- binding-value-slot binding-size))
404     (storew value symbol symbol-value-slot other-pointer-lowtag)
405     (storew 0 bsp (- binding-symbol-slot binding-size))
406     (storew 0 bsp (- binding-value-slot binding-size))
407     (inst sub bsp (* binding-size n-word-bytes))
408     (store-symbol-value bsp *binding-stack-pointer*)))
409
410 (define-vop (unbind-to-here)
411   (:args (where :scs (descriptor-reg any-reg)))
412   (:temporary (:sc unsigned-reg) symbol value bsp #!+sb-thread tls-index)
413   (:generator 0
414     (load-binding-stack-pointer bsp)
415     (inst cmp where bsp)
416     (inst jmp :e DONE)
417
418     LOOP
419     (loadw symbol bsp (- binding-symbol-slot binding-size))
420     (inst or symbol symbol)
421     (inst jmp :z SKIP)
422     ;; Bind stack debug sentinels have the unbound marker in the symbol slot
423     (inst cmp symbol unbound-marker-widetag)
424     (inst jmp :eq SKIP)
425     (loadw value bsp (- binding-value-slot binding-size))
426     #!-sb-thread
427     (storew value symbol symbol-value-slot other-pointer-lowtag)
428     #!+sb-thread
429     (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
430     #!+sb-thread
431     (inst mov (make-ea :qword :base thread-base-tn :scale 1 :index tls-index)
432           value)
433     (storew 0 bsp (- binding-symbol-slot binding-size))
434
435     SKIP
436     (storew 0 bsp (- binding-value-slot binding-size))
437     (inst sub bsp (* binding-size n-word-bytes))
438     (inst cmp where bsp)
439     (inst jmp :ne LOOP)
440     (store-binding-stack-pointer bsp)
441
442     DONE))
443
444 (define-vop (bind-sentinel)
445   (:temporary (:sc unsigned-reg) bsp)
446   (:generator 1
447      (load-binding-stack-pointer bsp)
448      (inst add bsp (* binding-size n-word-bytes))
449      (storew unbound-marker-widetag bsp (- binding-symbol-slot binding-size))
450      (storew rbp-tn bsp (- binding-value-slot binding-size))
451      (store-binding-stack-pointer bsp)))
452
453 (define-vop (unbind-sentinel)
454   (:temporary (:sc unsigned-reg) bsp)
455   (:generator 1
456      (load-binding-stack-pointer bsp)
457      (storew 0 bsp (- binding-value-slot binding-size))
458      (storew 0 bsp (- binding-symbol-slot binding-size))
459      (inst sub bsp (* binding-size n-word-bytes))
460      (store-binding-stack-pointer bsp)))
461
462 \f
463
464 \f
465 ;;;; closure indexing
466
467 (define-full-reffer closure-index-ref *
468   closure-info-offset fun-pointer-lowtag
469   (any-reg descriptor-reg) * %closure-index-ref)
470
471 (define-full-setter set-funcallable-instance-info *
472   funcallable-instance-info-offset fun-pointer-lowtag
473   (any-reg descriptor-reg) * %set-funcallable-instance-info)
474
475 (define-full-reffer funcallable-instance-info *
476   funcallable-instance-info-offset fun-pointer-lowtag
477   (descriptor-reg any-reg) * %funcallable-instance-info)
478
479 (define-vop (closure-ref slot-ref)
480   (:variant closure-info-offset fun-pointer-lowtag))
481
482 (define-vop (closure-init slot-set)
483   (:variant closure-info-offset fun-pointer-lowtag))
484 \f
485 ;;;; value cell hackery
486
487 (define-vop (value-cell-ref cell-ref)
488   (:variant value-cell-value-slot other-pointer-lowtag))
489
490 (define-vop (value-cell-set cell-set)
491   (:variant value-cell-value-slot other-pointer-lowtag))
492 \f
493 ;;;; structure hackery
494
495 (define-vop (instance-length)
496   (:policy :fast-safe)
497   (:translate %instance-length)
498   (:args (struct :scs (descriptor-reg)))
499   (:results (res :scs (unsigned-reg)))
500   (:result-types positive-fixnum)
501   (:generator 4
502     (loadw res struct 0 instance-pointer-lowtag)
503     (inst shr res n-widetag-bits)))
504
505 (define-full-reffer instance-index-ref * instance-slots-offset
506   instance-pointer-lowtag (any-reg descriptor-reg) * %instance-ref)
507
508 (define-full-setter instance-index-set * instance-slots-offset
509   instance-pointer-lowtag (any-reg descriptor-reg) * %instance-set)
510
511 (define-full-compare-and-swap %compare-and-swap-instance-ref instance
512   instance-slots-offset instance-pointer-lowtag
513   (any-reg descriptor-reg) *
514   %compare-and-swap-instance-ref)
515 \f
516 ;;;; code object frobbing
517
518 (define-full-reffer code-header-ref * 0 other-pointer-lowtag
519   (any-reg descriptor-reg) * code-header-ref)
520
521 (define-full-setter code-header-set * 0 other-pointer-lowtag
522   (any-reg descriptor-reg) * code-header-set)
523 \f
524 ;;;; raw instance slot accessors
525
526 (defun make-ea-for-raw-slot (object index instance-length
527                              &optional (adjustment 0))
528   (if (integerp instance-length)
529       ;; For RAW-INSTANCE-INIT/* VOPs, which know the exact instance length
530       ;; at compile time.
531       (make-ea :qword
532                :base object
533                :disp (+ (* (- instance-length instance-slots-offset index)
534                            n-word-bytes)
535                         (- instance-pointer-lowtag)
536                         adjustment))
537       (etypecase index
538         (tn
539          (make-ea :qword :base object :index instance-length
540                   :disp (+ (* (1- instance-slots-offset) n-word-bytes)
541                            (- instance-pointer-lowtag)
542                            adjustment)))
543         (integer
544          (make-ea :qword :base object :index instance-length
545                   :scale 8
546                   :disp (+ (* (1- instance-slots-offset) n-word-bytes)
547                            (- instance-pointer-lowtag)
548                            adjustment
549                            (* index (- n-word-bytes))))))))
550
551 (define-vop (raw-instance-ref/word)
552   (:translate %raw-instance-ref/word)
553   (:policy :fast-safe)
554   (:args (object :scs (descriptor-reg)) (index :scs (any-reg)))
555   (:arg-types * tagged-num)
556   (:temporary (:sc unsigned-reg) tmp)
557   (:results (value :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     (inst shl tmp 3)
563     (inst sub tmp index)
564     (inst mov value (make-ea-for-raw-slot object index tmp))))
565
566 (define-vop (raw-instance-ref-c/word)
567   (:translate %raw-instance-ref/word)
568   (:policy :fast-safe)
569   (:args (object :scs (descriptor-reg)))
570   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
571                                              #.instance-pointer-lowtag
572                                              #.instance-slots-offset)))
573   (:info index)
574   (:temporary (:sc unsigned-reg) tmp)
575   (:results (value :scs (unsigned-reg)))
576   (:result-types unsigned-num)
577   (:generator 4
578     (loadw tmp object 0 instance-pointer-lowtag)
579     (inst shr tmp n-widetag-bits)
580     (inst mov value (make-ea-for-raw-slot object index tmp))))
581
582 (define-vop (raw-instance-set/word)
583   (:translate %raw-instance-set/word)
584   (:policy :fast-safe)
585   (:args (object :scs (descriptor-reg))
586          (index :scs (any-reg))
587          (value :scs (unsigned-reg) :target result))
588   (:arg-types * tagged-num unsigned-num)
589   (:temporary (:sc unsigned-reg) tmp)
590   (:results (result :scs (unsigned-reg)))
591   (:result-types unsigned-num)
592   (:generator 5
593     (loadw tmp object 0 instance-pointer-lowtag)
594     (inst shr tmp n-widetag-bits)
595     (inst shl tmp 3)
596     (inst sub tmp index)
597     (inst mov (make-ea-for-raw-slot object index tmp) value)
598     (move result value)))
599
600 (define-vop (raw-instance-set-c/word)
601   (:translate %raw-instance-set/word)
602   (:policy :fast-safe)
603   (:args (object :scs (descriptor-reg))
604          (value :scs (unsigned-reg) :target result))
605   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
606                                              #.instance-pointer-lowtag
607                                              #.instance-slots-offset))
608               unsigned-num)
609   (:info index)
610   (:temporary (:sc unsigned-reg) tmp)
611   (:results (result :scs (unsigned-reg)))
612   (:result-types unsigned-num)
613   (:generator 4
614     (loadw tmp object 0 instance-pointer-lowtag)
615     (inst shr tmp n-widetag-bits)
616     (inst mov (make-ea-for-raw-slot object index tmp) value)
617     (move result value)))
618
619 (define-vop (raw-instance-init/word)
620   (:args (object :scs (descriptor-reg))
621          (value :scs (unsigned-reg)))
622   (:arg-types * unsigned-num)
623   (:info instance-length index)
624   (:generator 4
625     (inst mov (make-ea-for-raw-slot object index instance-length) value)))
626
627 (define-vop (raw-instance-atomic-incf-c/word)
628   (:translate %raw-instance-atomic-incf/word)
629   (:policy :fast-safe)
630   (:args (object :scs (descriptor-reg))
631          (diff :scs (signed-reg) :target result))
632   (:arg-types * (:constant (load/store-index #.n-word-bytes
633                                              #.instance-pointer-lowtag
634                                              #.instance-slots-offset))
635               signed-num)
636   (:info index)
637   (:temporary (:sc unsigned-reg) tmp)
638   (:results (result :scs (unsigned-reg)))
639   (:result-types unsigned-num)
640   (:generator 4
641     (loadw tmp object 0 instance-pointer-lowtag)
642     (inst shr tmp n-widetag-bits)
643     #!+sb-thread
644     (inst lock)
645     (inst xadd (make-ea-for-raw-slot object index tmp) diff)
646     (move result diff)))
647
648 (define-vop (raw-instance-ref/single)
649   (:translate %raw-instance-ref/single)
650   (:policy :fast-safe)
651   (:args (object :scs (descriptor-reg))
652          (index :scs (any-reg)))
653   (:arg-types * positive-fixnum)
654   (:temporary (:sc unsigned-reg) tmp)
655   (:results (value :scs (single-reg)))
656   (:result-types single-float)
657   (:generator 5
658     (loadw tmp object 0 instance-pointer-lowtag)
659     (inst shr tmp n-widetag-bits)
660     (inst shl tmp 3)
661     (inst sub tmp index)
662     (inst movss value (make-ea-for-raw-slot object index tmp))))
663
664 (define-vop (raw-instance-ref-c/single)
665   (:translate %raw-instance-ref/single)
666   (:policy :fast-safe)
667   (:args (object :scs (descriptor-reg)))
668   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
669                                              #.instance-pointer-lowtag
670                                              #.instance-slots-offset)))
671   (:info index)
672   (:temporary (:sc unsigned-reg) tmp)
673   (:results (value :scs (single-reg)))
674   (:result-types single-float)
675   (:generator 4
676     (loadw tmp object 0 instance-pointer-lowtag)
677     (inst shr tmp n-widetag-bits)
678     (inst movss value (make-ea-for-raw-slot object index tmp))))
679
680 (define-vop (raw-instance-set/single)
681   (:translate %raw-instance-set/single)
682   (:policy :fast-safe)
683   (:args (object :scs (descriptor-reg))
684          (index :scs (any-reg))
685          (value :scs (single-reg) :target result))
686   (:arg-types * positive-fixnum single-float)
687   (:temporary (:sc unsigned-reg) tmp)
688   (:results (result :scs (single-reg)))
689   (:result-types single-float)
690   (:generator 5
691     (loadw tmp object 0 instance-pointer-lowtag)
692     (inst shr tmp n-widetag-bits)
693     (inst shl tmp 3)
694     (inst sub tmp index)
695     (inst movss (make-ea-for-raw-slot object index tmp) value)
696    (unless (location= result value)
697      (inst movss result value))))
698
699 (define-vop (raw-instance-set-c/single)
700   (:translate %raw-instance-set/single)
701   (:policy :fast-safe)
702   (:args (object :scs (descriptor-reg))
703          (value :scs (single-reg) :target result))
704   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
705                                              #.instance-pointer-lowtag
706                                              #.instance-slots-offset))
707               single-float)
708   (:info index)
709   (:temporary (:sc unsigned-reg) tmp)
710   (:results (result :scs (single-reg)))
711   (:result-types single-float)
712   (:generator 4
713     (loadw tmp object 0 instance-pointer-lowtag)
714     (inst shr tmp n-widetag-bits)
715     (inst movss (make-ea-for-raw-slot object index tmp) value)
716    (unless (location= result value)
717      (inst movss result value))))
718
719 (define-vop (raw-instance-init/single)
720   (:args (object :scs (descriptor-reg))
721          (value :scs (single-reg)))
722   (:arg-types * single-float)
723   (:info instance-length index)
724   (:generator 4
725     (inst movss (make-ea-for-raw-slot object index instance-length) value)))
726
727 (define-vop (raw-instance-ref/double)
728   (:translate %raw-instance-ref/double)
729   (:policy :fast-safe)
730   (:args (object :scs (descriptor-reg))
731          (index :scs (any-reg)))
732   (:arg-types * positive-fixnum)
733   (:temporary (:sc unsigned-reg) tmp)
734   (:results (value :scs (double-reg)))
735   (:result-types double-float)
736   (:generator 5
737     (loadw tmp object 0 instance-pointer-lowtag)
738     (inst shr tmp n-widetag-bits)
739     (inst shl tmp 3)
740     (inst sub tmp index)
741     (inst movsd value (make-ea-for-raw-slot object index tmp))))
742
743 (define-vop (raw-instance-ref-c/double)
744   (:translate %raw-instance-ref/double)
745   (:policy :fast-safe)
746   (:args (object :scs (descriptor-reg)))
747   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
748                                              #.instance-pointer-lowtag
749                                              #.instance-slots-offset)))
750   (:info index)
751   (:temporary (:sc unsigned-reg) tmp)
752   (:results (value :scs (double-reg)))
753   (:result-types double-float)
754   (:generator 4
755     (loadw tmp object 0 instance-pointer-lowtag)
756     (inst shr tmp n-widetag-bits)
757     (inst movsd value (make-ea-for-raw-slot object index tmp))))
758
759 (define-vop (raw-instance-set/double)
760   (:translate %raw-instance-set/double)
761   (:policy :fast-safe)
762   (:args (object :scs (descriptor-reg))
763          (index :scs (any-reg))
764          (value :scs (double-reg) :target result))
765   (:arg-types * positive-fixnum double-float)
766   (:temporary (:sc unsigned-reg) tmp)
767   (:results (result :scs (double-reg)))
768   (:result-types double-float)
769   (:generator 5
770     (loadw tmp object 0 instance-pointer-lowtag)
771     (inst shr tmp n-widetag-bits)
772     (inst shl tmp 3)
773     (inst sub tmp index)
774     (inst movsd (make-ea-for-raw-slot object index tmp) value)
775    (unless (location= result value)
776      (inst movsd result value))))
777
778 (define-vop (raw-instance-set-c/double)
779   (:translate %raw-instance-set/double)
780   (:policy :fast-safe)
781   (:args (object :scs (descriptor-reg))
782          (value :scs (double-reg) :target result))
783   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
784                                              #.instance-pointer-lowtag
785                                              #.instance-slots-offset))
786               double-float)
787   (:info index)
788   (:temporary (:sc unsigned-reg) tmp)
789   (:results (result :scs (double-reg)))
790   (:result-types double-float)
791   (:generator 4
792     (loadw tmp object 0 instance-pointer-lowtag)
793     (inst shr tmp n-widetag-bits)
794     (inst movsd (make-ea-for-raw-slot object index tmp) value)
795    (unless (location= result value)
796      (inst movsd result value))))
797
798 (define-vop (raw-instance-init/double)
799   (:args (object :scs (descriptor-reg))
800          (value :scs (double-reg)))
801   (:arg-types * double-float)
802   (:info instance-length index)
803   (:generator 4
804     (inst movsd (make-ea-for-raw-slot object index instance-length) value)))
805
806 (define-vop (raw-instance-ref/complex-single)
807   (:translate %raw-instance-ref/complex-single)
808   (:policy :fast-safe)
809   (:args (object :scs (descriptor-reg))
810          (index :scs (any-reg)))
811   (:arg-types * positive-fixnum)
812   (:temporary (:sc unsigned-reg) tmp)
813   (:results (value :scs (complex-single-reg)))
814   (:result-types complex-single-float)
815   (:generator 5
816     (loadw tmp object 0 instance-pointer-lowtag)
817     (inst shr tmp n-widetag-bits)
818     (inst shl tmp 3)
819     (inst sub tmp index)
820     (let ((real-tn (complex-single-reg-real-tn value)))
821       (inst movss real-tn (make-ea-for-raw-slot object index tmp)))
822     (let ((imag-tn (complex-single-reg-imag-tn value)))
823       (inst movss imag-tn (make-ea-for-raw-slot object index tmp 4)))))
824
825 (define-vop (raw-instance-ref-c/complex-single)
826   (:translate %raw-instance-ref/complex-single)
827   (:policy :fast-safe)
828   (:args (object :scs (descriptor-reg)))
829   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
830                                              #.instance-pointer-lowtag
831                                              #.instance-slots-offset)))
832   (:info index)
833   (:temporary (:sc unsigned-reg) tmp)
834   (:results (value :scs (complex-single-reg)))
835   (:result-types complex-single-float)
836   (:generator 4
837     (loadw tmp object 0 instance-pointer-lowtag)
838     (inst shr tmp n-widetag-bits)
839     (let ((real-tn (complex-single-reg-real-tn value)))
840       (inst movss real-tn (make-ea-for-raw-slot object index tmp)))
841     (let ((imag-tn (complex-single-reg-imag-tn value)))
842       (inst movss imag-tn (make-ea-for-raw-slot object index tmp 4)))))
843
844 (define-vop (raw-instance-set/complex-single)
845   (:translate %raw-instance-set/complex-single)
846   (:policy :fast-safe)
847   (:args (object :scs (descriptor-reg))
848          (index :scs (any-reg))
849          (value :scs (complex-single-reg) :target result))
850   (:arg-types * positive-fixnum complex-single-float)
851   (:temporary (:sc unsigned-reg) tmp)
852   (:results (result :scs (complex-single-reg)))
853   (:result-types complex-single-float)
854   (:generator 5
855     (loadw tmp object 0 instance-pointer-lowtag)
856     (inst shr tmp n-widetag-bits)
857     (inst shl tmp 3)
858     (inst sub tmp index)
859     (let ((value-real (complex-single-reg-real-tn value))
860           (result-real (complex-single-reg-real-tn result)))
861       (inst movss (make-ea-for-raw-slot object index tmp) value-real)
862       (unless (location= value-real result-real)
863         (inst movss result-real value-real)))
864     (let ((value-imag (complex-single-reg-imag-tn value))
865           (result-imag (complex-single-reg-imag-tn result)))
866       (inst movss (make-ea-for-raw-slot object index tmp 4) value-imag)
867       (unless (location= value-imag result-imag)
868         (inst movss result-imag value-imag)))))
869
870 (define-vop (raw-instance-set-c/complex-single)
871   (:translate %raw-instance-set/complex-single)
872   (:policy :fast-safe)
873   (:args (object :scs (descriptor-reg))
874          (value :scs (complex-single-reg) :target result))
875   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
876                                              #.instance-pointer-lowtag
877                                              #.instance-slots-offset))
878               complex-single-float)
879   (:info index)
880   (:temporary (:sc unsigned-reg) tmp)
881   (:results (result :scs (complex-single-reg)))
882   (:result-types complex-single-float)
883   (:generator 4
884     (loadw tmp object 0 instance-pointer-lowtag)
885     (inst shr tmp n-widetag-bits)
886     (let ((value-real (complex-single-reg-real-tn value))
887           (result-real (complex-single-reg-real-tn result)))
888       (inst movss (make-ea-for-raw-slot object index tmp) value-real)
889       (unless (location= value-real result-real)
890         (inst movss result-real value-real)))
891     (let ((value-imag (complex-single-reg-imag-tn value))
892           (result-imag (complex-single-reg-imag-tn result)))
893       (inst movss (make-ea-for-raw-slot object index tmp 4) value-imag)
894       (unless (location= value-imag result-imag)
895         (inst movss result-imag value-imag)))))
896
897 (define-vop (raw-instance-init/complex-single)
898   (:args (object :scs (descriptor-reg))
899          (value :scs (complex-single-reg)))
900   (:arg-types * complex-single-float)
901   (:info instance-length index)
902   (:generator 4
903     (let ((value-real (complex-single-reg-real-tn value)))
904       (inst movss (make-ea-for-raw-slot object index instance-length) value-real))
905     (let ((value-imag (complex-single-reg-imag-tn value)))
906       (inst movss (make-ea-for-raw-slot object index instance-length 4) value-imag))))
907
908 (define-vop (raw-instance-ref/complex-double)
909   (:translate %raw-instance-ref/complex-double)
910   (:policy :fast-safe)
911   (:args (object :scs (descriptor-reg))
912          (index :scs (any-reg)))
913   (:arg-types * positive-fixnum)
914   (:temporary (:sc unsigned-reg) tmp)
915   (:results (value :scs (complex-double-reg)))
916   (:result-types complex-double-float)
917   (:generator 5
918     (loadw tmp object 0 instance-pointer-lowtag)
919     (inst shr tmp n-widetag-bits)
920     (inst shl tmp 3)
921     (inst sub tmp index)
922     (let ((real-tn (complex-double-reg-real-tn value)))
923       (inst movsd real-tn (make-ea-for-raw-slot object index tmp -8)))
924     (let ((imag-tn (complex-double-reg-imag-tn value)))
925       (inst movsd imag-tn (make-ea-for-raw-slot object index tmp)))))
926
927 (define-vop (raw-instance-ref-c/complex-double)
928   (:translate %raw-instance-ref/complex-double)
929   (:policy :fast-safe)
930   (:args (object :scs (descriptor-reg)))
931   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
932                                              #.instance-pointer-lowtag
933                                              #.instance-slots-offset)))
934   (:info index)
935   (:temporary (:sc unsigned-reg) tmp)
936   (:results (value :scs (complex-double-reg)))
937   (:result-types complex-double-float)
938   (:generator 4
939     (loadw tmp object 0 instance-pointer-lowtag)
940     (inst shr tmp n-widetag-bits)
941     (let ((real-tn (complex-double-reg-real-tn value)))
942       (inst movsd real-tn (make-ea-for-raw-slot object index tmp -8)))
943     (let ((imag-tn (complex-double-reg-imag-tn value)))
944       (inst movsd imag-tn (make-ea-for-raw-slot object index tmp)))))
945
946 (define-vop (raw-instance-set/complex-double)
947   (:translate %raw-instance-set/complex-double)
948   (:policy :fast-safe)
949   (:args (object :scs (descriptor-reg))
950          (index :scs (any-reg))
951          (value :scs (complex-double-reg) :target result))
952   (:arg-types * positive-fixnum complex-double-float)
953   (:temporary (:sc unsigned-reg) tmp)
954   (:results (result :scs (complex-double-reg)))
955   (:result-types complex-double-float)
956   (:generator 5
957     (loadw tmp object 0 instance-pointer-lowtag)
958     (inst shr tmp n-widetag-bits)
959     (inst shl tmp 3)
960     (inst sub tmp index)
961     (let ((value-real (complex-double-reg-real-tn value))
962           (result-real (complex-double-reg-real-tn result)))
963       (inst movsd (make-ea-for-raw-slot object index tmp -8) value-real)
964       (unless (location= value-real result-real)
965         (inst movsd result-real value-real)))
966     (let ((value-imag (complex-double-reg-imag-tn value))
967           (result-imag (complex-double-reg-imag-tn result)))
968       (inst movsd (make-ea-for-raw-slot object index tmp) value-imag)
969       (unless (location= value-imag result-imag)
970         (inst movsd result-imag value-imag)))))
971
972 (define-vop (raw-instance-set-c/complex-double)
973   (:translate %raw-instance-set/complex-double)
974   (:policy :fast-safe)
975   (:args (object :scs (descriptor-reg))
976          (value :scs (complex-double-reg) :target result))
977   (:arg-types * (:constant (load/store-index #.sb!vm:n-word-bytes
978                                              #.instance-pointer-lowtag
979                                              #.instance-slots-offset))
980               complex-double-float)
981   (:info index)
982   (:temporary (:sc unsigned-reg) tmp)
983   (:results (result :scs (complex-double-reg)))
984   (:result-types complex-double-float)
985   (:generator 4
986     (loadw tmp object 0 instance-pointer-lowtag)
987     (inst shr tmp n-widetag-bits)
988     (let ((value-real (complex-double-reg-real-tn value))
989           (result-real (complex-double-reg-real-tn result)))
990       (inst movsd (make-ea-for-raw-slot object index tmp -8) value-real)
991       (unless (location= value-real result-real)
992         (inst movsd result-real value-real)))
993     (let ((value-imag (complex-double-reg-imag-tn value))
994           (result-imag (complex-double-reg-imag-tn result)))
995       (inst movsd (make-ea-for-raw-slot object index tmp) value-imag)
996       (unless (location= value-imag result-imag)
997         (inst movsd result-imag value-imag)))))
998
999 (define-vop (raw-instance-init/complex-double)
1000   (:args (object :scs (descriptor-reg))
1001          (value :scs (complex-double-reg)))
1002   (:arg-types * complex-double-float)
1003   (:info instance-length index)
1004   (:generator 4
1005     (let ((value-real (complex-double-reg-real-tn value)))
1006       (inst movsd (make-ea-for-raw-slot object index instance-length -8) value-real))
1007     (let ((value-imag (complex-double-reg-imag-tn value)))
1008       (inst movsd (make-ea-for-raw-slot object index instance-length) value-imag))))