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