aa716b585f29d7b3f2b13007109495a4580874cf
[ghc-hetmet.git] / compiler / nativeGen / RegAlloc / Linear / SPARC / FreeRegs.hs
1
2 -- | Free regs map for SPARC
3 module RegAlloc.Linear.SPARC.FreeRegs
4 where
5
6 import Regs
7
8 import Outputable
9 import FastBool
10
11 import Data.Word
12 import Data.Bits
13 import Data.List
14
15
16 --------------------------------------------------------------------------------
17 -- SPARC is like PPC, except for twinning of floating point regs.
18 --      When we allocate a double reg we must take an even numbered
19 --      float reg, as well as the one after it.
20
21
22 -- Holds bitmaps showing what registers are currently allocated.
23 --      The float and double reg bitmaps overlap, but we only alloc
24 --      float regs into the float map, and double regs into the double map.
25 --
26 --      Free regs have a bit set in the corresponding bitmap.
27 --
28 data FreeRegs 
29         = FreeRegs 
30                 !Word32         -- int    reg bitmap    regs  0..31
31                 !Word32         -- float  reg bitmap    regs 32..63
32                 !Word32         -- double reg bitmap    regs 32..63
33         deriving( Show )
34
35
36 -- | A reg map where no regs are free to be allocated.
37 noFreeRegs :: FreeRegs
38 noFreeRegs = FreeRegs 0 0 0
39
40
41 -- | The initial set of free regs.
42 --      Don't treat the top half of reg pairs we're using as doubles as being free.
43 initFreeRegs :: FreeRegs
44 initFreeRegs 
45  =      regs
46  where  
47 --      freeDouble      = getFreeRegs RcDouble regs
48         regs            = foldr releaseReg noFreeRegs allocable
49         allocable       = allocatableRegs \\ doublePairs
50         doublePairs     = [43, 45, 47, 49, 51, 53]
51
52                         
53 -- | Get all the free registers of this class.
54 getFreeRegs :: RegClass -> FreeRegs -> [RegNo]  -- lazilly
55 getFreeRegs cls (FreeRegs g f d)
56         | RcInteger <- cls = go g 1 0
57         | RcFloat   <- cls = go f 1 32
58         | RcDouble  <- cls = go d 1 32
59         | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
60         where
61                 go _ 0 _ = []
62                 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
63                          | otherwise    = go x (m `shiftL` 1) $! i+1
64 {-
65 showFreeRegs :: FreeRegs -> String
66 showFreeRegs regs
67         =  "FreeRegs\n"
68         ++ "    integer: " ++ (show $ getFreeRegs RcInteger regs)       ++ "\n"
69         ++ "      float: " ++ (show $ getFreeRegs RcFloat   regs)       ++ "\n"
70         ++ "     double: " ++ (show $ getFreeRegs RcDouble  regs)       ++ "\n"
71 -}
72
73 {-
74 -- | Check whether a reg is free
75 regIsFree :: RegNo -> FreeRegs -> Bool
76 regIsFree r (FreeRegs g f d)
77
78         -- a general purpose reg
79         | r <= 31       
80         , mask  <- 1 `shiftL` fromIntegral r
81         = g .&. mask /= 0
82
83         -- use the first 22 float regs as double precision
84         | r >= 32
85         , r <= 53
86         , mask  <- 1 `shiftL` (fromIntegral r - 32)
87         = d .&. mask /= 0
88
89         -- use the last 10 float regs as single precision
90         | otherwise 
91         , mask  <- 1 `shiftL` (fromIntegral r - 32)
92         = f .&. mask /= 0
93 -}
94
95 -- | Grab a register.
96 grabReg :: RegNo -> FreeRegs -> FreeRegs
97 grabReg r (FreeRegs g f d)
98
99         -- a general purpose reg
100         | r <= 31
101         , mask  <- complement (1 `shiftL` fromIntegral r)
102         = FreeRegs (g .&. mask) f d
103     
104         -- use the first 22 float regs as double precision
105         | r >= 32
106         , r <= 53
107         , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
108         = FreeRegs g f (d .&. mask)
109
110         -- use the last 10 float regs as single precision
111         | otherwise
112         , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
113         = FreeRegs g (f .&. mask) d
114
115
116
117 -- | Release a register from allocation.
118 --      The register liveness information says that most regs die after a C call, 
119 --      but we still don't want to allocate to some of them.
120 --
121 releaseReg :: RegNo -> FreeRegs -> FreeRegs
122 releaseReg r regs@(FreeRegs g f d)
123         -- don't release pinned reg
124         | not $ isFastTrue (freeReg r)
125         = regs
126         
127         -- don't release the high part of double regs
128         --      this prevents them from being allocated as single precison regs.
129         | r == 43               = regs
130         | r == 45               = regs
131         | r == 47               = regs
132         | r == 49               = regs
133         | r == 51               = regs
134         | r == 53               = regs
135         
136         -- a general purpose reg
137         | r <= 31       
138         , mask  <- 1 `shiftL` fromIntegral r
139         = FreeRegs (g .|. mask) f d
140
141         -- use the first 22 float regs as double precision
142         | r >= 32
143         , r <= 53
144         , mask  <- 1 `shiftL` (fromIntegral r - 32)
145         = FreeRegs g f (d .|. mask)
146
147         -- use the last 10 float regs as single precision
148         | otherwise 
149         , mask  <- 1 `shiftL` (fromIntegral r - 32)
150         = FreeRegs g (f .|. mask) d
151
152
153 -- | Allocate a register in the map.
154 allocateReg :: RegNo -> FreeRegs -> FreeRegs
155 allocateReg r regs -- (FreeRegs g f d) 
156
157         -- if the reg isn't actually free then we're in trouble
158 {-      | not $ regIsFree r regs
159         = pprPanic 
160                 "RegAllocLinear.allocateReg"
161                 (text "reg " <> ppr r <> text " is not free")
162 -}  
163         | otherwise
164         = grabReg r regs
165