438deba00a3b3b155ed47e666fd415456f84ebdb
[ghc.git] / compiler / nativeGen / SPARC / CodeGen / Gen64.hs
1 -- | Evaluation of 64 bit values on 32 bit platforms.
2 module SPARC.CodeGen.Gen64 (
3 assignMem_I64Code,
4 assignReg_I64Code,
5 iselExpr64
6 )
7
8 where
9
10 import {-# SOURCE #-} SPARC.CodeGen.Gen32
11 import SPARC.CodeGen.Base
12 import SPARC.CodeGen.Amode
13 import SPARC.Regs
14 import SPARC.AddrMode
15 import SPARC.Imm
16 import SPARC.Instr
17 import SPARC.Ppr()
18 import NCGMonad
19 import Instruction
20 import Size
21 import Reg
22
23 import Cmm
24
25 import DynFlags
26 import OrdList
27 import Outputable
28
29 -- | Code to assign a 64 bit value to memory.
30 assignMem_I64Code
31 :: CmmExpr -- ^ expr producing the destination address
32 -> CmmExpr -- ^ expr producing the source value.
33 -> NatM InstrBlock
34
35 assignMem_I64Code addrTree valueTree
36 = do
37 ChildCode64 vcode rlo <- iselExpr64 valueTree
38
39 (src, acode) <- getSomeReg addrTree
40 let
41 rhi = getHiVRegFromLo rlo
42
43 -- Big-endian store
44 mov_hi = ST II32 rhi (AddrRegImm src (ImmInt 0))
45 mov_lo = ST II32 rlo (AddrRegImm src (ImmInt 4))
46
47 code = vcode `appOL` acode `snocOL` mov_hi `snocOL` mov_lo
48
49 {- pprTrace "assignMem_I64Code"
50 (vcat [ text "addrTree: " <+> ppr addrTree
51 , text "valueTree: " <+> ppr valueTree
52 , text "vcode:"
53 , vcat $ map ppr $ fromOL vcode
54 , text ""
55 , text "acode:"
56 , vcat $ map ppr $ fromOL acode ])
57 $ -}
58 return code
59
60
61 -- | Code to assign a 64 bit value to a register.
62 assignReg_I64Code
63 :: CmmReg -- ^ the destination register
64 -> CmmExpr -- ^ expr producing the source value
65 -> NatM InstrBlock
66
67 assignReg_I64Code (CmmLocal (LocalReg u_dst pk)) valueTree
68 = do
69 ChildCode64 vcode r_src_lo <- iselExpr64 valueTree
70 let
71 r_dst_lo = RegVirtual $ mkVirtualReg u_dst (cmmTypeSize pk)
72 r_dst_hi = getHiVRegFromLo r_dst_lo
73 r_src_hi = getHiVRegFromLo r_src_lo
74 mov_lo = mkMOV r_src_lo r_dst_lo
75 mov_hi = mkMOV r_src_hi r_dst_hi
76 mkMOV sreg dreg = OR False g0 (RIReg sreg) dreg
77
78 return (vcode `snocOL` mov_hi `snocOL` mov_lo)
79
80 assignReg_I64Code _ _
81 = panic "assignReg_I64Code(sparc): invalid lvalue"
82
83
84
85
86 -- | Get the value of an expression into a 64 bit register.
87
88 iselExpr64 :: CmmExpr -> NatM ChildCode64
89
90 -- Load a 64 bit word
91 iselExpr64 (CmmLoad addrTree ty)
92 | isWord64 ty
93 = do Amode amode addr_code <- getAmode addrTree
94 let result
95
96 | AddrRegReg r1 r2 <- amode
97 = do rlo <- getNewRegNat II32
98 tmp <- getNewRegNat II32
99 let rhi = getHiVRegFromLo rlo
100
101 return $ ChildCode64
102 ( addr_code
103 `appOL` toOL
104 [ ADD False False r1 (RIReg r2) tmp
105 , LD II32 (AddrRegImm tmp (ImmInt 0)) rhi
106 , LD II32 (AddrRegImm tmp (ImmInt 4)) rlo ])
107 rlo
108
109 | AddrRegImm r1 (ImmInt i) <- amode
110 = do rlo <- getNewRegNat II32
111 let rhi = getHiVRegFromLo rlo
112
113 return $ ChildCode64
114 ( addr_code
115 `appOL` toOL
116 [ LD II32 (AddrRegImm r1 (ImmInt $ 0 + i)) rhi
117 , LD II32 (AddrRegImm r1 (ImmInt $ 4 + i)) rlo ])
118 rlo
119
120 | otherwise
121 = panic "SPARC.CodeGen.Gen64: no match"
122
123 result
124
125
126 -- Add a literal to a 64 bit integer
127 iselExpr64 (CmmMachOp (MO_Add _) [e1, CmmLit (CmmInt i _)])
128 = do ChildCode64 code1 r1_lo <- iselExpr64 e1
129 let r1_hi = getHiVRegFromLo r1_lo
130
131 r_dst_lo <- getNewRegNat II32
132 let r_dst_hi = getHiVRegFromLo r_dst_lo
133
134 let code = code1
135 `appOL` toOL
136 [ ADD False True r1_lo (RIImm (ImmInteger i)) r_dst_lo
137 , ADD True False r1_hi (RIReg g0) r_dst_hi ]
138
139 return $ ChildCode64 code r_dst_lo
140
141
142 -- Addition of II64
143 iselExpr64 (CmmMachOp (MO_Add _) [e1, e2])
144 = do ChildCode64 code1 r1_lo <- iselExpr64 e1
145 let r1_hi = getHiVRegFromLo r1_lo
146
147 ChildCode64 code2 r2_lo <- iselExpr64 e2
148 let r2_hi = getHiVRegFromLo r2_lo
149
150 r_dst_lo <- getNewRegNat II32
151 let r_dst_hi = getHiVRegFromLo r_dst_lo
152
153 let code = code1
154 `appOL` code2
155 `appOL` toOL
156 [ ADD False True r1_lo (RIReg r2_lo) r_dst_lo
157 , ADD True False r1_hi (RIReg r2_hi) r_dst_hi ]
158
159 return $ ChildCode64 code r_dst_lo
160
161
162 iselExpr64 (CmmReg (CmmLocal (LocalReg uq ty)))
163 | isWord64 ty
164 = do
165 r_dst_lo <- getNewRegNat II32
166 let r_dst_hi = getHiVRegFromLo r_dst_lo
167 r_src_lo = RegVirtual $ mkVirtualReg uq II32
168 r_src_hi = getHiVRegFromLo r_src_lo
169 mov_lo = mkMOV r_src_lo r_dst_lo
170 mov_hi = mkMOV r_src_hi r_dst_hi
171 mkMOV sreg dreg = OR False g0 (RIReg sreg) dreg
172 return (
173 ChildCode64 (toOL [mov_hi, mov_lo]) r_dst_lo
174 )
175
176 -- Convert something into II64
177 iselExpr64 (CmmMachOp (MO_UU_Conv _ W64) [expr])
178 = do
179 r_dst_lo <- getNewRegNat II32
180 let r_dst_hi = getHiVRegFromLo r_dst_lo
181
182 -- compute expr and load it into r_dst_lo
183 (a_reg, a_code) <- getSomeReg expr
184
185 dflags <- getDynFlags
186 let platform = targetPlatform dflags
187 code = a_code
188 `appOL` toOL
189 [ mkRegRegMoveInstr platform g0 r_dst_hi -- clear high 32 bits
190 , mkRegRegMoveInstr platform a_reg r_dst_lo ]
191
192 return $ ChildCode64 code r_dst_lo
193
194
195 iselExpr64 expr
196 = pprPanic "iselExpr64(sparc)" (ppr expr)
197
198
199