-- | 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)