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] IntegerCmpOp args@[sa1,da1, sa2,da2]
59 = gmpCompare res (sa1,da1, sa2,da2)
61 primCode [res] IntegerCmpIntOp args@[sa1,da1,ai]
62 = gmpCompareInt res (sa1,da1,ai)
64 primCode [res] Integer2IntOp arg@[sa,da]
65 = gmpInteger2Int res (sa,da)
67 primCode [res] Integer2WordOp arg@[sa,da]
68 = gmpInteger2Word res (sa,da)
70 primCode [res] Int2AddrOp [arg]
71 = simpleCoercion AddrRep res arg
73 primCode [res] Addr2IntOp [arg]
74 = simpleCoercion IntRep res arg
76 primCode [res] Int2WordOp [arg]
77 = simpleCoercion IntRep{-WordRep?-} res arg
79 primCode [res] Word2IntOp [arg]
80 = simpleCoercion IntRep res arg
82 primCode [res] AddrToHValueOp [arg]
83 = simpleCoercion PtrRep res arg
87 primCode [res] SameMutableArrayOp args
89 compare = StPrim AddrEqOp (map amodeToStix args)
90 assign = StAssign IntRep (amodeToStix res) compare
92 returnUs (\xs -> assign : xs)
94 primCode res@[_] SameMutableByteArrayOp args
95 = primCode res SameMutableArrayOp args
97 primCode res@[_] SameMutVarOp args
98 = primCode res SameMutableArrayOp args
100 primCode res@[_] SameMVarOp args
101 = primCode res SameMutableArrayOp args
104 Freezing an array of pointers is a double assignment. We fix the
105 header of the ``new'' closure because the lhs is probably a better
106 addressing mode for the indirection (most likely, it's a VanillaReg).
110 primCode [lhs] UnsafeFreezeArrayOp [rhs]
112 lhs' = amodeToStix lhs
113 rhs' = amodeToStix rhs
114 header = StInd PtrRep lhs'
115 assign = StAssign PtrRep lhs' rhs'
116 freeze = StAssign PtrRep header mutArrPtrsFrozen_info
118 returnUs (\xs -> assign : freeze : xs)
120 primCode [lhs] UnsafeFreezeByteArrayOp [rhs]
121 = simpleCoercion PtrRep lhs rhs
124 Returning the size of (mutable) byte arrays is just
125 an indexing operation.
128 primCode [lhs] SizeofByteArrayOp [rhs]
130 lhs' = amodeToStix lhs
131 rhs' = amodeToStix rhs
132 sz = StIndex IntRep rhs' fixedHS
133 assign = StAssign IntRep lhs' (StInd IntRep sz)
135 returnUs (\xs -> assign : xs)
137 primCode [lhs] SizeofMutableByteArrayOp [rhs]
139 lhs' = amodeToStix lhs
140 rhs' = amodeToStix rhs
141 sz = StIndex IntRep rhs' fixedHS
142 assign = StAssign IntRep lhs' (StInd IntRep sz)
144 returnUs (\xs -> assign : xs)
148 Most other array primitives translate to simple indexing.
151 primCode lhs@[_] IndexArrayOp args
152 = primCode lhs ReadArrayOp args
154 primCode [lhs] ReadArrayOp [obj, ix]
156 lhs' = amodeToStix lhs
157 obj' = amodeToStix obj
159 base = StIndex IntRep obj' arrPtrsHS
160 assign = StAssign PtrRep lhs' (StInd PtrRep (StIndex PtrRep base ix'))
162 returnUs (\xs -> assign : xs)
164 primCode [] WriteArrayOp [obj, ix, v]
166 obj' = amodeToStix obj
169 base = StIndex IntRep obj' arrPtrsHS
170 assign = StAssign PtrRep (StInd PtrRep (StIndex PtrRep base ix')) v'
172 returnUs (\xs -> assign : xs)
174 primCode [] WriteForeignObjOp [obj, v]
176 obj' = amodeToStix obj
178 obj'' = StIndex AddrRep obj' (StInt 4711) -- fixedHS
179 assign = StAssign AddrRep (StInd AddrRep obj'') v'
181 returnUs (\xs -> assign : xs)
183 -- NB: indexing in "pk" units, *not* in bytes (WDP 95/09)
184 primCode ls IndexByteArrayOp_Char rs = primCode_ReadByteArrayOp Int8Rep ls rs
185 primCode ls IndexByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
186 primCode ls IndexByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
187 primCode ls IndexByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
188 primCode ls IndexByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
189 primCode ls IndexByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
190 primCode ls IndexByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
191 primCode ls IndexByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
192 primCode ls IndexByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
194 primCode ls ReadByteArrayOp_Char rs = primCode_ReadByteArrayOp Int8Rep ls rs
195 primCode ls ReadByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
196 primCode ls ReadByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
197 primCode ls ReadByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
198 primCode ls ReadByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
199 primCode ls ReadByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
200 primCode ls ReadByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
201 primCode ls ReadByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
202 primCode ls ReadByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
204 primCode ls ReadOffAddrOp_Char rs = primCode_IndexOffAddrOp Int8Rep ls rs
205 primCode ls ReadOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
206 primCode ls ReadOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
207 primCode ls ReadOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
208 primCode ls ReadOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
209 primCode ls ReadOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
210 primCode ls ReadOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
211 primCode ls ReadOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
212 primCode ls ReadOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
214 primCode ls IndexOffAddrOp_Char rs = primCode_IndexOffAddrOp Int8Rep ls rs
215 primCode ls IndexOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
216 primCode ls IndexOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
217 primCode ls IndexOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
218 primCode ls IndexOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
219 primCode ls IndexOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
220 primCode ls IndexOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
221 primCode ls IndexOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
222 primCode ls IndexOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
224 primCode ls IndexOffForeignObjOp_Char rs = primCode_IndexOffForeignObjOp Int8Rep ls rs
225 primCode ls IndexOffForeignObjOp_Int rs = primCode_IndexOffForeignObjOp IntRep ls rs
226 primCode ls IndexOffForeignObjOp_Word rs = primCode_IndexOffForeignObjOp WordRep ls rs
227 primCode ls IndexOffForeignObjOp_Addr rs = primCode_IndexOffForeignObjOp AddrRep ls rs
228 primCode ls IndexOffForeignObjOp_Float rs = primCode_IndexOffForeignObjOp FloatRep ls rs
229 primCode ls IndexOffForeignObjOp_Double rs = primCode_IndexOffForeignObjOp DoubleRep ls rs
230 primCode ls IndexOffForeignObjOp_StablePtr rs = primCode_IndexOffForeignObjOp StablePtrRep ls rs
231 primCode ls IndexOffForeignObjOp_Int64 rs = primCode_IndexOffForeignObjOp Int64Rep ls rs
232 primCode ls IndexOffForeignObjOp_Word64 rs = primCode_IndexOffForeignObjOp Word64Rep ls rs
234 primCode ls WriteOffAddrOp_Char rs = primCode_WriteOffAddrOp Int8Rep ls rs
235 primCode ls WriteOffAddrOp_Int rs = primCode_WriteOffAddrOp IntRep ls rs
236 primCode ls WriteOffAddrOp_Word rs = primCode_WriteOffAddrOp WordRep ls rs
237 primCode ls WriteOffAddrOp_Addr rs = primCode_WriteOffAddrOp AddrRep ls rs
238 primCode ls WriteOffAddrOp_Float rs = primCode_WriteOffAddrOp FloatRep ls rs
239 primCode ls WriteOffAddrOp_Double rs = primCode_WriteOffAddrOp DoubleRep ls rs
240 primCode ls WriteOffAddrOp_StablePtr rs = primCode_WriteOffAddrOp StablePtrRep ls rs
241 primCode ls WriteOffAddrOp_Int64 rs = primCode_WriteOffAddrOp Int64Rep ls rs
242 primCode ls WriteOffAddrOp_Word64 rs = primCode_WriteOffAddrOp Word64Rep ls rs
244 primCode ls WriteByteArrayOp_Char rs = primCode_WriteByteArrayOp Int8Rep ls rs
245 primCode ls WriteByteArrayOp_Int rs = primCode_WriteByteArrayOp IntRep ls rs
246 primCode ls WriteByteArrayOp_Word rs = primCode_WriteByteArrayOp WordRep ls rs
247 primCode ls WriteByteArrayOp_Addr rs = primCode_WriteByteArrayOp AddrRep ls rs
248 primCode ls WriteByteArrayOp_Float rs = primCode_WriteByteArrayOp FloatRep ls rs
249 primCode ls WriteByteArrayOp_Double rs = primCode_WriteByteArrayOp DoubleRep ls rs
250 primCode ls WriteByteArrayOp_StablePtr rs = primCode_WriteByteArrayOp StablePtrRep ls rs
251 primCode ls WriteByteArrayOp_Int64 rs = primCode_WriteByteArrayOp Int64Rep ls rs
252 primCode ls WriteByteArrayOp_Word64 rs = primCode_WriteByteArrayOp Word64Rep ls rs
256 ToDo: saving/restoring of volatile regs around ccalls.
258 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
259 rather than inheriting the calling convention of the thing which we're really
263 primCode lhs (CCallOp (CCall (StaticTarget fn) is_asm may_gc cconv)) rhs
264 | is_asm = error "ERROR: Native code generator can't handle casm"
265 | not may_gc = returnUs (\xs -> ccall : xs)
267 save_thread_state `thenUs` \ save ->
268 load_thread_state `thenUs` \ load ->
269 getUniqueUs `thenUs` \ uniq ->
271 id = StReg (StixTemp uniq IntRep)
273 suspend = StAssign IntRep id
274 (StCall SLIT("suspendThread") {-no:cconv-} cCallConv
276 resume = StCall SLIT("resumeThread") {-no:cconv-} cCallConv
279 returnUs (\xs -> save (suspend : ccall : resume : load xs))
282 args = map amodeCodeForCCall rhs
283 amodeCodeForCCall x =
284 let base = amodeToStix' x
286 case getAmodeRep x of
287 ArrayRep -> StIndex PtrRep base arrPtrsHS
288 ByteArrayRep -> StIndex IntRep base arrWordsHS
289 ForeignObjRep -> StInd PtrRep (StIndex PtrRep base fixedHS)
293 [] -> StCall fn cconv VoidRep args
295 let lhs' = amodeToStix lhs
296 pk = case getAmodeRep lhs of
298 DoubleRep -> DoubleRep
301 StAssign pk lhs' (StCall fn cconv pk args)
304 DataToTagOp won't work for 64-bit archs, as it is.
307 primCode [lhs] DataToTagOp [arg]
308 = let lhs' = amodeToStix lhs
309 arg' = amodeToStix arg
310 infoptr = StInd PtrRep arg'
311 word_32 = StInd WordRep (StIndex PtrRep infoptr (StInt (-1)))
312 masked_le32 = StPrim SrlOp [word_32, StInt 16]
313 masked_be32 = StPrim AndOp [word_32, StInt 65535]
314 #ifdef WORDS_BIGENDIAN
319 assign = StAssign IntRep lhs' masked
321 returnUs (\xs -> assign : xs)
324 MutVars are pretty simple.
325 #define writeMutVarzh(a,v) (P_)(((StgMutVar *)(a))->var)=(v)
328 primCode [] WriteMutVarOp [aa,vv]
329 = let aa_s = amodeToStix aa
330 vv_s = amodeToStix vv
331 var_field = StIndex PtrRep aa_s fixedHS
332 assign = StAssign PtrRep (StInd PtrRep var_field) vv_s
334 returnUs (\xs -> assign : xs)
336 primCode [rr] ReadMutVarOp [aa]
337 = let aa_s = amodeToStix aa
338 rr_s = amodeToStix rr
339 var_field = StIndex PtrRep aa_s fixedHS
340 assign = StAssign PtrRep rr_s (StInd PtrRep var_field)
342 returnUs (\xs -> assign : xs)
348 primCode [rr] ForeignObjToAddrOp [fo]
349 = let code = StAssign AddrRep (amodeToStix rr)
351 (StIndex PtrRep (amodeToStix fo) fixedHS))
353 returnUs (\xs -> code : xs)
355 primCode [] TouchOp [_] = returnUs id
358 Now the more mundane operations.
363 lhs' = map amodeToStix lhs
364 rhs' = map amodeToStix' rhs
365 pk = getAmodeRep (head lhs)
367 returnUs (\ xs -> simplePrim pk lhs' op rhs' : xs)
370 Helper fns for some array ops.
373 primCode_ReadByteArrayOp pk [lhs] [obj, ix]
375 lhs' = amodeToStix lhs
376 obj' = amodeToStix obj
378 base = StIndex IntRep obj' arrWordsHS
379 assign = StAssign pk lhs' (StInd pk (StIndex pk base ix'))
381 returnUs (\xs -> assign : xs)
384 primCode_IndexOffAddrOp pk [lhs] [obj, ix]
386 lhs' = amodeToStix lhs
387 obj' = amodeToStix obj
389 assign = StAssign pk lhs' (StInd pk (StIndex pk obj' ix'))
391 returnUs (\xs -> assign : xs)
394 primCode_IndexOffForeignObjOp pk [lhs] [obj, ix]
396 lhs' = amodeToStix lhs
397 obj' = amodeToStix obj
399 obj'' = StIndex AddrRep obj' fixedHS
400 assign = StAssign pk lhs' (StInd pk (StIndex pk obj'' ix'))
402 returnUs (\xs -> assign : xs)
405 primCode_WriteOffAddrOp pk [] [obj, ix, v]
407 obj' = amodeToStix obj
410 assign = StAssign pk (StInd pk (StIndex pk obj' ix')) v'
412 returnUs (\xs -> assign : xs)
415 primCode_WriteByteArrayOp pk [] [obj, ix, v]
417 obj' = amodeToStix obj
420 base = StIndex IntRep obj' arrWordsHS
421 assign = StAssign pk (StInd pk (StIndex pk base ix')) v'
423 returnUs (\xs -> assign : xs)
432 -> UniqSM StixTreeList
434 simpleCoercion pk lhs rhs
435 = returnUs (\xs -> StAssign pk (amodeToStix lhs) (amodeToStix rhs) : xs)
438 Here we try to rewrite primitives into a form the code generator can
439 understand. Any primitives not handled here must be handled at the
440 level of the specific code generator.
444 :: PrimRep -- Rep of first destination
445 -> [StixTree] -- Destinations
451 Now look for something more conventional.
454 simplePrim pk [lhs] op rest = StAssign pk lhs (StPrim op rest)
455 simplePrim pk as op bs = simplePrim_error op
458 = 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")
461 %---------------------------------------------------------------------
463 Here we generate the Stix code for CAddrModes.
465 When a character is fetched from a mixed type location, we have to do
466 an extra cast. This is reflected in amodeCode', which is for rhs
467 amodes that might possibly need the extra cast.
470 amodeToStix, amodeToStix' :: CAddrMode -> StixTree
472 amodeToStix'{-'-} am@(CVal rr CharRep)
473 | mixedTypeLocn am = StPrim ChrOp [amodeToStix am]
474 | otherwise = amodeToStix am
476 amodeToStix' am = amodeToStix am
479 amodeToStix am@(CVal rr CharRep)
481 = StInd IntRep (amodeToStix (CAddr rr))
483 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
485 amodeToStix (CAddr (SpRel off))
486 = StIndex PtrRep stgSp (StInt (toInteger (iBox off)))
488 amodeToStix (CAddr (HpRel off))
489 = StIndex IntRep stgHp (StInt (toInteger (- (iBox off))))
491 amodeToStix (CAddr (NodeRel off))
492 = StIndex IntRep stgNode (StInt (toInteger (iBox off)))
494 amodeToStix (CAddr (CIndex base off pk))
495 = StIndex pk (amodeToStix base) (amodeToStix off)
497 amodeToStix (CReg magic) = StReg (StixMagicId magic)
498 amodeToStix (CTemp uniq pk) = StReg (StixTemp uniq pk)
500 amodeToStix (CLbl lbl _) = StCLbl lbl
502 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
504 amodeToStix (CCharLike (CLit (MachChar c)))
505 = StIndex Int8Rep cHARLIKE_closure (StInt (toInteger off))
507 off = charLikeSize * (c - mIN_CHARLIKE)
509 amodeToStix (CCharLike x)
512 amodeToStix (CIntLike (CLit (MachInt i)))
513 = StIndex Int8Rep iNTLIKE_closure (StInt (toInteger off))
515 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
517 amodeToStix (CIntLike x)
520 amodeToStix (CLit core)
522 MachChar c -> StInt (toInteger c)
523 MachStr s -> StString s
524 MachAddr a -> StInt a
526 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
527 MachLitLit s _ -> litLitErr
528 MachLabel l -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
529 MachFloat d -> StFloat d
530 MachDouble d -> StDouble d
531 _ -> panic "amodeToStix:core literal"
533 amodeToStix (CMacroExpr _ macro [arg])
535 ENTRY_CODE -> amodeToStix arg
536 ARG_TAG -> amodeToStix arg -- just an integer no. of words
538 #ifdef WORDS_BIGENDIAN
540 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
541 (StInt (toInteger (-1)))),
545 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
546 (StInt (toInteger (-1)))),
550 -> StInd PtrRep (StIndex PtrRep (amodeToStix arg)
551 (StInt (toInteger uF_UPDATEE)))
554 panic "native code generator can't compile lit-lits, use -fvia-C"
557 Sizes of the CharLike and IntLike closures that are arranged as arrays
558 in the data segment. (These are in bytes.)
561 -- The INTLIKE base pointer
563 iNTLIKE_closure :: StixTree
564 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
568 cHARLIKE_closure :: StixTree
569 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
571 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
573 -- these are the sizes of charLike and intLike closures, in _bytes_.
574 charLikeSize = (fixedHdrSize + 1) * (fromInteger (sizeOf PtrRep))
575 intLikeSize = (fixedHdrSize + 1) * (fromInteger (sizeOf PtrRep))
581 = getUniqueUs `thenUs` \tso_uq ->
582 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
584 StAssign ThreadIdRep tso stgCurrentTSO :
586 (StInd PtrRep (StPrim IntAddOp
587 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
590 (StInd PtrRep (StPrim IntAddOp
591 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
594 (StInd PtrRep (StPrim IntAddOp
596 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]))
597 (StPrim IntAddOp [stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) :
602 = getUniqueUs `thenUs` \tso_uq ->
603 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
605 StAssign ThreadIdRep tso stgCurrentTSO :
606 StAssign PtrRep stgSp
607 (StInd PtrRep (StPrim IntAddOp
608 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])) :
609 StAssign PtrRep stgSu
610 (StInd PtrRep (StPrim IntAddOp
611 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])) :
612 StAssign PtrRep stgSpLim
613 (StPrim IntAddOp [tso,
614 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
615 *BYTES_PER_WORD))]) :
616 StAssign PtrRep stgHp
618 StInd PtrRep (StPrim IntAddOp
620 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
621 StInt (toInteger (1 * BYTES_PER_WORD))
623 StAssign PtrRep stgHpLim
625 StInd PtrRep (StPrim IntAddOp
627 StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
628 StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))