[project @ 2000-03-07 11:35:36 by simonmar]
[ghc-hetmet.git] / ghc / rts / StgCRun.c
1 /* -----------------------------------------------------------------------------
2  * $Id: StgCRun.c,v 1.13 2000/03/07 11:35:36 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-2000
5  *
6  * STG-to-C glue.
7  *
8  * To run an STG function from C land, call
9  *
10  *              rv = StgRun(f,BaseReg);
11  *
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).
15  *
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.
20  *
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
24  * in STG land.
25  * 
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
32  * variables.  
33  *
34  * -------------------------------------------------------------------------- */
35
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.
38  */
39 #include "Stg.h"
40 #include "Rts.h"
41 #include "StgRun.h"
42
43 #ifdef DEBUG
44 #include "RtsFlags.h"
45 #include "RtsUtils.h"
46 #include "Printer.h"
47 #endif
48
49 #ifdef USE_MINIINTERPRETER
50
51 /* -----------------------------------------------------------------------------
52    any architecture (using miniinterpreter)
53    -------------------------------------------------------------------------- */
54         
55 /* The static @jmp_environment@ variable allows @miniInterpret@ to
56  * communicate with @StgReturn@.
57  * 
58  * Because @StgRun@ may be used recursively, we carefully
59  * save and restore the whole of @jmp_environment@.
60  */
61 #include <setjmp.h>
62 #include <string.h> /* for memcpy */
63
64 static jmp_buf jmp_environment;
65
66 #if 1
67
68 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg)
69 {
70     jmp_buf save_buf;
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) {
74         while ( 1 ) {
75             IF_DEBUG(evaluator,
76                      fprintf(stderr,"Jumping to ");
77                      printPtr((P_)f);
78                      fprintf(stderr,"\n");
79                      );
80             f = (StgFunPtr) (f)();
81         }
82     }
83     /* Restore jmp_environment for previous call */
84     memcpy((void*) save_buf, (void*) jmp_environment, sizeof(jmp_buf));
85
86     return (StgThreadReturnCode)R1.i;
87 }
88
89 EXTFUN(StgReturn)
90 {
91     longjmp(jmp_environment, 1);
92 }
93
94 #else
95
96 static void scanStackSeg ( W_* ptr, int nwords )
97 {
98    W_ w;
99    int nwords0 = nwords;
100    while (nwords > 0) {
101       w = *ptr;
102       if (IS_ARG_TAG(w)) {
103          fprintf ( stderr, "%d",w ); nwords--; ptr++;
104          while (w) { fprintf(stderr, "_"); w--; nwords--; ptr++; }
105       }
106       else {
107          fprintf(stderr, "p"); 
108          nwords--; ptr++;
109       }
110    }
111    if (nwords < 0) fprintf(stderr, "erk: nwords < 0\n");
112    checkStackChunk ( ptr, ptr-nwords0 );
113 }
114
115
116 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg)
117 {
118     char* nm;
119     while (1) {
120
121 #define STACK_DETAILS 0
122
123 #if STACK_DETAILS
124    {
125    int i;
126    StgWord* sp  = basereg->rSp;
127    StgWord* su  = basereg->rSu;
128    StgTSO*  tso = basereg->rCurrentTSO;
129    StgWord* sb  = tso->stack + tso->stack_size;
130    int ws;
131
132    fprintf(stderr, "== SP = %p   SU = %p\n", sp,su);
133
134    if (su >= sb) goto postloop;
135    if (!sp || !su) goto postloop;
136
137    //printStack ( sp, sb, su);
138
139    while (1) {
140       ws = su - sp;
141       switch (get_itbl((StgClosure*)su)->type) {
142          case STOP_FRAME: 
143             scanStackSeg(sp,ws);
144             fprintf(stderr, "S%d ",ws); 
145             fprintf(stderr, "\n");
146             goto postloop;
147          case UPDATE_FRAME: 
148             scanStackSeg(sp,ws);
149             fprintf(stderr,"U%d ",ws); 
150             sp = su + sizeofW(StgUpdateFrame);
151             su = ((StgUpdateFrame*)su)->link;
152             break;
153          case SEQ_FRAME: 
154             scanStackSeg(sp,ws);
155             fprintf(stderr,"Q%d ",ws); 
156             sp = su + sizeofW(StgSeqFrame);
157             su = ((StgSeqFrame*)su)->link;
158             break;
159          case CATCH_FRAME: 
160             scanStackSeg(sp,ws);
161             fprintf(stderr,"C%d ",ws); 
162             sp = su + sizeofW(StgCatchFrame);
163             su = ((StgCatchFrame*)su)->link;
164             break;
165          default:
166             fprintf(stderr, "?\nweird record on stack\n");
167             goto postloop;
168       }
169    }
170    postloop:
171    }
172 #endif    
173
174 #if STACK_DETAILS
175        fprintf(stderr,"\n");
176 #endif
177        fprintf(stderr,"-- enter: ");
178        nm = nameFromOPtr ( f );
179        if (nm)
180             fprintf(stderr, "%s (%p)", nm, f); else
181             printPtr((P_)f);
182        fprintf ( stderr, "\n");
183 #if STACK_DETAILS
184        fprintf(stderr,"\n");
185 #endif
186        f = (StgFunPtr) (f)();
187        if (!f) break;
188     }
189     fprintf (stderr, "miniInterpreter: bye!\n\n" );
190     return (StgThreadReturnCode)R1.i;
191 }
192
193 EXTFUN(StgReturn)
194 {
195    return 0;
196 }
197 #endif
198
199
200
201 #else /* !USE_MINIINTERPRETER */
202
203 #ifdef LEADING_UNDERSCORE
204 #define STG_RETURN "_StgReturn"
205 #else
206 #define STG_RETURN "StgReturn"
207 #endif
208
209 /* -----------------------------------------------------------------------------
210    x86 architecture
211    -------------------------------------------------------------------------- */
212         
213 #ifdef i386_TARGET_ARCH
214
215 StgThreadReturnCode
216 StgRun(StgFunPtr f, StgRegTable *basereg) {
217
218     StgChar space[ RESERVED_C_STACK_BYTES + 4*sizeof(void *) ];
219     StgThreadReturnCode r;
220
221     __asm__ volatile (
222         /* 
223          * save callee-saves registers on behalf of the STG code.
224          */
225         "movl %%esp, %%eax\n\t"
226         "addl %4, %%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"
231         /*
232          * Set BaseReg
233          */
234         "movl %3,%%ebx\n\t"
235         /*
236          * grab the function argument from the stack, and jump to it.
237          */
238         "movl %2,%%eax\n\t"
239         "jmp *%%eax\n\t"
240
241         ".global " STG_RETURN "\n"
242         STG_RETURN ":\n\t"
243
244         "movl %%esi, %%eax\n\t"   /* Return value in R1  */
245
246         /*
247          * restore callee-saves registers.  (Don't stomp on %%eax!)
248          */
249         "movl %%esp, %%edx\n\t"
250         "addl %4, %%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"
255
256       : "=&a" (r), "=m" (space)
257       : "m" (f), "m" (basereg), "i" (RESERVED_C_STACK_BYTES)
258       : "edx" /* stomps on %edx */
259     );
260
261     return r;
262 }
263
264 #endif
265
266 /* -----------------------------------------------------------------------------
267    sparc architecture
268    -------------------------------------------------------------------------- */
269         
270 #ifdef sparc_TARGET_ARCH
271
272 StgThreadReturnCode
273 StgRun(StgFunPtr f, StgRegTable *basereg) {
274
275     StgChar space[RESERVED_C_STACK_BYTES+sizeof(void *)];
276     register void *i7 __asm__("%i7");
277     ((void **)(space))[100] = i7;
278     f();
279     __asm__ volatile (".align 4\n"              
280             ".global " STG_RETURN "\n"
281             STG_RETURN ":\n"
282             "\tld %1,%0" : "=r" (i7) : "m" (((void **)(space))[100]));
283     return (StgThreadReturnCode)R1.i;
284 }
285
286 #endif
287
288 /* -----------------------------------------------------------------------------
289    alpha architecture
290    -------------------------------------------------------------------------- */
291
292 #ifdef alpha_TARGET_ARCH
293
294 StgThreadReturnCode
295 StgRun(StgFunPtr f, StgRegTable *basereg) 
296 {
297     StgThreadReturnCode ret;
298
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)));
317
318     f();
319
320     __asm__ volatile (".align 3\n"
321                       ".globl " STG_RETURN "\n"
322                       STG_RETURN ":\n\t"
323                       "lda %0,($14)\n\t"  /* save R1 */
324                       "lda $30,%0($30)\n\t"
325                       "ldq $9,-8($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" 
339                       "ldt $f9,-120($30)" 
340                       : "=r" (ret)
341                       : "K" (RESERVED_C_STACK_BYTES+
342                            8*sizeof(double)+8*sizeof(long)));
343
344     return ret;
345 }
346
347 #endif /* alpha_TARGET_ARCH */
348
349 /* -----------------------------------------------------------------------------
350    HP-PA architecture
351    -------------------------------------------------------------------------- */
352
353 #ifdef hppa1_1_TARGET_ARCH
354
355 StgThreadReturnCode
356 StgRun(StgFunPtr f, StgRegTable *basereg) 
357 {
358     StgChar space[RESERVED_C_STACK_BYTES+16*sizeof(long)+10*sizeof(double)];
359     StgThreadReturnCode ret;
360
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"
392                       );
393
394     f();
395
396     __asm__ volatile (".align 4\n"
397                       "\t.EXPORT " STG_RETURN ",CODE\n"
398                       "\t.EXPORT " STG_RETURN ",ENTRY,PRIV_LEV=3\n"
399                       STG_RETURN "\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" 
432                          : "=r" (ret)
433                          : "n" (-(116 * sizeof(long) + 10 * sizeof(double)))
434                          : "%r19"
435                       );
436
437     return ret;
438 }
439
440 #endif /* hppa1_1_TARGET_ARCH */
441
442 #endif /* !USE_MINIINTERPRETER */