-%
-% (c) The AQUA Project, Glasgow University, 1996
-%
-\section[MachRegs]{Machine-specific info about registers}
-
-Also includes stuff about immediate operands, which are
-often/usually quite entangled with registers.
-
-(Immediates could be untangled from registers at some cost in tangled
-modules --- the pleasure has been foregone.)
+-- -----------------------------------------------------------------------------
+--
+-- (c) The University of Glasgow 1994-2004
+--
+-- Machine-specific info about registers.
+--
+-- Also includes stuff about immediate operands, which are
+-- often/usually quite entangled with registers.
+--
+-- (Immediates could be untangled from registers at some cost in tangled
+-- modules --- the pleasure has been foregone.)
+--
+-- -----------------------------------------------------------------------------
\begin{code}
-#include "HsVersions.h"
#include "nativeGen/NCG.h"
module MachRegs (
- Reg(..),
- Imm(..),
- Addr(..),
- RegLoc(..),
- SYN_IE(RegNo),
+ -- * Immediate values
+ Imm(..), strImmLit, litToImm,
+ -- * Addressing modes
+ AddrMode(..),
addrOffset,
- argRegs,
- baseRegOffset,
- callClobberedRegs,
+
+ -- * The 'Reg' type
+ RegNo,
+ Reg(..), isRealReg, isVirtualReg,
+ RegClass(..), regClass,
+ getHiVRegFromLo,
+ mkVReg,
+
+ -- * Global registers
+ get_GlobalReg_reg_or_addr,
callerSaves,
- dblImmLit,
- extractMappedRegNos,
- freeMappedRegs,
- freeReg, freeRegs,
- getNewRegNCG,
- magicIdRegMaybe,
- mkReg,
- realReg,
- reservedRegs,
- saveLoc,
+
+ -- * Machine-dependent register-related stuff
+ allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
+ freeReg,
spRel,
- stgReg,
- strImmLit
#if alpha_TARGET_ARCH
- , allArgRegs
- , fits8Bits
- , fReg
- , gp, pv, ra, sp, t9, t10, t11, t12, v0, f0, zeroh
+ allArgRegs,
+ fits8Bits,
+ fReg,
+ gp, pv, ra, sp, t9, t10, t11, t12, v0, f0, zeroh,
#endif
#if i386_TARGET_ARCH
- , eax, ebx, ecx, edx, esi, esp
- , st0, st1, st2, st3, st4, st5, st6, st7
+ eax, ebx, ecx, edx, esi, edi, ebp, esp,
+ fake0, fake1, fake2, fake3, fake4, fake5,
+ addrModeRegs,
#endif
#if sparc_TARGET_ARCH
- , allArgRegs
- , fits13Bits
- , fPair, fpRel, gReg, iReg, lReg, oReg, largeOffsetError
- , fp, g0, o0, f0
-
+ fits13Bits,
+ fpRel, gReg, iReg, lReg, oReg, largeOffsetError,
+ fp, sp, g0, g1, g2, o0, o1, f0, f6, f8, f26, f27,
+#endif
+#if powerpc_TARGET_ARCH
+ allFPArgRegs,
+ makeImmediate,
+ sp,
+ r3, r4, r27, r28,
+ f1, f20, f21,
#endif
) where
-#if __GLASGOW_HASKELL__ >= 202
-import GlaExts hiding (Addr)
-import FastString
+#include "HsVersions.h"
+
+#if i386_TARGET_ARCH
+# define STOLEN_X86_REGS 4
+-- HACK: go for the max
+#endif
+
+#include "../includes/MachRegs.h"
+
+import Cmm
+import MachOp ( MachRep(..) )
+
+import CLabel ( CLabel, mkMainCapabilityLabel )
+import Unique ( Unique )
+import Pretty
+import Outputable ( Outputable(..), pprPanic, panic )
+import qualified Outputable
+import Unique
+import Constants
+import FastTypes
+
+#if powerpc_TARGET_ARCH
+#if __GLASGOW_HASKELL__ >= 504
+import Data.Word ( Word8, Word16, Word32 )
+import Data.Int ( Int8, Int16, Int32 )
#else
-IMP_Ubiq(){-uitous-}
-#endif
-
-import AbsCSyn ( MagicId(..) )
-import AbsCUtils ( magicIdPrimRep )
-import CLabel ( CLabel )
-import Outputable ( Outputable(..) )
-import Pretty ( Doc, text, rational )
-import PrimOp ( PrimOp(..) )
-import PrimRep ( PrimRep(..) )
-import Stix ( sStLitLbl, StixTree(..), StixReg(..),
- CodeSegment
- )
-import Unique ( mkPseudoUnique1, mkPseudoUnique2, mkPseudoUnique3,
- Unique{-instance Ord3-}, Uniquable(..)
- )
-import UniqSupply ( getUnique, returnUs, thenUs, SYN_IE(UniqSM) )
-import Util ( panic, Ord3(..) )
-\end{code}
+import Word ( Word8, Word16, Word32 )
+import Int ( Int8, Int16, Int32 )
+#endif
+#endif
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-- -----------------------------------------------------------------------------
+-- Immediates
-\begin{code}
data Imm
= ImmInt Int
| ImmInteger Integer -- Sigh.
| ImmCLbl CLabel -- AbstractC Label (with baggage)
- | ImmLab Doc -- Simple string label (underscore-able)
- | ImmLit Doc -- Simple string
- IF_ARCH_sparc(
- | LO Imm -- Possible restrictions...
+ | ImmLit Doc -- Simple string
+ | ImmIndex CLabel Int
+ | ImmFloat Rational
+ | ImmDouble Rational
+ | ImmConstantSum Imm Imm
+ | ImmConstantDiff Imm Imm
+#if sparc_TARGET_ARCH
+ | LO Imm {- Possible restrictions... -}
| HI Imm
- ,)
-
+#endif
+#if powerpc_TARGET_ARCH
+ | LO Imm
+ | HI Imm
+ | HA Imm {- high halfword adjusted -}
+#endif
strImmLit s = ImmLit (text s)
-dblImmLit r
- = strImmLit (
- IF_ARCH_alpha({-prepend nothing-}
- ,IF_ARCH_i386( '0' : 'd' :
- ,IF_ARCH_sparc('0' : 'r' :,)))
- show (rational r))
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-\begin{code}
-data Addr
+litToImm :: CmmLit -> Imm
+litToImm (CmmInt i _) = ImmInteger i
+litToImm (CmmFloat f F32) = ImmFloat f
+litToImm (CmmFloat f F64) = ImmDouble f
+litToImm (CmmLabel l) = ImmCLbl l
+litToImm (CmmLabelOff l off) = ImmIndex l off
+litToImm (CmmLabelDiffOff l1 l2 off)
+ = ImmConstantSum
+ (ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
+ (ImmInt off)
+
+-- -----------------------------------------------------------------------------
+-- Addressing modes
+
+data AddrMode
#if alpha_TARGET_ARCH
= AddrImm Imm
| AddrReg Reg
#endif
#if i386_TARGET_ARCH
- = Addr Base Index Displacement
- | ImmAddr Imm Int
+ = AddrBaseIndex Base Index Displacement
+ | ImmAddr Imm Int
type Base = Maybe Reg
type Index = Maybe (Reg, Int) -- Int is 2, 4 or 8
| AddrRegImm Reg Imm
#endif
-addrOffset :: Addr -> Int -> Maybe Addr
+#if powerpc_TARGET_ARCH
+ = AddrRegReg Reg Reg
+ | AddrRegImm Reg Imm
+#endif
+
+#if i386_TARGET_ARCH
+addrModeRegs :: AddrMode -> [Reg]
+addrModeRegs (AddrBaseIndex b i _) = b_regs ++ i_regs
+ where
+ b_regs = case b of { Just r -> [r]; _ -> [] }
+ i_regs = case i of { Just (r,_) -> [r]; _ -> [] }
+addrModeRegs _ = []
+#endif
+
+
+addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset addr off
= case addr of
#endif
#if i386_TARGET_ARCH
ImmAddr i off0 -> Just (ImmAddr i (off0 + off))
- Addr r i (ImmInt n) -> Just (Addr r i (ImmInt (n + off)))
- Addr r i (ImmInteger n)
- -> Just (Addr r i (ImmInt (fromInteger (n + toInteger off))))
- _ -> Nothing
+
+ AddrBaseIndex r i (ImmInt n) -> Just (AddrBaseIndex r i (ImmInt (n + off)))
+ AddrBaseIndex r i (ImmInteger n)
+ -> Just (AddrBaseIndex r i (ImmInt (fromInteger (n + toInteger off))))
+
+ AddrBaseIndex r i (ImmCLbl lbl)
+ -> Just (AddrBaseIndex r i (ImmIndex lbl off))
+
+ AddrBaseIndex r i (ImmIndex lbl ix)
+ -> Just (AddrBaseIndex r i (ImmIndex lbl (ix+off)))
+
+ _ -> Nothing -- in theory, shouldn't happen
#endif
#if sparc_TARGET_ARCH
AddrRegImm r (ImmInt n)
| otherwise -> Nothing
where n2 = n + toInteger off
- AddrRegReg r (FixedReg ILIT(0))
+ AddrRegReg r (RealReg 0)
| fits13Bits off -> Just (AddrRegImm r (ImmInt off))
| otherwise -> Nothing
_ -> Nothing
+#endif /* sparc */
+#if powerpc_TARGET_ARCH
+ AddrRegImm r (ImmInt n)
+ | fits16Bits n2 -> Just (AddrRegImm r (ImmInt n2))
+ | otherwise -> Nothing
+ where n2 = n + off
-#endif {-sparc-}
+ AddrRegImm r (ImmInteger n)
+ | fits16Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
+ | otherwise -> Nothing
+ where n2 = n + toInteger off
+
+ _ -> Nothing
+#endif /* powerpc */
-----------------
#if alpha_TARGET_ARCH
#endif
#if sparc_TARGET_ARCH
-{-# SPECIALIZE
- fits13Bits :: Int -> Bool
- #-}
-{-# SPECIALIZE
- fits13Bits :: Integer -> Bool
- #-}
+{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
fits13Bits :: Integral a => a -> Bool
fits13Bits x = x >= -4096 && x < 4096
-----------------
largeOffsetError i
- = error ("ERROR: SPARC native-code generator cannot handle large offset ("++show i++");\nprobably because of large constant data structures;\nworkaround: use -fvia-C on this module.\n")
-
-#endif {-sparc-}
-\end{code}
+ = error ("ERROR: SPARC native-code generator cannot handle large offset ("
+ ++show i++");\nprobably because of large constant data structures;" ++
+ "\nworkaround: use -fvia-C on this module.\n")
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#endif /* sparc */
-@stgReg@: we map STG registers onto appropriate Stix Trees. First, we
-handle the two constants, @STK_STUB_closure@ and @vtbl_StdUpdFrame@.
-The rest are either in real machine registers or stored as offsets
-from BaseReg.
+#if powerpc_TARGET_ARCH
+fits16Bits :: Integral a => a -> Bool
+fits16Bits x = x >= -32768 && x < 32768
-\begin{code}
-data RegLoc = Save StixTree | Always StixTree
-\end{code}
-
-Trees for register save locations:
-\begin{code}
-saveLoc :: MagicId -> StixTree
-
-saveLoc reg = case (stgReg reg) of {Always loc -> loc; Save loc -> loc}
-\end{code}
+makeImmediate :: Integral a => MachRep -> Bool -> a -> Maybe Imm
-\begin{code}
-stgReg :: MagicId -> RegLoc
-
-stgReg x
- = case (magicIdRegMaybe x) of
- Just _ -> Save nonReg
- Nothing -> Always nonReg
- where
- offset = baseRegOffset x
-
- baseLoc = case (magicIdRegMaybe BaseReg) of
- Just _ -> StReg (StixMagicId BaseReg)
- Nothing -> sStLitLbl SLIT("MainRegTable")
-
- nonReg = case x of
- StkStubReg -> sStLitLbl SLIT("STK_STUB_closure")
- StdUpdRetVecReg -> sStLitLbl SLIT("vtbl_StdUpdFrame")
- BaseReg -> sStLitLbl SLIT("MainRegTable")
- -- these Hp&HpLim cases perhaps should
- -- not be here for i386 (???) WDP 96/03
- Hp -> StInd PtrRep (sStLitLbl SLIT("StorageMgrInfo"))
- HpLim -> StInd PtrRep (sStLitLbl
- (_PK_ ("StorageMgrInfo+" ++ BYTES_PER_WORD_STR)))
- TagReg -> StInd IntRep (StPrim IntSubOp [infoptr,
- StInt (1*BYTES_PER_WORD)])
- where
- r2 = VanillaReg PtrRep ILIT(2)
- infoptr = case (stgReg r2) of
- Always t -> t
- Save _ -> StReg (StixMagicId r2)
- _ -> StInd (magicIdPrimRep x)
- (StPrim IntAddOp [baseLoc,
- StInt (toInteger (offset*BYTES_PER_WORD))])
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-@spRel@ gives us a stack relative addressing mode for volatile
-temporaries and for excess call arguments. @fpRel@, where
-applicable, is the same but for the frame pointer.
+makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
+ where
+ narrow I32 False = fromIntegral (fromIntegral x :: Word32)
+ narrow I16 False = fromIntegral (fromIntegral x :: Word16)
+ narrow I8 False = fromIntegral (fromIntegral x :: Word8)
+ narrow I32 True = fromIntegral (fromIntegral x :: Int32)
+ narrow I16 True = fromIntegral (fromIntegral x :: Int16)
+ narrow I8 True = fromIntegral (fromIntegral x :: Int8)
+
+ narrowed = narrow rep signed
+
+ toI16 I32 True
+ | narrowed >= -32768 && narrowed < 32768 = Just narrowed
+ | otherwise = Nothing
+ toI16 I32 False
+ | narrowed >= 0 && narrowed < 65536 = Just narrowed
+ | otherwise = Nothing
+ toI16 _ _ = Just narrowed
+#endif
+
+
+-- @spRel@ gives us a stack relative addressing mode for volatile
+-- temporaries and for excess call arguments. @fpRel@, where
+-- applicable, is the same but for the frame pointer.
-\begin{code}
spRel :: Int -- desired stack offset in words, positive or negative
- -> Addr
+ -> AddrMode
spRel n
#if i386_TARGET_ARCH
- = Addr (Just esp) Nothing (ImmInt (n * BYTES_PER_WORD))
+ = AddrBaseIndex (Just esp) Nothing (ImmInt (n * wORD_SIZE))
#else
- = AddrRegImm sp (ImmInt (n * BYTES_PER_WORD))
+ = AddrRegImm sp (ImmInt (n * wORD_SIZE))
#endif
#if sparc_TARGET_ARCH
-fpRel :: Int -> Addr
+fpRel :: Int -> AddrMode
-- Duznae work for offsets greater than 13 bits; we just hope for
-- the best
fpRel n
- = AddrRegImm fp (ImmInt (n * BYTES_PER_WORD))
-#endif
-\end{code}
-
-%************************************************************************
-%* *
-\subsection[Reg]{Real registers}
-%* *
-%************************************************************************
+ = AddrRegImm fp (ImmInt (n * wORD_SIZE))
+#endif
+
+
+-- -----------------------------------------------------------------------------
+-- Global registers
+
+-- We map STG registers onto appropriate CmmExprs. Either they map
+-- to real machine registers or stored as offsets from BaseReg. Given
+-- a GlobalReg, get_GlobalReg_reg_or_addr produces either the real
+-- register it is in, on this platform, or a StixExpr denoting the
+-- address in the register table holding it. get_MagicId_addr always
+-- produces the register table address for it.
+
+get_GlobalReg_reg_or_addr :: GlobalReg -> Either Reg CmmExpr
+get_GlobalReg_addr :: GlobalReg -> CmmExpr
+get_Regtable_addr_from_offset :: MachRep -> Int -> CmmExpr
+
+get_GlobalReg_reg_or_addr mid
+ = case globalRegMaybe mid of
+ Just rr -> Left rr
+ Nothing -> Right (get_GlobalReg_addr mid)
+
+get_GlobalReg_addr BaseReg = regTableOffset 0
+get_GlobalReg_addr mid = get_Regtable_addr_from_offset
+ (globalRegRep mid) (baseRegOffset mid)
+
+-- Calculate a literal representing an offset into the register table.
+-- Used when we don't have an actual BaseReg to offset from.
+regTableOffset n =
+ CmmLit (CmmLabelOff mkMainCapabilityLabel (oFFSET_Capability_r + n))
+
+get_Regtable_addr_from_offset rep offset
+ = case globalRegMaybe BaseReg of
+ Nothing -> regTableOffset offset
+ Just _ -> CmmRegOff (CmmGlobal BaseReg) offset
+
+-- ---------------------------------------------------------------------------
+-- Registers
+
+-- RealRegs are machine regs which are available for allocation, in
+-- the usual way. We know what class they are, because that's part of
+-- the processor's architecture.
+
+-- VirtualRegs are virtual registers. The register allocator will
+-- eventually have to map them into RealRegs, or into spill slots.
+-- VirtualRegs are allocated on the fly, usually to represent a single
+-- value in the abstract assembly code (i.e. dynamic registers are
+-- usually single assignment). With the new register allocator, the
+-- single assignment restriction isn't necessary to get correct code,
+-- although a better register allocation will result if single
+-- assignment is used -- because the allocator maps a VirtualReg into
+-- a single RealReg, even if the VirtualReg has multiple live ranges.
+
+-- Virtual regs can be of either class, so that info is attached.
+
+-- Determine the upper-half vreg for a 64-bit quantity on a 32-bit platform
+-- when supplied with the vreg for the lower-half of the quantity.
+-- (NB. Not reversible).
+getHiVRegFromLo (VirtualRegI u)
+ = VirtualRegHi (newTagUnique u 'H') -- makes a pseudo-unique with tag 'H'
+getHiVRegFromLo other
+ = pprPanic "getHiVRegFromLo" (ppr other)
+
+data RegClass
+ = RcInteger
+ | RcFloat
+ | RcDouble
+ deriving Eq
-Static Registers correspond to actual machine registers. These should
-be avoided until the last possible moment.
-
-Dynamic registers are allocated on the fly, usually to represent a single
-value in the abstract assembly code (i.e. dynamic registers are usually
-single assignment). Ultimately, they are mapped to available machine
-registers before spitting out the code.
+type RegNo = Int
-\begin{code}
data Reg
- = FixedReg FAST_INT -- A pre-allocated machine register
-
- | MappedReg FAST_INT -- A dynamically allocated machine register
-
- | MemoryReg Int PrimRep -- A machine "register" actually held in
- -- a memory allocated table of
- -- registers which didn't fit in real
- -- registers.
-
- | UnmappedReg Unique PrimRep -- One of an infinite supply of registers,
- -- always mapped to one of the earlier
- -- two (?) before we're done.
+ = RealReg {-# UNPACK #-} !RegNo
+ | VirtualRegI {-# UNPACK #-} !Unique
+ | VirtualRegHi {-# UNPACK #-} !Unique -- High part of 2-word register
+ | VirtualRegF {-# UNPACK #-} !Unique
+ | VirtualRegD {-# UNPACK #-} !Unique
+ deriving (Eq,Ord)
+
+-- We like to have Uniques for Reg so that we can make UniqFM and UniqSets
+-- in the register allocator.
+instance Uniquable Reg where
+ getUnique (RealReg i) = mkUnique 'C' i
+ getUnique (VirtualRegI u) = u
+ getUnique (VirtualRegHi u) = u
+ getUnique (VirtualRegF u) = u
+ getUnique (VirtualRegD u) = u
+
+mkVReg :: Unique -> MachRep -> Reg
+mkVReg u rep
+ = case rep of
+#if sparc_TARGET_ARCH
+ F32 -> VirtualRegF u
+#else
+ F32 -> VirtualRegD u
+#endif
+ F64 -> VirtualRegD u
+ other -> VirtualRegI u
-mkReg :: Unique -> PrimRep -> Reg
-mkReg = UnmappedReg
+isVirtualReg :: Reg -> Bool
+isVirtualReg (RealReg _) = False
+isVirtualReg (VirtualRegI _) = True
+isVirtualReg (VirtualRegHi _) = True
+isVirtualReg (VirtualRegF _) = True
+isVirtualReg (VirtualRegD _) = True
-getNewRegNCG :: PrimRep -> UniqSM Reg
-getNewRegNCG pk
- = getUnique `thenUs` \ u ->
- returnUs (UnmappedReg u pk)
+isRealReg :: Reg -> Bool
+isRealReg = not . isVirtualReg
-instance Text Reg where
- showsPrec _ (FixedReg i) = showString "%" . shows IBOX(i)
- showsPrec _ (MappedReg i) = showString "%" . shows IBOX(i)
- showsPrec _ (MemoryReg i _) = showString "%M" . shows i
- showsPrec _ (UnmappedReg i _) = showString "%U" . shows i
+instance Show Reg where
+ show (RealReg i) = showReg i
+ show (VirtualRegI u) = "%vI_" ++ show u
+ show (VirtualRegHi u) = "%vHi_" ++ show u
+ show (VirtualRegF u) = "%vF_" ++ show u
+ show (VirtualRegD u) = "%vD_" ++ show u
-#ifdef DEBUG
instance Outputable Reg where
- ppr sty r = text (show r)
-#endif
-
-cmpReg (FixedReg i) (FixedReg i') = cmp_ihash i i'
-cmpReg (MappedReg i) (MappedReg i') = cmp_ihash i i'
-cmpReg (MemoryReg i _) (MemoryReg i' _) = cmp_i i i'
-cmpReg (UnmappedReg u _) (UnmappedReg u' _) = cmp u u'
-cmpReg r1 r2
- = let tag1 = tagReg r1
- tag2 = tagReg r2
- in
- if tag1 _LT_ tag2 then LT_ else GT_
- where
- tagReg (FixedReg _) = (ILIT(1) :: FAST_INT)
- tagReg (MappedReg _) = ILIT(2)
- tagReg (MemoryReg _ _) = ILIT(3)
- tagReg (UnmappedReg _ _) = ILIT(4)
-
-cmp_i :: Int -> Int -> TAG_
-cmp_i a1 a2 = if a1 == a2 then EQ_ else if a1 < a2 then LT_ else GT_
-
-cmp_ihash :: FAST_INT -> FAST_INT -> TAG_
-cmp_ihash a1 a2 = if a1 _EQ_ a2 then EQ_ else if a1 _LT_ a2 then LT_ else GT_
-
-instance Ord3 Reg where
- cmp = cmpReg
-
-instance Eq Reg where
- a == b = case (a `cmp` b) of { EQ_ -> True; _ -> False }
- a /= b = case (a `cmp` b) of { EQ_ -> False; _ -> True }
-
-instance Ord Reg where
- a <= b = case (a `cmp` b) of { LT_ -> True; EQ_ -> True; GT__ -> False }
- a < b = case (a `cmp` b) of { LT_ -> True; EQ_ -> False; GT__ -> False }
- a >= b = case (a `cmp` b) of { LT_ -> False; EQ_ -> True; GT__ -> True }
- a > b = case (a `cmp` b) of { LT_ -> False; EQ_ -> False; GT__ -> True }
- _tagCmp a b = case (a `cmp` b) of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
+ ppr r = Outputable.text (show r)
-instance Uniquable Reg where
- uniqueOf (UnmappedReg u _) = u
- uniqueOf (FixedReg i) = mkPseudoUnique1 IBOX(i)
- uniqueOf (MappedReg i) = mkPseudoUnique2 IBOX(i)
- uniqueOf (MemoryReg i _) = mkPseudoUnique3 i
-\end{code}
-
-\begin{code}
-type RegNo = Int
-realReg :: RegNo -> Reg
-realReg n@IBOX(i)
- = if _IS_TRUE_(freeReg i) then MappedReg i else FixedReg i
+-- -----------------------------------------------------------------------------
+-- Machine-specific register stuff
-extractMappedRegNos :: [Reg] -> [RegNo]
+-- The Alpha has 64 registers of interest; 32 integer registers and 32 floating
+-- point registers. The mapping of STG registers to alpha machine registers
+-- is defined in StgRegs.h. We are, of course, prepared for any eventuality.
-extractMappedRegNos regs
- = foldr ex [] regs
- where
- ex (MappedReg i) acc = IBOX(i) : acc -- we'll take it
- ex _ acc = acc -- leave it out
-\end{code}
-
-** Machine-specific Reg stuff: **
-
-The Alpha has 64 registers of interest; 32 integer registers and 32 floating
-point registers. The mapping of STG registers to alpha machine registers
-is defined in StgRegs.h. We are, of course, prepared for any eventuality.
-\begin{code}
#if alpha_TARGET_ARCH
-fReg :: Int -> Int
+fReg :: Int -> RegNo
fReg x = (32 + x)
v0, f0, ra, pv, gp, sp, zeroh :: Reg
t11 = realReg 25
t12 = realReg 27
#endif
-\end{code}
+{-
Intel x86 architecture:
- All registers except 7 (esp) are available for use.
- Only ebx, esi, edi and esp are available across a C call (they are callee-saves).
- Registers 0-7 have 16-bit counterparts (ax, bx etc.)
- Registers 0-3 have 8 bit counterparts (ah, bh etc.)
-- Registers 8-15 hold extended floating point values.
-\begin{code}
-#if i386_TARGET_ARCH
+- Registers 8-13 are fakes; we pretend x86 has 6 conventionally-addressable
+ fp registers, and 3-operand insns for them, and we translate this into
+ real stack-based x86 fp code after register allocation.
-gReg,fReg :: Int -> Int
-gReg x = x
-fReg x = (8 + x)
-
-st0, st1, st2, st3, st4, st5, st6, st7, eax, ebx, ecx, edx, esp :: Reg
-eax = case (gReg 0) of { IBOX(g0) -> FixedReg g0 }
-ebx = case (gReg 1) of { IBOX(g1) -> FixedReg g1 }
-ecx = case (gReg 2) of { IBOX(g2) -> FixedReg g2 }
-edx = case (gReg 3) of { IBOX(g3) -> FixedReg g3 }
-esi = case (gReg 4) of { IBOX(g4) -> FixedReg g4 }
-edi = case (gReg 5) of { IBOX(g5) -> FixedReg g5 }
-ebp = case (gReg 6) of { IBOX(g6) -> FixedReg g6 }
-esp = case (gReg 7) of { IBOX(g7) -> FixedReg g7 }
-st0 = realReg (fReg 0)
-st1 = realReg (fReg 1)
-st2 = realReg (fReg 2)
-st3 = realReg (fReg 3)
-st4 = realReg (fReg 4)
-st5 = realReg (fReg 5)
-st6 = realReg (fReg 6)
-st7 = realReg (fReg 7)
+The fp registers are all Double registers; we don't have any RcFloat class
+regs. @regClass@ barfs if you give it a VirtualRegF, and mkVReg above should
+never generate them.
+-}
-#endif
-\end{code}
+#if i386_TARGET_ARCH
+fake0, fake1, fake2, fake3, fake4, fake5,
+ eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg
+eax = RealReg 0
+ebx = RealReg 1
+ecx = RealReg 2
+edx = RealReg 3
+esi = RealReg 4
+edi = RealReg 5
+ebp = RealReg 6
+esp = RealReg 7
+fake0 = RealReg 8
+fake1 = RealReg 9
+fake2 = RealReg 10
+fake3 = RealReg 11
+fake4 = RealReg 12
+fake5 = RealReg 13
+
+-- On x86, we might want to have an 8-bit RegClass, which would
+-- contain just regs 1-4 (the others don't have 8-bit versions).
+-- However, we can get away without this at the moment because the
+-- only allocatable integer regs are also 8-bit compatible (1, 3, 4).
+regClass (RealReg i) = if i < 8 then RcInteger else RcDouble
+regClass (VirtualRegI u) = RcInteger
+regClass (VirtualRegHi u) = RcInteger
+regClass (VirtualRegD u) = RcDouble
+regClass (VirtualRegF u) = pprPanic "regClass(x86):VirtualRegF"
+ (ppr (VirtualRegF u))
+
+regNames
+ = ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
+ "%fake0", "%fake1", "%fake2", "%fake3", "%fake4", "%fake5", "%fake6"]
+
+showReg :: RegNo -> String
+showReg n
+ = if n >= 0 && n < 14
+ then regNames !! n
+ else "%unknown_x86_real_reg_" ++ show n
+
+#endif
+
+{-
The SPARC has 64 registers of interest; 32 integer registers and 32
floating point registers. The mapping of STG registers to SPARC
machine registers is defined in StgRegs.h. We are, of course,
prepared for any eventuality.
-\begin{code}
+The whole fp-register pairing thing on sparcs is a huge nuisance. See
+fptools/ghc/includes/MachRegs.h for a description of what's going on
+here.
+-}
+
#if sparc_TARGET_ARCH
-gReg,lReg,iReg,oReg,fReg :: Int -> Int
+gReg,lReg,iReg,oReg,fReg :: Int -> RegNo
gReg x = x
oReg x = (8 + x)
lReg x = (16 + x)
iReg x = (24 + x)
fReg x = (32 + x)
-fPair :: Reg -> Reg
-fPair (FixedReg i) = FixedReg (i _ADD_ ILIT(1))
-fPair (MappedReg i) = MappedReg (i _ADD_ ILIT(1))
+nCG_FirstFloatReg :: RegNo
+nCG_FirstFloatReg = unRealReg NCG_FirstFloatReg
+
+regClass (VirtualRegI u) = RcInteger
+regClass (VirtualRegF u) = RcFloat
+regClass (VirtualRegD u) = RcDouble
+regClass (RealReg i) | i < 32 = RcInteger
+ | i < nCG_FirstFloatReg = RcDouble
+ | otherwise = RcFloat
+
+showReg :: RegNo -> String
+showReg n
+ | n >= 0 && n < 8 = "%g" ++ show n
+ | n >= 8 && n < 16 = "%o" ++ show (n-8)
+ | n >= 16 && n < 24 = "%l" ++ show (n-16)
+ | n >= 24 && n < 32 = "%i" ++ show (n-24)
+ | n >= 32 && n < 64 = "%f" ++ show (n-32)
+ | otherwise = "%unknown_sparc_real_reg_" ++ show n
+
+g0, g1, g2, fp, sp, o0, o1, f0, f1, f6, f8, f22, f26, f27 :: Reg
+
+f6 = RealReg (fReg 6)
+f8 = RealReg (fReg 8)
+f22 = RealReg (fReg 22)
+f26 = RealReg (fReg 26)
+f27 = RealReg (fReg 27)
-g0, fp, sp, o0, f0 :: Reg
-g0 = case (gReg 0) of { IBOX(g0) -> FixedReg g0 }
-fp = case (iReg 6) of { IBOX(i6) -> FixedReg i6 }
-sp = case (oReg 6) of { IBOX(o6) -> FixedReg o6 }
-o0 = realReg (oReg 0)
-f0 = realReg (fReg 0)
+
+-- g0 is useful for codegen; is always zero, and writes to it vanish.
+g0 = RealReg (gReg 0)
+g1 = RealReg (gReg 1)
+g2 = RealReg (gReg 2)
+
+-- FP, SP, int and float return (from C) regs.
+fp = RealReg (iReg 6)
+sp = RealReg (oReg 6)
+o0 = RealReg (oReg 0)
+o1 = RealReg (oReg 1)
+f0 = RealReg (fReg 0)
+f1 = RealReg (fReg 1)
#endif
-\end{code}
+{-
+The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
+point registers.
+-}
+
+#if powerpc_TARGET_ARCH
+fReg :: Int -> RegNo
+fReg x = (32 + x)
+
+regClass (VirtualRegI u) = RcInteger
+regClass (VirtualRegHi u) = RcInteger
+regClass (VirtualRegF u) = pprPanic "regClass(ppc):VirtualRegF"
+ (ppr (VirtualRegF u))
+regClass (VirtualRegD u) = RcDouble
+regClass (RealReg i) | i < 32 = RcInteger
+ | otherwise = RcDouble
+
+showReg :: RegNo -> String
+showReg n
+ | n >= 0 && n <= 31 = "%r" ++ show n
+ | n >= 32 && n <= 63 = "%f" ++ show (n - 32)
+ | otherwise = "%unknown_powerpc_real_reg_" ++ show n
+
+sp = RealReg 1
+r3 = RealReg 3
+r4 = RealReg 4
+r27 = RealReg 27
+r28 = RealReg 28
+f1 = RealReg $ fReg 1
+f20 = RealReg $ fReg 20
+f21 = RealReg $ fReg 21
+#endif
+
+{-
Redefine the literals used for machine-registers with non-numeric
names in the header files. Gag me with a spoon, eh?
-\begin{code}
+-}
+
#if alpha_TARGET_ARCH
#define f0 32
#define f1 33
#define edi 5
#define ebp 6
#define esp 7
-#define st0 8
-#define st1 9
-#define st2 10
-#define st3 11
-#define st4 12
-#define st5 13
-#define st6 14
-#define st7 15
+#define fake0 8
+#define fake1 9
+#define fake2 10
+#define fake3 11
+#define fake4 12
+#define fake5 13
#endif
#if sparc_TARGET_ARCH
#define g0 0
#define i5 29
#define i6 30
#define i7 31
-#define f0 32
-#define f1 33
-#define f2 34
-#define f3 35
-#define f4 36
-#define f5 37
-#define f6 38
-#define f7 39
-#define f8 40
-#define f9 41
+
+#define f0 32
+#define f1 33
+#define f2 34
+#define f3 35
+#define f4 36
+#define f5 37
+#define f6 38
+#define f7 39
+#define f8 40
+#define f9 41
#define f10 42
#define f11 43
#define f12 44
#define f30 62
#define f31 63
#endif
+
+#if powerpc_TARGET_ARCH
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+#ifdef darwin_TARGET_OS
+#define f0 32
+#define f1 33
+#define f2 34
+#define f3 35
+#define f4 36
+#define f5 37
+#define f6 38
+#define f7 39
+#define f8 40
+#define f9 41
+#define f10 42
+#define f11 43
+#define f12 44
+#define f13 45
+#define f14 46
+#define f15 47
+#define f16 48
+#define f17 49
+#define f18 50
+#define f19 51
+#define f20 52
+#define f21 53
+#define f22 54
+#define f23 55
+#define f24 56
+#define f25 57
+#define f26 58
+#define f27 59
+#define f28 60
+#define f29 61
+#define f30 62
+#define f31 63
+#else
+#define fr0 32
+#define fr1 33
+#define fr2 34
+#define fr3 35
+#define fr4 36
+#define fr5 37
+#define fr6 38
+#define fr7 39
+#define fr8 40
+#define fr9 41
+#define fr10 42
+#define fr11 43
+#define fr12 44
+#define fr13 45
+#define fr14 46
+#define fr15 47
+#define fr16 48
+#define fr17 49
+#define fr18 50
+#define fr19 51
+#define fr20 52
+#define fr21 53
+#define fr22 54
+#define fr23 55
+#define fr24 56
+#define fr25 57
+#define fr26 58
+#define fr27 59
+#define fr28 60
+#define fr29 61
+#define fr30 62
+#define fr31 63
+#endif
+#endif
+
+
+-- allMachRegs is the complete set of machine regs.
+allMachRegNos :: [RegNo]
+allMachRegNos
+ = IF_ARCH_alpha( [0..63],
+ IF_ARCH_i386( [0..13],
+ IF_ARCH_sparc( ([0..31]
+ ++ [f0,f2 .. nCG_FirstFloatReg-1]
+ ++ [nCG_FirstFloatReg .. f31]),
+ IF_ARCH_powerpc([0..63],
+ ))))
+
+-- allocatableRegs is allMachRegNos with the fixed-use regs removed.
+-- i.e., these are the regs for which we are prepared to allow the
+-- register allocator to attempt to map VRegs to.
+allocatableRegs :: [RegNo]
+allocatableRegs
+ = let isFree i = isFastTrue (freeReg i)
+ in filter isFree allMachRegNos
+
+-- these are the regs which we cannot assume stay alive over a
+-- C call.
+callClobberedRegs :: [Reg]
+callClobberedRegs
+ =
+#if alpha_TARGET_ARCH
+ [0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ fReg 0, fReg 1, fReg 10, fReg 11, fReg 12, fReg 13, fReg 14, fReg 15,
+ fReg 16, fReg 17, fReg 18, fReg 19, fReg 20, fReg 21, fReg 22, fReg 23,
+ fReg 24, fReg 25, fReg 26, fReg 27, fReg 28, fReg 29, fReg 30]
+#endif /* alpha_TARGET_ARCH */
+#if i386_TARGET_ARCH
+ -- caller-saves registers
+ map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5]
+#endif /* i386_TARGET_ARCH */
+#if sparc_TARGET_ARCH
+ map RealReg
+ ( oReg 7 :
+ [oReg i | i <- [0..5]] ++
+ [gReg i | i <- [1..7]] ++
+ [fReg i | i <- [0..31]] )
+#endif /* sparc_TARGET_ARCH */
+#if powerpc_TARGET_ARCH
+#if darwin_TARGET_OS
+ map RealReg (0:[2..12] ++ map fReg [0..13])
+#elif linux_TARGET_OS
+ map RealReg (0:[2..13] ++ map fReg [0..13])
+#endif
+#endif /* powerpc_TARGET_ARCH */
+
+
+-- argRegs is the set of regs which are read for an n-argument call to C.
+-- For archs which pass all args on the stack (x86), is empty.
+-- Sparc passes up to the first 6 args in regs.
+-- Dunno about Alpha.
+argRegs :: RegNo -> [Reg]
+
+#if i386_TARGET_ARCH
+argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
+#endif
+
+#if alpha_TARGET_ARCH
+argRegs 0 = []
+argRegs 1 = freeMappedRegs [16, fReg 16]
+argRegs 2 = freeMappedRegs [16, 17, fReg 16, fReg 17]
+argRegs 3 = freeMappedRegs [16, 17, 18, fReg 16, fReg 17, fReg 18]
+argRegs 4 = freeMappedRegs [16, 17, 18, 19, fReg 16, fReg 17, fReg 18, fReg 19]
+argRegs 5 = freeMappedRegs [16, 17, 18, 19, 20, fReg 16, fReg 17, fReg 18, fReg 19, fReg 20]
+argRegs 6 = freeMappedRegs [16, 17, 18, 19, 20, 21, fReg 16, fReg 17, fReg 18, fReg 19, fReg 20, fReg 21]
+argRegs _ = panic "MachRegs.argRegs(alpha): don't know about >6 arguments!"
+#endif /* alpha_TARGET_ARCH */
+
+#if sparc_TARGET_ARCH
+argRegs 0 = []
+argRegs 1 = map (RealReg . oReg) [0]
+argRegs 2 = map (RealReg . oReg) [0,1]
+argRegs 3 = map (RealReg . oReg) [0,1,2]
+argRegs 4 = map (RealReg . oReg) [0,1,2,3]
+argRegs 5 = map (RealReg . oReg) [0,1,2,3,4]
+argRegs 6 = map (RealReg . oReg) [0,1,2,3,4,5]
+argRegs _ = panic "MachRegs.argRegs(sparc): don't know about >6 arguments!"
+#endif /* sparc_TARGET_ARCH */
+
+#if powerpc_TARGET_ARCH
+argRegs 0 = []
+argRegs 1 = map RealReg [3]
+argRegs 2 = map RealReg [3,4]
+argRegs 3 = map RealReg [3..5]
+argRegs 4 = map RealReg [3..6]
+argRegs 5 = map RealReg [3..7]
+argRegs 6 = map RealReg [3..8]
+argRegs 7 = map RealReg [3..9]
+argRegs 8 = map RealReg [3..10]
+argRegs _ = panic "MachRegs.argRegs(powerpc): don't know about >8 arguments!"
+#endif /* powerpc_TARGET_ARCH */
+
+
+-- all of the arg regs ??
+#if alpha_TARGET_ARCH
+allArgRegs :: [(Reg, Reg)]
+allArgRegs = [(realReg i, realReg (fReg i)) | i <- [16..21]]
+#endif /* alpha_TARGET_ARCH */
+
+#if sparc_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = map RealReg [oReg i | i <- [0..5]]
+#endif /* sparc_TARGET_ARCH */
+
+#if i386_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = panic "MachRegs.allArgRegs(x86): should not be used!"
+#endif
+
+#if powerpc_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = map RealReg [3..10]
+allFPArgRegs :: [Reg]
+#if darwin_TARGET_OS
+allFPArgRegs = map (RealReg . fReg) [1..13]
+#elif linux_TARGET_OS
+allFPArgRegs = map (RealReg . fReg) [1..8]
+#endif
+#endif /* powerpc_TARGET_ARCH */
\end{code}
\begin{code}
-baseRegOffset :: MagicId -> Int
-
-baseRegOffset StkOReg = OFFSET_StkO
-baseRegOffset (VanillaReg _ ILIT(1)) = OFFSET_R1
-baseRegOffset (VanillaReg _ ILIT(2)) = OFFSET_R2
-baseRegOffset (VanillaReg _ ILIT(3)) = OFFSET_R3
-baseRegOffset (VanillaReg _ ILIT(4)) = OFFSET_R4
-baseRegOffset (VanillaReg _ ILIT(5)) = OFFSET_R5
-baseRegOffset (VanillaReg _ ILIT(6)) = OFFSET_R6
-baseRegOffset (VanillaReg _ ILIT(7)) = OFFSET_R7
-baseRegOffset (VanillaReg _ ILIT(8)) = OFFSET_R8
-baseRegOffset (FloatReg ILIT(1)) = OFFSET_Flt1
-baseRegOffset (FloatReg ILIT(2)) = OFFSET_Flt2
-baseRegOffset (FloatReg ILIT(3)) = OFFSET_Flt3
-baseRegOffset (FloatReg ILIT(4)) = OFFSET_Flt4
-baseRegOffset (DoubleReg ILIT(1)) = OFFSET_Dbl1
-baseRegOffset (DoubleReg ILIT(2)) = OFFSET_Dbl2
-baseRegOffset TagReg = OFFSET_Tag
-baseRegOffset RetReg = OFFSET_Ret
-baseRegOffset SpA = OFFSET_SpA
-baseRegOffset SuA = OFFSET_SuA
-baseRegOffset SpB = OFFSET_SpB
-baseRegOffset SuB = OFFSET_SuB
-baseRegOffset Hp = OFFSET_Hp
-baseRegOffset HpLim = OFFSET_HpLim
-baseRegOffset LivenessReg = OFFSET_Liveness
+freeReg :: RegNo -> FastBool
+
+#if alpha_TARGET_ARCH
+freeReg 26 = fastBool False -- return address (ra)
+freeReg 28 = fastBool False -- reserved for the assembler (at)
+freeReg 29 = fastBool False -- global pointer (gp)
+freeReg 30 = fastBool False -- stack pointer (sp)
+freeReg 31 = fastBool False -- always zero (zeroh)
+freeReg 63 = fastBool False -- always zero (f31)
+#endif
+
+#if i386_TARGET_ARCH
+freeReg esp = fastBool False -- %esp is the C stack pointer
+#endif
+
+#if sparc_TARGET_ARCH
+freeReg g0 = fastBool False -- %g0 is always 0.
+freeReg g5 = fastBool False -- %g5 is reserved (ABI).
+freeReg g6 = fastBool False -- %g6 is reserved (ABI).
+freeReg g7 = fastBool False -- %g7 is reserved (ABI).
+freeReg i6 = fastBool False -- %i6 is our frame pointer.
+freeReg i7 = fastBool False -- %i7 tends to have ret-addr-ish things
+freeReg o6 = fastBool False -- %o6 is our stack pointer.
+freeReg o7 = fastBool False -- %o7 holds ret addrs (???)
+freeReg f0 = fastBool False -- %f0/%f1 are the C fp return registers.
+freeReg f1 = fastBool False
+#endif
+
+#if powerpc_TARGET_ARCH
+freeReg 0 = fastBool False -- Hack: r0 can't be used in all insns, but it's actually free
+freeReg 1 = fastBool False -- The Stack Pointer
+#if !darwin_TARGET_OS
+ -- most non-darwin powerpc OSes use r2 as a TOC pointer or something like that
+freeReg 2 = fastBool False
+#endif
+#endif
+
+#ifdef REG_Base
+freeReg REG_Base = fastBool False
+#endif
+#ifdef REG_R1
+freeReg REG_R1 = fastBool False
+#endif
+#ifdef REG_R2
+freeReg REG_R2 = fastBool False
+#endif
+#ifdef REG_R3
+freeReg REG_R3 = fastBool False
+#endif
+#ifdef REG_R4
+freeReg REG_R4 = fastBool False
+#endif
+#ifdef REG_R5
+freeReg REG_R5 = fastBool False
+#endif
+#ifdef REG_R6
+freeReg REG_R6 = fastBool False
+#endif
+#ifdef REG_R7
+freeReg REG_R7 = fastBool False
+#endif
+#ifdef REG_R8
+freeReg REG_R8 = fastBool False
+#endif
+#ifdef REG_F1
+freeReg REG_F1 = fastBool False
+#endif
+#ifdef REG_F2
+freeReg REG_F2 = fastBool False
+#endif
+#ifdef REG_F3
+freeReg REG_F3 = fastBool False
+#endif
+#ifdef REG_F4
+freeReg REG_F4 = fastBool False
+#endif
+#ifdef REG_D1
+freeReg REG_D1 = fastBool False
+#endif
+#ifdef REG_D2
+freeReg REG_D2 = fastBool False
+#endif
+#ifdef REG_Sp
+freeReg REG_Sp = fastBool False
+#endif
+#ifdef REG_Su
+freeReg REG_Su = fastBool False
+#endif
+#ifdef REG_SpLim
+freeReg REG_SpLim = fastBool False
+#endif
+#ifdef REG_Hp
+freeReg REG_Hp = fastBool False
+#endif
+#ifdef REG_HpLim
+freeReg REG_HpLim = fastBool False
+#endif
+freeReg n = fastBool True
+
+
+-- -----------------------------------------------------------------------------
+-- Information about global registers
+
+baseRegOffset :: GlobalReg -> Int
+
+baseRegOffset (VanillaReg 1) = oFFSET_StgRegTable_rR1
+baseRegOffset (VanillaReg 2) = oFFSET_StgRegTable_rR2
+baseRegOffset (VanillaReg 3) = oFFSET_StgRegTable_rR3
+baseRegOffset (VanillaReg 4) = oFFSET_StgRegTable_rR4
+baseRegOffset (VanillaReg 5) = oFFSET_StgRegTable_rR5
+baseRegOffset (VanillaReg 6) = oFFSET_StgRegTable_rR6
+baseRegOffset (VanillaReg 7) = oFFSET_StgRegTable_rR7
+baseRegOffset (VanillaReg 8) = oFFSET_StgRegTable_rR8
+baseRegOffset (VanillaReg 9) = oFFSET_StgRegTable_rR9
+baseRegOffset (VanillaReg 10) = oFFSET_StgRegTable_rR10
+baseRegOffset (FloatReg 1) = oFFSET_StgRegTable_rF1
+baseRegOffset (FloatReg 2) = oFFSET_StgRegTable_rF2
+baseRegOffset (FloatReg 3) = oFFSET_StgRegTable_rF3
+baseRegOffset (FloatReg 4) = oFFSET_StgRegTable_rF4
+baseRegOffset (DoubleReg 1) = oFFSET_StgRegTable_rD1
+baseRegOffset (DoubleReg 2) = oFFSET_StgRegTable_rD2
+baseRegOffset Sp = oFFSET_StgRegTable_rSp
+baseRegOffset SpLim = oFFSET_StgRegTable_rSpLim
+baseRegOffset (LongReg 1) = oFFSET_StgRegTable_rL1
+baseRegOffset Hp = oFFSET_StgRegTable_rHp
+baseRegOffset HpLim = oFFSET_StgRegTable_rHpLim
+baseRegOffset CurrentTSO = oFFSET_StgRegTable_rCurrentTSO
+baseRegOffset CurrentNursery = oFFSET_StgRegTable_rCurrentNursery
+baseRegOffset HpAlloc = oFFSET_StgRegTable_rHpAlloc
+baseRegOffset GCEnter1 = oFFSET_stgGCEnter1
+baseRegOffset GCFun = oFFSET_stgGCFun
#ifdef DEBUG
-baseRegOffset BaseReg = panic "baseRegOffset:BaseReg"
-baseRegOffset StdUpdRetVecReg = panic "baseRegOffset:StgUpdRetVecReg"
-baseRegOffset StkStubReg = panic "baseRegOffset:StkStubReg"
-baseRegOffset CurCostCentre = panic "baseRegOffset:CurCostCentre"
-baseRegOffset VoidReg = panic "baseRegOffset:VoidReg"
+baseRegOffset BaseReg = panic "baseRegOffset:BaseReg"
+baseRegOffset _ = panic "baseRegOffset:other"
#endif
-\end{code}
-\begin{code}
-callerSaves :: MagicId -> Bool
+
+-- | Returns 'True' if this global register is stored in a caller-saves
+-- machine register.
+
+callerSaves :: GlobalReg -> Bool
#ifdef CALLER_SAVES_Base
callerSaves BaseReg = True
#endif
-#ifdef CALLER_SAVES_StkO
-callerSaves StkOReg = True
-#endif
#ifdef CALLER_SAVES_R1
callerSaves (VanillaReg _ ILIT(1)) = True
#endif
#ifdef CALLER_SAVES_R8
callerSaves (VanillaReg _ ILIT(8)) = True
#endif
-#ifdef CALLER_SAVES_FltReg1
-callerSaves (FloatReg ILIT(1)) = True
-#endif
-#ifdef CALLER_SAVES_FltReg2
-callerSaves (FloatReg ILIT(2)) = True
-#endif
-#ifdef CALLER_SAVES_FltReg3
-callerSaves (FloatReg ILIT(3)) = True
+#ifdef CALLER_SAVES_F1
+callerSaves (FloatReg 1#) = True
#endif
-#ifdef CALLER_SAVES_FltReg4
-callerSaves (FloatReg ILIT(4)) = True
+#ifdef CALLER_SAVES_F2
+callerSaves (FloatReg 2#) = True
#endif
-#ifdef CALLER_SAVES_DblReg1
-callerSaves (DoubleReg ILIT(1)) = True
+#ifdef CALLER_SAVES_F3
+callerSaves (FloatReg 3#) = True
#endif
-#ifdef CALLER_SAVES_DblReg2
-callerSaves (DoubleReg ILIT(2)) = True
+#ifdef CALLER_SAVES_F4
+callerSaves (FloatReg 4#) = True
#endif
-#ifdef CALLER_SAVES_Tag
-callerSaves TagReg = True
+#ifdef CALLER_SAVES_D1
+callerSaves (DoubleReg 1#) = True
#endif
-#ifdef CALLER_SAVES_Ret
-callerSaves RetReg = True
+#ifdef CALLER_SAVES_D2
+callerSaves (DoubleReg 2#) = True
#endif
-#ifdef CALLER_SAVES_SpA
-callerSaves SpA = True
+#ifdef CALLER_SAVES_L1
+callerSaves (LongReg _ ILIT(1)) = True
#endif
-#ifdef CALLER_SAVES_SuA
-callerSaves SuA = True
+#ifdef CALLER_SAVES_Sp
+callerSaves Sp = True
#endif
-#ifdef CALLER_SAVES_SpB
-callerSaves SpB = True
-#endif
-#ifdef CALLER_SAVES_SuB
-callerSaves SuB = True
+#ifdef CALLER_SAVES_SpLim
+callerSaves SpLim = True
#endif
#ifdef CALLER_SAVES_Hp
callerSaves Hp = True
#ifdef CALLER_SAVES_HpLim
callerSaves HpLim = True
#endif
-#ifdef CALLER_SAVES_Liveness
-callerSaves LivenessReg = True
-#endif
-#ifdef CALLER_SAVES_StdUpdRetVec
-callerSaves StdUpdRetVecReg = True
+#ifdef CALLER_SAVES_CurrentTSO
+callerSaves CurrentTSO = True
#endif
-#ifdef CALLER_SAVES_StkStub
-callerSaves StkStubReg = True
+#ifdef CALLER_SAVES_CurrentNursery
+callerSaves CurrentNursery = True
#endif
callerSaves _ = False
-\end{code}
-\begin{code}
-magicIdRegMaybe :: MagicId -> Maybe Reg
+
+-- | Returns 'Nothing' if this global register is not stored
+-- in a real machine register, otherwise returns @'Just' reg@, where
+-- reg is the machine register it is stored in.
+
+globalRegMaybe :: GlobalReg -> Maybe Reg
#ifdef REG_Base
-magicIdRegMaybe BaseReg = Just (FixedReg ILIT(REG_Base))
-#endif
-#ifdef REG_StkO
-magicIdRegMaybe StkOReg = Just (FixedReg ILIT(REG_StkOReg))
+globalRegMaybe BaseReg = Just (RealReg REG_Base)
#endif
#ifdef REG_R1
-magicIdRegMaybe (VanillaReg _ ILIT(1)) = Just (FixedReg ILIT(REG_R1))
+globalRegMaybe (VanillaReg 1) = Just (RealReg REG_R1)
#endif
#ifdef REG_R2
-magicIdRegMaybe (VanillaReg _ ILIT(2)) = Just (FixedReg ILIT(REG_R2))
+globalRegMaybe (VanillaReg 2) = Just (RealReg REG_R2)
#endif
#ifdef REG_R3
-magicIdRegMaybe (VanillaReg _ ILIT(3)) = Just (FixedReg ILIT(REG_R3))
+globalRegMaybe (VanillaReg 3) = Just (RealReg REG_R3)
#endif
#ifdef REG_R4
-magicIdRegMaybe (VanillaReg _ ILIT(4)) = Just (FixedReg ILIT(REG_R4))
+globalRegMaybe (VanillaReg 4) = Just (RealReg REG_R4)
#endif
#ifdef REG_R5
-magicIdRegMaybe (VanillaReg _ ILIT(5)) = Just (FixedReg ILIT(REG_R5))
+globalRegMaybe (VanillaReg 5) = Just (RealReg REG_R5)
#endif
#ifdef REG_R6
-magicIdRegMaybe (VanillaReg _ ILIT(6)) = Just (FixedReg ILIT(REG_R6))
+globalRegMaybe (VanillaReg 6) = Just (RealReg REG_R6)
#endif
#ifdef REG_R7
-magicIdRegMaybe (VanillaReg _ ILIT(7)) = Just (FixedReg ILIT(REG_R7))
+globalRegMaybe (VanillaReg 7) = Just (RealReg REG_R7)
#endif
#ifdef REG_R8
-magicIdRegMaybe (VanillaReg _ ILIT(8)) = Just (FixedReg ILIT(REG_R8))
+globalRegMaybe (VanillaReg 8) = Just (RealReg REG_R8)
+#endif
+#ifdef REG_R9
+globalRegMaybe (VanillaReg 9) = Just (RealReg REG_R9)
#endif
-#ifdef REG_Flt1
-magicIdRegMaybe (FloatReg ILIT(1)) = Just (FixedReg ILIT(REG_Flt1))
+#ifdef REG_R10
+globalRegMaybe (VanillaReg 10) = Just (RealReg REG_R10)
+#endif
+#ifdef REG_F1
+globalRegMaybe (FloatReg 1) = Just (RealReg REG_F1)
#endif
-#ifdef REG_Flt2
-magicIdRegMaybe (FloatReg ILIT(2)) = Just (FixedReg ILIT(REG_Flt2))
+#ifdef REG_F2
+globalRegMaybe (FloatReg 2) = Just (RealReg REG_F2)
#endif
-#ifdef REG_Flt3
-magicIdRegMaybe (FloatReg ILIT(3)) = Just (FixedReg ILIT(REG_Flt3))
+#ifdef REG_F3
+globalRegMaybe (FloatReg 3) = Just (RealReg REG_F3)
#endif
-#ifdef REG_Flt4
-magicIdRegMaybe (FloatReg ILIT(4)) = Just (FixedReg ILIT(REG_Flt4))
+#ifdef REG_F4
+globalRegMaybe (FloatReg 4) = Just (RealReg REG_F4)
#endif
-#ifdef REG_Dbl1
-magicIdRegMaybe (DoubleReg ILIT(1)) = Just (FixedReg ILIT(REG_Dbl1))
+#ifdef REG_D1
+globalRegMaybe (DoubleReg 1) = Just (RealReg REG_D1)
#endif
-#ifdef REG_Dbl2
-magicIdRegMaybe (DoubleReg ILIT(2)) = Just (FixedReg ILIT(REG_Dbl2))
-#endif
-#ifdef REG_Tag
-magicIdRegMaybe TagReg = Just (FixedReg ILIT(REG_TagReg))
-#endif
-#ifdef REG_Ret
-magicIdRegMaybe RetReg = Just (FixedReg ILIT(REG_Ret))
-#endif
-#ifdef REG_SpA
-magicIdRegMaybe SpA = Just (FixedReg ILIT(REG_SpA))
-#endif
-#ifdef REG_SuA
-magicIdRegMaybe SuA = Just (FixedReg ILIT(REG_SuA))
-#endif
-#ifdef REG_SpB
-magicIdRegMaybe SpB = Just (FixedReg ILIT(REG_SpB))
-#endif
-#ifdef REG_SuB
-magicIdRegMaybe SuB = Just (FixedReg ILIT(REG_SuB))
+#ifdef REG_D2
+globalRegMaybe (DoubleReg 2) = Just (RealReg REG_D2)
+#endif
+#ifdef REG_Sp
+globalRegMaybe Sp = Just (RealReg REG_Sp)
+#endif
+#ifdef REG_Lng1
+globalRegMaybe (LongReg 1) = Just (RealReg REG_Lng1)
+#endif
+#ifdef REG_Lng2
+globalRegMaybe (LongReg 2) = Just (RealReg REG_Lng2)
+#endif
+#ifdef REG_SpLim
+globalRegMaybe SpLim = Just (RealReg REG_SpLim)
#endif
#ifdef REG_Hp
-magicIdRegMaybe Hp = Just (FixedReg ILIT(REG_Hp))
+globalRegMaybe Hp = Just (RealReg REG_Hp)
#endif
#ifdef REG_HpLim
-magicIdRegMaybe HpLim = Just (FixedReg ILIT(REG_HpLim))
-#endif
-#ifdef REG_Liveness
-magicIdRegMaybe LivenessReg = Just (FixedReg ILIT(REG_Liveness))
+globalRegMaybe HpLim = Just (RealReg REG_HpLim)
#endif
-#ifdef REG_StdUpdRetVec
-magicIdRegMaybe StdUpdRetVecReg = Just (FixedReg ILIT(REG_StdUpdRetVec))
+#ifdef REG_CurrentTSO
+globalRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO)
#endif
-#ifdef REG_StkStub
-magicIdRegMaybe StkStubReg = Just (FixedReg ILIT(REG_StkStub))
+#ifdef REG_CurrentNursery
+globalRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery)
#endif
-magicIdRegMaybe _ = Nothing
-\end{code}
-
-%************************************************************************
-%* *
-\subsection{Free, reserved, call-clobbered, and argument registers}
-%* *
-%************************************************************************
+globalRegMaybe _ = Nothing
-@freeRegs@ is the list of registers we can use in register allocation.
-@freeReg@ (below) says if a particular register is free.
-
-With a per-instruction clobber list, we might be able to get some of
-these back, but it's probably not worth the hassle.
-
-@callClobberedRegs@ ... the obvious.
-
-@argRegs@: assuming a call with N arguments, what registers will be
-used to hold arguments? (NB: it doesn't know whether the arguments
-are integer or floating-point...)
-
-\begin{code}
-reservedRegs :: [RegNo]
-reservedRegs
-#if alpha_TARGET_ARCH
- = [NCG_Reserved_I1, NCG_Reserved_I2,
- NCG_Reserved_F1, NCG_Reserved_F2]
-#endif
-#if i386_TARGET_ARCH
- = [{-certainly cannot afford any!-}]
-#endif
-#if sparc_TARGET_ARCH
- = [NCG_Reserved_I1, NCG_Reserved_I2,
- NCG_Reserved_F1, NCG_Reserved_F2,
- NCG_Reserved_D1, NCG_Reserved_D2]
-#endif
--------------------------------
-freeRegs :: [Reg]
-freeRegs
- = freeMappedRegs IF_ARCH_alpha( [0..63],
- IF_ARCH_i386( [0..15],
- IF_ARCH_sparc( [0..63],)))
-
--------------------------------
-callClobberedRegs :: [Reg]
-callClobberedRegs
- = freeMappedRegs
-#if alpha_TARGET_ARCH
- [0, 1, 2, 3, 4, 5, 6, 7, 8,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- fReg 0, fReg 1, fReg 10, fReg 11, fReg 12, fReg 13, fReg 14, fReg 15,
- fReg 16, fReg 17, fReg 18, fReg 19, fReg 20, fReg 21, fReg 22, fReg 23,
- fReg 24, fReg 25, fReg 26, fReg 27, fReg 28, fReg 29, fReg 30]
-#endif {- alpha_TARGET_ARCH -}
-#if i386_TARGET_ARCH
- [{-none-}]
-#endif {- i386_TARGET_ARCH -}
-#if sparc_TARGET_ARCH
- ( oReg 7 :
- [oReg i | i <- [0..5]] ++
- [gReg i | i <- [1..7]] ++
- [fReg i | i <- [0..31]] )
-#endif {- sparc_TARGET_ARCH -}
-
--------------------------------
-argRegs :: Int -> [Reg]
-
-argRegs 0 = []
-#if alpha_TARGET_ARCH
-argRegs 1 = freeMappedRegs [16, fReg 16]
-argRegs 2 = freeMappedRegs [16, 17, fReg 16, fReg 17]
-argRegs 3 = freeMappedRegs [16, 17, 18, fReg 16, fReg 17, fReg 18]
-argRegs 4 = freeMappedRegs [16, 17, 18, 19, fReg 16, fReg 17, fReg 18, fReg 19]
-argRegs 5 = freeMappedRegs [16, 17, 18, 19, 20, fReg 16, fReg 17, fReg 18, fReg 19, fReg 20]
-argRegs 6 = freeMappedRegs [16, 17, 18, 19, 20, 21, fReg 16, fReg 17, fReg 18, fReg 19, fReg 20, fReg 21]
-#endif {- alpha_TARGET_ARCH -}
-#if i386_TARGET_ARCH
-argRegs _ = panic "MachRegs.argRegs: doesn't work on I386"
-#endif {- i386_TARGET_ARCH -}
-#if sparc_TARGET_ARCH
-argRegs 1 = freeMappedRegs (map oReg [0])
-argRegs 2 = freeMappedRegs (map oReg [0,1])
-argRegs 3 = freeMappedRegs (map oReg [0,1,2])
-argRegs 4 = freeMappedRegs (map oReg [0,1,2,3])
-argRegs 5 = freeMappedRegs (map oReg [0,1,2,3,4])
-argRegs 6 = freeMappedRegs (map oReg [0,1,2,3,4,5])
-#endif {- sparc_TARGET_ARCH -}
-argRegs _ = panic "MachRegs.argRegs: don't know about >6 arguments!"
-
--------------------------------
-
-#if alpha_TARGET_ARCH
-allArgRegs :: [(Reg, Reg)]
-
-allArgRegs = [(realReg i, realReg (fReg i)) | i <- [16..21]]
-#endif {- alpha_TARGET_ARCH -}
-
-#if sparc_TARGET_ARCH
-allArgRegs :: [Reg]
-
-allArgRegs = map realReg [oReg i | i <- [0..5]]
-#endif {- sparc_TARGET_ARCH -}
-
--------------------------------
-freeMappedRegs :: [Int] -> [Reg]
-
-freeMappedRegs nums
- = foldr free [] nums
- where
- free IBOX(i) acc
- = if _IS_TRUE_(freeReg i) then (MappedReg i) : acc else acc
-\end{code}
-
-\begin{code}
-freeReg :: FAST_INT -> FAST_BOOL
-
-#if alpha_TARGET_ARCH
-freeReg ILIT(26) = _FALSE_ -- return address (ra)
-freeReg ILIT(28) = _FALSE_ -- reserved for the assembler (at)
-freeReg ILIT(29) = _FALSE_ -- global pointer (gp)
-freeReg ILIT(30) = _FALSE_ -- stack pointer (sp)
-freeReg ILIT(31) = _FALSE_ -- always zero (zeroh)
-freeReg ILIT(63) = _FALSE_ -- always zero (f31)
-#endif
-
-#if i386_TARGET_ARCH
-freeReg ILIT(esp) = _FALSE_ -- %esp is the C stack pointer
-#endif
-
-#if sparc_TARGET_ARCH
-freeReg ILIT(g0) = _FALSE_ -- %g0 is always 0.
-freeReg ILIT(g5) = _FALSE_ -- %g5 is reserved (ABI).
-freeReg ILIT(g6) = _FALSE_ -- %g6 is reserved (ABI).
-freeReg ILIT(g7) = _FALSE_ -- %g7 is reserved (ABI).
-freeReg ILIT(i6) = _FALSE_ -- %i6 is our frame pointer.
-freeReg ILIT(o6) = _FALSE_ -- %o6 is our stack pointer.
-#endif
-
-#ifdef REG_Base
-freeReg ILIT(REG_Base) = _FALSE_
-#endif
-#ifdef REG_StkO
-freeReg ILIT(REG_StkO) = _FALSE_
-#endif
-#ifdef REG_R1
-freeReg ILIT(REG_R1) = _FALSE_
-#endif
-#ifdef REG_R2
-freeReg ILIT(REG_R2) = _FALSE_
-#endif
-#ifdef REG_R3
-freeReg ILIT(REG_R3) = _FALSE_
-#endif
-#ifdef REG_R4
-freeReg ILIT(REG_R4) = _FALSE_
-#endif
-#ifdef REG_R5
-freeReg ILIT(REG_R5) = _FALSE_
-#endif
-#ifdef REG_R6
-freeReg ILIT(REG_R6) = _FALSE_
-#endif
-#ifdef REG_R7
-freeReg ILIT(REG_R7) = _FALSE_
-#endif
-#ifdef REG_R8
-freeReg ILIT(REG_R8) = _FALSE_
-#endif
-#ifdef REG_Flt1
-freeReg ILIT(REG_Flt1) = _FALSE_
-#endif
-#ifdef REG_Flt2
-freeReg ILIT(REG_Flt2) = _FALSE_
-#endif
-#ifdef REG_Flt3
-freeReg ILIT(REG_Flt3) = _FALSE_
-#endif
-#ifdef REG_Flt4
-freeReg ILIT(REG_Flt4) = _FALSE_
-#endif
-#ifdef REG_Dbl1
-freeReg ILIT(REG_Dbl1) = _FALSE_
-#endif
-#ifdef REG_Dbl2
-freeReg ILIT(REG_Dbl2) = _FALSE_
-#endif
-#ifdef REG_Tag
-freeReg ILIT(REG_Tag) = _FALSE_
-#endif
-#ifdef REG_Ret
-freeReg ILIT(REG_Ret) = _FALSE_
-#endif
-#ifdef REG_SpA
-freeReg ILIT(REG_SpA) = _FALSE_
-#endif
-#ifdef REG_SuA
-freeReg ILIT(REG_SuA) = _FALSE_
-#endif
-#ifdef REG_SpB
-freeReg ILIT(REG_SpB) = _FALSE_
-#endif
-#ifdef REG_SuB
-freeReg ILIT(REG_SuB) = _FALSE_
-#endif
-#ifdef REG_Hp
-freeReg ILIT(REG_Hp) = _FALSE_
-#endif
-#ifdef REG_HpLim
-freeReg ILIT(REG_HpLim) = _FALSE_
-#endif
-#ifdef REG_Liveness
-freeReg ILIT(REG_Liveness) = _FALSE_
-#endif
-#ifdef REG_StdUpdRetVec
-freeReg ILIT(REG_StdUpdRetVec) = _FALSE_
-#endif
-#ifdef REG_StkStub
-freeReg ILIT(REG_StkStub) = _FALSE_
-#endif
-freeReg _ = _TRUE_
-freeReg n
- -- we hang onto two double regs for dedicated
- -- use; this is not necessary on Alphas and
- -- may not be on other non-SPARCs.
-#ifdef REG_Dbl1
- | n _EQ_ (ILIT(REG_Dbl1) _ADD_ ILIT(1)) = _FALSE_
-#endif
-#ifdef REG_Dbl2
- | n _EQ_ (ILIT(REG_Dbl2) _ADD_ ILIT(1)) = _FALSE_
-#endif
- | otherwise = _TRUE_
\end{code}