Split Reg into vreg/hreg and add register pairs
[ghc-hetmet.git] / compiler / nativeGen / RegAlloc / Linear / SPARC / FreeRegs.hs
index e46d87d..d828347 100644 (file)
@@ -3,14 +3,19 @@
 module RegAlloc.Linear.SPARC.FreeRegs
 where
 
-import MachRegs
+import SPARC.Regs
+import SPARC.RegPlate
+import RegClass
+import Reg
 
 import Outputable
+import FastBool
 
 import Data.Word
 import Data.Bits
 import Data.List
 
+
 --------------------------------------------------------------------------------
 -- SPARC is like PPC, except for twinning of floating point regs.
 --     When we allocate a double reg we must take an even numbered
@@ -28,8 +33,9 @@ data FreeRegs
                !Word32         -- int    reg bitmap    regs  0..31
                !Word32         -- float  reg bitmap    regs 32..63
                !Word32         -- double reg bitmap    regs 32..63
-       deriving( Show )
 
+instance Show FreeRegs where
+       show = showFreeRegs
 
 -- | A reg map where no regs are free to be allocated.
 noFreeRegs :: FreeRegs
@@ -37,170 +43,144 @@ noFreeRegs = FreeRegs 0 0 0
 
 
 -- | The initial set of free regs.
---     Don't treat the top half of reg pairs we're using as doubles as being free.
 initFreeRegs :: FreeRegs
 initFreeRegs 
- =     regs
- where 
---     freeDouble      = getFreeRegs RcDouble regs
-       regs            = foldr releaseReg noFreeRegs allocable
-       allocable       = allocatableRegs \\ doublePairs
-       doublePairs     = [43, 45, 47, 49, 51, 53]
+ =     foldr releaseReg noFreeRegs allocatableRegs
 
                        
 -- | Get all the free registers of this class.
-getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
+getFreeRegs :: RegClass -> FreeRegs -> [RealReg]       -- lazilly
 getFreeRegs cls (FreeRegs g f d)
-       | RcInteger <- cls = go g 1 0
-       | RcFloat   <- cls = go f 1 32
-       | RcDouble  <- cls = go d 1 32
+       | RcInteger <- cls = map RealRegSingle                  $ go 1 g 1 0  
+       | RcFloat   <- cls = map RealRegSingle                  $ go 1 f 1 32 
+       | RcDouble  <- cls = map (\i -> RealRegPair i (i+1))    $ go 2 d 1 32 
        | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
        where
-               go _ 0 _ = []
-               go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
-                        | otherwise    = go x (m `shiftL` 1) $! i+1
-{-
-showFreeRegs :: FreeRegs -> String
-showFreeRegs regs
-       =  "FreeRegs\n"
-       ++ "    integer: " ++ (show $ getFreeRegs RcInteger regs)       ++ "\n"
-       ++ "      float: " ++ (show $ getFreeRegs RcFloat   regs)       ++ "\n"
-       ++ "     double: " ++ (show $ getFreeRegs RcDouble  regs)       ++ "\n"
--}
-
-{-
--- | Check whether a reg is free
-regIsFree :: RegNo -> FreeRegs -> Bool
-regIsFree r (FreeRegs g f d)
+               go _    _      0    _
+                       = []
 
-       -- a general purpose reg
-       | r <= 31       
-       , mask  <- 1 `shiftL` fromIntegral r
-       = g .&. mask /= 0
+               go step bitmap mask ix 
+                       | bitmap .&. mask /= 0 
+                       = ix : (go step bitmap (mask `shiftL` step) $! ix + step) 
 
-       -- use the first 22 float regs as double precision
-       | r >= 32
-       , r <= 53
-       , mask  <- 1 `shiftL` (fromIntegral r - 32)
-       = d .&. mask /= 0
+                       | otherwise    
+                       = go step bitmap (mask `shiftL` step) $! ix + step
 
-       -- use the last 10 float regs as single precision
-       | otherwise 
-       , mask  <- 1 `shiftL` (fromIntegral r - 32)
-       = f .&. mask /= 0
--}
 
 -- | Grab a register.
-grabReg :: RegNo -> FreeRegs -> FreeRegs
-grabReg r (FreeRegs g f d)
-
+allocateReg :: RealReg -> FreeRegs -> FreeRegs
+allocateReg 
+        reg@(RealRegSingle r)
+            (FreeRegs g f d)
+
+       -- can't allocate free regs
+       | not $ isFastTrue (freeReg r)
+       = pprPanic "SPARC.FreeRegs.allocateReg: not allocating pinned reg" (ppr reg)
+       
        -- a general purpose reg
        | r <= 31
-       , mask  <- complement (1 `shiftL` fromIntegral r)
-       = FreeRegs (g .&. mask) f d
-    
-       -- use the first 22 float regs as double precision
-       | r >= 32
-       , r <= 53
-       , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
-       = FreeRegs g f (d .&. mask)
-
-       -- use the last 10 float regs as single precision
-       | otherwise
-       , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
-       = FreeRegs g (f .&. mask) d
+       = let   mask    = complement (bitMask r)
+         in    FreeRegs 
+                       (g .&. mask) 
+                       f 
+                       d
+
+       -- a float reg
+       | r >= 32, r <= 63
+       = let   mask    = complement (bitMask (r - 32))
+       
+               -- the mask of the double this FP reg aliases
+               maskLow = if r `mod` 2 == 0
+                               then complement (bitMask (r - 32))
+                               else complement (bitMask (r - 32 - 1))
+         in    FreeRegs
+                       g
+                       (f .&. mask)
+                       (d .&. maskLow)
 
+       | otherwise
+       = pprPanic "SPARC.FreeRegs.releaseReg: not allocating bad reg" (ppr reg)
+                       
+allocateReg
+        reg@(RealRegPair r1 r2)
+             (FreeRegs g f d)
+       
+       | r1 >= 32, r1 <= 63, r1 `mod` 2 == 0
+       , r2 >= 32, r2 <= 63
+       = let   mask1   = complement (bitMask (r1 - 32))
+               mask2   = complement (bitMask (r2 - 32))
+         in
+               FreeRegs
+                       g
+                       ((f .&. mask1) .&. mask2)
+                       (d .&. mask1)
+                       
+       | otherwise
+       = pprPanic "SPARC.FreeRegs.releaseReg: not allocating bad reg" (ppr reg)
 
 
 -- | Release a register from allocation.
 --     The register liveness information says that most regs die after a C call, 
 --     but we still don't want to allocate to some of them.
 --
-releaseReg :: RegNo -> FreeRegs -> FreeRegs
-releaseReg r regs@(FreeRegs g f d)
-
-       -- used by STG machine, or otherwise unavailable
-       --      see includes/MachRegs.h for more info
-
-       -- Global Regs g0-g7
-       --         r0: always zero
-       --      r1-r4: allocable
-       --      r5-r7: reserved for OS
-       | r == 0                = regs
-       | r >= 5 && r <= 7      = regs
-       
-       -- Output Regs o0-o7
-       --   caller saves
-       --   r8 - r13: allocable
-       --        r14: C stack ptr
-       --        r15: C ret addr
-       | r >= 14 && r <= 15    = regs
-       
-       -- Local Regs 
-       --        r16: allocable
-       --  r17 - r21: R1-R5
-       --  r22 - r23: allocable
-       | r >= 17 && r <= 21    = regs          
-
-       -- Input Regs
-       --  r24 - r29: Sp, Base, SpLim, Hp, HpLim, R6
-       --        r30: C frame ptr
-       --        r31: C ret addr
-       | r >= 24 && r <= 31    = regs
-       
-       -- Float regs
-       --  r32 & r33: floating point return from C fun
-       --  r34 & r35: D1
-       --  r36 & r37: D2
-       --  r38 & r39: NCG spill tmp
-       --  r40 & r41: NCG spill tmp
-       | r >= 32 && r <= 41    = regs
-
-       --  r42 - r53: allocatable as double prec float regs
-
-       --  r54 - r57: F1-F4
-       --  r58 - r59: NCG spill tmps
-       | r >= 54 && r <= 59    = regs
-
-       --  r60-r64: allocatable as single prec float regs.
-
-
-       -- never release the high part of double regs.
-       --      this prevents them from being allocated as single precison regs.
-       | r == 43               = regs
-       | r == 45               = regs
-       | r == 47               = regs
-       | r == 49               = regs
-       | r == 51               = regs
-       | r == 53               = regs
-       
+releaseReg :: RealReg -> FreeRegs -> FreeRegs
+releaseReg 
+        reg@(RealRegSingle r) 
+       regs@(FreeRegs g f d)
+
+       -- don't release pinned reg
+       | not $ isFastTrue (freeReg r)
+       = regs
+
        -- a general purpose reg
        | r <= 31       
-       , mask  <- 1 `shiftL` fromIntegral r
-       = FreeRegs (g .|. mask) f d
-
-       -- use the first 22 float regs as double precision
-       | r >= 32
-       , r <= 53
-       , mask  <- 1 `shiftL` (fromIntegral r - 32)
-       = FreeRegs g f (d .|. mask)
-
-       -- use the last 10 float regs as single precision
-       | otherwise 
-       , mask  <- 1 `shiftL` (fromIntegral r - 32)
-       = FreeRegs g (f .|. mask) d
-
-
--- | Allocate a register in the map.
-allocateReg :: RegNo -> FreeRegs -> FreeRegs
-allocateReg r regs -- (FreeRegs g f d) 
-
-       -- if the reg isn't actually free then we're in trouble
-{-     | not $ regIsFree r regs
-       = pprPanic 
-               "RegAllocLinear.allocateReg"
-               (text "reg " <> ppr r <> text " is not free")
--}  
+       = let   mask    = bitMask r
+         in    FreeRegs (g .|. mask) f d
+
+       -- a float reg
+       | r >= 32, r <= 63
+       = let   mask    = bitMask (r - 32)
+               
+               -- the mask of the double this FP reg aliases
+               maskLow = if r `mod` 2 == 0
+                               then bitMask (r - 32)
+                               else bitMask (r - 32 - 1)
+         in    FreeRegs 
+                       g 
+                       (f .|. mask)
+                       (d .|. maskLow)
+
        | otherwise
-       = grabReg r regs
+       = pprPanic "SPARC.FreeRegs.releaseReg: not releasing bad reg" (ppr reg)
+       
+releaseReg 
+        reg@(RealRegPair r1 r2) 
+            (FreeRegs g f d)
+
+       | r1 >= 32, r1 <= 63, r1 `mod` 2 == 0
+       , r2 >= 32, r2 <= 63
+       = let   mask1   = bitMask (r1 - 32)
+               mask2   = bitMask (r2 - 32)
+         in
+               FreeRegs
+                       g
+                       ((f .|. mask1) .|. mask2)
+                       (d .|. mask1)
+                       
+       | otherwise
+       = pprPanic "SPARC.FreeRegs.releaseReg: not releasing bad reg" (ppr reg)
+          
+
+
+bitMask :: Int -> Word32
+bitMask n      = 1 `shiftL` n
+
+
+showFreeRegs :: FreeRegs -> String
+showFreeRegs regs
+       =  "FreeRegs\n"
+       ++ "    integer: " ++ (show $ getFreeRegs RcInteger regs)       ++ "\n"
+       ++ "      float: " ++ (show $ getFreeRegs RcFloat   regs)       ++ "\n"
+       ++ "     double: " ++ (show $ getFreeRegs RcDouble  regs)       ++ "\n"