[project @ 1996-01-11 14:06:51 by partain]
[ghc-hetmet.git] / ghc / runtime / c-as-asm / CallWrap_C.lc
1 %************************************************************************
2 %*                                                                      *
3 \section[CallWrap_C.lc]{``callWrapper'' stuff that can be written in C}
4 %*                                                                      *
5 %************************************************************************
6
7 \begin{code}
8 #define MAIN_REG_MAP        /* These routines are all a bit special */
9 #define CALLWRAPPER_C       /* Don't give standard declarations for wrappers */
10 #include "rtsdefs.h"
11 \end{code}
12
13 %************************************************************************
14 %*                                                                      *
15 \subsection[call-wrapping]{Routines to ``wrap'' special calls to C}
16 %*                                                                      *
17 %************************************************************************
18
19 In most cases, this requires some assembly-language hacking (see the
20 discussion in @COptWraps.lh@.)
21
22 \begin{code}
23 #if defined(__STG_GCC_REGS__)
24
25 # if defined(CALLER_SAVES_SYSTEM) || defined(CALLER_SAVES_USER)
26 void
27 callWrapper(STG_NO_ARGS)
28 {
29     MAGIC_CALL_SETUP
30
31     CALLER_SAVE_Base
32     CALLER_SAVE_StkO
33     CALLER_SAVE_R1
34     CALLER_SAVE_R2
35     CALLER_SAVE_R3
36     CALLER_SAVE_R4
37     CALLER_SAVE_R5
38     CALLER_SAVE_R6
39     CALLER_SAVE_R7
40     CALLER_SAVE_R8
41     CALLER_SAVE_FltReg1
42     CALLER_SAVE_FltReg2
43     CALLER_SAVE_FltReg3
44     CALLER_SAVE_FltReg4
45     CALLER_SAVE_DblReg1
46     CALLER_SAVE_DblReg2
47     CALLER_SAVE_Tag
48     CALLER_SAVE_SpA
49     CALLER_SAVE_SuA
50     CALLER_SAVE_SpB
51     CALLER_SAVE_SuB
52     CALLER_SAVE_Hp
53     CALLER_SAVE_HpLim
54     CALLER_SAVE_Liveness
55     CALLER_SAVE_Ret
56
57     MAGIC_CALL
58
59     CALLER_RESTORE_Base     /* has to be first! */
60
61     CALLER_RESTORE_StkO
62     CALLER_RESTORE_R1
63     CALLER_RESTORE_R2
64     CALLER_RESTORE_R3
65     CALLER_RESTORE_R4
66     CALLER_RESTORE_R5
67     CALLER_RESTORE_R6
68     CALLER_RESTORE_R7
69     CALLER_RESTORE_R8
70     CALLER_RESTORE_FltReg1
71     CALLER_RESTORE_FltReg2
72     CALLER_RESTORE_FltReg3
73     CALLER_RESTORE_FltReg4
74     CALLER_RESTORE_DblReg1
75     CALLER_RESTORE_DblReg2
76     CALLER_RESTORE_Tag
77     CALLER_RESTORE_SpA
78     CALLER_RESTORE_SuA
79     CALLER_RESTORE_SpB
80     CALLER_RESTORE_SuB
81     CALLER_RESTORE_Hp
82     CALLER_RESTORE_HpLim
83     CALLER_RESTORE_Liveness
84     CALLER_RESTORE_Ret
85     
86     /* These next two are restore-only */
87     CALLER_RESTORE_StdUpdRetVec
88     CALLER_RESTORE_StkStub
89
90     MAGIC_RETURN
91 }
92 # endif /* defined(CALLER_SAVES_SYSTEM) || defined(CALLER_SAVES_USER) */
93
94 # if defined(CALLER_SAVES_SYSTEM)
95 void
96 callWrapper_safe(STG_NO_ARGS)
97 {
98     MAGIC_CALL_SETUP
99
100     CALLER_SAVE_Base
101     CALLER_SAVE_StkO
102     CALLER_SAVE_SpA
103     CALLER_SAVE_SuA
104     CALLER_SAVE_SpB
105     CALLER_SAVE_SuB
106     CALLER_SAVE_Hp
107     CALLER_SAVE_HpLim
108     CALLER_SAVE_Liveness
109     CALLER_SAVE_Ret
110
111     MAGIC_CALL
112
113     CALLER_RESTORE_Base /* has to be first! */
114
115     CALLER_RESTORE_StkO
116     CALLER_RESTORE_SpA
117     CALLER_RESTORE_SuA
118     CALLER_RESTORE_SpB
119     CALLER_RESTORE_SuB
120     CALLER_RESTORE_Hp
121     CALLER_RESTORE_HpLim
122     CALLER_RESTORE_Liveness
123     CALLER_RESTORE_Ret
124     
125     /* These next two are restore-only */
126     CALLER_RESTORE_StdUpdRetVec
127     CALLER_RESTORE_StkStub
128
129     MAGIC_RETURN
130 }
131 # endif /* defined(CALLER_SAVES_SYSTEM) */
132
133 /* 
134 Nota Bene: 
135
136 Anyone changing the definition of @callWrapper_GC@ should make
137 appropriate changes in the compiler (absCSyn/PprAbsC.lhs :: pprCCall).
138
139 The reason is that \tr{_ccall_GC_} and \tr{_casm_GC_} generate code like this:
140 \begin{verbatim}
141    { R _ccall_result;
142      SaveAllStgRegs();
143      inCCallGC+=1;
144      _ccall_result = << do the call/asm>>;
145      inCCallGC-=1;
146      RestoreAllStgRegs();
147    }
148 \end{verbatim}
149
150 This avoids limiting _ccall_GC_ to 6 arguments and makes it possible
151 to implement _ccall_GC_.  (The local variable avoids the need for some
152 of the deeper magic hidden inside @GC_SETUP@, @GC_CCALL@ and
153 @GC_RETURN@.)
154
155 ADR */
156
157 EXTFUN(EnterNodeCode);
158
159 void *__temp_esp, *__temp_eax;
160
161 void PerformGC_wrapper PROTO((W_))          WRAPPER_NAME(PerformGC);
162 void PerformGC_wrapper(args)
163 W_ args;
164 {
165 #if i386_TARGET_ARCH
166     void *ret_addr;
167
168     WRAPPER_SETUP(PerformGC,ret_addr,args)
169 #else
170     WRAPPER_SETUP(PerformGC, ignore_me, ignore_me)
171 #endif
172     PerformGC(args);
173     WRAPPER_RETURN(0)
174 }
175
176 # ifdef CONCURRENT
177
178 void __DISCARD__ (STG_NO_ARGS) { /*nothing*/ }
179
180 void StackOverflow_wrapper PROTO((W_,W_))   WRAPPER_NAME(StackOverflow);
181 void StackOverflow_wrapper(args1,args2)
182 W_ args1, args2;
183 {
184 #if i386_TARGET_ARCH
185     void *ret_addr, *ignore_me;
186     WRAPPER_SETUP(StackOverflow,ret_addr,ignore_me)
187 #else
188     WRAPPER_SETUP(StackOverflow, ignore_me, ignore_me)
189 #endif
190     if(StackOverflow(args1,args2)) {
191         WRAPPER_RETURN(1)
192     }
193     WRAPPER_RETURN(0)
194 }
195
196 void Yield_wrapper PROTO((W_))              WRAPPER_NAME(Yield);
197 void Yield_wrapper(args)
198 W_ args;
199 {
200 #if i386_TARGET_ARCH
201     void *ret_addr, *ignore_me;
202     WRAPPER_SETUP(Yield, ret_addr, ignore_me)
203 #else
204     WRAPPER_SETUP(Yield, ignore_me, ignore_me)
205 #endif
206     Yield(args);
207     WRAPPER_RETURN(0)
208 }
209
210 # endif
211
212 # ifdef GRAN
213
214 void PerformReschedule_wrapper PROTO((W_, W_))      WRAPPER_NAME(PerformReschedule);
215 void PerformReschedule_wrapper(liveness, always_reenter_node)
216   W_ liveness;
217   W_  always_reenter_node;
218 {
219 #if i386_TARGET_ARCH
220     void *ret_addr, *ignore_me;
221     WRAPPER_SETUP(PerformReschedule, ret_addr, ignore_me)
222 #else
223     WRAPPER_SETUP(PerformReschedule, ignore_me, ignore_me)
224 #endif
225     PerformReschedule(liveness, always_reenter_node);
226     WRAPPER_RETURN(0)
227 }
228
229 # endif /* GRAN */
230
231 /* 
232  * In the threaded world, context switches may occur during one of these
233  * wrapped calls, and when we come back, our stack will have been trashed.
234  * If gcc, in all of its cleverness, tries to store any temporary values on
235  * the stack, we need to separate the restoration function.  See the sparc
236  * code for an example.
237  */
238
239 SEPARATE_WRAPPER_RESTORE
240
241 #endif /* defined(__STG_GCC_REGS__) */
242
243 /* We can perform a runtime check that we have used @_ccall_GC_@ when
244    appropriate using this flag. */
245 StgInt inCCallGC = 0;
246
247 void
248 checkInCCallGC()
249 {
250   if (inCCallGC == 0) {
251     fprintf(stderr, "Error: entering a closure from C without using _ccall_GC_\n");
252     EXIT(EXIT_FAILURE);
253   }
254 }
255 \end{code}
256
257 Hack for -UGRAN setup. % HWL
258
259 \begin{code}
260 #ifndef GRAN
261 void PerformReschedule_wrapper PROTO((W_, W_));
262 void PerformReschedule_wrapper(liveness, always_reenter_node)
263   W_ liveness;
264   W_  always_reenter_node;
265 { }
266 #endif
267 \end{code}