5e67c47eded35ae675c0c7e98b3a7570d3b4761e
[sbcl.git] / src / compiler / sparc / nlx.lisp
1 ;;;; the definitions of VOPs used for non-local exit (throw, lexical
2 ;;;; exit, etc.)
3
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.
12
13 (in-package "SB!VM")
14
15 ;;; Make an environment-live stack TN for saving the SP for NLX entry.
16 (!def-vm-support-routine make-nlx-sp-tn (env)
17   (physenv-live-tn
18    (make-representation-tn *fixnum-primitive-type* immediate-arg-scn)
19    env))
20
21 ;;; Make a TN for the argument count passing location for a non-local
22 ;;; entry.
23 (!def-vm-support-routine make-nlx-entry-arg-start-location ()
24   (make-wired-tn *fixnum-primitive-type* immediate-arg-scn ocfp-offset))
25 \f
26 ;;; save and restore dynamic environment.
27 ;;;
28 ;;; These VOPs are used in the reentered function to restore the
29 ;;; appropriate dynamic environment.  Currently we only save the
30 ;;; CURRENT-CATCH and binding stack pointer.  We don't need to
31 ;;; save/restore the current UNWIND-PROTECT, since UNWIND-PROTECTs are
32 ;;; implicitly processed during unwinding.  If there were any
33 ;;; additional stacks, then this would be the place to restore the top
34 ;;; pointers.
35
36
37 ;;; Return a list of TNs that can be used to snapshot the dynamic
38 ;;; state for use with the Save/Restore-Dynamic-Environment VOPs.
39 (!def-vm-support-routine make-dynamic-state-tns ()
40   (make-n-tns 4 *backend-t-primitive-type*))
41
42 (define-vop (save-dynamic-state)
43     (:results (catch :scs (descriptor-reg))
44               (nfp :scs (descriptor-reg))
45               (nsp :scs (descriptor-reg))
46               (eval :scs (descriptor-reg)))
47   (:vop-var vop)
48   (:generator 13
49               (load-symbol-value catch *current-catch-block*)
50               (let ((cur-nfp (current-nfp-tn vop)))
51                 (when cur-nfp
52                   (move nfp cur-nfp)))
53               (move nsp nsp-tn)))
54
55 (define-vop (restore-dynamic-state)
56     (:args (catch :scs (descriptor-reg))
57            (nfp :scs (descriptor-reg))
58            (nsp :scs (descriptor-reg))
59            (eval :scs (descriptor-reg)))
60   (:vop-var vop)
61   (:generator 10
62               (store-symbol-value catch *current-catch-block*)
63               (let ((cur-nfp (current-nfp-tn vop)))
64                 (when cur-nfp
65                   (move cur-nfp nfp)))
66               (move nsp-tn nsp)))
67
68 (define-vop (current-stack-pointer)
69     (:results (res :scs (any-reg descriptor-reg)))
70   (:generator 1
71               (move res csp-tn)))
72
73 (define-vop (current-binding-pointer)
74     (:results (res :scs (any-reg descriptor-reg)))
75   (:generator 1
76               (move res bsp-tn)))
77
78 \f
79 ;;;; unwind block hackery:
80
81 ;;; Compute the address of the catch block from its TN, then store
82 ;;; into the block the current Fp, Env, Unwind-Protect, and the entry
83 ;;; PC.
84 (define-vop (make-unwind-block)
85   (:args (tn))
86   (:info entry-label)
87   (:results (block :scs (any-reg)))
88   (:temporary (:scs (descriptor-reg)) temp)
89   (:temporary (:scs (non-descriptor-reg)) ndescr)
90   (:generator 22
91     (inst add block cfp-tn (* (tn-offset tn) n-word-bytes))
92     (load-symbol-value temp *current-unwind-protect-block*)
93     (storew temp block unwind-block-current-uwp-slot)
94     (storew cfp-tn block unwind-block-current-cont-slot)
95     (storew code-tn block unwind-block-current-code-slot)
96     (inst compute-lra-from-code temp code-tn entry-label ndescr)
97     (storew temp block catch-block-entry-pc-slot)))
98
99
100 ;;; Like Make-Unwind-Block, except that we also store in the specified tag, and
101 ;;; link the block into the Current-Catch list.
102 (define-vop (make-catch-block)
103   (:args (tn)
104          (tag :scs (any-reg descriptor-reg)))
105   (:info entry-label)
106   (:results (block :scs (any-reg)))
107   (:temporary (:scs (descriptor-reg)) temp)
108   (:temporary (:scs (descriptor-reg) :target block :to (:result 0)) result)
109   (:temporary (:scs (non-descriptor-reg)) ndescr)
110   (:generator 44
111     (inst add result cfp-tn (* (tn-offset tn) n-word-bytes))
112     (load-symbol-value temp *current-unwind-protect-block*)
113     (storew temp result catch-block-current-uwp-slot)
114     (storew cfp-tn result catch-block-current-cont-slot)
115     (storew code-tn result catch-block-current-code-slot)
116     (inst compute-lra-from-code temp code-tn entry-label ndescr)
117     (storew temp result catch-block-entry-pc-slot)
118
119     (storew tag result catch-block-tag-slot)
120     (load-symbol-value temp *current-catch-block*)
121     (storew temp result catch-block-previous-catch-slot)
122     (store-symbol-value result *current-catch-block*)
123
124     (move block result)))
125
126
127 ;;; Just set the current unwind-protect to TN's address.  This instantiates an
128 ;;; unwind block as an unwind-protect.
129 (define-vop (set-unwind-protect)
130   (:args (tn))
131   (:temporary (:scs (descriptor-reg)) new-uwp)
132   (:generator 7
133     (inst add new-uwp cfp-tn (* (tn-offset tn) n-word-bytes))
134     (store-symbol-value new-uwp *current-unwind-protect-block*)))
135
136
137 (define-vop (unlink-catch-block)
138   (:temporary (:scs (any-reg)) block)
139   (:policy :fast-safe)
140   (:translate %catch-breakup)
141   (:generator 17
142     (load-symbol-value block *current-catch-block*)
143     (loadw block block catch-block-previous-catch-slot)
144     (store-symbol-value block *current-catch-block*)))
145
146 (define-vop (unlink-unwind-protect)
147   (:temporary (:scs (any-reg)) block)
148   (:policy :fast-safe)
149   (:translate %unwind-protect-breakup)
150   (:generator 17
151     (load-symbol-value block *current-unwind-protect-block*)
152     (loadw block block unwind-block-current-uwp-slot)
153     (store-symbol-value block *current-unwind-protect-block*)))
154
155 \f
156 ;;;; NLX entry VOPs:
157
158
159 (define-vop (nlx-entry)
160   (:args (sp) ; Note: we can't list an sc-restriction, 'cause any load vops
161               ; would be inserted before the LRA.
162          (start)
163          (count))
164   (:results (values :more t))
165   (:temporary (:scs (descriptor-reg)) move-temp)
166   (:info label nvals)
167   (:save-p :force-to-stack)
168   (:vop-var vop)
169   (:generator 30
170     (emit-return-pc label)
171     (note-this-location vop :non-local-entry)
172     (cond ((zerop nvals))
173           ((= nvals 1)
174            (let ((no-values (gen-label)))
175              (inst cmp count)
176              (inst b :eq no-values)
177              (move (tn-ref-tn values) null-tn)
178              (loadw (tn-ref-tn values) start)
179              (emit-label no-values)))
180           (t
181            (collect ((defaults))
182              (inst subcc count (fixnumize 1))
183              (do ((i 0 (1+ i))
184                   (tn-ref values (tn-ref-across tn-ref)))
185                  ((null tn-ref))
186                (let ((default-lab (gen-label))
187                      (tn (tn-ref-tn tn-ref)))
188                  (defaults (cons default-lab tn))
189                  
190                  (inst b :lt default-lab)
191                  (inst subcc count (fixnumize 1))
192                  (sc-case tn
193                           ((descriptor-reg any-reg)
194                            (loadw tn start i))
195                           (control-stack
196                            (loadw move-temp start i)
197                            (store-stack-tn tn move-temp)))))
198              
199              (let ((defaulting-done (gen-label)))
200                
201                (emit-label defaulting-done)
202                
203                (assemble (*elsewhere*)
204                  (dolist (def (defaults))
205                    (emit-label (car def))
206                    (let ((tn (cdr def)))
207                      (sc-case tn
208                               ((descriptor-reg any-reg)
209                                (move tn null-tn))
210                               (control-stack
211                                (store-stack-tn tn null-tn)))))
212                  (inst b defaulting-done)
213                  (inst nop))))))
214     (load-stack-tn csp-tn sp)))
215
216
217 (define-vop (nlx-entry-multiple)
218   (:args (top :target result) (src) (count))
219   ;; Again, no SC restrictions for the args, 'cause the loading would
220   ;; happen before the entry label.
221   (:info label)
222   (:temporary (:scs (any-reg)) dst)
223   (:temporary (:scs (descriptor-reg)) temp)
224   (:results (result :scs (any-reg) :from (:argument 0))
225             (num :scs (any-reg) :from (:argument 0)))
226   (:save-p :force-to-stack)
227   (:vop-var vop)
228   (:generator 30
229     (emit-return-pc label)
230     (note-this-location vop :non-local-entry)
231     (let ((loop (gen-label))
232           (done (gen-label)))
233
234       ;; Setup results, and test for the zero value case.
235       (load-stack-tn result top)
236       (inst cmp count)
237       (inst b :eq done)
238       (inst li num 0)
239
240       ;; Compute dst as one slot down from result, because we inc the index
241       ;; before we use it.
242       (inst sub dst result 4)
243
244       ;; Copy stuff down the stack.
245       (emit-label loop)
246       (inst ld temp src num)
247       (inst add num (fixnumize 1))
248       (inst cmp num count)
249       (inst b :ne loop)
250       (inst st temp dst num)
251
252       ;; Reset the CSP.
253       (emit-label done)
254       (inst add csp-tn result num))))
255
256
257 ;;; This VOP is just to force the TNs used in the cleanup onto the stack.
258 ;;;
259 (define-vop (uwp-entry)
260   (:info label)
261   (:save-p :force-to-stack)
262   (:results (block) (start) (count))
263   (:ignore block start count)
264   (:vop-var vop)
265   (:generator 0
266     (emit-return-pc label)
267     (note-this-location vop :non-local-entry)))
268