/[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.5 - (show annotations)
Sun Feb 6 19:43:15 2005 UTC (9 years, 2 months ago) by rtoy
Branch: MAIN
Changes since 1.4: +117 -0 lines
Initial support for linkage-tables on PPC/Darwin.  This is a
relatively straightforward port of the sparc version of
linkage-tables.  Some refinements are probably still needed, as well
as some testing.

Use boot-2005-02-ppc-linkage.lisp to bootstrap this change from the
2005-02 snapshot.

* code/ppc-vm.lisp
  o Add appropriate FOREIGN-SYMBOL-ADDRESS-AUX and FIND-FOREIGN-SYMBOL
    functions for linkage-table.

* compiler/generic/new-genesis.lisp
  o Basically do the same as the sparc port for linkage-tables.
  o need to extern-alien-name on the cold linkages since they C names
    depend on the backend conventions.

* compiler/ppc/alloc.lisp
  o Load "undefined_tramp" appropriately for linkage-tables.

* compiler/ppc/c-call.lisp
  o Define new vops (FOREIGN-SYMBOL-CODE-ADDRESS,
    FOREIGN-SYMBOL-DATA-ADDRESS) for linkage-tables so we can access
    correctly.

* compiler/ppc/cell.lisp
  o Load "closure_tramp" appropriately for linkage-tables
  o Load "undefined_tramp" appropriately for linkage-tables

* compiler/ppc/parms.lisp
  o Put the foreign linkage space start at the end of the static space
    to make it easier to bootstrap.  (We need already mapped memory.)
    We can move this later.
  o Correct TARGET-FOREIGN-LINKAGE-ENTRY-SIZE.
  o Add new static-symbol *linkage-table-data*
  o While were at it, add SPARE-9 and SPARE-0 static symbols so we
    have 10 spares.

* lisp/Config.ppc_darwin
  o Add -DLINKAGE_TABLE to CFLAGS/ASFLAGS if we have linkage-table
    support.

* lisp/Darwin-os.c
  o Add os_dlsym to support linkage-tables.  (This nees a little
    refactoring because we just copied the #defines for dlopen modes.)

* lisp/os-common.c
  o The checking of the linkage tables that is done for sparc almost
    works for ppc, but not quite.  Implement one for ppc.

* lisp/ppc-arch.c
  o Add PPC version of arch_make_jump_entry, arch_make_linkage_entry,
    arch_linkage_entry.

* lisp/ppc-assem.S
  o Add lazy_resolve_linkage to support linkage-tables.  This needs
    some more work.
  o Add undefined_foreign_symbol_trap.  This probably needs work, and
    definitely needs testing.

* lisp/ppc-validate.h
  o Define the start of the linkage space and size.
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 li reg_NL3,-4
207 li reg_ALLOC,4
208 store(reg_ZERO,reg_NL4,_foreign_function_call_active)
209 load(reg_NL4,_current_dynamic_space_free_pointer)
210 add reg_ALLOC,reg_ALLOC,reg_NL4
211 load(reg_BSP,_current_binding_stack_pointer)
212 load(reg_CSP,_current_control_stack_pointer)
213 load(reg_OCFP,_current_control_frame_pointer)
214
215 /* No longer atomic, and check for interrupt */
216 add reg_ALLOC,reg_ALLOC,reg_NL3
217 twlti reg_ALLOC,0
218
219 /* Pass in the arguments */
220
221 mr reg_CFP,reg_NL1
222 mr reg_LEXENV,reg_NL0
223 lwz reg_A0,0(reg_CFP)
224 lwz reg_A1,4(reg_CFP)
225 lwz reg_A2,8(reg_CFP)
226 lwz reg_A3,12(reg_CFP)
227
228 /* Calculate LRA */
229 lis reg_LRA,ha16(lra)
230 addi reg_LRA,reg_LRA,lo16(lra)
231 addi reg_LRA,reg_LRA,type_OtherPointer
232
233 /* Function is an indirect closure */
234 lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
235 #ifdef PPC_FUN-HACK
236 mtctr reg_CODE
237 #else
238 addi reg_LIP,reg_CODE,6*4-type_FunctionPointer
239 mtctr reg_LIP
240 #endif
241 slwi reg_NARGS,reg_NL2,2
242 bctr
243 .align 3
244 lra:
245 .long type_ReturnPcHeader
246
247 /* Blow off any extra values. */
248 mr reg_CSP,reg_OCFP
249 nop
250
251 /* Return the one value. */
252
253 mr REG(3),reg_A0
254
255 /* Turn on pseudo-atomic */
256 li reg_NL3,-4
257 la reg_ALLOC,4(reg_ALLOC)
258
259 /* Store lisp state */
260 clrrwi reg_NL1,reg_ALLOC,3
261 store(reg_NL1,reg_NL2,_current_dynamic_space_free_pointer)
262 /* store(reg_POLL,reg_NL2,poll_flag) */
263 /* load(reg_NL2,current_thread) */
264 store(reg_BSP,reg_NL2,_current_binding_stack_pointer)
265 store(reg_CSP,reg_NL2,_current_control_stack_pointer)
266 store(reg_CFP,reg_NL2,_current_control_frame_pointer)
267 /* load(reg_POLL,saver2) */
268
269 /* No longer in Lisp. */
270 store(reg_NL1,reg_NL2,_foreign_function_call_active)
271
272 /* Check for interrupt */
273 add reg_ALLOC,reg_ALLOC,reg_NL3
274 twlti reg_ALLOC,0
275
276 /* Back to C */
277 C_FULL_EPILOG
278 blr
279 SET_SIZE(call_into_lisp)
280
281
282 GFUNCDEF(call_into_c)
283 /* We're kind of low on unboxed, non-dedicated registers here:
284 most of the unboxed registers may have outgoing C args in them.
285 CFUNC is going to have to go in the CTR in a moment, anyway
286 so we'll free it up soon. reg_NFP is preserved by lisp if it
287 has a meaningful value in it, so we can use it. reg_NARGS is
288 free when it's not holding a copy of the "real" reg_NL3, which
289 gets tied up by the pseudo-atomic mechanism */
290 mtctr reg_CFUNC
291 mflr reg_LIP
292 /* Build a lisp stack frame */
293 mr reg_OCFP,reg_CFP
294 mr reg_CFP,reg_CSP
295 la reg_CSP,32(reg_CSP)
296 stw reg_OCFP,0(reg_CFP)
297 stw reg_CODE,8(reg_CFP)
298 /* The pseudo-atomic mechanism wants to use reg_NL3, but that
299 may be an outgoing C argument. Copy reg_NL3 to something that's
300 unboxed and -not- one of the C argument registers */
301 mr reg_NARGS,reg_NL3
302
303 /* Turn on pseudo-atomic */
304 li reg_NL3,-4
305 la reg_ALLOC,4(reg_ALLOC)
306
307 /* Convert the return address to an offset and save it on the stack. */
308 sub reg_NFP,reg_LIP,reg_CODE
309 la reg_NFP,type_OtherPointer(reg_NFP)
310 stw reg_NFP,4(reg_CFP)
311
312 /* Store Lisp state */
313 clrrwi reg_NFP,reg_ALLOC,3
314 store(reg_NFP,reg_CFUNC,_current_dynamic_space_free_pointer)
315 /* load(reg_CFUNC,current_thread) */
316
317 store(reg_BSP,reg_CFUNC,_current_binding_stack_pointer)
318 store(reg_CSP,reg_CFUNC,_current_control_stack_pointer)
319 store(reg_CFP,reg_CFUNC,_current_control_frame_pointer)
320
321 /* No longer in Lisp */
322 store(reg_CSP,reg_CFUNC,_foreign_function_call_active)
323 /* load(reg_POLL,saver2) */
324 /* Disable pseudo-atomic; check pending interrupt */
325 add reg_ALLOC,reg_ALLOC,reg_NL3
326 twlti reg_ALLOC,0
327 mr reg_NL3,reg_NARGS
328
329 /* PowerOpen (i.e. OS X) requires the callee address in r12
330 (a.k.a. CFUNC), so move it back there, too. */
331 mfctr reg_CFUNC
332 /* Into C we go. */
333 bctrl
334
335 /* Re-establish NIL */
336 lis reg_NULL,hi16(NIL)
337 ori reg_NULL,reg_NULL,lo16(NIL)
338 /* And reg_ZERO */
339 li reg_ZERO,0
340
341 /* If we GC'ed during the FF code (as the result of a callback ?)
342 the tagged lisp registers may now contain garbage (since the
343 registers were saved by C and not seen by the GC.) Put something
344 harmless in all such registers before allowing an interrupt */
345 li reg_CODE,0
346 li reg_CNAME,0
347 li reg_LEXENV,0
348 /* reg_OCFP was pointing to a control stack frame & was preserved by C */
349 li reg_LRA,0
350 li reg_A0,0
351 li reg_A1,0
352 li reg_A2,0
353 li reg_A3,0
354 li reg_L0,0
355 li reg_L1,0
356 li reg_L2,0
357 li reg_LIP,0
358
359 /* Atomic ... */
360 li reg_NL3,-4
361 li reg_ALLOC,4
362
363 /* No long in foreign function call. */
364 store(reg_ZERO,reg_NL2,_foreign_function_call_active)
365
366 /* The free pointer may have moved */
367 load(reg_NL4,_current_dynamic_space_free_pointer)
368 add reg_ALLOC,reg_ALLOC,reg_NL4
369
370 /* The BSP wasn't preserved by C, so load it */
371 load(reg_BSP,_current_binding_stack_pointer)
372
373 /* Other lisp stack/frame pointers were preserved by C.
374 I can't imagine why they'd have moved */
375
376 /* Get the return address back. */
377 lwz reg_LIP,4(reg_CFP)
378 lwz reg_CODE,8(reg_CFP)
379 add reg_LIP,reg_CODE,reg_LIP
380 la reg_LIP,-type_OtherPointer(reg_LIP)
381
382 /* No longer atomic */
383 add reg_ALLOC,reg_ALLOC,reg_NL3
384 twlti reg_ALLOC,0
385 mtlr reg_LIP
386
387 /* Reset the lisp stack. */
388 mr reg_CSP,reg_CFP
389 mr reg_CFP,reg_OCFP
390
391 /* And back into Lisp. */
392 blr
393
394 SET_SIZE(call_into_c)
395
396 GFUNCDEF(xundefined_tramp)
397 .globl _undefined_tramp
398 .byte 0,0,0,type_FunctionHeader
399
400 /*
401 * The next 4 bytes are the encoding for a PPC jump instruction.
402 * The jump should go to the twllei instruction below.
403 */
404 .byte 18<<2
405 _undefined_tramp:
406 .byte 0,0,24
407 .long _undefined_tramp
408 .long NIL
409 .long NIL
410 .long NIL
411 .long NIL
412 twllei reg_ZERO,trap_Cerror
413 /* Number of argument bytes */
414 .byte 4
415 .byte UNDEFINED_SYMBOL_ERROR
416 /* Escape to create 16bit number from following two bytes,
417 in little-endian order */
418 .byte 254
419 .byte SC_OFFSET_LO(sc_DescriptorReg, reg_FDEFN_NUM)
420 .byte SC_OFFSET_HI(sc_DescriptorReg, reg_FDEFN_NUM)
421 /*
422 .byte sc_DescriptorReg+0x40
423 .byte 1
424 */
425 .align 2
426 #ifdef PPC_FUN_HACK_MAYBE
427 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_CNAME)
428 #else
429 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
430 #endif
431 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
432 mtctr reg_LIP
433 bctr
434
435 mr reg_CSP, reg_CFP
436 b 1b
437
438 SET_SIZE(xundefined_tramp)
439
440 GFUNCDEF(xclosure_tramp)
441 .globl _closure_tramp
442 .byte 0,0,0,type_FunctionHeader
443 .byte 18<<2
444 _closure_tramp:
445 .byte 0,0,24
446 .long _closure_tramp
447 .long NIL
448 .long NIL
449 .long NIL
450 .long NIL
451 #ifdef PPC_FUN_HACK_MAYBE
452 lwz reg_LEXENV,FDEFN_FUNCTION_OFFSET(reg_CNAME)
453 #else
454 lwz reg_LEXENV,FDEFN_FUNCTION_OFFSET(reg_FDEFN)
455 #endif
456 lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
457 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
458 mtctr reg_LIP
459 bctr
460
461 SET_SIZE(xclosure_tramp)
462
463 GFUNCDEF(function_end_breakpoint_trap)
464 .long 0
465 SET_SIZE(function_end_breakpoint_trap)
466
467 GFUNCDEF(function_end_breakpoint)
468 .long 0
469 SET_SIZE(function_end_breakpoint)
470
471 GFUNCDEF(function_end_breakpoint_guts)
472 .long 0
473 SET_SIZE(function_end_breakpoint_guts)
474
475 GFUNCDEF(function_end_breakpoint_end)
476 .long 0
477 SET_SIZE(function_end_breakpoint_end)
478
479
480 GFUNCDEF(ppc_flush_cache_line)
481 dcbf 0,REG(3)
482 sync
483 icbi 0,REG(3)
484 sync
485 isync
486 blr
487 SET_SIZE(ppc_flush_cache_line)
488
489 #ifdef LINKAGE_TABLE
490 /*
491 * Call into C code to resolve a linkage entry.
492 *
493 * We get here by Lisp calling call_into_c with an address of the
494 * desired function which is contained in the register reg_CFUNC (aka
495 * %i4, aka %r28). This is the address of the entry in the linkage
496 * table, which is what we need to figure out what function we really
497 * wanted.
498 *
499 * Note that because we get here from call_into_c, all necessary live
500 * registers have been saved, including FP registers. Hence, no need
501 * to save them.
502 */
503 .globl _lazy_resolve_linkage
504 GFUNCDEF(resolve_linkage_tramp)
505 /*
506 * We need to call lazy_resolve_linkage. reg_A0 (= r24)
507 * (see ppc-arch.c) contains the address of the linkage entry.
508 */
509 /*
510 * Need to save all parameter regs to the stack because we
511 * need them for later.
512 */
513 subi r1, r1, 8*4+8
514 stw r3, 0(r1)
515 stw r4, 4(r1)
516 stw r5, 8(r1)
517 stw r6, 12(r1)
518 stw r7, 16(r1)
519 stw r8, 20(r1)
520 stw r9, 24(r1)
521 stw r10, 28(r1)
522
523 mr reg_NL0, reg_A0
524
525 stwu r1, (-(24+4))(r1)
526 /*
527 * At this point reg_NIL should be available to us.
528 * Call lazy_resolve_linkage to figure out the real function address.
529 */
530 lis reg_NULL, hi16(_lazy_resolve_linkage)
531 ori reg_NULL, reg_NULL, lo16(_lazy_resolve_linkage)
532 mtctr reg_NULL
533 mflr reg_CODE
534 bctrl
535
536 addi r1,r1,24+4
537
538 /*
539 * The desired function is in r3 (NL0), so save it
540 * and restore the real arg parameters
541 */
542
543 mtctr reg_NL0
544 lwz r3, 0(r1)
545 lwz r4, 4(r1)
546 lwz r5, 8(r1)
547 lwz r6, 12(r1)
548 lwz r7, 16(r1)
549 lwz r8, 20(r1)
550 lwz r9, 24(r1)
551 lwz r10, 28(r1)
552
553 /*
554 * Got it, so we can now jump directly to the desired function.
555 * reg_NL0 contains the result. Restore the stack and go!
556 */
557
558 mtlr reg_CODE
559
560 /* Back to C */
561 /* mtlr reg_CODE*/
562 bctr
563
564 SET_SIZE(resolve_linkage_tramp)
565
566
567 /*
568 * When we get called, r3 (reg_NL0) contains the address of the
569 * data_vector object which is a string naming the bad symbol.
570 */
571 GFUNCDEF(undefined_foreign_symbol_trap)
572
573 /*
574 Need to restore all the global registers with the Lisp values that
575 were saved away in call_into_c. (This routine is only called from
576 os_link_one_symbol, which is called from resolve_linkage_tramp, which
577 is called from call_into_c.)
578
579 The global registers are volatile across function calls, so who
580 knows what values have been they contain now!
581
582 */
583
584 load(reg_ALLOC, _current_dynamic_space_free_pointer)
585 load(reg_BSP, _current_binding_stack_pointer)
586 load(reg_CSP, _current_control_stack_pointer)
587 load(reg_CFP, _current_control_frame_pointer)
588
589 lis reg_NULL,hi16(NIL)
590 ori reg_NULL,reg_NULL,lo16(NIL)
591 /* And reg_ZERO */
592 li reg_ZERO,0
593
594 mr reg_NL0, reg_A0
595 twllei reg_ZERO, trap_Error
596 .byte 4 /* Number of argument bytes */
597 .byte UNDEFINED_FOREIGN_SYMBOL_ERROR
598 /* Escape to create 16bit number from following two bytes, in
599 little-endian order */
600 .byte 254
601 .byte SC_OFFSET_LO(sc_DescriptorReg, reg_A0_NUM)
602 .byte SC_OFFSET_HI(sc_DescriptorReg, reg_A0_NUM)
603 .align 4
604
605 #endif

  ViewVC Help
Powered by ViewVC 1.1.5