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