-%
-% (c) The AQUA Project, Glasgow University, 1996-1998
-%
-\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 "nativeGen/NCG.h"
module MachRegs (
- RegClass(..), regClass,
- VRegUnique(..), pprVRegUnique, getHiVRegFromLo,
- Reg(..), isRealReg, isVirtualReg, getVRegUnique,
- allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
-
- Imm(..),
- MachRegsAddr(..),
+ -- * Immediate values
+ Imm(..), strImmLit, litToImm,
+ -- * Addressing modes
+ AddrMode(..),
addrOffset,
- baseRegOffset,
+
+ -- * The 'Reg' type
+ RegNo,
+ Reg(..), isRealReg, isVirtualReg,
+ RegClass(..), regClass,
+ getHiVRegFromLo,
+ mkVReg,
+
+ -- * Global registers
+ get_GlobalReg_reg_or_addr,
callerSaves,
+
+ -- * Machine-dependent register-related stuff
+ allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
freeReg,
- getNewRegNCG,
- mkVReg,
- get_MagicId_reg_or_addr,
- get_MagicId_addr,
- get_Regtable_addr_from_offset,
spRel,
- 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
- , fake0, fake1, fake2, fake3, fake4, fake5
+ eax, ebx, ecx, edx, esi, edi, ebp, esp,
+ fake0, fake1, fake2, fake3, fake4, fake5,
+ addrModeRegs,
#endif
#if sparc_TARGET_ARCH
- , fits13Bits
- , fpRel, gReg, iReg, lReg, oReg, largeOffsetError
- , fp, sp, g0, g1, g2, o0, o1, f0, f6, f8, f26, f27
-
+ 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
- , fits16Bits
- , sp
- , r3, r4, r27, r28
- , f1, f20, f21
+ allFPArgRegs,
+ makeImmediate,
+ sp,
+ r3, r4, r27, r28,
+ f1, f20, f21,
#endif
) where
#include "HsVersions.h"
-import AbsCSyn ( MagicId(..) )
+#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 PrimRep ( PrimRep(..), isFloatingRep )
-import Stix ( StixExpr(..), StixReg(..),
- getUniqueNat, returnNat, thenNat, NatM )
import Unique ( Unique )
import Pretty
import Outputable ( Outputable(..), pprPanic, panic )
import qualified Outputable
+import Unique
+import Constants
import FastTypes
-\end{code}
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#if powerpc_TARGET_ARCH
+#if __GLASGOW_HASKELL__ >= 504
+import Data.Word ( Word8, Word16, Word32 )
+import Data.Int ( Int8, Int16, Int32 )
+#else
+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 Bool Doc -- Simple string label (underscore-able)
- -- Bool==True ==> in a different DLL
- | ImmLit Doc -- Simple string
+ | ImmLit Doc -- Simple string
| ImmIndex CLabel Int
| ImmFloat Rational
| ImmDouble Rational
- IF_ARCH_sparc(
- | LO Imm -- Possible restrictions...
+ | ImmConstantSum Imm Imm
+ | ImmConstantDiff Imm Imm
+#if sparc_TARGET_ARCH
+ | LO Imm {- Possible restrictions... -}
| HI Imm
- ,IF_ARCH_powerpc(
+#endif
+#if powerpc_TARGET_ARCH
| LO Imm
| HI Imm
- | HA Imm -- high halfword adjusted
- ,))
+ | HA Imm {- high halfword adjusted -}
+#endif
strImmLit s = ImmLit (text s)
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-\begin{code}
-data MachRegsAddr
+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
| AddrRegImm Reg Imm
#endif
-addrOffset :: MachRegsAddr -> Int -> Maybe MachRegsAddr
+#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))
+
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))))
- _ -> Nothing
+
+ 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
_ -> Nothing
-
#endif /* sparc */
#if powerpc_TARGET_ARCH
AddrRegImm r (ImmInt n)
| fits16Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
| otherwise -> Nothing
where n2 = n + toInteger off
-
- AddrRegReg r (RealReg 0)
- | fits16Bits off -> Just (AddrRegImm r (ImmInt off))
- | otherwise -> Nothing
_ -> Nothing
#endif /* powerpc */
#if powerpc_TARGET_ARCH
fits16Bits :: Integral a => a -> Bool
fits16Bits x = x >= -32768 && x < 32768
-#endif
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-@stgReg@: we map STG registers onto appropriate Stix Trees. Either
-they map to real machine registers or stored as offsets from BaseReg.
-Given a MagicId, get_MagicId_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.
+makeImmediate :: Integral a => MachRep -> Bool -> a -> Maybe Imm
+
+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}
-get_MagicId_reg_or_addr :: MagicId -> Either Reg StixExpr
-get_MagicId_addr :: MagicId -> StixExpr
-get_Regtable_addr_from_offset :: Int -> StixExpr
-
-get_MagicId_reg_or_addr mid
- = case magicIdRegMaybe mid of
- Just rr -> Left rr
- Nothing -> Right (get_MagicId_addr mid)
-
-get_MagicId_addr BaseReg
- = -- This arch doesn't have BaseReg in a register, so we have to
- -- use &MainRegTable.r instead.
- StIndex PtrRep (StCLbl mkMainCapabilityLabel)
- (StInt (toInteger OFFW_Capability_r))
-get_MagicId_addr mid
- = get_Regtable_addr_from_offset (baseRegOffset mid)
-
-get_Regtable_addr_from_offset offset_in_words
- = let ptr_to_RegTable
- = case magicIdRegMaybe BaseReg of
- Nothing
- -> -- This arch doesn't have BaseReg in a register, so we have to
- -- use &MainRegTable.r instead.
- StIndex PtrRep (StCLbl mkMainCapabilityLabel)
- (StInt (toInteger OFFW_Capability_r))
- Just _
- -> -- It's in a reg, so leave it as it is
- StReg (StixMagicId BaseReg)
- in
- StIndex PtrRep ptr_to_RegTable (StInt (toInteger offset_in_words))
-\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.
-
-\begin{code}
spRel :: Int -- desired stack offset in words, positive or negative
- -> MachRegsAddr
+ -> AddrMode
spRel n
#if i386_TARGET_ARCH
- = AddrBaseIndex (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 -> MachRegsAddr
+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))
+ = AddrRegImm fp (ImmInt (n * wORD_SIZE))
#endif
-\end{code}
-%************************************************************************
-%* *
-\subsection[Reg]{Real 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.
+-- -----------------------------------------------------------------------------
+-- Global registers
-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.
+-- 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.
-Virtual regs can be of either class, so that info is attached.
+get_GlobalReg_reg_or_addr :: GlobalReg -> Either Reg CmmExpr
+get_GlobalReg_addr :: GlobalReg -> CmmExpr
+get_Regtable_addr_from_offset :: MachRep -> Int -> CmmExpr
-\begin{code}
+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
-data VRegUnique
- = VRegUniqueLo Unique -- lower part of a split quantity
- | VRegUniqueHi Unique -- upper part thereof
- deriving (Eq, Ord)
+-- ---------------------------------------------------------------------------
+-- Registers
-instance Show VRegUnique where
- show (VRegUniqueLo u) = show u
- show (VRegUniqueHi u) = "_hi_" ++ show u
+-- 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.
-pprVRegUnique :: VRegUnique -> Outputable.SDoc
-pprVRegUnique
- = Outputable.text . show
+-- 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.
-getHiVRegFromLo (VirtualRegI (VRegUniqueLo u))
- = VirtualRegI (VRegUniqueHi u)
+-- (NB. Not reversible).
+getHiVRegFromLo (VirtualRegI u)
+ = VirtualRegHi (newTagUnique u 'H') -- makes a pseudo-unique with tag 'H'
getHiVRegFromLo other
= pprPanic "getHiVRegFromLo" (ppr other)
| RcDouble
deriving Eq
+type RegNo = Int
+
data Reg
- = RealReg Int
- | VirtualRegI VRegUnique
- | VirtualRegF VRegUnique
- | VirtualRegD VRegUnique
-
-unRealReg (RealReg i) = i
-unRealReg vreg = pprPanic "unRealReg on VirtualReg" (ppr vreg)
-
-getVRegUnique :: Reg -> VRegUnique
-getVRegUnique (VirtualRegI vu) = vu
-getVRegUnique (VirtualRegF vu) = vu
-getVRegUnique (VirtualRegD vu) = vu
-getVRegUnique rreg = pprPanic "getVRegUnique on RealReg" (ppr rreg)
-
-mkVReg :: Unique -> PrimRep -> Reg
-mkVReg u pk
+ = 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
- = case pk of
- FloatRep -> VirtualRegF (VRegUniqueLo u)
- DoubleRep -> VirtualRegD (VRegUniqueLo u)
- other -> VirtualRegI (VRegUniqueLo u)
+ F32 -> VirtualRegF u
#else
- = if isFloatingRep pk then VirtualRegD (VRegUniqueLo u)
- else VirtualRegI (VRegUniqueLo u)
+ F32 -> VirtualRegD u
#endif
+ F64 -> VirtualRegD u
+ other -> VirtualRegI u
-isVirtualReg (RealReg _) = False
-isVirtualReg (VirtualRegI _) = True
-isVirtualReg (VirtualRegF _) = True
-isVirtualReg (VirtualRegD _) = True
-isRealReg = not . isVirtualReg
-
-getNewRegNCG :: PrimRep -> NatM Reg
-getNewRegNCG pk
- = getUniqueNat `thenNat` \ u -> returnNat (mkVReg u pk)
-
-instance Eq Reg where
- (==) (RealReg i1) (RealReg i2) = i1 == i2
- (==) (VirtualRegI u1) (VirtualRegI u2) = u1 == u2
- (==) (VirtualRegF u1) (VirtualRegF u2) = u1 == u2
- (==) (VirtualRegD u1) (VirtualRegD u2) = u1 == u2
- (==) reg1 reg2 = False
-
-instance Ord Reg where
- compare (RealReg i1) (RealReg i2) = compare i1 i2
- compare (RealReg _) (VirtualRegI _) = LT
- compare (RealReg _) (VirtualRegF _) = LT
- compare (RealReg _) (VirtualRegD _) = LT
-
- compare (VirtualRegI _) (RealReg _) = GT
- compare (VirtualRegI u1) (VirtualRegI u2) = compare u1 u2
- compare (VirtualRegI _) (VirtualRegF _) = LT
- compare (VirtualRegI _) (VirtualRegD _) = LT
-
- compare (VirtualRegF _) (RealReg _) = GT
- compare (VirtualRegF _) (VirtualRegI _) = GT
- compare (VirtualRegF u1) (VirtualRegF u2) = compare u1 u2
- compare (VirtualRegF _) (VirtualRegD _) = LT
-
- compare (VirtualRegD _) (RealReg _) = GT
- compare (VirtualRegD _) (VirtualRegI _) = GT
- compare (VirtualRegD _) (VirtualRegF _) = GT
- compare (VirtualRegD u1) (VirtualRegD u2) = compare u1 u2
+isVirtualReg :: Reg -> Bool
+isVirtualReg (RealReg _) = False
+isVirtualReg (VirtualRegI _) = True
+isVirtualReg (VirtualRegHi _) = True
+isVirtualReg (VirtualRegF _) = True
+isVirtualReg (VirtualRegD _) = True
+isRealReg :: Reg -> Bool
+isRealReg = not . isVirtualReg
instance Show Reg where
- show (RealReg i) = showReg i
- show (VirtualRegI u) = "%vI_" ++ show u
- show (VirtualRegF u) = "%vF_" ++ show u
- show (VirtualRegD u) = "%vD_" ++ show u
+ 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
instance Outputable Reg where
ppr r = Outputable.text (show r)
-\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}
+-- -----------------------------------------------------------------------------
+-- Machine-specific register 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.
+
#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).
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.
+-}
-\begin{code}
#if i386_TARGET_ARCH
fake0, fake1, fake2, fake3, fake4, fake5,
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 (VirtualRegD u) = RcDouble
-regClass (VirtualRegF u) = pprPanic "regClass(x86):VirtualRegF"
+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 :: Int -> String
+showReg :: RegNo -> String
showReg n
= if n >= 0 && n < 14
then regNames !! n
else "%unknown_x86_real_reg_" ++ show n
#endif
-\end{code}
+{-
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,
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.
+-}
-\begin{code}
#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)
-nCG_FirstFloatReg :: Int
+nCG_FirstFloatReg :: RegNo
nCG_FirstFloatReg = unRealReg NCG_FirstFloatReg
regClass (VirtualRegI u) = RcInteger
| i < nCG_FirstFloatReg = RcDouble
| otherwise = RcFloat
-showReg :: Int -> String
+showReg :: RegNo -> String
showReg n
| n >= 0 && n < 8 = "%g" ++ show n
| n >= 8 && n < 16 = "%o" ++ show (n-8)
f1 = RealReg (fReg 1)
#endif
-\end{code}
+{-
The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
point registers.
-\begin{code}
+-}
+
#if powerpc_TARGET_ARCH
-fReg :: Int -> Int
+fReg :: Int -> RegNo
fReg x = (32 + x)
-regClass (VirtualRegI u) = RcInteger
-regClass (VirtualRegF u) = RcFloat
+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
- -- | i < nCG_FirstFloatReg = RcDouble
- -- | otherwise = RcFloat
-showReg :: Int -> String
+showReg :: RegNo -> String
showReg n
| n >= 0 && n <= 31 = "%r" ++ show n
| n >= 32 && n <= 63 = "%f" ++ show (n - 32)
f20 = RealReg $ fReg 20
f21 = RealReg $ fReg 21
#endif
-\end{code}
+{-
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 r29 29
#define r30 30
#define r31 31
+
+#ifdef darwin_TARGET_OS
#define f0 32
#define f1 33
#define f2 34
#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
-\end{code}
-
-\begin{code}
-baseRegOffset :: MagicId -> Int
-
-baseRegOffset (VanillaReg _ 1#) = OFFSET_R1
-baseRegOffset (VanillaReg _ 2#) = OFFSET_R2
-baseRegOffset (VanillaReg _ 3#) = OFFSET_R3
-baseRegOffset (VanillaReg _ 4#) = OFFSET_R4
-baseRegOffset (VanillaReg _ 5#) = OFFSET_R5
-baseRegOffset (VanillaReg _ 6#) = OFFSET_R6
-baseRegOffset (VanillaReg _ 7#) = OFFSET_R7
-baseRegOffset (VanillaReg _ 8#) = OFFSET_R8
-baseRegOffset (VanillaReg _ 9#) = OFFSET_R9
-baseRegOffset (VanillaReg _ 10#) = OFFSET_R10
-baseRegOffset (FloatReg 1#) = OFFSET_F1
-baseRegOffset (FloatReg 2#) = OFFSET_F2
-baseRegOffset (FloatReg 3#) = OFFSET_F3
-baseRegOffset (FloatReg 4#) = OFFSET_F4
-baseRegOffset (DoubleReg 1#) = OFFSET_D1
-baseRegOffset (DoubleReg 2#) = OFFSET_D2
-baseRegOffset Sp = OFFSET_Sp
-baseRegOffset SpLim = OFFSET_SpLim
-#ifdef OFFSET_L1
-baseRegOffset (LongReg _ 1#) = OFFSET_L1
-#endif
-baseRegOffset Hp = OFFSET_Hp
-baseRegOffset HpLim = OFFSET_HpLim
-baseRegOffset CurrentTSO = OFFSET_CurrentTSO
-baseRegOffset CurrentNursery = OFFSET_CurrentNursery
-baseRegOffset HpAlloc = OFFSET_HpAlloc
-#ifdef NCG_DEBUG
-baseRegOffset BaseReg = panic "baseRegOffset:BaseReg"
-baseRegOffset CurCostCentre = panic "baseRegOffset:CurCostCentre"
-baseRegOffset VoidReg = panic "baseRegOffset:VoidReg"
-#endif
-\end{code}
-
-\begin{code}
-callerSaves :: MagicId -> Bool
-
-#ifdef CALLER_SAVES_Base
-callerSaves BaseReg = True
-#endif
-#ifdef CALLER_SAVES_R1
-callerSaves (VanillaReg _ ILIT(1)) = True
-#endif
-#ifdef CALLER_SAVES_R2
-callerSaves (VanillaReg _ ILIT(2)) = True
-#endif
-#ifdef CALLER_SAVES_R3
-callerSaves (VanillaReg _ ILIT(3)) = True
-#endif
-#ifdef CALLER_SAVES_R4
-callerSaves (VanillaReg _ ILIT(4)) = True
-#endif
-#ifdef CALLER_SAVES_R5
-callerSaves (VanillaReg _ ILIT(5)) = True
-#endif
-#ifdef CALLER_SAVES_R6
-callerSaves (VanillaReg _ ILIT(6)) = True
-#endif
-#ifdef CALLER_SAVES_R7
-callerSaves (VanillaReg _ ILIT(7)) = True
-#endif
-#ifdef CALLER_SAVES_R8
-callerSaves (VanillaReg _ ILIT(8)) = True
-#endif
-#ifdef CALLER_SAVES_F1
-callerSaves (FloatReg 1#) = True
-#endif
-#ifdef CALLER_SAVES_F2
-callerSaves (FloatReg 2#) = True
-#endif
-#ifdef CALLER_SAVES_F3
-callerSaves (FloatReg 3#) = True
-#endif
-#ifdef CALLER_SAVES_F4
-callerSaves (FloatReg 4#) = True
-#endif
-#ifdef CALLER_SAVES_D1
-callerSaves (DoubleReg 1#) = True
-#endif
-#ifdef CALLER_SAVES_D2
-callerSaves (DoubleReg 2#) = True
-#endif
-#ifdef CALLER_SAVES_L1
-callerSaves (LongReg _ ILIT(1)) = True
-#endif
-#ifdef CALLER_SAVES_Sp
-callerSaves Sp = True
-#endif
-#ifdef CALLER_SAVES_SpLim
-callerSaves SpLim = True
-#endif
-#ifdef CALLER_SAVES_Hp
-callerSaves Hp = True
-#endif
-#ifdef CALLER_SAVES_HpLim
-callerSaves HpLim = True
-#endif
-#ifdef CALLER_SAVES_CurrentTSO
-callerSaves CurrentTSO = True
-#endif
-#ifdef CALLER_SAVES_CurrentNursery
-callerSaves CurrentNursery = True
#endif
-callerSaves _ = False
-\end{code}
-
-\begin{code}
-magicIdRegMaybe :: MagicId -> Maybe Reg
-#ifdef REG_Base
-magicIdRegMaybe BaseReg = Just (RealReg REG_Base)
-#endif
-#ifdef REG_R1
-magicIdRegMaybe (VanillaReg _ 1#) = Just (RealReg REG_R1)
-#endif
-#ifdef REG_R2
-magicIdRegMaybe (VanillaReg _ 2#) = Just (RealReg REG_R2)
-#endif
-#ifdef REG_R3
-magicIdRegMaybe (VanillaReg _ 3#) = Just (RealReg REG_R3)
-#endif
-#ifdef REG_R4
-magicIdRegMaybe (VanillaReg _ 4#) = Just (RealReg REG_R4)
-#endif
-#ifdef REG_R5
-magicIdRegMaybe (VanillaReg _ 5#) = Just (RealReg REG_R5)
-#endif
-#ifdef REG_R6
-magicIdRegMaybe (VanillaReg _ 6#) = Just (RealReg REG_R6)
-#endif
-#ifdef REG_R7
-magicIdRegMaybe (VanillaReg _ 7#) = Just (RealReg REG_R7)
-#endif
-#ifdef REG_R8
-magicIdRegMaybe (VanillaReg _ 8#) = Just (RealReg REG_R8)
-#endif
-#ifdef REG_R9
-magicIdRegMaybe (VanillaReg _ 9#) = Just (RealReg REG_R9)
-#endif
-#ifdef REG_R10
-magicIdRegMaybe (VanillaReg _ 10#) = Just (RealReg REG_R10)
-#endif
-#ifdef REG_F1
-magicIdRegMaybe (FloatReg 1#) = Just (RealReg REG_F1)
-#endif
-#ifdef REG_F2
-magicIdRegMaybe (FloatReg 2#) = Just (RealReg REG_F2)
-#endif
-#ifdef REG_F3
-magicIdRegMaybe (FloatReg 3#) = Just (RealReg REG_F3)
-#endif
-#ifdef REG_F4
-magicIdRegMaybe (FloatReg 4#) = Just (RealReg REG_F4)
-#endif
-#ifdef REG_D1
-magicIdRegMaybe (DoubleReg 1#) = Just (RealReg REG_D1)
-#endif
-#ifdef REG_D2
-magicIdRegMaybe (DoubleReg 2#) = Just (RealReg REG_D2)
-#endif
-#ifdef REG_Sp
-magicIdRegMaybe Sp = Just (RealReg REG_Sp)
-#endif
-#ifdef REG_Lng1
-magicIdRegMaybe (LongReg _ ILIT(1)) = Just (RealReg REG_Lng1)
-#endif
-#ifdef REG_Lng2
-magicIdRegMaybe (LongReg _ ILIT(2)) = Just (RealReg REG_Lng2)
-#endif
-#ifdef REG_SpLim
-magicIdRegMaybe SpLim = Just (RealReg REG_SpLim)
-#endif
-#ifdef REG_Hp
-magicIdRegMaybe Hp = Just (RealReg REG_Hp)
-#endif
-#ifdef REG_HpLim
-magicIdRegMaybe HpLim = Just (RealReg REG_HpLim)
-#endif
-#ifdef REG_CurrentTSO
-magicIdRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO)
-#endif
-#ifdef REG_CurrentNursery
-magicIdRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery)
-#endif
-magicIdRegMaybe _ = Nothing
-\end{code}
-\begin{code}
--------------------------------
-- allMachRegs is the complete set of machine regs.
-allMachRegNos :: [Int]
+allMachRegNos :: [RegNo]
allMachRegNos
= IF_ARCH_alpha( [0..63],
IF_ARCH_i386( [0..13],
++ [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 :: [Reg]
+allocatableRegs :: [RegNo]
allocatableRegs
= let isFree i = isFastTrue (freeReg i)
- in map RealReg (filter isFree allMachRegNos)
+ in filter isFree allMachRegNos
--------------------------------
-- these are the regs which we cannot assume stay alive over a
-- C call.
callClobberedRegs :: [Reg]
[fReg i | i <- [0..31]] )
#endif /* sparc_TARGET_ARCH */
#if powerpc_TARGET_ARCH
- map RealReg ([0..12] ++ map fReg [0..13])
+#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 :: Int -> [Reg]
+argRegs :: RegNo -> [Reg]
#if i386_TARGET_ARCH
argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
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 :: [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}
-freeReg :: Int -> FastBool
+freeReg :: RegNo -> FastBool
#if alpha_TARGET_ARCH
freeReg 26 = fastBool False -- return address (ra)
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 _ = panic "baseRegOffset:other"
+#endif
+
+
+-- | 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_R1
+callerSaves (VanillaReg _ ILIT(1)) = True
+#endif
+#ifdef CALLER_SAVES_R2
+callerSaves (VanillaReg _ ILIT(2)) = True
+#endif
+#ifdef CALLER_SAVES_R3
+callerSaves (VanillaReg _ ILIT(3)) = True
+#endif
+#ifdef CALLER_SAVES_R4
+callerSaves (VanillaReg _ ILIT(4)) = True
+#endif
+#ifdef CALLER_SAVES_R5
+callerSaves (VanillaReg _ ILIT(5)) = True
+#endif
+#ifdef CALLER_SAVES_R6
+callerSaves (VanillaReg _ ILIT(6)) = True
+#endif
+#ifdef CALLER_SAVES_R7
+callerSaves (VanillaReg _ ILIT(7)) = True
+#endif
+#ifdef CALLER_SAVES_R8
+callerSaves (VanillaReg _ ILIT(8)) = True
+#endif
+#ifdef CALLER_SAVES_F1
+callerSaves (FloatReg 1#) = True
+#endif
+#ifdef CALLER_SAVES_F2
+callerSaves (FloatReg 2#) = True
+#endif
+#ifdef CALLER_SAVES_F3
+callerSaves (FloatReg 3#) = True
+#endif
+#ifdef CALLER_SAVES_F4
+callerSaves (FloatReg 4#) = True
+#endif
+#ifdef CALLER_SAVES_D1
+callerSaves (DoubleReg 1#) = True
+#endif
+#ifdef CALLER_SAVES_D2
+callerSaves (DoubleReg 2#) = True
+#endif
+#ifdef CALLER_SAVES_L1
+callerSaves (LongReg _ ILIT(1)) = True
+#endif
+#ifdef CALLER_SAVES_Sp
+callerSaves Sp = True
+#endif
+#ifdef CALLER_SAVES_SpLim
+callerSaves SpLim = True
+#endif
+#ifdef CALLER_SAVES_Hp
+callerSaves Hp = True
+#endif
+#ifdef CALLER_SAVES_HpLim
+callerSaves HpLim = True
+#endif
+#ifdef CALLER_SAVES_CurrentTSO
+callerSaves CurrentTSO = True
+#endif
+#ifdef CALLER_SAVES_CurrentNursery
+callerSaves CurrentNursery = True
+#endif
+callerSaves _ = False
+
+
+-- | 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
+globalRegMaybe BaseReg = Just (RealReg REG_Base)
+#endif
+#ifdef REG_R1
+globalRegMaybe (VanillaReg 1) = Just (RealReg REG_R1)
+#endif
+#ifdef REG_R2
+globalRegMaybe (VanillaReg 2) = Just (RealReg REG_R2)
+#endif
+#ifdef REG_R3
+globalRegMaybe (VanillaReg 3) = Just (RealReg REG_R3)
+#endif
+#ifdef REG_R4
+globalRegMaybe (VanillaReg 4) = Just (RealReg REG_R4)
+#endif
+#ifdef REG_R5
+globalRegMaybe (VanillaReg 5) = Just (RealReg REG_R5)
+#endif
+#ifdef REG_R6
+globalRegMaybe (VanillaReg 6) = Just (RealReg REG_R6)
+#endif
+#ifdef REG_R7
+globalRegMaybe (VanillaReg 7) = Just (RealReg REG_R7)
+#endif
+#ifdef REG_R8
+globalRegMaybe (VanillaReg 8) = Just (RealReg REG_R8)
+#endif
+#ifdef REG_R9
+globalRegMaybe (VanillaReg 9) = Just (RealReg REG_R9)
+#endif
+#ifdef REG_R10
+globalRegMaybe (VanillaReg 10) = Just (RealReg REG_R10)
+#endif
+#ifdef REG_F1
+globalRegMaybe (FloatReg 1) = Just (RealReg REG_F1)
+#endif
+#ifdef REG_F2
+globalRegMaybe (FloatReg 2) = Just (RealReg REG_F2)
+#endif
+#ifdef REG_F3
+globalRegMaybe (FloatReg 3) = Just (RealReg REG_F3)
+#endif
+#ifdef REG_F4
+globalRegMaybe (FloatReg 4) = Just (RealReg REG_F4)
+#endif
+#ifdef REG_D1
+globalRegMaybe (DoubleReg 1) = Just (RealReg REG_D1)
+#endif
+#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
+globalRegMaybe Hp = Just (RealReg REG_Hp)
+#endif
+#ifdef REG_HpLim
+globalRegMaybe HpLim = Just (RealReg REG_HpLim)
+#endif
+#ifdef REG_CurrentTSO
+globalRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO)
+#endif
+#ifdef REG_CurrentNursery
+globalRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery)
+#endif
+globalRegMaybe _ = Nothing
+
+
\end{code}