1 /* -----------------------------------------------------------------------------
2 * $Id: StgCRun.c,v 1.13 2000/03/07 11:35:36 simonmar Exp $
4 * (c) The GHC Team, 1998-2000
8 * To run an STG function from C land, call
10 * rv = StgRun(f,BaseReg);
12 * where "f" is the STG function to call, and BaseReg is the address of the
13 * RegTable for this run (we might have separate RegTables if we're running
14 * multiple threads on an SMP machine).
16 * In the end, "f" must JMP to StgReturn (defined below),
17 * passing the return-value "rv" in R1,
18 * to return to the caller of StgRun returning "rv" in
19 * the whatever way C returns a value.
21 * NOTE: StgRun/StgReturn do *NOT* load or store Hp or any
22 * other registers (other than saving the C callee-saves
23 * registers). Instead, the called function "f" must do that
26 * GCC will have assumed that pushing/popping of C-stack frames is
27 * going on when it generated its code, and used stack space
28 * accordingly. However, we actually {\em post-process away} all
29 * such stack-framery (see \tr{ghc/driver/ghc-asm.lprl}). Things will
30 * be OK however, if we initially make sure there are
31 * @RESERVED_C_STACK_BYTES@ on the C-stack to begin with, for local
34 * -------------------------------------------------------------------------- */
36 /* include Stg.h first because we want real machine regs in here: we
37 * have to get the value of R1 back from Stg land to C land intact.
49 #ifdef USE_MINIINTERPRETER
51 /* -----------------------------------------------------------------------------
52 any architecture (using miniinterpreter)
53 -------------------------------------------------------------------------- */
55 /* The static @jmp_environment@ variable allows @miniInterpret@ to
56 * communicate with @StgReturn@.
58 * Because @StgRun@ may be used recursively, we carefully
59 * save and restore the whole of @jmp_environment@.
62 #include <string.h> /* for memcpy */
64 static jmp_buf jmp_environment;
68 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg)
71 /* Save jmp_environment for previous call to miniInterpret */
72 memcpy((void *) jmp_environment, (void *) save_buf, sizeof(jmp_buf));
73 if (setjmp(jmp_environment) == 0) {
76 fprintf(stderr,"Jumping to ");
80 f = (StgFunPtr) (f)();
83 /* Restore jmp_environment for previous call */
84 memcpy((void*) save_buf, (void*) jmp_environment, sizeof(jmp_buf));
86 return (StgThreadReturnCode)R1.i;
91 longjmp(jmp_environment, 1);
96 static void scanStackSeg ( W_* ptr, int nwords )
103 fprintf ( stderr, "%d",w ); nwords--; ptr++;
104 while (w) { fprintf(stderr, "_"); w--; nwords--; ptr++; }
107 fprintf(stderr, "p");
111 if (nwords < 0) fprintf(stderr, "erk: nwords < 0\n");
112 checkStackChunk ( ptr, ptr-nwords0 );
116 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg)
121 #define STACK_DETAILS 0
126 StgWord* sp = basereg->rSp;
127 StgWord* su = basereg->rSu;
128 StgTSO* tso = basereg->rCurrentTSO;
129 StgWord* sb = tso->stack + tso->stack_size;
132 fprintf(stderr, "== SP = %p SU = %p\n", sp,su);
134 if (su >= sb) goto postloop;
135 if (!sp || !su) goto postloop;
137 //printStack ( sp, sb, su);
141 switch (get_itbl((StgClosure*)su)->type) {
144 fprintf(stderr, "S%d ",ws);
145 fprintf(stderr, "\n");
149 fprintf(stderr,"U%d ",ws);
150 sp = su + sizeofW(StgUpdateFrame);
151 su = ((StgUpdateFrame*)su)->link;
155 fprintf(stderr,"Q%d ",ws);
156 sp = su + sizeofW(StgSeqFrame);
157 su = ((StgSeqFrame*)su)->link;
161 fprintf(stderr,"C%d ",ws);
162 sp = su + sizeofW(StgCatchFrame);
163 su = ((StgCatchFrame*)su)->link;
166 fprintf(stderr, "?\nweird record on stack\n");
175 fprintf(stderr,"\n");
177 fprintf(stderr,"-- enter: ");
178 nm = nameFromOPtr ( f );
180 fprintf(stderr, "%s (%p)", nm, f); else
182 fprintf ( stderr, "\n");
184 fprintf(stderr,"\n");
186 f = (StgFunPtr) (f)();
189 fprintf (stderr, "miniInterpreter: bye!\n\n" );
190 return (StgThreadReturnCode)R1.i;
201 #else /* !USE_MINIINTERPRETER */
203 #ifdef LEADING_UNDERSCORE
204 #define STG_RETURN "_StgReturn"
206 #define STG_RETURN "StgReturn"
209 /* -----------------------------------------------------------------------------
211 -------------------------------------------------------------------------- */
213 #ifdef i386_TARGET_ARCH
216 StgRun(StgFunPtr f, StgRegTable *basereg) {
218 StgChar space[ RESERVED_C_STACK_BYTES + 4*sizeof(void *) ];
219 StgThreadReturnCode r;
223 * save callee-saves registers on behalf of the STG code.
225 "movl %%esp, %%eax\n\t"
227 "movl %%ebx,0(%%eax)\n\t"
228 "movl %%esi,4(%%eax)\n\t"
229 "movl %%edi,8(%%eax)\n\t"
230 "movl %%ebp,12(%%eax)\n\t"
236 * grab the function argument from the stack, and jump to it.
241 ".global " STG_RETURN "\n"
244 "movl %%esi, %%eax\n\t" /* Return value in R1 */
247 * restore callee-saves registers. (Don't stomp on %%eax!)
249 "movl %%esp, %%edx\n\t"
251 "movl 0(%%edx),%%ebx\n\t" /* restore the registers saved above */
252 "movl 4(%%edx),%%esi\n\t"
253 "movl 8(%%edx),%%edi\n\t"
254 "movl 12(%%edx),%%ebp\n\t"
256 : "=&a" (r), "=m" (space)
257 : "m" (f), "m" (basereg), "i" (RESERVED_C_STACK_BYTES)
258 : "edx" /* stomps on %edx */
266 /* -----------------------------------------------------------------------------
268 -------------------------------------------------------------------------- */
270 #ifdef sparc_TARGET_ARCH
273 StgRun(StgFunPtr f, StgRegTable *basereg) {
275 StgChar space[RESERVED_C_STACK_BYTES+sizeof(void *)];
276 register void *i7 __asm__("%i7");
277 ((void **)(space))[100] = i7;
279 __asm__ volatile (".align 4\n"
280 ".global " STG_RETURN "\n"
282 "\tld %1,%0" : "=r" (i7) : "m" (((void **)(space))[100]));
283 return (StgThreadReturnCode)R1.i;
288 /* -----------------------------------------------------------------------------
290 -------------------------------------------------------------------------- */
292 #ifdef alpha_TARGET_ARCH
295 StgRun(StgFunPtr f, StgRegTable *basereg)
297 StgThreadReturnCode ret;
299 __asm__ volatile ("stq $9,-8($30)\n\t"
300 "stq $10,-16($30)\n\t"
301 "stq $11,-24($30)\n\t"
302 "stq $12,-32($30)\n\t"
303 "stq $13,-40($30)\n\t"
304 "stq $14,-48($30)\n\t"
305 "stq $15,-56($30)\n\t"
306 "stt $f2,-64($30)\n\t"
307 "stt $f3,-72($30)\n\t"
308 "stt $f4,-80($30)\n\t"
309 "stt $f5,-88($30)\n\t"
310 "stt $f6,-96($30)\n\t"
311 "stt $f7,-104($30)\n\t"
312 "stt $f8,-112($30)\n\t"
313 "stt $f9,-120($30)\n\t"
314 "lda $30,-%0($30)" : :
315 "K" (RESERVED_C_STACK_BYTES+
316 8*sizeof(double)+8*sizeof(long)));
320 __asm__ volatile (".align 3\n"
321 ".globl " STG_RETURN "\n"
323 "lda %0,($14)\n\t" /* save R1 */
324 "lda $30,%0($30)\n\t"
326 "ldq $10,-16($30)\n\t"
327 "ldq $11,-24($30)\n\t"
328 "ldq $12,-32($30)\n\t"
329 "ldq $13,-40($30)\n\t"
330 "ldq $14,-48($30)\n\t"
331 "ldq $15,-56($30)\n\t"
332 "ldt $f2,-64($30)\n\t"
333 "ldt $f3,-72($30)\n\t"
334 "ldt $f4,-80($30)\n\t"
335 "ldt $f5,-88($30)\n\t"
336 "ldt $f6,-96($30)\n\t"
337 "ldt $f7,-104($30)\n\t"
338 "ldt $f8,-112($30)\n\t"
341 : "K" (RESERVED_C_STACK_BYTES+
342 8*sizeof(double)+8*sizeof(long)));
347 #endif /* alpha_TARGET_ARCH */
349 /* -----------------------------------------------------------------------------
351 -------------------------------------------------------------------------- */
353 #ifdef hppa1_1_TARGET_ARCH
356 StgRun(StgFunPtr f, StgRegTable *basereg)
358 StgChar space[RESERVED_C_STACK_BYTES+16*sizeof(long)+10*sizeof(double)];
359 StgThreadReturnCode ret;
361 __asm__ volatile ("ldo %0(%%r30),%%r19\n"
362 "\tstw %%r3, 0(0,%%r19)\n"
363 "\tstw %%r4, 4(0,%%r19)\n"
364 "\tstw %%r5, 8(0,%%r19)\n"
365 "\tstw %%r6,12(0,%%r19)\n"
366 "\tstw %%r7,16(0,%%r19)\n"
367 "\tstw %%r8,20(0,%%r19)\n"
368 "\tstw %%r9,24(0,%%r19)\n"
369 "\tstw %%r10,28(0,%%r19)\n"
370 "\tstw %%r11,32(0,%%r19)\n"
371 "\tstw %%r12,36(0,%%r19)\n"
372 "\tstw %%r13,40(0,%%r19)\n"
373 "\tstw %%r14,44(0,%%r19)\n"
374 "\tstw %%r15,48(0,%%r19)\n"
375 "\tstw %%r16,52(0,%%r19)\n"
376 "\tstw %%r17,56(0,%%r19)\n"
377 "\tstw %%r18,60(0,%%r19)\n"
378 "\tldo 80(%%r19),%%r19\n"
379 "\tfstds %%fr12,-16(0,%%r19)\n"
380 "\tfstds %%fr13, -8(0,%%r19)\n"
381 "\tfstds %%fr14, 0(0,%%r19)\n"
382 "\tfstds %%fr15, 8(0,%%r19)\n"
383 "\tldo 32(%%r19),%%r19\n"
384 "\tfstds %%fr16,-16(0,%%r19)\n"
385 "\tfstds %%fr17, -8(0,%%r19)\n"
386 "\tfstds %%fr18, 0(0,%%r19)\n"
387 "\tfstds %%fr19, 8(0,%%r19)\n"
388 "\tldo 32(%%r19),%%r19\n"
389 "\tfstds %%fr20,-16(0,%%r19)\n"
390 "\tfstds %%fr21, -8(0,%%r19)\n" : :
391 "n" (-(116 * sizeof(long) + 10 * sizeof(double))) : "%r19"
396 __asm__ volatile (".align 4\n"
397 "\t.EXPORT " STG_RETURN ",CODE\n"
398 "\t.EXPORT " STG_RETURN ",ENTRY,PRIV_LEV=3\n"
400 /* "\tldo %0(%%r3),%%r19\n" */
401 "\tldo %1(%%r30),%%r19\n"
402 "\tcopy %%r11, %0\n" /* save R1 */
403 "\tldw 0(0,%%r19),%%r3\n"
404 "\tldw 4(0,%%r19),%%r4\n"
405 "\tldw 8(0,%%r19),%%r5\n"
406 "\tldw 12(0,%%r19),%%r6\n"
407 "\tldw 16(0,%%r19),%%r7\n"
408 "\tldw 20(0,%%r19),%%r8\n"
409 "\tldw 24(0,%%r19),%%r9\n"
410 "\tldw 28(0,%%r19),%%r10\n"
411 "\tldw 32(0,%%r19),%%r11\n"
412 "\tldw 36(0,%%r19),%%r12\n"
413 "\tldw 40(0,%%r19),%%r13\n"
414 "\tldw 44(0,%%r19),%%r14\n"
415 "\tldw 48(0,%%r19),%%r15\n"
416 "\tldw 52(0,%%r19),%%r16\n"
417 "\tldw 56(0,%%r19),%%r17\n"
418 "\tldw 60(0,%%r19),%%r18\n"
419 "\tldo 80(%%r19),%%r19\n"
420 "\tfldds -16(0,%%r19),%%fr12\n"
421 "\tfldds -8(0,%%r19),%%fr13\n"
422 "\tfldds 0(0,%%r19),%%fr14\n"
423 "\tfldds 8(0,%%r19),%%fr15\n"
424 "\tldo 32(%%r19),%%r19\n"
425 "\tfldds -16(0,%%r19),%%fr16\n"
426 "\tfldds -8(0,%%r19),%%fr17\n"
427 "\tfldds 0(0,%%r19),%%fr18\n"
428 "\tfldds 8(0,%%r19),%%fr19\n"
429 "\tldo 32(%%r19),%%r19\n"
430 "\tfldds -16(0,%%r19),%%fr20\n"
431 "\tfldds -8(0,%%r19),%%fr21\n"
433 : "n" (-(116 * sizeof(long) + 10 * sizeof(double)))
440 #endif /* hppa1_1_TARGET_ARCH */
442 #endif /* !USE_MINIINTERPRETER */