1.0.16.10: function-ify ERROR-CALL and GENERATE-ERROR-CODE on x86
[sbcl.git] / src / compiler / x86 / cell.lisp
1 ;;;; various primitive memory access VOPs for the x86 VM
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!VM")
13 \f
14 ;;;; data object ref/set stuff
15
16 (define-vop (slot)
17   (:args (object :scs (descriptor-reg)))
18   (:info name offset lowtag)
19   (:ignore name)
20   (:results (result :scs (descriptor-reg any-reg)))
21   (:generator 1
22     (loadw result object offset lowtag)))
23
24 (define-vop (set-slot)
25   (:args (object :scs (descriptor-reg))
26          (value :scs (descriptor-reg any-reg immediate)))
27   (:info name offset lowtag)
28   (:ignore name)
29   (:results)
30   (:generator 1
31      (storew (encode-value-if-immediate value) object offset lowtag)))
32
33 (define-vop (compare-and-swap-slot)
34   (:args (object :scs (descriptor-reg) :to :eval)
35          (old :scs (descriptor-reg any-reg) :target eax)
36          (new :scs (descriptor-reg any-reg)))
37   (:temporary (:sc descriptor-reg :offset eax-offset
38                    :from (:argument 1) :to :result :target result)
39               eax)
40   (:info name offset lowtag)
41   (:ignore name)
42   (:results (result :scs (descriptor-reg any-reg)))
43   (:generator 5
44      (move eax old)
45      #!+sb-thread
46      (inst lock)
47      (inst cmpxchg (make-ea :dword :base object
48                             :disp (- (* offset n-word-bytes) lowtag))
49            new)
50      (move result eax)))
51 \f
52 ;;;; symbol hacking VOPs
53
54 (define-vop (%compare-and-swap-symbol-value)
55   (:translate %compare-and-swap-symbol-value)
56   (:args (symbol :scs (descriptor-reg) :to (:result 1))
57          (old :scs (descriptor-reg any-reg) :target eax)
58          (new :scs (descriptor-reg any-reg)))
59   (:temporary (:sc descriptor-reg :offset eax-offset) eax)
60   #!+sb-thread
61   (:temporary (:sc descriptor-reg) tls)
62   (:results (result :scs (descriptor-reg any-reg)))
63   (:policy :fast-safe)
64   (:vop-var vop)
65   (:generator 15
66     ;; This code has to pathological cases: NO-TLS-VALUE-MARKER
67     ;; or UNBOUND-MARKER as NEW: in either case we would end up
68     ;; doing possible damage with CMPXCHG -- so don't do that!
69     (let ((unbound (generate-error-code vop 'unbound-symbol-error symbol))
70           (check (gen-label)))
71       (move eax old)
72       #!+sb-thread
73       (progn
74         (loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
75         ;; Thread-local area, no LOCK needed.
76         (inst fs-segment-prefix)
77         (inst cmpxchg (make-ea :dword :base tls) new)
78         (inst cmp eax no-tls-value-marker-widetag)
79         (inst jmp :ne check)
80         (move eax old)
81         (inst lock))
82       (inst cmpxchg (make-ea :dword :base symbol
83                              :disp (- (* symbol-value-slot n-word-bytes)
84                                       other-pointer-lowtag))
85             new)
86       (emit-label check)
87       (move result eax)
88       (inst cmp result unbound-marker-widetag)
89       (inst jmp :e unbound))))
90
91 ;;; these next two cf the sparc version, by jrd.
92 ;;; FIXME: Deref this ^ reference.
93
94
95 ;;; The compiler likes to be able to directly SET symbols.
96 #!+sb-thread
97 (define-vop (set)
98   (:args (symbol :scs (descriptor-reg))
99          (value :scs (descriptor-reg any-reg)))
100   (:temporary (:sc descriptor-reg) tls)
101   ;;(:policy :fast-safe)
102   (:generator 4
103     (let ((global-val (gen-label))
104           (done (gen-label)))
105       (loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
106       (inst fs-segment-prefix)
107       (inst cmp (make-ea :dword :base tls) no-tls-value-marker-widetag)
108       (inst jmp :z global-val)
109       (inst fs-segment-prefix)
110       (inst mov (make-ea :dword :base tls) value)
111       (inst jmp done)
112       (emit-label global-val)
113       (storew value symbol symbol-value-slot other-pointer-lowtag)
114       (emit-label done))))
115
116 ;; unithreaded it's a lot simpler ...
117 #!-sb-thread
118 (define-vop (set cell-set)
119   (:variant symbol-value-slot other-pointer-lowtag))
120
121 ;;; With Symbol-Value, we check that the value isn't the trap object. So
122 ;;; Symbol-Value of NIL is NIL.
123 #!+sb-thread
124 (define-vop (symbol-value)
125   (:translate symbol-value)
126   (:policy :fast-safe)
127   (:args (object :scs (descriptor-reg) :to (:result 1)))
128   (:results (value :scs (descriptor-reg any-reg)))
129   (:vop-var vop)
130   (:save-p :compute-only)
131   (:generator 9
132     (let* ((check-unbound-label (gen-label))
133            (err-lab (generate-error-code vop 'unbound-symbol-error object))
134            (ret-lab (gen-label)))
135       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
136       (inst fs-segment-prefix)
137       (inst mov value (make-ea :dword :base value))
138       (inst cmp value no-tls-value-marker-widetag)
139       (inst jmp :ne check-unbound-label)
140       (loadw value object symbol-value-slot other-pointer-lowtag)
141       (emit-label check-unbound-label)
142       (inst cmp value unbound-marker-widetag)
143       (inst jmp :e err-lab)
144       (emit-label ret-lab))))
145
146 #!+sb-thread
147 (define-vop (fast-symbol-value symbol-value)
148   ;; KLUDGE: not really fast, in fact, because we're going to have to
149   ;; do a full lookup of the thread-local area anyway.  But half of
150   ;; the meaning of FAST-SYMBOL-VALUE is "do not signal an error if
151   ;; unbound", which is used in the implementation of COPY-SYMBOL.  --
152   ;; CSR, 2003-04-22
153   (:policy :fast)
154   (:translate symbol-value)
155   (:generator 8
156     (let ((ret-lab (gen-label)))
157       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
158       (inst fs-segment-prefix)
159       (inst mov value (make-ea :dword :base value))
160       (inst cmp value no-tls-value-marker-widetag)
161       (inst jmp :ne ret-lab)
162       (loadw value object symbol-value-slot other-pointer-lowtag)
163       (emit-label ret-lab))))
164
165 #!-sb-thread
166 (define-vop (symbol-value)
167   (:translate symbol-value)
168   (:policy :fast-safe)
169   (:args (object :scs (descriptor-reg) :to (:result 1)))
170   (:results (value :scs (descriptor-reg any-reg)))
171   (:vop-var vop)
172   (:save-p :compute-only)
173   (:generator 9
174     (let ((err-lab (generate-error-code vop 'unbound-symbol-error object)))
175       (loadw value object symbol-value-slot other-pointer-lowtag)
176       (inst cmp value unbound-marker-widetag)
177       (inst jmp :e err-lab))))
178
179 #!-sb-thread
180 (define-vop (fast-symbol-value cell-ref)
181   (:variant symbol-value-slot other-pointer-lowtag)
182   (:policy :fast)
183   (:translate symbol-value))
184
185 (defknown locked-symbol-global-value-add (symbol fixnum) fixnum ())
186
187 (define-vop (locked-symbol-global-value-add)
188     (:args (object :scs (descriptor-reg) :to :result)
189            (value :scs (any-reg) :target result))
190   (:arg-types * tagged-num)
191   (:results (result :scs (any-reg) :from (:argument 1)))
192   (:policy :fast)
193   (:translate locked-symbol-global-value-add)
194   (:result-types tagged-num)
195   (:policy :fast-safe)
196   (:generator 4
197     (move result value)
198     (inst lock)
199     (inst add (make-ea-for-object-slot object symbol-value-slot
200                                        other-pointer-lowtag)
201           value)))
202
203 #!+sb-thread
204 (define-vop (boundp)
205   (:translate boundp)
206   (:policy :fast-safe)
207   (:args (object :scs (descriptor-reg)))
208   (:conditional)
209   (:info target not-p)
210   (:temporary (:sc descriptor-reg #+nil(:from (:argument 0))) value)
211   (:generator 9
212     (let ((check-unbound-label (gen-label)))
213       (loadw value object symbol-tls-index-slot other-pointer-lowtag)
214       (inst fs-segment-prefix)
215       (inst mov value (make-ea :dword :base value))
216       (inst cmp value no-tls-value-marker-widetag)
217       (inst jmp :ne check-unbound-label)
218       (loadw value object symbol-value-slot other-pointer-lowtag)
219       (emit-label check-unbound-label)
220       (inst cmp value unbound-marker-widetag)
221       (inst jmp (if not-p :e :ne) target))))
222
223 #!-sb-thread
224 (define-vop (boundp)
225   (:translate boundp)
226   (:policy :fast-safe)
227   (:args (object :scs (descriptor-reg)))
228   (:conditional)
229   (:info target not-p)
230   (:generator 9
231     (inst cmp (make-ea-for-object-slot object symbol-value-slot
232                                        other-pointer-lowtag)
233           unbound-marker-widetag)
234     (inst jmp (if not-p :e :ne) target)))
235
236
237 (define-vop (symbol-hash)
238   (:policy :fast-safe)
239   (:translate symbol-hash)
240   (:args (symbol :scs (descriptor-reg)))
241   (:results (res :scs (any-reg)))
242   (:result-types positive-fixnum)
243   (:generator 2
244     ;; The symbol-hash slot of NIL holds NIL because it is also the
245     ;; cdr slot, so we have to strip off the two low bits to make sure
246     ;; it is a fixnum.  The lowtag selection magic that is required to
247     ;; ensure this is explained in the comment in objdef.lisp
248     (loadw res symbol symbol-hash-slot other-pointer-lowtag)
249     (inst and res (lognot #b11))))
250 \f
251 ;;;; fdefinition (FDEFN) objects
252
253 (define-vop (fdefn-fun cell-ref)        ; /pfw - alpha
254   (:variant fdefn-fun-slot other-pointer-lowtag))
255
256 (define-vop (safe-fdefn-fun)
257   (:args (object :scs (descriptor-reg) :to (:result 1)))
258   (:results (value :scs (descriptor-reg any-reg)))
259   (:vop-var vop)
260   (:save-p :compute-only)
261   (:generator 10
262     (loadw value object fdefn-fun-slot other-pointer-lowtag)
263     (inst cmp value nil-value)
264     (let ((err-lab (generate-error-code vop 'undefined-fun-error object)))
265       (inst jmp :e err-lab))))
266
267 (define-vop (set-fdefn-fun)
268   (:policy :fast-safe)
269   (:translate (setf fdefn-fun))
270   (:args (function :scs (descriptor-reg) :target result)
271          (fdefn :scs (descriptor-reg)))
272   (:temporary (:sc unsigned-reg) raw)
273   (:temporary (:sc byte-reg) type)
274   (:results (result :scs (descriptor-reg)))
275   (:generator 38
276     (load-type type function (- fun-pointer-lowtag))
277     (inst lea raw
278           (make-ea-for-object-slot function simple-fun-code-offset
279                                    fun-pointer-lowtag))
280     (inst cmp type simple-fun-header-widetag)
281     (inst jmp :e normal-fn)
282     (inst lea raw (make-fixup "closure_tramp" :foreign))
283     NORMAL-FN
284     (storew function fdefn fdefn-fun-slot other-pointer-lowtag)
285     (storew raw fdefn fdefn-raw-addr-slot other-pointer-lowtag)
286     (move result function)))
287
288 (define-vop (fdefn-makunbound)
289   (:policy :fast-safe)
290   (:translate fdefn-makunbound)
291   (:args (fdefn :scs (descriptor-reg) :target result))
292   (:results (result :scs (descriptor-reg)))
293   (:generator 38
294     (storew nil-value fdefn fdefn-fun-slot other-pointer-lowtag)
295     (storew (make-fixup "undefined_tramp" :foreign)
296             fdefn fdefn-raw-addr-slot other-pointer-lowtag)
297     (move result fdefn)))
298 \f
299 ;;;; binding and unbinding
300
301 ;;; BIND -- Establish VAL as a binding for SYMBOL. Save the old value and
302 ;;; the symbol on the binding stack and stuff the new value into the
303 ;;; symbol.
304
305 ;;; FIXME: Split into DYNBIND and BIND: DYNBIND needs to ensure
306 ;;; TLS-INDEX, whereas BIND should assume it is already in place. Make
307 ;;; LET &co compile into BIND, and PROGV into DYNBIND, plus ensure
308 ;;; TLS-INDEX at compile-time, and make loader and dumper preserve
309 ;;; the existence of a TLS-INDEX.
310 #!+sb-thread
311 (define-vop (bind)
312   (:args (val :scs (any-reg descriptor-reg))
313          (symbol :scs (descriptor-reg)))
314   (:temporary (:sc unsigned-reg) tls-index bsp)
315   (:generator 10
316     (let ((tls-index-valid (gen-label)))
317       (load-binding-stack-pointer bsp)
318       (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
319       (inst add bsp (* binding-size n-word-bytes))
320       (store-binding-stack-pointer bsp)
321       (inst or tls-index tls-index)
322       (inst jmp :ne tls-index-valid)
323       (inst mov tls-index symbol)
324       (inst call (make-fixup
325                   (ecase (tn-offset tls-index)
326                     (#.eax-offset 'alloc-tls-index-in-eax)
327                     (#.ebx-offset 'alloc-tls-index-in-ebx)
328                     (#.ecx-offset 'alloc-tls-index-in-ecx)
329                     (#.edx-offset 'alloc-tls-index-in-edx)
330                     (#.edi-offset 'alloc-tls-index-in-edi)
331                     (#.esi-offset 'alloc-tls-index-in-esi))
332                   :assembly-routine))
333       (emit-label tls-index-valid)
334       (inst fs-segment-prefix)
335       (inst push (make-ea :dword :base tls-index))
336       (popw bsp (- binding-value-slot binding-size))
337       (storew symbol bsp (- binding-symbol-slot binding-size))
338       (inst fs-segment-prefix)
339       (inst mov (make-ea :dword :base tls-index) val))))
340
341 #!-sb-thread
342 (define-vop (bind)
343   (:args (val :scs (any-reg descriptor-reg))
344          (symbol :scs (descriptor-reg)))
345   (:temporary (:sc unsigned-reg) temp bsp)
346   (:generator 5
347     (load-symbol-value bsp *binding-stack-pointer*)
348     (loadw temp symbol symbol-value-slot other-pointer-lowtag)
349     (inst add bsp (* binding-size n-word-bytes))
350     (store-symbol-value bsp *binding-stack-pointer*)
351     (storew temp bsp (- binding-value-slot binding-size))
352     (storew symbol bsp (- binding-symbol-slot binding-size))
353     (storew val symbol symbol-value-slot other-pointer-lowtag)))
354
355 #!+sb-thread
356 (define-vop (unbind)
357   (:temporary (:sc unsigned-reg) temp bsp tls-index)
358   (:generator 0
359     (load-binding-stack-pointer bsp)
360     ;; Load SYMBOL from stack, and get the TLS-INDEX.
361     (loadw temp bsp (- binding-symbol-slot binding-size))
362     (loadw tls-index temp symbol-tls-index-slot other-pointer-lowtag)
363     ;; Load VALUE from stack, then restore it to the TLS area.
364     (loadw temp bsp (- binding-value-slot binding-size))
365     (inst fs-segment-prefix)
366     (inst mov (make-ea :dword :base tls-index) temp)
367     ;; Zero out the stack.
368     (storew 0 bsp (- binding-symbol-slot binding-size))
369     (storew 0 bsp (- binding-value-slot binding-size))
370     (inst sub bsp (* binding-size n-word-bytes))
371     (store-binding-stack-pointer bsp)))
372
373 #!-sb-thread
374 (define-vop (unbind)
375   (:temporary (:sc unsigned-reg) symbol value bsp)
376   (:generator 0
377     (load-symbol-value bsp *binding-stack-pointer*)
378     (loadw symbol bsp (- binding-symbol-slot binding-size))
379     (loadw value bsp (- binding-value-slot binding-size))
380     (storew value symbol symbol-value-slot other-pointer-lowtag)
381     (storew 0 bsp (- binding-symbol-slot binding-size))
382     (storew 0 bsp (- binding-value-slot binding-size))
383     (inst sub bsp (* binding-size n-word-bytes))
384     (store-symbol-value bsp *binding-stack-pointer*)))
385
386
387 (define-vop (unbind-to-here)
388   (:args (where :scs (descriptor-reg any-reg)))
389   (:temporary (:sc unsigned-reg) symbol value bsp #!+sb-thread tls-index)
390   (:generator 0
391     (load-binding-stack-pointer bsp)
392     (inst cmp where bsp)
393     (inst jmp :e done)
394
395     LOOP
396     (loadw symbol bsp (- binding-symbol-slot binding-size))
397     (inst or symbol symbol)
398     (inst jmp :z skip)
399     ;; Bind stack debug sentinels have the unbound marker in the symbol slot
400     (inst cmp symbol unbound-marker-widetag)
401     (inst jmp :eq skip)
402     (loadw value bsp (- binding-value-slot binding-size))
403     #!-sb-thread (storew value symbol symbol-value-slot other-pointer-lowtag)
404
405     #!+sb-thread (loadw
406                   tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
407     #!+sb-thread (inst fs-segment-prefix)
408     #!+sb-thread (inst mov (make-ea :dword :base tls-index) value)
409     (storew 0 bsp (- binding-symbol-slot binding-size))
410
411     SKIP
412     (storew 0 bsp (- binding-value-slot binding-size))
413     (inst sub bsp (* binding-size n-word-bytes))
414     (inst cmp where bsp)
415     (inst jmp :ne loop)
416     (store-binding-stack-pointer bsp)
417
418     DONE))
419
420 (define-vop (bind-sentinel)
421   (:temporary (:sc unsigned-reg) bsp)
422   (:generator 1
423      (load-binding-stack-pointer bsp)
424      (inst add bsp (* binding-size n-word-bytes))
425      (storew unbound-marker-widetag bsp (- binding-symbol-slot binding-size))
426      (storew ebp-tn bsp (- binding-value-slot binding-size))
427      (store-binding-stack-pointer bsp)))
428
429 (define-vop (unbind-sentinel)
430   (:temporary (:sc unsigned-reg) bsp)
431   (:generator 1
432      (load-binding-stack-pointer bsp)
433      (storew 0 bsp (- binding-value-slot binding-size))
434      (storew 0 bsp (- binding-symbol-slot binding-size))
435      (inst sub bsp (* binding-size n-word-bytes))
436      (store-binding-stack-pointer bsp)))
437 \f
438
439 \f
440 ;;;; closure indexing
441
442 (define-full-reffer closure-index-ref *
443   closure-info-offset fun-pointer-lowtag
444   (any-reg descriptor-reg) * %closure-index-ref)
445
446 (define-full-setter set-funcallable-instance-info *
447   funcallable-instance-info-offset fun-pointer-lowtag
448   (any-reg descriptor-reg) * %set-funcallable-instance-info)
449
450 (define-full-reffer funcallable-instance-info *
451   funcallable-instance-info-offset fun-pointer-lowtag
452   (descriptor-reg any-reg) * %funcallable-instance-info)
453
454 (define-vop (closure-ref slot-ref)
455   (:variant closure-info-offset fun-pointer-lowtag))
456
457 (define-vop (closure-init slot-set)
458   (:variant closure-info-offset fun-pointer-lowtag))
459 \f
460 ;;;; value cell hackery
461
462 (define-vop (value-cell-ref cell-ref)
463   (:variant value-cell-value-slot other-pointer-lowtag))
464
465 (define-vop (value-cell-set cell-set)
466   (:variant value-cell-value-slot other-pointer-lowtag))
467 \f
468 ;;;; structure hackery
469
470 (define-vop (instance-length)
471   (:policy :fast-safe)
472   (:translate %instance-length)
473   (:args (struct :scs (descriptor-reg)))
474   (:results (res :scs (unsigned-reg)))
475   (:result-types positive-fixnum)
476   (:generator 4
477     (loadw res struct 0 instance-pointer-lowtag)
478     (inst shr res n-widetag-bits)))
479
480 (define-full-reffer instance-index-ref *
481   instance-slots-offset instance-pointer-lowtag
482   (any-reg descriptor-reg) *
483   %instance-ref)
484
485 (define-full-setter instance-index-set *
486   instance-slots-offset instance-pointer-lowtag
487   (any-reg descriptor-reg) *
488   %instance-set)
489
490 (define-full-compare-and-swap %compare-and-swap-instance-ref instance
491   instance-slots-offset instance-pointer-lowtag
492   (any-reg descriptor-reg) *
493   %compare-and-swap-instance-ref)
494 \f
495 ;;;; code object frobbing
496
497 (define-full-reffer code-header-ref * 0 other-pointer-lowtag
498   (any-reg descriptor-reg) * code-header-ref)
499
500 (define-full-setter code-header-set * 0 other-pointer-lowtag
501   (any-reg descriptor-reg) * code-header-set)
502 \f
503 ;;;; raw instance slot accessors
504
505 (defun make-ea-for-raw-slot (object index instance-length n-words)
506   (sc-case index
507     (any-reg (make-ea :dword
508                       :base object
509                       :index instance-length
510                       :disp (- (* (- instance-slots-offset n-words)
511                                   n-word-bytes)
512                                instance-pointer-lowtag)))
513     (immediate (make-ea :dword :base object
514                         :index instance-length
515                         :scale 4
516                         :disp (- (* (- instance-slots-offset n-words)
517                                     n-word-bytes)
518                                  instance-pointer-lowtag
519                                  (fixnumize (tn-value index)))))))
520
521 (define-vop (raw-instance-ref/word)
522   (:translate %raw-instance-ref/word)
523   (:policy :fast-safe)
524   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
525   (:arg-types * tagged-num)
526   (:temporary (:sc unsigned-reg) tmp)
527   (:results (value :scs (unsigned-reg)))
528   (:result-types unsigned-num)
529   (:generator 5
530     (loadw tmp object 0 instance-pointer-lowtag)
531     (inst shr tmp n-widetag-bits)
532     (when (sc-is index any-reg)
533       (inst shl tmp 2)
534       (inst sub tmp index))
535     (inst mov value (make-ea-for-raw-slot object index tmp 1))))
536
537 (define-vop (raw-instance-set/word)
538   (:translate %raw-instance-set/word)
539   (:policy :fast-safe)
540   (:args (object :scs (descriptor-reg))
541          (index :scs (any-reg immediate))
542          (value :scs (unsigned-reg) :target result))
543   (:arg-types * tagged-num unsigned-num)
544   (:temporary (:sc unsigned-reg) tmp)
545   (:results (result :scs (unsigned-reg)))
546   (:result-types unsigned-num)
547   (:generator 5
548     (loadw tmp object 0 instance-pointer-lowtag)
549     (inst shr tmp n-widetag-bits)
550     (when (sc-is index any-reg)
551       (inst shl tmp 2)
552       (inst sub tmp index))
553     (inst mov (make-ea-for-raw-slot object index tmp 1) value)
554     (move result value)))
555
556 (define-vop (raw-instance-ref/single)
557   (:translate %raw-instance-ref/single)
558   (:policy :fast-safe)
559   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
560   (:arg-types * tagged-num)
561   (:temporary (:sc unsigned-reg) tmp)
562   (:results (value :scs (single-reg)))
563   (:result-types single-float)
564   (:generator 5
565     (loadw tmp object 0 instance-pointer-lowtag)
566     (inst shr tmp n-widetag-bits)
567     (when (sc-is index any-reg)
568       (inst shl tmp 2)
569       (inst sub tmp index))
570     (with-empty-tn@fp-top(value)
571       (inst fld (make-ea-for-raw-slot object index tmp 1)))))
572
573 (define-vop (raw-instance-set/single)
574   (:translate %raw-instance-set/single)
575   (:policy :fast-safe)
576   (:args (object :scs (descriptor-reg))
577          (index :scs (any-reg immediate))
578          (value :scs (single-reg) :target result))
579   (:arg-types * tagged-num single-float)
580   (:temporary (:sc unsigned-reg) tmp)
581   (:results (result :scs (single-reg)))
582   (:result-types single-float)
583   (:generator 5
584     (loadw tmp object 0 instance-pointer-lowtag)
585     (inst shr tmp n-widetag-bits)
586     (when (sc-is index any-reg)
587       (inst shl tmp 2)
588       (inst sub tmp index))
589     (unless (zerop (tn-offset value))
590       (inst fxch value))
591     (inst fst (make-ea-for-raw-slot object index tmp 1))
592     (cond
593       ((zerop (tn-offset value))
594         (unless (zerop (tn-offset result))
595           (inst fst result)))
596       ((zerop (tn-offset result))
597         (inst fst value))
598       (t
599         (unless (location= value result)
600           (inst fst result))
601         (inst fxch value)))))
602
603 (define-vop (raw-instance-ref/double)
604   (:translate %raw-instance-ref/double)
605   (:policy :fast-safe)
606   (:args (object :scs (descriptor-reg)) (index :scs (any-reg immediate)))
607   (:arg-types * tagged-num)
608   (:temporary (:sc unsigned-reg) tmp)
609   (:results (value :scs (double-reg)))
610   (:result-types double-float)
611   (:generator 5
612     (loadw tmp object 0 instance-pointer-lowtag)
613     (inst shr tmp n-widetag-bits)
614     (when (sc-is index any-reg)
615       (inst shl tmp 2)
616       (inst sub tmp index))
617     (with-empty-tn@fp-top(value)
618       (inst fldd (make-ea-for-raw-slot object index tmp 2)))))
619
620 (define-vop (raw-instance-set/double)
621   (:translate %raw-instance-set/double)
622   (:policy :fast-safe)
623   (:args (object :scs (descriptor-reg))
624          (index :scs (any-reg immediate))
625          (value :scs (double-reg) :target result))
626   (:arg-types * tagged-num double-float)
627   (:temporary (:sc unsigned-reg) tmp)
628   (:results (result :scs (double-reg)))
629   (:result-types double-float)
630   (:generator 5
631     (loadw tmp object 0 instance-pointer-lowtag)
632     (inst shr tmp n-widetag-bits)
633     (when (sc-is index any-reg)
634       (inst shl tmp 2)
635       (inst sub tmp index))
636     (unless (zerop (tn-offset value))
637       (inst fxch value))
638     (inst fstd (make-ea-for-raw-slot object index tmp 2))
639     (cond
640       ((zerop (tn-offset value))
641         (unless (zerop (tn-offset result))
642           (inst fstd result)))
643       ((zerop (tn-offset result))
644         (inst fstd value))
645       (t
646         (unless (location= value result)
647           (inst fstd result))
648         (inst fxch value)))))
649
650 (define-vop (raw-instance-ref/complex-single)
651   (:translate %raw-instance-ref/complex-single)
652   (:policy :fast-safe)
653   (:args (object :scs (descriptor-reg))
654          (index :scs (any-reg immediate)))
655   (:arg-types * positive-fixnum)
656   (:temporary (:sc unsigned-reg) tmp)
657   (:results (value :scs (complex-single-reg)))
658   (:result-types complex-single-float)
659   (:generator 5
660     (loadw tmp object 0 instance-pointer-lowtag)
661     (inst shr tmp n-widetag-bits)
662     (when (sc-is index any-reg)
663       (inst shl tmp 2)
664       (inst sub tmp index))
665     (let ((real-tn (complex-single-reg-real-tn value)))
666       (with-empty-tn@fp-top (real-tn)
667         (inst fld (make-ea-for-raw-slot object index tmp 2))))
668     (let ((imag-tn (complex-single-reg-imag-tn value)))
669       (with-empty-tn@fp-top (imag-tn)
670         (inst fld (make-ea-for-raw-slot object index tmp 1))))))
671
672 (define-vop (raw-instance-set/complex-single)
673   (:translate %raw-instance-set/complex-single)
674   (:policy :fast-safe)
675   (:args (object :scs (descriptor-reg))
676          (index :scs (any-reg immediate))
677          (value :scs (complex-single-reg) :target result))
678   (:arg-types * positive-fixnum complex-single-float)
679   (:temporary (:sc unsigned-reg) tmp)
680   (:results (result :scs (complex-single-reg)))
681   (:result-types complex-single-float)
682   (:generator 5
683     (loadw tmp object 0 instance-pointer-lowtag)
684     (inst shr tmp n-widetag-bits)
685     (when (sc-is index any-reg)
686       (inst shl tmp 2)
687       (inst sub tmp index))
688     (let ((value-real (complex-single-reg-real-tn value))
689           (result-real (complex-single-reg-real-tn result)))
690       (cond ((zerop (tn-offset value-real))
691              ;; Value is in ST0.
692              (inst fst (make-ea-for-raw-slot object index tmp 2))
693              (unless (zerop (tn-offset result-real))
694                ;; Value is in ST0 but not result.
695                (inst fst result-real)))
696             (t
697              ;; Value is not in ST0.
698              (inst fxch value-real)
699              (inst fst (make-ea-for-raw-slot object index tmp 2))
700              (cond ((zerop (tn-offset result-real))
701                     ;; The result is in ST0.
702                     (inst fst value-real))
703                    (t
704                     ;; Neither value or result are in ST0
705                     (unless (location= value-real result-real)
706                       (inst fst result-real))
707                     (inst fxch value-real))))))
708     (let ((value-imag (complex-single-reg-imag-tn value))
709           (result-imag (complex-single-reg-imag-tn result)))
710       (inst fxch value-imag)
711       (inst fst (make-ea-for-raw-slot object index tmp 1))
712       (unless (location= value-imag result-imag)
713         (inst fst result-imag))
714       (inst fxch value-imag))))
715
716 (define-vop (raw-instance-ref/complex-double)
717   (:translate %raw-instance-ref/complex-double)
718   (:policy :fast-safe)
719   (:args (object :scs (descriptor-reg))
720          (index :scs (any-reg immediate)))
721   (:arg-types * positive-fixnum)
722   (:temporary (:sc unsigned-reg) tmp)
723   (:results (value :scs (complex-double-reg)))
724   (:result-types complex-double-float)
725   (:generator 7
726     (loadw tmp object 0 instance-pointer-lowtag)
727     (inst shr tmp n-widetag-bits)
728     (when (sc-is index any-reg)
729       (inst shl tmp 2)
730       (inst sub tmp index))
731     (let ((real-tn (complex-double-reg-real-tn value)))
732       (with-empty-tn@fp-top (real-tn)
733         (inst fldd (make-ea-for-raw-slot object index tmp 4))))
734     (let ((imag-tn (complex-double-reg-imag-tn value)))
735       (with-empty-tn@fp-top (imag-tn)
736         (inst fldd (make-ea-for-raw-slot object index tmp 2))))))
737
738 (define-vop (raw-instance-set/complex-double)
739   (:translate %raw-instance-set/complex-double)
740   (:policy :fast-safe)
741   (:args (object :scs (descriptor-reg))
742          (index :scs (any-reg immediate))
743          (value :scs (complex-double-reg) :target result))
744   (:arg-types * positive-fixnum complex-double-float)
745   (:temporary (:sc unsigned-reg) tmp)
746   (:results (result :scs (complex-double-reg)))
747   (:result-types complex-double-float)
748   (:generator 20
749     (loadw tmp object 0 instance-pointer-lowtag)
750     (inst shr tmp n-widetag-bits)
751     (when (sc-is index any-reg)
752       (inst shl tmp 2)
753       (inst sub tmp index))
754     (let ((value-real (complex-double-reg-real-tn value))
755           (result-real (complex-double-reg-real-tn result)))
756       (cond ((zerop (tn-offset value-real))
757              ;; Value is in ST0.
758              (inst fstd (make-ea-for-raw-slot object index tmp 4))
759              (unless (zerop (tn-offset result-real))
760                ;; Value is in ST0 but not result.
761                (inst fstd result-real)))
762             (t
763              ;; Value is not in ST0.
764              (inst fxch value-real)
765              (inst fstd (make-ea-for-raw-slot object index tmp 4))
766              (cond ((zerop (tn-offset result-real))
767                     ;; The result is in ST0.
768                     (inst fstd value-real))
769                    (t
770                     ;; Neither value or result are in ST0
771                     (unless (location= value-real result-real)
772                       (inst fstd result-real))
773                     (inst fxch value-real))))))
774     (let ((value-imag (complex-double-reg-imag-tn value))
775           (result-imag (complex-double-reg-imag-tn result)))
776       (inst fxch value-imag)
777       (inst fstd (make-ea-for-raw-slot object index tmp 2))
778       (unless (location= value-imag result-imag)
779         (inst fstd result-imag))
780       (inst fxch value-imag))))