3b6e53f374d03bdd8db2be6239080e1b29ca632f
[sbcl.git] / 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 #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
293
294 #ifdef LISP_FEATURE_SB_SAFEPOINT
295 /* OAOOM because we don't have the C headers here. */
296 # define THREAD_CSP_PAGE_SIZE 4096
297
298 /* the CSP page sits right before the thread */
299 # define THREAD_SAVED_CSP_OFFSET (-THREAD_CSP_PAGE_SIZE)
300 #endif
301
302         .text
303
304 /*
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  */
308
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
321
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
332
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 */
365
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
384
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
389
390         /* Pass in the arguments */
391
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)
398
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
408
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 
419
420         /* Blow off any extra values. */
421         mr reg_CSP,reg_OCFP
422         nop
423
424         /* Return the one value. */
425
426         mr REG(3),reg_A0
427
428         /* Turn on  pseudo-atomic */
429         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
430
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)
436
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) */
449
450         /* No longer in Lisp. */
451         store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
452 #endif
453
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)
463 \f
464
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
485
486         /* Turn on pseudo-atomic */
487         la reg_ALLOC,flag_PseudoAtomic(reg_ALLOC)
488
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)
493
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)
499
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))
511
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
520
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
525
526         mr reg_NL3,reg_NARGS
527
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
535
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
546
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_CODE,0
552         li reg_CNAME,0
553         li reg_LEXENV,0
554         /* reg_OCFP was pointing to a control stack frame & was preserved by C */
555         li reg_LRA,0
556         li reg_A0,0
557         li reg_A1,0
558         li reg_A2,0
559         li reg_A3,0
560         li reg_L0,0
561         li reg_L1,0
562 #if !defined(LISP_FEATURE_SB_THREAD)
563         /* reg_L2 is our TLS block pointer. */
564         li reg_L2,0
565 #endif
566         li reg_LIP,0
567
568 # ifdef LISP_FEATURE_SB_SAFEPOINT
569         /* No longer OK to run GC except at safepoints. */
570         stw reg_ZERO,THREAD_SAVED_CSP_OFFSET(reg_THREAD)
571 # endif
572
573         /* Atomic ... */
574         li reg_ALLOC,flag_PseudoAtomic
575
576 #if defined(LISP_FEATURE_SB_THREAD)
577         /* No longer in foreign function call. */
578         stw reg_ZERO,THREAD_FOREIGN_FUNCTION_CALL_ACTIVE_OFFSET(reg_THREAD)
579
580         /* The binding stack pointer isn't preserved by C. */
581         lwz reg_BSP,THREAD_BINDING_STACK_POINTER_OFFSET(reg_THREAD)
582 #else
583         /* No long in foreign function call. */
584         store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
585
586         /* The free pointer may have moved */
587         /* (moved below) */
588
589         /* The BSP wasn't preserved by C, so load it */
590         load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
591 #endif
592         /* This is important for CHENEYGC: It's the allocation
593          * pointer.  It's also important for ROOM on GENCGC:
594          * It's a pointer to the end of dynamic space, used to
595          * determine where to stop in MAP-ALLOCATED-OBJECTS. */
596         load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
597         add reg_ALLOC,reg_ALLOC,reg_NL4
598
599         /* Other lisp stack/frame pointers were preserved by C.
600         I can't imagine why they'd have moved */
601
602         /* Get the return address back. */
603         lwz reg_LIP,4(reg_CFP)
604         lwz reg_CODE,8(reg_CFP)
605         add reg_LIP,reg_CODE,reg_LIP
606         la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
607
608         /* No longer atomic */
609         subi reg_ALLOC, reg_ALLOC, flag_PseudoAtomic
610         andi. reg_NL3, reg_ALLOC, flag_PseudoAtomicInterrupted
611         twnei reg_NL3, 0
612
613         mtlr reg_LIP
614         
615         /* Reset the lisp stack. */
616         mr reg_CSP,reg_CFP
617         mr reg_CFP,reg_OCFP
618         
619         /* And back into Lisp. */
620         blr
621
622         SET_SIZE(call_into_c)
623
624         GFUNCDEF(xundefined_tramp)
625         .globl CSYMBOL(undefined_tramp)
626         .long   SIMPLE_FUN_HEADER_WIDETAG                         /* header */
627         .long   CSYMBOL(undefined_tramp) - SIMPLE_FUN_CODE_OFFSET /* self */
628         .long   NIL                                               /* next */
629         .long   NIL                                               /* name */
630         .long   NIL                                               /* arglist */
631         .long   NIL                                               /* type */
632         .long   NIL                                               /* xref */
633 CSYMBOL(undefined_tramp):
634         /* Point reg_CODE to the header and tag it as function, since
635            the debugger regards a function pointer in reg_CODE which
636            doesn't point to a code object as undefined function.  */
637         /* We are given that reg_LIP points to undefined_tramp by
638            virtue of the calling convention.  */
639         addi reg_CODE,reg_LIP,-SIMPLE_FUN_CODE_OFFSET
640
641         /* If we are called with stack arguments (or in a tail-call
642            scenario), we end up with an allocated stack frame, but the
643            frame link information is uninitialized.  Fix things by
644            allocating and initializing our stack frame "properly". */
645         cmpwi cr0,reg_NARGS,16
646         bt gt,1f
647         addi reg_CSP,reg_CFP,16
648         b 2f
649 1:      add reg_CSP,reg_CFP,reg_NARGS
650 2:      stw reg_OCFP,0(reg_CFP)
651         stw reg_LRA,4(reg_CFP)
652
653         /* Now that the preliminaries are dealt with, actually trap. */
654         twllei reg_ZERO,trap_Cerror
655         .byte 4
656         .byte UNDEFINED_FUN_ERROR
657         .byte 254, sc_DescriptorReg+0x80, 0x2 /* 280 */
658         /* This stuff is for the continuable error.  I don't think there's
659          * any support for it on the lisp side */
660         .align 2
661 1:      lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
662         la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
663         mtctr reg_LIP
664         bctr
665         mr reg_CSP,reg_CFP
666         b 1b
667
668         SET_SIZE(xundefined_tramp)
669
670         GFUNCDEF(xclosure_tramp)
671         .globl CSYMBOL(closure_tramp)
672 CSYMBOL(closure_tramp):
673         lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
674         lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
675         la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
676         mtctr reg_LIP
677         bctr
678
679         SET_SIZE(xclosure_tramp)
680
681         GFUNCDEF(xfuncallable_instance_tramp)
682         .globl CSYMBOL(funcallable_instance_tramp)
683         .long SIMPLE_FUN_HEADER_WIDETAG
684 CSYMBOL(funcallable_instance_tramp) = . + 1
685         .long CSYMBOL(funcallable_instance_tramp)
686         .long NIL
687         .long NIL
688         .long NIL
689         .long NIL
690         .long NIL
691         lwz reg_LEXENV,FUNCALLABLE_INSTANCE_FUNCTION_OFFSET(reg_LEXENV)
692         lwz reg_FDEFN,CLOSURE_FUN_OFFSET(reg_LEXENV)
693         addi reg_LIP,reg_FDEFN,SIMPLE_FUN_CODE_OFFSET
694         mtctr reg_LIP
695         bctr
696         SET_SIZE(funcallable_instance_tramp)
697 \f
698         /* The fun_end_breakpoint support here is considered by the
699         authors of the other $ARCH-assem.S files to be magic, and it
700         is.  It is a small fragment of code that is copied into a heap
701         code-object when needed, and contains an LRA object, code to
702         convert a single-value return to unknown-values format, and a
703         trap_FunEndBreakpoint. */
704         GFUNCDEF(fun_end_breakpoint_guts)
705         .globl CSYMBOL(fun_end_breakpoint_trap)
706         .globl CSYMBOL(fun_end_breakpoint_end)
707
708         /* Due to pointer verification in MAKE-LISP-OBJ, this must
709         include its header data (the offset from the start of the
710         code-object to the LRA).  The code-object header is five
711         words, there are two words of constants, and the instruction
712         space is doubleword-aligned, making an offset of eight.
713         This is header data for a widetag, so shift left eight bits
714         and add. */
715         .long RETURN_PC_HEADER_WIDETAG + 0x800
716
717         /* We are receiving unknown multiple values, thus must deal
718         with the single-value and multiple-value cases separately. */
719         b fun_end_breakpoint_multiple_values
720         nop
721
722         /* Compute the correct value for reg_CODE based on the LRA.
723         This is a "simple" matter of subtracting a constant from
724         reg_LRA (where the LRA is stored by the return sequence) to
725         obtain a tagged pointer to the enclosing code component.  Both
726         values are tagged OTHER_POINTER_LOWTAG, so we just have to
727         account for the eight words (see calculation for
728         RETURN_PC_HEADER_WIDETAG, above) between the two addresses.
729         Restoring reg_CODE doesn't appear to be strictly necessary
730         here, but let's observe the niceties.*/
731         addi reg_CODE, reg_LRA, -32
732
733         /* Multiple values are stored relative to reg_OCFP, which we
734         set to be the current top-of-stack. */
735         mr reg_OCFP, reg_CSP
736
737         /* Reserve a save location for the one value we have. */
738         addi reg_CSP, reg_CSP, 4
739
740         /* Record the number of values we have as a FIXNUM. */
741         li reg_NARGS, 4
742
743         /* Blank the remaining arg-passing registers. */
744         mr reg_A1, reg_NULL
745         mr reg_A2, reg_NULL
746         mr reg_A3, reg_NULL
747
748         /* And branch to our trap. */
749         b CSYMBOL(fun_end_breakpoint_trap)
750
751 fun_end_breakpoint_multiple_values:
752         /* Compute the correct value for reg_CODE.  See the
753         explanation for the single-value case, above. */
754         addi reg_CODE, reg_LRA, -32
755
756         /* The actual magic trap. */
757 CSYMBOL(fun_end_breakpoint_trap):
758         twllei  reg_ZERO, trap_FunEndBreakpoint
759
760         /* Finally, the debugger needs to know where the end of the
761         fun_end_breakpoint_guts are, so that it may calculate its size
762         in order to populate out a suitably-sized code object. */
763 CSYMBOL(fun_end_breakpoint_end):
764         SET_SIZE(fun_end_breakpoint_guts)
765 \f
766
767         GFUNCDEF(ppc_flush_cache_line)
768         dcbf 0,REG(3)
769         sync
770         icbi 0,REG(3)
771         sync
772         isync
773         blr
774         SET_SIZE(ppc_flush_cache_line)
775
776         GFUNCDEF(do_pending_interrupt)
777         twllei  reg_ZERO, trap_PendingInterrupt
778         blr
779 /* King Nato's branch has a nop here. Do we need this? */
780         SET_SIZE(do_pending_interrupt)
781         
782 #if defined LISP_FEATURE_GENCGC
783
784         GFUNCDEF(fpu_save)
785         stfd    FREG(1), 0(REG(3))
786         stfd    FREG(2), 8(REG(3))
787         stfd    FREG(3), 16(REG(3))
788         stfd    FREG(4), 24(REG(3))
789         stfd    FREG(5), 32(REG(3))
790         stfd    FREG(6), 40(REG(3))
791         stfd    FREG(7), 48(REG(3))
792         stfd    FREG(8), 56(REG(3))
793         stfd    FREG(9), 64(REG(3))
794         stfd    FREG(10), 72(REG(3))
795         stfd    FREG(11), 80(REG(3))
796         stfd    FREG(12), 88(REG(3))
797         stfd    FREG(13), 96(REG(3))
798         stfd    FREG(14), 104(REG(3))
799         stfd    FREG(15), 112(REG(3))
800         stfd    FREG(16), 120(REG(3))
801         stfd    FREG(17), 128(REG(3))
802         stfd    FREG(18), 136(REG(3))
803         stfd    FREG(19), 144(REG(3))
804         stfd    FREG(20), 152(REG(3))
805         stfd    FREG(21), 160(REG(3))
806         stfd    FREG(22), 168(REG(3))
807         stfd    FREG(23), 176(REG(3))
808         stfd    FREG(24), 184(REG(3))
809         stfd    FREG(25), 192(REG(3))
810         stfd    FREG(26), 200(REG(3))
811         stfd    FREG(27), 208(REG(3))
812         stfd    FREG(28), 216(REG(3))
813         stfd    FREG(29), 224(REG(3))
814         stfd    FREG(30), 232(REG(3))
815         stfd    FREG(31), 240(REG(3))
816         blr
817         SET_SIZE(fpu_save)
818         
819         GFUNCDEF(fpu_restore)
820         lfd     FREG(1), 0(REG(3))
821         lfd     FREG(2), 8(REG(3))
822         lfd     FREG(3), 16(REG(3))
823         lfd     FREG(4), 24(REG(3))
824         lfd     FREG(5), 32(REG(3))
825         lfd     FREG(6), 40(REG(3))
826         lfd     FREG(7), 48(REG(3))
827         lfd     FREG(8), 56(REG(3))
828         lfd     FREG(9), 64(REG(3))
829         lfd     FREG(10), 72(REG(3))
830         lfd     FREG(11), 80(REG(3))
831         lfd     FREG(12), 88(REG(3))
832         lfd     FREG(13), 96(REG(3))
833         lfd     FREG(14), 104(REG(3))
834         lfd     FREG(15), 112(REG(3))
835         lfd     FREG(16), 120(REG(3))
836         lfd     FREG(17), 128(REG(3))
837         lfd     FREG(18), 136(REG(3))
838         lfd     FREG(19), 144(REG(3))
839         lfd     FREG(20), 152(REG(3))
840         lfd     FREG(21), 160(REG(3))
841         lfd     FREG(22), 168(REG(3))
842         lfd     FREG(23), 176(REG(3))
843         lfd     FREG(24), 184(REG(3))
844         lfd     FREG(25), 192(REG(3))
845         lfd     FREG(26), 200(REG(3))
846         lfd     FREG(27), 208(REG(3))
847         lfd     FREG(28), 216(REG(3))
848         lfd     FREG(29), 224(REG(3))
849         lfd     FREG(30), 232(REG(3))
850         lfd     FREG(31), 240(REG(3))
851         blr
852         SET_SIZE(fpu_restore)
853         
854 #endif