    module GHC.CmmToAsm.SPARC.CodeGen.Amode (
            getAmode
    )

    where

    import GHC.Prelude

    import {-# SOURCE #-} GHC.CmmToAsm.SPARC.CodeGen.Gen32
    import GHC.CmmToAsm.SPARC.CodeGen.Base
    import GHC.CmmToAsm.SPARC.AddrMode
    import GHC.CmmToAsm.SPARC.Imm
    import GHC.CmmToAsm.SPARC.Instr
    import GHC.CmmToAsm.SPARC.Regs
    import GHC.CmmToAsm.SPARC.Base
    import GHC.CmmToAsm.Monad
    import GHC.CmmToAsm.Format

    import GHC.Cmm

    import GHC.Data.OrdList

    -- | Generate code to reference a memory address.
    getAmode
            :: CmmExpr      -- ^ expr producing an address
            -> NatM Amode

    getAmode :: CmmExpr -> NatM Amode
    getAmode tree :: CmmExpr
    tree@(CmmRegOff CmmReg
    _ Int
    _)
        = do Platform
    platform <- NatM Platform
    getPlatform
             CmmExpr -> NatM Amode
    getAmode (Platform -> CmmExpr -> CmmExpr
    mangleIndexTree Platform
    platform CmmExpr
    tree)

    getAmode (CmmMachOp (MO_Sub Width
    _) [CmmExpr
    x, CmmLit (CmmInt Integer
    i Width
    _)])
      | forall a. Integral a => a -> Bool
    fits13Bits (-Integer
    i)
      = do
           (Reg
    reg, InstrBlock
    code) <- CmmExpr -> NatM (Reg, InstrBlock)
    getSomeReg CmmExpr
    x
           let
             off :: Imm
    off  = Int -> Imm
    ImmInt (-(forall a. Num a => Integer -> a
    fromInteger Integer
    i))
           forall (m :: * -> *) a. Monad m => a -> m a
    return (AddrMode -> InstrBlock -> Amode
    Amode (Reg -> Imm -> AddrMode
    AddrRegImm Reg
    reg Imm
    off) InstrBlock
    code)

    getAmode (CmmMachOp (MO_Add Width
    _) [CmmExpr
    x, CmmLit (CmmInt Integer
    i Width
    _)])
      | forall a. Integral a => a -> Bool
    fits13Bits Integer
    i
      = do
           (Reg
    reg, InstrBlock
    code) <- CmmExpr -> NatM (Reg, InstrBlock)
    getSomeReg CmmExpr
    x
           let
             off :: Imm
    off  = Int -> Imm
    ImmInt (forall a. Num a => Integer -> a
    fromInteger Integer
    i)
           forall (m :: * -> *) a. Monad m => a -> m a
    return (AddrMode -> InstrBlock -> Amode
    Amode (Reg -> Imm -> AddrMode
    AddrRegImm Reg
    reg Imm
    off) InstrBlock
    code)

    getAmode (CmmMachOp (MO_Add Width
    _) [CmmExpr
    x, CmmExpr
    y])
      = do
        (Reg
    regX, InstrBlock
    codeX) <- CmmExpr -> NatM (Reg, InstrBlock)
    getSomeReg CmmExpr
    x
        (Reg
    regY, InstrBlock
    codeY) <- CmmExpr -> NatM (Reg, InstrBlock)
    getSomeReg CmmExpr
    y
        let
            code :: InstrBlock
    code = InstrBlock
    codeX forall a. OrdList a -> OrdList a -> OrdList a
    `appOL` InstrBlock
    codeY
        forall (m :: * -> *) a. Monad m => a -> m a
    return (AddrMode -> InstrBlock -> Amode
    Amode (Reg -> Reg -> AddrMode
    AddrRegReg Reg
    regX Reg
    regY) InstrBlock
    code)

    getAmode (CmmLit CmmLit
    lit)
      = do
            let imm__2 :: Imm
    imm__2      = CmmLit -> Imm
    litToImm CmmLit
    lit
            Reg
    tmp1    <- Format -> NatM Reg
    getNewRegNat Format
    II32
            Reg
    tmp2    <- Format -> NatM Reg
    getNewRegNat Format
    II32

            let code :: InstrBlock
    code = forall a. [a] -> OrdList a
    toOL [ Imm -> Reg -> Instr
    SETHI (Imm -> Imm
    HI Imm
    imm__2) Reg
    tmp1
                            , Bool -> Reg -> RI -> Reg -> Instr
    OR    Bool
    False Reg
    tmp1 (Imm -> RI
    RIImm (Imm -> Imm
    LO Imm
    imm__2)) Reg
    tmp2]

            forall (m :: * -> *) a. Monad m => a -> m a
    return (AddrMode -> InstrBlock -> Amode
    Amode (Reg -> Reg -> AddrMode
    AddrRegReg Reg
    tmp2 Reg
    g0) InstrBlock
    code)

    getAmode CmmExpr
    other
      = do
           (Reg
    reg, InstrBlock
    code) <- CmmExpr -> NatM (Reg, InstrBlock)
    getSomeReg CmmExpr
    other
           let
                off :: Imm
    off  = Int -> Imm
    ImmInt Int
    0
           forall (m :: * -> *) a. Monad m => a -> m a
    return (AddrMode -> InstrBlock -> Amode
    Amode (Reg -> Imm -> AddrMode
    AddrRegImm Reg
    reg Imm
    off) InstrBlock
    code)