/[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.2 - (show annotations)
Thu Jul 29 11:52:24 2004 UTC (9 years, 8 months ago) by rtoy
Branch: MAIN
Changes since 1.1: +9 -2 lines
(defun foo () (zot)) when compiled and run gave a silly message about
#C(0d0 0d0) failing a typecase.  Then doing a backtrace gave another
error about some negative number not being a positive fixnum.

The former error is caused by a bad definition of undefined_tramp.
The latter error is caused by the debugger not being able to compute
the offset correctly.

(Fixes ported from sbcl.)
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 .byte 18<<2
401 _undefined_tramp:
402 .byte 0,0,48
403 .long _undefined_tramp
404 .long NIL
405 .long NIL
406 .long NIL
407 .long NIL
408 twllei reg_ZERO,trap_Cerror
409 .byte 4
410 .byte UNDEFINED_SYMBOL_ERROR
411 .byte 254
412 .byte sc_DescriptorReg+0x40
413 .byte 1
414 .align 2
415 #ifdef PPC_FUN_HACK_MAYBE
416 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_CNAME)
417 #else
418 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
419 #endif
420 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
421 mtctr reg_LIP
422 bctr
423
424 mr reg_CSP, reg_CFP
425 b 1b
426
427 SET_SIZE(xundefined_tramp)
428
429 GFUNCDEF(xclosure_tramp)
430 .globl _closure_tramp
431 .byte 0,0,0,type_FunctionHeader
432 .byte 18<<2
433 _closure_tramp:
434 .byte 0,0,24
435 .long _closure_tramp
436 .long NIL
437 .long NIL
438 .long NIL
439 .long NIL
440 #ifdef PPC_FUN_HACK_MAYBE
441 lwz reg_LEXENV,FDEFN_FUNCTION_OFFSET(reg_CNAME)
442 #else
443 lwz reg_LEXENV,FDEFN_FUNCTION_OFFSET(reg_FDEFN)
444 #endif
445 lwz reg_CODE,CLOSURE_FUNCTION_OFFSET(reg_LEXENV)
446 la reg_LIP,FUNCTION_CODE_OFFSET(reg_CODE)
447 mtctr reg_LIP
448 bctr
449
450 SET_SIZE(xclosure_tramp)
451
452 GFUNCDEF(function_end_breakpoint_trap)
453 .long 0
454 SET_SIZE(function_end_breakpoint_trap)
455
456 GFUNCDEF(function_end_breakpoint)
457 .long 0
458 SET_SIZE(function_end_breakpoint)
459
460 GFUNCDEF(function_end_breakpoint_guts)
461 .long 0
462 SET_SIZE(function_end_breakpoint_guts)
463
464 GFUNCDEF(function_end_breakpoint_end)
465 .long 0
466 SET_SIZE(function_end_breakpoint_end)
467
468
469 GFUNCDEF(ppc_flush_cache_line)
470 dcbf 0,REG(3)
471 sync
472 icbi 0,REG(3)
473 sync
474 isync
475 blr
476 SET_SIZE(ppc_flush_cache_line)
477

  ViewVC Help
Powered by ViewVC 1.1.5