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 NCGMonad
import Instruction
import Format
import Reg
import Cmm
import DynFlags
import OrdList
import Outputable
assignMem_I64Code
:: CmmExpr
-> CmmExpr
-> NatM InstrBlock
assignMem_I64Code addrTree valueTree
= do
ChildCode64 vcode rlo <- iselExpr64 valueTree
(src, acode) <- getSomeReg addrTree
let
rhi = getHiVRegFromLo rlo
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
return code
assignReg_I64Code
:: CmmReg
-> CmmExpr
-> 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"
iselExpr64 :: CmmExpr -> NatM ChildCode64
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
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
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
)
iselExpr64 (CmmMachOp (MO_UU_Conv _ W64) [expr])
= do
r_dst_lo <- getNewRegNat II32
let r_dst_hi = getHiVRegFromLo 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
, mkRegRegMoveInstr platform a_reg r_dst_lo ]
return $ ChildCode64 code r_dst_lo
iselExpr64 (CmmMachOp (MO_SS_Conv W32 W64) [expr])
= do
r_dst_lo <- getNewRegNat II32
let r_dst_hi = getHiVRegFromLo 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)