NCG: Split up the native code generator into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / SPARC / RegInfo.hs
1
2 -----------------------------------------------------------------------------
3 --
4 -- Machine-specific parts of the register allocator
5 --
6 -- (c) The University of Glasgow 1996-2004
7 --
8 -----------------------------------------------------------------------------
9
10 module SPARC.RegInfo (
11         mkVReg,
12
13         riZero,
14         fpRelEA,
15         moveSp,
16         fPair,
17
18         shortcutStatic,
19         regDotColor,
20
21         JumpDest(..), 
22         canShortcut, 
23         shortcutJump,
24 )
25
26 where
27
28 import SPARC.Instr
29 import SPARC.Regs
30 import RegClass
31 import Reg
32 import Size
33
34 import Constants        (wORD_SIZE)
35 import Cmm
36 import CLabel
37 import BlockId
38 import Outputable
39 import Unique
40
41
42 -- | Make a virtual reg with this size.
43 mkVReg :: Unique -> Size -> Reg
44 mkVReg u size
45         | not (isFloatSize size) 
46         = VirtualRegI u
47
48         | otherwise
49         = case size of
50                 FF32    -> VirtualRegF u
51                 FF64    -> VirtualRegD u
52                 _       -> panic "mkVReg"
53
54
55 -- | Check if a RI represents a zero value.
56 --      - a literal zero
57 --      - register %g0, which is always zero.
58 --
59 riZero :: RI -> Bool
60 riZero (RIImm (ImmInt 0))           = True
61 riZero (RIImm (ImmInteger 0))       = True
62 riZero (RIReg (RealReg 0))          = True
63 riZero _                            = False
64
65
66 -- | Calculate the effective address which would be used by the
67 --      corresponding fpRel sequence.  fpRel is in MachRegs.lhs,
68 --      alas -- can't have fpRelEA here because of module dependencies.
69 fpRelEA :: Int -> Reg -> Instr
70 fpRelEA n dst
71    = ADD False False fp (RIImm (ImmInt (n * wORD_SIZE))) dst
72
73
74 -- | Code to shift the stack pointer by n words.
75 moveSp :: Int -> Instr
76 moveSp n
77    = ADD False False sp (RIImm (ImmInt (n * wORD_SIZE))) sp
78
79
80 -- | Produce the second-half-of-a-double register given the first half.
81 fPair :: Reg -> Maybe Reg
82 fPair (RealReg n) 
83         | n >= 32 && n `mod` 2 == 0  = Just (RealReg (n+1))
84
85 fPair (VirtualRegD u)
86         = Just (VirtualRegHi u)
87
88 fPair _
89         = trace ("MachInstrs.fPair: can't get high half of supposed double reg ") 
90                 Nothing
91
92 -- Here because it knows about JumpDest
93 shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
94 shortcutStatic fn (CmmStaticLit (CmmLabel lab))
95   | Just uq <- maybeAsmTemp lab 
96   = CmmStaticLit (CmmLabel (shortBlockId fn (BlockId uq)))
97 shortcutStatic fn (CmmStaticLit (CmmLabelDiffOff lbl1 lbl2 off))
98   | Just uq <- maybeAsmTemp lbl1
99   = CmmStaticLit (CmmLabelDiffOff (shortBlockId fn (BlockId uq)) lbl2 off)
100         -- slightly dodgy, we're ignoring the second label, but this
101         -- works with the way we use CmmLabelDiffOff for jump tables now.
102 shortcutStatic _ other_static
103         = other_static
104
105 shortBlockId :: (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
106 shortBlockId fn blockid@(BlockId uq) =
107    case fn blockid of
108       Nothing -> mkAsmTempLabel uq
109       Just (DestBlockId blockid')  -> shortBlockId fn blockid'
110       Just (DestImm (ImmCLbl lbl)) -> lbl
111       _other -> panic "shortBlockId"
112
113
114 regDotColor :: Reg -> SDoc
115 regDotColor reg
116  = case regClass reg of
117         RcInteger       -> text "blue"
118         RcFloat         -> text "red"
119         RcDouble        -> text "green"
120
121
122
123 data JumpDest = DestBlockId BlockId | DestImm Imm
124
125 canShortcut :: Instr -> Maybe JumpDest
126 canShortcut _ = Nothing
127
128 shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
129 shortcutJump _ other = other