never executed always true always false
1 -- | Evaluation of 64 bit values on 32 bit platforms.
2 module GHC.CmmToAsm.SPARC.CodeGen.Gen64 (
3 assignMem_I64Code,
4 assignReg_I64Code,
5 iselExpr64
6 )
7
8 where
9
10 import GHC.Prelude
11
12 import {-# SOURCE #-} GHC.CmmToAsm.SPARC.CodeGen.Gen32
13 import GHC.CmmToAsm.SPARC.CodeGen.Base
14 import GHC.CmmToAsm.SPARC.CodeGen.Amode
15 import GHC.CmmToAsm.SPARC.Regs
16 import GHC.CmmToAsm.SPARC.AddrMode
17 import GHC.CmmToAsm.SPARC.Imm
18 import GHC.CmmToAsm.SPARC.Instr
19 import GHC.CmmToAsm.Monad
20 import GHC.CmmToAsm.Format
21 import GHC.Platform.Reg
22
23 import GHC.Cmm
24
25 import GHC.Data.OrdList
26 import GHC.Utils.Outputable
27 import GHC.Utils.Panic
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 (cmmTypeFormat 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 platform <- getPlatform
186 let code = a_code
187 `appOL` toOL
188 [ mkRegRegMoveInstr platform g0 r_dst_hi -- clear high 32 bits
189 , mkRegRegMoveInstr platform a_reg r_dst_lo ]
190
191 return $ ChildCode64 code r_dst_lo
192
193 -- only W32 supported for now
194 iselExpr64 (CmmMachOp (MO_SS_Conv W32 W64) [expr])
195 = do
196 r_dst_lo <- getNewRegNat II32
197 let r_dst_hi = getHiVRegFromLo r_dst_lo
198
199 -- compute expr and load it into r_dst_lo
200 (a_reg, a_code) <- getSomeReg expr
201
202 platform <- getPlatform
203 let code = a_code
204 `appOL` toOL
205 [ SRA a_reg (RIImm (ImmInt 31)) r_dst_hi
206 , mkRegRegMoveInstr platform a_reg r_dst_lo ]
207
208 return $ ChildCode64 code r_dst_lo
209
210
211 iselExpr64 expr
212 = do
213 platform <- getPlatform
214 pprPanic "iselExpr64(sparc)" (pdoc platform expr)