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