[project @ 2000-07-11 19:17:20 by panne]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachRegs.lhs
index bf0b939..5e7e586 100644 (file)
@@ -14,26 +14,21 @@ modules --- the pleasure has been foregone.)
 
 module MachRegs (
 
 
 module MachRegs (
 
-       Reg(..),
+        RegClass(..), regClass,
+       Reg(..), isRealReg, isVirtualReg,
+        allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
+
        Imm(..),
        MachRegsAddr(..),
        RegLoc(..),
        Imm(..),
        MachRegsAddr(..),
        RegLoc(..),
-       RegNo,
 
        addrOffset,
 
        addrOffset,
-       argRegs,
        baseRegOffset,
        baseRegOffset,
-       callClobberedRegs,
        callerSaves,
        callerSaves,
-       dblImmLit,
-       extractMappedRegNos,
-       freeMappedRegs,
-       freeReg, freeRegs,
+       freeReg,
        getNewRegNCG,
        getNewRegNCG,
+       mkVReg,
        magicIdRegMaybe,
        magicIdRegMaybe,
-       mkReg,
-       realReg,
-       reservedRegs,
        saveLoc,
        spRel,
        stgReg,
        saveLoc,
        spRel,
        stgReg,
@@ -47,13 +42,12 @@ module MachRegs (
 #endif
 #if i386_TARGET_ARCH
        , eax, ebx, ecx, edx, esi, esp
 #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
 #endif
 #if sparc_TARGET_ARCH
-       , allArgRegs
        , fits13Bits
        , fits13Bits
-       , fPair, fpRel, gReg, iReg, lReg, oReg, largeOffsetError
-       , fp, g0, o0, f0
+       , fpRel, gReg, iReg, lReg, oReg, largeOffsetError
+       , fp, sp, g0, g1, g2, o0, f0, f6, f8, f26, f27
        
 #endif
     ) where
        
 #endif
     ) where
@@ -62,14 +56,12 @@ module MachRegs (
 
 import AbsCSyn         ( MagicId(..) )
 import AbsCUtils       ( magicIdPrimRep )
 
 import AbsCSyn         ( MagicId(..) )
 import AbsCUtils       ( magicIdPrimRep )
-import CLabel           ( CLabel )
+import CLabel           ( CLabel, mkMainRegTableLabel )
 import PrimOp          ( PrimOp(..) )
 import PrimOp          ( PrimOp(..) )
-import PrimRep         ( PrimRep(..) )
-import Stix            ( sStLitLbl, StixTree(..), StixReg(..) )
-import Unique          ( mkPseudoUnique1, mkPseudoUnique2, mkPseudoUnique3,
-                         Uniquable(..), Unique
-                       )
-import UniqSupply      ( getUniqueUs, returnUs, thenUs, UniqSM )
+import PrimRep         ( PrimRep(..), isFloatingRep )
+import Stix            ( StixTree(..), StixReg(..),
+                          getUniqueNat, returnNat, thenNat, NatM )
+import Unique          ( mkPseudoUnique2, Uniquable(..), Unique )
 import Outputable
 \end{code}
 
 import Outputable
 \end{code}
 
@@ -80,20 +72,17 @@ data Imm
   = ImmInt     Int
   | ImmInteger Integer     -- Sigh.
   | ImmCLbl    CLabel      -- AbstractC Label (with baggage)
   = ImmInt     Int
   | ImmInteger Integer     -- Sigh.
   | ImmCLbl    CLabel      -- AbstractC Label (with baggage)
-  | ImmLab     SDoc    -- Simple string label (underscore-able)
+  | ImmLab     Bool SDoc    -- Simple string label (underscore-able)
+                             -- Bool==True ==> in a different DLL
   | ImmLit     SDoc    -- Simple string
   | ImmIndex    CLabel Int
   | ImmLit     SDoc    -- Simple string
   | ImmIndex    CLabel Int
+  | ImmFloat   Rational
+  | ImmDouble  Rational
   IF_ARCH_sparc(
   | LO Imm                 -- Possible restrictions...
   | HI Imm
   ,)
 strImmLit s = ImmLit (text s)
   IF_ARCH_sparc(
   | LO Imm                 -- Possible restrictions...
   | HI Imm
   ,)
 strImmLit s = ImmLit (text s)
-dblImmLit r
-  = strImmLit (
-        IF_ARCH_alpha({-prepend nothing-}
-       ,IF_ARCH_i386( '0' : 'd' :
-       ,IF_ARCH_sparc('0' : 'r' :,)))
-       showSDoc (rational r))
 \end{code}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -145,7 +134,7 @@ addrOffset addr off
        | otherwise     -> Nothing
        where n2 = n + toInteger 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
        
        | fits13Bits off -> Just (AddrRegImm r (ImmInt off))
        | otherwise     -> Nothing
        
@@ -162,19 +151,16 @@ fits8Bits i = i >= -256 && i < 256
 #endif
 
 #if sparc_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
 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")
+  = 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}
 
 #endif {-sparc-}
 \end{code}
@@ -209,10 +195,10 @@ stgReg x
 
     baseLoc = case (magicIdRegMaybe BaseReg) of
       Just _  -> StReg (StixMagicId BaseReg)
 
     baseLoc = case (magicIdRegMaybe BaseReg) of
       Just _  -> StReg (StixMagicId BaseReg)
-      Nothing -> sStLitLbl SLIT("MainRegTable")
+      Nothing -> StCLbl mkMainRegTableLabel
 
     nonReg = case x of
 
     nonReg = case x of
-      BaseReg          -> sStLitLbl SLIT("MainRegTable")
+      BaseReg -> StCLbl mkMainRegTableLabel
 
       _ -> StInd (magicIdPrimRep x)
                 (StPrim IntAddOp [baseLoc,
 
       _ -> StInd (magicIdPrimRep x)
                 (StPrim IntAddOp [baseLoc,
@@ -251,97 +237,103 @@ 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.
 
 
-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.
-
-\begin{code}
-data Reg
-  = FixedReg  FAST_INT         -- A pre-allocated machine register
+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.
 
 
-  | MappedReg FAST_INT         -- A dynamically allocated machine register
+Virtual regs can be of either class, so that info is attached.
 
 
-  | MemoryReg Int PrimRep      -- A machine "register" actually held in
-                               -- a memory allocated table of
-                               -- registers which didn't fit in real
-                               -- registers.
+\begin{code}
 
 
-  | 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
+data RegClass 
+   = RcInteger 
+   | RcFloat
+   | RcDouble
+     deriving Eq
 
 
-getNewRegNCG :: PrimRep -> UniqSM Reg
-getNewRegNCG pk
-  = getUniqueUs        `thenUs` \ u ->
-    returnUs (UnmappedReg u pk)
+data Reg
+   = RealReg     Int
+   | VirtualRegI Unique
+   | VirtualRegF Unique
+   | VirtualRegD Unique
 
 
-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
+unRealReg (RealReg i) = i
+unRealReg vreg        = pprPanic "unRealReg on VirtualReg" (ppr vreg)
 
 
-#ifdef DEBUG
-instance Outputable Reg where
-    ppr r = text (show r)
+mkVReg :: Unique -> PrimRep -> Reg
+mkVReg u pk
+#if sparc_TARGET_ARCH
+   = case pk of
+        FloatRep  -> VirtualRegF u
+        DoubleRep -> VirtualRegD u
+        other     -> VirtualRegI u
+#else
+   = if isFloatingRep pk then VirtualRegD u else VirtualRegI u
 #endif
 
 #endif
 
-cmpReg (FixedReg i)      (FixedReg i')      = cmp_ihash i i'
-cmpReg (MappedReg i)     (MappedReg i')     = cmp_ihash i i'
-cmpReg (MemoryReg i _)   (MemoryReg i' _)   = i `compare` i'
-cmpReg (UnmappedReg u _) (UnmappedReg u' _) = compare 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_ihash :: FAST_INT -> FAST_INT -> Ordering
-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
+
+getNewRegNCG :: PrimRep -> NatM Reg
+getNewRegNCG pk
+   = getUniqueNat `thenNat` \ u -> returnNat (mkVReg u pk)
 
 instance Eq Reg where
 
 instance Eq Reg where
-    a == b = case (a `compare` b) of { EQ -> True;  _ -> False }
-    a /= b = case (a `compare` 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
 
 instance Ord Reg where
-    a <= b = case (a `compare` b) of { LT -> True;     EQ -> True;  GT -> False }
-    a <         b = case (a `compare` b) of { LT -> True;      EQ -> False; GT -> False }
-    a >= b = case (a `compare` b) of { LT -> False; EQ -> True;  GT -> True  }
-    a >         b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True  }
-    compare a b = cmpReg a b
+   compare (RealReg i1)     (RealReg i2)     = compare i1 i2
+   compare (RealReg _)      (VirtualRegI _)  = LT
+   compare (RealReg _)      (VirtualRegF _)  = LT
+   compare (RealReg _)      (VirtualRegD _)  = LT
 
 
-instance Uniquable Reg where
-    getUnique (UnmappedReg u _) = u
-    getUnique (FixedReg i)      = mkPseudoUnique1 IBOX(i)
-    getUnique (MappedReg i)     = mkPseudoUnique2 IBOX(i)
-    getUnique (MemoryReg i _)   = mkPseudoUnique3 i
-\end{code}
+   compare (VirtualRegI _)  (RealReg _)      = GT
+   compare (VirtualRegI u1) (VirtualRegI u2) = compare u1 u2
+   compare (VirtualRegI _)  (VirtualRegF _)  = LT
+   compare (VirtualRegI _)  (VirtualRegD _)  = LT
 
 
-\begin{code}
-type RegNo = Int
+   compare (VirtualRegF _)  (RealReg _)      = GT
+   compare (VirtualRegF _)  (VirtualRegI _)  = GT
+   compare (VirtualRegF u1) (VirtualRegF u2) = compare u1 u2
+   compare (VirtualRegF _)  (VirtualRegD _)  = LT
 
 
-realReg :: RegNo -> Reg
-realReg n@IBOX(i)
-  = if _IS_TRUE_(freeReg i) then MappedReg i else FixedReg i
+   compare (VirtualRegD _)  (RealReg _)      = GT
+   compare (VirtualRegD _)  (VirtualRegI _)  = GT
+   compare (VirtualRegD _)  (VirtualRegF _)  = GT
+   compare (VirtualRegD u1) (VirtualRegD u2) = compare u1 u2
 
 
-extractMappedRegNos :: [Reg] -> [RegNo]
 
 
-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
+    showsPrec _ (RealReg i)     = showString (showReg i)
+    showsPrec _ (VirtualRegI u) = showString "%vI_"  . shows u
+    showsPrec _ (VirtualRegF u) = showString "%vF_"  . shows u
+    showsPrec _ (VirtualRegD u) = showString "%vD_"  . shows u
+
+instance Outputable Reg where
+    ppr r = text (show r)
+
+instance Uniquable Reg where
+    getUnique (RealReg i)     = mkPseudoUnique2 i
+    getUnique (VirtualRegI u) = u
+    getUnique (VirtualRegF u) = u
+    getUnique (VirtualRegD u) = u
 \end{code}
 
 ** Machine-specific Reg stuff: **
 \end{code}
 
 ** Machine-specific Reg stuff: **
@@ -376,31 +368,44 @@ 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.)
 - 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.
+
 \begin{code}
 #if i386_TARGET_ARCH
 
 \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 = realReg (gReg 0)
-ebx = realReg (gReg 1)
-ecx = realReg (gReg 2)
-edx = realReg (gReg 3)
-esi = realReg (gReg 4)
-edi = realReg (gReg 5)
-ebp = realReg (gReg 6)
-esp = realReg (gReg 7)
-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 (VirtualRegF u) = RcFloat
+regClass (VirtualRegD u) = RcDouble
+
+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}
 
 #endif
 \end{code}
@@ -410,6 +415,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.
 
 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
 
 \begin{code}
 #if sparc_TARGET_ARCH
 
@@ -420,18 +429,70 @@ lReg x = (16 + x)
 iReg x = (24 + x)
 fReg x = (32 + 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
+
+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, f0, f1, f6, f8, f22, f26, f27 :: Reg
 
 
-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)
+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)
+f0  = RealReg (fReg 0)
+f1  = RealReg (fReg 1)
 
 #endif
 
 #endif
+
+-------------------------------
+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
+    [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 -}
 \end{code}
 
 Redefine the literals used for machine-registers with non-numeric
 \end{code}
 
 Redefine the literals used for machine-registers with non-numeric
@@ -480,14 +541,12 @@ names in the header files.  Gag me with a spoon, eh?
 #define edi 5
 #define ebp 6
 #define esp 7
 #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
 #endif
 #if sparc_TARGET_ARCH
 #define g0 0
@@ -522,16 +581,17 @@ names in the header files.  Gag me with a spoon, eh?
 #define i5 29
 #define i6 30
 #define i7 31
 #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 f10 42
 #define f11 43
 #define f12 44
@@ -554,6 +614,7 @@ names in the header files.  Gag me with a spoon, eh?
 #define f29 61
 #define f30 62
 #define f31 63
 #define f29 61
 #define f30 62
 #define f31 63
+
 #endif
 \end{code}
 
 #endif
 \end{code}
 
@@ -568,6 +629,8 @@ 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 (VanillaReg _ ILIT(6)) = OFFSET_R6
 baseRegOffset (VanillaReg _ ILIT(7)) = OFFSET_R7
 baseRegOffset (VanillaReg _ ILIT(8)) = OFFSET_R8
+baseRegOffset (VanillaReg _ ILIT(9)) = OFFSET_R9
+baseRegOffset (VanillaReg _ ILIT(10)) = OFFSET_R10
 baseRegOffset (FloatReg  ILIT(1))    = OFFSET_F1
 baseRegOffset (FloatReg  ILIT(2))    = OFFSET_F2
 baseRegOffset (FloatReg  ILIT(3))    = OFFSET_F3
 baseRegOffset (FloatReg  ILIT(1))    = OFFSET_F1
 baseRegOffset (FloatReg  ILIT(2))    = OFFSET_F2
 baseRegOffset (FloatReg  ILIT(3))    = OFFSET_F3
@@ -585,6 +648,8 @@ baseRegOffset (LongReg _ ILIT(2))    = OFFSET_Lng2
 #endif
 baseRegOffset Hp                    = OFFSET_Hp
 baseRegOffset HpLim                 = OFFSET_HpLim
 #endif
 baseRegOffset Hp                    = OFFSET_Hp
 baseRegOffset HpLim                 = OFFSET_HpLim
+baseRegOffset CurrentTSO            = OFFSET_CurrentTSO
+baseRegOffset CurrentNursery        = OFFSET_CurrentNursery
 #ifdef DEBUG
 baseRegOffset BaseReg               = panic "baseRegOffset:BaseReg"
 baseRegOffset CurCostCentre         = panic "baseRegOffset:CurCostCentre"
 #ifdef DEBUG
 baseRegOffset BaseReg               = panic "baseRegOffset:BaseReg"
 baseRegOffset CurCostCentre         = panic "baseRegOffset:CurCostCentre"
@@ -658,6 +723,12 @@ callerSaves Hp                             = True
 #ifdef CALLER_SAVES_HpLim
 callerSaves HpLim                      = 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}
 
 callerSaves _                          = False
 \end{code}
 
@@ -665,184 +736,154 @@ callerSaves _                           = False
 magicIdRegMaybe :: MagicId -> Maybe Reg
 
 #ifdef REG_Base
 magicIdRegMaybe :: MagicId -> Maybe Reg
 
 #ifdef REG_Base
-magicIdRegMaybe BaseReg                        = Just (FixedReg ILIT(REG_Base))
+magicIdRegMaybe BaseReg                        = Just (RealReg REG_Base)
 #endif
 #ifdef REG_R1
 #endif
 #ifdef REG_R1
-magicIdRegMaybe (VanillaReg _ ILIT(1))         = Just (FixedReg ILIT(REG_R1))
+magicIdRegMaybe (VanillaReg _ ILIT(1))         = Just (RealReg REG_R1)
 #endif 
 #ifdef REG_R2 
 #endif 
 #ifdef REG_R2 
-magicIdRegMaybe (VanillaReg _ ILIT(2))         = Just (FixedReg ILIT(REG_R2))
+magicIdRegMaybe (VanillaReg _ ILIT(2))         = Just (RealReg REG_R2)
 #endif 
 #ifdef REG_R3 
 #endif 
 #ifdef REG_R3 
-magicIdRegMaybe (VanillaReg _ ILIT(3))         = Just (FixedReg ILIT(REG_R3))
+magicIdRegMaybe (VanillaReg _ ILIT(3))         = Just (RealReg REG_R3)
 #endif 
 #ifdef REG_R4 
 #endif 
 #ifdef REG_R4 
-magicIdRegMaybe (VanillaReg _ ILIT(4))         = Just (FixedReg ILIT(REG_R4))
+magicIdRegMaybe (VanillaReg _ ILIT(4))         = Just (RealReg REG_R4)
 #endif 
 #ifdef REG_R5 
 #endif 
 #ifdef REG_R5 
-magicIdRegMaybe (VanillaReg _ ILIT(5))         = Just (FixedReg ILIT(REG_R5))
+magicIdRegMaybe (VanillaReg _ ILIT(5))         = Just (RealReg REG_R5)
 #endif 
 #ifdef REG_R6 
 #endif 
 #ifdef REG_R6 
-magicIdRegMaybe (VanillaReg _ ILIT(6))         = Just (FixedReg ILIT(REG_R6))
+magicIdRegMaybe (VanillaReg _ ILIT(6))         = Just (RealReg REG_R6)
 #endif 
 #ifdef REG_R7 
 #endif 
 #ifdef REG_R7 
-magicIdRegMaybe (VanillaReg _ ILIT(7))         = Just (FixedReg ILIT(REG_R7))
+magicIdRegMaybe (VanillaReg _ ILIT(7))         = Just (RealReg REG_R7)
 #endif 
 #ifdef REG_R8 
 #endif 
 #ifdef REG_R8 
-magicIdRegMaybe (VanillaReg _ ILIT(8))         = Just (FixedReg ILIT(REG_R8))
+magicIdRegMaybe (VanillaReg _ ILIT(8))         = Just (RealReg REG_R8)
+#endif
+#ifdef REG_R9 
+magicIdRegMaybe (VanillaReg _ ILIT(9))         = Just (RealReg REG_R9)
+#endif
+#ifdef REG_R10 
+magicIdRegMaybe (VanillaReg _ ILIT(10))        = Just (RealReg REG_R10)
 #endif
 #ifdef REG_F1
 #endif
 #ifdef REG_F1
-magicIdRegMaybe (FloatReg ILIT(1))     = Just (FixedReg ILIT(REG_F1))
+magicIdRegMaybe (FloatReg ILIT(1))     = Just (RealReg REG_F1)
 #endif                                 
 #ifdef REG_F2                          
 #endif                                 
 #ifdef REG_F2                          
-magicIdRegMaybe (FloatReg ILIT(2))     = Just (FixedReg ILIT(REG_F2))
+magicIdRegMaybe (FloatReg ILIT(2))     = Just (RealReg REG_F2)
 #endif                                 
 #ifdef REG_F3                          
 #endif                                 
 #ifdef REG_F3                          
-magicIdRegMaybe (FloatReg ILIT(3))     = Just (FixedReg ILIT(REG_F3))
+magicIdRegMaybe (FloatReg ILIT(3))     = Just (RealReg REG_F3)
 #endif                                 
 #ifdef REG_F4                          
 #endif                                 
 #ifdef REG_F4                          
-magicIdRegMaybe (FloatReg ILIT(4))     = Just (FixedReg ILIT(REG_F4))
+magicIdRegMaybe (FloatReg ILIT(4))     = Just (RealReg REG_F4)
 #endif                                 
 #ifdef REG_D1                          
 #endif                                 
 #ifdef REG_D1                          
-magicIdRegMaybe (DoubleReg ILIT(1))    = Just (FixedReg ILIT(REG_D1))
+magicIdRegMaybe (DoubleReg ILIT(1))    = Just (RealReg REG_D1)
 #endif                                 
 #ifdef REG_D2                          
 #endif                                 
 #ifdef REG_D2                          
-magicIdRegMaybe (DoubleReg ILIT(2))    = Just (FixedReg ILIT(REG_D2))
+magicIdRegMaybe (DoubleReg ILIT(2))    = Just (RealReg REG_D2)
 #endif
 #ifdef REG_Sp      
 #endif
 #ifdef REG_Sp      
-magicIdRegMaybe Sp                     = Just (FixedReg ILIT(REG_Sp))
+magicIdRegMaybe Sp                     = Just (RealReg REG_Sp)
 #endif
 #ifdef REG_Lng1                                
 #endif
 #ifdef REG_Lng1                                
-magicIdRegMaybe (LongReg _ ILIT(1))    = Just (FixedReg ILIT(REG_Lng1))
+magicIdRegMaybe (LongReg _ ILIT(1))    = Just (RealReg REG_Lng1)
 #endif                                 
 #ifdef REG_Lng2                                
 #endif                                 
 #ifdef REG_Lng2                                
-magicIdRegMaybe (LongReg _ ILIT(2))    = Just (FixedReg ILIT(REG_Lng2))
+magicIdRegMaybe (LongReg _ ILIT(2))    = Just (RealReg REG_Lng2)
 #endif
 #ifdef REG_Su                          
 #endif
 #ifdef REG_Su                          
-magicIdRegMaybe Su                     = Just (FixedReg ILIT(REG_Su))
+magicIdRegMaybe Su                     = Just (RealReg REG_Su)
 #endif                                 
 #ifdef REG_SpLim                               
 #endif                                 
 #ifdef REG_SpLim                               
-magicIdRegMaybe SpLim                  = Just (FixedReg ILIT(REG_SpLim))
+magicIdRegMaybe SpLim                  = Just (RealReg REG_SpLim)
 #endif                                 
 #ifdef REG_Hp                          
 #endif                                 
 #ifdef REG_Hp                          
-magicIdRegMaybe Hp                     = Just (FixedReg ILIT(REG_Hp))
+magicIdRegMaybe Hp                     = Just (RealReg REG_Hp)
 #endif                                 
 #ifdef REG_HpLim                       
 #endif                                 
 #ifdef REG_HpLim                       
-magicIdRegMaybe HpLim                  = Just (FixedReg ILIT(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}
 
 #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}
 \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 -}
+-- 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]),
+                   )))
+-- allocatableRegs is allMachRegNos with the fixed-use regs removed.
+allocatableRegs :: [Reg]
+allocatableRegs
+   = let isFree (RealReg (I# i)) = _IS_TRUE_(freeReg i)
+     in  filter isFree (map RealReg allMachRegNos)
 
 -------------------------------
 
 -------------------------------
+-- 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 :: Int -> [Reg]
 
-argRegs 0 = []
 #if i386_TARGET_ARCH
 #if i386_TARGET_ARCH
-argRegs _ = panic "MachRegs.argRegs: doesn't work on I386"
-#else
+argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
+#endif
+
 #if alpha_TARGET_ARCH
 #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 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 -}
 #endif {- alpha_TARGET_ARCH -}
+
 #if sparc_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])
+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 -}
 #endif {- sparc_TARGET_ARCH -}
-argRegs _ = panic "MachRegs.argRegs: don't know about >6 arguments!"
-#endif {- i386_TARGET_ARCH -}
 
 
--------------------------------
 
 
+
+-------------------------------
+-- all of the arg regs ??
 #if alpha_TARGET_ARCH
 allArgRegs :: [(Reg, Reg)]
 #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 = [(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]]
+allArgRegs = map RealReg [oReg i | i <- [0..5]]
 #endif {- sparc_TARGET_ARCH -}
 
 #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
+#if i386_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = panic "MachRegs.allArgRegs(x86): should not be used!"
+#endif
 \end{code}
 
 \begin{code}
 \end{code}
 
 \begin{code}
@@ -868,6 +909,8 @@ 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 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 ILIT(f0) = _FALSE_  --  %f0/%f1 are the C fp return registers.
+freeReg ILIT(f1) = _FALSE_
 #endif
 
 #ifdef REG_Base
 #endif
 
 #ifdef REG_Base
@@ -930,15 +973,5 @@ freeReg ILIT(REG_Hp)   = _FALSE_
 #ifdef REG_HpLim
 freeReg ILIT(REG_HpLim) = _FALSE_
 #endif
 #ifdef REG_HpLim
 freeReg ILIT(REG_HpLim) = _FALSE_
 #endif
-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_D1
-  | n _EQ_ (ILIT(REG_D1) _ADD_ ILIT(1)) = _FALSE_
-#endif
-#ifdef REG_D2
-  | n _EQ_ (ILIT(REG_D2) _ADD_ ILIT(1)) = _FALSE_
-#endif
-  | otherwise = _TRUE_
+freeReg n               = _TRUE_
 \end{code}
 \end{code}