/[cmucl]/src/lisp/ppc-assem.S
ViewVC logotype

Contents of /src/lisp/ppc-assem.S

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Sat Apr 16 02:03:22 2005 UTC (9 years ago) by rtoy
Branch: MAIN
CVS Tags: release-19b-pre1, release-19b-pre2, snapshot-2005-07, release-19b-base, snapshot-2005-06, snapshot-2005-05, snapshot-2005-08
Branch point for: release-19b-branch
Changes since 1.9: +22 -10 lines
New pseudo-atomic scheme that looks more like sparc where we use the
LSB of alloc-tn to denote pseudo-atomic interrupted.  We still need
the flag-gn (hardwired to NL3) as a temporary though because we need
somewhere to store the LSB of alloc-tn so we can trap if it's not
zero.

ppc/macros.lisp:
o New pseudo-atomic macro implementing the change.

lisp/ppc-arch.c:
o Update arch_set_pseudo_atomic_interrupted to set the LSB of
  alloc-tn.
o Catch the TWNEI reg_NL3, 0 instruction that denotes a deferred
  interrupt.

lisp/ppc-assem.S:
o Update assembly to code to set and test pseudo-atomic stuff like the
  pseudo-atomic macro does.
1 #define LANGUAGE_ASSEMBLY
2
3 #include "internals.h"
4 #include "lispregs.h"
5 #include "globals.h"
6
7 #if defined DARWIN
8 #define FUNCDEF(x) .text @ \
9 .align 3 @ \
10 _##x:
11 #define GFUNCDEF(x) .globl _/**/x @ \
12 FUNCDEF(x)
13 #else
14 #define FUNCDEF(x) .text ; \
15 .align 3 ; \
16 .type x,@function ; \
17 x:
18 #define GFUNCDEF(x) .globl _/**/x @ \
19 FUNCDEF(x)
20 #endif
21
22 #if defined DARWIN
23 #define SET_SIZE(x)
24 #else
25 #define SET_SIZE(x) .size x,.-x
26 #endif
27
28 /* Load a register from a global, using the register as an intermediary */
29 /* The register will be a fixnum for one instruction, so this is gc-safe */
30
31 #if defined DARWIN
32 #define load(reg,global) \
33 lis reg,ha16(global) @ \
34 lwz reg,lo16(global)(reg) ; Comment
35 #define store(reg,temp,global) \
36 lis temp,ha16(global) @\
37 stw reg,lo16(global)(temp) ; Comment
38 #else
39 #define load(reg,global) \
40 lis reg,global@ha; lwz reg,global@l(reg)
41 #define store(reg,temp,global) \
42 lis temp,global@ha; stw reg,global@l(temp)
43 #endif
44
45 #define FIRST_SAVE_FPR 14 /* lowest-numbered non-volatile FPR */
46 #define FIRST_SAVE_GPR 13 /* lowest-numbered non-volatile GPR */
47 #define NFPR_SAVE_BYTES(n) ((32-(n))*8)
48 #if defined DARWIN
49 #define NGPR_SAVE_BYTES(n) ((32-(n))*4)
50 #define FRAME_ARG_BYTES(n) (((((n)+6)*4)+15)&~15)
51 #else
52 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
53 #define FRAME_ARG_BYTES(n) (((((n)+2)*4)+15)&~15)
54 #endif
55
56 #if defined DARWIN
57 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
58 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words))
59 #define SAVE_FPR(n) stfd f##n,-8*(32- n)(r11)
60 #define SAVE_GPR(n) stw r##n,-4*(32- n)(r11)
61 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,8,1)
62 #else
63 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
64 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
65 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
66 #define SAVE_GPR(n) stw n,-4*(32-(n))(11)
67 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
68 #endif
69
70 #if defined DARWIN
71 #define RESTORE_FPR(n) lfd f##n,-8*(32- n)(r11)
72 #define RESTORE_GPR(n) lwz r##n,-4*(32- n)(r11)
73 #else
74 #define RESTORE_FPR(n) lfd f##n,-8*(32-(r##n))(r11)
75 #define RESTORE_GPR(n) lwz r##n,-4*(32-(r##n))(r11)
76 #endif
77 #define C_FULL_PROLOG \
78 nop @\
79 nop @ \
80 mfcr REG(0) @ \
81 stw REG(0),4(REG(1)) @ \
82 mflr REG(0) @ \
83 stw REG(0),8(REG(1)) @ \
84 mr REG(11),REG(1) @ \
85 stwu REG(1),-FULL_FRAME_SIZE(REG(1)) @ \
86 SAVE_FPR(14) @ \
87 SAVE_FPR(15) @ \
88 SAVE_FPR(16) @ \
89 SAVE_FPR(17) @ \
90 SAVE_FPR(18) @ \
91 SAVE_FPR(19) @ \
92 SAVE_FPR(20) @ \
93 SAVE_FPR(21) @ \
94 SAVE_FPR(22) @ \
95 SAVE_FPR(23) @ \
96 SAVE_FPR(24) @ \
97 SAVE_FPR(25) @ \
98 SAVE_FPR(26) @ \
99 SAVE_FPR(27) @ \
100 SAVE_FPR(28) @ \
101 SAVE_FPR(29) @ \
102 SAVE_FPR(30) @ \
103 SAVE_FPR(31) @ \
104 la REG(11),-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
105 SAVE_GPR(13) @ \
106 SAVE_GPR(14) @ \
107 SAVE_GPR(15) @ \
108 SAVE_GPR(16) @ \
109 SAVE_GPR(17) @ \
110 SAVE_GPR(18) @ \
111 SAVE_GPR(19) @ \
112 SAVE_GPR(20) @ \
113 SAVE_GPR(21) @ \
114 SAVE_GPR(22) @ \
115 SAVE_GPR(23) @ \
116 SAVE_GPR(24) @ \
117 SAVE_GPR(25) @ \
118 SAVE_GPR(26) @ \
119 SAVE_GPR(27) @ \
120 SAVE_GPR(28) @ \
121 SAVE_GPR(29) @ \
122 SAVE_GPR(30) @ \
123 SAVE_GPR(31)
124
125
126 #define C_FULL_EPILOG \
127 la REG(11),FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(1)) @ \
128 RESTORE_GPR(13) @ \
129 RESTORE_GPR(14) @ \
130 RESTORE_GPR(15) @ \
131 RESTORE_GPR(16) @ \
132 RESTORE_GPR(17) @ \
133 RESTORE_GPR(18) @ \
134 RESTORE_GPR(19) @ \
135 RESTORE_GPR(20) @ \
136 RESTORE_GPR(21) @ \
137 RESTORE_GPR(22) @ \
138 RESTORE_GPR(23) @ \
139 RESTORE_GPR(24) @ \
140 RESTORE_GPR(25) @ \
141 RESTORE_GPR(26) @ \
142 RESTORE_GPR(27) @ \
143 RESTORE_GPR(28) @ \
144 RESTORE_GPR(29) @ \
145 RESTORE_GPR(30) @ \
146 RESTORE_GPR(31) @ \
147 la REG(11),NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
148 RESTORE_FPR(14) @ \
149 RESTORE_FPR(15) @ \
150 RESTORE_FPR(16) @ \
151 RESTORE_FPR(17) @ \
152 RESTORE_FPR(18) @ \
153 RESTORE_FPR(19) @ \
154 RESTORE_FPR(20) @ \
155 RESTORE_FPR(21) @ \
156 RESTORE_FPR(22) @ \
157 RESTORE_FPR(23) @ \
158 RESTORE_FPR(24) @ \
159 RESTORE_FPR(25) @ \
160 RESTORE_FPR(26) @ \
161 RESTORE_FPR(27) @ \
162 RESTORE_FPR(28) @ \
163 RESTORE_FPR(29) @ \
164 RESTORE_FPR(30) @ \
165 RESTORE_FPR(31) @ \
166 lwz REG(1),0(REG(1)) @ \
167 lwz REG(0),4(REG(1)) @ \
168 mtcr REG(0) @ \
169 lwz REG(0),8(REG(1)) @ \
170 mtlr REG(0) @ \
171
172
173
174
175 .text
176
177 /*
178 * Function to transfer control into lisp. The lisp object to invoke is
179 * passed as the first argument, which puts it in NL0
180 */
181
182 GFUNCDEF(call_into_lisp)
183 C_FULL_PROLOG
184 /* store(reg_POLL,11,saver2) */
185 /* Initialize tagged registers */
186 li reg_ZERO,0
187 li reg_CODE,0
188 li reg_CNAME,0
189 li reg_LEXENV,0
190 li reg_FDEFN,0
191 li reg_OCFP,0
192 li reg_LRA,0
193 li reg_A0,0
194 li reg_A1,0
195 li reg_A2,0
196 li reg_A3,0
197 li reg_L0,0
198 li reg_L1,0
199 li reg_L2,0
200 li reg_LIP,0
201 lis reg_NULL,hi16(NIL)
202 ori reg_NULL,reg_NULL,lo16(NIL)
203
204 /* Turn on pseudo-atomic */
205
206 #if 0
207 li reg_NL3,-4
208 #endif
209 li reg_ALLOC,4
210 store(reg_ZERO,reg_NL4,_foreign_function_call_active)
211 load(reg_NL4,_current_dynamic_space_free_pointer)
212 add reg_ALLOC,reg_ALLOC,reg_NL4
213 load(reg_BSP,_current_binding_stack_pointer)
214 load(reg_CSP,_current_control_stack_pointer)
215 load(reg_OCFP,_current_control_frame_pointer)
216
217 /* No longer atomic, and check for interrupt */
218 andi. reg_NL3, reg_ALLOC, 1
219 subi reg_ALLOC,reg_ALLOC,4
220 twnei reg_NL3, 0
221
222 /* Pass in the arguments */
223
224 mr reg_CFP,reg_NL1
225 mr reg_LEXENV,reg_NL0
226 lwz reg_A0,0(reg_CFP)
227 lwz reg_A1,4(reg_CFP)
228 lwz reg_A2,8(reg_CFP)
229 lwz reg_A3,12(reg_CFP)
230
231 /* Calculate LRA */
232 lis reg_LRA,ha16(lra)
233 addi reg_LRA,reg_LRA,lo16(lra)
234 addi reg_LRA,reg_LRA,type_OtherPointer
235
236 /* Function is an indirect closure */
237 lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
238 /*
239 * The 6 is vm:function-code-offset, the 4 is
240 * the number of bytes in a lispobj.
241 */
242 addi reg_LIP,reg_CODE,6*4-type_FunctionPointer
243 mtctr reg_LIP
244 slwi reg_NARGS,reg_NL2,2
245 bctr
246 .align 3
247 lra:
248 .long type_ReturnPcHeader
249
250 /* Blow off any extra values. */
251 mr reg_CSP,reg_OCFP
252 nop
253
254 /* Return the one value. */
255
256 mr REG(3),reg_A0
257
258 /* Turn on pseudo-atomic */
259 li reg_NL3,-4
260 la reg_ALLOC,4(reg_ALLOC)
261
262 /* Store lisp state */
263 clrrwi reg_NL1,reg_ALLOC,3
264 store(reg_NL1,reg_NL2,_current_dynamic_space_free_pointer)
265 /* store(reg_POLL,reg_NL2,poll_flag) */
266 /* load(reg_NL2,current_thread) */
267 store(reg_BSP,reg_NL2,_current_binding_stack_pointer)
268 store(reg_CSP,reg_NL2,_current_control_stack_pointer)
269 store(reg_CFP,reg_NL2,_current_control_frame_pointer)
270 /* load(reg_POLL,saver2) */
271
272 /* No longer in Lisp. */
273 store(reg_NL1,reg_NL2,_foreign_function_call_active)
274
275 /* Check for interrupt */
276 andi. reg_NL3, reg_ALLOC, 1
277 subi reg_ALLOC, reg_ALLOC, 4
278 twnei reg_NL3,0
279
280 /* Back to C */
281 C_FULL_EPILOG
282 blr
283 SET_SIZE(call_into_lisp)
284
285
286 GFUNCDEF(call_into_c)
287 /* We're kind of low on unboxed, non-dedicated registers here:
288 most of the unboxed registers may have outgoing C args in them.
289 CFUNC is going to have to go in the CTR in a moment, anyway
290 so we'll free it up soon. reg_NFP is preserved by lisp if it
291 has a meaningful value in it, so we can use it. reg_NARGS is
292 free when it's not holding a copy of the "real" reg_NL3, which
293 gets tied up by the pseudo-atomic mechanism */
294 mtctr reg_CFUNC
295 mflr reg_LIP
296 /* Build a lisp stack frame */
297 mr reg_OCFP,reg_CFP
298 mr reg_CFP,reg_CSP
299 la reg_CSP,32(reg_CSP)
300 stw reg_OCFP,0(reg_CFP)
301 stw reg_CODE,8(reg_CFP)
302 /* The pseudo-atomic mechanism wants to use reg_NL3, but that
303 may be an outgoing C argument. Copy reg_NL3 to something that's
304 unboxed and -not- one of the C argument registers */
305 mr reg_NARGS,reg_NL3
306
307 /* Turn on pseudo-atomic */
308 #if 0
309 li reg_NL3,-4
310 #endif
311 la reg_ALLOC,4(reg_ALLOC)
312
313 /* Convert the return address to an offset and save it on the stack. */
314 sub reg_NFP,reg_LIP,reg_CODE
315 la reg_NFP,type_OtherPointer(reg_NFP)
316 stw reg_NFP,4(reg_CFP)
317
318 /* Store Lisp state */
319 clrrwi reg_NFP,reg_ALLOC,3
320 store(reg_NFP,reg_CFUNC,_current_dynamic_space_free_pointer)
321 /* load(reg_CFUNC,current_thread) */
322
323 store(reg_BSP,reg_CFUNC,_current_binding_stack_pointer)
324 store(reg_CSP,reg_CFUNC,_current_control_stack_pointer)
325 store(reg_CFP,reg_CFUNC,_current_control_frame_pointer)
326
327 /* No longer in Lisp */
328 store(reg_CSP,reg_CFUNC,_foreign_function_call_active)
329 /* load(reg_POLL,saver2) */
330 /* Disable pseudo-atomic; check pending interrupt */
331 andi. reg_NL3, reg_ALLOC, 1
332 subi reg_ALLOC, reg_ALLOC, 4
333 twnei reg_NL3, 0
334
335 mr reg_NL3,reg_NARGS
336
337 /* PowerOpen (i.e. OS X) requires the callee address in r12
338 (a.k.a. CFUNC), so move it back there, too. */
339 mfctr reg_CFUNC
340 /* Into C we go. */
341 bctrl
342
343 /* Re-establish NIL */
344 lis reg_NULL,hi16(NIL)
345 ori reg_NULL,reg_NULL,lo16(NIL)
346 /* And reg_ZERO */
347 li reg_ZERO,0
348
349 /* If we GC'ed during the FF code (as the result of a callback ?)
350 the tagged lisp registers may now contain garbage (since the
351 registers were saved by C and not seen by the GC.) Put something
352 harmless in all such registers before allowing an interrupt */
353 li reg_CODE,0
354 li reg_CNAME,0
355 li reg_LEXENV,0
356 /* reg_OCFP was pointing to a control stack frame & was preserved by C */
357 li reg_LRA,0
358 li reg_A0,0
359 li reg_A1,0
360 li reg_A2,0
361 li reg_A3,0
362 li reg_L0,0
363 li reg_L1,0
364 li reg_L2,0
365 li reg_LIP,0
366
367 /* Atomic ... */
368 #if 0
369 li reg_NL3,-4
370 #endif
371 li reg_ALLOC,4
372
373 /* No long in foreign function call. */
374 store(reg_ZERO,reg_NL2,_foreign_function_call_active)
375
376 /* The free pointer may have moved */
377 load(reg_NL4,_current_dynamic_space_free_pointer)
378 add reg_ALLOC,reg_ALLOC,reg_NL4
379
380 /* The BSP wasn't preserved by C, so load it */
381 load(reg_BSP,_current_binding_stack_pointer)
382
383 /* Other lisp stack/frame pointers were preserved by C.
384 I can't imagine why they'd have moved */
385
386 /* Get the return address back. */
387 lwz reg_LIP,4(reg_CFP)
388 lwz reg_CODE,8(reg_CFP)
389 add reg_LIP,reg_CODE,reg_LIP
390 la reg_LIP,-type_OtherPointer(reg_LIP)
391
392 /* No longer atomic */
393 andi. reg_NL3, reg_ALLOC, 1
394 subi reg_ALLOC, reg_ALLOC, 4
395 twnei reg_NL3, 0
396
397 mtlr reg_LIP
398
399 /* Reset the lisp stack. */
400 mr reg_CSP,reg_CFP
401 mr reg_CFP,reg_OCFP
402
403 /* And back into Lisp. */
404 blr
405
406 SET_SIZE(call_into_c)
407
408 GFUNCDEF(xundefined_tramp)
409 .globl _undefined_tramp
410 .byte 0,0,0,type_FunctionHeader /* Header */
411
412 .long _undefined_tramp /* self slot */
413 .long NIL /* next slot */
414 .long NIL /* name slot */
415 .long NIL /* arglist slot */
416 .long NIL /* type slot */
417 _undefined_tramp:
418 twllei reg_ZERO,trap_Cerror
419 /* Number of argument bytes */
420 .byte 4
421 .byte UNDEFINED_SYMBOL_ERROR
422 /* Escape to create 16bit number from following two bytes,
423 in little-endian order */
424 .byte 254
425 .byte SC_OFFSET_LO(sc_DescriptorReg, reg_FDEFN_NUM)
426 .byte SC_OFFSET_HI(sc_DescriptorReg, reg_FDEFN_NUM)
427 /*
428 .byte sc_DescriptorReg+0x40
429 .byte 1
430 */
431 .align 2
432 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
433 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
434 mtctr reg_LIP
435 bctr
436
437 mr reg_CSP, reg_CFP
438 b 1b
439
440 SET_SIZE(xundefined_tramp)
441
442 GFUNCDEF(xclosure_tramp)
443 .globl _closure_tramp
444 .byte 0,0,0,type_FunctionHeader /* Header */
445 .long _closure_tramp
446 .long NIL
447 .long NIL
448 .long NIL
449 .long NIL
450 _closure_tramp:
451 lwz reg_LEXENV,FDEFN_FUNCTION_OFFSET(reg_FDEFN)
452 lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
453 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
454 mtctr reg_LIP
455 bctr
456
457 SET_SIZE(xclosure_tramp)
458
459 /*
460 * Function-end breakpoint magic. See MAKE-BOGUS-LRA in
461 * code/debug-int.lisp.
462 */
463 .text
464 .align 3
465 .globl _function_end_breakpoint_guts
466 _function_end_breakpoint_guts:
467 .long type_ReturnPcHeader
468 b 1f
469 /*
470 * Are these really necessary? I'm cargo-culting from the sparc port
471 */
472 mr reg_OCFP, reg_CSP
473 addi reg_CSP, reg_CSP, 4
474 li reg_NARGS, 4
475 mr reg_A1, reg_NULL
476 mr reg_A2, reg_NULL
477 mr reg_A3, reg_NULL
478 1:
479 .globl _function_end_breakpoint_trap
480 _function_end_breakpoint_trap:
481 twllei reg_ZERO, trap_FunctionEndBreakpoint
482 b 1b
483 .globl _function_end_breakpoint_end
484 _function_end_breakpoint_end:
485
486
487 GFUNCDEF(ppc_flush_cache_line)
488 dcbf 0,REG(3)
489 sync
490 icbi 0,REG(3)
491 sync
492 isync
493 blr
494 SET_SIZE(ppc_flush_cache_line)
495
496 #ifdef LINKAGE_TABLE
497 /*
498 * Call into C code to resolve a linkage entry.
499 *
500 * We get here by Lisp calling call_into_c with an address of the
501 * desired function which is contained in the register reg_CFUNC (aka
502 * %i4, aka %r28). This is the address of the entry in the linkage
503 * table, which is what we need to figure out what function we really
504 * wanted.
505 *
506 * Note that because we get here from call_into_c, all necessary live
507 * registers have been saved, including FP registers. Hence, no need
508 * to save them.
509 */
510 .globl _lazy_resolve_linkage
511 GFUNCDEF(resolve_linkage_tramp)
512 /*
513 * We need to call lazy_resolve_linkage. reg_A0 (= r24)
514 * (see ppc-arch.c) contains the address of the linkage entry.
515 */
516 /*
517 * Need to save all parameter regs to the stack because we
518 * need them for later. We save the FP registers too. (Do
519 * we really need to? lazy_resolve_linkage shouldn't call
520 * anything that uses FP registers. It's safe to do so.)
521 */
522 subi r1, r1, 8*4+8+8*13
523 stfd f1, 0(r1)
524 stfd f2, 8(r1)
525 stfd f3, 16(r1)
526 stfd f4, 24(r1)
527 stfd f5, 32(r1)
528 stfd f6, 40(r1)
529 stfd f7, 48(r1)
530 stfd f8, 56(r1)
531 stfd f9, 64(r1)
532 stfd f10, 72(r1)
533 stfd f11, 80(r1)
534 stfd f12, 88(r1)
535 stfd f13, 96(r1)
536
537 stw r3, 104+0(r1)
538 stw r4, 104+4(r1)
539 stw r5, 104+8(r1)
540 stw r6, 104+12(r1)
541 stw r7, 104+16(r1)
542 stw r8, 104+20(r1)
543 stw r9, 104+24(r1)
544 stw r10, 104+28(r1)
545
546
547 mr reg_NL0, reg_A0
548
549 stwu r1, (-(24+4))(r1)
550 /*
551 * At this point reg_NIL should be available to us.
552 * Call lazy_resolve_linkage to figure out the real function address.
553 */
554 lis reg_NULL, hi16(_lazy_resolve_linkage)
555 ori reg_NULL, reg_NULL, lo16(_lazy_resolve_linkage)
556 mtctr reg_NULL
557 mflr reg_CODE
558 bctrl
559
560 addi r1,r1,24+4
561
562 /*
563 * The desired function is in r3 (NL0), so save it
564 * and restore the real arg parameters
565 */
566
567 mtctr reg_NL0
568 lfd f1, 0(r1)
569 lfd f2, 8(r1)
570 lfd f3, 16(r1)
571 lfd f4, 24(r1)
572 lfd f5, 32(r1)
573 lfd f6, 40(r1)
574 lfd f7, 48(r1)
575 lfd f8, 56(r1)
576 lfd f9, 64(r1)
577 lfd f10, 72(r1)
578 lfd f11, 80(r1)
579 lfd f12, 88(r1)
580 lfd f13, 96(r1)
581
582 lwz r3, 104+0(r1)
583 lwz r4, 104+4(r1)
584 lwz r5, 104+8(r1)
585 lwz r6, 104+12(r1)
586 lwz r7, 104+16(r1)
587 lwz r8, 104+20(r1)
588 lwz r9, 104+24(r1)
589 lwz r10, 104+28(r1)
590
591 addi r1,r1,8*4+8+8*13
592
593 /*
594 * Got it, so we can now jump directly to the desired function.
595 * reg_NL0 contains the result. Restore the stack and go!
596 */
597
598 mtlr reg_CODE
599
600 /* Back to C */
601 /* mtlr reg_CODE*/
602 bctr
603
604 SET_SIZE(resolve_linkage_tramp)
605
606
607 /*
608 * When we get called, r3 (reg_NL0) contains the address of the
609 * data_vector object which is a string naming the bad symbol.
610 */
611 GFUNCDEF(undefined_foreign_symbol_trap)
612
613 /*
614 Need to restore all the global registers with the Lisp values that
615 were saved away in call_into_c. (This routine is only called from
616 os_link_one_symbol, which is called from resolve_linkage_tramp, which
617 is called from call_into_c.)
618
619 The global registers are volatile across function calls, so who
620 knows what values have been they contain now!
621
622 */
623
624 load(reg_ALLOC, _current_dynamic_space_free_pointer)
625 load(reg_BSP, _current_binding_stack_pointer)
626 load(reg_CSP, _current_control_stack_pointer)
627 load(reg_CFP, _current_control_frame_pointer)
628
629 lis reg_NULL,hi16(NIL)
630 ori reg_NULL,reg_NULL,lo16(NIL)
631 /* And reg_ZERO */
632 li reg_ZERO,0
633
634 mr reg_NL0, reg_A0
635 twllei reg_ZERO, trap_Error
636 .byte 4 /* Number of argument bytes */
637 .byte UNDEFINED_FOREIGN_SYMBOL_ERROR
638 /* Escape to create 16bit number from following two bytes, in
639 little-endian order */
640 .byte 254
641 .byte SC_OFFSET_LO(sc_DescriptorReg, reg_A0_NUM)
642 .byte SC_OFFSET_HI(sc_DescriptorReg, reg_A0_NUM)
643 .align 4
644
645 #endif

  ViewVC Help
Powered by ViewVC 1.1.5