SPARC NCG: Give regs o0-o5 back to the allocator
[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 MachRegs
7
8 import Outputable
9
10 import Data.Word
11 import Data.Bits
12 import Data.List
13
14 --------------------------------------------------------------------------------
15 -- SPARC is like PPC, except for twinning of floating point regs.
16 --      When we allocate a double reg we must take an even numbered
17 --      float reg, as well as the one after it.
18
19
20 -- Holds bitmaps showing what registers are currently allocated.
21 --      The float and double reg bitmaps overlap, but we only alloc
22 --      float regs into the float map, and double regs into the double map.
23 --
24 --      Free regs have a bit set in the corresponding bitmap.
25 --
26 data FreeRegs 
27         = FreeRegs 
28                 !Word32         -- int    reg bitmap    regs  0..31
29                 !Word32         -- float  reg bitmap    regs 32..63
30                 !Word32         -- double reg bitmap    regs 32..63
31         deriving( Show )
32
33
34 -- | A reg map where no regs are free to be allocated.
35 noFreeRegs :: FreeRegs
36 noFreeRegs = FreeRegs 0 0 0
37
38
39 -- | The initial set of free regs.
40 --      Don't treat the top half of reg pairs we're using as doubles as being free.
41 initFreeRegs :: FreeRegs
42 initFreeRegs 
43  =      regs
44  where  
45 --      freeDouble      = getFreeRegs RcDouble regs
46         regs            = foldr releaseReg noFreeRegs allocable
47         allocable       = allocatableRegs \\ doublePairs
48         doublePairs     = [43, 45, 47, 49, 51, 53]
49
50                         
51 -- | Get all the free registers of this class.
52 getFreeRegs :: RegClass -> FreeRegs -> [RegNo]  -- lazilly
53 getFreeRegs cls (FreeRegs g f d)
54         | RcInteger <- cls = go g 1 0
55         | RcFloat   <- cls = go f 1 32
56         | RcDouble  <- cls = go d 1 32
57         | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
58         where
59                 go _ 0 _ = []
60                 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
61                          | otherwise    = go x (m `shiftL` 1) $! i+1
62 {-
63 showFreeRegs :: FreeRegs -> String
64 showFreeRegs regs
65         =  "FreeRegs\n"
66         ++ "    integer: " ++ (show $ getFreeRegs RcInteger regs)       ++ "\n"
67         ++ "      float: " ++ (show $ getFreeRegs RcFloat   regs)       ++ "\n"
68         ++ "     double: " ++ (show $ getFreeRegs RcDouble  regs)       ++ "\n"
69 -}
70
71 {-
72 -- | Check whether a reg is free
73 regIsFree :: RegNo -> FreeRegs -> Bool
74 regIsFree r (FreeRegs g f d)
75
76         -- a general purpose reg
77         | r <= 31       
78         , mask  <- 1 `shiftL` fromIntegral r
79         = g .&. mask /= 0
80
81         -- use the first 22 float regs as double precision
82         | r >= 32
83         , r <= 53
84         , mask  <- 1 `shiftL` (fromIntegral r - 32)
85         = d .&. mask /= 0
86
87         -- use the last 10 float regs as single precision
88         | otherwise 
89         , mask  <- 1 `shiftL` (fromIntegral r - 32)
90         = f .&. mask /= 0
91 -}
92
93 -- | Grab a register.
94 grabReg :: RegNo -> FreeRegs -> FreeRegs
95 grabReg r (FreeRegs g f d)
96
97         -- a general purpose reg
98         | r <= 31
99         , mask  <- complement (1 `shiftL` fromIntegral r)
100         = FreeRegs (g .&. mask) f d
101     
102         -- use the first 22 float regs as double precision
103         | r >= 32
104         , r <= 53
105         , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
106         = FreeRegs g f (d .&. mask)
107
108         -- use the last 10 float regs as single precision
109         | otherwise
110         , mask  <- complement (1 `shiftL` (fromIntegral r - 32))
111         = FreeRegs g (f .&. mask) d
112
113
114
115 -- | Release a register from allocation.
116 --      The register liveness information says that most regs die after a C call, 
117 --      but we still don't want to allocate to some of them.
118 --
119 releaseReg :: RegNo -> FreeRegs -> FreeRegs
120 releaseReg r regs@(FreeRegs g f d)
121
122         -- used by STG machine, or otherwise unavailable
123         --      see includes/MachRegs.h for more info
124
125         -- Global Regs g0-g7
126         --         r0: always zero
127         --      r1-r4: allocable
128         --      r5-r7: reserved for OS
129         | r == 0                = regs
130         | r >= 5 && r <= 7      = regs
131         
132         -- Output Regs o0-o7
133         --   caller saves
134         --   r8 - r13: allocable
135         --        r14: C stack ptr
136         --        r15: C ret addr
137         | r >= 14 && r <= 15    = regs
138         
139         -- Local Regs 
140         --        r16: allocable
141         --  r17 - r21: R1-R5
142         --  r22 - r23: allocable
143         | r >= 17 && r <= 21    = regs          
144
145         -- Input Regs
146         --  r24 - r29: Sp, Base, SpLim, Hp, HpLim, R6
147         --        r30: C frame ptr
148         --        r31: C ret addr
149         | r >= 24 && r <= 31    = regs
150         
151         -- Float regs
152         --  r32 & r33: floating point return from C fun
153         --  r34 & r35: D1
154         --  r36 & r37: D2
155         --  r38 & r39: NCG spill tmp
156         --  r40 & r41: NCG spill tmp
157         | r >= 32 && r <= 41    = regs
158
159         --  r42 - r53: allocatable as double prec float regs
160
161         --  r54 - r57: F1-F4
162         --  r58 - r59: NCG spill tmps
163         | r >= 54 && r <= 59    = regs
164
165         --  r60-r64: allocatable as single prec float regs.
166
167
168         -- never release the high part of double regs.
169         --      this prevents them from being allocated as single precison regs.
170         | r == 43               = regs
171         | r == 45               = regs
172         | r == 47               = regs
173         | r == 49               = regs
174         | r == 51               = regs
175         | r == 53               = regs
176         
177         -- a general purpose reg
178         | r <= 31       
179         , mask  <- 1 `shiftL` fromIntegral r
180         = FreeRegs (g .|. mask) f d
181
182         -- use the first 22 float regs as double precision
183         | r >= 32
184         , r <= 53
185         , mask  <- 1 `shiftL` (fromIntegral r - 32)
186         = FreeRegs g f (d .|. mask)
187
188         -- use the last 10 float regs as single precision
189         | otherwise 
190         , mask  <- 1 `shiftL` (fromIntegral r - 32)
191         = FreeRegs g (f .|. mask) d
192
193
194 -- | Allocate a register in the map.
195 allocateReg :: RegNo -> FreeRegs -> FreeRegs
196 allocateReg r regs -- (FreeRegs g f d) 
197
198         -- if the reg isn't actually free then we're in trouble
199 {-      | not $ regIsFree r regs
200         = pprPanic 
201                 "RegAllocLinear.allocateReg"
202                 (text "reg " <> ppr r <> text " is not free")
203 -}  
204         | otherwise
205         = grabReg r regs
206