81c266b90968fce2b8c2635c6059d6a84af9c57f
[ghc-hetmet.git] / ghc / includes / COptWraps.lh
1 \section[COptWraps]{Wrappers for calls to ``STG C'' routines}
2
3 % this file is part of the C-as-assembler document
4
5 \begin{code}
6 #ifndef COPTWRAPS_H
7 #define COPTWRAPS_H
8 \end{code}
9
10 %************************************************************************
11 %*                                                                      *
12 \subsection[COptWraps-portable]{Wrappers for ``portable~C''}
13 %*                                                                      *
14 %************************************************************************
15
16 @STGCALL@ macros are used when we really have to be careful about saving
17 any caller-saves STG registers.  @SAFESTGCALL@ macros are used
18 when the caller has previously arranged to save/restore volatile user
19 registers (vanilla, float, and double STG registers), and we only have to
20 worry about the ``system'' registers (stack and heap pointers, @STK_STUB@,
21 etc.).  @STGCALL_GC@ macros are used whenever the callee is going to
22 need to access (and perhaps modify) some STG registers.  @ULTRASAFESTGCALL@
23 is available for our own routines that we are absolutely certain will not
24 damage any STG registers.
25
26 In short,
27 \begin{itemize}
28 \item @STGCALL@ saves/restores all caller-saves STG registers.
29 \item @SAFESTGCALL@ saves/restores only caller-saves STG ``system'' registers.
30 \item @ULTRASAFECALL@ is a simple call, without a wrapper.
31 \item @STGCALL_GC@ saves/restores {\em all} STG registers.
32 \end{itemize}
33     
34 Several macros are provided to handle outcalls to functions requiring from
35 one to five arguments.  (If we could assume GCC, we could use macro varargs,
36 but unfortunately, we have to cater to ANSI C as well.)
37
38 \begin{code}
39
40 #define ULTRASAFESTGCALL0(t,p,f)            f()
41 #define ULTRASAFESTGCALL1(t,p,f,a)          f(a)
42 #define ULTRASAFESTGCALL2(t,p,f,a,b)        f(a,b)
43 #define ULTRASAFESTGCALL3(t,p,f,a,b,c)      f(a,b,c)
44 #define ULTRASAFESTGCALL4(t,p,f,a,b,c,d)    f(a,b,c,d)
45 #define ULTRASAFESTGCALL5(t,p,f,a,b,c,d,e)  f(a,b,c,d,e)
46
47 #if ! (defined(__GNUC__) && defined(__STG_GCC_REGS__))
48
49 #define STGCALL0(t,p,f)             f()
50 #define STGCALL1(t,p,f,a)           f(a)
51 #define STGCALL2(t,p,f,a,b)         f(a,b)
52 #define STGCALL3(t,p,f,a,b,c)       f(a,b,c)
53 #define STGCALL4(t,p,f,a,b,c,d)     f(a,b,c,d)
54 #define STGCALL5(t,p,f,a,b,c,d,e)   f(a,b,c,d,e)
55
56 #define SAFESTGCALL0(t,p,f)           f()
57 #define SAFESTGCALL1(t,p,f,a)         f(a)
58 #define SAFESTGCALL2(t,p,f,a,b)       f(a,b)
59 #define SAFESTGCALL3(t,p,f,a,b,c)     f(a,b,c)
60 #define SAFESTGCALL4(t,p,f,a,b,c,d)   f(a,b,c,d)
61 #define SAFESTGCALL5(t,p,f,a,b,c,d,e) f(a,b,c,d,e)
62
63 /* 
64  * Generic call_GC wrappers have gone away in favor of these partially
65  * evaluated versions.
66  */
67
68 #define DO_GC(args)                         \
69     do {SaveAllStgRegs(); PerformGC(args); RestoreAllStgRegs();} while(0)
70 #define DO_STACKOVERFLOW(headroom,args)     \
71     do {SaveAllStgRegs(); StackOverflow(headroom,args); RestoreAllStgRegs();} while(0)
72
73 #if defined(GRAN)
74
75 #define DO_YIELD(args)   DO_GRAN_YIELD(args)
76 #define DO_GRAN_YIELD(liveness)             \
77     do {SaveAllStgRegs(); Yield(liveness); RestoreAllStgRegs();} while(0)
78
79 #define DO_PERFORM_RESCHEDULE(liveness_mask,reenter)                \
80     do {SaveAllStgRegs(); PerformReschedule(liveness_mask,reenter); RestoreAllStgRegs();} while(0)
81
82 #else
83
84 #define DO_YIELD(args)              \
85     do {SaveAllStgRegs(); Yield(args); RestoreAllStgRegs();} while(0)
86
87 #endif   /* GRAN */
88
89 \end{code}
90
91 %************************************************************************
92 %*                                                                      *
93 \subsection[COptWraps-optimised]{Wrappers in ``optimised~C''}
94 %*                                                                      *
95 %************************************************************************
96
97 We {\em expect} the call-wrappery to be boring---the defaults shown
98 herein will kick in--- but you never know.
99
100 For example: Don't try an @STGCALL6@ on a SPARC!  That's because you
101 cannot pass that many arguments to \tr{f} just by heaving them into
102 \tr{%o*} registers; anything else is too painful to contemplate.
103
104 \begin{code}
105 #else /* __GNUC__ && __STG_GCC_REGS__ */
106
107 #if !(defined(CALLER_SAVES_SYSTEM) || defined(CALLER_SAVES_USER))
108 #define STGCALL0(t,p,f)           f()
109 #define STGCALL1(t,p,f,a)         f(a)
110 #define STGCALL2(t,p,f,a,b)       f(a,b)
111 #define STGCALL3(t,p,f,a,b,c)     f(a,b,c)
112 #define STGCALL4(t,p,f,a,b,c,d)   f(a,b,c,d)
113 #define STGCALL5(t,p,f,a,b,c,d,e) f(a,b,c,d,e)
114
115 #else
116
117 extern void callWrapper(STG_NO_ARGS);
118
119 #define STGCALL0(t,p,f)             \
120     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f);})
121
122 #define STGCALL1(t,p,f,a)           \
123     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f,a);})
124
125 #define STGCALL2(t,p,f,a,b)         \
126     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f,a,b);})
127
128 #define STGCALL3(t,p,f,a,b,c)       \
129     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f,a,b,c);})
130
131 #define STGCALL4(t,p,f,a,b,c,d)     \
132     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f,a,b,c,d);})
133
134 #define STGCALL5(t,p,f,a,b,c,d,e)   \
135     ({t (*_w)p = (t (*)p) callWrapper; (*_w)((void *)f,a,b,c,d,e);})
136
137 #endif
138
139 #if !defined(CALLER_SAVES_SYSTEM)
140 #define SAFESTGCALL0(t,p,f)           f()
141 #define SAFESTGCALL1(t,p,f,a)         f(a)
142 #define SAFESTGCALL2(t,p,f,a,b)       f(a,b)
143 #define SAFESTGCALL3(t,p,f,a,b,c)     f(a,b,c)
144 #define SAFESTGCALL4(t,p,f,a,b,c,d)   f(a,b,c,d)
145 #define SAFESTGCALL5(t,p,f,a,b,c,d,e) f(a,b,c,d,e)
146
147 #else
148
149 extern void callWrapper_safe(STG_NO_ARGS);
150
151 #define SAFESTGCALL0(t,p,f)             \
152     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f);})
153
154 #define SAFESTGCALL1(t,p,f,a)           \
155     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f,a);})
156
157 #define SAFESTGCALL2(t,p,f,a,b)         \
158     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f,a,b);})
159
160 #define SAFESTGCALL3(t,p,f,a,b,c)       \
161     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f,a,b,c);})
162
163 #define SAFESTGCALL4(t,p,f,a,b,c,d)     \
164     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f,a,b,c,d);})
165
166 #define SAFESTGCALL5(t,p,f,a,b,c,d,e)   \
167     ({t (*_w)p = (t (*)p) callWrapper_safe; (*_w)((void *)f,a,b,c,d,e);})
168
169 #endif
170
171 /* 
172  * Generic call_GC wrappers have gone away in favor of these partially
173  * evaluated versions.  These are only here so that we can avoid putting
174  * all of the STG register save/restore code at each call site.
175  */
176
177 #ifndef CALLWRAPPER_C
178 /* 
179  * We may have funny declarations in CallWrapper_C, to avoid sliding the
180  * register windows and other nastiness.
181  */
182 void PerformGC_wrapper PROTO((W_));
183 void StackOverflow_wrapper PROTO((W_, W_));
184 void Yield_wrapper PROTO((W_));
185 #  ifdef GRAN
186 void PerformReschedule_wrapper PROTO((W_, W_));
187 void GranSimAllocate_wrapper PROTO((I_, P_, W_));
188 void GranSimUnallocate_wrapper PROTO((I_, P_, W_));
189 void GranSimFetch_wrapper PROTO((P_));
190 void GranSimExec_wrapper PROTO((W_, W_, W_, W_, W_));
191 #  endif
192 #endif
193
194 #define DO_GC(args)                     PerformGC_wrapper(args)
195 #define DO_STACKOVERFLOW(headroom,args) StackOverflow_wrapper(headroom,args)
196
197 #  ifdef GRAN
198
199 #define DO_YIELD(args)   DO_GRAN_YIELD(args)
200 #define DO_GRAN_YIELD(liveness)                 Yield_wrapper(liveness)
201
202 #define DO_PERFORMRESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node)
203 #define DO_GRANSIMALLOCATE(n, node, liveness)   GranSimAllocate_wrapper(n, node, liveness)
204 #define DO_GRANSIMUNALLOCATE(n, node, liveness) GranSimUnallocate_wrapper(n, node, liveness)
205 #define DO_GRANSIMFETCH(node)                   GranSimFetch_wrapper(node)
206 #define DO_GRANSIMEXEC(arith,branch,load,store,floats) GranSimExec_wrapper(arith,branch,load,store,floats)
207
208 #  else
209
210 #define DO_YIELD(args)                  Yield_wrapper(args)
211
212 #  endif
213
214 #endif /* __GNUC__ && __STG_GCC_REGS__ */
215 \end{code}
216
217 %************************************************************************
218 %*                                                                      *
219 \subsection[COptWraps-magic]{Magic assembly bits for call wrappers}
220 %*                                                                      *
221 %************************************************************************
222
223 Call wrappers need to be able to call arbitrary functions, regardless of
224 their arguments and return types.  (Okay, we actually only allow up to
225 five arguments, because on the SPARC it gets more complicated to handle
226 any more.)  The nasty bit is that the return value can be in either an
227 integer register or a floating point register, and we don't know which.
228 (We {\em don't} handle structure returns, and we don't want to.)
229 Still, we have to stash the result away while we restore caller-saves
230 STG registers, and then we have to pass the result back to our caller
231 in the end.
232
233 Getting this right requires three extremely @MAGIC@ macros, no doubt
234 chock full of assembly gook for the current platform.  These are
235 @MAGIC_CALL_SET
236 UP@, which gets ready for one of these magic calls,
237 @MAGIC_CALL@, which performs the call and stashes away all possible
238 results, and @MAGIC_RETURN@, which collects all possible results back
239 up again.
240
241 For example, in the SPARC version, the @SETUP@ guarantees that we
242 have enough space to store all of our argument registers for a wee
243 bit, and it gives a `C' name to the register that we're going to use
244 for the call.  (It helps to do the call in actual `C' fashion, so that
245 gcc knows about register death.)  It also stashes the incoming arguments
246 in the space  provided.  The @MAGIC_CALL@ then reloads the argument
247 registers, rotated by one, so that the function to call is in \tr{%o5},
248 calls the function in `C' fashion, and stashes away the possible return
249 values (either \tr{%o0} or \tr{%f0}) on the stack.  Finally, @MAGIC_RETURN@
250 ensures that \tr{%o0} and \tr{%f0} are both set to the values we stashed
251 away.  Presumably, we then fall into a return instruction and our caller
252 gets whatever it's after.
253
254 %************************************************************************
255 %*                                                                      *
256 \subsubsection[alpha-magic]{Call-wrapper MAGIC for DEC Alpha}
257 %*                                                                      *
258 %************************************************************************
259
260 \begin{code}
261
262 #if defined(__GNUC__) && defined(__STG_GCC_REGS__)
263
264 #if alpha_TARGET_ARCH
265
266 #define MAGIC_CALL_SETUP        \
267     long WeNeedThisSpace[7];    \
268     double AndThisSpaceToo[6];  \
269     register void (*f)() __asm__("$21");\
270     __asm__ volatile (          \
271         "stq $16,8($30)\n"      \
272         "\tstq $17,16($30)\n"   \
273         "\tstq $18,24($30)\n"   \
274         "\tstq $19,32($30)\n"   \
275         "\tstq $20,40($30)\n"   \
276         "\tstq $21,48($30)\n"   \
277         "\tstt $f16,56($30)\n"  \
278         "\tstt $f17,64($30)\n"  \
279         "\tstt $f18,72($30)\n"  \
280         "\tstt $f19,80($30)\n"  \
281         "\tstt $f20,88($30)\n"  \
282         "\tstt $f21,96($30)");
283
284 #define MAGIC_CALL              \
285     __asm__ volatile (          \
286         "ldq $21,8($30)\n"      \
287         "\tldq $16,16($30)\n"   \
288         "\tldq $17,24($30)\n"   \
289         "\tldq $18,32($30)\n"   \
290         "\tldq $19,40($30)\n"   \
291         "\tldq $20,48($30)\n"   \
292         "\tldt $f16,56($30)\n"  \
293         "\tldt $f17,64($30)\n"  \
294         "\tldt $f18,72($30)\n"  \
295         "\tldt $f19,80($30)\n"  \
296         "\tldt $f20,88($30)\n"  \
297         "\tldt $f21,96($30)");\
298     (*f)();                     \
299     __asm__ volatile (          \
300         "stq $0,8($30)\n"       \
301         "\tstt $f0,16($30)");
302
303 #define MAGIC_RETURN            \
304     __asm__ volatile (          \
305         "ldq $0,8($30)\n"       \
306         "\tldt $f0,16($30)");
307
308 #define WRAPPER_NAME(f)   /* nothing */
309
310 /* 
311    Threaded code needs to be able to grab the return address, in case we have
312    an intervening context switch.
313  */
314
315 #define SET_RETADDR(loc)  { register StgFunPtrFunPtr ra __asm__ ("$26"); loc = ra; }
316
317 #define WRAPPER_SETUP(f,ignore1,ignore2)  SaveAllStgContext();
318
319 #define WRAPPER_RETURN(x)   \
320     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0);
321
322 #define SEPARATE_WRAPPER_RESTORE    /* none */
323
324 #endif /* __alpha */
325
326 \end{code}
327
328 %************************************************************************
329 %*                                                                      *
330 \subsubsection[hppa-magic]{Call-wrapper MAGIC for HP-PA}
331 %*                                                                      *
332 %************************************************************************
333
334 \begin{code}
335
336 #if hppa1_1_TARGET_ARCH
337
338 #define MAGIC_CALL_SETUP            \
339     long SavedIntArgRegs[4];        \
340     double SavedFltArgRegs[2];      \
341     register void (*f)() __asm__("%r28");\
342     __asm__ volatile (              \
343         "copy %r26,%r28\n"          \
344         "\tstw %r25,8(0,%r3)\n"     \
345         "\tstw %r24,12(0,%r3)\n"    \
346         "\tstw %r23,16(0,%r3)\n"    \
347         "\tldo 40(%r3),%r19\n"      \
348         "\tfstds %fr5,-16(0,%r19)\n"\
349         "\tfstds %fr7, -8(0,%r19)\n");
350
351
352 #define MAGIC_CALL                  \
353     __asm__ volatile (              \
354         "ldw 8(0,%r3),%r26\n"       \
355         "\tldw 12(0,%r3),%r25\n"    \
356         "\tldw 16(0,%r3),%r24\n"    \
357         "\tldw -52(0,%r3),%r23\n"   \
358         "\tldw -56(0,%r3),%r19\n"   \
359         "\tstw %r19,-52(0,%r30)\n"  \
360         "\tldo 40(%r3),%r19\n"      \
361         "\tfldds -16(0,%r19),%fr5\n"\
362         "\tfldds -8(0,%r19),%fr7\n" \
363         "\tldo -64(%r3),%r19\n"     \
364         "\tldo -64(%r30),%r20\n"    \
365         "\tfldds -16(0,%r19),%fr4\n"\
366         "\tfstds %fr4,-16(0,%r20)\n"\
367         "\tfldds -8(0,%r19)%fr4\n"  \
368         "\tfstds %fr4,-8(0,%r19)\n" \
369         "\tfldds 0(0,%r19),%fr4\n"  \
370         "\tfstds %fr4,0(0,%r19)\n"  \
371         "\tfldds 8(0,%r19),%fr4\n"  \
372         "\tfstds %fr4,8(0,%r19)\n");\
373     (*f)();                         \
374     __asm__ volatile (              \
375         "stw %r28,8(0,%r3)\n"       \
376         "\tfstds %fr4,16(0,%r3)");
377
378 #define MAGIC_RETURN                \
379     __asm__ volatile (              \
380         "\tfldds 16(0,%r3),%fr4"    \
381         "ldw 8(0,%r3),%r28\n");
382
383 #define WRAPPER_NAME(f)   /* nothing */
384
385 /* 
386    Threaded code needs to be able to grab the return address, in case we have
387    an intervening context switch.
388  */
389
390 #define SET_RETADDR(loc)  __asm__ volatile ("stw %%r2, %0" : "=m" ((void *)(loc)));
391
392 #define WRAPPER_SETUP(f,ignore1,ignore2)  SaveAllStgContext();
393
394 #define WRAPPER_RETURN(x)   \
395     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0);
396
397 #define SEPARATE_WRAPPER_RESTORE    /* none */
398
399 #endif /* __hppa */
400
401 \end{code}
402
403 %************************************************************************
404 %*                                                                      *
405 \subsubsection[iX86-magic]{Call-wrapper MAGIC for iX86}
406 %*                                                                      *
407 %************************************************************************
408
409 \begin{code}
410 #if i386_TARGET_ARCH
411
412 /* modelled loosely on SPARC stuff */
413
414 /* NB: no MAGIC_CALL_SETUP, MAGIC_CALL, or MAGIC_RETURN! */
415
416 #define WRAPPER_NAME(f) /*nothing*/
417
418 #if defined(solaris2_TARGET_OS) || defined(linux_TARGET_OS)
419 #define REAL_NAME(f)   #f
420 #else
421 #define REAL_NAME(f)   "_" #f
422 #endif
423
424 /* 
425    Threaded code needs to be able to grab the return address, in case we have
426    an intervening context switch.
427  */
428
429 #define SET_RETADDR(loc,val) loc = val;
430
431 /* the grab-%eax-quickly HACK is here because we use a VERY SPECIAL
432    calling convention on iX86 just for calling PerformGC_wrapper.
433    (WDP 95/09)
434
435    NB: mangler makes sure that __temp_{eax,esp} get loaded.
436    (This is about as ugly as it can get.)
437 */
438
439 #define WRAPPER_SETUP(f,ret_addr,args)                  \
440     __asm__ volatile (                                  \
441         "movl "   REAL_NAME(__temp_esp)  ",%%edx\n"     \
442         "\tmovl (%%edx),%0\n"                           \
443         "\tmovl " REAL_NAME(__temp_eax) ",%1"           \
444         : "=r" (ret_addr), "=r" (args) );               \
445     SaveAllStgContext(ret_addr);
446
447 /* Note re WRAPPER_SETUP: we have special code just for PerformGC_wrapper;
448    pls see its definition.  WDP 95/09
449
450    Also note the EXTREMELY UGLY slamming in of an "sp_offset"; the
451    return address *is* on the stack, but it is hard to get there
452    before GCC has moved the sp pointer... WDP 95/11
453 */
454
455 #define WRAPPER_RETURN(x)   \
456     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0);
457
458 #define SEPARATE_WRAPPER_RESTORE    /* none */
459
460 #endif /* iX86 */
461 \end{code}
462
463 %************************************************************************
464 %*                                                                      *
465 \subsubsection[m68k-magic]{Call-wrapper MAGIC for m68k}
466 %*                                                                      *
467 %************************************************************************
468
469 \begin{code}
470
471 #if m68k_TARGET_ARCH
472
473 #define MAGIC_CALL_SETUP  \
474     int WeNeedThisSpace[5];             \
475     register void (*f)() __asm__("a0"); \
476     __asm__ volatile (                  \
477     "movel a6@(8),a0\n"                 \
478     "\tmovel a6@(12),a6@(-20)\n"        \
479     "\tmovel a6@(16),a6@(-16)\n"        \
480     "\tmovel a6@(20),a6@(-12)\n"        \
481     "\tmovel a6@(24),a6@(-8)\n"         \
482     "\tmovel a6@(28),a6@(-4)");
483
484 #define MAGIC_CALL      \
485     (*f)();             \
486      __asm__ volatile ( \
487     "movel d0, sp@-\n"  \
488     "\tmovel d1,sp@-");
489
490 #define MAGIC_RETURN    \
491     __asm__ volatile (  \
492     "movel sp@+,d0\n"   \
493     "\tmovel sp@+,d1");
494
495 #define WRAPPER_NAME(f)   /* nothing */
496
497 #define WRAPPER_SETUP(f,ignore1,ignore2)  SaveAllStgContext();
498
499 #define WRAPPER_RETURN(x)  \
500     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0);
501
502 #define SEPARATE_WRAPPER_RESTORE    /* none */
503
504 #endif /* __mc680x0__ */
505
506 \end{code}
507
508 %************************************************************************
509 %*                                                                      *
510 \subsubsection[mips-magic]{Call-wrapper MAGIC for MIPS}
511 %*                                                                      *
512 %************************************************************************
513
514 \begin{code}
515 #if mipseb_TARGET_ARCH || mipsel_TARGET_ARCH
516
517 /* shift 4 arg registers down one */
518
519 #define MAGIC_CALL_SETUP  \
520     register void (*f)() __asm__("$2"); \
521     __asm__ volatile (                  \
522     "move $2,$4\n"                      \
523     "\tmove $4,$5\n"                    \
524     "\tmove $5,$6\n"                    \
525     "\tmove $6,$7\n"                    \
526     "\tlw $7,16($sp)\n"                 \
527     "\taddu $sp,$sp,4\n"                \
528     : : : "$2" );
529
530 #define MAGIC_CALL              \
531     (*f)();                     \
532      __asm__ volatile (         \
533     "subu $sp,$sp,4\n"          \
534     "\ts.d $f0, -8($sp)\n"      \
535     "\tsw  $2, -12($sp)");
536
537
538 #define MAGIC_RETURN            \
539     __asm__ volatile (          \
540     "l.d $f0, -8($sp)\n"        \
541     "\tlw  $2, -12($sp)");
542
543 #define WRAPPER_NAME(f)   /* nothing */
544
545 /* 
546    Threaded code needs to be able to grab the return address, in case we have
547    an intervening context switch.
548  */
549
550 #define SET_RETADDR(loc)  { register StgFunPtrFunPtr ra __asm__ ("$31"); loc = ra; }
551
552 #define WRAPPER_SETUP(f,ignore1,ignore2)  SaveAllStgContext();
553
554 #define WRAPPER_RETURN(x)  \
555     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0);
556
557 #define SEPARATE_WRAPPER_RESTORE    /* none */
558
559 #endif /* mips */
560 \end{code}
561
562 %************************************************************************
563 %*                                                                      *
564 \subsubsection[powerpc-magic]{Call-wrapper MAGIC for PowerPC}
565 %*                                                                      *
566 %************************************************************************
567
568 \begin{code}
569 #if powerpc_TARGET_ARCH || rs6000_TARGET_ARCH
570
571 #define MAGIC_CALL_SETUP  \
572     register void (*f)() __asm__("$2"); \
573     __asm__ volatile (                  \
574     "not used!!!????\n"                 \
575     : : : "$2" );
576
577 #define MAGIC_CALL              \
578     (*f)();                     \
579      __asm__ volatile (         \
580     "not used!!!????\n");
581
582 #define MAGIC_RETURN            \
583     __asm__ volatile (          \
584     "not used!!!????\n");
585
586 #define WRAPPER_NAME(f)   /* nothing */
587
588 #define SET_RETADDR(loc)        \
589     __asm__ volatile (          \
590         "mflr 0\n"              \
591         "\tst 0,%0"             \
592         :"=m" (loc) :: "0");
593 /*    __asm__ volatile ("st %%r0, %0" : "=m" ((void *)(loc))); */
594
595 #define WRAPPER_SETUP(f,ignore1,ignore2)  SaveAllStgContext();
596
597 /* we have to make sure the STG registers are restored. 
598 GCC tries to restore the value the registers had in
599 the beginning of the current call, which we don't want. 
600 We defeat it by saving the registers in the stack again. :-( */
601
602 #define WRAPPER_RETURN(x)  \
603     do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); \
604     __asm__ volatile (          \
605         "cal 1,136(1)\n" \
606         "\tstm 14,-72(1)\n" \
607         "\tstu 1,-136(1)");
608
609 #define SEPARATE_WRAPPER_RESTORE    /* none */
610
611 #endif /* powerpc */
612 \end{code}
613
614 %************************************************************************
615 %*                                                                      *
616 \subsubsection[sparc-magic]{Call-wrapper MAGIC for SPARC}
617 %*                                                                      *
618 %************************************************************************
619
620 \begin{code}
621 #if sparc_TARGET_ARCH
622
623 #define MAGIC_CALL_SETUP        \
624     int WeNeedThisSpace[6];     \
625     register void (*f)() __asm__("%o5");\
626     __asm__ volatile (          \
627         "std %i0,[%fp-40]\n"    \
628         "\tstd %i2,[%fp-32]\n"  \
629         "\tstd %i4,[%fp-24]");
630
631 /* Lest GCC attempt to stick something in
632    the delay slot: with compile with
633    -fno-delayed-branch.  A weak solution. WDP 96/07
634 */
635 #define MAGIC_CALL              \
636     __asm__ volatile (          \
637         "ld [%%fp-40],%%o5\n"   \
638         "\tld [%%fp-36],%%o0\n" \
639         "\tld [%%fp-32],%%o1\n" \
640         "\tld [%%fp-28],%%o2\n" \
641         "\tld [%%fp-24],%%o3\n" \
642         "\tld [%%fp-20],%%o4"   \
643         : : : "%o0", "%o1", "%o2", "%o3", "%o4", "%o5");\
644     (*f)();                     \
645     __asm__ volatile (          \
646         "std %f0,[%fp-40]\n"    \
647         "\tstd %o0,[%fp-32]");
648 #if 0
649 /* We leave nothing to chance here; we have seen
650    GCC stick "unwanted" code in the branch delay
651    slot, causing mischief (WDP 96/05)
652 */
653 /* the problem with this one: GCC has no way of
654    knowing there is a "call" in there, so it
655    does not do any calling-convention stuff
656    (e.g., saving used regs).  WDP 96/07
657 */
658 #define MAGIC_CALL              \
659     __asm__ volatile (          \
660         "ld [%%fp-40],%%o5\n"   \
661         "\tld [%%fp-36],%%o0\n" \
662         "\tld [%%fp-32],%%o1\n" \
663         "\tld [%%fp-28],%%o2\n" \
664         "\tld [%%fp-24],%%o3\n" \
665         "\tld [%%fp-20],%%o4\n" \
666         "\tcall %%o5\n"         \
667         "\tnop\n"               \
668         "\tstd %%f0,[%%fp-40]\n"\
669         "\tstd %%o0,[%%fp-32]"  \
670         : : : "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", "%f0", "memory");
671 #endif /* 0 */
672
673 #define MAGIC_RETURN            \
674     __asm__ volatile (          \
675         "ldd [%fp-40],%f0\n"    \
676         "\tldd [%fp-32],%i0");
677
678 /* 
679    We rename the entry points for wrappers so that we can introduce a
680    new entry point after the prologue.  We want to ensure that the
681    register window does not slide!  However, we insert a call to
682    abort() to make gcc _believe_ that the window slid.
683  */
684
685 #define WRAPPER_NAME(f)   __asm__("L" #f "_wrapper")
686
687 #ifdef solaris2_TARGET_OS
688 #define REAL_NAME(f)   #f
689 #else
690 #define REAL_NAME(f)   "_" #f
691 #endif
692
693 #define WRAPPER_SETUP(f,ignore1,ignore2)    \
694     __asm__ volatile (                      \
695         ".global " REAL_NAME(f) "_wrapper\n"\
696         REAL_NAME(f) "_wrapper:\n"          \
697         "\tstd %o0,[%sp-24]\n"              \
698         "\tmov %o7,%i7");                   \
699     SaveAllStgContext();                    \
700     __asm__ volatile (                      \
701         "ldd [%sp-24],%i0\n"                \
702         "\tmov %i0,%o0\n"                   \
703         "\tmov %i1,%o1");
704 /* 
705  * In the above, we want to ensure that the arguments are both in the
706  * %i registers and the %o registers, with the assumption that gcc
707  * will expect them now to be in one or the other.  This is a terrible
708  * hack.
709  */
710
711 /* 
712    Threaded code needs to be able to grab the return address, in case
713    we have an intervening context switch.  Note that we want the
714    address of the next instruction to be executed, so we add 8 to the
715    link address.
716  */
717
718 #define SET_RETADDR(loc)        \
719     __asm__ volatile (          \
720         "add %%i7,8,%%o7\n"     \
721         "\tst %%o7,%0"          \
722         : "=m" (loc) : : "%o7");
723
724
725 #define WRAPPER_RETURN(x)               \
726     __asm__ volatile (                  \
727         "call Lwrapper_restore" #x "\n" \
728         "\tnop");                       \
729     abort();
730
731 /* 
732    The sparc is a big nuisance.  We use a separate function for 
733    restoring STG registers so that gcc won't try to leave anything
734    (like the address of MainRegTable) in the stack frame that we
735    didn't build.  We also use a leaf return in a format that allows us 
736    to pass %o7 in as an argument known to gcc, in the hope that its
737    value will be preserved during the reloading of STG registers.
738    Note that the current gcc (2.5.6) does not use the delay slot
739    here (%#), but perhaps future versions will.
740  */
741
742 #if defined(CONCURRENT)
743 #define WRAPPER_REENTER    \
744 void wrapper_restore_and_reenter_node(STG_NO_ARGS)  \
745 {                                       \
746      __asm__("Lwrapper_restore1:");     \
747     RestoreAllStgRegs();                \
748     JMP_(EnterNodeCode);                \
749 }
750 #else
751 #define WRAPPER_REENTER
752 #endif
753
754 #define SEPARATE_WRAPPER_RESTORE        \
755 void wrapper_restore(STG_NO_ARGS)       \
756 {                                       \
757     register void *o7 __asm__("%o7");   \
758     __asm__ volatile (                  \
759         "Lwrapper_restore0:\n"          \
760         "\tmov %%i7,%0" : "=r" (o7));   \
761     RestoreAllStgRegs();                \
762     __asm__ volatile ("jmp %0+8%#" : : "r" (o7));       \
763 }                                       \
764 WRAPPER_REENTER
765
766 #endif /* __sparc__ */
767
768 #endif /* __GNUC__ && __STG_GCC_REGS__ */
769
770 \end{code}
771
772 That's all, folks.
773 \begin{code}
774 #endif /* ! COPTWRAPS_H */
775 \end{code}