2 % (c) The AQUA Project, Glasgow University, 1993-1998
6 module StixPrim ( primCode, amodeToStix, amodeToStix' ) where
8 #include "HsVersions.h"
14 import AbsCSyn hiding ( spRel )
15 import AbsCUtils ( getAmodeRep, mixedTypeLocn )
16 import SMRep ( fixedHdrSize )
17 import Literal ( Literal(..), word2IntLit )
18 import PrimOp ( PrimOp(..), CCall(..), CCallTarget(..) )
19 import PrimRep ( PrimRep(..) )
20 import UniqSupply ( returnUs, thenUs, getUniqueUs, UniqSM )
21 import Constants ( mIN_INTLIKE, mIN_CHARLIKE, uF_UPDATEE, bLOCK_SIZE,
22 rESERVED_STACK_WORDS )
23 import CLabel ( mkIntlikeClosureLabel, mkCharlikeClosureLabel,
24 mkMAP_FROZEN_infoLabel, mkForeignLabel )
25 import CallConv ( cCallConv )
32 The main honcho here is primCode, which handles the guts of COpStmts.
36 :: [CAddrMode] -- results
38 -> [CAddrMode] -- args
39 -> UniqSM StixTreeList
42 First, the dreaded @ccall@. We can't handle @casm@s.
44 Usually, this compiles to an assignment, but when the left-hand side
45 is empty, we just perform the call and ignore the result.
47 btw Why not let programmer use casm to provide assembly code instead
50 The (MP) integer operations are a true nightmare. Since we don't have
51 a convenient abstract way of allocating temporary variables on the (C)
52 stack, we use the space just below HpLim for the @MP_INT@ structures,
53 and modify our heap check accordingly.
56 -- NB: ordering of clauses somewhere driven by
57 -- the desire to getting sane patt-matching behavior
58 primCode res@[sr,dr] IntegerNegOp arg@[sa,da]
59 = gmpNegate (sr,dr) (sa,da)
61 primCode [res] IntegerCmpOp args@[sa1,da1, sa2,da2]
62 = gmpCompare res (sa1,da1, sa2,da2)
64 primCode [res] IntegerCmpIntOp args@[sa1,da1,ai]
65 = gmpCompareInt res (sa1,da1,ai)
67 primCode [res] Integer2IntOp arg@[sa,da]
68 = gmpInteger2Int res (sa,da)
70 primCode [res] Integer2WordOp arg@[sa,da]
71 = gmpInteger2Word res (sa,da)
73 primCode [res] Int2AddrOp [arg]
74 = simpleCoercion AddrRep res arg
76 primCode [res] Addr2IntOp [arg]
77 = simpleCoercion IntRep res arg
79 primCode [res] Int2WordOp [arg]
80 = simpleCoercion IntRep{-WordRep?-} res arg
82 primCode [res] Word2IntOp [arg]
83 = simpleCoercion IntRep res arg
85 primCode [res] AddrToHValueOp [arg]
86 = simpleCoercion PtrRep res arg
90 primCode [res] SameMutableArrayOp args
92 compare = StPrim AddrEqOp (map amodeToStix args)
93 assign = StAssign IntRep (amodeToStix res) compare
95 returnUs (\xs -> assign : xs)
97 primCode res@[_] SameMutableByteArrayOp args
98 = primCode res SameMutableArrayOp args
100 primCode res@[_] SameMutVarOp args
101 = primCode res SameMutableArrayOp args
103 primCode res@[_] SameMVarOp args
104 = primCode res SameMutableArrayOp args
107 Freezing an array of pointers is a double assignment. We fix the
108 header of the ``new'' closure because the lhs is probably a better
109 addressing mode for the indirection (most likely, it's a VanillaReg).
113 primCode [lhs] UnsafeFreezeArrayOp [rhs]
115 lhs' = amodeToStix lhs
116 rhs' = amodeToStix rhs
117 header = StInd PtrRep lhs'
118 assign = StAssign PtrRep lhs' rhs'
119 freeze = StAssign PtrRep header mutArrPtrsFrozen_info
121 returnUs (\xs -> assign : freeze : xs)
123 primCode [lhs] UnsafeFreezeByteArrayOp [rhs]
124 = simpleCoercion PtrRep lhs rhs
127 Returning the size of (mutable) byte arrays is just
128 an indexing operation.
131 primCode [lhs] SizeofByteArrayOp [rhs]
133 lhs' = amodeToStix lhs
134 rhs' = amodeToStix rhs
135 sz = StIndex IntRep rhs' fixedHS
136 assign = StAssign IntRep lhs' (StInd IntRep sz)
138 returnUs (\xs -> assign : xs)
140 primCode [lhs] SizeofMutableByteArrayOp [rhs]
142 lhs' = amodeToStix lhs
143 rhs' = amodeToStix rhs
144 sz = StIndex IntRep rhs' fixedHS
145 assign = StAssign IntRep lhs' (StInd IntRep sz)
147 returnUs (\xs -> assign : xs)
151 Most other array primitives translate to simple indexing.
154 primCode lhs@[_] IndexArrayOp args
155 = primCode lhs ReadArrayOp args
157 primCode [lhs] ReadArrayOp [obj, ix]
159 lhs' = amodeToStix lhs
160 obj' = amodeToStix obj
162 base = StIndex IntRep obj' arrPtrsHS
163 assign = StAssign PtrRep lhs' (StInd PtrRep (StIndex PtrRep base ix'))
165 returnUs (\xs -> assign : xs)
167 primCode [] WriteArrayOp [obj, ix, v]
169 obj' = amodeToStix obj
172 base = StIndex IntRep obj' arrPtrsHS
173 assign = StAssign PtrRep (StInd PtrRep (StIndex PtrRep base ix')) v'
175 returnUs (\xs -> assign : xs)
177 primCode [] WriteForeignObjOp [obj, v]
179 obj' = amodeToStix obj
181 obj'' = StIndex AddrRep obj' (StInt 4711) -- fixedHS
182 assign = StAssign AddrRep (StInd AddrRep obj'') v'
184 returnUs (\xs -> assign : xs)
186 -- NB: indexing in "pk" units, *not* in bytes (WDP 95/09)
187 primCode ls IndexByteArrayOp_Char rs = primCode_ReadByteArrayOp Int8Rep ls rs
188 primCode ls IndexByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
189 primCode ls IndexByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
190 primCode ls IndexByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
191 primCode ls IndexByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
192 primCode ls IndexByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
193 primCode ls IndexByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
194 primCode ls IndexByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
195 primCode ls IndexByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
197 primCode ls ReadByteArrayOp_Char rs = primCode_ReadByteArrayOp Int8Rep ls rs
198 primCode ls ReadByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
199 primCode ls ReadByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
200 primCode ls ReadByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
201 primCode ls ReadByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
202 primCode ls ReadByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
203 primCode ls ReadByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
204 primCode ls ReadByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
205 primCode ls ReadByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
207 primCode ls ReadOffAddrOp_Char rs = primCode_IndexOffAddrOp Int8Rep ls rs
208 primCode ls ReadOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
209 primCode ls ReadOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
210 primCode ls ReadOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
211 primCode ls ReadOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
212 primCode ls ReadOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
213 primCode ls ReadOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
214 primCode ls ReadOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
215 primCode ls ReadOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
217 primCode ls IndexOffAddrOp_Char rs = primCode_IndexOffAddrOp Int8Rep ls rs
218 primCode ls IndexOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
219 primCode ls IndexOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
220 primCode ls IndexOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
221 primCode ls IndexOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
222 primCode ls IndexOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
223 primCode ls IndexOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
224 primCode ls IndexOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
225 primCode ls IndexOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
227 primCode ls IndexOffForeignObjOp_Char rs = primCode_IndexOffForeignObjOp Int8Rep ls rs
228 primCode ls IndexOffForeignObjOp_Int rs = primCode_IndexOffForeignObjOp IntRep ls rs
229 primCode ls IndexOffForeignObjOp_Word rs = primCode_IndexOffForeignObjOp WordRep ls rs
230 primCode ls IndexOffForeignObjOp_Addr rs = primCode_IndexOffForeignObjOp AddrRep ls rs
231 primCode ls IndexOffForeignObjOp_Float rs = primCode_IndexOffForeignObjOp FloatRep ls rs
232 primCode ls IndexOffForeignObjOp_Double rs = primCode_IndexOffForeignObjOp DoubleRep ls rs
233 primCode ls IndexOffForeignObjOp_StablePtr rs = primCode_IndexOffForeignObjOp StablePtrRep ls rs
234 primCode ls IndexOffForeignObjOp_Int64 rs = primCode_IndexOffForeignObjOp Int64Rep ls rs
235 primCode ls IndexOffForeignObjOp_Word64 rs = primCode_IndexOffForeignObjOp Word64Rep ls rs
237 primCode ls WriteOffAddrOp_Char rs = primCode_WriteOffAddrOp Int8Rep ls rs
238 primCode ls WriteOffAddrOp_Int rs = primCode_WriteOffAddrOp IntRep ls rs
239 primCode ls WriteOffAddrOp_Word rs = primCode_WriteOffAddrOp WordRep ls rs
240 primCode ls WriteOffAddrOp_Addr rs = primCode_WriteOffAddrOp AddrRep ls rs
241 primCode ls WriteOffAddrOp_Float rs = primCode_WriteOffAddrOp FloatRep ls rs
242 primCode ls WriteOffAddrOp_Double rs = primCode_WriteOffAddrOp DoubleRep ls rs
243 primCode ls WriteOffAddrOp_StablePtr rs = primCode_WriteOffAddrOp StablePtrRep ls rs
244 primCode ls WriteOffAddrOp_Int64 rs = primCode_WriteOffAddrOp Int64Rep ls rs
245 primCode ls WriteOffAddrOp_Word64 rs = primCode_WriteOffAddrOp Word64Rep ls rs
247 primCode ls WriteByteArrayOp_Char rs = primCode_WriteByteArrayOp Int8Rep ls rs
248 primCode ls WriteByteArrayOp_Int rs = primCode_WriteByteArrayOp IntRep ls rs
249 primCode ls WriteByteArrayOp_Word rs = primCode_WriteByteArrayOp WordRep ls rs
250 primCode ls WriteByteArrayOp_Addr rs = primCode_WriteByteArrayOp AddrRep ls rs
251 primCode ls WriteByteArrayOp_Float rs = primCode_WriteByteArrayOp FloatRep ls rs
252 primCode ls WriteByteArrayOp_Double rs = primCode_WriteByteArrayOp DoubleRep ls rs
253 primCode ls WriteByteArrayOp_StablePtr rs = primCode_WriteByteArrayOp StablePtrRep ls rs
254 primCode ls WriteByteArrayOp_Int64 rs = primCode_WriteByteArrayOp Int64Rep ls rs
255 primCode ls WriteByteArrayOp_Word64 rs = primCode_WriteByteArrayOp Word64Rep ls rs
259 ToDo: saving/restoring of volatile regs around ccalls.
261 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
262 rather than inheriting the calling convention of the thing which we're really
266 primCode lhs (CCallOp (CCall (StaticTarget fn) is_asm may_gc cconv)) rhs
267 | is_asm = error "ERROR: Native code generator can't handle casm"
268 | not may_gc = returnUs (\xs -> ccall : xs)
270 save_thread_state `thenUs` \ save ->
271 load_thread_state `thenUs` \ load ->
272 getUniqueUs `thenUs` \ uniq ->
274 id = StReg (StixTemp uniq IntRep)
276 suspend = StAssign IntRep id
277 (StCall SLIT("suspendThread") {-no:cconv-} cCallConv
279 resume = StCall SLIT("resumeThread") {-no:cconv-} cCallConv
282 returnUs (\xs -> save (suspend : ccall : resume : load xs))
285 args = map amodeCodeForCCall rhs
286 amodeCodeForCCall x =
287 let base = amodeToStix' x
289 case getAmodeRep x of
290 ArrayRep -> StIndex PtrRep base arrPtrsHS
291 ByteArrayRep -> StIndex IntRep base arrWordsHS
292 ForeignObjRep -> StInd PtrRep (StIndex PtrRep base fixedHS)
296 [] -> StCall fn cconv VoidRep args
298 let lhs' = amodeToStix lhs
299 pk = case getAmodeRep lhs of
301 DoubleRep -> DoubleRep
304 StAssign pk lhs' (StCall fn cconv pk args)
307 DataToTagOp won't work for 64-bit archs, as it is.
310 primCode [lhs] DataToTagOp [arg]
311 = let lhs' = amodeToStix lhs
312 arg' = amodeToStix arg
313 infoptr = StInd PtrRep arg'
314 word_32 = StInd WordRep (StIndex PtrRep infoptr (StInt (-1)))
315 masked_le32 = StPrim SrlOp [word_32, StInt 16]
316 masked_be32 = StPrim AndOp [word_32, StInt 65535]
317 #ifdef WORDS_BIGENDIAN
322 assign = StAssign IntRep lhs' masked
324 returnUs (\xs -> assign : xs)
327 MutVars are pretty simple.
328 #define writeMutVarzh(a,v) (P_)(((StgMutVar *)(a))->var)=(v)
331 primCode [] WriteMutVarOp [aa,vv]
332 = let aa_s = amodeToStix aa
333 vv_s = amodeToStix vv
334 var_field = StIndex PtrRep aa_s fixedHS
335 assign = StAssign PtrRep (StInd PtrRep var_field) vv_s
337 returnUs (\xs -> assign : xs)
339 primCode [rr] ReadMutVarOp [aa]
340 = let aa_s = amodeToStix aa
341 rr_s = amodeToStix rr
342 var_field = StIndex PtrRep aa_s fixedHS
343 assign = StAssign PtrRep rr_s (StInd PtrRep var_field)
345 returnUs (\xs -> assign : xs)
351 primCode [rr] ForeignObjToAddrOp [fo]
352 = let code = StAssign AddrRep (amodeToStix rr)
354 (StIndex PtrRep (amodeToStix fo) fixedHS))
356 returnUs (\xs -> code : xs)
358 primCode [] TouchOp [_] = returnUs id
361 Now the more mundane operations.
366 lhs' = map amodeToStix lhs
367 rhs' = map amodeToStix' rhs
368 pk = getAmodeRep (head lhs)
370 returnUs (\ xs -> simplePrim pk lhs' op rhs' : xs)
373 Helper fns for some array ops.
376 primCode_ReadByteArrayOp pk [lhs] [obj, ix]
378 lhs' = amodeToStix lhs
379 obj' = amodeToStix obj
381 base = StIndex IntRep obj' arrWordsHS
382 assign = StAssign pk lhs' (StInd pk (StIndex pk base ix'))
384 returnUs (\xs -> assign : xs)
387 primCode_IndexOffAddrOp pk [lhs] [obj, ix]
389 lhs' = amodeToStix lhs
390 obj' = amodeToStix obj
392 assign = StAssign pk lhs' (StInd pk (StIndex pk obj' ix'))
394 returnUs (\xs -> assign : xs)
397 primCode_IndexOffForeignObjOp pk [lhs] [obj, ix]
399 lhs' = amodeToStix lhs
400 obj' = amodeToStix obj
402 obj'' = StIndex AddrRep obj' fixedHS
403 assign = StAssign pk lhs' (StInd pk (StIndex pk obj'' ix'))
405 returnUs (\xs -> assign : xs)
408 primCode_WriteOffAddrOp pk [] [obj, ix, v]
410 obj' = amodeToStix obj
413 assign = StAssign pk (StInd pk (StIndex pk obj' ix')) v'
415 returnUs (\xs -> assign : xs)
418 primCode_WriteByteArrayOp pk [] [obj, ix, v]
420 obj' = amodeToStix obj
423 base = StIndex IntRep obj' arrWordsHS
424 assign = StAssign pk (StInd pk (StIndex pk base ix')) v'
426 returnUs (\xs -> assign : xs)
435 -> UniqSM StixTreeList
437 simpleCoercion pk lhs rhs
438 = returnUs (\xs -> StAssign pk (amodeToStix lhs) (amodeToStix rhs) : xs)
441 Here we try to rewrite primitives into a form the code generator can
442 understand. Any primitives not handled here must be handled at the
443 level of the specific code generator.
447 :: PrimRep -- Rep of first destination
448 -> [StixTree] -- Destinations
454 Now look for something more conventional.
457 simplePrim pk [lhs] op rest = StAssign pk lhs (StPrim op rest)
458 simplePrim pk as op bs = simplePrim_error op
461 = error ("ERROR: primitive operation `"++show op++"'cannot be handled\nby the native-code generator. Workaround: use -fvia-C.\n(Perhaps you should report it as a GHC bug, also.)\n")
464 %---------------------------------------------------------------------
466 Here we generate the Stix code for CAddrModes.
468 When a character is fetched from a mixed type location, we have to do
469 an extra cast. This is reflected in amodeCode', which is for rhs
470 amodes that might possibly need the extra cast.
473 amodeToStix, amodeToStix' :: CAddrMode -> StixTree
475 amodeToStix'{-'-} am@(CVal rr CharRep)
476 | mixedTypeLocn am = StPrim ChrOp [amodeToStix am]
477 | otherwise = amodeToStix am
479 amodeToStix' am = amodeToStix am
482 amodeToStix am@(CVal rr CharRep)
484 = StInd IntRep (amodeToStix (CAddr rr))
486 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
488 amodeToStix (CAddr (SpRel off))
489 = StIndex PtrRep stgSp (StInt (toInteger (iBox off)))
491 amodeToStix (CAddr (HpRel off))
492 = StIndex IntRep stgHp (StInt (toInteger (- (iBox off))))
494 amodeToStix (CAddr (NodeRel off))
495 = StIndex IntRep stgNode (StInt (toInteger (iBox off)))
497 amodeToStix (CAddr (CIndex base off pk))
498 = StIndex pk (amodeToStix base) (amodeToStix off)
500 amodeToStix (CReg magic) = StReg (StixMagicId magic)
501 amodeToStix (CTemp uniq pk) = StReg (StixTemp uniq pk)
503 amodeToStix (CLbl lbl _) = StCLbl lbl
505 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
507 amodeToStix (CCharLike (CLit (MachChar c)))
508 = StIndex Int8Rep cHARLIKE_closure (StInt (toInteger off))
510 off = charLikeSize * (c - mIN_CHARLIKE)
512 amodeToStix (CCharLike x)
515 amodeToStix (CIntLike (CLit (MachInt i)))
516 = StIndex Int8Rep iNTLIKE_closure (StInt (toInteger off))
518 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
520 amodeToStix (CIntLike x)
523 amodeToStix (CLit core)
525 MachChar c -> StInt (toInteger c)
526 MachStr s -> StString s
527 MachAddr a -> StInt a
529 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
530 MachLitLit s _ -> litLitErr
531 MachLabel l -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
532 MachFloat d -> StFloat d
533 MachDouble d -> StDouble d
534 _ -> panic "amodeToStix:core literal"
536 amodeToStix (CMacroExpr _ macro [arg])
538 ENTRY_CODE -> amodeToStix arg
539 ARG_TAG -> amodeToStix arg -- just an integer no. of words
541 #ifdef WORDS_BIGENDIAN
543 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
544 (StInt (toInteger (-1)))),
548 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
549 (StInt (toInteger (-1)))),
553 -> StInd PtrRep (StIndex PtrRep (amodeToStix arg)
554 (StInt (toInteger uF_UPDATEE)))
557 panic "native code generator can't compile lit-lits, use -fvia-C"
560 Sizes of the CharLike and IntLike closures that are arranged as arrays
561 in the data segment. (These are in bytes.)
564 -- The INTLIKE base pointer
566 iNTLIKE_closure :: StixTree
567 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
571 cHARLIKE_closure :: StixTree
572 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
574 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
576 -- these are the sizes of charLike and intLike closures, in _bytes_.
577 charLikeSize = (fixedHdrSize + 1) * (fromInteger (sizeOf PtrRep))
578 intLikeSize = (fixedHdrSize + 1) * (fromInteger (sizeOf PtrRep))
584 = getUniqueUs `thenUs` \tso_uq ->
585 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
587 StAssign ThreadIdRep tso stgCurrentTSO :
589 (StInd PtrRep (StPrim IntAddOp
590 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
593 (StInd PtrRep (StPrim IntAddOp
594 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
597 (StInd PtrRep (StPrim IntAddOp
599 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]))
600 (StPrim IntAddOp [stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) :
605 = getUniqueUs `thenUs` \tso_uq ->
606 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
608 StAssign ThreadIdRep tso stgCurrentTSO :
609 StAssign PtrRep stgSp
610 (StInd PtrRep (StPrim IntAddOp
611 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])) :
612 StAssign PtrRep stgSu
613 (StInd PtrRep (StPrim IntAddOp
614 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])) :
615 StAssign PtrRep stgSpLim
616 (StPrim IntAddOp [tso,
617 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
618 *BYTES_PER_WORD))]) :
619 StAssign PtrRep stgHp
621 StInd PtrRep (StPrim IntAddOp
623 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
624 StInt (toInteger (1 * BYTES_PER_WORD))
626 StAssign PtrRep stgHpLim
628 StInd PtrRep (StPrim IntAddOp
630 StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
631 StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))