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