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