Change immobile space free pointers to alien vars
[sbcl.git] / src / runtime / ppc-assem.S
blob812fdd0e9778c9fdb21113f7c10da6ad741befbf
1 #ifdef __ELF__
2 // Mark the object as not requiring an executable stack.
3 .section .note.GNU-stack,"",%progbits
4 #endif
6 #define LANGUAGE_ASSEMBLY
8 #include "sbcl.h" 
9 #include "lispregs.h"
10 #include "globals.h"
12 #include "genesis/simple-fun.h"
13 #include "genesis/fdefn.h"
14 #include "genesis/closure.h"
15 #include "genesis/funcallable-instance.h"
16 #include "genesis/static-symbols.h"
17 #ifdef LISP_FEATURE_SB_THREAD
18 #include "genesis/thread.h"
19 #endif
21 #ifdef LISP_FEATURE_DARWIN
22 #define CSYMBOL(x) _ ## x
23 #else
24 #define CSYMBOL(x) x
25 #endif
27 #if defined LISP_FEATURE_DARWIN
28 #define FUNCDEF(x)      .text @ \
29                         .align 3 @ \
30 _##x:
32 #define GFUNCDEF(x)     .globl _ ## x @ \
33         FUNCDEF(x)
34 #else
35 #define FUNCDEF(x)      .text ; \
36                         .align 3 ; \
37                         .type x,@function ; \
40 #define GFUNCDEF(x)     .globl x ; \
41         FUNCDEF(x)
42 #endif
44 #if defined LISP_FEATURE_DARWIN
45 #define SET_SIZE(x)
46 #else
47 #define SET_SIZE(x) .size x,.-x
48 #endif
50 /* Load a register from a global, using the register as an intermediary */
51 /* The register will be a fixnum for one instruction, so this is gc-safe */
53 #if defined LISP_FEATURE_DARWIN
54 #define load(reg,global) \
55         lis reg,ha16(global) @ \
56         lwz reg,lo16(global)(reg) ; Comment
57 #define store(reg,temp,global) \
58         lis temp,ha16(global) @\
59         stw reg,lo16(global)(temp) ; Comment
60 #else
61 #define load(reg,global) \
62         lis reg,global@ha; lwz reg,global@l(reg)
63 #define store(reg,temp,global) \
64         lis temp,global@ha; stw reg,global@l(temp)
65 #endif
66         
67 #define FIRST_SAVE_FPR  14      /* lowest-numbered non-volatile FPR */
68 #ifdef LISP_FEATURE_DARWIN
69 #define FIRST_SAVE_GPR  13      /* lowest-numbered non-volatile GPR */
70 #define NGPR_SAVE_BYTES(n) ((32-(n))*4)
71 #define FRAME_ARG_BYTES(n)  (((((n)+6)*4)+15)&~15)
72 #else
73 #define FIRST_SAVE_GPR  14      /* lowest-numbered non-volatile GPR */
74 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
75 #define FRAME_ARG_BYTES(n)  (((((n)+2)*4)+15)&~15)
76 #endif
77 #define NFPR_SAVE_BYTES(n) ((32-(n))*8)
79 #ifdef LISP_FEATURE_DARWIN
80 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
81 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words))
82 #define SAVE_FPR(n) stfd f##n,-8*(32- n)(r11)
83 #define SAVE_GPR(n) stw r##n,-4*(32- n)(r11)
84 #define FULL_FRAME_SIZE (FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,8,1)+15&~15)
85 #define RESTORE_FPR(n) lfd f##n,-8*(32- n)(r11)
86 #define RESTORE_GPR(n) lwz r##n,-4*(32- n)(r11)
87 #else
88 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
89 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
90 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
91 #define SAVE_GPR(n) stw n,-4*(32-(n))(11)
92 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
94 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
95 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
96 #endif
98 #ifdef LISP_FEATURE_DARWIN
99 #define C_FULL_PROLOG \
100         nop @\
101         nop @ \
102         mfcr REG(0) @ \
103         stw REG(0),4(REG(1)) @ \
104         mflr REG(0) @ \
105         stw REG(0),8(REG(1)) @ \
106         mr REG(11),REG(1) @ \
107         stwu REG(1),-FULL_FRAME_SIZE(REG(1)) @ \
108         SAVE_FPR(14) @ \
109         SAVE_FPR(15) @ \
110         SAVE_FPR(16) @ \
111         SAVE_FPR(17) @ \
112         SAVE_FPR(18) @ \
113         SAVE_FPR(19) @ \
114         SAVE_FPR(20) @ \
115         SAVE_FPR(21) @ \
116         SAVE_FPR(22) @ \
117         SAVE_FPR(23) @ \
118         SAVE_FPR(24) @ \
119         SAVE_FPR(25) @ \
120         SAVE_FPR(26) @ \
121         SAVE_FPR(27) @ \
122         SAVE_FPR(28) @ \
123         SAVE_FPR(29) @ \
124         SAVE_FPR(30) @ \
125         SAVE_FPR(31) @ \
126         la REG(11),-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
127         SAVE_GPR(13) @ \
128         SAVE_GPR(14) @ \
129         SAVE_GPR(15) @ \
130         SAVE_GPR(16) @ \
131         SAVE_GPR(17) @ \
132         SAVE_GPR(18) @ \
133         SAVE_GPR(19) @ \
134         SAVE_GPR(20) @ \
135         SAVE_GPR(21) @ \
136         SAVE_GPR(22) @ \
137         SAVE_GPR(23) @ \
138         SAVE_GPR(24) @ \
139         SAVE_GPR(25) @ \
140         SAVE_GPR(26) @ \
141         SAVE_GPR(27) @ \
142         SAVE_GPR(28) @ \
143         SAVE_GPR(29) @ \
144         SAVE_GPR(30) @ \
145         SAVE_GPR(31)
148 #define C_FULL_EPILOG \
149         la REG(11),FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(1)) @ \
150         RESTORE_GPR(13) @ \
151         RESTORE_GPR(14) @ \
152         RESTORE_GPR(15) @ \
153         RESTORE_GPR(16) @ \
154         RESTORE_GPR(17) @ \
155         RESTORE_GPR(18) @ \
156         RESTORE_GPR(19) @ \
157         RESTORE_GPR(20) @ \
158         RESTORE_GPR(21) @ \
159         RESTORE_GPR(22) @ \
160         RESTORE_GPR(23) @ \
161         RESTORE_GPR(24) @ \
162         RESTORE_GPR(25) @ \
163         RESTORE_GPR(26) @ \
164         RESTORE_GPR(27) @ \
165         RESTORE_GPR(28) @ \
166         RESTORE_GPR(29) @ \
167         RESTORE_GPR(30) @ \
168         RESTORE_GPR(31) @ \
169         la REG(11),NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
170         RESTORE_FPR(14) @ \
171         RESTORE_FPR(15) @ \
172         RESTORE_FPR(16) @ \
173         RESTORE_FPR(17) @ \
174         RESTORE_FPR(18) @ \
175         RESTORE_FPR(19) @ \
176         RESTORE_FPR(20) @ \
177         RESTORE_FPR(21) @ \
178         RESTORE_FPR(22) @ \
179         RESTORE_FPR(23) @ \
180         RESTORE_FPR(24) @ \
181         RESTORE_FPR(25) @ \
182         RESTORE_FPR(26) @ \
183         RESTORE_FPR(27) @ \
184         RESTORE_FPR(28) @ \
185         RESTORE_FPR(29) @ \
186         RESTORE_FPR(30) @ \
187         RESTORE_FPR(31) @ \
188         lwz REG(1),0(REG(1)) @ \
189         lwz REG(0),4(REG(1)) @ \
190         mtcr REG(0) @ \
191         lwz REG(0),8(REG(1)) @ \
192         mtlr REG(0) @ \
193         
194 #else   
196 #define C_FULL_PROLOG \
197         mflr 0 ; \
198         stw 0,4(1) ; \
199         mr 11,1 ; \
200         stwu 1,-FULL_FRAME_SIZE(1) ; \
201         SAVE_FPR(14) ; \
202         SAVE_FPR(15) ; \
203         SAVE_FPR(16) ; \
204         SAVE_FPR(17) ; \
205         SAVE_FPR(18) ; \
206         SAVE_FPR(19) ; \
207         SAVE_FPR(20) ; \
208         SAVE_FPR(21) ; \
209         SAVE_FPR(22) ; \
210         SAVE_FPR(23) ; \
211         SAVE_FPR(24) ; \
212         SAVE_FPR(25) ; \
213         SAVE_FPR(26) ; \
214         SAVE_FPR(27) ; \
215         SAVE_FPR(28) ; \
216         SAVE_FPR(29) ; \
217         SAVE_FPR(30) ; \
218         SAVE_FPR(31) ; \
219         la 11,-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
220         SAVE_GPR(14) ; \
221         SAVE_GPR(15) ; \
222         SAVE_GPR(16) ; \
223         SAVE_GPR(17) ; \
224         SAVE_GPR(18) ; \
225         SAVE_GPR(19) ; \
226         SAVE_GPR(20) ; \
227         SAVE_GPR(21) ; \
228         SAVE_GPR(22) ; \
229         SAVE_GPR(23) ; \
230         SAVE_GPR(24) ; \
231         SAVE_GPR(25) ; \
232         SAVE_GPR(26) ; \
233         SAVE_GPR(27) ; \
234         SAVE_GPR(28) ; \
235         SAVE_GPR(29) ; \
236         SAVE_GPR(30) ; \
237         SAVE_GPR(31) ; \
238         mfcr 0  ; \
239         stw 0,8(1)
241 #define C_FULL_EPILOG \
242         lwz 5,8(1) ; \
243         mtcrf 255,5 ; \
244         la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
245         RESTORE_GPR(14) ; \
246         RESTORE_GPR(15) ; \
247         RESTORE_GPR(16) ; \
248         RESTORE_GPR(17) ; \
249         RESTORE_GPR(18) ; \
250         RESTORE_GPR(19) ; \
251         RESTORE_GPR(20) ; \
252         RESTORE_GPR(21) ; \
253         RESTORE_GPR(22) ; \
254         RESTORE_GPR(23) ; \
255         RESTORE_GPR(24) ; \
256         RESTORE_GPR(25) ; \
257         RESTORE_GPR(26) ; \
258         RESTORE_GPR(27) ; \
259         RESTORE_GPR(28) ; \
260         RESTORE_GPR(29) ; \
261         RESTORE_GPR(30) ; \
262         RESTORE_GPR(31) ; \
263         la 11,NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
264         RESTORE_FPR(14) ; \
265         RESTORE_FPR(15) ; \
266         RESTORE_FPR(16) ; \
267         RESTORE_FPR(17) ; \
268         RESTORE_FPR(18) ; \
269         RESTORE_FPR(19) ; \
270         RESTORE_FPR(20) ; \
271         RESTORE_FPR(21) ; \
272         RESTORE_FPR(22) ; \
273         RESTORE_FPR(23) ; \
274         RESTORE_FPR(24) ; \
275         RESTORE_FPR(25) ; \
276         RESTORE_FPR(26) ; \
277         RESTORE_FPR(27) ; \
278         RESTORE_FPR(28) ; \
279         RESTORE_FPR(29) ; \
280         RESTORE_FPR(30) ; \
281         RESTORE_FPR(31) ; \
282         lwz 1,0(1) ; \
283         lwz 0,4(1) ; \
284         mtlr 0 ; \
285         
286 #endif
288 /* gas can't parse nnnnLU; redefine */
289 #if BACKEND_PAGE_BYTES == 65536
290 # undef BACKEND_PAGE_BYTES
291 # define BACKEND_PAGE_BYTES 65536
292 #elif BACKEND_PAGE_BYTES == 4096
293 # undef BACKEND_PAGE_BYTES
294 # define BACKEND_PAGE_BYTES 4096
295 #else
296 # error BACKEND_PAGE_BYTES mismatch
297 #endif
299 #ifdef LISP_FEATURE_SB_SAFEPOINT
300 /* OAOOM because we don't have the C headers here. */
301 # define THREAD_CSP_PAGE_SIZE 4096
303 /* the CSP page sits right before the thread */
304 # define THREAD_SAVED_CSP_OFFSET (-THREAD_CSP_PAGE_SIZE)
305 #endif
307         .text
310  * Function to transfer control into lisp.  The lisp object to invoke is
311  * passed as the first argument, which puts it in NL0
312  */
314         GFUNCDEF(call_into_lisp)
315         C_FULL_PROLOG
316         /* NL0 - function, NL1 - frame pointer, NL2 - nargs. */
317 #if defined(LISP_FEATURE_SB_THREAD)
318         /* We need to obtain a pointer to our TLS block before we do
319          * anything else.  For this, we call pthread_getspecific().
320          * We've preserved all of the callee-saves registers, so we
321          * can use them to stash our arguments temporarily while we
322          * make the call. */
323         mr reg_A0, reg_NL0
324         mr reg_A1, reg_NL1
325         mr reg_A2, reg_NL2
327         /* Call out to obtain our TLS block. */
328         load(reg_NL0,CSYMBOL(specials))
329         /* This won't work on darwin: wrong fixup style.  And is it
330          * supposed to be lis/ori or lis/addi?  Or does it differ
331          * between darwin and everything else again? */
332         lis reg_CFUNC,CSYMBOL(pthread_getspecific)@h
333         ori reg_CFUNC,reg_CFUNC,CSYMBOL(pthread_getspecific)@l
334         mtctr reg_CFUNC
335         bctrl
336         mr reg_THREAD, reg_NL0
338         /* Restore our original parameters. */
339         mr reg_NL2, reg_A2
340         mr reg_NL1, reg_A1
341         mr reg_NL0, reg_A0
342 #endif
343         /* store(reg_POLL,11,saver2) */
344         /* Initialize tagged registers */
345         li reg_ZERO,0
346         li reg_CODE,0
347         li reg_CNAME,0
348         li reg_LEXENV,0
349         li reg_FDEFN,0
350         li reg_OCFP,0
351         li reg_LRA,0
352         li reg_A0,0
353         li reg_A1,0
354         li reg_A2,0
355         li reg_A3,0
356         li reg_L0,0
357         li reg_L1,0
358 #if !defined(LISP_FEATURE_SB_THREAD)
359         li reg_L2,0
360 #endif
361         li reg_LIP,0
362 #ifdef LISP_FEATURE_DARWIN      
363         lis reg_NULL,hi16(NIL)
364         ori reg_NULL,reg_NULL,lo16(NIL)
365 #else
366         lis reg_NULL,NIL@h
367         ori reg_NULL,reg_NULL,NIL@l
368 #endif
369         /* Turn on pseudo-atomic */
371         li reg_ALLOC,flag_PseudoAtomic
372 #if defined(LISP_FEATURE_SB_THREAD)
373         stw reg_ZERO,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
374         lwz reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
375         lwz reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
376         lwz reg_OCFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
377 #else
378         store(reg_ZERO,reg_NL4,CSYMBOL(foreign_function_call_active))
379         load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
380         load(reg_CSP,CSYMBOL(current_control_stack_pointer))
381         load(reg_OCFP,CSYMBOL(current_control_frame_pointer))
382 #endif
383         /* This is important for CHENEYGC: It's the allocation
384          * pointer.  It's also important for ROOM on GENCGC:
385          * It's a pointer to the end of dynamic space, used to
386          * determine where to stop in MAP-ALLOCATED-OBJECTS. */
387         load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
388         add reg_ALLOC,reg_ALLOC,reg_NL4
390         /* No longer atomic, and check for interrupt */
391         subi reg_ALLOC,reg_ALLOC,flag_PseudoAtomic
392         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
393         twnei reg_NL3, 0
395         /* Pass in the arguments */
397         mr reg_CFP,reg_NL1
398         mr reg_LEXENV,reg_NL0
399         lwz reg_A0,0(reg_CFP)
400         lwz reg_A1,4(reg_CFP)
401         lwz reg_A2,8(reg_CFP)
402         lwz reg_A3,12(reg_CFP)
404         /* Calculate LRA */
405 #ifdef LISP_FEATURE_DARWIN
406         lis reg_LRA,ha16(lra)
407         addi reg_LRA,reg_LRA,lo16(lra)
408 #else
409         lis reg_LRA,lra@h
410         ori reg_LRA,reg_LRA,lra@l
411 #endif
412         addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
414         /* Function is an indirect closure */
415         lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
416         addi reg_LIP,reg_CODE,SIMPLE_FUN_CODE_OFFSET
417         mtctr reg_LIP
418         slwi reg_NARGS,reg_NL2,2
419         bctr                    
420         
421         .align 3
422 lra:
423         .long RETURN_PC_WIDETAG 
425         /* Blow off any extra values. */
426         mr reg_CSP,reg_OCFP
427         nop
429         /* Return the one value. */
431         mr REG(3),reg_A0
433         /* Turn on  pseudo-atomic */
434         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
436 #if defined(LISP_FEATURE_SB_THREAD)
437         /* Store lisp state */
438         stw reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
439         stw reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
440         stw reg_CFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
442         /* No longer in Lisp. */
443         stw reg_ALLOC,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
444 #else
445         /* Store lisp state */
446         clrrwi reg_NL1,reg_ALLOC,3
447         store(reg_NL1,reg_NL2,CSYMBOL(dynamic_space_free_pointer))
448         /* store(reg_POLL,reg_NL2,poll_flag) */
449         /* load(reg_NL2,current_thread) */
450         store(reg_BSP,reg_NL2,CSYMBOL(current_binding_stack_pointer))
451         store(reg_CSP,reg_NL2,CSYMBOL(current_control_stack_pointer))
452         store(reg_CFP,reg_NL2,CSYMBOL(current_control_frame_pointer))
453         /* load(reg_POLL,saver2) */
455         /* No longer in Lisp. */
456         store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
457 #endif
459         /* Check for interrupt */
460         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
461         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
462         twnei reg_NL3,0
463         
464         /* Back to C */
465         C_FULL_EPILOG
466         blr
467         SET_SIZE(call_into_lisp)
470         GFUNCDEF(call_into_c)
471         /* We're kind of low on unboxed, non-dedicated registers here:
472         most of the unboxed registers may have outgoing C args in them.
473         CFUNC is going to have to go in the CTR in a moment, anyway
474         so we'll free it up soon.  reg_NFP is preserved by lisp if it
475         has a meaningful value in it, so we can use it.  reg_NARGS is
476         free when it's not holding a copy of the "real" reg_NL3, which
477         gets tied up by the pseudo-atomic mechanism */
478         mtctr reg_CFUNC
479         mflr reg_LIP
480         /* Build a lisp stack frame */
481         mr reg_OCFP,reg_CFP
482         mr reg_CFP,reg_CSP
483         la reg_CSP,32(reg_CSP)
484         stw reg_OCFP,0(reg_CFP)
485         stw reg_CODE,8(reg_CFP)
486         /* The pseudo-atomic mechanism wants to use reg_NL3, but that
487         may be an outgoing C argument.  Copy reg_NL3 to something that's
488         unboxed and -not- one of the C argument registers */
489         mr reg_NARGS,reg_NL3
491         /* Turn on pseudo-atomic */
492         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
494         /* Convert the return address to an offset and save it on the stack. */
495         sub reg_NFP,reg_LIP,reg_CODE
496         la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
497         stw reg_NFP,4(reg_CFP)
499 #ifdef LISP_FEATURE_SB_THREAD
500         /* Store Lisp state */
501         stw reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
502         stw reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
503         stw reg_CFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
505         /* No longer in Lisp. */
506         stw reg_CSP,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
507 #else
508         /* Store Lisp state */
509         clrrwi reg_NFP,reg_ALLOC,3
510         store(reg_NFP,reg_CFUNC,CSYMBOL(dynamic_space_free_pointer))
511         /* load(reg_CFUNC,current_thread) */
512         
513         store(reg_BSP,reg_CFUNC,CSYMBOL(current_binding_stack_pointer))
514         store(reg_CSP,reg_CFUNC,CSYMBOL(current_control_stack_pointer))
515         store(reg_CFP,reg_CFUNC,CSYMBOL(current_control_frame_pointer))
517         /* No longer in Lisp */
518         store(reg_CSP,reg_CFUNC,CSYMBOL(foreign_function_call_active))
519 #endif
520         /* load(reg_POLL,saver2) */
521         /* Disable pseudo-atomic; check pending interrupt */
522         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
523         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
524         twnei reg_NL3, 0
526 #ifdef LISP_FEATURE_SB_SAFEPOINT
527         /* OK to run GC without stopping this thread from this point on. */
528         stw reg_CSP,THREAD_SAVED_CSP_OFFSET(reg_THREAD)
529 #endif
531         mr reg_NL3,reg_NARGS
533 #ifdef LISP_FEATURE_DARWIN
534         /* PowerOpen (i.e. OS X) requires the callee address in r12
535            (a.k.a. CFUNC), so move it back there, too. */
536         mfctr reg_CFUNC
537 #endif
538         /* Into C we go. */
539         bctrl
541         /* Re-establish NIL */
542 #ifdef LISP_FEATURE_DARWIN
543         lis reg_NULL,hi16(NIL)
544         ori reg_NULL,reg_NULL,lo16(NIL)
545 #else
546         lis reg_NULL,NIL@h
547         ori reg_NULL,reg_NULL,NIL@l
548 #endif
549         /* And reg_ZERO */
550         li reg_ZERO,0
552         /* If we GC'ed during the FF code (as the result of a callback ?)
553         the tagged lisp registers may now contain garbage (since the
554         registers were saved by C and not seen by the GC.)  Put something
555         harmless in all such registers before allowing an interrupt */
556         li reg_FDEFN,0
557         li reg_CODE,0
558         li reg_CNAME,0
559         li reg_LEXENV,0
560         /* reg_OCFP was pointing to a control stack frame & was preserved by C */
561         li reg_LRA,0
562         li reg_A0,0
563         li reg_A1,0
564         li reg_A2,0
565         li reg_A3,0
566         li reg_L0,0
567         li reg_L1,0
568 #if !defined(LISP_FEATURE_SB_THREAD)
569         /* reg_L2 is our TLS block pointer. */
570         li reg_L2,0
571 #endif
572         li reg_LIP,0
574 # ifdef LISP_FEATURE_SB_SAFEPOINT
575         /* No longer OK to run GC except at safepoints. */
576         stw reg_ZERO,THREAD_SAVED_CSP_OFFSET(reg_THREAD)
577 # endif
579         /* Atomic ... */
580         li reg_ALLOC,flag_PseudoAtomic
582 #if defined(LISP_FEATURE_SB_THREAD)
583         /* No longer in foreign function call. */
584         stw reg_ZERO,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
586         /* The binding stack pointer isn't preserved by C. */
587         lwz reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
588 #else
589         /* No long in foreign function call. */
590         store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
592         /* The free pointer may have moved */
593         /* (moved below) */
595         /* The BSP wasn't preserved by C, so load it */
596         load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
597 #endif
598         /* This is important for CHENEYGC: It's the allocation
599          * pointer.  It's also important for ROOM on GENCGC:
600          * It's a pointer to the end of dynamic space, used to
601          * determine where to stop in MAP-ALLOCATED-OBJECTS. */
602         load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
603         add reg_ALLOC,reg_ALLOC,reg_NL4
605         /* Other lisp stack/frame pointers were preserved by C.
606         I can't imagine why they'd have moved */
608         /* Get the return address back. */
609         lwz reg_LIP,4(reg_CFP)
610         lwz reg_CODE,8(reg_CFP)
611         add reg_LIP,reg_CODE,reg_LIP
612         la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
614         /* No longer atomic */
615         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
616         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
617         twnei reg_NL3, 0
619         mtlr reg_LIP
620         
621         /* Reset the lisp stack. */
622         mr reg_CSP,reg_CFP
623         mr reg_CFP,reg_OCFP
624         
625         /* And back into Lisp. */
626         blr
628         SET_SIZE(call_into_c)
630         /* The fun_end_breakpoint support here is considered by the
631         authors of the other $ARCH-assem.S files to be magic, and it
632         is.  It is a small fragment of code that is copied into a heap
633         code-object when needed, and contains an LRA object, code to
634         convert a single-value return to unknown-values format, and a
635         trap_FunEndBreakpoint. */
636         GFUNCDEF(fun_end_breakpoint_guts)
637         .globl CSYMBOL(fun_end_breakpoint_trap)
638         .globl CSYMBOL(fun_end_breakpoint_end)
640         /* Due to pointer verification in MAKE-LISP-OBJ, this must
641         include its header data (the offset from the start of the
642         code-object to the LRA).  The code-object header is 4
643         words, there are 1 word of constants, and the instruction
644         space is doubleword-aligned, making an offset of six.
645         This is header data for a widetag, so shift left eight bits
646         and add. */
647         /* FIXME: the above is full of magic numbers. */
648         .long RETURN_PC_WIDETAG + 0x600
650         /* We are receiving unknown multiple values, thus must deal
651         with the single-value and multiple-value cases separately. */
652         b fun_end_breakpoint_multiple_values
653         nop
655         /* Compute the correct value for reg_CODE based on the LRA.
656         This is a "simple" matter of subtracting a constant from
657         reg_LRA (where the LRA is stored by the return sequence) to
658         obtain a tagged pointer to the enclosing code component.  Both
659         values are tagged OTHER_POINTER_LOWTAG, so we just have to
660         account for the six words (see calculation for
661         RETURN_PC_WIDETAG, above) between the two addresses.
662         Restoring reg_CODE doesn't appear to be strictly necessary
663         here, but let's observe the niceties.*/
664         addi reg_CODE, reg_LRA, -24
666         /* Multiple values are stored relative to reg_OCFP, which we
667         set to be the current top-of-stack. */
668         mr reg_OCFP, reg_CSP
670         /* Reserve a save location for the one value we have. */
671         addi reg_CSP, reg_CSP, 4
673         /* Record the number of values we have as a FIXNUM. */
674         li reg_NARGS, 4
676         /* Blank the remaining arg-passing registers. */
677         mr reg_A1, reg_NULL
678         mr reg_A2, reg_NULL
679         mr reg_A3, reg_NULL
681         /* And branch to our trap. */
682         b CSYMBOL(fun_end_breakpoint_trap)
684 fun_end_breakpoint_multiple_values:
685         /* Compute the correct value for reg_CODE.  See the
686         explanation for the single-value case, above. */
687         addi reg_CODE, reg_LRA, -24
689         /* The actual magic trap. */
690 CSYMBOL(fun_end_breakpoint_trap):
691         twllei  reg_ZERO, trap_FunEndBreakpoint
693         /* Finally, the debugger needs to know where the end of the
694         fun_end_breakpoint_guts are, so that it may calculate its size
695         in order to populate out a suitably-sized code object. */
696 CSYMBOL(fun_end_breakpoint_end):
697         SET_SIZE(fun_end_breakpoint_guts)
700         GFUNCDEF(ppc_flush_cache_line)
701         dcbf 0,REG(3)
702         sync
703         icbi 0,REG(3)
704         sync
705         isync
706         blr
707         SET_SIZE(ppc_flush_cache_line)
709         GFUNCDEF(do_pending_interrupt)
710         trap
711         blr
712 /* King Nato's branch has a nop here. Do we need this? */
713         SET_SIZE(do_pending_interrupt)