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