Pass through DX-P to INIT-SLOT vop
[sbcl.git] / src / compiler / arm / cell.lisp
blobf22aa9a48accbcaa660c0df25162cb830f4d9c3f
1 ;;;; the VM definition of various primitive memory access VOPs for the
2 ;;;; ARM
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB!VM")
15 ;;;; Data object ref/set stuff.
17 (define-vop (slot)
18 (:args (object :scs (descriptor-reg)))
19 (:info name offset lowtag)
20 (:ignore name)
21 (:results (result :scs (descriptor-reg any-reg)))
22 (:generator 1
23 (loadw result object offset lowtag)))
25 (define-vop (set-slot)
26 (:args (object :scs (descriptor-reg))
27 (value :scs (descriptor-reg any-reg)))
28 (:info name offset lowtag)
29 (:ignore name)
30 (:results)
31 (:generator 1
32 (storew value object offset lowtag)))
34 (define-vop (init-slot set-slot)
35 (:info name dx-p offset lowtag)
36 (:ignore name dx-p))
38 ;;;; Symbol hacking VOPs:
40 ;;; The compiler likes to be able to directly SET symbols.
41 ;;;
42 (define-vop (set cell-set)
43 (:variant symbol-value-slot other-pointer-lowtag))
45 ;;; Do a cell ref with an error check for being unbound.
46 ;;;
47 (define-vop (checked-cell-ref)
48 (:args (object :scs (descriptor-reg) :target obj-temp))
49 (:results (value :scs (descriptor-reg any-reg)))
50 (:policy :fast-safe)
51 (:vop-var vop)
52 (:save-p :compute-only)
53 (:temporary (:scs (descriptor-reg) :from (:argument 0)) obj-temp))
55 ;;; With Symbol-Value, we check that the value isn't the trap object. So
56 ;;; Symbol-Value of NIL is NIL.
57 ;;;
58 (define-vop (symbol-value checked-cell-ref)
59 (:translate symeval)
60 (:generator 9
61 (move obj-temp object)
62 (loadw value obj-temp symbol-value-slot other-pointer-lowtag)
63 (let ((err-lab (generate-error-code vop 'unbound-symbol-error obj-temp)))
64 (inst cmp value unbound-marker-widetag)
65 (inst b :eq err-lab))))
67 ;;; Like CHECKED-CELL-REF, only we are a predicate to see if the cell is bound.
68 (define-vop (boundp-frob)
69 (:args (object :scs (descriptor-reg)))
70 (:conditional)
71 (:info target not-p)
72 (:policy :fast-safe)
73 (:temporary (:scs (descriptor-reg)) value))
75 (define-vop (boundp boundp-frob)
76 (:translate boundp)
77 (:generator 9
78 (loadw value object symbol-value-slot other-pointer-lowtag)
79 (inst cmp value unbound-marker-widetag)
80 (inst b (if not-p :eq :ne) target)))
82 (define-vop (fast-symbol-value cell-ref)
83 (:variant symbol-value-slot other-pointer-lowtag)
84 (:policy :fast)
85 (:translate symeval))
87 (define-vop (symbol-hash)
88 (:policy :fast-safe)
89 (:translate symbol-hash)
90 (:args (symbol :scs (descriptor-reg)))
91 (:temporary (:scs (non-descriptor-reg)) temp)
92 (:results (res :scs (any-reg)))
93 (:result-types positive-fixnum)
94 (:generator 2
95 ;; The symbol-hash slot of NIL holds NIL because it is also the
96 ;; cdr slot, so we have to strip off the two low bits to make sure
97 ;; it is a fixnum. The lowtag selection magic that is required to
98 ;; ensure this is explained in the comment in objdef.lisp
99 (loadw temp symbol symbol-hash-slot other-pointer-lowtag)
100 (inst bic res temp fixnum-tag-mask)))
102 ;;; On unithreaded builds these are just copies of the non-global versions.
103 (define-vop (%set-symbol-global-value set))
104 (define-vop (symbol-global-value symbol-value)
105 (:translate sym-global-val))
106 (define-vop (fast-symbol-global-value fast-symbol-value)
107 (:translate sym-global-val))
109 ;;;; Fdefinition (fdefn) objects.
111 (define-vop (fdefn-fun cell-ref)
112 (:variant fdefn-fun-slot other-pointer-lowtag))
114 (define-vop (safe-fdefn-fun)
115 (:translate safe-fdefn-fun)
116 (:policy :fast-safe)
117 (:args (object :scs (descriptor-reg) :target obj-temp))
118 (:results (value :scs (descriptor-reg any-reg)))
119 (:vop-var vop)
120 (:save-p :compute-only)
121 (:temporary (:scs (descriptor-reg) :from (:argument 0)) obj-temp)
122 (:generator 10
123 (move obj-temp object)
124 (loadw value obj-temp fdefn-fun-slot other-pointer-lowtag)
125 (inst cmp value null-tn)
126 (let ((err-lab (generate-error-code vop 'undefined-fun-error obj-temp)))
127 (inst b :eq err-lab))))
129 (define-vop (set-fdefn-fun)
130 (:policy :fast-safe)
131 (:translate (setf fdefn-fun))
132 (:args (function :scs (descriptor-reg) :target result)
133 (fdefn :scs (descriptor-reg)))
134 (:temporary (:scs (interior-reg)) lip)
135 (:temporary (:scs (non-descriptor-reg)) type)
136 (:results (result :scs (descriptor-reg)))
137 (:generator 38
138 (let ((closure-tramp-fixup (gen-label)))
139 (assemble (*elsewhere*)
140 (emit-label closure-tramp-fixup)
141 (inst word (make-fixup 'closure-tramp :assembly-routine)))
142 (load-type type function (- fun-pointer-lowtag))
143 (inst cmp type simple-fun-widetag)
144 (inst mov :eq lip function)
145 (inst load-from-label :ne lip lip closure-tramp-fixup)
146 (storew lip fdefn fdefn-raw-addr-slot other-pointer-lowtag)
147 (storew function fdefn fdefn-fun-slot other-pointer-lowtag)
148 (move result function))))
150 (define-vop (fdefn-makunbound)
151 (:policy :fast-safe)
152 (:translate fdefn-makunbound)
153 (:args (fdefn :scs (descriptor-reg) :target result))
154 (:temporary (:scs (non-descriptor-reg)) temp)
155 (:temporary (:scs (interior-reg)) lip)
156 (:results (result :scs (descriptor-reg)))
157 (:generator 38
158 (let ((undefined-tramp-fixup (gen-label)))
159 (assemble (*elsewhere*)
160 (emit-label undefined-tramp-fixup)
161 (inst word (make-fixup 'undefined-tramp :assembly-routine)))
162 (storew null-tn fdefn fdefn-fun-slot other-pointer-lowtag)
163 (inst load-from-label temp lip undefined-tramp-fixup)
164 (storew temp fdefn fdefn-raw-addr-slot other-pointer-lowtag)
165 (move result fdefn))))
169 ;;;; Binding and Unbinding.
171 ;;; BIND -- Establish VAL as a binding for SYMBOL. Save the old value and
172 ;;; the symbol on the binding stack and stuff the new value into the
173 ;;; symbol.
175 (define-vop (dynbind)
176 (:args (val :scs (any-reg descriptor-reg))
177 (symbol :scs (descriptor-reg)))
178 (:temporary (:scs (descriptor-reg)) value-temp)
179 (:temporary (:scs (any-reg)) bsp-temp)
180 (:generator 5
181 (loadw value-temp symbol symbol-value-slot other-pointer-lowtag)
182 (load-symbol-value bsp-temp *binding-stack-pointer*)
183 (inst add bsp-temp bsp-temp (* 2 n-word-bytes))
184 (store-symbol-value bsp-temp *binding-stack-pointer*)
185 (storew value-temp bsp-temp (- binding-value-slot binding-size))
186 (storew symbol bsp-temp (- binding-symbol-slot binding-size))
187 (storew val symbol symbol-value-slot other-pointer-lowtag)))
189 (define-vop (unbind)
190 (:temporary (:scs (descriptor-reg)) symbol value)
191 (:temporary (:scs (any-reg)) bsp-temp)
192 (:temporary (:scs (any-reg)) zero-temp)
193 (:generator 0
194 (inst mov zero-temp 0)
195 (load-symbol-value bsp-temp *binding-stack-pointer*)
196 (loadw symbol bsp-temp (- binding-symbol-slot binding-size))
197 (loadw value bsp-temp (- binding-value-slot binding-size))
198 (storew value symbol symbol-value-slot other-pointer-lowtag)
199 (storew zero-temp bsp-temp (- binding-symbol-slot binding-size))
200 (storew zero-temp bsp-temp (- binding-value-slot binding-size))
201 (inst sub bsp-temp bsp-temp (* 2 n-word-bytes))
202 (store-symbol-value bsp-temp *binding-stack-pointer*)))
204 (define-vop (unbind-to-here)
205 (:args (arg :scs (descriptor-reg any-reg) :target where))
206 (:temporary (:scs (any-reg) :from (:argument 0)) where)
207 (:temporary (:scs (descriptor-reg)) symbol value)
208 (:temporary (:scs (any-reg)) bsp-temp zero-temp)
209 (:generator 0
210 (load-symbol-value bsp-temp *binding-stack-pointer*)
211 (inst mov zero-temp 0)
212 (move where arg)
213 (inst cmp where bsp-temp)
214 (inst b :eq DONE)
216 LOOP
217 (loadw symbol bsp-temp (- binding-symbol-slot binding-size))
218 (inst cmp symbol 0)
219 (loadw value bsp-temp (- binding-value-slot binding-size) 0 :ne)
220 (storew value symbol symbol-value-slot other-pointer-lowtag :ne)
221 (storew zero-temp bsp-temp (- binding-symbol-slot binding-size) 0 :ne)
223 (storew zero-temp bsp-temp (- binding-value-slot binding-size))
224 (inst sub bsp-temp bsp-temp (* 2 n-word-bytes))
225 (inst cmp where bsp-temp)
226 (inst b :ne LOOP)
228 DONE
229 (store-symbol-value bsp-temp *binding-stack-pointer*)))
231 ;;;; Closure indexing.
233 (define-full-reffer closure-index-ref *
234 closure-info-offset fun-pointer-lowtag
235 (descriptor-reg any-reg) * %closure-index-ref)
237 (define-full-setter set-funcallable-instance-info *
238 funcallable-instance-info-offset fun-pointer-lowtag
239 (descriptor-reg any-reg null) * %set-funcallable-instance-info)
241 (define-full-reffer funcallable-instance-info *
242 funcallable-instance-info-offset fun-pointer-lowtag
243 (descriptor-reg any-reg) * %funcallable-instance-info)
245 (define-vop (closure-ref slot-ref)
246 (:variant closure-info-offset fun-pointer-lowtag))
248 (define-vop (closure-init slot-set)
249 (:variant closure-info-offset fun-pointer-lowtag))
251 (define-vop (closure-init-from-fp)
252 (:args (object :scs (descriptor-reg)))
253 (:info offset)
254 (:generator 4
255 (storew cfp-tn object (+ closure-info-offset offset) fun-pointer-lowtag)))
257 ;;;; Value Cell hackery.
259 (define-vop (value-cell-ref cell-ref)
260 (:variant value-cell-value-slot other-pointer-lowtag))
262 (define-vop (value-cell-set cell-set)
263 (:variant value-cell-value-slot other-pointer-lowtag))
265 ;;;; Instance hackery:
267 (define-vop (instance-length)
268 (:policy :fast-safe)
269 (:translate %instance-length)
270 (:args (struct :scs (descriptor-reg)))
271 (:temporary (:scs (non-descriptor-reg)) temp)
272 (:results (res :scs (unsigned-reg)))
273 (:result-types positive-fixnum)
274 (:generator 4
275 (loadw temp struct 0 instance-pointer-lowtag)
276 (inst mov res (lsr temp n-widetag-bits))))
278 (define-full-reffer instance-index-ref * instance-slots-offset
279 instance-pointer-lowtag (descriptor-reg any-reg) * %instance-ref)
281 (define-full-setter instance-index-set * instance-slots-offset
282 instance-pointer-lowtag (descriptor-reg any-reg null) * %instance-set)
284 ;;;; Code object frobbing.
286 (define-full-reffer code-header-ref * 0 other-pointer-lowtag
287 (descriptor-reg any-reg) * code-header-ref)
289 (define-full-setter code-header-set * 0 other-pointer-lowtag
290 (descriptor-reg any-reg null) * code-header-set)
292 ;;;; raw instance slot accessors
294 (macrolet
295 ((define-raw-slot-vops (name ref-inst set-inst value-primtype value-sc
296 &key use-lip (move-macro 'move))
297 (labels ((emit-generator (instruction move-result)
298 `((inst add offset index
299 (- (* instance-slots-offset n-word-bytes)
300 instance-pointer-lowtag))
301 ,@(if use-lip
302 `((inst add lip object offset)
303 (inst ,instruction value (@ lip)))
304 `((inst ,instruction value (@ object offset))))
305 ,@(when move-result
306 `((,move-macro result value))))))
307 (let ((ref-vop (symbolicate "RAW-INSTANCE-REF/" name))
308 (set-vop (symbolicate "RAW-INSTANCE-SET/" name)))
309 `(progn
310 (define-vop (,ref-vop)
311 (:translate ,(symbolicate "%" ref-vop))
312 (:policy :fast-safe)
313 (:args (object :scs (descriptor-reg))
314 (index :scs (any-reg)))
315 (:arg-types * positive-fixnum)
316 (:results (value :scs (,value-sc)))
317 (:result-types ,value-primtype)
318 (:temporary (:scs (non-descriptor-reg)) offset)
319 ,@(when use-lip '((:temporary (:scs (interior-reg)) lip)))
320 (:generator 5 ,@(emit-generator ref-inst nil)))
321 (define-vop (,set-vop)
322 (:translate ,(symbolicate "%" set-vop))
323 (:policy :fast-safe)
324 (:args (object :scs (descriptor-reg))
325 (index :scs (any-reg))
326 (value :scs (,value-sc) :target result))
327 (:arg-types * positive-fixnum ,value-primtype)
328 (:results (result :scs (,value-sc)))
329 (:result-types ,value-primtype)
330 (:temporary (:scs (non-descriptor-reg)) offset)
331 ,@(when use-lip '((:temporary (:scs (interior-reg)) lip)))
332 (:generator 5 ,@(emit-generator set-inst t))))))))
333 (define-raw-slot-vops word ldr str unsigned-num unsigned-reg)
334 (define-raw-slot-vops single flds fsts single-float single-reg
335 :use-lip t :move-macro move-single)
336 (define-raw-slot-vops double fldd fstd double-float double-reg
337 :use-lip t :move-macro move-double)
338 (define-raw-slot-vops complex-single load-complex-single store-complex-single complex-single-float complex-single-reg
339 :use-lip t :move-macro move-complex-single)
340 (define-raw-slot-vops complex-double load-complex-double store-complex-double complex-double-float complex-double-reg
341 :use-lip t :move-macro move-complex-double))