3d3283e8117bd9dee3887ea3d88d2f91eabf2436
[ghc-hetmet.git] / includes / Cmm.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The University of Glasgow 2004
4  *
5  * This file is included at the top of all .cmm source files (and
6  * *only* .cmm files).  It defines a collection of useful macros for
7  * making .cmm code a bit less error-prone to write, and a bit easier
8  * on the eye for the reader.
9  *
10  * For the syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
11  *
12  * If you're used to the old HC file syntax, here's a quick cheat sheet
13  * for converting HC code:
14  *
15  *       - Remove FB_/FE_
16  *       - Remove all type casts
17  *       - Remove '&'
18  *       - STGFUN(foo) { ... }  ==>  foo { ... }
19  *       - FN_(foo) { ... }  ==>  foo { ... }
20  *       - JMP_(e)  ==> jump e;
21  *       - Remove EXTFUN(foo)
22  *       - Sp[n]  ==>  Sp(n)
23  *       - Hp[n]  ==>  Hp(n)
24  *       - Sp += n  ==> Sp_adj(n)
25  *       - Hp += n  ==> Hp_adj(n)
26  *       - R1.i   ==>  R1   (similarly for R1.w, R1.cl etc.)
27  *       - You need to explicitly dereference variables; eg. 
28  *             context_switch   ==>  CInt[context_switch]
29  *       - convert all word offsets into byte offsets:
30  *              - e ==> WDS(e)
31  *       - sizeofW(StgFoo)  ==>  SIZEOF_StgFoo
32  *       - ENTRY_CODE(e)  ==>  %ENTRY_CODE(e)
33  *       - get_itbl(c)  ==>  %GET_STD_INFO(c)
34  *       - Change liveness masks in STK_CHK_GEN, HP_CHK_GEN:
35  *              R1_PTR | R2_PTR  ==>  R1_PTR & R2_PTR
36  *              (NOTE: | becomes &)
37  *       - Declarations like 'StgPtr p;' become just 'W_ p;'
38  *       - e->payload[n] ==> PAYLOAD(e,n)
39  *       - Be very careful with comparisons: the infix versions (>, >=, etc.)
40  *         are unsigned, so use %lt(a,b) to get signed less-than for example.
41  *
42  * Accessing fields of structures defined in the RTS header files is
43  * done via automatically-generated macros in DerivedConstants.h.  For
44  * example, where previously we used
45  *
46  *          CurrentTSO->what_next = x
47  *
48  * in C-- we now use
49  *
50  *          StgTSO_what_next(CurrentTSO) = x
51  *
52  * where the StgTSO_what_next() macro is automatically generated by
53  * mkDerivedConstnants.c.  If you need to access a field that doesn't
54  * already have a macro, edit that file (it's pretty self-explanatory).
55  *
56  * -------------------------------------------------------------------------- */
57
58 #ifndef CMM_H
59 #define CMM_H
60
61 /*
62  * In files that are included into both C and C-- (and perhaps
63  * Haskell) sources, we sometimes need to conditionally compile bits
64  * depending on the language.  CMINUSMINUS==1 in .cmm sources:
65  */
66 #define CMINUSMINUS 1
67
68 #include "ghcconfig.h"
69 #include "RtsConfig.h"
70
71 /* -----------------------------------------------------------------------------
72    Types 
73
74    The following synonyms for C-- types are declared here:
75
76      I8, I16, I32, I64    MachRep-style names for convenience
77
78      W_                   is shorthand for the word type (== StgWord)
79      F_                   shorthand for float  (F_ == StgFloat == C's float)
80      D_                   shorthand for double (D_ == StgDouble == C's double)
81
82      CInt                 has the same size as an int in C on this platform
83      CLong                has the same size as a long in C on this platform
84    
85   --------------------------------------------------------------------------- */
86
87 #define I8  bits8
88 #define I16 bits16
89 #define I32 bits32
90 #define I64 bits64
91
92 #if SIZEOF_VOID_P == 4
93 #define W_ bits32
94 #elif SIZEOF_VOID_P == 8
95 #define W_ bits64
96 #else
97 #error Unknown word size
98 #endif
99
100 #if SIZEOF_INT == 4
101 #define CInt bits32
102 #elif SIZEOF_INT == 8
103 #define CInt bits64
104 #else
105 #error Unknown int size
106 #endif
107
108 #if SIZEOF_LONG == 4
109 #define CLong bits32
110 #elif SIZEOF_LONG == 8
111 #define CLong bits64
112 #else
113 #error Unknown long size
114 #endif
115
116 #define F_ float32
117 #define D_ float64
118 #define L_ bits64
119
120 #define SIZEOF_StgDouble 8
121 #define SIZEOF_StgWord64 8
122
123 /* -----------------------------------------------------------------------------
124    Misc useful stuff
125    -------------------------------------------------------------------------- */
126
127 #define NULL (0::W_)
128
129 #define STRING(name,str)                        \
130   section "rodata" {                            \
131         name : bits8[] str;                     \
132   }                                             \
133
134 /* -----------------------------------------------------------------------------
135    Byte/word macros
136
137    Everything in C-- is in byte offsets (well, most things).  We use
138    some macros to allow us to express offsets in words and to try to
139    avoid byte/word confusion.
140    -------------------------------------------------------------------------- */
141
142 #define SIZEOF_W  SIZEOF_VOID_P
143 #define W_MASK    (SIZEOF_W-1)
144
145 #if SIZEOF_W == 4
146 #define W_SHIFT 2
147 #elif SIZEOF_W == 8
148 #define W_SHIFT 4
149 #endif
150
151 /* Converting quantities of words to bytes */
152 #define WDS(n) ((n)*SIZEOF_W)
153
154 /*
155  * Converting quantities of bytes to words
156  * NB. these work on *unsigned* values only
157  */
158 #define BYTES_TO_WDS(n) ((n) / SIZEOF_W)
159 #define ROUNDUP_BYTES_TO_WDS(n) (((n) + SIZEOF_W - 1) / SIZEOF_W)
160
161 /* TO_W_(n) converts n to W_ type from a smaller type */
162 #if SIZEOF_W == 4
163 #define TO_W_(x) %sx32(x)
164 #define HALF_W_(x) %lobits16(x)
165 #elif SIZEOF_W == 8
166 #define TO_W_(x) %sx64(x)
167 #define HALF_W_(x) %lobits32(x)
168 #endif
169
170 #if SIZEOF_INT == 4 && SIZEOF_W == 8
171 #define W_TO_INT(x) %lobits32(x)
172 #elif SIZEOF_INT == SIZEOF_W
173 #define W_TO_INT(x) (x)
174 #endif
175
176 /* -----------------------------------------------------------------------------
177    Heap/stack access, and adjusting the heap/stack pointers.
178    -------------------------------------------------------------------------- */
179
180 #define Sp(n)  W_[Sp + WDS(n)]
181 #define Hp(n)  W_[Hp + WDS(n)]
182
183 #define Sp_adj(n) Sp = Sp + WDS(n)
184 #define Hp_adj(n) Hp = Hp + WDS(n)
185
186 /* -----------------------------------------------------------------------------
187    Assertions and Debuggery
188    -------------------------------------------------------------------------- */
189
190 #ifdef DEBUG
191 #define ASSERT(predicate)                       \
192         if (predicate) {                        \
193             /*null*/;                           \
194         } else {                                \
195             foreign "C" _assertFail(NULL, __LINE__); \
196         }
197 #else
198 #define ASSERT(p) /* nothing */
199 #endif
200
201 #ifdef DEBUG
202 #define DEBUG_ONLY(s) s
203 #else
204 #define DEBUG_ONLY(s) /* nothing */
205 #endif
206
207 /*
208  * The IF_DEBUG macro is useful for debug messages that depend on one
209  * of the RTS debug options.  For example:
210  * 
211  *   IF_DEBUG(RtsFlags_DebugFlags_apply,
212  *      foreign "C" fprintf(stderr, stg_ap_0_ret_str));
213  *
214  * Note the syntax is slightly different to the C version of this macro.
215  */
216 #ifdef DEBUG
217 #define IF_DEBUG(c,s)  if (RtsFlags_DebugFlags_##c(RtsFlags) != 0::I32) { s; }
218 #else
219 #define IF_DEBUG(c,s)  /* nothing */
220 #endif
221
222 /* -----------------------------------------------------------------------------
223    Entering 
224
225    It isn't safe to "enter" every closure.  Functions in particular
226    have no entry code as such; their entry point contains the code to
227    apply the function.
228
229    ToDo: range should end in N_CLOSURE_TYPES-1, not N_CLOSURE_TYPES,
230    but switch doesn't allow us to use exprs there yet.
231    -------------------------------------------------------------------------- */
232
233 #define ENTER()                                         \
234  again:                                                 \
235   W_ info;                                              \
236   info = %INFO_PTR(R1);                                 \
237   switch [INVALID_OBJECT .. N_CLOSURE_TYPES]            \
238          (TO_W_( %INFO_TYPE(%STD_INFO(info)) )) {       \
239   case                                                  \
240     IND,                                                \
241     IND_OLDGEN,                                         \
242     IND_PERM,                                           \
243     IND_OLDGEN_PERM,                                    \
244     IND_STATIC:                                         \
245    {                                                    \
246       R1 = StgInd_indirectee(R1);                       \
247       goto again;                                       \
248    }                                                    \
249   case                                                  \
250     BCO,                                                \
251     FUN,                                                \
252     FUN_1_0,                                            \
253     FUN_0_1,                                            \
254     FUN_2_0,                                            \
255     FUN_1_1,                                            \
256     FUN_0_2,                                            \
257     FUN_STATIC,                                         \
258     PAP:                                                \
259    {                                                    \
260       jump %ENTRY_CODE(Sp(0));                          \
261    }                                                    \
262   default:                                              \
263    {                                                    \
264       jump %ENTRY_CODE(info);                           \
265    }                                                    \
266   }
267
268 /* -----------------------------------------------------------------------------
269    Constants.
270    -------------------------------------------------------------------------- */
271
272 #include "Constants.h"
273 #include "DerivedConstants.h"
274 #include "ClosureTypes.h"
275 #include "StgFun.h"
276
277 /*
278  * Need MachRegs, because some of the RTS code is conditionally
279  * compiled based on REG_R1, REG_R2, etc.
280  */
281 #define STOLEN_X86_REGS 4
282 #include "MachRegs.h"
283
284 #include "Liveness.h"
285 #include "StgLdvProf.h"
286
287 #undef BLOCK_SIZE
288 #undef MBLOCK_SIZE
289 #include "Block.h"  /* For Bdescr() */
290
291
292 /* Can't think of a better place to put this. */
293 #if SIZEOF_mp_limb_t != SIZEOF_VOID_P
294 #error mp_limb_t != StgWord: assumptions in PrimOps.cmm are now false
295 #endif
296
297 #define MyCapability()  (BaseReg - OFFSET_Capability_r)
298
299 /* -------------------------------------------------------------------------
300    Allocation and garbage collection
301    ------------------------------------------------------------------------- */
302
303 /*
304  * ALLOC_PRIM is for allocating memory on the heap for a primitive
305  * object.  It is used all over PrimOps.cmm.
306  *
307  * We make the simplifying assumption that the "admin" part of a
308  * primitive closure is just the header when calculating sizes for
309  * ticky-ticky.  It's not clear whether eg. the size field of an array
310  * should be counted as "admin", or the various fields of a BCO.
311  */
312 #define ALLOC_PRIM(bytes,liveness,reentry)                      \
313    HP_CHK_GEN_TICKY(bytes,liveness,reentry);                    \
314    TICK_ALLOC_PRIM(SIZEOF_StgHeader,bytes-SIZEOF_StgHeader,0);  \
315    CCCS_ALLOC(bytes);
316
317 /* CCS_ALLOC wants the size in words, because ccs->mem_alloc is in words */
318 #define CCCS_ALLOC(__alloc) CCS_ALLOC(BYTES_TO_WDS(__alloc), W_[CCCS])
319
320 #define HP_CHK_GEN_TICKY(alloc,liveness,reentry)        \
321    HP_CHK_GEN(alloc,liveness,reentry);                  \
322    TICK_ALLOC_HEAP_NOCTR(alloc);
323
324 // allocateLocal() allocates from the nursery, so we check to see
325 // whether the nursery is nearly empty in any function that uses
326 // allocateLocal() - this includes many of the primops.
327 #define MAYBE_GC(liveness,reentry)                      \
328   if (bdescr_link(CurrentNursery) == NULL || CInt[alloc_blocks] >= CInt[alloc_blocks_lim]) {            \
329         R9  = liveness;                                 \
330         R10 = reentry;                                  \
331         HpAlloc = 0;                                    \
332         jump stg_gc_gen_hp;                             \
333    }
334
335 /* -----------------------------------------------------------------------------
336    Closure headers
337    -------------------------------------------------------------------------- */
338
339 /*
340  * This is really ugly, since we don't do the rest of StgHeader this
341  * way.  The problem is that values from DerivedConstants.h cannot be 
342  * dependent on the way (SMP, PROF etc.).  For SIZEOF_StgHeader we get
343  * the value from GHC, but it seems like too much trouble to do that
344  * for StgThunkHeader.
345  */
346 #define SIZEOF_StgThunkHeader SIZEOF_StgHeader+SIZEOF_StgSMPThunkHeader
347
348 #define StgThunk_payload(__ptr__,__ix__) \
349     W_[__ptr__+SIZEOF_StgThunkHeader+ WDS(__ix__)]
350
351 /* -----------------------------------------------------------------------------
352    Closures
353    -------------------------------------------------------------------------- */
354
355 /* The offset of the payload of an array */
356 #define BYTE_ARR_CTS(arr)  ((arr) + SIZEOF_StgArrWords)
357
358 /* Getting/setting the info pointer of a closure */
359 #define SET_INFO(p,info) StgHeader_info(p) = info
360 #define GET_INFO(p) StgHeader_info(p)
361
362 /* Determine the size of an ordinary closure from its info table */
363 #define sizeW_fromITBL(itbl) \
364   SIZEOF_StgHeader + WDS(%INFO_PTRS(itbl)) + WDS(%INFO_NPTRS(itbl))
365
366 /* NB. duplicated from InfoTables.h! */
367 #define BITMAP_SIZE(bitmap) ((bitmap) & BITMAP_SIZE_MASK)
368 #define BITMAP_BITS(bitmap) ((bitmap) >> BITMAP_BITS_SHIFT)
369
370 /* Debugging macros */
371 #define LOOKS_LIKE_INFO_PTR(p)                          \
372    ((p) != NULL &&                                      \
373      (TO_W_(%INFO_TYPE(%STD_INFO(p))) != INVALID_OBJECT) &&     \
374      (TO_W_(%INFO_TYPE(%STD_INFO(p))) <  N_CLOSURE_TYPES))
375
376 #define LOOKS_LIKE_CLOSURE_PTR(p) (LOOKS_LIKE_INFO_PTR(GET_INFO(p)))
377
378 /*
379  * The layout of the StgFunInfoExtra part of an info table changes
380  * depending on TABLES_NEXT_TO_CODE.  So we define field access
381  * macros which use the appropriate version here:
382  */
383 #ifdef TABLES_NEXT_TO_CODE
384 /*
385  * when TABLES_NEXT_TO_CODE, slow_apply is stored as an offset
386  * instead of the normal pointer.
387  */
388         
389 #define StgFunInfoExtra_slow_apply(fun_info)    \
390         (TO_W_(StgFunInfoExtraRev_slow_apply_offset(fun_info))    \
391                + (fun_info) + SIZEOF_StgFunInfoExtraRev + SIZEOF_StgInfoTable)
392
393 #define StgFunInfoExtra_fun_type(i)   StgFunInfoExtraRev_fun_type(i)
394 #define StgFunInfoExtra_arity(i)      StgFunInfoExtraRev_arity(i)
395 #define StgFunInfoExtra_bitmap(i)     StgFunInfoExtraRev_bitmap(i)
396 #else
397 #define StgFunInfoExtra_slow_apply(i) StgFunInfoExtraFwd_slow_apply(i)
398 #define StgFunInfoExtra_fun_type(i)   StgFunInfoExtraFwd_fun_type(i)
399 #define StgFunInfoExtra_arity(i)      StgFunInfoExtraFwd_arity(i)
400 #define StgFunInfoExtra_bitmap(i)     StgFunInfoExtraFwd_bitmap(i)
401 #endif
402
403 /* -----------------------------------------------------------------------------
404    Voluntary Yields/Blocks
405
406    We only have a generic version of this at the moment - if it turns
407    out to be slowing us down we can make specialised ones.
408    -------------------------------------------------------------------------- */
409
410 #define YIELD(liveness,reentry)                 \
411    R9  = liveness;                              \
412    R10 = reentry;                               \
413    jump stg_gen_yield;
414
415 #define BLOCK(liveness,reentry)                 \
416    R9  = liveness;                              \
417    R10 = reentry;                               \
418    jump stg_gen_block;
419
420 /* -----------------------------------------------------------------------------
421    Ticky macros 
422    -------------------------------------------------------------------------- */
423
424 #ifdef TICKY_TICKY
425 #define TICK_BUMP_BY(ctr,n) CLong[ctr] = CLong[ctr] + n
426 #else
427 #define TICK_BUMP_BY(ctr,n) /* nothing */
428 #endif
429
430 #define TICK_BUMP(ctr)      TICK_BUMP_BY(ctr,1)
431
432 #define TICK_ENT_DYN_IND()              TICK_BUMP(ENT_DYN_IND_ctr)
433 #define TICK_ENT_DYN_THK()              TICK_BUMP(ENT_DYN_THK_ctr)
434 #define TICK_ENT_VIA_NODE()             TICK_BUMP(ENT_VIA_NODE_ctr)
435 #define TICK_ENT_STATIC_IND()           TICK_BUMP(ENT_STATIC_IND_ctr)
436 #define TICK_ENT_PERM_IND()             TICK_BUMP(ENT_PERM_IND_ctr)
437 #define TICK_ENT_PAP()                  TICK_BUMP(ENT_PAP_ctr)
438 #define TICK_ENT_AP()                   TICK_BUMP(ENT_AP_ctr)
439 #define TICK_ENT_AP_STACK()             TICK_BUMP(ENT_AP_STACK_ctr)
440 #define TICK_ENT_BH()                   TICK_BUMP(ENT_BH_ctr)
441 #define TICK_UNKNOWN_CALL()             TICK_BUMP(UNKNOWN_CALL_ctr)
442 #define TICK_UPDF_PUSHED()              TICK_BUMP(UPDF_PUSHED_ctr)
443 #define TICK_CATCHF_PUSHED()            TICK_BUMP(CATCHF_PUSHED_ctr)
444 #define TICK_UPDF_OMITTED()             TICK_BUMP(UPDF_OMITTED_ctr)
445 #define TICK_UPD_NEW_IND()              TICK_BUMP(UPD_NEW_IND_ctr)
446 #define TICK_UPD_NEW_PERM_IND()         TICK_BUMP(UPD_NEW_PERM_IND_ctr)
447 #define TICK_UPD_OLD_IND()              TICK_BUMP(UPD_OLD_IND_ctr)
448 #define TICK_UPD_OLD_PERM_IND()         TICK_BUMP(UPD_OLD_PERM_IND_ctr)
449   
450 #define TICK_SLOW_CALL_FUN_TOO_FEW()    TICK_BUMP(SLOW_CALL_FUN_TOO_FEW_ctr)
451 #define TICK_SLOW_CALL_FUN_CORRECT()    TICK_BUMP(SLOW_CALL_FUN_CORRECT_ctr)
452 #define TICK_SLOW_CALL_FUN_TOO_MANY()   TICK_BUMP(SLOW_CALL_FUN_TOO_MANY_ctr)
453 #define TICK_SLOW_CALL_PAP_TOO_FEW()    TICK_BUMP(SLOW_CALL_PAP_TOO_FEW_ctr)
454 #define TICK_SLOW_CALL_PAP_CORRECT()    TICK_BUMP(SLOW_CALL_PAP_CORRECT_ctr)
455 #define TICK_SLOW_CALL_PAP_TOO_MANY()   TICK_BUMP(SLOW_CALL_PAP_TOO_MANY_ctr)
456
457 #define TICK_SLOW_CALL_v()              TICK_BUMP(SLOW_CALL_v_ctr)
458 #define TICK_SLOW_CALL_p()              TICK_BUMP(SLOW_CALL_p_ctr)
459 #define TICK_SLOW_CALL_pv()             TICK_BUMP(SLOW_CALL_pv_ctr)
460 #define TICK_SLOW_CALL_pp()             TICK_BUMP(SLOW_CALL_pp_ctr)
461 #define TICK_SLOW_CALL_ppp()            TICK_BUMP(SLOW_CALL_ppp_ctr)
462 #define TICK_SLOW_CALL_pppp()           TICK_BUMP(SLOW_CALL_pppp_ctr)
463 #define TICK_SLOW_CALL_ppppp()          TICK_BUMP(SLOW_CALL_ppppp_ctr)
464 #define TICK_SLOW_CALL_pppppp()         TICK_BUMP(SLOW_CALL_pppppp_ctr)
465
466 #ifdef TICKY_TICKY
467 #define TICK_HISTO_BY(histo,n,i)                        \
468          W_ __idx;                                      \
469          __idx = (n);                                   \
470          if (__idx > 8) {                               \
471             __idx = 8;                                  \
472          }                                              \
473          CLong[histo##_hst + _idx*SIZEOF_LONG]          \
474            = histo##_hst + __idx*SIZEOF_LONG] + i;
475 #else
476 #define TICK_HISTO_BY(histo,n,i) /* nothing */
477 #endif
478
479 #define TICK_HISTO(histo,n) TICK_HISTO_BY(histo,n,1)
480
481 /* An unboxed tuple with n components. */
482 #define TICK_RET_UNBOXED_TUP(n)                 \
483   TICK_BUMP(RET_UNBOXED_TUP_ctr++);             \
484   TICK_HISTO(RET_UNBOXED_TUP,n)
485
486 /*
487  * A slow call with n arguments.  In the unevald case, this call has
488  * already been counted once, so don't count it again.
489  */
490 #define TICK_SLOW_CALL(n)                       \
491   TICK_BUMP(SLOW_CALL_ctr);                     \
492   TICK_HISTO(SLOW_CALL,n)
493
494 /*
495  * This slow call was found to be to an unevaluated function; undo the
496  * ticks we did in TICK_SLOW_CALL.
497  */
498 #define TICK_SLOW_CALL_UNEVALD(n)               \
499   TICK_BUMP(SLOW_CALL_UNEVALD_ctr);             \
500   TICK_BUMP_BY(SLOW_CALL_ctr,-1);               \
501   TICK_HISTO_BY(SLOW_CALL,n,-1);
502
503 /* Updating a closure with a new CON */
504 #define TICK_UPD_CON_IN_NEW(n)                  \
505   TICK_BUMP(UPD_CON_IN_NEW_ctr);                \
506   TICK_HISTO(UPD_CON_IN_NEW,n)
507
508 #define TICK_ALLOC_HEAP_NOCTR(n)                \
509     TICK_BUMP(ALLOC_HEAP_ctr);                  \
510     TICK_BUMP_BY(ALLOC_HEAP_tot,n)
511
512 /* -----------------------------------------------------------------------------
513    Misc junk
514    -------------------------------------------------------------------------- */
515
516 #define TICK_MILLISECS   (1000/TICK_FREQUENCY)   /* ms per tick */
517
518 #define NO_TREC        stg_NO_TREC_closure
519 #define END_TSO_QUEUE  stg_END_TSO_QUEUE_closure
520
521 #define dirtyTSO(tso) \
522     StgTSO_flags(tso) = StgTSO_flags(tso) | TSO_DIRTY::I32;
523
524 #define recordMutableCap(p, gen, regs)                                  \
525   W_ __bd;                                                              \
526   W_ mut_list;                                                          \
527   mut_list = Capability_mut_lists(MyCapability()) + WDS(gen);           \
528  __bd = W_[mut_list];                                                   \
529   if (bdescr_free(__bd) >= bdescr_start(__bd) + BLOCK_SIZE) {           \
530       W_ __new_bd;                                                      \
531       "ptr" __new_bd = foreign "C" allocBlock_lock() [regs];            \
532       bdescr_link(__new_bd) = __bd;                                     \
533       __bd = __new_bd;                                                  \
534       W_[mut_list] = __bd;                                              \
535   }                                                                     \
536   W_ free;                                                              \
537   free = bdescr_free(__bd);                                             \
538   W_[free] = p;                                                         \
539   bdescr_free(__bd) = free + WDS(1);
540
541 #define recordMutable(p, regs)                                          \
542       W_ __p;                                                           \
543       __p = p;                                                          \
544       recordMutableCap(__p, TO_W_(bdescr_gen_no(Bdescr(__p))), regs)
545
546 #endif /* CMM_H */