1 ;;;; various useful macros for generating HPPA code
3 ;;;; This software is part of the SBCL system. See the README file for
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.
15 (defmacro expand
(expr)
16 (let ((gensym (gensym)))
22 ;;; Instruction-like macros.
23 ;;; FIXME-lav: add if always-emit-code-p is :e= then error if location=
24 (defmacro move
(src dst
&optional always-emit-code-p
)
25 "Move SRC into DST (unless they are location= and ALWAYS-EMIT-CODE-P is nil)."
26 (once-only ((n-src src
)
28 `(if (location= ,n-dst
,n-src
)
29 (when ,always-emit-code-p
31 (inst move
,n-src
,n-dst
))))
33 (defmacro loadw
(result base
&optional
(offset 0) (lowtag 0))
34 (once-only ((result result
) (base base
))
35 `(inst ldw
(- (ash ,offset word-shift
) ,lowtag
) ,base
,result
)))
37 (defmacro storew
(value base
&optional
(offset 0) (lowtag 0))
38 (once-only ((value value
) (base base
) (offset offset
) (lowtag lowtag
))
39 `(inst stw
,value
(- (ash ,offset word-shift
) ,lowtag
) ,base
)))
41 (defmacro load-symbol
(reg symbol
)
42 (once-only ((reg reg
) (symbol symbol
))
43 `(let ((offset (static-symbol-offset ,symbol
)))
45 ((typep offset
'(signed-byte 11))
46 (inst addi offset null-tn
,reg
))
48 (inst ldil offset
,reg
)
49 (inst ldo offset null-tn
,reg
:unsigned t
))))))
51 (defmacro load-symbol-value
(reg symbol
)
53 (+ (static-symbol-offset ',symbol
)
54 (ash symbol-value-slot word-shift
)
55 (- other-pointer-lowtag
))
58 (defmacro store-symbol-value
(reg symbol
)
59 `(inst stw
,reg
(+ (static-symbol-offset ',symbol
)
60 (ash symbol-value-slot word-shift
)
61 (- other-pointer-lowtag
))
64 (defmacro load-type
(target source
&optional
(offset 0))
65 "Loads the type bits of a pointer into target independent of
66 byte-ordering issues."
67 (once-only ((n-target target
)
70 (ecase *backend-byte-order
*
72 `(inst ldb
,n-offset
,n-source
,n-target
))
74 `(inst ldb
(+ ,n-offset
(1- n-word-bytes
)) ,n-source
,n-target
)))))
76 (defmacro set-lowtag
(tag src dst
)
79 (inst dep
,tag
31 n-lowtag-bits
,dst
)))
81 ;;; Macros to handle the fact that we cannot use the machine native call and
82 ;;; return instructions.
84 (defmacro lisp-jump
(function)
85 "Jump to the lisp function FUNCTION."
87 (inst addi
(- (ash simple-fun-code-offset word-shift
)
88 fun-pointer-lowtag
) ,function lip-tn
)
90 (move ,function code-tn t
)))
92 (defmacro lisp-return
(return-pc &key
(offset 0) (frob-code t
))
93 "Return to RETURN-PC."
95 (inst addi
(- (* (1+ ,offset
) n-word-bytes
) other-pointer-lowtag
)
97 (inst bv lip-tn
,@(unless frob-code
'(:nullify t
)))
99 `((move ,return-pc code-tn t
)))))
101 (defmacro emit-return-pc
(label)
102 "Emit a return-pc header word. LABEL is the label to use for this
105 ;; alignment causes the return point to land on two address,
106 ;; where the first must be nop pad.
107 (emit-alignment n-lowtag-bits
)
109 (inst lra-header-word
)))
114 ;;; Move a stack TN to a register and vice-versa.
115 (defmacro load-stack-tn
(reg stack
)
118 (let ((offset (tn-offset stack
)))
121 (loadw reg cfp-tn offset
))))))
123 (defmacro store-stack-tn
(stack reg
)
124 `(let ((stack ,stack
)
126 (let ((offset (tn-offset stack
)))
129 (storew reg cfp-tn offset
))))))
131 (defmacro maybe-load-stack-tn
(reg reg-or-stack
)
132 "Move the TN Reg-Or-Stack into Reg if it isn't already there."
133 (once-only ((n-reg reg
)
134 (n-stack reg-or-stack
))
136 ((any-reg descriptor-reg
)
138 ((any-reg descriptor-reg
)
139 (move ,n-stack
,n-reg
))
141 (loadw ,n-reg cfp-tn
(tn-offset ,n-stack
))))))))
144 ;;;; Storage allocation:
146 (defmacro with-fixed-allocation
((result-tn flag-tn temp-tn type-code
147 size dynamic-extent-p
148 &key
(lowtag other-pointer-lowtag
)
151 "Do stuff to allocate an other-pointer object of fixed Size with a single
152 word header having the specified Type-Code. The result is placed in
153 Result-TN, and Temp-TN is a non-descriptor temp (which may be randomly used
154 by the body.) The body is placed inside the PSEUDO-ATOMIC, and presumably
155 initializes the object."
156 (declare (ignore flag-tn
))
157 (once-only ((result-tn result-tn
) (temp-tn temp-tn
)
158 (type-code type-code
) (size size
)
160 (let ((write-body `((inst li
(logior (ash (1- ,size
) n-widetag-bits
) ,type-code
) ,temp-tn
)
161 (storew ,temp-tn
,result-tn
0 ,lowtag
))))
162 `(if ,dynamic-extent-p
165 (set-lowtag ,lowtag csp-tn
,result-tn
)
166 (inst addi
(pad-data-block ,size
) csp-tn csp-tn
)
168 `((when ,type-code
,@write-body
))
171 (pseudo-atomic (:extra
(pad-data-block ,size
))
172 (set-lowtag ,lowtag alloc-tn
,result-tn
)
174 `((when ,type-code
,@write-body
))
178 ;;; is used for stack allocation of dynamic-extent objects
179 ;;; FIXME-lav, if using defun, atleast surround in assembly-form ? macro better ?
180 (defun align-csp (temp)
181 (declare (ignore temp
))
182 (let ((aligned (gen-label)))
183 (inst extru csp-tn
31 n-lowtag-bits zero-tn
:<>)
184 (inst b aligned
:nullify t
)
185 (inst addi n-word-bytes csp-tn csp-tn
)
186 (storew zero-tn csp-tn -
1)
187 (emit-label aligned
)))
191 (defun emit-error-break (vop kind code values
)
194 (note-this-location vop
:internal-error
))
197 (encode-internal-error-args values
)
198 (emit-alignment word-shift
)))
200 (defun error-call (vop error-code
&rest values
)
201 "Cause an error. ERROR-CODE is the error to cause."
202 (emit-error-break vop error-trap
(error-number-or-lose error-code
) values
))
205 (defun cerror-call (vop label error-code
&rest values
)
206 "Cause a continuable error. If the error is continued, execution resumes at
208 (without-scheduling ()
210 (emit-error-break vop cerror-trap
(error-number-or-lose error-code
) values
)))
212 (defun generate-error-code (vop error-code
&rest values
)
213 "Generate-Error-Code Error-code Value*
214 Emit code for an error with the specified Error-Code and context Values."
215 (assemble (*elsewhere
*)
216 (let ((start-lab (gen-label)))
217 (emit-label start-lab
)
218 (apply #'error-call vop error-code values
)
221 (defmacro generate-cerror-code
(vop error-code
&rest values
)
222 "Generate-CError-Code Error-code Value*
223 Emit code for a continuable error with the specified Error-Code and
224 context Values. If the error is continued, execution resumes after
225 the GENERATE-CERROR-CODE form."
227 (let ((continue (gen-label)))
228 (emit-label continue
)
229 (assemble (*elsewhere
*)
230 (let ((error (gen-label)))
232 (apply #'cerror-call vop continue error-code values
)
237 ;;; handy macro for making sequences look atomic
238 (defmacro pseudo-atomic
((&key
(extra 0)) &rest forms
)
239 (let ((n-extra (gensym)))
240 `(let ((,n-extra
,extra
))
241 (inst addi
4 alloc-tn alloc-tn
)
244 ((typep ,n-extra
'(signed-byte 11))
245 (inst addit
(- ,n-extra
4) alloc-tn alloc-tn
:od
))
246 ((typep ,n-extra
'(signed-byte 14))
247 (inst ldo
,n-extra alloc-tn alloc-tn
)
248 (inst addit -
4 alloc-tn alloc-tn
:od
))
250 ;; FIXME: Make this case work, somehow
251 (error "EXTRA out-of-range in PSEUDO-ATOMIC"))))))
253 ;;;; indexed references
255 (deftype load
/store-index
(scale lowtag min-offset
256 &optional
(max-offset min-offset
))
257 `(integer ,(- (truncate (+ (ash 1 14)
258 (* min-offset n-word-bytes
)
261 ,(truncate (- (+ (1- (ash 1 14)) lowtag
)
262 (* max-offset n-word-bytes
))
265 (defmacro define-full-reffer
(name type offset lowtag scs el-type
270 `((:translate
,translate
)))
272 (:args
(object :scs
(descriptor-reg))
273 (index :scs
(any-reg)))
274 (:arg-types
,type tagged-num
)
275 (:temporary
(:scs
(interior-reg)) lip
)
276 (:results
(value :scs
,scs
))
277 (:result-types
,el-type
)
279 (inst add object index lip
)
280 (loadw value lip
,offset
,lowtag
)))
281 (define-vop (,(symbolicate name
"-C"))
283 `((:translate
,translate
)))
285 (:args
(object :scs
(descriptor-reg)))
288 (:constant
(load/store-index
,n-word-bytes
,(eval lowtag
)
290 (:results
(value :scs
,scs
))
291 (:result-types
,el-type
)
293 (loadw value object
(+ ,offset index
) ,lowtag
)))))
295 (defmacro define-full-setter
(name type offset lowtag scs el-type
300 `((:translate
,translate
)))
302 (:args
(object :scs
(descriptor-reg))
303 (index :scs
(any-reg))
304 (value :scs
,scs
:target result
))
305 (:arg-types
,type tagged-num
,el-type
)
306 (:temporary
(:scs
(interior-reg)) lip
)
307 (:results
(result :scs
,scs
))
308 (:result-types
,el-type
)
310 (inst add object index lip
)
311 (storew value lip
,offset
,lowtag
)
312 (move value result
)))
313 (define-vop (,(symbolicate name
"-C"))
315 `((:translate
,translate
)))
317 (:args
(object :scs
(descriptor-reg))
321 (:constant
(load/store-index
,n-word-bytes
,(eval lowtag
)
324 (:results
(result :scs
,scs
))
325 (:result-types
,el-type
)
327 (storew value object
(+ ,offset index
) ,lowtag
)
328 (move value result
)))))
331 (defmacro define-partial-reffer
(name type size signed offset lowtag scs
332 el-type
&optional translate
)
333 (let ((scale (ecase size
(:byte
1) (:short
2))))
337 `((:translate
,translate
)))
339 (:args
(object :scs
(descriptor-reg) :to
(:eval
0))
340 (index :scs
(unsigned-reg)))
341 (:arg-types
,type positive-fixnum
)
342 (:results
(value :scs
,scs
))
343 (:result-types
,el-type
)
344 (:temporary
(:scs
(interior-reg)) lip
)
346 (inst ,(ecase size
(:byte
'add
) (:short
'sh1add
))
348 (inst ,(ecase size
(:byte
'ldb
) (:short
'ldh
))
349 (- (* ,offset n-word-bytes
) ,lowtag
) lip value
)
351 `((inst extrs value
31 ,(* scale n-byte-bits
) value
)))))
352 (define-vop (,(symbolicate name
"-C"))
354 `((:translate
,translate
)))
356 (:args
(object :scs
(descriptor-reg)))
359 (:constant
(load/store-index
,scale
362 (:results
(value :scs
,scs
))
363 (:result-types
,el-type
)
365 (inst ,(ecase size
(:byte
'ldb
) (:short
'ldh
))
366 (- (+ (* ,offset n-word-bytes
) (* index
,scale
)) ,lowtag
)
369 `((inst extrs value
31 ,(* scale n-byte-bits
) value
))))))))
371 (defmacro define-partial-setter
(name type size offset lowtag scs el-type
373 (let ((scale (ecase size
(:byte
1) (:short
2))))
377 `((:translate
,translate
)))
379 (:args
(object :scs
(descriptor-reg))
380 (index :scs
(unsigned-reg))
381 (value :scs
,scs
:target result
))
382 (:arg-types
,type positive-fixnum
,el-type
)
383 (:temporary
(:scs
(interior-reg)) lip
)
384 (:results
(result :scs
,scs
))
385 (:result-types
,el-type
)
387 (inst ,(ecase size
(:byte
'add
) (:short
'sh1add
))
389 (inst ,(ecase size
(:byte
'stb
) (:short
'sth
))
390 value
(- (* ,offset n-word-bytes
) ,lowtag
) lip
)
391 (move value result
)))
392 (define-vop (,(symbolicate name
"-C"))
394 `((:translate
,translate
)))
396 (:args
(object :scs
(descriptor-reg))
397 (value :scs
,scs
:target result
))
400 (:constant
(load/store-index
,scale
404 (:results
(result :scs
,scs
))
405 (:result-types
,el-type
)
407 (inst ,(ecase size
(:byte
'stb
) (:short
'sth
))
409 (- (+ (* ,offset n-word-bytes
) (* index
,scale
)) ,lowtag
)
411 (move value result
))))))