[project @ 2000-09-26 16:45:33 by simonpj]
[ghc-hetmet.git] / ghc / includes / PrimOps.h
1 /* -----------------------------------------------------------------------------
2  * $Id: PrimOps.h,v 1.63 2000/09/26 16:45:34 simonpj Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Macros for primitive operations in STG-ish C code.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #ifndef PRIMOPS_H
11 #define PRIMOPS_H
12
13 /* -----------------------------------------------------------------------------
14    Helpers for the metacircular interpreter.
15    -------------------------------------------------------------------------- */
16
17 #ifdef GHCI
18
19 #define CHASE_INDIRECTIONS(lval)                                        \
20    do {                                                                 \
21         int again;                                                      \
22         do {                                                            \
23            again = 0;                                                   \
24            if (get_itbl((StgClosure*)lval)->type == IND)                \
25               { again = 1; lval = ((StgInd*)lval)->indirectee; }        \
26            else                                                         \
27            if (get_itbl((StgClosure*)lval)->type == IND_OLDGEN)         \
28               { again = 1; lval = ((StgIndOldGen*)lval)->indirectee; }  \
29         } while (again);                                                \
30    } while (0)
31
32 #define indexWordOffClosurezh(r,a,i)                                    \
33    do { StgClosure* tmp = (StgClosure*)(a);                             \
34         CHASE_INDIRECTIONS(tmp);                                        \
35         r = ((W_ *)tmp)[i];                                             \
36    } while (0)
37
38 #define indexPtrOffClosurezh(r,a,i)                                     \
39    do { StgClosure* tmp = (StgClosure*)(a);                             \
40         CHASE_INDIRECTIONS(tmp);                                        \
41         r = ((P_ *)tmp)[i];                                             \
42    } while (0)
43
44
45 #else
46
47 /* These are the original definitions.  They don't chase indirections. */
48 #define indexWordOffClosurezh(r,a,i)    r= ((W_ *)(a))[i]
49 #define indexPtrOffClosurezh(r,a,i)     r= ((P_ *)(a))[i]
50
51 #endif
52
53
54 /* -----------------------------------------------------------------------------
55    Comparison PrimOps.
56    -------------------------------------------------------------------------- */
57
58 #define gtCharzh(r,a,b) r=(I_)((a)> (b))
59 #define geCharzh(r,a,b) r=(I_)((a)>=(b))
60 #define eqCharzh(r,a,b) r=(I_)((a)==(b))
61 #define neCharzh(r,a,b) r=(I_)((a)!=(b))
62 #define ltCharzh(r,a,b) r=(I_)((a)< (b))
63 #define leCharzh(r,a,b) r=(I_)((a)<=(b))
64
65 /* Int comparisons: >#, >=# etc */
66 #define zgzh(r,a,b)     r=(I_)((I_)(a) >(I_)(b))
67 #define zgzezh(r,a,b)   r=(I_)((I_)(a)>=(I_)(b))
68 #define zezezh(r,a,b)   r=(I_)((I_)(a)==(I_)(b))
69 #define zszezh(r,a,b)   r=(I_)((I_)(a)!=(I_)(b))
70 #define zlzh(r,a,b)     r=(I_)((I_)(a) <(I_)(b))
71 #define zlzezh(r,a,b)   r=(I_)((I_)(a)<=(I_)(b))
72
73 #define gtWordzh(r,a,b) r=(I_)((W_)(a) >(W_)(b))
74 #define geWordzh(r,a,b) r=(I_)((W_)(a)>=(W_)(b))
75 #define eqWordzh(r,a,b) r=(I_)((W_)(a)==(W_)(b))
76 #define neWordzh(r,a,b) r=(I_)((W_)(a)!=(W_)(b))
77 #define ltWordzh(r,a,b) r=(I_)((W_)(a) <(W_)(b))
78 #define leWordzh(r,a,b) r=(I_)((W_)(a)<=(W_)(b))
79
80 #define gtAddrzh(r,a,b) r=(I_)((a) >(b))
81 #define geAddrzh(r,a,b) r=(I_)((a)>=(b))
82 #define eqAddrzh(r,a,b) r=(I_)((a)==(b))
83 #define neAddrzh(r,a,b) r=(I_)((a)!=(b))
84 #define ltAddrzh(r,a,b) r=(I_)((a) <(b))
85 #define leAddrzh(r,a,b) r=(I_)((a)<=(b))
86
87 #define gtFloatzh(r,a,b)  r=(I_)((a)> (b))
88 #define geFloatzh(r,a,b)  r=(I_)((a)>=(b))
89 #define eqFloatzh(r,a,b)  r=(I_)((a)==(b))
90 #define neFloatzh(r,a,b)  r=(I_)((a)!=(b))
91 #define ltFloatzh(r,a,b)  r=(I_)((a)< (b))
92 #define leFloatzh(r,a,b)  r=(I_)((a)<=(b))
93
94 /* Double comparisons: >##, >=#@ etc */
95 #define zgzhzh(r,a,b)   r=(I_)((a) >(b))
96 #define zgzezhzh(r,a,b) r=(I_)((a)>=(b))
97 #define zezezhzh(r,a,b) r=(I_)((a)==(b))
98 #define zszezhzh(r,a,b) r=(I_)((a)!=(b))
99 #define zlzhzh(r,a,b)   r=(I_)((a) <(b))
100 #define zlzezhzh(r,a,b) r=(I_)((a)<=(b))
101
102 /* -----------------------------------------------------------------------------
103    Char# PrimOps.
104    -------------------------------------------------------------------------- */
105
106 #define ordzh(r,a)      r=(I_)((W_) (a))
107 #define chrzh(r,a)      r=(StgChar)((W_)(a))
108
109 /* -----------------------------------------------------------------------------
110    Int# PrimOps.
111    -------------------------------------------------------------------------- */
112
113 I_ stg_div (I_ a, I_ b);
114
115 #define zpzh(r,a,b)             r=(a)+(b)
116 #define zmzh(r,a,b)             r=(a)-(b)
117 #define ztzh(r,a,b)             r=(a)*(b)
118 #define quotIntzh(r,a,b)        r=(a)/(b)
119 #define zszh(r,a,b)             r=ULTRASAFESTGCALL2(I_,(void *, I_, I_),stg_div,(a),(b))
120 #define remIntzh(r,a,b)         r=(a)%(b)
121 #define negateIntzh(r,a)        r=-(a)
122
123 /* -----------------------------------------------------------------------------
124  * Int operations with carry.
125  * -------------------------------------------------------------------------- */
126
127 /* With some bit-twiddling, we can define int{Add,Sub}Czh portably in
128  * C, and without needing any comparisons.  This may not be the
129  * fastest way to do it - if you have better code, please send it! --SDM
130  *
131  * Return : r = a + b,  c = 0 if no overflow, 1 on overflow.
132  *
133  * We currently don't make use of the r value if c is != 0 (i.e. 
134  * overflow), we just convert to big integers and try again.  This
135  * could be improved by making r and c the correct values for
136  * plugging into a new J#.  
137  */
138 #define addIntCzh(r,c,a,b)                      \
139 { r = a + b;                                    \
140   c = ((StgWord)(~(a^b) & (a^r)))               \
141     >> (BITS_PER_BYTE * sizeof(I_) - 1);        \
142 }
143
144
145 #define subIntCzh(r,c,a,b)                      \
146 { r = a - b;                                    \
147   c = ((StgWord)((a^b) & (a^r)))                \
148     >> (BITS_PER_BYTE * sizeof(I_) - 1);        \
149 }
150
151 /* Multiply with overflow checking.
152  *
153  * This is slightly more tricky - the usual sign rules for add/subtract
154  * don't apply.  
155  *
156  * On x86 hardware we use a hand-crafted assembly fragment to do the job.
157  *
158  * On other 32-bit machines we use gcc's 'long long' types, finding
159  * overflow with some careful bit-twiddling.
160  *
161  * On 64-bit machines where gcc's 'long long' type is also 64-bits,
162  * we use a crude approximation, testing whether either operand is
163  * larger than 32-bits; if neither is, then we go ahead with the
164  * multiplication.
165  */
166
167 #if i386_TARGET_ARCH
168
169 #define mulIntCzh(r,c,a,b)                              \
170 {                                                       \
171   __asm__("xorl %1,%1\n\t                               \
172            imull %2,%3\n\t                              \
173            jno 1f\n\t                                   \
174            movl $1,%1\n\t                               \
175            1:"                                          \
176         : "=r" (r), "=&r" (c) : "r" (a), "0" (b));      \
177 }
178
179 #elif SIZEOF_VOID_P == 4
180
181 #ifdef WORDS_BIGENDIAN
182 #define C 0
183 #define R 1
184 #else
185 #define C 1
186 #define R 0
187 #endif
188
189 typedef union {
190     StgInt64 l;
191     StgInt32 i[2];
192 } long_long_u ;
193
194 #define mulIntCzh(r,c,a,b)                      \
195 {                                               \
196   long_long_u z;                                \
197   z.l = (StgInt64)a * (StgInt64)b;              \
198   r = z.i[R];                                   \
199   c = z.i[C];                                   \
200   if (c == 0 || c == -1) {                      \
201     c = ((StgWord)((a^b) ^ r))                  \
202       >> (BITS_PER_BYTE * sizeof(I_) - 1);      \
203   }                                             \
204 }
205 /* Careful: the carry calculation above is extremely delicate.  Make sure
206  * you test it thoroughly after changing it.
207  */
208
209 #else
210
211 #define HALF_INT  (1 << (BITS_PER_BYTE * sizeof(I_) / 2))
212
213 #define stg_abs(a) ((a) < 0 ? -(a) : (a))
214
215 #define mulIntCzh(r,c,a,b)                      \
216 {                                               \
217   if (stg_abs(a) >= HALF_INT                    \
218       stg_abs(b) >= HALF_INT) {                 \
219     c = 1;                                      \
220   } else {                                      \
221     r = a * b;                                  \
222     c = 0;                                      \
223   }                                             \
224 }
225 #endif
226
227 /* -----------------------------------------------------------------------------
228    Word PrimOps.
229    -------------------------------------------------------------------------- */
230
231 #define quotWordzh(r,a,b)       r=((W_)a)/((W_)b)
232 #define remWordzh(r,a,b)        r=((W_)a)%((W_)b)
233
234 #define andzh(r,a,b)            r=(a)&(b)
235 #define orzh(r,a,b)             r=(a)|(b)
236 #define xorzh(r,a,b)            r=(a)^(b)
237 #define notzh(r,a)              r=~(a)
238
239 /* The extra tests below properly define the behaviour when shifting
240  * by offsets larger than the width of the value being shifted.  Doing
241  * so is undefined in C (and in fact gives different answers depending
242  * on whether the operation is constant folded or not with gcc on x86!)
243  */
244
245 #define shiftLzh(r,a,b)         r=((b) >= BITS_IN(W_)) ? 0 : (a)<<(b)
246 #define shiftRLzh(r,a,b)        r=((b) >= BITS_IN(W_)) ? 0 : (a)>>(b)
247 #define iShiftLzh(r,a,b)        r=((b) >= BITS_IN(W_)) ? 0 : (a)<<(b)
248 /* Right shifting of signed quantities is not portable in C, so
249    the behaviour you'll get from using these primops depends
250    on the whatever your C compiler is doing. ToDo: fix/document. -- sof 8/98
251 */
252 #define iShiftRAzh(r,a,b)       r=((b) >= BITS_IN(I_)) ? (((a) < 0) ? -1 : 0) : (a)>>(b)
253 #define iShiftRLzh(r,a,b)       r=((b) >= BITS_IN(I_)) ? 0 : ((W_)(a))>>(b)
254
255 #define int2Wordzh(r,a)         r=(W_)(a)
256 #define word2Intzh(r,a)         r=(I_)(a)
257
258 /* -----------------------------------------------------------------------------
259    Addr PrimOps.
260    -------------------------------------------------------------------------- */
261
262 #define int2Addrzh(r,a)         r=(A_)(a)
263 #define addr2Intzh(r,a)         r=(I_)(a)
264
265 #define readCharOffAddrzh(r,a,i)        r= ((unsigned char *)(a))[i]
266 /* unsigned char is for compatibility: the index is still in bytes. */
267 #define readIntOffAddrzh(r,a,i)         r= ((I_ *)(a))[i]
268 #define readWordOffAddrzh(r,a,i)        r= ((W_ *)(a))[i]
269 #define readAddrOffAddrzh(r,a,i)        r= ((PP_)(a))[i]
270 #define readFloatOffAddrzh(r,a,i)       r= PK_FLT((P_) (((StgFloat *)(a)) + i))
271 #define readDoubleOffAddrzh(r,a,i)      r= PK_DBL((P_) (((StgDouble *)(a)) + i))
272 #define readStablePtrOffAddrzh(r,a,i)   r= ((StgStablePtr *)(a))[i]
273 #ifdef SUPPORT_LONG_LONGS
274 #define readInt64OffAddrzh(r,a,i)       r= ((LI_ *)(a))[i]
275 #define readWord64OffAddrzh(r,a,i)      r= ((LW_ *)(a))[i]
276 #endif
277
278 #define writeCharOffAddrzh(a,i,v)       ((unsigned char *)(a))[i] = (unsigned char)(v)
279 /* unsigned char is for compatibility: the index is still in bytes. */
280 #define writeIntOffAddrzh(a,i,v)        ((I_ *)(a))[i] = (v)
281 #define writeWordOffAddrzh(a,i,v)       ((W_ *)(a))[i] = (v)
282 #define writeAddrOffAddrzh(a,i,v)       ((PP_)(a))[i] = (v)
283 #define writeForeignObjOffAddrzh(a,i,v) ((PP_)(a))[i] = ForeignObj_CLOSURE_DATA(v)
284 #define writeFloatOffAddrzh(a,i,v)      ASSIGN_FLT((P_) (((StgFloat *)(a)) + i),v)
285 #define writeDoubleOffAddrzh(a,i,v)     ASSIGN_DBL((P_) (((StgDouble *)(a)) + i),v)
286 #define writeStablePtrOffAddrzh(a,i,v)  ((StgStablePtr *)(a))[i] = (v)
287 #ifdef SUPPORT_LONG_LONGS
288 #define writeInt64OffAddrzh(a,i,v)   ((LI_ *)(a))[i] = (v)
289 #define writeWord64OffAddrzh(a,i,v)  ((LW_ *)(a))[i] = (v)
290 #endif
291
292 #define indexCharOffAddrzh(r,a,i)       r= ((unsigned char *)(a))[i]
293 /* unsigned char is for compatibility: the index is still in bytes. */
294 #define indexIntOffAddrzh(r,a,i)        r= ((I_ *)(a))[i]
295 #define indexWordOffAddrzh(r,a,i)       r= ((W_ *)(a))[i]
296 #define indexAddrOffAddrzh(r,a,i)       r= ((PP_)(a))[i]
297 #define indexFloatOffAddrzh(r,a,i)      r= PK_FLT((P_) (((StgFloat *)(a)) + i))
298 #define indexDoubleOffAddrzh(r,a,i)     r= PK_DBL((P_) (((StgDouble *)(a)) + i))
299 #define indexStablePtrOffAddrzh(r,a,i)  r= ((StgStablePtr *)(a))[i]
300 #ifdef SUPPORT_LONG_LONGS
301 #define indexInt64OffAddrzh(r,a,i)      r= ((LI_ *)(a))[i]
302 #define indexWord64OffAddrzh(r,a,i)     r= ((LW_ *)(a))[i]
303 #endif
304
305 /* -----------------------------------------------------------------------------
306    Float PrimOps.
307    -------------------------------------------------------------------------- */
308
309 #define plusFloatzh(r,a,b)   r=(a)+(b)
310 #define minusFloatzh(r,a,b)  r=(a)-(b)
311 #define timesFloatzh(r,a,b)  r=(a)*(b)
312 #define divideFloatzh(r,a,b) r=(a)/(b)
313 #define negateFloatzh(r,a)   r=-(a)
314                              
315 #define int2Floatzh(r,a)     r=(StgFloat)(a)
316 #define float2Intzh(r,a)     r=(I_)(a)
317                              
318 #define expFloatzh(r,a)      r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,exp,a)
319 #define logFloatzh(r,a)      r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,log,a)
320 #define sqrtFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sqrt,a)
321 #define sinFloatzh(r,a)      r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sin,a)
322 #define cosFloatzh(r,a)      r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cos,a)
323 #define tanFloatzh(r,a)      r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tan,a)
324 #define asinFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,asin,a)
325 #define acosFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,acos,a)
326 #define atanFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,atan,a)
327 #define sinhFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sinh,a)
328 #define coshFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cosh,a)
329 #define tanhFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tanh,a)
330 #define powerFloatzh(r,a,b)  r=(StgFloat) RET_PRIM_STGCALL2(StgDouble,pow,a,b)
331
332 /* -----------------------------------------------------------------------------
333    Double PrimOps.
334    -------------------------------------------------------------------------- */
335
336 #define zpzhzh(r,a,b)        r=(a)+(b)
337 #define zmzhzh(r,a,b)        r=(a)-(b)
338 #define ztzhzh(r,a,b)        r=(a)*(b)
339 #define zszhzh(r,a,b)        r=(a)/(b)
340 #define negateDoublezh(r,a)  r=-(a)
341                              
342 #define int2Doublezh(r,a)    r=(StgDouble)(a)
343 #define double2Intzh(r,a)    r=(I_)(a)
344                              
345 #define float2Doublezh(r,a)  r=(StgDouble)(a)
346 #define double2Floatzh(r,a)  r=(StgFloat)(a)
347                              
348 #define expDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,exp,a)
349 #define logDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,log,a)
350 #define sqrtDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sqrt,a)
351 #define sinDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sin,a)
352 #define cosDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cos,a)
353 #define tanDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tan,a)
354 #define asinDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,asin,a)
355 #define acosDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,acos,a)
356 #define atanDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,atan,a)
357 #define sinhDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sinh,a)
358 #define coshDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cosh,a)
359 #define tanhDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tanh,a)
360 /* Power: **## */
361 #define ztztzhzh(r,a,b) r=(StgDouble) RET_PRIM_STGCALL2(StgDouble,pow,a,b)
362
363 /* -----------------------------------------------------------------------------
364    Integer PrimOps.
365    -------------------------------------------------------------------------- */
366
367 /* We can do integer2Int and cmpInteger inline, since they don't need
368  * to allocate any memory.
369  *
370  * integer2Int# is now modular.
371  */
372
373 #define integer2Intzh(r, sa,da)                         \
374 { StgWord word0 = ((StgWord *)BYTE_ARR_CTS(da))[0];     \
375   int size = sa;                                        \
376                                                         \
377   (r) =                                                 \
378     ( size == 0 ) ?                                     \
379        0 :                                              \
380        ( size < 0 && word0 != 0x8000000 ) ?             \
381          -(I_)word0 :                                   \
382           (I_)word0;                                    \
383 }
384
385 #define integer2Wordzh(r, sa,da)                        \
386 { StgWord word0 = ((StgWord *)BYTE_ARR_CTS(da))[0];     \
387   int size = sa;                                        \
388   (r) = ( size == 0 ) ? 0 : word0 ;                     \
389 }
390
391 #define cmpIntegerzh(r, s1,d1, s2,d2)                           \
392 { MP_INT arg1;                                                  \
393   MP_INT arg2;                                                  \
394                                                                 \
395   arg1._mp_size = (s1);                                         \
396   arg1._mp_alloc= ((StgArrWords *)d1)->words;                   \
397   arg1._mp_d    = (unsigned long int *) (BYTE_ARR_CTS(d1));     \
398   arg2._mp_size = (s2);                                         \
399   arg2._mp_alloc= ((StgArrWords *)d2)->words;                   \
400   arg2._mp_d    = (unsigned long int *) (BYTE_ARR_CTS(d2));     \
401                                                                 \
402   (r) = RET_PRIM_STGCALL2(I_,mpz_cmp,&arg1,&arg2);              \
403 }
404
405 #define cmpIntegerIntzh(r, s,d, i)                              \
406 { MP_INT arg;                                                   \
407                                                                 \
408   arg._mp_size  = (s);                                          \
409   arg._mp_alloc = ((StgArrWords *)d)->words;                    \
410   arg._mp_d     = (unsigned long int *) (BYTE_ARR_CTS(d));      \
411                                                                 \
412   (r) = RET_PRIM_STGCALL2(I_,mpz_cmp_si,&arg,i);                \
413 }
414
415 /* NOTE: gcdIntzh and gcdIntegerIntzh work only for positive inputs! */
416
417 /* mp_limb_t must be able to hold an StgInt for this to work properly */
418 #define gcdIntzh(r,a,b) \
419 { mp_limb_t aa = (mp_limb_t)(a); \
420   r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(&aa), 1, (mp_limb_t)(b)); \
421 }
422
423 #define gcdIntegerIntzh(r,sa,a,b) \
424   r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(BYTE_ARR_CTS(a)), sa, b)
425
426 /* The rest are all out-of-line: -------- */
427
428 /* Integer arithmetic */
429 EXTFUN_RTS(plusIntegerzh_fast);
430 EXTFUN_RTS(minusIntegerzh_fast);
431 EXTFUN_RTS(timesIntegerzh_fast);
432 EXTFUN_RTS(gcdIntegerzh_fast);
433 EXTFUN_RTS(quotRemIntegerzh_fast);
434 EXTFUN_RTS(quotIntegerzh_fast);
435 EXTFUN_RTS(remIntegerzh_fast);
436 EXTFUN_RTS(divExactIntegerzh_fast);
437 EXTFUN_RTS(divModIntegerzh_fast);
438
439 /* Conversions */
440 EXTFUN_RTS(int2Integerzh_fast);
441 EXTFUN_RTS(word2Integerzh_fast);
442
443 /* Floating-point decodings */
444 EXTFUN_RTS(decodeFloatzh_fast);
445 EXTFUN_RTS(decodeDoublezh_fast);
446
447 /* -----------------------------------------------------------------------------
448    Word64 PrimOps.
449    -------------------------------------------------------------------------- */
450
451 #ifdef SUPPORT_LONG_LONGS
452
453 #define integerToWord64zh(r, sa,da)                     \
454 { unsigned long int* d;                                 \
455   I_ s;                                                 \
456   StgWord64 res;                                        \
457                                                         \
458   d = (unsigned long int *) (BYTE_ARR_CTS(da));         \
459   s = (sa);                                             \
460   if ( s == 0 ) {                                       \
461      res = (LW_)0;                                      \
462   } else if ( s == 1) {                                 \
463      res = (LW_)d[0];                                   \
464   } else {                                              \
465      res = (LW_)d[0] + (LW_)d[1] * 0x100000000ULL;      \
466   }                                                     \
467   (r) = res;                                            \
468 }
469
470 #define integerToInt64zh(r, sa,da)                      \
471 { unsigned long int* d;                                 \
472   I_ s;                                                 \
473   StgInt64 res;                                         \
474                                                         \
475   d = (unsigned long int *) (BYTE_ARR_CTS(da));         \
476   s = (sa);                                             \
477   if ( s == 0 ) {                                       \
478      res = (LI_)0;                                      \
479   } else if ( s == 1) {                                 \
480      res = (LI_)d[0];                                   \
481   } else {                                              \
482      res = (LI_)d[0] + (LI_)d[1] * 0x100000000LL;       \
483      if ( s < 0 ) {                                     \
484            res = (LI_)-res;                             \
485      }                                                  \
486   }                                                     \
487   (r) = res;                                            \
488 }
489
490 /* Conversions */
491 EXTFUN_RTS(int64ToIntegerzh_fast);
492 EXTFUN_RTS(word64ToIntegerzh_fast);
493
494 /* The rest are (way!) out of line, implemented via C entry points.
495  */
496 I_ stg_gtWord64 (StgWord64, StgWord64);
497 I_ stg_geWord64 (StgWord64, StgWord64);
498 I_ stg_eqWord64 (StgWord64, StgWord64);
499 I_ stg_neWord64 (StgWord64, StgWord64);
500 I_ stg_ltWord64 (StgWord64, StgWord64);
501 I_ stg_leWord64 (StgWord64, StgWord64);
502
503 I_ stg_gtInt64 (StgInt64, StgInt64);
504 I_ stg_geInt64 (StgInt64, StgInt64);
505 I_ stg_eqInt64 (StgInt64, StgInt64);
506 I_ stg_neInt64 (StgInt64, StgInt64);
507 I_ stg_ltInt64 (StgInt64, StgInt64);
508 I_ stg_leInt64 (StgInt64, StgInt64);
509
510 LW_ stg_remWord64  (StgWord64, StgWord64);
511 LW_ stg_quotWord64 (StgWord64, StgWord64);
512
513 LI_ stg_remInt64    (StgInt64, StgInt64);
514 LI_ stg_quotInt64   (StgInt64, StgInt64);
515 LI_ stg_negateInt64 (StgInt64);
516 LI_ stg_plusInt64   (StgInt64, StgInt64);
517 LI_ stg_minusInt64  (StgInt64, StgInt64);
518 LI_ stg_timesInt64  (StgInt64, StgInt64);
519
520 LW_ stg_and64  (StgWord64, StgWord64);
521 LW_ stg_or64   (StgWord64, StgWord64);
522 LW_ stg_xor64  (StgWord64, StgWord64);
523 LW_ stg_not64  (StgWord64);
524
525 LW_ stg_shiftL64   (StgWord64, StgInt);
526 LW_ stg_shiftRL64  (StgWord64, StgInt);
527 LI_ stg_iShiftL64  (StgInt64, StgInt);
528 LI_ stg_iShiftRL64 (StgInt64, StgInt);
529 LI_ stg_iShiftRA64 (StgInt64, StgInt);
530
531 LI_ stg_intToInt64    (StgInt);
532 I_ stg_int64ToInt     (StgInt64);
533 LW_ stg_int64ToWord64 (StgInt64);
534
535 LW_ stg_wordToWord64  (StgWord);
536 W_  stg_word64ToWord  (StgWord64);
537 LI_ stg_word64ToInt64 (StgWord64);
538 #endif
539
540 /* -----------------------------------------------------------------------------
541    Array PrimOps.
542    -------------------------------------------------------------------------- */
543
544 /* We cast to void* instead of StgChar* because this avoids a warning
545  * about increasing the alignment requirements.
546  */
547 #define REAL_BYTE_ARR_CTS(a)   ((void *) (((StgArrWords *)(a))->payload))
548 #define REAL_PTRS_ARR_CTS(a)   ((P_)   (((StgMutArrPtrs  *)(a))->payload))
549
550 #ifdef DEBUG
551 #define BYTE_ARR_CTS(a)                           \
552  ({ ASSERT(GET_INFO((StgArrWords *)(a)) == &ARR_WORDS_info);      \
553     REAL_BYTE_ARR_CTS(a); })
554 #define PTRS_ARR_CTS(a)                           \
555  ({ ASSERT((GET_INFO((StgMutArrPtrs  *)(a)) == &MUT_ARR_PTRS_FROZEN_info)         \
556         || (GET_INFO((StgMutArrPtrs  *)(a)) == &MUT_ARR_PTRS_info));  \
557     REAL_PTRS_ARR_CTS(a); })
558 #else
559 #define BYTE_ARR_CTS(a)         REAL_BYTE_ARR_CTS(a)
560 #define PTRS_ARR_CTS(a)         REAL_PTRS_ARR_CTS(a)
561 #endif
562
563 extern I_ genSymZh(void);
564 extern I_ resetGenSymZh(void);
565
566 /*--- everything except new*Array is done inline: */
567
568 #define sameMutableArrayzh(r,a,b)       r=(I_)((a)==(b))
569 #define sameMutableByteArrayzh(r,a,b)   r=(I_)((a)==(b))
570
571 #define readArrayzh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
572
573 #define readCharArrayzh(r,a,i)   indexCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
574 #define readIntArrayzh(r,a,i)    indexIntOffAddrzh(r,BYTE_ARR_CTS(a),i)
575 #define readWordArrayzh(r,a,i)   indexWordOffAddrzh(r,BYTE_ARR_CTS(a),i)
576 #define readAddrArrayzh(r,a,i)   indexAddrOffAddrzh(r,BYTE_ARR_CTS(a),i)
577 #define readFloatArrayzh(r,a,i)  indexFloatOffAddrzh(r,BYTE_ARR_CTS(a),i)
578 #define readDoubleArrayzh(r,a,i) indexDoubleOffAddrzh(r,BYTE_ARR_CTS(a),i)
579 #define readStablePtrArrayzh(r,a,i) indexStablePtrOffAddrzh(r,BYTE_ARR_CTS(a),i)
580 #ifdef SUPPORT_LONG_LONGS
581 #define readInt64Arrayzh(r,a,i)  indexInt64OffAddrzh(r,BYTE_ARR_CTS(a),i)
582 #define readWord64Arrayzh(r,a,i) indexWord64OffAddrzh(r,BYTE_ARR_CTS(a),i)
583 #endif
584
585 /* result ("r") arg ignored in write macros! */
586 #define writeArrayzh(a,i,v)     ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
587
588 #define writeCharArrayzh(a,i,v)   ((unsigned char *)(BYTE_ARR_CTS(a)))[i] = (unsigned char)(v)
589 /* unsigned char is for compatibility: the index is still in bytes. */
590 #define writeIntArrayzh(a,i,v)    ((I_ *)(BYTE_ARR_CTS(a)))[i] = (v)
591 #define writeWordArrayzh(a,i,v)   ((W_ *)(BYTE_ARR_CTS(a)))[i] = (v)
592 #define writeAddrArrayzh(a,i,v)   ((PP_)(BYTE_ARR_CTS(a)))[i] = (v)
593 #define writeFloatArrayzh(a,i,v)  \
594         ASSIGN_FLT((P_) (((StgFloat *)(BYTE_ARR_CTS(a))) + i),v)
595 #define writeDoubleArrayzh(a,i,v) \
596         ASSIGN_DBL((P_) (((StgDouble *)(BYTE_ARR_CTS(a))) + i),v)
597 #define writeStablePtrArrayzh(a,i,v)      ((StgStablePtr *)(BYTE_ARR_CTS(a)))[i] = (v)
598 #ifdef SUPPORT_LONG_LONGS
599 #define writeInt64Arrayzh(a,i,v)  ((LI_ *)(BYTE_ARR_CTS(a)))[i] = (v)
600 #define writeWord64Arrayzh(a,i,v) ((LW_ *)(BYTE_ARR_CTS(a)))[i] = (v)
601 #endif
602
603 #define indexArrayzh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
604
605 #define indexCharArrayzh(r,a,i)   indexCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
606 #define indexIntArrayzh(r,a,i)    indexIntOffAddrzh(r,BYTE_ARR_CTS(a),i)
607 #define indexWordArrayzh(r,a,i)   indexWordOffAddrzh(r,BYTE_ARR_CTS(a),i)
608 #define indexAddrArrayzh(r,a,i)   indexAddrOffAddrzh(r,BYTE_ARR_CTS(a),i)
609 #define indexFloatArrayzh(r,a,i)  indexFloatOffAddrzh(r,BYTE_ARR_CTS(a),i)
610 #define indexDoubleArrayzh(r,a,i) indexDoubleOffAddrzh(r,BYTE_ARR_CTS(a),i)
611 #define indexStablePtrArrayzh(r,a,i) indexStablePtrOffAddrzh(r,BYTE_ARR_CTS(a),i)
612 #ifdef SUPPORT_LONG_LONGS
613 #define indexInt64Arrayzh(r,a,i)  indexInt64OffAddrzh(r,BYTE_ARR_CTS(a),i)
614 #define indexWord64Arrayzh(r,a,i) indexWord64OffAddrzh(r,BYTE_ARR_CTS(a),i)
615 #endif
616
617 /* Freezing arrays-of-ptrs requires changing an info table, for the
618    benefit of the generational collector.  It needs to scavenge mutable
619    objects, even if they are in old space.  When they become immutable,
620    they can be removed from this scavenge list.  */
621
622 #define unsafeFreezzeArrayzh(r,a)                                       \
623         {                                                               \
624         SET_INFO((StgClosure *)a,&MUT_ARR_PTRS_FROZEN_info);            \
625         r = a;                                                          \
626         }
627
628 #define unsafeFreezzeByteArrayzh(r,a)   r=(a)
629
630 EXTFUN_RTS(unsafeThawArrayzh_fast);
631
632 #define sizzeofByteArrayzh(r,a) \
633      r = (((StgArrWords *)(a))->words * sizeof(W_))
634 #define sizzeofMutableByteArrayzh(r,a) \
635      r = (((StgArrWords *)(a))->words * sizeof(W_))
636
637 /* and the out-of-line ones... */
638
639 EXTFUN_RTS(newCharArrayzh_fast);
640 EXTFUN_RTS(newIntArrayzh_fast);
641 EXTFUN_RTS(newWordArrayzh_fast);
642 EXTFUN_RTS(newAddrArrayzh_fast);
643 EXTFUN_RTS(newFloatArrayzh_fast);
644 EXTFUN_RTS(newDoubleArrayzh_fast);
645 EXTFUN_RTS(newStablePtrArrayzh_fast);
646 EXTFUN_RTS(newArrayzh_fast);
647
648 /* encoding and decoding of floats/doubles. */
649
650 /* We only support IEEE floating point format */
651 #include "ieee-flpt.h"
652
653 /* The decode operations are out-of-line because they need to allocate
654  * a byte array.
655  */
656 #ifdef FLOATS_AS_DOUBLES
657 #define decodeFloatzh_fast decodeDoublezh_fast
658 #else
659 EXTFUN_RTS(decodeFloatzh_fast);
660 #endif
661
662 EXTFUN_RTS(decodeDoublezh_fast);
663
664 /* grimy low-level support functions defined in StgPrimFloat.c */
665
666 extern StgDouble __encodeDouble (I_ size, StgByteArray arr, I_ e);
667 extern StgDouble __int_encodeDouble (I_ j, I_ e);
668 #ifndef FLOATS_AS_DOUBLES
669 extern StgFloat  __encodeFloat (I_ size, StgByteArray arr, I_ e);
670 extern StgFloat  __int_encodeFloat (I_ j, I_ e);
671 #endif
672 extern void      __decodeDouble (MP_INT *man, I_ *_exp, StgDouble dbl);
673 extern void      __decodeFloat  (MP_INT *man, I_ *_exp, StgFloat flt);
674 extern StgInt    isDoubleNaN(StgDouble d);
675 extern StgInt    isDoubleInfinite(StgDouble d);
676 extern StgInt    isDoubleDenormalized(StgDouble d);
677 extern StgInt    isDoubleNegativeZero(StgDouble d);
678 extern StgInt    isFloatNaN(StgFloat f);
679 extern StgInt    isFloatInfinite(StgFloat f);
680 extern StgInt    isFloatDenormalized(StgFloat f);
681 extern StgInt    isFloatNegativeZero(StgFloat f);
682
683 /* -----------------------------------------------------------------------------
684    Mutable variables
685
686    newMutVar is out of line.
687    -------------------------------------------------------------------------- */
688
689 EXTFUN_RTS(newMutVarzh_fast);
690
691 #define readMutVarzh(r,a)        r=(P_)(((StgMutVar *)(a))->var)
692 #define writeMutVarzh(a,v)       (P_)(((StgMutVar *)(a))->var)=(v)
693 #define sameMutVarzh(r,a,b)      r=(I_)((a)==(b))
694
695 /* -----------------------------------------------------------------------------
696    MVar PrimOps.
697
698    All out of line, because they either allocate or may block.
699    -------------------------------------------------------------------------- */
700 #define sameMVarzh(r,a,b)        r=(I_)((a)==(b))
701
702 /* Assume external decl of EMPTY_MVAR_info is in scope by now */
703 #define isEmptyMVarzh(r,a)       r=(I_)((GET_INFO((StgMVar*)(a))) == &EMPTY_MVAR_info )
704 EXTFUN_RTS(newMVarzh_fast);
705 EXTFUN_RTS(takeMVarzh_fast);
706 EXTFUN_RTS(tryTakeMVarzh_fast);
707 EXTFUN_RTS(putMVarzh_fast);
708
709
710 /* -----------------------------------------------------------------------------
711    Delay/Wait PrimOps
712    -------------------------------------------------------------------------- */
713
714 EXTFUN_RTS(waitReadzh_fast);
715 EXTFUN_RTS(waitWritezh_fast);
716 EXTFUN_RTS(delayzh_fast);
717
718 /* -----------------------------------------------------------------------------
719    Primitive I/O, error-handling PrimOps
720    -------------------------------------------------------------------------- */
721
722 EXTFUN_RTS(catchzh_fast);
723 EXTFUN_RTS(raisezh_fast);
724
725 extern void stg_exit(I_ n)  __attribute__ ((noreturn));
726
727 /* -----------------------------------------------------------------------------
728    Stable Name / Stable Pointer  PrimOps
729    -------------------------------------------------------------------------- */
730
731 #ifndef PAR
732
733 EXTFUN_RTS(makeStableNamezh_fast);
734
735 #define stableNameToIntzh(r,s)   (r = ((StgStableName *)s)->sn)
736
737 #define eqStableNamezh(r,sn1,sn2)                                       \
738     (r = (((StgStableName *)sn1)->sn == ((StgStableName *)sn2)->sn))
739
740 #define makeStablePtrzh(r,a) \
741    r = RET_STGCALL1(StgStablePtr,getStablePtr,a)
742
743 #define deRefStablePtrzh(r,sp) do {             \
744   ASSERT(stable_ptr_table[stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK].weight > 0);    \
745   r = stable_ptr_table[stgCast(StgWord,sp) & ~STABLEPTR_WEIGHT_MASK].addr; \
746 } while (0);
747
748 #define eqStablePtrzh(r,sp1,sp2) \
749     (r = ((stgCast(StgWord,sp1) & ~STABLEPTR_WEIGHT_MASK) == (stgCast(StgWord,sp2) & ~STABLEPTR_WEIGHT_MASK)))
750
751 #endif
752
753 /* -----------------------------------------------------------------------------
754    Concurrency/Exception PrimOps.
755    -------------------------------------------------------------------------- */
756
757 EXTFUN_RTS(forkzh_fast);
758 EXTFUN_RTS(yieldzh_fast);
759 EXTFUN_RTS(killThreadzh_fast);
760 EXTFUN_RTS(seqzh_fast);
761 EXTFUN_RTS(blockAsyncExceptionszh_fast);
762 EXTFUN_RTS(unblockAsyncExceptionszh_fast);
763
764 #define myThreadIdzh(t) (t = CurrentTSO)
765
766 extern int cmp_thread(const StgTSO *tso1, const StgTSO *tso2);
767
768 /* ------------------------------------------------------------------------
769    Parallel PrimOps
770
771    A par in the Haskell code is ultimately translated to a parzh macro
772    (with a case wrapped around it to guarantee that the macro is actually 
773     executed; see compiler/prelude/PrimOps.lhs)
774    In GUM and SMP we only add a pointer to the spark pool.
775    In GranSim we call an RTS fct, forwarding additional parameters which
776    supply info on granularity of the computation, size of the result value
777    and the degree of parallelism in the sparked expression.
778    ---------------------------------------------------------------------- */
779
780 #if defined(GRAN)
781 //@cindex _par_
782 #define parzh(r,node)             PAR(r,node,1,0,0,0,0,0)
783
784 //@cindex _parAt_
785 #define parAtzh(r,node,where,identifier,gran_info,size_info,par_info,rest) \
786         parAT(r,node,where,identifier,gran_info,size_info,par_info,rest,1)
787
788 //@cindex _parAtAbs_
789 #define parAtAbszh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
790         parAT(r,node,proc,identifier,gran_info,size_info,par_info,rest,2)
791
792 //@cindex _parAtRel_
793 #define parAtRelzh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
794         parAT(r,node,proc,identifier,gran_info,size_info,par_info,rest,3)
795
796 //@cindex _parAtForNow_
797 #define parAtForNowzh(r,node,where,identifier,gran_info,size_info,par_info,rest)        \
798         parAT(r,node,where,identifier,gran_info,size_info,par_info,rest,0)
799
800 #define parAT(r,node,where,identifier,gran_info,size_info,par_info,rest,local)  \
801 {                                                               \
802   if (closure_SHOULD_SPARK((StgClosure*)node)) {                \
803     rtsSparkQ result;                                           \
804     PEs p;                                                      \
805                                                                 \
806     STGCALL6(newSpark, node,identifier,gran_info,size_info,par_info,local); \
807     switch (local) {                                                        \
808       case 2: p = where;  /* parAtAbs means absolute PE no. expected */     \
809               break;                                                        \
810       case 3: p = CurrentProc+where; /* parAtRel means rel PE no. expected */\
811               break;                                                        \
812       default: p = where_is(where); /* parAt means closure expected */      \
813               break;                                                        \
814     }                                                                       \
815     /* update GranSim state according to this spark */                      \
816     STGCALL3(GranSimSparkAtAbs, result, (I_)p, identifier);                 \
817   }                                                                         \
818 }
819
820 //@cindex _parLocal_
821 #define parLocalzh(r,node,identifier,gran_info,size_info,par_info,rest) \
822         PAR(r,node,rest,identifier,gran_info,size_info,par_info,1)
823
824 //@cindex _parGlobal_
825 #define parGlobalzh(r,node,identifier,gran_info,size_info,par_info,rest) \
826         PAR(r,node,rest,identifier,gran_info,size_info,par_info,0)
827
828 #define PAR(r,node,rest,identifier,gran_info,size_info,par_info,local) \
829 {                                                                        \
830   if (closure_SHOULD_SPARK((StgClosure*)node)) {                         \
831     rtsSpark *result;                                                    \
832     result = RET_STGCALL6(rtsSpark*, newSpark,                           \
833                           node,identifier,gran_info,size_info,par_info,local);\
834     STGCALL1(add_to_spark_queue,result);                                \
835     STGCALL2(GranSimSpark, local,(P_)node);                             \
836   }                                                                     \
837 }
838
839 #define copyablezh(r,node)                              \
840   /* copyable not yet implemented!! */
841
842 #define noFollowzh(r,node)                              \
843   /* noFollow not yet implemented!! */
844
845 #elif defined(SMP) || defined(PAR)
846
847 #define parzh(r,node)                                   \
848 {                                                       \
849   extern unsigned int context_switch;                   \
850   if (closure_SHOULD_SPARK((StgClosure *)node) &&       \
851       SparkTl < SparkLim) {                             \
852     *SparkTl++ = (StgClosure *)(node);                  \
853   }                                                     \
854   r = context_switch = 1;                               \
855 }
856 #else /* !GRAN && !SMP && !PAR */
857 #define parzh(r,node) r = 1
858 #endif
859
860 /* -----------------------------------------------------------------------------
861    Pointer equality
862    -------------------------------------------------------------------------- */
863
864 /* warning: extremely non-referentially transparent, need to hide in
865    an appropriate monad.
866
867    ToDo: follow indirections.  
868 */
869
870 #define reallyUnsafePtrEqualityzh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
871
872 /* -----------------------------------------------------------------------------
873    Weak Pointer PrimOps.
874    -------------------------------------------------------------------------- */
875
876 #ifndef PAR
877
878 EXTFUN_RTS(mkWeakzh_fast);
879 EXTFUN_RTS(finalizzeWeakzh_fast);
880
881 #define deRefWeakzh(code,val,w)                         \
882   if (((StgWeak *)w)->header.info == &WEAK_info) {      \
883         code = 1;                                       \
884         val = (P_)((StgWeak *)w)->value;                \
885   } else {                                              \
886         code = 0;                                       \
887         val = (P_)w;                                    \
888   }
889
890 #define sameWeakzh(w1,w2)  ((w1)==(w2))
891
892 #endif
893
894 /* -----------------------------------------------------------------------------
895    Foreign Object PrimOps.
896    -------------------------------------------------------------------------- */
897
898 #ifndef PAR
899
900 #define ForeignObj_CLOSURE_DATA(c)  (((StgForeignObj *)c)->data)
901
902 #define foreignObjToAddrzh(r,fo)    r=ForeignObj_CLOSURE_DATA(fo)
903 #define touchzh(o)                  /* nothing */
904
905 EXTFUN_RTS(mkForeignObjzh_fast);
906
907 #define writeForeignObjzh(res,datum) \
908    (ForeignObj_CLOSURE_DATA(res) = (P_)(datum))
909
910 #define eqForeignObj(f1,f2)  ((f1)==(f2))
911
912 #define indexCharOffForeignObjzh(r,fo,i)   indexCharOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
913 #define indexIntOffForeignObjzh(r,fo,i)    indexIntOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
914 #define indexWordOffForeignObjzh(r,fo,i)   indexWordOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
915 #define indexAddrOffForeignObjzh(r,fo,i)   indexAddrOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
916 #define indexFloatOffForeignObjzh(r,fo,i)  indexFloatOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
917 #define indexDoubleOffForeignObjzh(r,fo,i) indexDoubleOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
918 #define indexStablePtrOffForeignObjzh(r,fo,i)  indexStablePtrOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
919 #ifdef SUPPORT_LONG_LONGS
920 #define indexInt64OffForeignObjzh(r,fo,i)  indexInt64OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
921 #define indexWord64OffForeignObjzh(r,fo,i) indexWord64OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
922 #endif
923
924 #endif
925
926
927 /* -----------------------------------------------------------------------------
928    Constructor tags
929    -------------------------------------------------------------------------- */
930
931 #ifdef GHCI
932 #define dataToTagzh(r,a)                                                \
933    do { StgClosure* tmp = (StgClosure*)(a);                             \
934         CHASE_INDIRECTIONS(tmp);                                        \
935         r = (GET_TAG(((StgClosure *)tmp)->header.info));                \
936    } while (0)
937 #else
938 /* Original version doesn't chase indirections. */
939 #define dataToTagzh(r,a)  r=(GET_TAG(((StgClosure *)a)->header.info))
940 #endif
941
942 /*  tagToEnum# is handled directly by the code generator. */
943
944 /* -----------------------------------------------------------------------------
945    Signal processing.  Not really primops, but called directly from
946    Haskell. 
947    -------------------------------------------------------------------------- */
948
949 #define STG_SIG_DFL  (-1)
950 #define STG_SIG_IGN  (-2)
951 #define STG_SIG_ERR  (-3)
952 #define STG_SIG_HAN  (-4)
953
954 extern StgInt sig_install (StgInt, StgInt, StgStablePtr, sigset_t *);
955 #define stg_sig_default(sig,mask) sig_install(sig,STG_SIG_DFL,0,(sigset_t *)mask)
956 #define stg_sig_ignore(sig,mask) sig_install(sig,STG_SIG_IGN,0,(sigset_t *)mask)
957 #define stg_sig_catch(sig,ptr,mask) sig_install(sig,STG_SIG_HAN,ptr,(sigset_t *)mask)
958
959 #endif /* PRIMOPS_H */