module SPARC.CodeGen.Amode (
        getAmode
)

where

import GhcPrelude

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

import Cmm

import 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 DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
         CmmExpr -> NatM Amode
getAmode (DynFlags -> CmmExpr -> CmmExpr
mangleIndexTree DynFlags
dflags CmmExpr
tree)

getAmode (CmmMachOp (MO_Sub Width
_) [CmmExpr
x, CmmLit (CmmInt Integer
i Width
_)])
  | Integer -> Bool
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 (-(Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
i))
       Amode -> NatM Amode
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
_)])
  | Integer -> Bool
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 (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
i)
       Amode -> NatM Amode
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 InstrBlock -> InstrBlock -> InstrBlock
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` InstrBlock
codeY
    Amode -> NatM Amode
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 = [Instr] -> InstrBlock
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]

        Amode -> NatM Amode
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
       Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> InstrBlock -> Amode
Amode (Reg -> Imm -> AddrMode
AddrRegImm Reg
reg Imm
off) InstrBlock
code)