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