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