1 ;;;; a bunch of handy macros for the PPC
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.
14 ;;; Instruction-like macros.
16 (defmacro move (dst src)
17 "Move SRC into DST unless they are location=."
18 (once-only ((n-dst dst)
20 `(unless (location= ,n-dst ,n-src)
21 (inst mr ,n-dst ,n-src))))
24 ((frob (op inst shift)
25 `(defmacro ,op (object base &optional (offset 0) (lowtag 0))
26 `(inst ,',inst ,object ,base (- (ash ,offset ,,shift) ,lowtag)))))
27 (frob loadw lwz word-shift)
28 (frob storew stw word-shift))
30 (defmacro load-symbol (reg symbol)
31 `(inst addi ,reg null-tn (static-symbol-offset ,symbol)))
35 (let ((loader (intern (concatenate 'simple-string
38 (storer (intern (concatenate 'simple-string
41 (offset (intern (concatenate 'simple-string
45 (find-package "SB!VM"))))
47 (defmacro ,loader (reg symbol)
48 `(inst lwz ,reg null-tn
49 (+ (static-symbol-offset ',symbol)
50 (ash ,',offset word-shift)
51 (- other-pointer-lowtag))))
52 (defmacro ,storer (reg symbol)
53 `(inst stw ,reg null-tn
54 (+ (static-symbol-offset ',symbol)
55 (ash ,',offset word-shift)
56 (- other-pointer-lowtag))))))))
60 (defmacro load-type (target source &optional (offset 0))
61 "Loads the type bits of a pointer into target independent of
62 byte-ordering issues."
63 (once-only ((n-target target)
66 (ecase *backend-byte-order*
68 `(inst lbz ,n-target ,n-source ,n-offset))
70 `(inst lbz ,n-target ,n-source (+ ,n-offset 3))))))
72 ;;; Macros to handle the fact that we cannot use the machine native call and
73 ;;; return instructions.
75 (defmacro lisp-jump (function lip)
76 "Jump to the lisp function FUNCTION. LIP is an interior-reg temporary."
78 ;; something is deeply bogus. look at this
79 ;; (loadw ,lip ,function sb!vm:function-code-offset sb!vm:function-pointer-type)
80 (inst addi ,lip ,function (- (* n-word-bytes sb!vm:simple-fun-code-offset) sb!vm:fun-pointer-lowtag))
82 (move code-tn ,function)
85 (defmacro lisp-return (return-pc lip &key (offset 0) (frob-code t))
86 "Return to RETURN-PC."
88 (inst addi ,lip ,return-pc (- (* (1+ ,offset) n-word-bytes) other-pointer-lowtag))
91 `((move code-tn ,return-pc)))
94 (defmacro emit-return-pc (label)
95 "Emit a return-pc header word. LABEL is the label to use for this return-pc."
99 (inst lra-header-word)))
105 ;;; Load-Stack-TN, Store-Stack-TN -- Interface
107 ;;; Move a stack TN to a register and vice-versa.
108 (defmacro load-stack-tn (reg stack)
111 (let ((offset (tn-offset stack)))
114 (loadw reg cfp-tn offset))))))
116 (defmacro store-stack-tn (stack reg)
117 `(let ((stack ,stack)
119 (let ((offset (tn-offset stack)))
122 (storew reg cfp-tn offset))))))
124 (defmacro maybe-load-stack-tn (reg reg-or-stack)
125 "Move the TN Reg-Or-Stack into Reg if it isn't already there."
126 (once-only ((n-reg reg)
127 (n-stack reg-or-stack))
129 ((any-reg descriptor-reg)
131 ((any-reg descriptor-reg)
132 (move ,n-reg ,n-stack))
134 (loadw ,n-reg cfp-tn (tn-offset ,n-stack))))))))
137 ;;;; Storage allocation:
138 (defmacro with-fixed-allocation ((result-tn flag-tn temp-tn type-code size)
140 "Do stuff to allocate an other-pointer object of fixed Size with a single
141 word header having the specified Type-Code. The result is placed in
142 Result-TN, and Temp-TN is a non-descriptor temp (which may be randomly used
143 by the body.) The body is placed inside the PSEUDO-ATOMIC, and presumably
144 initializes the object."
145 (once-only ((result-tn result-tn) (temp-tn temp-tn) (flag-tn flag-tn)
146 (type-code type-code) (size size))
147 `(pseudo-atomic (,flag-tn :extra (pad-data-block ,size))
148 (inst ori ,result-tn alloc-tn other-pointer-lowtag)
149 (inst lr ,temp-tn (logior (ash (1- ,size) n-widetag-bits) ,type-code))
150 (storew ,temp-tn ,result-tn 0 other-pointer-lowtag)
155 (eval-when (:compile-toplevel :load-toplevel :execute)
156 (defun emit-error-break (vop kind code values)
157 (let ((vector (gensym)))
160 (note-this-location vop :internal-error)))
162 (with-adjustable-vector (,vector)
163 (write-var-integer (error-number-or-lose ',code) ,vector)
164 ,@(mapcar #'(lambda (tn)
166 (write-var-integer (make-sc-offset (sc-number
171 (inst byte (length ,vector))
172 (dotimes (i (length ,vector))
173 (inst byte (aref ,vector i))))
174 (align word-shift)))))
176 (defmacro error-call (vop error-code &rest values)
177 "Cause an error. ERROR-CODE is the error to cause."
179 (emit-error-break vop error-trap error-code values)))
182 (defmacro cerror-call (vop label error-code &rest values)
183 "Cause a continuable error. If the error is continued, execution resumes at
186 ,@(emit-error-break vop cerror-trap error-code values)
189 (defmacro generate-error-code (vop error-code &rest values)
190 "Generate-Error-Code Error-code Value*
191 Emit code for an error with the specified Error-Code and context Values."
192 `(assemble (*elsewhere*)
193 (let ((start-lab (gen-label)))
194 (emit-label start-lab)
195 (error-call ,vop ,error-code ,@values)
198 (defmacro generate-cerror-code (vop error-code &rest values)
199 "Generate-CError-Code Error-code Value*
200 Emit code for a continuable error with the specified Error-Code and
201 context Values. If the error is continued, execution resumes after
202 the GENERATE-CERROR-CODE form."
203 (let ((continue (gensym "CONTINUE-LABEL-"))
204 (error (gensym "ERROR-LABEL-")))
205 `(let ((,continue (gen-label)))
206 (emit-label ,continue)
207 (assemble (*elsewhere*)
208 (let ((,error (gen-label)))
210 (cerror-call ,vop ,continue ,error-code ,@values)
215 ;;; PSEUDO-ATOMIC -- Handy macro for making sequences look atomic.
217 ;;; flag-tn must be wired to NL3. If a deferred interrupt happens
218 ;;; while we have the low bits of alloc-tn set, we add a "large"
219 ;;; constant to flag-tn. On exit, we add flag-tn to alloc-tn
220 ;;; which (a) aligns alloc-tn again and (b) makes alloc-tn go
221 ;;; negative. We then trap if alloc-tn's negative (handling the
222 ;;; deferred interrupt) and using flag-tn - minus the large constant -
223 ;;; to correct alloc-tn.
224 (defmacro pseudo-atomic ((flag-tn &key (extra 0)) &rest forms)
225 (let ((n-extra (gensym)))
226 `(let ((,n-extra ,extra))
227 (without-scheduling ()
228 ;; Extra debugging stuff:
231 (inst andi. ,flag-tn alloc-tn 7)
232 (inst twi :ne ,flag-tn 0))
233 (inst lr ,flag-tn (- ,n-extra 4))
234 (inst addi alloc-tn alloc-tn 4))
236 (without-scheduling ()
237 (inst add alloc-tn alloc-tn ,flag-tn)
238 (inst twi :lt alloc-tn 0))
241 (inst andi. ,flag-tn alloc-tn 7)
242 (inst twi :ne ,flag-tn 0)))))