a9a4ed0352d049af212698a1d69fbd0714eef37a
[sbcl.git] / src / runtime / ppc-assem.S
1 #define LANGUAGE_ASSEMBLY
2
3 #include "sbcl.h" 
4 #include "lispregs.h"
5 #include "globals.h"
6
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
15
16 #ifdef LISP_FEATURE_DARWIN
17 #define CSYMBOL(x) _ ## x
18 #else
19 #define CSYMBOL(x) x
20 #endif
21
22 #if defined LISP_FEATURE_DARWIN
23 #define FUNCDEF(x)      .text @ \
24                         .align 3 @ \
25 _##x:
26
27 #define GFUNCDEF(x)     .globl _ ## x @ \
28         FUNCDEF(x)
29 #else
30 #define FUNCDEF(x)      .text ; \
31                         .align 3 ; \
32                         .type x,@function ; \
33 x:
34
35 #define GFUNCDEF(x)     .globl x ; \
36         FUNCDEF(x)
37 #endif
38
39 #if defined LISP_FEATURE_DARWIN
40 #define SET_SIZE(x)
41 #else
42 #define SET_SIZE(x) .size x,.-x
43 #endif
44
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 */
47
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)
73
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)
88
89 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
90 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
91 #endif
92
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)
141
142
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   
190
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)
235
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
282
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 #else
288 # error BACKEND_PAGE_BYTES mismatch
289 #endif
290
291 #ifdef LISP_FEATURE_SB_SAFEPOINT
292 /* OAOOM because we don't have the C headers here. */
293 # define THREAD_CSP_PAGE_SIZE 4096
294
295 /* the CSP page sits right before the thread */
296 # define THREAD_SAVED_CSP_OFFSET (-THREAD_CSP_PAGE_SIZE)
297 #endif
298
299         .text
300
301 /*
302  * Function to transfer control into lisp.  The lisp object to invoke is
303  * passed as the first argument, which puts it in NL0
304  */
305
306         GFUNCDEF(call_into_lisp)
307         C_FULL_PROLOG
308         /* NL0 - function, NL1 - frame pointer, NL2 - nargs. */
309 #if defined(LISP_FEATURE_SB_THREAD)
310         /* We need to obtain a pointer to our TLS block before we do
311          * anything else.  For this, we call pthread_getspecific().
312          * We've preserved all of the callee-saves registers, so we
313          * can use them to stash our arguments temporarily while we
314          * make the call. */
315         mr reg_A0, reg_NL0
316         mr reg_A1, reg_NL1
317         mr reg_A2, reg_NL2
318
319         /* Call out to obtain our TLS block. */
320         load(reg_NL0,CSYMBOL(specials))
321         /* This won't work on darwin: wrong fixup style.  And is it
322          * supposed to be lis/ori or lis/addi?  Or does it differ
323          * between darwin and everything else again? */
324         lis reg_CFUNC,CSYMBOL(pthread_getspecific)@h
325         ori reg_CFUNC,reg_CFUNC,CSYMBOL(pthread_getspecific)@l
326         mtctr reg_CFUNC
327         bctrl
328         mr reg_THREAD, reg_NL0
329
330         /* Restore our original parameters. */
331         mr reg_NL2, reg_A2
332         mr reg_NL1, reg_A1
333         mr reg_NL0, reg_A0
334 #endif
335         /* store(reg_POLL,11,saver2) */
336         /* Initialize tagged registers */
337         li reg_ZERO,0
338         li reg_CODE,0
339         li reg_CNAME,0
340         li reg_LEXENV,0
341         li reg_FDEFN,0
342         li reg_OCFP,0
343         li reg_LRA,0
344         li reg_A0,0
345         li reg_A1,0
346         li reg_A2,0
347         li reg_A3,0
348         li reg_L0,0
349         li reg_L1,0
350 #if !defined(LISP_FEATURE_SB_THREAD)
351         li reg_L2,0
352 #endif
353         li reg_LIP,0
354 #ifdef LISP_FEATURE_DARWIN      
355         lis reg_NULL,hi16(NIL)
356         ori reg_NULL,reg_NULL,lo16(NIL)
357 #else
358         lis reg_NULL,NIL@h
359         ori reg_NULL,reg_NULL,NIL@l
360 #endif
361         /* Turn on pseudo-atomic */
362
363         li reg_ALLOC,flag_PseudoAtomic
364 #if defined(LISP_FEATURE_SB_THREAD)
365         stw reg_ZERO,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
366         lwz reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
367         lwz reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
368         lwz reg_OCFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
369 #else
370         store(reg_ZERO,reg_NL4,CSYMBOL(foreign_function_call_active))
371         load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
372         load(reg_CSP,CSYMBOL(current_control_stack_pointer))
373         load(reg_OCFP,CSYMBOL(current_control_frame_pointer))
374 #endif
375         /* This is important for CHENEYGC: It's the allocation
376          * pointer.  It's also important for ROOM on GENCGC:
377          * It's a pointer to the end of dynamic space, used to
378          * determine where to stop in MAP-ALLOCATED-OBJECTS. */
379         load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
380         add reg_ALLOC,reg_ALLOC,reg_NL4
381
382         /* No longer atomic, and check for interrupt */
383         subi reg_ALLOC,reg_ALLOC,flag_PseudoAtomic
384         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
385         twnei reg_NL3, 0
386
387         /* Pass in the arguments */
388
389         mr reg_CFP,reg_NL1
390         mr reg_LEXENV,reg_NL0
391         lwz reg_A0,0(reg_CFP)
392         lwz reg_A1,4(reg_CFP)
393         lwz reg_A2,8(reg_CFP)
394         lwz reg_A3,12(reg_CFP)
395
396         /* Calculate LRA */
397 #ifdef LISP_FEATURE_DARWIN
398         lis reg_LRA,ha16(lra)
399         addi reg_LRA,reg_LRA,lo16(lra)
400 #else
401         lis reg_LRA,lra@h
402         ori reg_LRA,reg_LRA,lra@l
403 #endif
404         addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
405
406         /* Function is an indirect closure */
407         lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
408         addi reg_LIP,reg_CODE,SIMPLE_FUN_CODE_OFFSET
409         mtctr reg_LIP
410         slwi reg_NARGS,reg_NL2,2
411         bctr                    
412         
413         .align 3
414 lra:
415         .long RETURN_PC_HEADER_WIDETAG 
416
417         /* Blow off any extra values. */
418         mr reg_CSP,reg_OCFP
419         nop
420
421         /* Return the one value. */
422
423         mr REG(3),reg_A0
424
425         /* Turn on  pseudo-atomic */
426         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
427
428 #if defined(LISP_FEATURE_SB_THREAD)
429         /* Store lisp state */
430         stw reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
431         stw reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
432         stw reg_CFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
433
434         /* No longer in Lisp. */
435         stw reg_ALLOC,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
436 #else
437         /* Store lisp state */
438         clrrwi reg_NL1,reg_ALLOC,3
439         store(reg_NL1,reg_NL2,CSYMBOL(dynamic_space_free_pointer))
440         /* store(reg_POLL,reg_NL2,poll_flag) */
441         /* load(reg_NL2,current_thread) */
442         store(reg_BSP,reg_NL2,CSYMBOL(current_binding_stack_pointer))
443         store(reg_CSP,reg_NL2,CSYMBOL(current_control_stack_pointer))
444         store(reg_CFP,reg_NL2,CSYMBOL(current_control_frame_pointer))
445         /* load(reg_POLL,saver2) */
446
447         /* No longer in Lisp. */
448         store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
449 #endif
450
451         /* Check for interrupt */
452         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
453         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
454         twnei reg_NL3,0
455         
456         /* Back to C */
457         C_FULL_EPILOG
458         blr
459         SET_SIZE(call_into_lisp)
460 \f
461
462         GFUNCDEF(call_into_c)
463         /* We're kind of low on unboxed, non-dedicated registers here:
464         most of the unboxed registers may have outgoing C args in them.
465         CFUNC is going to have to go in the CTR in a moment, anyway
466         so we'll free it up soon.  reg_NFP is preserved by lisp if it
467         has a meaningful value in it, so we can use it.  reg_NARGS is
468         free when it's not holding a copy of the "real" reg_NL3, which
469         gets tied up by the pseudo-atomic mechanism */
470         mtctr reg_CFUNC
471         mflr reg_LIP
472         /* Build a lisp stack frame */
473         mr reg_OCFP,reg_CFP
474         mr reg_CFP,reg_CSP
475         la reg_CSP,32(reg_CSP)
476         stw reg_OCFP,0(reg_CFP)
477         stw reg_CODE,8(reg_CFP)
478         /* The pseudo-atomic mechanism wants to use reg_NL3, but that
479         may be an outgoing C argument.  Copy reg_NL3 to something that's
480         unboxed and -not- one of the C argument registers */
481         mr reg_NARGS,reg_NL3
482
483         /* Turn on pseudo-atomic */
484         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
485
486         /* Convert the return address to an offset and save it on the stack. */
487         sub reg_NFP,reg_LIP,reg_CODE
488         la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
489         stw reg_NFP,4(reg_CFP)
490
491 #ifdef LISP_FEATURE_SB_THREAD
492         /* Store Lisp state */
493         stw reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
494         stw reg_CSP,THREAD_CONTROL_STACK_POINTER_OFFSET(reg_THREAD)
495         stw reg_CFP,THREAD_CONTROL_FRAME_POINTER_OFFSET(reg_THREAD)
496
497         /* No longer in Lisp. */
498         stw reg_CSP,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
499 #else
500         /* Store Lisp state */
501         clrrwi reg_NFP,reg_ALLOC,3
502         store(reg_NFP,reg_CFUNC,CSYMBOL(dynamic_space_free_pointer))
503         /* load(reg_CFUNC,current_thread) */
504         
505         store(reg_BSP,reg_CFUNC,CSYMBOL(current_binding_stack_pointer))
506         store(reg_CSP,reg_CFUNC,CSYMBOL(current_control_stack_pointer))
507         store(reg_CFP,reg_CFUNC,CSYMBOL(current_control_frame_pointer))
508
509         /* No longer in Lisp */
510         store(reg_CSP,reg_CFUNC,CSYMBOL(foreign_function_call_active))
511 #endif
512         /* load(reg_POLL,saver2) */
513         /* Disable pseudo-atomic; check pending interrupt */
514         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
515         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
516         twnei reg_NL3, 0
517
518 #ifdef LISP_FEATURE_SB_SAFEPOINT
519         /* OK to run GC without stopping this thread from this point on. */
520         stw reg_CSP,THREAD_SAVED_CSP_OFFSET(reg_THREAD)
521 #endif
522
523         mr reg_NL3,reg_NARGS
524
525 #ifdef LISP_FEATURE_DARWIN
526         /* PowerOpen (i.e. OS X) requires the callee address in r12
527            (a.k.a. CFUNC), so move it back there, too. */
528         mfctr reg_CFUNC
529 #endif
530         /* Into C we go. */
531         bctrl
532
533         /* Re-establish NIL */
534 #ifdef LISP_FEATURE_DARWIN
535         lis reg_NULL,hi16(NIL)
536         ori reg_NULL,reg_NULL,lo16(NIL)
537 #else
538         lis reg_NULL,NIL@h
539         ori reg_NULL,reg_NULL,NIL@l
540 #endif
541         /* And reg_ZERO */
542         li reg_ZERO,0
543
544         /* If we GC'ed during the FF code (as the result of a callback ?)
545         the tagged lisp registers may now contain garbage (since the
546         registers were saved by C and not seen by the GC.)  Put something
547         harmless in all such registers before allowing an interrupt */
548         li reg_CODE,0
549         li reg_CNAME,0
550         li reg_LEXENV,0
551         /* reg_OCFP was pointing to a control stack frame & was preserved by C */
552         li reg_LRA,0
553         li reg_A0,0
554         li reg_A1,0
555         li reg_A2,0
556         li reg_A3,0
557         li reg_L0,0
558         li reg_L1,0
559 #if !defined(LISP_FEATURE_SB_THREAD)
560         /* reg_L2 is our TLS block pointer. */
561         li reg_L2,0
562 #endif
563         li reg_LIP,0
564
565 # ifdef LISP_FEATURE_SB_SAFEPOINT
566         /* No longer OK to run GC except at safepoints. */
567         stw reg_ZERO,THREAD_SAVED_CSP_OFFSET(reg_THREAD)
568 # endif
569
570         /* Atomic ... */
571         li reg_ALLOC,flag_PseudoAtomic
572
573 #if defined(LISP_FEATURE_SB_THREAD)
574         /* No longer in foreign function call. */
575         stw reg_ZERO,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
576
577         /* The binding stack pointer isn't preserved by C. */
578         lwz reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
579 #else
580         /* No long in foreign function call. */
581         store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
582
583         /* The free pointer may have moved */
584         /* (moved below) */
585
586         /* The BSP wasn't preserved by C, so load it */
587         load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
588 #endif
589         /* This is important for CHENEYGC: It's the allocation
590          * pointer.  It's also important for ROOM on GENCGC:
591          * It's a pointer to the end of dynamic space, used to
592          * determine where to stop in MAP-ALLOCATED-OBJECTS. */
593         load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
594         add reg_ALLOC,reg_ALLOC,reg_NL4
595
596         /* Other lisp stack/frame pointers were preserved by C.
597         I can't imagine why they'd have moved */
598
599         /* Get the return address back. */
600         lwz reg_LIP,4(reg_CFP)
601         lwz reg_CODE,8(reg_CFP)
602         add reg_LIP,reg_CODE,reg_LIP
603         la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
604
605         /* No longer atomic */
606         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
607         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
608         twnei reg_NL3, 0
609
610         mtlr reg_LIP
611         
612         /* Reset the lisp stack. */
613         mr reg_CSP,reg_CFP
614         mr reg_CFP,reg_OCFP
615         
616         /* And back into Lisp. */
617         blr
618
619         SET_SIZE(call_into_c)
620
621         GFUNCDEF(xundefined_tramp)
622         .globl CSYMBOL(undefined_tramp)
623         .long   SIMPLE_FUN_HEADER_WIDETAG                         /* header */
624         .long   CSYMBOL(undefined_tramp) - SIMPLE_FUN_CODE_OFFSET /* self */
625         .long   NIL                                               /* next */
626         .long   NIL                                               /* name */
627         .long   NIL                                               /* arglist */
628         .long   NIL                                               /* type */
629         .long   NIL                                               /* xref */
630 CSYMBOL(undefined_tramp):
631         /* Point reg_CODE to the header and tag it as function, since
632            the debugger regards a function pointer in reg_CODE which
633            doesn't point to a code object as undefined function.  */
634         /* We are given that reg_LIP points to undefined_tramp by
635            virtue of the calling convention.  */
636         addi reg_CODE,reg_LIP,-SIMPLE_FUN_CODE_OFFSET
637
638         /* If we are called with stack arguments (or in a tail-call
639            scenario), we end up with an allocated stack frame, but the
640            frame link information is uninitialized.  Fix things by
641            allocating and initializing our stack frame "properly". */
642         cmpwi cr0,reg_NARGS,16
643         bt gt,1f
644         addi reg_CSP,reg_CFP,16
645         b 2f
646 1:      add reg_CSP,reg_CFP,reg_NARGS
647 2:      stw reg_OCFP,0(reg_CFP)
648         stw reg_LRA,4(reg_CFP)
649
650         /* Now that the preliminaries are dealt with, actually trap. */
651         twllei reg_ZERO,trap_Cerror
652         .byte 4
653         .byte UNDEFINED_FUN_ERROR
654         .byte 254, sc_DescriptorReg+0x40, 1 /* 140?  sparc says sc_descriptorReg */
655         /* This stuff is for the continuable error.  I don't think there's
656          * any support for it on the lisp side */
657         .align 2
658 1:      lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
659         la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
660         mtctr reg_LIP
661         bctr
662         mr reg_CSP,reg_CFP
663         b 1b
664
665         SET_SIZE(xundefined_tramp)
666
667         GFUNCDEF(xclosure_tramp)
668         .globl CSYMBOL(closure_tramp)
669 CSYMBOL(closure_tramp):
670         lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
671         lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
672         la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
673         mtctr reg_LIP
674         bctr
675
676         SET_SIZE(xclosure_tramp)
677
678         GFUNCDEF(xfuncallable_instance_tramp)
679         .globl CSYMBOL(funcallable_instance_tramp)
680         .long SIMPLE_FUN_HEADER_WIDETAG
681 CSYMBOL(funcallable_instance_tramp) = . + 1
682         .long CSYMBOL(funcallable_instance_tramp)
683         .long NIL
684         .long NIL
685         .long NIL
686         .long NIL
687         .long NIL
688         lwz reg_LEXENV,FUNCALLABLE_INSTANCE_FUNCTION_OFFSET(reg_LEXENV)
689         lwz reg_FDEFN,CLOSURE_FUN_OFFSET(reg_LEXENV)
690         addi reg_LIP,reg_FDEFN,SIMPLE_FUN_CODE_OFFSET
691         mtctr reg_LIP
692         bctr
693         SET_SIZE(funcallable_instance_tramp)
694 \f
695         /* The fun_end_breakpoint support here is considered by the
696         authors of the other $ARCH-assem.S files to be magic, and it
697         is.  It is a small fragment of code that is copied into a heap
698         code-object when needed, and contains an LRA object, code to
699         convert a single-value return to unknown-values format, and a
700         trap_FunEndBreakpoint. */
701         GFUNCDEF(fun_end_breakpoint_guts)
702         .globl CSYMBOL(fun_end_breakpoint_trap)
703         .globl CSYMBOL(fun_end_breakpoint_end)
704
705         /* Due to pointer verification in MAKE-LISP-OBJ, this must
706         include its header data (the offset from the start of the
707         code-object to the LRA).  The code-object header is five
708         words, there are two words of constants, and the instruction
709         space is doubleword-aligned, making an offset of eight.
710         This is header data for a widetag, so shift left eight bits
711         and add. */
712         .long RETURN_PC_HEADER_WIDETAG + 0x800
713
714         /* We are receiving unknown multiple values, thus must deal
715         with the single-value and multiple-value cases separately. */
716         b fun_end_breakpoint_multiple_values
717         nop
718
719         /* Compute the correct value for reg_CODE based on the LRA.
720         This is a "simple" matter of subtracting a constant from
721         reg_LRA (where the LRA is stored by the return sequence) to
722         obtain a tagged pointer to the enclosing code component.  Both
723         values are tagged OTHER_POINTER_LOWTAG, so we just have to
724         account for the eight words (see calculation for
725         RETURN_PC_HEADER_WIDETAG, above) between the two addresses.
726         Restoring reg_CODE doesn't appear to be strictly necessary
727         here, but let's observe the niceties.*/
728         addi reg_CODE, reg_LRA, -32
729
730         /* Multiple values are stored relative to reg_OCFP, which we
731         set to be the current top-of-stack. */
732         mr reg_OCFP, reg_CSP
733
734         /* Reserve a save location for the one value we have. */
735         addi reg_CSP, reg_CSP, 4
736
737         /* Record the number of values we have as a FIXNUM. */
738         li reg_NARGS, 4
739
740         /* Blank the remaining arg-passing registers. */
741         mr reg_A1, reg_NULL
742         mr reg_A2, reg_NULL
743         mr reg_A3, reg_NULL
744
745         /* And branch to our trap. */
746         b CSYMBOL(fun_end_breakpoint_trap)
747
748 fun_end_breakpoint_multiple_values:
749         /* Compute the correct value for reg_CODE.  See the
750         explanation for the single-value case, above. */
751         addi reg_CODE, reg_LRA, -32
752
753         /* The actual magic trap. */
754 CSYMBOL(fun_end_breakpoint_trap):
755         twllei  reg_ZERO, trap_FunEndBreakpoint
756
757         /* Finally, the debugger needs to know where the end of the
758         fun_end_breakpoint_guts are, so that it may calculate its size
759         in order to populate out a suitably-sized code object. */
760 CSYMBOL(fun_end_breakpoint_end):
761         SET_SIZE(fun_end_breakpoint_guts)
762 \f
763
764         GFUNCDEF(ppc_flush_cache_line)
765         dcbf 0,REG(3)
766         sync
767         icbi 0,REG(3)
768         sync
769         isync
770         blr
771         SET_SIZE(ppc_flush_cache_line)
772
773         GFUNCDEF(do_pending_interrupt)
774         twllei  reg_ZERO, trap_PendingInterrupt
775         blr
776 /* King Nato's branch has a nop here. Do we need this? */
777         SET_SIZE(do_pending_interrupt)
778         
779 #if defined LISP_FEATURE_GENCGC
780
781         GFUNCDEF(fpu_save)
782         stfd    FREG(1), 0(REG(3))
783         stfd    FREG(2), 8(REG(3))
784         stfd    FREG(3), 16(REG(3))
785         stfd    FREG(4), 24(REG(3))
786         stfd    FREG(5), 32(REG(3))
787         stfd    FREG(6), 40(REG(3))
788         stfd    FREG(7), 48(REG(3))
789         stfd    FREG(8), 56(REG(3))
790         stfd    FREG(9), 64(REG(3))
791         stfd    FREG(10), 72(REG(3))
792         stfd    FREG(11), 80(REG(3))
793         stfd    FREG(12), 88(REG(3))
794         stfd    FREG(13), 96(REG(3))
795         stfd    FREG(14), 104(REG(3))
796         stfd    FREG(15), 112(REG(3))
797         stfd    FREG(16), 120(REG(3))
798         stfd    FREG(17), 128(REG(3))
799         stfd    FREG(18), 136(REG(3))
800         stfd    FREG(19), 144(REG(3))
801         stfd    FREG(20), 152(REG(3))
802         stfd    FREG(21), 160(REG(3))
803         stfd    FREG(22), 168(REG(3))
804         stfd    FREG(23), 176(REG(3))
805         stfd    FREG(24), 184(REG(3))
806         stfd    FREG(25), 192(REG(3))
807         stfd    FREG(26), 200(REG(3))
808         stfd    FREG(27), 208(REG(3))
809         stfd    FREG(28), 216(REG(3))
810         stfd    FREG(29), 224(REG(3))
811         stfd    FREG(30), 232(REG(3))
812         stfd    FREG(31), 240(REG(3))
813         blr
814         SET_SIZE(fpu_save)
815         
816         GFUNCDEF(fpu_restore)
817         lfd     FREG(1), 0(REG(3))
818         lfd     FREG(2), 8(REG(3))
819         lfd     FREG(3), 16(REG(3))
820         lfd     FREG(4), 24(REG(3))
821         lfd     FREG(5), 32(REG(3))
822         lfd     FREG(6), 40(REG(3))
823         lfd     FREG(7), 48(REG(3))
824         lfd     FREG(8), 56(REG(3))
825         lfd     FREG(9), 64(REG(3))
826         lfd     FREG(10), 72(REG(3))
827         lfd     FREG(11), 80(REG(3))
828         lfd     FREG(12), 88(REG(3))
829         lfd     FREG(13), 96(REG(3))
830         lfd     FREG(14), 104(REG(3))
831         lfd     FREG(15), 112(REG(3))
832         lfd     FREG(16), 120(REG(3))
833         lfd     FREG(17), 128(REG(3))
834         lfd     FREG(18), 136(REG(3))
835         lfd     FREG(19), 144(REG(3))
836         lfd     FREG(20), 152(REG(3))
837         lfd     FREG(21), 160(REG(3))
838         lfd     FREG(22), 168(REG(3))
839         lfd     FREG(23), 176(REG(3))
840         lfd     FREG(24), 184(REG(3))
841         lfd     FREG(25), 192(REG(3))
842         lfd     FREG(26), 200(REG(3))
843         lfd     FREG(27), 208(REG(3))
844         lfd     FREG(28), 216(REG(3))
845         lfd     FREG(29), 224(REG(3))
846         lfd     FREG(30), 232(REG(3))
847         lfd     FREG(31), 240(REG(3))
848         blr
849         SET_SIZE(fpu_restore)
850         
851 #endif