[project @ 2003-12-10 11:35:24 by wolfgang]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachRegs.lhs
index 00e16b7..b7c1680 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The AQUA Project, Glasgow University, 1996
+% (c) The AQUA Project, Glasgow University, 1996-1998
 %
 \section[MachRegs]{Machine-specific info about registers}
 
@@ -10,34 +10,28 @@ often/usually quite entangled with registers.
 modules --- the pleasure has been foregone.)
 
 \begin{code}
-#include "HsVersions.h"
 #include "nativeGen/NCG.h"
 
 module MachRegs (
 
-       Reg(..),
+        RegClass(..), regClass,
+       VRegUnique(..), pprVRegUnique, getHiVRegFromLo, 
+       Reg(..), isRealReg, isVirtualReg, getVRegUnique,
+        allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
+
        Imm(..),
-       Address(..),
-       RegLoc(..),
-       SYN_IE(RegNo),
+       MachRegsAddr(..),
 
        addrOffset,
-       argRegs,
        baseRegOffset,
-       callClobberedRegs,
        callerSaves,
-       dblImmLit,
-       extractMappedRegNos,
-       freeMappedRegs,
-       freeReg, freeRegs,
+       freeReg,
        getNewRegNCG,
-       magicIdRegMaybe,
-       mkReg,
-       realReg,
-       reservedRegs,
-       saveLoc,
+       mkVReg,
+        get_MagicId_reg_or_addr,
+        get_MagicId_addr,
+        get_Regtable_addr_from_offset,
        spRel,
-       stgReg,
        strImmLit
 
 #if alpha_TARGET_ARCH
@@ -48,39 +42,35 @@ module MachRegs (
 #endif
 #if i386_TARGET_ARCH
        , eax, ebx, ecx, edx, esi, esp
-       , st0, st1, st2, st3, st4, st5, st6, st7
+       , fake0, fake1, fake2, fake3, fake4, fake5
 #endif
 #if sparc_TARGET_ARCH
-       , allArgRegs
        , fits13Bits
-       , fPair, fpRel, gReg, iReg, lReg, oReg, largeOffsetError
-       , fp, g0, o0, f0
+       , 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
+#endif
     ) where
 
-#if __GLASGOW_HASKELL__ >= 202
-import GlaExts
-import FastString
-#else
-IMP_Ubiq(){-uitous-}
-#endif
+#include "HsVersions.h"
 
 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(..) )
+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 FastTypes
 \end{code}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -90,25 +80,27 @@ data Imm
   = ImmInt     Int
   | ImmInteger Integer     -- Sigh.
   | ImmCLbl    CLabel      -- AbstractC Label (with baggage)
-  | ImmLab     Doc    -- Simple string label (underscore-able)
+  | ImmLab     Bool Doc    -- Simple string label (underscore-able)
+                             -- Bool==True ==> in a different DLL
   | ImmLit     Doc    -- Simple string
+  | ImmIndex    CLabel Int
+  | ImmFloat   Rational
+  | ImmDouble  Rational
   IF_ARCH_sparc(
-  | LO Imm                 -- Possible restrictions...
+  | LO Imm                 {- Possible restrictions... -}
+  | HI Imm
+  ,IF_ARCH_powerpc(
+  | LO Imm
   | HI Imm
-  ,)
+  | HA Imm     {- high halfword adjusted -}
+  ,))
 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 Address
+data MachRegsAddr
 #if alpha_TARGET_ARCH
   = AddrImm    Imm
   | AddrReg    Reg
@@ -116,8 +108,8 @@ data Address
 #endif
 
 #if i386_TARGET_ARCH
-  = Address    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
@@ -129,7 +121,12 @@ type Displacement = Imm
   | AddrRegImm Reg Imm
 #endif
 
-addrOffset :: Address -> Int -> Maybe Address
+#if powerpc_TARGET_ARCH
+  = AddrRegReg Reg Reg
+  | AddrRegImm Reg Imm
+#endif
+
+addrOffset :: MachRegsAddr -> Int -> Maybe MachRegsAddr
 
 addrOffset addr off
   = case addr of
@@ -137,10 +134,10 @@ addrOffset addr off
       _ -> panic "MachMisc.addrOffset not defined for Alpha"
 #endif
 #if i386_TARGET_ARCH
-      ImmAddr i off0        -> Just (ImmAddr i (off0 + off))
-      Address r i (ImmInt n) -> Just (Address r i (ImmInt (n + off)))
-      Address r i (ImmInteger n)
-       -> Just (Address r i (ImmInt (fromInteger (n + toInteger off))))
+      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
 #endif
 #if sparc_TARGET_ARCH
@@ -154,13 +151,30 @@ addrOffset addr off
        | 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-}
+#endif /* sparc */
+#if powerpc_TARGET_ARCH
+      AddrRegImm r (ImmInt n)
+       | fits16Bits n2 -> Just (AddrRegImm r (ImmInt n2))
+       | otherwise     -> Nothing
+       where n2 = n + off
+
+      AddrRegImm r (ImmInteger 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 alpha_TARGET_ARCH
@@ -171,81 +185,65 @@ fits8Bits i = i >= -256 && i < 256
 #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")
 
-@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.
+#endif /* sparc */
 
-\begin{code}
-data RegLoc = Save StixTree | Always StixTree
+#if powerpc_TARGET_ARCH
+fits16Bits :: Integral a => a -> Bool
+fits16Bits x = x >= -32768 && x < 32768
+#endif
 \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}
+@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.
 
 \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
-#ifndef i386_TARGET_ARCH
-       -- Yup, Hp&HpLim are not mapped into registers for x86's at the mo, so
-       -- fetching Hp off BaseReg is the sensible option, since that's
-       -- where gcc generated code stuffs/expects it (RTBL_Hp & RTBL_HpLim).
-       --  SOF 97/09
-       -- In fact, why use StorageMgrInfo at all?
-      Hp               -> StInd PtrRep (sStLitLbl SLIT("StorageMgrInfo"))
-      HpLim            -> StInd PtrRep (sStLitLbl
-                               (_PK_ ("StorageMgrInfo+" ++ BYTES_PER_WORD_STR)))
-#endif
-      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))])
+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}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -256,17 +254,17 @@ applicable, is the same but for the frame pointer.
 
 \begin{code}
 spRel :: Int   -- desired stack offset in words, positive or negative
-      -> Address
+      -> MachRegsAddr
 
 spRel n
 #if i386_TARGET_ARCH
-  = Address (Just esp) Nothing (ImmInt (n * BYTES_PER_WORD))
+  = AddrBaseIndex (Just esp) Nothing (ImmInt (n * BYTES_PER_WORD))
 #else
   = AddrRegImm sp (ImmInt (n * BYTES_PER_WORD))
 #endif
 
 #if sparc_TARGET_ARCH
-fpRel :: Int -> Address
+fpRel :: Int -> MachRegsAddr
     -- Duznae work for offsets greater than 13 bits; we just hope for
     -- the best
 fpRel n
@@ -280,103 +278,124 @@ fpRel n
 %*                                                                     *
 %************************************************************************
 
-Static Registers correspond to actual machine registers.  These should
-be avoided until the last possible moment.
+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.
 
-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.
+Virtual regs can be of either class, so that info is attached.
 
 \begin{code}
-data Reg
-  = FixedReg  FAST_INT         -- A pre-allocated machine register
 
-  | MappedReg FAST_INT         -- A dynamically allocated machine register
+data VRegUnique
+   = VRegUniqueLo Unique               -- lower part of a split quantity
+   | VRegUniqueHi Unique               -- upper part thereof
+     deriving (Eq, Ord)
 
-  | MemoryReg Int PrimRep      -- A machine "register" actually held in
-                               -- a memory allocated table of
-                               -- registers which didn't fit in real
-                               -- registers.
+instance Show VRegUnique where
+   show (VRegUniqueLo u) = show u
+   show (VRegUniqueHi u) = "_hi_" ++ show u
 
-  | UnmappedReg Unique PrimRep -- One of an infinite supply of registers,
-                               -- always mapped to one of the earlier
-                               -- two (?)  before we're done.
-mkReg :: Unique -> PrimRep -> Reg
-mkReg = UnmappedReg
+pprVRegUnique :: VRegUnique -> Outputable.SDoc
+pprVRegUnique 
+   = Outputable.text . show
 
-getNewRegNCG :: PrimRep -> UniqSM Reg
-getNewRegNCG pk
-  = getUnique  `thenUs` \ u ->
-    returnUs (UnmappedReg u pk)
+-- 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)
+getHiVRegFromLo other 
+   = pprPanic "getHiVRegFromLo" (ppr other)
 
-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
+data RegClass 
+   = RcInteger 
+   | RcFloat
+   | RcDouble
+     deriving Eq
 
-#ifdef DEBUG
-instance Outputable Reg where
-    ppr sty r = text (show r)
+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
+#if sparc_TARGET_ARCH
+   = case pk of
+        FloatRep  -> VirtualRegF (VRegUniqueLo u)
+        DoubleRep -> VirtualRegD (VRegUniqueLo u)
+        other     -> VirtualRegI (VRegUniqueLo u)
+#else
+   = if isFloatingRep pk then VirtualRegD (VRegUniqueLo u) 
+                         else VirtualRegI (VRegUniqueLo u)
 #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_
+isVirtualReg (RealReg _)     = False
+isVirtualReg (VirtualRegI _) = True
+isVirtualReg (VirtualRegF _) = True
+isVirtualReg (VirtualRegD _) = True
+isRealReg = not . isVirtualReg
 
-instance Ord3 Reg where
-    cmp = cmpReg
+getNewRegNCG :: PrimRep -> NatM Reg
+getNewRegNCG pk
+   = getUniqueNat `thenNat` \ u -> returnNat (mkVReg u pk)
 
 instance Eq Reg where
-    a == b = case (a `cmp` b) of { EQ_ -> True;  _ -> False }
-    a /= b = case (a `cmp` b) of { EQ_ -> False; _ -> True  }
+   (==) (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
-    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 }
-
-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}
+   compare (RealReg i1)     (RealReg i2)     = compare i1 i2
+   compare (RealReg _)      (VirtualRegI _)  = LT
+   compare (RealReg _)      (VirtualRegF _)  = LT
+   compare (RealReg _)      (VirtualRegD _)  = LT
 
-\begin{code}
-type RegNo = Int
+   compare (VirtualRegI _)  (RealReg _)      = GT
+   compare (VirtualRegI u1) (VirtualRegI u2) = compare u1 u2
+   compare (VirtualRegI _)  (VirtualRegF _)  = LT
+   compare (VirtualRegI _)  (VirtualRegD _)  = LT
 
-realReg :: RegNo -> Reg
-realReg n@IBOX(i)
-  = if _IS_TRUE_(freeReg i) then MappedReg i else FixedReg i
+   compare (VirtualRegF _)  (RealReg _)      = GT
+   compare (VirtualRegF _)  (VirtualRegI _)  = GT
+   compare (VirtualRegF u1) (VirtualRegF u2) = compare u1 u2
+   compare (VirtualRegF _)  (VirtualRegD _)  = LT
 
-extractMappedRegNos :: [Reg] -> [RegNo]
+   compare (VirtualRegD _)  (RealReg _)      = GT
+   compare (VirtualRegD _)  (VirtualRegI _)  = GT
+   compare (VirtualRegD _)  (VirtualRegF _)  = GT
+   compare (VirtualRegD u1) (VirtualRegD u2) = compare u1 u2
 
-extractMappedRegNos regs
-  = foldr ex [] regs
-  where
-    ex (MappedReg i) acc = IBOX(i) : acc  -- we'll take it
-    ex _            acc = acc            -- leave it out
+
+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
+
+instance Outputable Reg where
+    ppr r = Outputable.text (show r)
 \end{code}
 
 ** Machine-specific Reg stuff: **
@@ -411,31 +430,49 @@ Intel x86 architecture:
 - 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.
+- 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.
+
+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
 
-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)
+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
+
+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" 
+                                    (ppr (VirtualRegF u))
+
+regNames 
+   = ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp", 
+      "%fake0", "%fake1", "%fake2", "%fake3", "%fake4", "%fake5", "%fake6"]
+
+showReg :: Int -> String
+showReg n
+   = if   n >= 0 && n < 14
+     then regNames !! n
+     else "%unknown_x86_real_reg_" ++ show n
 
 #endif
 \end{code}
@@ -445,6 +482,10 @@ 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.
 
+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
 
@@ -455,20 +496,82 @@ 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 :: Int
+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
 
-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)
+showReg :: Int -> 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 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.
+\begin{code}
+#if powerpc_TARGET_ARCH
+fReg :: Int -> Int
+fReg x = (32 + x)
+
+regClass (VirtualRegI u) = RcInteger
+regClass (VirtualRegF u) = RcFloat
+regClass (VirtualRegD u) = RcDouble
+regClass (RealReg i) | i < 32                = RcInteger 
+                    | otherwise             = RcDouble
+                  --   | i < nCG_FirstFloatReg = RcDouble
+                  --   | otherwise             = RcFloat
+
+showReg :: Int -> 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
+\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}
@@ -515,14 +618,12 @@ names in the header files.  Gag me with a spoon, eh?
 #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
@@ -557,16 +658,17 @@ names in the header files.  Gag me with a spoon, eh?
 #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
@@ -590,39 +692,142 @@ names in the header files.  Gag me with a spoon, eh?
 #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
 \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 (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 LivenessReg           = OFFSET_Liveness
-#ifdef DEBUG
+baseRegOffset CurrentTSO            = OFFSET_CurrentTSO
+baseRegOffset CurrentNursery        = OFFSET_CurrentNursery
+baseRegOffset HpAlloc               = OFFSET_HpAlloc
+#ifdef NCG_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"
 #endif
@@ -634,9 +839,6 @@ callerSaves :: MagicId -> 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
@@ -661,41 +863,32 @@ callerSaves (VanillaReg _ ILIT(7))        = True
 #ifdef CALLER_SAVES_R8
 callerSaves (VanillaReg _ ILIT(8))     = True
 #endif
-#ifdef CALLER_SAVES_FltReg1
-callerSaves (FloatReg ILIT(1))         = True
+#ifdef CALLER_SAVES_F1
+callerSaves (FloatReg 1#)              = True
 #endif
-#ifdef CALLER_SAVES_FltReg2
-callerSaves (FloatReg ILIT(2))         = True
+#ifdef CALLER_SAVES_F2
+callerSaves (FloatReg 2#)              = True
 #endif
-#ifdef CALLER_SAVES_FltReg3
-callerSaves (FloatReg ILIT(3))         = True
+#ifdef CALLER_SAVES_F3
+callerSaves (FloatReg 3#)              = True
 #endif
-#ifdef CALLER_SAVES_FltReg4
-callerSaves (FloatReg ILIT(4))         = True
+#ifdef CALLER_SAVES_F4
+callerSaves (FloatReg 4#)              = True
 #endif
-#ifdef CALLER_SAVES_DblReg1
-callerSaves (DoubleReg ILIT(1))                = True
+#ifdef CALLER_SAVES_D1
+callerSaves (DoubleReg 1#)             = True
 #endif
-#ifdef CALLER_SAVES_DblReg2
-callerSaves (DoubleReg ILIT(2))                = True
+#ifdef CALLER_SAVES_D2
+callerSaves (DoubleReg 2#)             = True
 #endif
-#ifdef CALLER_SAVES_Tag
-callerSaves TagReg                     = True
+#ifdef CALLER_SAVES_L1
+callerSaves (LongReg _ ILIT(1))                = True
 #endif
-#ifdef CALLER_SAVES_Ret
-callerSaves RetReg                     = True
+#ifdef CALLER_SAVES_Sp
+callerSaves Sp                         = True
 #endif
-#ifdef CALLER_SAVES_SpA
-callerSaves SpA                                = True
-#endif
-#ifdef CALLER_SAVES_SuA
-callerSaves SuA                                = 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
@@ -703,14 +896,11 @@ callerSaves Hp                            = True
 #ifdef CALLER_SAVES_HpLim
 callerSaves HpLim                      = True
 #endif
-#ifdef CALLER_SAVES_Liveness
-callerSaves LivenessReg                        = True
+#ifdef CALLER_SAVES_CurrentTSO
+callerSaves CurrentTSO                 = True
 #endif
-#ifdef CALLER_SAVES_StdUpdRetVec
-callerSaves StdUpdRetVecReg            = True
-#endif
-#ifdef CALLER_SAVES_StkStub
-callerSaves StkStubReg                 = True
+#ifdef CALLER_SAVES_CurrentNursery
+callerSaves CurrentNursery             = True
 #endif
 callerSaves _                          = False
 \end{code}
@@ -719,316 +909,299 @@ callerSaves _                           = False
 magicIdRegMaybe :: MagicId -> Maybe Reg
 
 #ifdef REG_Base
-magicIdRegMaybe BaseReg                        = Just (FixedReg ILIT(REG_Base))
-#endif
-#ifdef REG_StkO
-magicIdRegMaybe StkOReg                        = Just (FixedReg ILIT(REG_StkOReg))
+magicIdRegMaybe BaseReg                        = Just (RealReg REG_Base)
 #endif
 #ifdef REG_R1
-magicIdRegMaybe (VanillaReg _ ILIT(1))         = Just (FixedReg ILIT(REG_R1))
+magicIdRegMaybe (VanillaReg _ 1#)      = Just (RealReg REG_R1)
 #endif 
 #ifdef REG_R2 
-magicIdRegMaybe (VanillaReg _ ILIT(2))         = Just (FixedReg ILIT(REG_R2))
+magicIdRegMaybe (VanillaReg _ 2#)      = Just (RealReg REG_R2)
 #endif 
 #ifdef REG_R3 
-magicIdRegMaybe (VanillaReg _ ILIT(3))         = Just (FixedReg ILIT(REG_R3))
+magicIdRegMaybe (VanillaReg _ 3#)      = Just (RealReg REG_R3)
 #endif 
 #ifdef REG_R4 
-magicIdRegMaybe (VanillaReg _ ILIT(4))         = Just (FixedReg ILIT(REG_R4))
+magicIdRegMaybe (VanillaReg _ 4#)      = Just (RealReg REG_R4)
 #endif 
 #ifdef REG_R5 
-magicIdRegMaybe (VanillaReg _ ILIT(5))         = Just (FixedReg ILIT(REG_R5))
+magicIdRegMaybe (VanillaReg _ 5#)      = Just (RealReg REG_R5)
 #endif 
 #ifdef REG_R6 
-magicIdRegMaybe (VanillaReg _ ILIT(6))         = Just (FixedReg ILIT(REG_R6))
+magicIdRegMaybe (VanillaReg _ 6#)      = Just (RealReg REG_R6)
 #endif 
 #ifdef REG_R7 
-magicIdRegMaybe (VanillaReg _ ILIT(7))         = Just (FixedReg ILIT(REG_R7))
+magicIdRegMaybe (VanillaReg _ 7#)      = Just (RealReg REG_R7)
 #endif 
 #ifdef REG_R8 
-magicIdRegMaybe (VanillaReg _ ILIT(8))         = Just (FixedReg ILIT(REG_R8))
+magicIdRegMaybe (VanillaReg _ 8#)      = Just (RealReg REG_R8)
 #endif
-#ifdef REG_Flt1
-magicIdRegMaybe (FloatReg ILIT(1))     = Just (FixedReg ILIT(REG_Flt1))
+#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_Flt2                                
-magicIdRegMaybe (FloatReg ILIT(2))     = Just (FixedReg ILIT(REG_Flt2))
+#ifdef REG_F2                          
+magicIdRegMaybe (FloatReg 2#)  = Just (RealReg REG_F2)
 #endif                                 
-#ifdef REG_Flt3                                
-magicIdRegMaybe (FloatReg ILIT(3))     = Just (FixedReg ILIT(REG_Flt3))
+#ifdef REG_F3                          
+magicIdRegMaybe (FloatReg 3#)  = Just (RealReg REG_F3)
 #endif                                 
-#ifdef REG_Flt4                                
-magicIdRegMaybe (FloatReg ILIT(4))     = Just (FixedReg ILIT(REG_Flt4))
+#ifdef REG_F4                          
+magicIdRegMaybe (FloatReg 4#)  = Just (RealReg REG_F4)
 #endif                                 
-#ifdef REG_Dbl1                                
-magicIdRegMaybe (DoubleReg ILIT(1))    = Just (FixedReg ILIT(REG_Dbl1))
+#ifdef REG_D1                          
+magicIdRegMaybe (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                          
+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 (FixedReg ILIT(REG_Hp))
+magicIdRegMaybe 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))
+magicIdRegMaybe HpLim                  = Just (RealReg REG_HpLim)
 #endif                                 
-#ifdef REG_StdUpdRetVec                        
-magicIdRegMaybe StdUpdRetVecReg        = Just (FixedReg ILIT(REG_StdUpdRetVec))
+#ifdef REG_CurrentTSO                          
+magicIdRegMaybe CurrentTSO             = Just (RealReg REG_CurrentTSO)
 #endif                                 
-#ifdef REG_StkStub                     
-magicIdRegMaybe StkStubReg             = Just (FixedReg ILIT(REG_StkStub))
+#ifdef REG_CurrentNursery                              
+magicIdRegMaybe CurrentNursery         = Just (RealReg REG_CurrentNursery)
 #endif                                 
 magicIdRegMaybe _                      = Nothing
 \end{code}
 
-%************************************************************************
-%*                                                                     *
-\subsection{Free, reserved, call-clobbered, and argument registers}
-%*                                                                     *
-%************************************************************************
-
-@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],)))
+-- allMachRegs is the complete set of machine regs.
+allMachRegNos :: [Int]
+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 :: [Reg]
+allocatableRegs
+   = let isFree i = isFastTrue (freeReg i)
+     in  map RealReg (filter isFree allMachRegNos)
 
 -------------------------------
+-- these are the regs which we cannot assume stay alive over a
+-- C call.  
 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 -}
+#endif /* alpha_TARGET_ARCH */
 #if i386_TARGET_ARCH
-    [{-none-}]
-#endif {- 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
-    ( oReg 7 :
-      [oReg i | i <- [0..5]] ++
-      [gReg i | i <- [1..7]] ++
-      [fReg i | i <- [0..31]] )
-#endif {- 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
+    map RealReg ([0..12] ++ map fReg [0..13])
+#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 0 = []
+#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]
-#endif {- alpha_TARGET_ARCH -}
-#if i386_TARGET_ARCH
-argRegs _ = panic "MachRegs.argRegs: doesn't work on I386"
-#endif {- i386_TARGET_ARCH -}
+argRegs _ = panic "MachRegs.argRegs(alpha): don't know about >6 arguments!"
+#endif /* alpha_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!"
+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 -}
+#endif /* alpha_TARGET_ARCH */
 
 #if sparc_TARGET_ARCH
 allArgRegs :: [Reg]
+allArgRegs = map RealReg [oReg i | i <- [0..5]]
+#endif /* sparc_TARGET_ARCH */
 
-allArgRegs = map realReg [oReg i | i <- [0..5]]
-#endif {- sparc_TARGET_ARCH -}
-
--------------------------------
-freeMappedRegs :: [Int] -> [Reg]
+#if i386_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = panic "MachRegs.allArgRegs(x86): should not be used!"
+#endif
 
-freeMappedRegs nums
-  = foldr free [] nums
-  where
-    free IBOX(i) acc
-      = if _IS_TRUE_(freeReg i) then (MappedReg i) : acc else acc
+#if powerpc_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = map RealReg [3..10]
+allFPArgRegs :: [Reg]
+allFPArgRegs = map (RealReg . fReg) [1..13]
+#endif /* powerpc_TARGET_ARCH */
 \end{code}
 
 \begin{code}
-freeReg :: FAST_INT -> FAST_BOOL
+freeReg :: Int -> FastBool
 
 #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)
+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 ILIT(esp) = _FALSE_  --        %esp is the C stack pointer
+freeReg esp = fastBool 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.
+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
 
-#ifdef REG_Base
-freeReg ILIT(REG_Base) = _FALSE_
+#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_StkO
-freeReg ILIT(REG_StkO) = _FALSE_
+
+#ifdef REG_Base
+freeReg REG_Base = fastBool False
 #endif
 #ifdef REG_R1
-freeReg ILIT(REG_R1)   = _FALSE_
+freeReg REG_R1   = fastBool False
 #endif 
 #ifdef REG_R2  
-freeReg ILIT(REG_R2)   = _FALSE_
+freeReg REG_R2   = fastBool False
 #endif 
 #ifdef REG_R3  
-freeReg ILIT(REG_R3)   = _FALSE_
+freeReg REG_R3   = fastBool False
 #endif 
 #ifdef REG_R4  
-freeReg ILIT(REG_R4)   = _FALSE_
+freeReg REG_R4   = fastBool False
 #endif 
 #ifdef REG_R5  
-freeReg ILIT(REG_R5)   = _FALSE_
+freeReg REG_R5   = fastBool False
 #endif 
 #ifdef REG_R6  
-freeReg ILIT(REG_R6)   = _FALSE_
+freeReg REG_R6   = fastBool False
 #endif 
 #ifdef REG_R7  
-freeReg ILIT(REG_R7)   = _FALSE_
+freeReg REG_R7   = fastBool False
 #endif 
 #ifdef REG_R8  
-freeReg ILIT(REG_R8)   = _FALSE_
+freeReg REG_R8   = fastBool False
 #endif
-#ifdef REG_Flt1
-freeReg ILIT(REG_Flt1) = _FALSE_
+#ifdef REG_F1
+freeReg REG_F1 = fastBool False
 #endif
-#ifdef REG_Flt2
-freeReg ILIT(REG_Flt2) = _FALSE_
+#ifdef REG_F2
+freeReg REG_F2 = fastBool False
 #endif
-#ifdef REG_Flt3
-freeReg ILIT(REG_Flt3) = _FALSE_
+#ifdef REG_F3
+freeReg REG_F3 = fastBool False
 #endif
-#ifdef REG_Flt4
-freeReg ILIT(REG_Flt4) = _FALSE_
+#ifdef REG_F4
+freeReg REG_F4 = fastBool False
 #endif
-#ifdef REG_Dbl1
-freeReg ILIT(REG_Dbl1) = _FALSE_
+#ifdef REG_D1
+freeReg REG_D1 = fastBool False
 #endif
-#ifdef REG_Dbl2
-freeReg ILIT(REG_Dbl2) = _FALSE_
+#ifdef REG_D2
+freeReg REG_D2 = fastBool 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_
+#ifdef REG_Sp 
+freeReg REG_Sp   = fastBool False
 #endif 
-#ifdef REG_SpB 
-freeReg ILIT(REG_SpB)  = _FALSE_
+#ifdef REG_Su
+freeReg REG_Su   = fastBool False
 #endif 
-#ifdef REG_SuB 
-freeReg ILIT(REG_SuB)  = _FALSE_
+#ifdef REG_SpLim 
+freeReg REG_SpLim = fastBool False
 #endif 
 #ifdef REG_Hp 
-freeReg ILIT(REG_Hp)   = _FALSE_
+freeReg REG_Hp   = fastBool 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_
+freeReg REG_HpLim = fastBool False
 #endif
-  | otherwise = _TRUE_
+freeReg n               = fastBool True
 \end{code}