{-# LANGUAGE CPP, GADTs, NondecreasingIndentation #-}
{-# OPTIONS_GHC -fmax-pmcheck-iterations=10000000 #-}
module X86.CodeGen (
cmmTopCodeGen,
generateJumpTableForInstr,
extractUnwindPoints,
invertCondBranches,
InstrBlock
)
where
#include "HsVersions.h"
#include "nativeGen/NCG.h"
#include "MachDeps.h"
import GhcPrelude
import X86.Instr
import X86.Cond
import X86.Regs
import X86.RegInfo
import X86.Ppr()
import CodeGen.Platform
import CPrim
import Debug ( DebugBlock(..), UnwindPoint(..), UnwindTable
, UnwindExpr(UwReg), toUnwindExpr )
import Instruction
import PIC
import NCGMonad ( NatM, getNewRegNat, getNewLabelNat, setDeltaNat
, getDeltaNat, getBlockIdNat, getPicBaseNat, getNewRegPairNat
, getPicBaseMaybeNat, getDebugBlock, getFileId
, addImmediateSuccessorNat, updateCfgNat)
import CFG
import Format
import Reg
import Platform
import BasicTypes
import BlockId
import Module ( primUnitId )
import PprCmm ()
import CmmUtils
import CmmSwitch
import Cmm
import Hoopl.Block
import Hoopl.Collections
import Hoopl.Graph
import Hoopl.Label
import CLabel
import CoreSyn ( Tickish(..) )
import SrcLoc ( srcSpanFile, srcSpanStartLine, srcSpanStartCol )
import ForeignCall ( CCallConv(..) )
import OrdList
import Outputable
import FastString
import DynFlags
import Util
import UniqSupply ( getUniqueM )
import Control.Monad
import Data.Bits
import Data.Foldable (fold)
import Data.Int
import Data.Maybe
import Data.Word
import qualified Data.Map as M
is32BitPlatform :: NatM Bool
is32BitPlatform :: NatM Bool
is32BitPlatform = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool -> NatM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> NatM Bool) -> Bool -> NatM Bool
forall a b. (a -> b) -> a -> b
$ Platform -> Bool
target32Bit (DynFlags -> Platform
targetPlatform DynFlags
dflags)
sse2Enabled :: NatM Bool
sse2Enabled :: NatM Bool
sse2Enabled = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool -> NatM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags -> Bool
isSse2Enabled DynFlags
dflags)
sse4_2Enabled :: NatM Bool
sse4_2Enabled :: NatM Bool
sse4_2Enabled = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool -> NatM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags -> Bool
isSse4_2Enabled DynFlags
dflags)
if_sse2 :: NatM a -> NatM a -> NatM a
if_sse2 :: NatM a -> NatM a -> NatM a
if_sse2 sse2 :: NatM a
sse2 x87 :: NatM a
x87 = do
Bool
b <- NatM Bool
sse2Enabled
if Bool
b then NatM a
sse2 else NatM a
x87
cmmTopCodeGen
:: RawCmmDecl
-> NatM [NatCmmDecl (Alignment, CmmStatics) Instr]
cmmTopCodeGen :: RawCmmDecl -> NatM [NatCmmDecl (Alignment, CmmStatics) Instr]
cmmTopCodeGen (CmmProc info :: LabelMap CmmStatics
info lab :: CLabel
lab live :: [GlobalReg]
live graph :: CmmGraph
graph) = do
let blocks :: [CmmBlock]
blocks = CmmGraph -> [CmmBlock]
toBlockListEntryFirst CmmGraph
graph
(nat_blocks :: [[NatBasicBlock Instr]]
nat_blocks,statics :: [[NatCmmDecl (Alignment, CmmStatics) Instr]]
statics) <- (CmmBlock
-> NatM
([NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr]))
-> [CmmBlock]
-> NatM
([[NatBasicBlock Instr]],
[[NatCmmDecl (Alignment, CmmStatics) Instr]])
forall (m :: * -> *) a b c.
Applicative m =>
(a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM CmmBlock
-> NatM
([NatBasicBlock Instr], [NatCmmDecl (Alignment, CmmStatics) Instr])
basicBlockCodeGen [CmmBlock]
blocks
Maybe Reg
picBaseMb <- NatM (Maybe Reg)
getPicBaseMaybeNat
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let proc :: NatCmmDecl (Alignment, CmmStatics) Instr
proc = LabelMap CmmStatics
-> CLabel
-> [GlobalReg]
-> ListGraph Instr
-> NatCmmDecl (Alignment, CmmStatics) Instr
forall d h g. h -> CLabel -> [GlobalReg] -> g -> GenCmmDecl d h g
CmmProc LabelMap CmmStatics
info CLabel
lab [GlobalReg]
live ([NatBasicBlock Instr] -> ListGraph Instr
forall i. [GenBasicBlock i] -> ListGraph i
ListGraph ([NatBasicBlock Instr] -> ListGraph Instr)
-> [NatBasicBlock Instr] -> ListGraph Instr
forall a b. (a -> b) -> a -> b
$ [[NatBasicBlock Instr]] -> [NatBasicBlock Instr]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[NatBasicBlock Instr]]
nat_blocks)
tops :: [NatCmmDecl (Alignment, CmmStatics) Instr]
tops = NatCmmDecl (Alignment, CmmStatics) Instr
proc NatCmmDecl (Alignment, CmmStatics) Instr
-> [NatCmmDecl (Alignment, CmmStatics) Instr]
-> [NatCmmDecl (Alignment, CmmStatics) Instr]
forall a. a -> [a] -> [a]
: [[NatCmmDecl (Alignment, CmmStatics) Instr]]
-> [NatCmmDecl (Alignment, CmmStatics) Instr]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[NatCmmDecl (Alignment, CmmStatics) Instr]]
statics
os :: OS
os = Platform -> OS
platformOS (Platform -> OS) -> Platform -> OS
forall a b. (a -> b) -> a -> b
$ DynFlags -> Platform
targetPlatform DynFlags
dflags
case Maybe Reg
picBaseMb of
Just picBase :: Reg
picBase -> Arch
-> OS
-> Reg
-> [NatCmmDecl (Alignment, CmmStatics) Instr]
-> NatM [NatCmmDecl (Alignment, CmmStatics) Instr]
initializePicBase_x86 Arch
ArchX86 OS
os Reg
picBase [NatCmmDecl (Alignment, CmmStatics) Instr]
tops
Nothing -> [NatCmmDecl (Alignment, CmmStatics) Instr]
-> NatM [NatCmmDecl (Alignment, CmmStatics) Instr]
forall (m :: * -> *) a. Monad m => a -> m a
return [NatCmmDecl (Alignment, CmmStatics) Instr]
tops
cmmTopCodeGen (CmmData sec :: Section
sec dat :: CmmStatics
dat) = do
[NatCmmDecl (Alignment, CmmStatics) Instr]
-> NatM [NatCmmDecl (Alignment, CmmStatics) Instr]
forall (m :: * -> *) a. Monad m => a -> m a
return [Section
-> (Alignment, CmmStatics)
-> NatCmmDecl (Alignment, CmmStatics) Instr
forall d h g. Section -> d -> GenCmmDecl d h g
CmmData Section
sec (1, CmmStatics
dat)]
basicBlockCodeGen
:: CmmBlock
-> NatM ( [NatBasicBlock Instr]
, [NatCmmDecl (Alignment, CmmStatics) Instr])
basicBlockCodeGen :: CmmBlock
-> NatM
([NatBasicBlock Instr], [NatCmmDecl (Alignment, CmmStatics) Instr])
basicBlockCodeGen block :: CmmBlock
block = do
let (_, nodes :: Block CmmNode O O
nodes, tail :: CmmNode O C
tail) = CmmBlock -> (CmmNode C O, Block CmmNode O O, CmmNode O C)
forall (n :: * -> * -> *).
Block n C C -> (n C O, Block n O O, n O C)
blockSplit CmmBlock
block
id :: Label
id = CmmBlock -> Label
forall (thing :: * -> * -> *) x.
NonLocal thing =>
thing C x -> Label
entryLabel CmmBlock
block
stmts :: [CmmNode O O]
stmts = Block CmmNode O O -> [CmmNode O O]
forall (n :: * -> * -> *). Block n O O -> [n O O]
blockToList Block CmmNode O O
nodes
Maybe DebugBlock
dbg <- Label -> NatM (Maybe DebugBlock)
getDebugBlock (CmmBlock -> Label
forall (thing :: * -> * -> *) x.
NonLocal thing =>
thing C x -> Label
entryLabel CmmBlock
block)
OrdList Instr
loc_instrs <- case DebugBlock -> Maybe CmmTickish
dblSourceTick (DebugBlock -> Maybe CmmTickish)
-> Maybe DebugBlock -> Maybe CmmTickish
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe DebugBlock
dbg of
Just (SourceNote span :: RealSrcSpan
span name :: String
name)
-> do Alignment
fileId <- FastString -> NatM Alignment
getFileId (RealSrcSpan -> FastString
srcSpanFile RealSrcSpan
span)
let line :: Alignment
line = RealSrcSpan -> Alignment
srcSpanStartLine RealSrcSpan
span; col :: Alignment
col = RealSrcSpan -> Alignment
srcSpanStartCol RealSrcSpan
span
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ Alignment -> Alignment -> Alignment -> String -> Instr
LOCATION Alignment
fileId Alignment
line Alignment
col String
name
_ -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
OrdList Instr
mid_instrs <- Label -> [CmmNode O O] -> NatM (OrdList Instr)
forall e x. Label -> [CmmNode e x] -> NatM (OrdList Instr)
stmtsToInstrs Label
id [CmmNode O O]
stmts
OrdList Instr
tail_instrs <- Label -> CmmNode O C -> NatM (OrdList Instr)
forall e x. Label -> CmmNode e x -> NatM (OrdList Instr)
stmtToInstrs Label
id CmmNode O C
tail
let instrs :: OrdList Instr
instrs = OrdList Instr
loc_instrs OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
mid_instrs OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
tail_instrs
OrdList Instr
instrs' <- OrdList (OrdList Instr) -> OrdList Instr
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (OrdList (OrdList Instr) -> OrdList Instr)
-> NatM (OrdList (OrdList Instr)) -> NatM (OrdList Instr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList (OrdList Instr))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Instr -> NatM (OrdList Instr)
addSpUnwindings OrdList Instr
instrs
let
(top :: [Instr]
top,other_blocks :: [NatBasicBlock Instr]
other_blocks,statics :: [NatCmmDecl (Alignment, CmmStatics) Instr]
statics) = (Instr
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr])
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr]))
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr])
-> OrdList Instr
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr])
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL Instr
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr])
-> ([Instr], [NatBasicBlock Instr],
[NatCmmDecl (Alignment, CmmStatics) Instr])
forall h g.
Instr
-> ([Instr], [NatBasicBlock Instr],
[GenCmmDecl (Alignment, CmmStatics) h g])
-> ([Instr], [NatBasicBlock Instr],
[GenCmmDecl (Alignment, CmmStatics) h g])
mkBlocks ([],[],[]) OrdList Instr
instrs'
mkBlocks :: Instr
-> ([Instr], [NatBasicBlock Instr],
[GenCmmDecl (Alignment, CmmStatics) h g])
-> ([Instr], [NatBasicBlock Instr],
[GenCmmDecl (Alignment, CmmStatics) h g])
mkBlocks (NEWBLOCK id :: Label
id) (instrs :: [Instr]
instrs,blocks :: [NatBasicBlock Instr]
blocks,statics :: [GenCmmDecl (Alignment, CmmStatics) h g]
statics)
= ([], Label -> [Instr] -> NatBasicBlock Instr
forall i. Label -> [i] -> GenBasicBlock i
BasicBlock Label
id [Instr]
instrs NatBasicBlock Instr
-> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
forall a. a -> [a] -> [a]
: [NatBasicBlock Instr]
blocks, [GenCmmDecl (Alignment, CmmStatics) h g]
statics)
mkBlocks (LDATA sec :: Section
sec dat :: (Alignment, CmmStatics)
dat) (instrs :: [Instr]
instrs,blocks :: [NatBasicBlock Instr]
blocks,statics :: [GenCmmDecl (Alignment, CmmStatics) h g]
statics)
= ([Instr]
instrs, [NatBasicBlock Instr]
blocks, Section
-> (Alignment, CmmStatics)
-> GenCmmDecl (Alignment, CmmStatics) h g
forall d h g. Section -> d -> GenCmmDecl d h g
CmmData Section
sec (Alignment, CmmStatics)
datGenCmmDecl (Alignment, CmmStatics) h g
-> [GenCmmDecl (Alignment, CmmStatics) h g]
-> [GenCmmDecl (Alignment, CmmStatics) h g]
forall a. a -> [a] -> [a]
:[GenCmmDecl (Alignment, CmmStatics) h g]
statics)
mkBlocks instr :: Instr
instr (instrs :: [Instr]
instrs,blocks :: [NatBasicBlock Instr]
blocks,statics :: [GenCmmDecl (Alignment, CmmStatics) h g]
statics)
= (Instr
instrInstr -> [Instr] -> [Instr]
forall a. a -> [a] -> [a]
:[Instr]
instrs, [NatBasicBlock Instr]
blocks, [GenCmmDecl (Alignment, CmmStatics) h g]
statics)
([NatBasicBlock Instr], [NatCmmDecl (Alignment, CmmStatics) Instr])
-> NatM
([NatBasicBlock Instr], [NatCmmDecl (Alignment, CmmStatics) Instr])
forall (m :: * -> *) a. Monad m => a -> m a
return (Label -> [Instr] -> NatBasicBlock Instr
forall i. Label -> [i] -> GenBasicBlock i
BasicBlock Label
id [Instr]
top NatBasicBlock Instr
-> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
forall a. a -> [a] -> [a]
: [NatBasicBlock Instr]
other_blocks, [NatCmmDecl (Alignment, CmmStatics) Instr]
statics)
addSpUnwindings :: Instr -> NatM (OrdList Instr)
addSpUnwindings :: Instr -> NatM (OrdList Instr)
addSpUnwindings instr :: Instr
instr@(DELTA d :: Alignment
d) = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
if DynFlags -> Alignment
debugLevel DynFlags
dflags Alignment -> Alignment -> Bool
forall a. Ord a => a -> a -> Bool
>= 1
then do CLabel
lbl <- Unique -> CLabel
forall a. Uniquable a => a -> CLabel
mkAsmTempLabel (Unique -> CLabel) -> NatM Unique -> NatM CLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NatM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
let unwind :: Map GlobalReg (Maybe UnwindExpr)
unwind = GlobalReg -> Maybe UnwindExpr -> Map GlobalReg (Maybe UnwindExpr)
forall k a. k -> a -> Map k a
M.singleton GlobalReg
MachSp (UnwindExpr -> Maybe UnwindExpr
forall a. a -> Maybe a
Just (UnwindExpr -> Maybe UnwindExpr) -> UnwindExpr -> Maybe UnwindExpr
forall a b. (a -> b) -> a -> b
$ GlobalReg -> Alignment -> UnwindExpr
UwReg GlobalReg
MachSp (Alignment -> UnwindExpr) -> Alignment -> UnwindExpr
forall a b. (a -> b) -> a -> b
$ Alignment -> Alignment
forall a. Num a => a -> a
negate Alignment
d)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Instr
instr, CLabel -> Map GlobalReg (Maybe UnwindExpr) -> Instr
UNWIND CLabel
lbl Map GlobalReg (Maybe UnwindExpr)
unwind ]
else OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL Instr
instr)
addSpUnwindings instr :: Instr
instr = OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL Instr
instr
stmtsToInstrs :: BlockId -> [CmmNode e x] -> NatM InstrBlock
stmtsToInstrs :: Label -> [CmmNode e x] -> NatM (OrdList Instr)
stmtsToInstrs bid :: Label
bid stmts :: [CmmNode e x]
stmts
= do [OrdList Instr]
instrss <- (CmmNode e x -> NatM (OrdList Instr))
-> [CmmNode e x] -> NatM [OrdList Instr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Label -> CmmNode e x -> NatM (OrdList Instr)
forall e x. Label -> CmmNode e x -> NatM (OrdList Instr)
stmtToInstrs Label
bid) [CmmNode e x]
stmts
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([OrdList Instr] -> OrdList Instr
forall a. [OrdList a] -> OrdList a
concatOL [OrdList Instr]
instrss)
stmtToInstrs :: BlockId -> CmmNode e x -> NatM InstrBlock
stmtToInstrs :: Label -> CmmNode e x -> NatM (OrdList Instr)
stmtToInstrs bid :: Label
bid stmt :: CmmNode e x
stmt = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool
is32Bit <- NatM Bool
is32BitPlatform
case CmmNode e x
stmt of
CmmComment s :: FastString
s -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (FastString -> Instr
COMMENT FastString
s))
CmmTick {} -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
CmmUnwind regs :: [(GlobalReg, Maybe CmmExpr)]
regs -> do
let to_unwind_entry :: (GlobalReg, Maybe CmmExpr) -> UnwindTable
to_unwind_entry :: (GlobalReg, Maybe CmmExpr) -> Map GlobalReg (Maybe UnwindExpr)
to_unwind_entry (reg :: GlobalReg
reg, expr :: Maybe CmmExpr
expr) = GlobalReg -> Maybe UnwindExpr -> Map GlobalReg (Maybe UnwindExpr)
forall k a. k -> a -> Map k a
M.singleton GlobalReg
reg ((CmmExpr -> UnwindExpr) -> Maybe CmmExpr -> Maybe UnwindExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CmmExpr -> UnwindExpr
toUnwindExpr Maybe CmmExpr
expr)
case ((GlobalReg, Maybe CmmExpr) -> Map GlobalReg (Maybe UnwindExpr))
-> [(GlobalReg, Maybe CmmExpr)] -> Map GlobalReg (Maybe UnwindExpr)
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (GlobalReg, Maybe CmmExpr) -> Map GlobalReg (Maybe UnwindExpr)
to_unwind_entry [(GlobalReg, Maybe CmmExpr)]
regs of
tbl :: Map GlobalReg (Maybe UnwindExpr)
tbl | Map GlobalReg (Maybe UnwindExpr) -> Bool
forall k a. Map k a -> Bool
M.null Map GlobalReg (Maybe UnwindExpr)
tbl -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
| Bool
otherwise -> do
CLabel
lbl <- Unique -> CLabel
forall a. Uniquable a => a -> CLabel
mkAsmTempLabel (Unique -> CLabel) -> NatM Unique -> NatM CLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NatM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ CLabel -> Map GlobalReg (Maybe UnwindExpr) -> Instr
UNWIND CLabel
lbl Map GlobalReg (Maybe UnwindExpr)
tbl
CmmAssign reg :: CmmReg
reg src :: CmmExpr
src
| CmmType -> Bool
isFloatType CmmType
ty -> Format -> CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_FltCode Format
format CmmReg
reg CmmExpr
src
| Bool
is32Bit Bool -> Bool -> Bool
&& CmmType -> Bool
isWord64 CmmType
ty -> CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_I64Code CmmReg
reg CmmExpr
src
| Bool
otherwise -> Format -> CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_IntCode Format
format CmmReg
reg CmmExpr
src
where ty :: CmmType
ty = DynFlags -> CmmReg -> CmmType
cmmRegType DynFlags
dflags CmmReg
reg
format :: Format
format = CmmType -> Format
cmmTypeFormat CmmType
ty
CmmStore addr :: CmmExpr
addr src :: CmmExpr
src
| CmmType -> Bool
isFloatType CmmType
ty -> Format -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_FltCode Format
format CmmExpr
addr CmmExpr
src
| Bool
is32Bit Bool -> Bool -> Bool
&& CmmType -> Bool
isWord64 CmmType
ty -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_I64Code CmmExpr
addr CmmExpr
src
| Bool
otherwise -> Format -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_IntCode Format
format CmmExpr
addr CmmExpr
src
where ty :: CmmType
ty = DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
src
format :: Format
format = CmmType -> Format
cmmTypeFormat CmmType
ty
CmmUnsafeForeignCall target :: ForeignTarget
target result_regs :: [CmmFormal]
result_regs args :: [CmmExpr]
args
-> DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
result_regs [CmmExpr]
args Label
bid
CmmBranch id :: Label
id -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Label -> OrdList Instr
genBranch Label
id
CmmCondBranch arg :: CmmExpr
arg true :: Label
true false :: Label
false _ -> Label -> Label -> Label -> CmmExpr -> NatM (OrdList Instr)
genCondBranch Label
bid Label
true Label
false CmmExpr
arg
CmmSwitch arg :: CmmExpr
arg ids :: SwitchTargets
ids -> do DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
DynFlags -> CmmExpr -> SwitchTargets -> NatM (OrdList Instr)
genSwitch DynFlags
dflags CmmExpr
arg SwitchTargets
ids
CmmCall { cml_target :: CmmNode O C -> CmmExpr
cml_target = CmmExpr
arg
, cml_args_regs :: CmmNode O C -> [GlobalReg]
cml_args_regs = [GlobalReg]
gregs } -> do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
CmmExpr -> [Reg] -> NatM (OrdList Instr)
genJump CmmExpr
arg (DynFlags -> [GlobalReg] -> [Reg]
jumpRegs DynFlags
dflags [GlobalReg]
gregs)
_ ->
String -> NatM (OrdList Instr)
forall a. String -> a
panic "stmtToInstrs: statement should have been cps'd away"
jumpRegs :: DynFlags -> [GlobalReg] -> [Reg]
jumpRegs :: DynFlags -> [GlobalReg] -> [Reg]
jumpRegs dflags :: DynFlags
dflags gregs :: [GlobalReg]
gregs = [ RealReg -> Reg
RegReal RealReg
r | Just r :: RealReg
r <- (GlobalReg -> Maybe RealReg) -> [GlobalReg] -> [Maybe RealReg]
forall a b. (a -> b) -> [a] -> [b]
map (Platform -> GlobalReg -> Maybe RealReg
globalRegMaybe Platform
platform) [GlobalReg]
gregs ]
where platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
type InstrBlock
= OrdList Instr
data CondCode
= CondCode Bool Cond InstrBlock
data ChildCode64
= ChildCode64
InstrBlock
Reg
data Register
= Fixed Format Reg InstrBlock
| Any Format (Reg -> InstrBlock)
swizzleRegisterRep :: Register -> Format -> Register
swizzleRegisterRep :: Register -> Format -> Register
swizzleRegisterRep (Fixed _ reg :: Reg
reg code :: OrdList Instr
code) format :: Format
format = Format -> Reg -> OrdList Instr -> Register
Fixed Format
format Reg
reg OrdList Instr
code
swizzleRegisterRep (Any _ codefn :: Reg -> OrdList Instr
codefn) format :: Format
format = Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
codefn
getRegisterReg :: Platform -> Bool -> CmmReg -> Reg
getRegisterReg :: Platform -> Bool -> CmmReg -> Reg
getRegisterReg _ use_sse2 :: Bool
use_sse2 (CmmLocal (LocalReg u :: Unique
u pk :: CmmType
pk))
= let fmt :: Format
fmt = CmmType -> Format
cmmTypeFormat CmmType
pk in
if Format -> Bool
isFloatFormat Format
fmt Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
use_sse2
then VirtualReg -> Reg
RegVirtual (Unique -> Format -> VirtualReg
mkVirtualReg Unique
u Format
FF80)
else VirtualReg -> Reg
RegVirtual (Unique -> Format -> VirtualReg
mkVirtualReg Unique
u Format
fmt)
getRegisterReg platform :: Platform
platform _ (CmmGlobal mid :: GlobalReg
mid)
= case Platform -> GlobalReg -> Maybe RealReg
globalRegMaybe Platform
platform GlobalReg
mid of
Just reg :: RealReg
reg -> RealReg -> Reg
RegReal (RealReg -> Reg) -> RealReg -> Reg
forall a b. (a -> b) -> a -> b
$ RealReg
reg
Nothing -> String -> SDoc -> Reg
forall a. HasCallStack => String -> SDoc -> a
pprPanic "getRegisterReg-memory" (CmmReg -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CmmReg -> SDoc) -> CmmReg -> SDoc
forall a b. (a -> b) -> a -> b
$ GlobalReg -> CmmReg
CmmGlobal GlobalReg
mid)
data Amode
= Amode AddrMode InstrBlock
is32BitInteger :: Integer -> Bool
is32BitInteger :: Integer -> Bool
is32BitInteger i :: Integer
i = Int64
i64 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= 0x7fffffff Bool -> Bool -> Bool
&& Int64
i64 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= -0x80000000
where i64 :: Int64
i64 = Integer -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i :: Int64
jumpTableEntry :: DynFlags -> Maybe BlockId -> CmmStatic
jumpTableEntry :: DynFlags -> Maybe Label -> CmmStatic
jumpTableEntry dflags :: DynFlags
dflags Nothing = CmmLit -> CmmStatic
CmmStaticLit (Integer -> Width -> CmmLit
CmmInt 0 (DynFlags -> Width
wordWidth DynFlags
dflags))
jumpTableEntry _ (Just blockid :: Label
blockid) = CmmLit -> CmmStatic
CmmStaticLit (CLabel -> CmmLit
CmmLabel CLabel
blockLabel)
where blockLabel :: CLabel
blockLabel = Label -> CLabel
blockLbl Label
blockid
mangleIndexTree :: DynFlags -> CmmReg -> Int -> CmmExpr
mangleIndexTree :: DynFlags -> CmmReg -> Alignment -> CmmExpr
mangleIndexTree dflags :: DynFlags
dflags reg :: CmmReg
reg off :: Alignment
off
= MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add Width
width) [CmmReg -> CmmExpr
CmmReg CmmReg
reg, CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Alignment -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Alignment
off) Width
width)]
where width :: Width
width = CmmType -> Width
typeWidth (DynFlags -> CmmReg -> CmmType
cmmRegType DynFlags
dflags CmmReg
reg)
getSomeReg :: CmmExpr -> NatM (Reg, InstrBlock)
getSomeReg :: CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg expr :: CmmExpr
expr = do
Register
r <- CmmExpr -> NatM Register
getRegister CmmExpr
expr
case Register
r of
Any rep :: Format
rep code :: Reg -> OrdList Instr
code -> do
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
tmp, Reg -> OrdList Instr
code Reg
tmp)
Fixed _ reg :: Reg
reg code :: OrdList Instr
code ->
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
reg, OrdList Instr
code)
assignMem_I64Code :: CmmExpr -> CmmExpr -> NatM InstrBlock
assignMem_I64Code :: CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_I64Code addrTree :: CmmExpr
addrTree valueTree :: CmmExpr
valueTree = do
Amode addr :: AddrMode
addr addr_code :: OrdList Instr
addr_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
addrTree
ChildCode64 vcode :: OrdList Instr
vcode rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
valueTree
let
rhi :: Reg
rhi = Reg -> Reg
getHiVRegFromLo Reg
rlo
mov_lo :: Instr
mov_lo = Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
rlo) (AddrMode -> Operand
OpAddr AddrMode
addr)
mov_hi :: Instr
mov_hi = Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
rhi) (AddrMode -> Operand
OpAddr (Maybe AddrMode -> AddrMode
forall a. HasCallStack => Maybe a -> a
fromJust (AddrMode -> Alignment -> Maybe AddrMode
addrOffset AddrMode
addr 4)))
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
vcode OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
addr_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_lo OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_hi)
assignReg_I64Code :: CmmReg -> CmmExpr -> NatM InstrBlock
assignReg_I64Code :: CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_I64Code (CmmLocal (LocalReg u_dst :: Unique
u_dst _)) valueTree :: CmmExpr
valueTree = do
ChildCode64 vcode :: OrdList Instr
vcode r_src_lo :: Reg
r_src_lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
valueTree
let
r_dst_lo :: Reg
r_dst_lo = VirtualReg -> Reg
RegVirtual (VirtualReg -> Reg) -> VirtualReg -> Reg
forall a b. (a -> b) -> a -> b
$ Unique -> Format -> VirtualReg
mkVirtualReg Unique
u_dst Format
II32
r_dst_hi :: Reg
r_dst_hi = Reg -> Reg
getHiVRegFromLo Reg
r_dst_lo
r_src_hi :: Reg
r_src_hi = Reg -> Reg
getHiVRegFromLo Reg
r_src_lo
mov_lo :: Instr
mov_lo = Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r_src_lo) (Reg -> Operand
OpReg Reg
r_dst_lo)
mov_hi :: Instr
mov_hi = Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r_src_hi) (Reg -> Operand
OpReg Reg
r_dst_hi)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (
OrdList Instr
vcode OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_lo OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_hi
)
assignReg_I64Code _ _
= String -> NatM (OrdList Instr)
forall a. String -> a
panic "assignReg_I64Code(i386): invalid lvalue"
iselExpr64 :: CmmExpr -> NatM ChildCode64
iselExpr64 :: CmmExpr -> NatM ChildCode64
iselExpr64 (CmmLit (CmmInt i :: Integer
i _)) = do
(rlo :: Reg
rlo,rhi :: Reg
rhi) <- Format -> NatM (Reg, Reg)
getNewRegPairNat Format
II32
let
r :: Integer
r = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i :: Word32)
q :: Integer
q = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
i Integer -> Alignment -> Integer
forall a. Bits a => a -> Alignment -> a
`shiftR` 32) :: Word32)
code :: OrdList Instr
code = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
r)) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
q)) (Reg -> Operand
OpReg Reg
rhi)
]
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> Reg -> ChildCode64
ChildCode64 OrdList Instr
code Reg
rlo)
iselExpr64 (CmmLoad addrTree :: CmmExpr
addrTree ty :: CmmType
ty) | CmmType -> Bool
isWord64 CmmType
ty = do
Amode addr :: AddrMode
addr addr_code :: OrdList Instr
addr_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
addrTree
(rlo :: Reg
rlo,rhi :: Reg
rhi) <- Format -> NatM (Reg, Reg)
getNewRegPairNat Format
II32
let
mov_lo :: Instr
mov_lo = Format -> Operand -> Operand -> Instr
MOV Format
II32 (AddrMode -> Operand
OpAddr AddrMode
addr) (Reg -> Operand
OpReg Reg
rlo)
mov_hi :: Instr
mov_hi = Format -> Operand -> Operand -> Instr
MOV Format
II32 (AddrMode -> Operand
OpAddr (Maybe AddrMode -> AddrMode
forall a. HasCallStack => Maybe a -> a
fromJust (AddrMode -> Alignment -> Maybe AddrMode
addrOffset AddrMode
addr 4))) (Reg -> Operand
OpReg Reg
rhi)
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (
OrdList Instr -> Reg -> ChildCode64
ChildCode64 (OrdList Instr
addr_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_lo OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
mov_hi)
Reg
rlo
)
iselExpr64 (CmmReg (CmmLocal (LocalReg vu :: Unique
vu ty :: CmmType
ty))) | CmmType -> Bool
isWord64 CmmType
ty
= ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> Reg -> ChildCode64
ChildCode64 OrdList Instr
forall a. OrdList a
nilOL (VirtualReg -> Reg
RegVirtual (VirtualReg -> Reg) -> VirtualReg -> Reg
forall a b. (a -> b) -> a -> b
$ Unique -> Format -> VirtualReg
mkVirtualReg Unique
vu Format
II32))
iselExpr64 (CmmMachOp (MO_Add _) [e1 :: CmmExpr
e1, CmmLit (CmmInt i :: Integer
i _)]) = do
ChildCode64 code1 :: OrdList Instr
code1 r1lo :: Reg
r1lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e1
(rlo :: Reg
rlo,rhi :: Reg
rhi) <- Format -> NatM (Reg, Reg)
getNewRegPairNat Format
II32
let
r :: Integer
r = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i :: Word32)
q :: Integer
q = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
i Integer -> Alignment -> Integer
forall a. Bits a => a -> Alignment -> a
`shiftR` 32) :: Word32)
r1hi :: Reg
r1hi = Reg -> Reg
getHiVRegFromLo Reg
r1lo
code :: OrdList Instr
code = OrdList Instr
code1 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1lo) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
ADD Format
II32 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
r)) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1hi) (Reg -> Operand
OpReg Reg
rhi),
Format -> Operand -> Operand -> Instr
ADC Format
II32 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
q)) (Reg -> Operand
OpReg Reg
rhi) ]
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> Reg -> ChildCode64
ChildCode64 OrdList Instr
code Reg
rlo)
iselExpr64 (CmmMachOp (MO_Add _) [e1 :: CmmExpr
e1,e2 :: CmmExpr
e2]) = do
ChildCode64 code1 :: OrdList Instr
code1 r1lo :: Reg
r1lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e1
ChildCode64 code2 :: OrdList Instr
code2 r2lo :: Reg
r2lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e2
(rlo :: Reg
rlo,rhi :: Reg
rhi) <- Format -> NatM (Reg, Reg)
getNewRegPairNat Format
II32
let
r1hi :: Reg
r1hi = Reg -> Reg
getHiVRegFromLo Reg
r1lo
r2hi :: Reg
r2hi = Reg -> Reg
getHiVRegFromLo Reg
r2lo
code :: OrdList Instr
code = OrdList Instr
code1 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
code2 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1lo) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
ADD Format
II32 (Reg -> Operand
OpReg Reg
r2lo) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1hi) (Reg -> Operand
OpReg Reg
rhi),
Format -> Operand -> Operand -> Instr
ADC Format
II32 (Reg -> Operand
OpReg Reg
r2hi) (Reg -> Operand
OpReg Reg
rhi) ]
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> Reg -> ChildCode64
ChildCode64 OrdList Instr
code Reg
rlo)
iselExpr64 (CmmMachOp (MO_Sub _) [e1 :: CmmExpr
e1,e2 :: CmmExpr
e2]) = do
ChildCode64 code1 :: OrdList Instr
code1 r1lo :: Reg
r1lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e1
ChildCode64 code2 :: OrdList Instr
code2 r2lo :: Reg
r2lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e2
(rlo :: Reg
rlo,rhi :: Reg
rhi) <- Format -> NatM (Reg, Reg)
getNewRegPairNat Format
II32
let
r1hi :: Reg
r1hi = Reg -> Reg
getHiVRegFromLo Reg
r1lo
r2hi :: Reg
r2hi = Reg -> Reg
getHiVRegFromLo Reg
r2lo
code :: OrdList Instr
code = OrdList Instr
code1 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
code2 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1lo) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
SUB Format
II32 (Reg -> Operand
OpReg Reg
r2lo) (Reg -> Operand
OpReg Reg
rlo),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r1hi) (Reg -> Operand
OpReg Reg
rhi),
Format -> Operand -> Operand -> Instr
SBB Format
II32 (Reg -> Operand
OpReg Reg
r2hi) (Reg -> Operand
OpReg Reg
rhi) ]
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> Reg -> ChildCode64
ChildCode64 OrdList Instr
code Reg
rlo)
iselExpr64 (CmmMachOp (MO_UU_Conv _ W64) [expr :: CmmExpr
expr]) = do
Reg -> OrdList Instr
fn <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
expr
Reg
r_dst_lo <- Format -> NatM Reg
getNewRegNat Format
II32
let r_dst_hi :: Reg
r_dst_hi = Reg -> Reg
getHiVRegFromLo Reg
r_dst_lo
code :: OrdList Instr
code = Reg -> OrdList Instr
fn Reg
r_dst_lo
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (
OrdList Instr -> Reg -> ChildCode64
ChildCode64 (OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt 0)) (Reg -> Operand
OpReg Reg
r_dst_hi))
Reg
r_dst_lo
)
iselExpr64 (CmmMachOp (MO_SS_Conv W32 W64) [expr :: CmmExpr
expr]) = do
Reg -> OrdList Instr
fn <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
expr
Reg
r_dst_lo <- Format -> NatM Reg
getNewRegNat Format
II32
let r_dst_hi :: Reg
r_dst_hi = Reg -> Reg
getHiVRegFromLo Reg
r_dst_lo
code :: OrdList Instr
code = Reg -> OrdList Instr
fn Reg
r_dst_lo
ChildCode64 -> NatM ChildCode64
forall (m :: * -> *) a. Monad m => a -> m a
return (
OrdList Instr -> Reg -> ChildCode64
ChildCode64 (OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
r_dst_lo) (Reg -> Operand
OpReg Reg
eax) OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Instr
CLTD Format
II32 OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
eax) (Reg -> Operand
OpReg Reg
r_dst_lo) OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
edx) (Reg -> Operand
OpReg Reg
r_dst_hi))
Reg
r_dst_lo
)
iselExpr64 expr :: CmmExpr
expr
= String -> SDoc -> NatM ChildCode64
forall a. HasCallStack => String -> SDoc -> a
pprPanic "iselExpr64(i386)" (CmmExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmExpr
expr)
getRegister :: CmmExpr -> NatM Register
getRegister :: CmmExpr -> NatM Register
getRegister e :: CmmExpr
e = do DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool
is32Bit <- NatM Bool
is32BitPlatform
DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' DynFlags
dflags Bool
is32Bit CmmExpr
e
getRegister' :: DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' :: DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (CmmReg reg :: CmmReg
reg)
= case CmmReg
reg of
CmmGlobal PicBaseReg
| Bool
is32Bit ->
do Reg
reg' <- Format -> NatM Reg
getPicBaseNat (Bool -> Format
archWordFormat Bool
is32Bit)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed (Bool -> Format
archWordFormat Bool
is32Bit) Reg
reg' OrdList Instr
forall a. OrdList a
nilOL)
_ ->
do Bool
use_sse2 <- NatM Bool
sse2Enabled
let
fmt :: Format
fmt = CmmType -> Format
cmmTypeFormat (DynFlags -> CmmReg -> CmmType
cmmRegType DynFlags
dflags CmmReg
reg)
format :: Format
format | Bool -> Bool
not Bool
use_sse2 Bool -> Bool -> Bool
&& Format -> Bool
isFloatFormat Format
fmt = Format
FF80
| Bool
otherwise = Format
fmt
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed Format
format
(Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 CmmReg
reg)
OrdList Instr
forall a. OrdList a
nilOL)
getRegister' dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (CmmRegOff r :: CmmReg
r n :: Alignment
n)
= DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' DynFlags
dflags Bool
is32Bit (CmmExpr -> NatM Register) -> CmmExpr -> NatM Register
forall a b. (a -> b) -> a -> b
$ DynFlags -> CmmReg -> Alignment -> CmmExpr
mangleIndexTree DynFlags
dflags CmmReg
r Alignment
n
getRegister' dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (CmmMachOp (MO_AlignmentCheck align :: Alignment
align _) [e :: CmmExpr
e])
= Alignment -> Register -> Register
addAlignmentCheck Alignment
align (Register -> Register) -> NatM Register -> NatM Register
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' DynFlags
dflags Bool
is32Bit CmmExpr
e
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_UU_Conv W64 W32)
[CmmMachOp (MO_U_Shr W64) [x :: CmmExpr
x,CmmLit (CmmInt 32 _)]])
| Bool
is32Bit = do
ChildCode64 code :: OrdList Instr
code rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
x
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> NatM Register) -> Register -> NatM Register
forall a b. (a -> b) -> a -> b
$ Format -> Reg -> OrdList Instr -> Register
Fixed Format
II32 (Reg -> Reg
getHiVRegFromLo Reg
rlo) OrdList Instr
code
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_SS_Conv W64 W32)
[CmmMachOp (MO_U_Shr W64) [x :: CmmExpr
x,CmmLit (CmmInt 32 _)]])
| Bool
is32Bit = do
ChildCode64 code :: OrdList Instr
code rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
x
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> NatM Register) -> Register -> NatM Register
forall a b. (a -> b) -> a -> b
$ Format -> Reg -> OrdList Instr -> Register
Fixed Format
II32 (Reg -> Reg
getHiVRegFromLo Reg
rlo) OrdList Instr
code
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_UU_Conv W64 W32) [x :: CmmExpr
x])
| Bool
is32Bit = do
ChildCode64 code :: OrdList Instr
code rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
x
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> NatM Register) -> Register -> NatM Register
forall a b. (a -> b) -> a -> b
$ Format -> Reg -> OrdList Instr -> Register
Fixed Format
II32 Reg
rlo OrdList Instr
code
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_SS_Conv W64 W32) [x :: CmmExpr
x])
| Bool
is32Bit = do
ChildCode64 code :: OrdList Instr
code rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
x
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> NatM Register) -> Register -> NatM Register
forall a b. (a -> b) -> a -> b
$ Format -> Reg -> OrdList Instr -> Register
Fixed Format
II32 Reg
rlo OrdList Instr
code
getRegister' _ _ (CmmLit lit :: CmmLit
lit@(CmmFloat f :: Rational
f w :: Width
w)) =
NatM Register -> NatM Register -> NatM Register
forall a. NatM a -> NatM a -> NatM a
if_sse2 NatM Register
float_const_sse2 NatM Register
float_const_x87
where
float_const_sse2 :: NatM Register
float_const_sse2
| Rational
f Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== 0.0 = do
let
format :: Format
format = Width -> Format
floatFormat Width
w
code :: Reg -> OrdList Instr
code dst :: Reg
dst = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
XOR Format
format (Reg -> Operand
OpReg Reg
dst) (Reg -> Operand
OpReg Reg
dst))
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
| Bool
otherwise = do
Amode addr :: AddrMode
addr code :: OrdList Instr
code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
lit
Bool -> Width -> AddrMode -> OrdList Instr -> NatM Register
loadFloatAmode Bool
True Width
w AddrMode
addr OrdList Instr
code
float_const_x87 :: NatM Register
float_const_x87 = case Width
w of
W64
| Rational
f Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== 0.0 ->
let code :: Reg -> OrdList Instr
code dst :: Reg
dst = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Reg -> Instr
GLDZ Reg
dst)
in Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
FF80 Reg -> OrdList Instr
code)
| Rational
f Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== 1.0 ->
let code :: Reg -> OrdList Instr
code dst :: Reg
dst = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Reg -> Instr
GLD1 Reg
dst)
in Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
FF80 Reg -> OrdList Instr
code)
_otherwise :: Width
_otherwise -> do
Amode addr :: AddrMode
addr code :: OrdList Instr
code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
lit
Bool -> Width -> AddrMode -> OrdList Instr -> NatM Register
loadFloatAmode Bool
False Width
w AddrMode
addr OrdList Instr
code
getRegister' _ _ (CmmMachOp (MO_UU_Conv W8 W32) [CmmLoad addr :: CmmExpr
addr _]) = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
getRegister' _ _ (CmmMachOp (MO_SS_Conv W8 W32) [CmmLoad addr :: CmmExpr
addr _]) = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVSxL Format
II8) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
getRegister' _ _ (CmmMachOp (MO_UU_Conv W16 W32) [CmmLoad addr :: CmmExpr
addr _]) = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
getRegister' _ _ (CmmMachOp (MO_SS_Conv W16 W32) [CmmLoad addr :: CmmExpr
addr _]) = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVSxL Format
II16) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_UU_Conv W8 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_SS_Conv W8 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVSxL Format
II8) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_UU_Conv W16 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_SS_Conv W16 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVSxL Format
II16) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_UU_Conv W32 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOV Format
II32) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_SS_Conv W32 W64) [CmmLoad addr :: CmmExpr
addr _])
| Bool -> Bool
not Bool
is32Bit = do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOVSxL Format
II32) CmmExpr
addr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp (MO_Add W64) [CmmReg (CmmGlobal PicBaseReg),
CmmLit displacement :: CmmLit
displacement])
| Bool -> Bool
not Bool
is32Bit = do
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> NatM Register) -> Register -> NatM Register
forall a b. (a -> b) -> a -> b
$ Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 (\dst :: Reg
dst -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$
Format -> Operand -> Operand -> Instr
LEA Format
II64 (AddrMode -> Operand
OpAddr (Imm -> AddrMode
ripRel (CmmLit -> Imm
litToImm CmmLit
displacement))) (Reg -> Operand
OpReg Reg
dst))
getRegister' dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (CmmMachOp mop :: MachOp
mop [x :: CmmExpr
x]) = do
Bool
sse2 <- NatM Bool
sse2Enabled
case MachOp
mop of
MO_F_Neg w :: Width
w
| Bool
sse2 -> Width -> CmmExpr -> NatM Register
sse2NegCode Width
w CmmExpr
x
| Bool
otherwise -> Format -> (Reg -> Reg -> Instr) -> CmmExpr -> NatM Register
trivialUFCode Format
FF80 (Format -> Reg -> Reg -> Instr
GNEG Format
FF80) CmmExpr
x
MO_S_Neg w :: Width
w -> (Format -> Operand -> Instr) -> Format -> NatM Register
triv_ucode Format -> Operand -> Instr
NEGI (Width -> Format
intFormat Width
w)
MO_Not w :: Width
w -> (Format -> Operand -> Instr) -> Format -> NatM Register
triv_ucode Format -> Operand -> Instr
NOT (Width -> Format
intFormat Width
w)
MO_UU_Conv W32 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W32 CmmExpr
x
MO_SS_Conv W32 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W32 CmmExpr
x
MO_XX_Conv W32 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W32 CmmExpr
x
MO_UU_Conv W16 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W16 CmmExpr
x
MO_SS_Conv W16 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W16 CmmExpr
x
MO_XX_Conv W16 W8 -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W16 CmmExpr
x
MO_UU_Conv W32 W16 -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W32 CmmExpr
x
MO_SS_Conv W32 W16 -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W32 CmmExpr
x
MO_XX_Conv W32 W16 -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W32 CmmExpr
x
MO_UU_Conv W64 W32 | Bool -> Bool
not Bool
is32Bit -> Format -> CmmExpr -> NatM Register
conversionNop Format
II64 CmmExpr
x
MO_SS_Conv W64 W32 | Bool -> Bool
not Bool
is32Bit -> Format -> CmmExpr -> NatM Register
conversionNop Format
II64 CmmExpr
x
MO_XX_Conv W64 W32 | Bool -> Bool
not Bool
is32Bit -> Format -> CmmExpr -> NatM Register
conversionNop Format
II64 CmmExpr
x
MO_UU_Conv W64 W16 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W64 CmmExpr
x
MO_SS_Conv W64 W16 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W64 CmmExpr
x
MO_XX_Conv W64 W16 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI16Reg Width
W64 CmmExpr
x
MO_UU_Conv W64 W8 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W64 CmmExpr
x
MO_SS_Conv W64 W8 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W64 CmmExpr
x
MO_XX_Conv W64 W8 | Bool -> Bool
not Bool
is32Bit -> Width -> CmmExpr -> NatM Register
toI8Reg Width
W64 CmmExpr
x
MO_UU_Conv rep1 :: Width
rep1 rep2 :: Width
rep2 | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 -> Format -> CmmExpr -> NatM Register
conversionNop (Width -> Format
intFormat Width
rep1) CmmExpr
x
MO_SS_Conv rep1 :: Width
rep1 rep2 :: Width
rep2 | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 -> Format -> CmmExpr -> NatM Register
conversionNop (Width -> Format
intFormat Width
rep1) CmmExpr
x
MO_XX_Conv rep1 :: Width
rep1 rep2 :: Width
rep2 | Width
rep1 Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
rep2 -> Format -> CmmExpr -> NatM Register
conversionNop (Width -> Format
intFormat Width
rep1) CmmExpr
x
MO_UU_Conv W8 W32 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W32 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_UU_Conv W16 W32 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W32 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_UU_Conv W8 W16 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W16 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_SS_Conv W8 W32 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W32 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_SS_Conv W16 W32 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W32 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_SS_Conv W8 W16 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W16 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_XX_Conv W8 W32
| Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W32 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
| Bool
otherwise -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W32 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_XX_Conv W8 W16
| Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W16 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
| Bool
otherwise -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W16 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_XX_Conv W16 W32 -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W32 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_UU_Conv W8 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W64 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_UU_Conv W16 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W64 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_UU_Conv W32 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W32 Width
W64 Format -> Operand -> Operand -> Instr
MOVZxL CmmExpr
x
MO_SS_Conv W8 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W64 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_SS_Conv W16 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W64 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_SS_Conv W32 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W32 Width
W64 Format -> Operand -> Operand -> Instr
MOVSxL CmmExpr
x
MO_XX_Conv W8 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W8 Width
W64 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_XX_Conv W16 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W16 Width
W64 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_XX_Conv W32 W64 | Bool -> Bool
not Bool
is32Bit -> Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend Width
W32 Width
W64 Format -> Operand -> Operand -> Instr
MOV CmmExpr
x
MO_FF_Conv W32 W64
| Bool
sse2 -> Width -> CmmExpr -> NatM Register
coerceFP2FP Width
W64 CmmExpr
x
| Bool
otherwise -> Format -> CmmExpr -> NatM Register
conversionNop Format
FF80 CmmExpr
x
MO_FF_Conv W64 W32 -> Width -> CmmExpr -> NatM Register
coerceFP2FP Width
W32 CmmExpr
x
MO_FS_Conv from :: Width
from to :: Width
to -> Width -> Width -> CmmExpr -> NatM Register
coerceFP2Int Width
from Width
to CmmExpr
x
MO_SF_Conv from :: Width
from to :: Width
to -> Width -> Width -> CmmExpr -> NatM Register
coerceInt2FP Width
from Width
to CmmExpr
x
MO_V_Insert {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Extract {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Add {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Sub {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Mul {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Quot {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Rem {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Neg {} -> NatM Register
forall a. NatM a
needLlvm
MO_VU_Quot {} -> NatM Register
forall a. NatM a
needLlvm
MO_VU_Rem {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Insert {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Extract {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Add {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Sub {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Mul {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Quot {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Neg {} -> NatM Register
forall a. NatM a
needLlvm
_other :: MachOp
_other -> String -> SDoc -> NatM Register
forall a. HasCallStack => String -> SDoc -> a
pprPanic "getRegister" (MachOp -> SDoc
pprMachOp MachOp
mop)
where
triv_ucode :: (Format -> Operand -> Instr) -> Format -> NatM Register
triv_ucode :: (Format -> Operand -> Instr) -> Format -> NatM Register
triv_ucode instr :: Format -> Operand -> Instr
instr format :: Format
format = Format -> (Operand -> Instr) -> CmmExpr -> NatM Register
trivialUCode Format
format (Format -> Operand -> Instr
instr Format
format) CmmExpr
x
integerExtend :: Width -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr -> NatM Register
integerExtend :: Width
-> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> NatM Register
integerExtend from :: Width
from to :: Width
to instr :: Format -> Operand -> Operand -> Instr
instr expr :: CmmExpr
expr = do
(reg :: Reg
reg,e_code :: OrdList Instr
e_code) <- if Width
from Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then CmmExpr -> NatM (Reg, OrdList Instr)
getByteReg CmmExpr
expr
else CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst =
OrdList Instr
e_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
instr (Width -> Format
intFormat Width
from) (Reg -> Operand
OpReg Reg
reg) (Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
intFormat Width
to) Reg -> OrdList Instr
code)
toI8Reg :: Width -> CmmExpr -> NatM Register
toI8Reg :: Width -> CmmExpr -> NatM Register
toI8Reg new_rep :: Width
new_rep expr :: CmmExpr
expr
= do Reg -> OrdList Instr
codefn <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
expr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
intFormat Width
new_rep) Reg -> OrdList Instr
codefn)
toI16Reg :: Width -> CmmExpr -> NatM Register
toI16Reg = Width -> CmmExpr -> NatM Register
toI8Reg
conversionNop :: Format -> CmmExpr -> NatM Register
conversionNop :: Format -> CmmExpr -> NatM Register
conversionNop new_format :: Format
new_format expr :: CmmExpr
expr
= do Register
e_code <- DynFlags -> Bool -> CmmExpr -> NatM Register
getRegister' DynFlags
dflags Bool
is32Bit CmmExpr
expr
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Register -> Format -> Register
swizzleRegisterRep Register
e_code Format
new_format)
getRegister' _ is32Bit :: Bool
is32Bit (CmmMachOp mop :: MachOp
mop [x :: CmmExpr
x, y :: CmmExpr
y]) = do
Bool
sse2 <- NatM Bool
sse2Enabled
case MachOp
mop of
MO_F_Eq _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
EQQ CmmExpr
x CmmExpr
y
MO_F_Ne _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
NE CmmExpr
x CmmExpr
y
MO_F_Gt _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
GTT CmmExpr
x CmmExpr
y
MO_F_Ge _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
GE CmmExpr
x CmmExpr
y
MO_F_Lt _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
GTT CmmExpr
y CmmExpr
x
MO_F_Le _ -> Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg Bool
is32Bit Cond
GE CmmExpr
y CmmExpr
x
MO_Eq _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
EQQ CmmExpr
x CmmExpr
y
MO_Ne _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
NE CmmExpr
x CmmExpr
y
MO_S_Gt _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
GTT CmmExpr
x CmmExpr
y
MO_S_Ge _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
GE CmmExpr
x CmmExpr
y
MO_S_Lt _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
LTT CmmExpr
x CmmExpr
y
MO_S_Le _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
LE CmmExpr
x CmmExpr
y
MO_U_Gt _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
GU CmmExpr
x CmmExpr
y
MO_U_Ge _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
GEU CmmExpr
x CmmExpr
y
MO_U_Lt _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
LU CmmExpr
x CmmExpr
y
MO_U_Le _ -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg Cond
LEU CmmExpr
x CmmExpr
y
MO_F_Add w :: Width
w | Bool
sse2 -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialFCode_sse2 Width
w Format -> Operand -> Operand -> Instr
ADD CmmExpr
x CmmExpr
y
| Bool
otherwise -> (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 Format -> Reg -> Reg -> Reg -> Instr
GADD CmmExpr
x CmmExpr
y
MO_F_Sub w :: Width
w | Bool
sse2 -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialFCode_sse2 Width
w Format -> Operand -> Operand -> Instr
SUB CmmExpr
x CmmExpr
y
| Bool
otherwise -> (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 Format -> Reg -> Reg -> Reg -> Instr
GSUB CmmExpr
x CmmExpr
y
MO_F_Quot w :: Width
w | Bool
sse2 -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialFCode_sse2 Width
w Format -> Operand -> Operand -> Instr
FDIV CmmExpr
x CmmExpr
y
| Bool
otherwise -> (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 Format -> Reg -> Reg -> Reg -> Instr
GDIV CmmExpr
x CmmExpr
y
MO_F_Mul w :: Width
w | Bool
sse2 -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialFCode_sse2 Width
w Format -> Operand -> Operand -> Instr
MUL CmmExpr
x CmmExpr
y
| Bool
otherwise -> (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 Format -> Reg -> Reg -> Reg -> Instr
GMUL CmmExpr
x CmmExpr
y
MO_Add rep :: Width
rep -> Width -> CmmExpr -> CmmExpr -> NatM Register
add_code Width
rep CmmExpr
x CmmExpr
y
MO_Sub rep :: Width
rep -> Width -> CmmExpr -> CmmExpr -> NatM Register
sub_code Width
rep CmmExpr
x CmmExpr
y
MO_S_Quot rep :: Width
rep -> Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code Width
rep Bool
True Bool
True CmmExpr
x CmmExpr
y
MO_S_Rem rep :: Width
rep -> Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code Width
rep Bool
True Bool
False CmmExpr
x CmmExpr
y
MO_U_Quot rep :: Width
rep -> Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code Width
rep Bool
False Bool
True CmmExpr
x CmmExpr
y
MO_U_Rem rep :: Width
rep -> Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code Width
rep Bool
False Bool
False CmmExpr
x CmmExpr
y
MO_S_MulMayOflo rep :: Width
rep -> Width -> CmmExpr -> CmmExpr -> NatM Register
imulMayOflo Width
rep CmmExpr
x CmmExpr
y
MO_Mul W8 -> CmmExpr -> CmmExpr -> NatM Register
imulW8 CmmExpr
x CmmExpr
y
MO_Mul rep :: Width
rep -> Width -> (Format -> Operand -> Operand -> Instr) -> NatM Register
triv_op Width
rep Format -> Operand -> Operand -> Instr
IMUL
MO_And rep :: Width
rep -> Width -> (Format -> Operand -> Operand -> Instr) -> NatM Register
triv_op Width
rep Format -> Operand -> Operand -> Instr
AND
MO_Or rep :: Width
rep -> Width -> (Format -> Operand -> Operand -> Instr) -> NatM Register
triv_op Width
rep Format -> Operand -> Operand -> Instr
OR
MO_Xor rep :: Width
rep -> Width -> (Format -> Operand -> Operand -> Instr) -> NatM Register
triv_op Width
rep Format -> Operand -> Operand -> Instr
XOR
MO_Shl rep :: Width
rep -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
shift_code Width
rep Format -> Operand -> Operand -> Instr
SHL CmmExpr
x CmmExpr
y
MO_U_Shr rep :: Width
rep -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
shift_code Width
rep Format -> Operand -> Operand -> Instr
SHR CmmExpr
x CmmExpr
y
MO_S_Shr rep :: Width
rep -> Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
shift_code Width
rep Format -> Operand -> Operand -> Instr
SAR CmmExpr
x CmmExpr
y
MO_V_Insert {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Extract {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Add {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Sub {} -> NatM Register
forall a. NatM a
needLlvm
MO_V_Mul {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Quot {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Rem {} -> NatM Register
forall a. NatM a
needLlvm
MO_VS_Neg {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Insert {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Extract {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Add {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Sub {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Mul {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Quot {} -> NatM Register
forall a. NatM a
needLlvm
MO_VF_Neg {} -> NatM Register
forall a. NatM a
needLlvm
_other :: MachOp
_other -> String -> SDoc -> NatM Register
forall a. HasCallStack => String -> SDoc -> a
pprPanic "getRegister(x86) - binary CmmMachOp (1)" (MachOp -> SDoc
pprMachOp MachOp
mop)
where
triv_op :: Width -> (Format -> Operand -> Operand -> Instr) -> NatM Register
triv_op width :: Width
width instr :: Format -> Operand -> Operand -> Instr
instr = Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode Width
width Operand -> Operand -> Instr
op ((Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just Operand -> Operand -> Instr
op) CmmExpr
x CmmExpr
y
where op :: Operand -> Operand -> Instr
op = Format -> Operand -> Operand -> Instr
instr (Width -> Format
intFormat Width
width)
imulW8 :: CmmExpr -> CmmExpr -> NatM Register
imulW8 :: CmmExpr -> CmmExpr -> NatM Register
imulW8 arg_a :: CmmExpr
arg_a arg_b :: CmmExpr
arg_b = do
(a_reg :: Reg
a_reg, a_code :: OrdList Instr
a_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
arg_a
Reg -> OrdList Instr
b_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg_b
let code :: OrdList Instr
code = OrdList Instr
a_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
b_code Reg
eax OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Instr
IMUL2 Format
format (Reg -> Operand
OpReg Reg
a_reg) ]
format :: Format
format = Width -> Format
intFormat Width
W8
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed Format
format Reg
eax OrdList Instr
code)
imulMayOflo :: Width -> CmmExpr -> CmmExpr -> NatM Register
imulMayOflo :: Width -> CmmExpr -> CmmExpr -> NatM Register
imulMayOflo rep :: Width
rep a :: CmmExpr
a b :: CmmExpr
b = do
(a_reg :: Reg
a_reg, a_code :: OrdList Instr
a_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
a
Reg -> OrdList Instr
b_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
b
let
shift_amt :: Alignment
shift_amt = case Width
rep of
W32 -> 31
W64 -> 63
_ -> String -> Alignment
forall a. String -> a
panic "shift_amt"
format :: Format
format = Width -> Format
intFormat Width
rep
code :: OrdList Instr
code = OrdList Instr
a_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
b_code Reg
eax OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Instr
IMUL2 Format
format (Reg -> Operand
OpReg Reg
a_reg),
Format -> Operand -> Operand -> Instr
SAR Format
format (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
shift_amt)) (Reg -> Operand
OpReg Reg
eax),
Format -> Operand -> Operand -> Instr
SUB Format
format (Reg -> Operand
OpReg Reg
edx) (Reg -> Operand
OpReg Reg
eax)
]
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed Format
format Reg
eax OrdList Instr
code)
shift_code :: Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
shift_code :: Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
shift_code width :: Width
width instr :: Format -> Operand -> Operand -> Instr
instr x :: CmmExpr
x (CmmLit lit :: CmmLit
lit) = do
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let
format :: Format
format = Width -> Format
intFormat Width
width
code :: Reg -> OrdList Instr
code dst :: Reg
dst
= Reg -> OrdList Instr
x_code Reg
dst OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
instr Format
format (Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit)) (Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
shift_code width :: Width
width instr :: Format -> Operand -> Operand -> Instr
instr x :: CmmExpr
x y :: CmmExpr
y = do
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let format :: Format
format = Width -> Format
intFormat Width
width
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
format
Reg -> OrdList Instr
y_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
y
let
code :: OrdList Instr
code = Reg -> OrdList Instr
x_code Reg
tmp OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
y_code Reg
ecx OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
instr Format
format (Reg -> Operand
OpReg Reg
ecx) (Reg -> Operand
OpReg Reg
tmp)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed Format
format Reg
tmp OrdList Instr
code)
add_code :: Width -> CmmExpr -> CmmExpr -> NatM Register
add_code :: Width -> CmmExpr -> CmmExpr -> NatM Register
add_code rep :: Width
rep x :: CmmExpr
x (CmmLit (CmmInt y :: Integer
y _))
| Integer -> Bool
is32BitInteger Integer
y = Width -> CmmExpr -> Integer -> NatM Register
add_int Width
rep CmmExpr
x Integer
y
add_code rep :: Width
rep x :: CmmExpr
x y :: CmmExpr
y = Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode Width
rep (Format -> Operand -> Operand -> Instr
ADD Format
format) ((Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just (Format -> Operand -> Operand -> Instr
ADD Format
format)) CmmExpr
x CmmExpr
y
where format :: Format
format = Width -> Format
intFormat Width
rep
sub_code :: Width -> CmmExpr -> CmmExpr -> NatM Register
sub_code :: Width -> CmmExpr -> CmmExpr -> NatM Register
sub_code rep :: Width
rep x :: CmmExpr
x (CmmLit (CmmInt y :: Integer
y _))
| Integer -> Bool
is32BitInteger (-Integer
y) = Width -> CmmExpr -> Integer -> NatM Register
add_int Width
rep CmmExpr
x (-Integer
y)
sub_code rep :: Width
rep x :: CmmExpr
x y :: CmmExpr
y = Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode Width
rep (Format -> Operand -> Operand -> Instr
SUB (Width -> Format
intFormat Width
rep)) Maybe (Operand -> Operand -> Instr)
forall a. Maybe a
Nothing CmmExpr
x CmmExpr
y
add_int :: Width -> CmmExpr -> Integer -> NatM Register
add_int width :: Width
width x :: CmmExpr
x y :: Integer
y = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
format :: Format
format = Width -> Format
intFormat Width
width
imm :: Imm
imm = Alignment -> Imm
ImmInt (Integer -> Alignment
forall a. Num a => Integer -> a
fromInteger Integer
y)
code :: Reg -> OrdList Instr
code dst :: Reg
dst
= OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
LEA Format
format
(AddrMode -> Operand
OpAddr (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
x_reg) EAIndex
EAIndexNone Imm
imm))
(Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
div_code :: Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code W8 signed :: Bool
signed quotient :: Bool
quotient x :: CmmExpr
x y :: CmmExpr
y = do
let widen :: MachOp
widen | Bool
signed = Width -> Width -> MachOp
MO_SS_Conv Width
W8 Width
W16
| Bool
otherwise = Width -> Width -> MachOp
MO_UU_Conv Width
W8 Width
W16
Width -> Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
div_code
Width
W16
Bool
signed
Bool
quotient
(MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
widen [CmmExpr
x])
(MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
widen [CmmExpr
y])
div_code width :: Width
width signed :: Bool
signed quotient :: Bool
quotient x :: CmmExpr
x y :: CmmExpr
y = do
(y_op :: Operand
y_op, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getRegOrMem CmmExpr
y
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let
format :: Format
format = Width -> Format
intFormat Width
width
widen :: Instr
widen | Bool
signed = Format -> Instr
CLTD Format
format
| Bool
otherwise = Format -> Operand -> Operand -> Instr
XOR Format
format (Reg -> Operand
OpReg Reg
edx) (Reg -> Operand
OpReg Reg
edx)
instr :: Format -> Operand -> Instr
instr | Bool
signed = Format -> Operand -> Instr
IDIV
| Bool
otherwise = Format -> Operand -> Instr
DIV
code :: OrdList Instr
code = OrdList Instr
y_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
x_code Reg
eax OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Instr
widen, Format -> Operand -> Instr
instr Format
format Operand
y_op]
result :: Reg
result | Bool
quotient = Reg
eax
| Bool
otherwise = Reg
edx
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> Reg -> OrdList Instr -> Register
Fixed Format
format Reg
result OrdList Instr
code)
getRegister' _ _ (CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk)
| CmmType -> Bool
isFloatType CmmType
pk
= do
Amode addr :: AddrMode
addr mem_code :: OrdList Instr
mem_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
Bool
use_sse2 <- NatM Bool
sse2Enabled
Bool -> Width -> AddrMode -> OrdList Instr -> NatM Register
loadFloatAmode Bool
use_sse2 (CmmType -> Width
typeWidth CmmType
pk) AddrMode
addr OrdList Instr
mem_code
getRegister' _ is32Bit :: Bool
is32Bit (CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk)
| Bool
is32Bit Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmType -> Bool
isWord64 CmmType
pk)
= do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode Operand -> Operand -> Instr
instr CmmExpr
mem
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
where
width :: Width
width = CmmType -> Width
typeWidth CmmType
pk
format :: Format
format = Width -> Format
intFormat Width
width
instr :: Operand -> Operand -> Instr
instr = case Width
width of
W8 -> Format -> Operand -> Operand -> Instr
MOVZxL Format
II8
_other :: Width
_other -> Format -> Operand -> Operand -> Instr
MOV Format
format
getRegister' _ is32Bit :: Bool
is32Bit (CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk)
| Bool -> Bool
not Bool
is32Bit
= do
Reg -> OrdList Instr
code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOV Format
format) CmmExpr
mem
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
where format :: Format
format = Width -> Format
intFormat (Width -> Format) -> Width -> Format
forall a b. (a -> b) -> a -> b
$ CmmType -> Width
typeWidth CmmType
pk
getRegister' _ is32Bit :: Bool
is32Bit (CmmLit (CmmInt 0 width :: Width
width))
= let
format :: Format
format = Width -> Format
intFormat Width
width
format1 :: Format
format1 = if Bool
is32Bit then Format
format
else case Format
format of
II64 -> Format
II32
_ -> Format
format
code :: Reg -> OrdList Instr
code dst :: Reg
dst
= Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
XOR Format
format1 (Reg -> Operand
OpReg Reg
dst) (Reg -> Operand
OpReg Reg
dst))
in
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
getRegister' dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (CmmLit lit :: CmmLit
lit)
| Bool -> Bool
not Bool
is32Bit, CmmType -> Bool
isWord64 (DynFlags -> CmmLit -> CmmType
cmmLitType DynFlags
dflags CmmLit
lit), Bool -> Bool
not (CmmLit -> Bool
isBigLit CmmLit
lit)
= let
imm :: Imm
imm = CmmLit -> Imm
litToImm CmmLit
lit
code :: Reg -> OrdList Instr
code dst :: Reg
dst = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm Imm
imm) (Reg -> Operand
OpReg Reg
dst))
in
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II64 Reg -> OrdList Instr
code)
where
isBigLit :: CmmLit -> Bool
isBigLit (CmmInt i :: Integer
i _) = Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< 0 Bool -> Bool -> Bool
|| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> 0xffffffff
isBigLit _ = Bool
False
getRegister' dflags :: DynFlags
dflags _ (CmmLit lit :: CmmLit
lit)
= do let format :: Format
format = CmmType -> Format
cmmTypeFormat (DynFlags -> CmmLit -> CmmType
cmmLitType DynFlags
dflags CmmLit
lit)
imm :: Imm
imm = CmmLit -> Imm
litToImm CmmLit
lit
code :: Reg -> OrdList Instr
code dst :: Reg
dst = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
format (Imm -> Operand
OpImm Imm
imm) (Reg -> Operand
OpReg Reg
dst))
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
getRegister' _ _ other :: CmmExpr
other
| CmmExpr -> Bool
isVecExpr CmmExpr
other = NatM Register
forall a. NatM a
needLlvm
| Bool
otherwise = String -> SDoc -> NatM Register
forall a. HasCallStack => String -> SDoc -> a
pprPanic "getRegister(x86)" (CmmExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmExpr
other)
intLoadCode :: (Operand -> Operand -> Instr) -> CmmExpr
-> NatM (Reg -> InstrBlock)
intLoadCode :: (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode instr :: Operand -> Operand -> Instr
instr mem :: CmmExpr
mem = do
Amode src :: AddrMode
src mem_code :: OrdList Instr
mem_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
(Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (\dst :: Reg
dst -> OrdList Instr
mem_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Operand -> Operand -> Instr
instr (AddrMode -> Operand
OpAddr AddrMode
src) (Reg -> Operand
OpReg Reg
dst))
getAnyReg :: CmmExpr -> NatM (Reg -> InstrBlock)
getAnyReg :: CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg expr :: CmmExpr
expr = do
Register
r <- CmmExpr -> NatM Register
getRegister CmmExpr
expr
Register -> NatM (Reg -> OrdList Instr)
anyReg Register
r
anyReg :: Register -> NatM (Reg -> InstrBlock)
anyReg :: Register -> NatM (Reg -> OrdList Instr)
anyReg (Any _ code :: Reg -> OrdList Instr
code) = (Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return Reg -> OrdList Instr
code
anyReg (Fixed rep :: Format
rep reg :: Reg
reg fcode :: OrdList Instr
fcode) = (Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (\dst :: Reg
dst -> OrdList Instr
fcode OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Reg -> Reg -> Instr
reg2reg Format
rep Reg
reg Reg
dst)
getByteReg :: CmmExpr -> NatM (Reg, InstrBlock)
getByteReg :: CmmExpr -> NatM (Reg, OrdList Instr)
getByteReg expr :: CmmExpr
expr = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
if Bool
is32Bit
then do Register
r <- CmmExpr -> NatM Register
getRegister CmmExpr
expr
case Register
r of
Any rep :: Format
rep code :: Reg -> OrdList Instr
code -> do
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
tmp, Reg -> OrdList Instr
code Reg
tmp)
Fixed rep :: Format
rep reg :: Reg
reg code :: OrdList Instr
code
| Reg -> Bool
isVirtualReg Reg
reg -> (Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
reg,OrdList Instr
code)
| Bool
otherwise -> do
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
tmp, OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Reg -> Reg -> Instr
reg2reg Format
rep Reg
reg Reg
tmp)
else CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
getNonClobberedReg :: CmmExpr -> NatM (Reg, InstrBlock)
getNonClobberedReg :: CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg expr :: CmmExpr
expr = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Register
r <- CmmExpr -> NatM Register
getRegister CmmExpr
expr
case Register
r of
Any rep :: Format
rep code :: Reg -> OrdList Instr
code -> do
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
tmp, Reg -> OrdList Instr
code Reg
tmp)
Fixed rep :: Format
rep reg :: Reg
reg code :: OrdList Instr
code
| Reg
reg Reg -> [Reg] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Platform -> [Reg]
instrClobberedRegs (DynFlags -> Platform
targetPlatform DynFlags
dflags)
-> do
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
tmp, OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Reg -> Reg -> Instr
reg2reg Format
rep Reg
reg Reg
tmp)
| Bool
otherwise ->
(Reg, OrdList Instr) -> NatM (Reg, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg
reg, OrdList Instr
code)
reg2reg :: Format -> Reg -> Reg -> Instr
reg2reg :: Format -> Reg -> Reg -> Instr
reg2reg format :: Format
format src :: Reg
src dst :: Reg
dst
| Format
format Format -> Format -> Bool
forall a. Eq a => a -> a -> Bool
== Format
FF80 = Reg -> Reg -> Instr
GMOV Reg
src Reg
dst
| Bool
otherwise = Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
src) (Reg -> Operand
OpReg Reg
dst)
getAmode :: CmmExpr -> NatM Amode
getAmode :: CmmExpr -> NatM Amode
getAmode e :: CmmExpr
e = do Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool -> CmmExpr -> NatM Amode
getAmode' Bool
is32Bit CmmExpr
e
getAmode' :: Bool -> CmmExpr -> NatM Amode
getAmode' :: Bool -> CmmExpr -> NatM Amode
getAmode' _ (CmmRegOff r :: CmmReg
r n :: Alignment
n) = do DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
CmmExpr -> NatM Amode
getAmode (CmmExpr -> NatM Amode) -> CmmExpr -> NatM Amode
forall a b. (a -> b) -> a -> b
$ DynFlags -> CmmReg -> Alignment -> CmmExpr
mangleIndexTree DynFlags
dflags CmmReg
r Alignment
n
getAmode' is32Bit :: Bool
is32Bit (CmmMachOp (MO_Add W64) [CmmReg (CmmGlobal PicBaseReg),
CmmLit displacement :: CmmLit
displacement])
| Bool -> Bool
not Bool
is32Bit
= Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (Amode -> NatM Amode) -> Amode -> NatM Amode
forall a b. (a -> b) -> a -> b
$ AddrMode -> OrdList Instr -> Amode
Amode (Imm -> AddrMode
ripRel (CmmLit -> Imm
litToImm CmmLit
displacement)) OrdList Instr
forall a. OrdList a
nilOL
getAmode' is32Bit :: Bool
is32Bit (CmmMachOp (MO_Sub _rep :: Width
_rep) [x :: CmmExpr
x, CmmLit lit :: CmmLit
lit@(CmmInt i :: Integer
i _)])
| Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
= do (x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let off :: Imm
off = Alignment -> Imm
ImmInt (-(Integer -> Alignment
forall a. Num a => Integer -> a
fromInteger Integer
i))
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
x_reg) EAIndex
EAIndexNone Imm
off) OrdList Instr
x_code)
getAmode' is32Bit :: Bool
is32Bit (CmmMachOp (MO_Add _rep :: Width
_rep) [x :: CmmExpr
x, CmmLit lit :: CmmLit
lit])
| Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
= do (x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let off :: Imm
off = CmmLit -> Imm
litToImm CmmLit
lit
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
x_reg) EAIndex
EAIndexNone Imm
off) OrdList Instr
x_code)
getAmode' is32Bit :: Bool
is32Bit (CmmMachOp (MO_Add rep :: Width
rep) [a :: CmmExpr
a@(CmmMachOp (MO_Shl _) _),
b :: CmmExpr
b@(CmmLit _)])
= Bool -> CmmExpr -> NatM Amode
getAmode' Bool
is32Bit (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add Width
rep) [CmmExpr
b,CmmExpr
a])
getAmode' _ (CmmMachOp (MO_Add _) [CmmRegOff x :: CmmReg
x offset :: Alignment
offset,
CmmMachOp (MO_Shl _)
[y :: CmmExpr
y, CmmLit (CmmInt shift :: Integer
shift _)]])
| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 1 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 2 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 3
= CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode (CmmReg -> CmmExpr
CmmReg CmmReg
x) CmmExpr
y Integer
shift (Alignment -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Alignment
offset)
getAmode' _ (CmmMachOp (MO_Add _) [x :: CmmExpr
x, CmmMachOp (MO_Shl _)
[y :: CmmExpr
y, CmmLit (CmmInt shift :: Integer
shift _)]])
| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 1 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 2 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 3
= CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode CmmExpr
x CmmExpr
y Integer
shift 0
getAmode' _ (CmmMachOp (MO_Add _)
[x :: CmmExpr
x, CmmMachOp (MO_Add _)
[CmmMachOp (MO_Shl _) [y :: CmmExpr
y, CmmLit (CmmInt shift :: Integer
shift _)],
CmmLit (CmmInt offset :: Integer
offset _)]])
| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 1 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 2 Bool -> Bool -> Bool
|| Integer
shift Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 3
Bool -> Bool -> Bool
&& Integer -> Bool
is32BitInteger Integer
offset
= CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode CmmExpr
x CmmExpr
y Integer
shift Integer
offset
getAmode' _ (CmmMachOp (MO_Add _) [x :: CmmExpr
x,y :: CmmExpr
y])
= CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode CmmExpr
x CmmExpr
y 0 0
getAmode' is32Bit :: Bool
is32Bit (CmmLit lit :: CmmLit
lit) | Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
= Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode (Imm -> Alignment -> AddrMode
ImmAddr (CmmLit -> Imm
litToImm CmmLit
lit) 0) OrdList Instr
forall a. OrdList a
nilOL)
getAmode' _ expr :: CmmExpr
expr = do
(reg :: Reg
reg,code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
reg) EAIndex
EAIndexNone (Alignment -> Imm
ImmInt 0)) OrdList Instr
code)
getSimpleAmode :: DynFlags -> Bool -> CmmExpr -> NatM Amode
getSimpleAmode :: DynFlags -> Bool -> CmmExpr -> NatM Amode
getSimpleAmode dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit addr :: CmmExpr
addr
| Bool
is32Bit = do
Reg -> OrdList Instr
addr_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
addr
Reg
addr_r <- Format -> NatM Reg
getNewRegNat (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags))
let amode :: AddrMode
amode = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
addr_r) EAIndex
EAIndexNone (Alignment -> Imm
ImmInt 0)
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (Amode -> NatM Amode) -> Amode -> NatM Amode
forall a b. (a -> b) -> a -> b
$! AddrMode -> OrdList Instr -> Amode
Amode AddrMode
amode (Reg -> OrdList Instr
addr_code Reg
addr_r)
| Bool
otherwise = CmmExpr -> NatM Amode
getAmode CmmExpr
addr
x86_complex_amode :: CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode :: CmmExpr -> CmmExpr -> Integer -> Integer -> NatM Amode
x86_complex_amode base :: CmmExpr
base index :: CmmExpr
index shift :: Integer
shift offset :: Integer
offset
= do (x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
base
(y_reg :: Reg
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
index
let
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
y_code
base :: Alignment
base = case Integer
shift of 0 -> 1; 1 -> 2; 2 -> 4; 3 -> 8;
n :: Integer
n -> String -> Alignment
forall a. String -> a
panic (String -> Alignment) -> String -> Alignment
forall a b. (a -> b) -> a -> b
$ "x86_complex_amode: unhandled shift! (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
x_reg) (Reg -> Alignment -> EAIndex
EAIndex Reg
y_reg Alignment
base) (Alignment -> Imm
ImmInt (Integer -> Alignment
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
offset)))
OrdList Instr
code)
getNonClobberedOperand :: CmmExpr -> NatM (Operand, InstrBlock)
getNonClobberedOperand :: CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand (CmmLit lit :: CmmLit
lit) = do
Bool
use_sse2 <- NatM Bool
sse2Enabled
if Bool
use_sse2 Bool -> Bool -> Bool
&& CmmLit -> Bool
isSuitableFloatingPointLit CmmLit
lit
then do
let CmmFloat _ w :: Width
w = CmmLit
lit
Amode addr :: AddrMode
addr code :: OrdList Instr
code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
lit
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> Operand
OpAddr AddrMode
addr, OrdList Instr
code)
else do
Bool
is32Bit <- NatM Bool
is32BitPlatform
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
if Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmType -> Bool
isFloatType (DynFlags -> CmmLit -> CmmType
cmmLitType DynFlags
dflags CmmLit
lit))
then (Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit), OrdList Instr
forall a. OrdList a
nilOL)
else CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand_generic (CmmLit -> CmmExpr
CmmLit CmmLit
lit)
getNonClobberedOperand (CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk) = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool
use_sse2 <- NatM Bool
sse2Enabled
if (Bool -> Bool
not (CmmType -> Bool
isFloatType CmmType
pk) Bool -> Bool -> Bool
|| Bool
use_sse2)
Bool -> Bool -> Bool
&& (if Bool
is32Bit then Bool -> Bool
not (CmmType -> Bool
isWord64 CmmType
pk) else Bool
True)
then do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
Amode src :: AddrMode
src mem_code :: OrdList Instr
mem_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
(src' :: AddrMode
src',save_code :: OrdList Instr
save_code) <-
if (Platform -> AddrMode -> Bool
amodeCouldBeClobbered Platform
platform AddrMode
src)
then do
Reg
tmp <- Format -> NatM Reg
getNewRegNat (Bool -> Format
archWordFormat Bool
is32Bit)
(AddrMode, OrdList Instr) -> NatM (AddrMode, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
tmp) EAIndex
EAIndexNone (Alignment -> Imm
ImmInt 0),
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
LEA (Bool -> Format
archWordFormat Bool
is32Bit)
(AddrMode -> Operand
OpAddr AddrMode
src)
(Reg -> Operand
OpReg Reg
tmp)))
else
(AddrMode, OrdList Instr) -> NatM (AddrMode, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode
src, OrdList Instr
forall a. OrdList a
nilOL)
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> Operand
OpAddr AddrMode
src', OrdList Instr
mem_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
save_code)
else do
CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand_generic (CmmExpr -> CmmType -> CmmExpr
CmmLoad CmmExpr
mem CmmType
pk)
getNonClobberedOperand e :: CmmExpr
e = CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand_generic CmmExpr
e
getNonClobberedOperand_generic :: CmmExpr -> NatM (Operand, InstrBlock)
getNonClobberedOperand_generic :: CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand_generic e :: CmmExpr
e = do
(reg :: Reg
reg, code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
e
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> Operand
OpReg Reg
reg, OrdList Instr
code)
amodeCouldBeClobbered :: Platform -> AddrMode -> Bool
amodeCouldBeClobbered :: Platform -> AddrMode -> Bool
amodeCouldBeClobbered platform :: Platform
platform amode :: AddrMode
amode = (Reg -> Bool) -> [Reg] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Platform -> Reg -> Bool
regClobbered Platform
platform) (AddrMode -> [Reg]
addrModeRegs AddrMode
amode)
regClobbered :: Platform -> Reg -> Bool
regClobbered :: Platform -> Reg -> Bool
regClobbered platform :: Platform
platform (RegReal (RealRegSingle rr :: Alignment
rr)) = Platform -> Alignment -> Bool
freeReg Platform
platform Alignment
rr
regClobbered _ _ = Bool
False
getOperand :: CmmExpr -> NatM (Operand, InstrBlock)
getOperand :: CmmExpr -> NatM (Operand, OrdList Instr)
getOperand (CmmLit lit :: CmmLit
lit) = do
Bool
use_sse2 <- NatM Bool
sse2Enabled
if (Bool
use_sse2 Bool -> Bool -> Bool
&& CmmLit -> Bool
isSuitableFloatingPointLit CmmLit
lit)
then do
let CmmFloat _ w :: Width
w = CmmLit
lit
Amode addr :: AddrMode
addr code :: OrdList Instr
code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
lit
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> Operand
OpAddr AddrMode
addr, OrdList Instr
code)
else do
Bool
is32Bit <- NatM Bool
is32BitPlatform
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
if Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit Bool -> Bool -> Bool
&& Bool -> Bool
not (CmmType -> Bool
isFloatType (DynFlags -> CmmLit -> CmmType
cmmLitType DynFlags
dflags CmmLit
lit))
then (Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit), OrdList Instr
forall a. OrdList a
nilOL)
else CmmExpr -> NatM (Operand, OrdList Instr)
getOperand_generic (CmmLit -> CmmExpr
CmmLit CmmLit
lit)
getOperand (CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk) = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool
use_sse2 <- NatM Bool
sse2Enabled
if (Bool -> Bool
not (CmmType -> Bool
isFloatType CmmType
pk) Bool -> Bool -> Bool
|| Bool
use_sse2) Bool -> Bool -> Bool
&& (if Bool
is32Bit then Bool -> Bool
not (CmmType -> Bool
isWord64 CmmType
pk) else Bool
True)
then do
Amode src :: AddrMode
src mem_code :: OrdList Instr
mem_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> Operand
OpAddr AddrMode
src, OrdList Instr
mem_code)
else
CmmExpr -> NatM (Operand, OrdList Instr)
getOperand_generic (CmmExpr -> CmmType -> CmmExpr
CmmLoad CmmExpr
mem CmmType
pk)
getOperand e :: CmmExpr
e = CmmExpr -> NatM (Operand, OrdList Instr)
getOperand_generic CmmExpr
e
getOperand_generic :: CmmExpr -> NatM (Operand, InstrBlock)
getOperand_generic :: CmmExpr -> NatM (Operand, OrdList Instr)
getOperand_generic e :: CmmExpr
e = do
(reg :: Reg
reg, code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
e
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> Operand
OpReg Reg
reg, OrdList Instr
code)
isOperand :: Bool -> CmmExpr -> Bool
isOperand :: Bool -> CmmExpr -> Bool
isOperand _ (CmmLoad _ _) = Bool
True
isOperand is32Bit :: Bool
is32Bit (CmmLit lit :: CmmLit
lit) = Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
Bool -> Bool -> Bool
|| CmmLit -> Bool
isSuitableFloatingPointLit CmmLit
lit
isOperand _ _ = Bool
False
addAlignmentCheck :: Int -> Register -> Register
addAlignmentCheck :: Alignment -> Register -> Register
addAlignmentCheck align :: Alignment
align reg :: Register
reg =
case Register
reg of
Fixed fmt :: Format
fmt reg :: Reg
reg code :: OrdList Instr
code -> Format -> Reg -> OrdList Instr -> Register
Fixed Format
fmt Reg
reg (OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Format -> Reg -> OrdList Instr
check Format
fmt Reg
reg)
Any fmt :: Format
fmt f :: Reg -> OrdList Instr
f -> Format -> (Reg -> OrdList Instr) -> Register
Any Format
fmt (\reg :: Reg
reg -> Reg -> OrdList Instr
f Reg
reg OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Format -> Reg -> OrdList Instr
check Format
fmt Reg
reg)
where
check :: Format -> Reg -> InstrBlock
check :: Format -> Reg -> OrdList Instr
check fmt :: Format
fmt reg :: Reg
reg =
ASSERT(not $ isFloatFormat fmt)
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
TEST Format
fmt (Imm -> Operand
OpImm (Imm -> Operand) -> Imm -> Operand
forall a b. (a -> b) -> a -> b
$ Alignment -> Imm
ImmInt (Alignment -> Imm) -> Alignment -> Imm
forall a b. (a -> b) -> a -> b
$ Alignment
alignAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-1) (Reg -> Operand
OpReg Reg
reg)
, Cond -> Imm -> Instr
JXX_GBL Cond
NE (Imm -> Instr) -> Imm -> Instr
forall a b. (a -> b) -> a -> b
$ CLabel -> Imm
ImmCLbl CLabel
mkBadAlignmentLabel
]
memConstant :: Int -> CmmLit -> NatM Amode
memConstant :: Alignment -> CmmLit -> NatM Amode
memConstant align :: Alignment
align lit :: CmmLit
lit = do
CLabel
lbl <- NatM CLabel
getNewLabelNat
let rosection :: Section
rosection = SectionType -> CLabel -> Section
Section SectionType
ReadOnlyData CLabel
lbl
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(addr :: AddrMode
addr, addr_code :: OrdList Instr
addr_code) <- if Platform -> Bool
target32Bit (DynFlags -> Platform
targetPlatform DynFlags
dflags)
then do CmmExpr
dynRef <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference
DynFlags
dflags
ReferenceKind
DataReference
CLabel
lbl
Amode addr :: AddrMode
addr addr_code :: OrdList Instr
addr_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
dynRef
(AddrMode, OrdList Instr) -> NatM (AddrMode, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode
addr, OrdList Instr
addr_code)
else (AddrMode, OrdList Instr) -> NatM (AddrMode, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Imm -> AddrMode
ripRel (CLabel -> Imm
ImmCLbl CLabel
lbl), OrdList Instr
forall a. OrdList a
nilOL)
let code :: OrdList Instr
code =
Section -> (Alignment, CmmStatics) -> Instr
LDATA Section
rosection (Alignment
align, CLabel -> [CmmStatic] -> CmmStatics
Statics CLabel
lbl [CmmLit -> CmmStatic
CmmStaticLit CmmLit
lit])
Instr -> OrdList Instr -> OrdList Instr
forall a. a -> OrdList a -> OrdList a
`consOL` OrdList Instr
addr_code
Amode -> NatM Amode
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> OrdList Instr -> Amode
Amode AddrMode
addr OrdList Instr
code)
loadFloatAmode :: Bool -> Width -> AddrMode -> InstrBlock -> NatM Register
loadFloatAmode :: Bool -> Width -> AddrMode -> OrdList Instr -> NatM Register
loadFloatAmode use_sse2 :: Bool
use_sse2 w :: Width
w addr :: AddrMode
addr addr_code :: OrdList Instr
addr_code = do
let format :: Format
format = Width -> Format
floatFormat Width
w
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
addr_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
if Bool
use_sse2
then Format -> Operand -> Operand -> Instr
MOV Format
format (AddrMode -> Operand
OpAddr AddrMode
addr) (Reg -> Operand
OpReg Reg
dst)
else Format -> AddrMode -> Reg -> Instr
GLD Format
format AddrMode
addr Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (if Bool
use_sse2 then Format
format else Format
FF80) Reg -> OrdList Instr
code)
isSuitableFloatingPointLit :: CmmLit -> Bool
isSuitableFloatingPointLit :: CmmLit -> Bool
isSuitableFloatingPointLit (CmmFloat f :: Rational
f _) = Rational
f Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= 0.0
isSuitableFloatingPointLit _ = Bool
False
getRegOrMem :: CmmExpr -> NatM (Operand, InstrBlock)
getRegOrMem :: CmmExpr -> NatM (Operand, OrdList Instr)
getRegOrMem e :: CmmExpr
e@(CmmLoad mem :: CmmExpr
mem pk :: CmmType
pk) = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool
use_sse2 <- NatM Bool
sse2Enabled
if (Bool -> Bool
not (CmmType -> Bool
isFloatType CmmType
pk) Bool -> Bool -> Bool
|| Bool
use_sse2) Bool -> Bool -> Bool
&& (if Bool
is32Bit then Bool -> Bool
not (CmmType -> Bool
isWord64 CmmType
pk) else Bool
True)
then do
Amode src :: AddrMode
src mem_code :: OrdList Instr
mem_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AddrMode -> Operand
OpAddr AddrMode
src, OrdList Instr
mem_code)
else do
(reg :: Reg
reg, code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
e
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> Operand
OpReg Reg
reg, OrdList Instr
code)
getRegOrMem e :: CmmExpr
e = do
(reg :: Reg
reg, code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
e
(Operand, OrdList Instr) -> NatM (Operand, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> Operand
OpReg Reg
reg, OrdList Instr
code)
is32BitLit :: Bool -> CmmLit -> Bool
is32BitLit :: Bool -> CmmLit -> Bool
is32BitLit is32Bit :: Bool
is32Bit (CmmInt i :: Integer
i W64)
| Bool -> Bool
not Bool
is32Bit
=
Integer -> Bool
is32BitInteger Integer
i
is32BitLit _ _ = Bool
True
getCondCode :: CmmExpr -> NatM CondCode
getCondCode :: CmmExpr -> NatM CondCode
getCondCode (CmmMachOp mop :: MachOp
mop [x :: CmmExpr
x, y :: CmmExpr
y])
=
case MachOp
mop of
MO_F_Eq W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
EQQ CmmExpr
x CmmExpr
y
MO_F_Ne W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
NE CmmExpr
x CmmExpr
y
MO_F_Gt W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GTT CmmExpr
x CmmExpr
y
MO_F_Ge W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GE CmmExpr
x CmmExpr
y
MO_F_Lt W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GTT CmmExpr
y CmmExpr
x
MO_F_Le W32 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GE CmmExpr
y CmmExpr
x
MO_F_Eq W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
EQQ CmmExpr
x CmmExpr
y
MO_F_Ne W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
NE CmmExpr
x CmmExpr
y
MO_F_Gt W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GTT CmmExpr
x CmmExpr
y
MO_F_Ge W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GE CmmExpr
x CmmExpr
y
MO_F_Lt W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GTT CmmExpr
y CmmExpr
x
MO_F_Le W64 -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
GE CmmExpr
y CmmExpr
x
_ -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode (MachOp -> Cond
machOpToCond MachOp
mop) CmmExpr
x CmmExpr
y
getCondCode other :: CmmExpr
other = String -> SDoc -> NatM CondCode
forall a. HasCallStack => String -> SDoc -> a
pprPanic "getCondCode(2)(x86,x86_64)" (CmmExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmExpr
other)
machOpToCond :: MachOp -> Cond
machOpToCond :: MachOp -> Cond
machOpToCond mo :: MachOp
mo = case MachOp
mo of
MO_Eq _ -> Cond
EQQ
MO_Ne _ -> Cond
NE
MO_S_Gt _ -> Cond
GTT
MO_S_Ge _ -> Cond
GE
MO_S_Lt _ -> Cond
LTT
MO_S_Le _ -> Cond
LE
MO_U_Gt _ -> Cond
GU
MO_U_Ge _ -> Cond
GEU
MO_U_Lt _ -> Cond
LU
MO_U_Le _ -> Cond
LEU
_other :: MachOp
_other -> String -> SDoc -> Cond
forall a. HasCallStack => String -> SDoc -> a
pprPanic "machOpToCond" (MachOp -> SDoc
pprMachOp MachOp
mo)
condIntCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y = do Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode' Bool
is32Bit Cond
cond CmmExpr
x CmmExpr
y
condIntCode' :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode' :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode' is32Bit :: Bool
is32Bit cond :: Cond
cond (CmmLoad x :: CmmExpr
x pk :: CmmType
pk) (CmmLit lit :: CmmLit
lit)
| Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit = do
Amode x_addr :: AddrMode
x_addr x_code :: OrdList Instr
x_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
x
let
imm :: Imm
imm = CmmLit -> Imm
litToImm CmmLit
lit
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
CMP (CmmType -> Format
cmmTypeFormat CmmType
pk) (Imm -> Operand
OpImm Imm
imm) (AddrMode -> Operand
OpAddr AddrMode
x_addr)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
cond OrdList Instr
code)
condIntCode' is32Bit :: Bool
is32Bit cond :: Cond
cond (CmmMachOp (MO_And _) [x :: CmmExpr
x,o2 :: CmmExpr
o2]) (CmmLit (CmmInt 0 pk :: Width
pk))
| (CmmLit lit :: CmmLit
lit@(CmmInt mask :: Integer
mask _)) <- CmmExpr
o2, Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
= do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
TEST (Width -> Format
intFormat Width
pk) (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
mask)) (Reg -> Operand
OpReg Reg
x_reg)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
cond OrdList Instr
code)
condIntCode' _ cond :: Cond
cond x :: CmmExpr
x (CmmLit (CmmInt 0 pk :: Width
pk)) = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
TEST (Width -> Format
intFormat Width
pk) (Reg -> Operand
OpReg Reg
x_reg) (Reg -> Operand
OpReg Reg
x_reg)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
cond OrdList Instr
code)
condIntCode' is32Bit :: Bool
is32Bit cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y
| Bool -> CmmExpr -> Bool
isOperand Bool
is32Bit CmmExpr
y = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
x
(y_op :: Operand
y_op, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
y
let
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
y_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
CMP (CmmType -> Format
cmmTypeFormat (DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
x)) Operand
y_op (Reg -> Operand
OpReg Reg
x_reg)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
cond OrdList Instr
code)
| Bool -> CmmExpr -> Bool
isOperand Bool
is32Bit CmmExpr
x
, Just revcond :: Cond
revcond <- Cond -> Maybe Cond
maybeFlipCond Cond
cond = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(y_reg :: Reg
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
y
(x_op :: Operand
x_op, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
x
let
code :: OrdList Instr
code = OrdList Instr
y_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
CMP (CmmType -> Format
cmmTypeFormat (DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
x)) Operand
x_op (Reg -> Operand
OpReg Reg
y_reg)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
revcond OrdList Instr
code)
condIntCode' _ cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(y_reg :: Reg
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
y
(x_op :: Operand
x_op, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getRegOrMem CmmExpr
x
let
code :: OrdList Instr
code = OrdList Instr
y_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
CMP (CmmType -> Format
cmmTypeFormat (DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
x)) (Reg -> Operand
OpReg Reg
y_reg) Operand
x_op
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
False Cond
cond OrdList Instr
code)
condFltCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y
= NatM CondCode -> NatM CondCode -> NatM CondCode
forall a. NatM a -> NatM a -> NatM a
if_sse2 NatM CondCode
condFltCode_sse2 NatM CondCode
condFltCode_x87
where
condFltCode_x87 :: NatM CondCode
condFltCode_x87
= ASSERT(cond `elem` ([EQQ, NE, LE, LTT, GE, GTT])) do
(x_reg, x_code) <- getNonClobberedReg x
(y_reg, y_code) <- getSomeReg y
let
code = x_code `appOL` y_code `snocOL`
GCMP cond x_reg y_reg
return (CondCode True EQQ code)
condFltCode_sse2 :: NatM CondCode
condFltCode_sse2 = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
x
(y_op :: Operand
y_op, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
y
let
code :: OrdList Instr
code = OrdList Instr
x_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
y_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
CMP (Width -> Format
floatFormat (Width -> Format) -> Width -> Format
forall a b. (a -> b) -> a -> b
$ DynFlags -> CmmExpr -> Width
cmmExprWidth DynFlags
dflags CmmExpr
x) Operand
y_op (Reg -> Operand
OpReg Reg
x_reg)
CondCode -> NatM CondCode
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Cond -> OrdList Instr -> CondCode
CondCode Bool
True (Cond -> Cond
condToUnsigned Cond
cond) OrdList Instr
code)
assignMem_IntCode :: Format -> CmmExpr -> CmmExpr -> NatM InstrBlock
assignReg_IntCode :: Format -> CmmReg -> CmmExpr -> NatM InstrBlock
assignMem_FltCode :: Format -> CmmExpr -> CmmExpr -> NatM InstrBlock
assignReg_FltCode :: Format -> CmmReg -> CmmExpr -> NatM InstrBlock
assignMem_IntCode :: Format -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_IntCode pk :: Format
pk addr :: CmmExpr
addr (CmmMachOp op :: MachOp
op [CmmLoad addr2 :: CmmExpr
addr2 _,
CmmLit (CmmInt i :: Integer
i _)])
| CmmExpr
addr CmmExpr -> CmmExpr -> Bool
forall a. Eq a => a -> a -> Bool
== CmmExpr
addr2, Format
pk Format -> Format -> Bool
forall a. Eq a => a -> a -> Bool
/= Format
II64 Bool -> Bool -> Bool
|| Integer -> Bool
is32BitInteger Integer
i,
Just instr :: Format -> Operand -> Operand -> Instr
instr <- MachOp -> Maybe (Format -> Operand -> Operand -> Instr)
check MachOp
op
= do Amode amode :: AddrMode
amode code_addr :: OrdList Instr
code_addr <- CmmExpr -> NatM Amode
getAmode CmmExpr
addr
let code :: OrdList Instr
code = OrdList Instr
code_addr OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
instr Format
pk (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt (Integer -> Alignment
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i))) (AddrMode -> Operand
OpAddr AddrMode
amode)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
where
check :: MachOp -> Maybe (Format -> Operand -> Operand -> Instr)
check (MO_Add _) = (Format -> Operand -> Operand -> Instr)
-> Maybe (Format -> Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just Format -> Operand -> Operand -> Instr
ADD
check (MO_Sub _) = (Format -> Operand -> Operand -> Instr)
-> Maybe (Format -> Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just Format -> Operand -> Operand -> Instr
SUB
check _ = Maybe (Format -> Operand -> Operand -> Instr)
forall a. Maybe a
Nothing
assignMem_IntCode pk :: Format
pk addr :: CmmExpr
addr src :: CmmExpr
src = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
Amode addr :: AddrMode
addr code_addr :: OrdList Instr
code_addr <- CmmExpr -> NatM Amode
getAmode CmmExpr
addr
(code_src :: OrdList Instr
code_src, op_src :: Operand
op_src) <- Bool -> CmmExpr -> NatM (OrdList Instr, Operand)
get_op_RI Bool
is32Bit CmmExpr
src
let
code :: OrdList Instr
code = OrdList Instr
code_src OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
code_addr OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
pk Operand
op_src (AddrMode -> Operand
OpAddr AddrMode
addr)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
where
get_op_RI :: Bool -> CmmExpr -> NatM (InstrBlock,Operand)
get_op_RI :: Bool -> CmmExpr -> NatM (OrdList Instr, Operand)
get_op_RI is32Bit :: Bool
is32Bit (CmmLit lit :: CmmLit
lit) | Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit
= (OrdList Instr, Operand) -> NatM (OrdList Instr, Operand)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
forall a. OrdList a
nilOL, Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit))
get_op_RI _ op :: CmmExpr
op
= do (reg :: Reg
reg,code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
op
(OrdList Instr, Operand) -> NatM (OrdList Instr, Operand)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code, Reg -> Operand
OpReg Reg
reg)
assignReg_IntCode :: Format -> CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_IntCode pk :: Format
pk reg :: CmmReg
reg (CmmLoad src :: CmmExpr
src _) = do
Reg -> OrdList Instr
load_code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOV Format
pk) CmmExpr
src
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> OrdList Instr
load_code (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False CmmReg
reg))
assignReg_IntCode _ reg :: CmmReg
reg src :: CmmExpr
src = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
Reg -> OrdList Instr
code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> OrdList Instr
code (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False CmmReg
reg))
assignMem_FltCode :: Format -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_FltCode pk :: Format
pk addr :: CmmExpr
addr src :: CmmExpr
src = do
(src_reg :: Reg
src_reg, src_code :: OrdList Instr
src_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
src
Amode addr :: AddrMode
addr addr_code :: OrdList Instr
addr_code <- CmmExpr -> NatM Amode
getAmode CmmExpr
addr
Bool
use_sse2 <- NatM Bool
sse2Enabled
let
code :: OrdList Instr
code = OrdList Instr
src_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
addr_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
if Bool
use_sse2 then Format -> Operand -> Operand -> Instr
MOV Format
pk (Reg -> Operand
OpReg Reg
src_reg) (AddrMode -> Operand
OpAddr AddrMode
addr)
else Format -> Reg -> AddrMode -> Instr
GST Format
pk Reg
src_reg AddrMode
addr
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
assignReg_FltCode :: Format -> CmmReg -> CmmExpr -> NatM (OrdList Instr)
assignReg_FltCode _ reg :: CmmReg
reg src :: CmmExpr
src = do
Bool
use_sse2 <- NatM Bool
sse2Enabled
Reg -> OrdList Instr
src_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> OrdList Instr
src_code (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 CmmReg
reg))
genJump :: CmmExpr -> [Reg] -> NatM InstrBlock
genJump :: CmmExpr -> [Reg] -> NatM (OrdList Instr)
genJump (CmmLoad mem :: CmmExpr
mem _) regs :: [Reg]
regs = do
Amode target :: AddrMode
target code :: OrdList Instr
code <- CmmExpr -> NatM Amode
getAmode CmmExpr
mem
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Operand -> [Reg] -> Instr
JMP (AddrMode -> Operand
OpAddr AddrMode
target) [Reg]
regs)
genJump (CmmLit lit :: CmmLit
lit) regs :: [Reg]
regs = do
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Operand -> [Reg] -> Instr
JMP (Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit)) [Reg]
regs))
genJump expr :: CmmExpr
expr regs :: [Reg]
regs = do
(reg :: Reg
reg,code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Operand -> [Reg] -> Instr
JMP (Reg -> Operand
OpReg Reg
reg) [Reg]
regs)
genBranch :: BlockId -> InstrBlock
genBranch :: Label -> OrdList Instr
genBranch = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL ([Instr] -> OrdList Instr)
-> (Label -> [Instr]) -> Label -> OrdList Instr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Label -> [Instr]
forall instr. Instruction instr => Label -> [instr]
mkJumpInstr
genCondBranch
:: BlockId
-> BlockId
-> BlockId
-> CmmExpr
-> NatM InstrBlock
genCondBranch :: Label -> Label -> Label -> CmmExpr -> NatM (OrdList Instr)
genCondBranch bid :: Label
bid id :: Label
id false :: Label
false expr :: CmmExpr
expr = do
Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool -> Label -> Label -> Label -> CmmExpr -> NatM (OrdList Instr)
genCondBranch' Bool
is32Bit Label
bid Label
id Label
false CmmExpr
expr
genCondBranch' :: Bool -> BlockId -> BlockId -> BlockId -> CmmExpr
-> NatM InstrBlock
genCondBranch' :: Bool -> Label -> Label -> Label -> CmmExpr -> NatM (OrdList Instr)
genCondBranch' is32Bit :: Bool
is32Bit _bid :: Label
_bid true :: Label
true false :: Label
false (CmmMachOp mop :: MachOp
mop [e1 :: CmmExpr
e1,e2 :: CmmExpr
e2])
| Bool
is32Bit, Just W64 <- MachOp -> Maybe Width
maybeIntComparison MachOp
mop = do
ChildCode64 code1 :: OrdList Instr
code1 r1_lo :: Reg
r1_lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e1
ChildCode64 code2 :: OrdList Instr
code2 r2_lo :: Reg
r2_lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
e2
let r1_hi :: Reg
r1_hi = Reg -> Reg
getHiVRegFromLo Reg
r1_lo
r2_hi :: Reg
r2_hi = Reg -> Reg
getHiVRegFromLo Reg
r2_lo
cond :: Cond
cond = MachOp -> Cond
machOpToCond MachOp
mop
Just cond' :: Cond
cond' = Cond -> Maybe Cond
maybeFlipCond Cond
cond
let code :: OrdList Instr
code = OrdList Instr
code1 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
code2 OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
CMP Format
II32 (Reg -> Operand
OpReg Reg
r2_hi) (Reg -> Operand
OpReg Reg
r1_hi),
Cond -> Label -> Instr
JXX Cond
cond Label
true,
Cond -> Label -> Instr
JXX Cond
cond' Label
false,
Format -> Operand -> Operand -> Instr
CMP Format
II32 (Reg -> Operand
OpReg Reg
r2_lo) (Reg -> Operand
OpReg Reg
r1_lo),
Cond -> Label -> Instr
JXX Cond
cond Label
true] OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Label -> OrdList Instr
genBranch Label
false
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
genCondBranch' _ bid :: Label
bid id :: Label
id false :: Label
false bool :: CmmExpr
bool = do
CondCode is_float :: Bool
is_float cond :: Cond
cond cond_code :: OrdList Instr
cond_code <- CmmExpr -> NatM CondCode
getCondCode CmmExpr
bool
Bool
use_sse2 <- NatM Bool
sse2Enabled
if Bool -> Bool
not Bool
is_float Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
use_sse2
then
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
cond_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Cond -> Label -> Instr
JXX Cond
cond Label
id OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Label -> OrdList Instr
genBranch Label
false)
else do
let jmpFalse :: OrdList Instr
jmpFalse = Label -> OrdList Instr
genBranch Label
false
code :: OrdList Instr
code
= case Cond
cond of
NE -> OrdList Instr
or_unordered
GU -> OrdList Instr
plain_test
GEU -> OrdList Instr
plain_test
LTT ->
ASSERT2(False, ppr "Should have been turned into >")
OrdList Instr
and_ordered
LE ->
ASSERT2(False, ppr "Should have been turned into >=")
OrdList Instr
and_ordered
_ -> OrdList Instr
and_ordered
plain_test :: OrdList Instr
plain_test = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (
Cond -> Label -> Instr
JXX Cond
cond Label
id
) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
jmpFalse
or_unordered :: OrdList Instr
or_unordered = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Label -> Instr
JXX Cond
cond Label
id,
Cond -> Label -> Instr
JXX Cond
PARITY Label
id
] OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
jmpFalse
and_ordered :: OrdList Instr
and_ordered = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Label -> Instr
JXX Cond
PARITY Label
false,
Cond -> Label -> Instr
JXX Cond
cond Label
id,
Cond -> Label -> Instr
JXX Cond
ALWAYS Label
false
]
(CFG -> CFG) -> NatM ()
updateCfgNat (\cfg :: CFG
cfg -> CFG -> (EdgeWeight -> EdgeWeight) -> Label -> Label -> CFG
adjustEdgeWeight CFG
cfg (EdgeWeight -> EdgeWeight -> EdgeWeight
forall a. Num a => a -> a -> a
+3) Label
bid Label
false)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
cond_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
code)
genCCall
:: DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmActual]
-> BlockId
-> NatM InstrBlock
genCCall :: DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Memcpy align :: Alignment
align)) _
[dst :: CmmExpr
dst, src :: CmmExpr
src, CmmLit (CmmInt n :: Integer
n _)] _
| Integer -> Alignment
forall a. Num a => Integer -> a
fromInteger Integer
insns Alignment -> Alignment -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Alignment
maxInlineMemcpyInsns DynFlags
dflags Bool -> Bool -> Bool
&& Alignment
align Alignment -> Alignment -> Alignment
forall a. Bits a => a -> a -> a
.&. 3 Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = do
Reg -> OrdList Instr
code_dst <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
dst
Reg
dst_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg
tmp_r <- Format -> NatM Reg
getNewRegNat Format
format
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_dst Reg
dst_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Reg -> Reg -> Integer -> OrdList Instr
go Reg
dst_r Reg
src_r Reg
tmp_r (Integer -> Integer
forall a. Num a => Integer -> a
fromInteger Integer
n)
where
insns :: Integer
insns = 2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* ((Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
sizeBytes Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
sizeBytes)
format :: Format
format = if Alignment
align Alignment -> Alignment -> Alignment
forall a. Bits a => a -> a -> a
.&. 4 Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
/= 0 then Format
II32 else (Bool -> Format
archWordFormat Bool
is32Bit)
sizeBytes :: Integer
sizeBytes :: Integer
sizeBytes = Alignment -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Format -> Alignment
formatInBytes Format
format)
go :: Reg -> Reg -> Reg -> Integer -> OrdList Instr
go :: Reg -> Reg -> Reg -> Integer -> OrdList Instr
go dst :: Reg
dst src :: Reg
src tmp :: Reg
tmp i :: Integer
i
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
sizeBytes =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
format (AddrMode -> Operand
OpAddr AddrMode
src_addr) (Reg -> Operand
OpReg Reg
tmp)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
tmp) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Reg -> Reg -> Integer -> OrdList Instr
go Reg
dst Reg
src Reg
tmp (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
sizeBytes)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 4 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II32 (AddrMode -> Operand
OpAddr AddrMode
src_addr) (Reg -> Operand
OpReg Reg
tmp)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
tmp) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Reg -> Reg -> Integer -> OrdList Instr
go Reg
dst Reg
src Reg
tmp (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 4)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 2 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16 (AddrMode -> Operand
OpAddr AddrMode
src_addr) (Reg -> Operand
OpReg Reg
tmp)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II16 (Reg -> Operand
OpReg Reg
tmp) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Reg -> Reg -> Integer -> OrdList Instr
go Reg
dst Reg
src Reg
tmp (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 2)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 1 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (AddrMode -> Operand
OpAddr AddrMode
src_addr) (Reg -> Operand
OpReg Reg
tmp)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II8 (Reg -> Operand
OpReg Reg
tmp) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Reg -> Reg -> Integer -> OrdList Instr
go Reg
dst Reg
src Reg
tmp (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1)
| Bool
otherwise = OrdList Instr
forall a. OrdList a
nilOL
where
src_addr :: AddrMode
src_addr = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
src) EAIndex
EAIndexNone
(Integer -> Imm
ImmInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
i))
dst_addr :: AddrMode
dst_addr = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
dst) EAIndex
EAIndexNone
(Integer -> Imm
ImmInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
i))
genCCall dflags :: DynFlags
dflags _ (PrimTarget (MO_Memset align :: Alignment
align)) _
[dst :: CmmExpr
dst,
CmmLit (CmmInt c :: Integer
c _),
CmmLit (CmmInt n :: Integer
n _)]
_
| Integer -> Alignment
forall a. Num a => Integer -> a
fromInteger Integer
insns Alignment -> Alignment -> Bool
forall a. Ord a => a -> a -> Bool
<= DynFlags -> Alignment
maxInlineMemsetInsns DynFlags
dflags Bool -> Bool -> Bool
&& Alignment
align Alignment -> Alignment -> Alignment
forall a. Bits a => a -> a -> a
.&. 3 Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = do
Reg -> OrdList Instr
code_dst <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
dst
Reg
dst_r <- Format -> NatM Reg
getNewRegNat Format
format
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_dst Reg
dst_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> Integer -> OrdList Instr
go Reg
dst_r (Integer -> Integer
forall a. Num a => Integer -> a
fromInteger Integer
n)
where
(format :: Format
format, val :: Integer
val) = case Alignment
align Alignment -> Alignment -> Alignment
forall a. Bits a => a -> a -> a
.&. 3 of
2 -> (Format
II16, Integer
c2)
0 -> (Format
II32, Integer
c4)
_ -> (Format
II8, Integer
c)
c2 :: Integer
c2 = Integer
c Integer -> Alignment -> Integer
forall a. Bits a => a -> Alignment -> a
`shiftL` 8 Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. Integer
c
c4 :: Integer
c4 = Integer
c2 Integer -> Alignment -> Integer
forall a. Bits a => a -> Alignment -> a
`shiftL` 16 Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. Integer
c2
insns :: Integer
insns = (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
sizeBytes Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
sizeBytes
sizeBytes :: Integer
sizeBytes :: Integer
sizeBytes = Alignment -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Format -> Alignment
formatInBytes Format
format)
go :: Reg -> Integer -> OrdList Instr
go :: Reg -> Integer -> OrdList Instr
go dst :: Reg
dst i :: Integer
i
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
sizeBytes =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
format (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
val)) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Integer -> OrdList Instr
go Reg
dst (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
sizeBytes)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 4 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
c4)) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Integer -> OrdList Instr
go Reg
dst (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 4)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 2 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II16 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
c2)) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Integer -> OrdList Instr
go Reg
dst (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 2)
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 1 =
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II8 (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger Integer
c)) (AddrMode -> Operand
OpAddr AddrMode
dst_addr)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> Integer -> OrdList Instr
go Reg
dst (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- 1)
| Bool
otherwise = OrdList Instr
forall a. OrdList a
nilOL
where
dst_addr :: AddrMode
dst_addr = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
dst) EAIndex
EAIndexNone
(Integer -> Imm
ImmInteger (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
i))
genCCall _ _ (PrimTarget MO_ReadBarrier) _ _ _ = OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
genCCall _ _ (PrimTarget MO_WriteBarrier) _ _ _ = OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
genCCall _ _ (PrimTarget MO_Touch) _ _ _ = OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
genCCall _ is32bit :: Bool
is32bit (PrimTarget (MO_Prefetch_Data n :: Alignment
n )) _ [src :: CmmExpr
src] _ =
case Alignment
n of
0 -> CmmExpr -> (Operand -> Instr) -> NatM (OrdList Instr)
genPrefetch CmmExpr
src ((Operand -> Instr) -> NatM (OrdList Instr))
-> (Operand -> Instr) -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ PrefetchVariant -> Format -> Operand -> Instr
PREFETCH PrefetchVariant
NTA Format
format
1 -> CmmExpr -> (Operand -> Instr) -> NatM (OrdList Instr)
genPrefetch CmmExpr
src ((Operand -> Instr) -> NatM (OrdList Instr))
-> (Operand -> Instr) -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ PrefetchVariant -> Format -> Operand -> Instr
PREFETCH PrefetchVariant
Lvl2 Format
format
2 -> CmmExpr -> (Operand -> Instr) -> NatM (OrdList Instr)
genPrefetch CmmExpr
src ((Operand -> Instr) -> NatM (OrdList Instr))
-> (Operand -> Instr) -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ PrefetchVariant -> Format -> Operand -> Instr
PREFETCH PrefetchVariant
Lvl1 Format
format
3 -> CmmExpr -> (Operand -> Instr) -> NatM (OrdList Instr)
genPrefetch CmmExpr
src ((Operand -> Instr) -> NatM (OrdList Instr))
-> (Operand -> Instr) -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ PrefetchVariant -> Format -> Operand -> Instr
PREFETCH PrefetchVariant
Lvl0 Format
format
l :: Alignment
l -> String -> NatM (OrdList Instr)
forall a. String -> a
panic (String -> NatM (OrdList Instr)) -> String -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ "unexpected prefetch level in genCCall MO_Prefetch_Data: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Alignment -> String
forall a. Show a => a -> String
show Alignment
l)
where
format :: Format
format = Bool -> Format
archWordFormat Bool
is32bit
genPrefetch :: CmmExpr -> (Operand -> Instr) -> NatM (OrdList Instr)
genPrefetch inRegSrc :: CmmExpr
inRegSrc prefetchCTor :: Operand -> Instr
prefetchCTor =
do
Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
inRegSrc
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Operand -> Instr
prefetchCTor (AddrMode -> Operand
OpAddr
((EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
src_r ) EAIndex
EAIndexNone (Alignment -> Imm
ImmInt 0)))) ))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_BSwap width :: Width
width)) [dst :: CmmFormal
dst] [src :: CmmExpr
src] _ = do
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
case Width
width of
W64 | Bool
is32Bit -> do
ChildCode64 vcode :: OrdList Instr
vcode rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
src
let dst_rhi :: Reg
dst_rhi = Reg -> Reg
getHiVRegFromLo Reg
dst_r
rhi :: Reg
rhi = Reg -> Reg
getHiVRegFromLo Reg
rlo
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
vcode OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
rlo) (Reg -> Operand
OpReg Reg
dst_rhi),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
rhi) (Reg -> Operand
OpReg Reg
dst_r),
Format -> Reg -> Instr
BSWAP Format
II32 Reg
dst_rhi,
Format -> Reg -> Instr
BSWAP Format
II32 Reg
dst_r ]
W16 -> do Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
dst_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Reg -> Instr
BSWAP Format
II32 Reg
dst_r) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
SHR Format
II32 (Imm -> Operand
OpImm (Imm -> Operand) -> Imm -> Operand
forall a b. (a -> b) -> a -> b
$ Alignment -> Imm
ImmInt 16) (Reg -> Operand
OpReg Reg
dst_r))
_ -> do Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
dst_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Reg -> Instr
BSWAP Format
format Reg
dst_r)
where
format :: Format
format = Width -> Format
intFormat Width
width
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_PopCnt width :: Width
width)) dest_regs :: [CmmFormal]
dest_regs@[dst :: CmmFormal
dst]
args :: [CmmExpr]
args@[src :: CmmExpr
src] bid :: Label
bid = do
Bool
sse4_2 <- NatM Bool
sse4_2Enabled
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
if Bool
sse4_2
then do Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
src_r) (Reg -> Operand
OpReg Reg
src_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Reg -> Instr
POPCNT Format
II16 (Reg -> Operand
OpReg Reg
src_r) Reg
dst_r)
else
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Reg -> Instr
POPCNT Format
format (Reg -> Operand
OpReg Reg
src_r) Reg
dst_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 Bool -> Bool -> Bool
|| Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W16 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16 (Reg -> Operand
OpReg Reg
dst_r) (Reg -> Operand
OpReg Reg
dst_r))
else OrdList Instr
forall a. OrdList a
nilOL)
else do
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags
ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr (CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv
[ForeignHint
NoHint] [ForeignHint
NoHint]
CmmReturnInfo
CmmMayReturn)
DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args Label
bid
where
format :: Format
format = Width -> Format
intFormat Width
width
lbl :: CLabel
lbl = UnitId -> FastString -> CLabel
mkCmmCodeLabel UnitId
primUnitId (String -> FastString
fsLit (Width -> String
popCntLabel Width
width))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Pdep width :: Width
width)) dest_regs :: [CmmFormal]
dest_regs@[dst :: CmmFormal
dst]
args :: [CmmExpr]
args@[src :: CmmExpr
src, mask :: CmmExpr
mask] bid :: Label
bid = do
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
if DynFlags -> Bool
isBmi2Enabled DynFlags
dflags
then do Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg -> OrdList Instr
code_mask <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
mask
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg
mask_r <- Format -> NatM Reg
getNewRegNat Format
format
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
code_mask Reg
mask_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
src_r ) (Reg -> Operand
OpReg Reg
src_r )) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
mask_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Reg -> Instr
PDEP Format
II16 (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
src_r ) Reg
dst_r)
else
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Reg -> Instr
PDEP Format
format (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
src_r) Reg
dst_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 Bool -> Bool -> Bool
|| Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W16 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16 (Reg -> Operand
OpReg Reg
dst_r) (Reg -> Operand
OpReg Reg
dst_r))
else OrdList Instr
forall a. OrdList a
nilOL)
else do
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags
ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr (CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv
[ForeignHint
NoHint] [ForeignHint
NoHint]
CmmReturnInfo
CmmMayReturn)
DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args Label
bid
where
format :: Format
format = Width -> Format
intFormat Width
width
lbl :: CLabel
lbl = UnitId -> FastString -> CLabel
mkCmmCodeLabel UnitId
primUnitId (String -> FastString
fsLit (Width -> String
pdepLabel Width
width))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Pext width :: Width
width)) dest_regs :: [CmmFormal]
dest_regs@[dst :: CmmFormal
dst]
args :: [CmmExpr]
args@[src :: CmmExpr
src, mask :: CmmExpr
mask] bid :: Label
bid = do
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
if DynFlags -> Bool
isBmi2Enabled DynFlags
dflags
then do Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg -> OrdList Instr
code_mask <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
mask
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg
mask_r <- Format -> NatM Reg
getNewRegNat Format
format
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
code_mask Reg
mask_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
src_r ) (Reg -> Operand
OpReg Reg
src_r )) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
mask_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Reg -> Instr
PEXT Format
II16 (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
src_r) Reg
dst_r)
else
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Reg -> Instr
PEXT Format
format (Reg -> Operand
OpReg Reg
mask_r) (Reg -> Operand
OpReg Reg
src_r) Reg
dst_r)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 Bool -> Bool -> Bool
|| Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W16 then
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOVZxL Format
II16 (Reg -> Operand
OpReg Reg
dst_r) (Reg -> Operand
OpReg Reg
dst_r))
else OrdList Instr
forall a. OrdList a
nilOL)
else do
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags
ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr (CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv
[ForeignHint
NoHint] [ForeignHint
NoHint]
CmmReturnInfo
CmmMayReturn)
DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args Label
bid
where
format :: Format
format = Width -> Format
intFormat Width
width
lbl :: CLabel
lbl = UnitId -> FastString -> CLabel
mkCmmCodeLabel UnitId
primUnitId (String -> FastString
fsLit (Width -> String
pextLabel Width
width))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Clz width :: Width
width)) dest_regs :: [CmmFormal]
dest_regs@[dst :: CmmFormal
dst] args :: [CmmExpr]
args@[src :: CmmExpr
src] bid :: Label
bid
| Bool
is32Bit Bool -> Bool -> Bool
&& Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W64 = do
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr (CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv
[ForeignHint
NoHint] [ForeignHint
NoHint]
CmmReturnInfo
CmmMayReturn)
DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args Label
bid
| Bool
otherwise = do
Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg
tmp_r <- Format -> NatM Reg
getNewRegNat Format
format
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
([ Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
src_r) (Reg -> Operand
OpReg Reg
src_r) | Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 ] [Instr] -> [Instr] -> [Instr]
forall a. [a] -> [a] -> [a]
++
[ Format -> Operand -> Reg -> Instr
BSR Format
format (Reg -> Operand
OpReg Reg
src_r) Reg
tmp_r
, Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt (2Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
*Alignment
bwAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-1))) (Reg -> Operand
OpReg Reg
dst_r)
, Cond -> Format -> Operand -> Reg -> Instr
CMOV Cond
NE Format
format (Reg -> Operand
OpReg Reg
tmp_r) Reg
dst_r
, Format -> Operand -> Operand -> Instr
XOR Format
format (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt (Alignment
bwAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-1))) (Reg -> Operand
OpReg Reg
dst_r)
])
where
bw :: Alignment
bw = Width -> Alignment
widthInBits Width
width
platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
format :: Format
format = if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then Format
II16 else Width -> Format
intFormat Width
width
lbl :: CLabel
lbl = UnitId -> FastString -> CLabel
mkCmmCodeLabel UnitId
primUnitId (String -> FastString
fsLit (Width -> String
clzLabel Width
width))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Ctz width :: Width
width)) [dst :: CmmFormal
dst] [src :: CmmExpr
src] bid :: Label
bid
| Bool
is32Bit, Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W64 = do
ChildCode64 vcode :: OrdList Instr
vcode rlo :: Reg
rlo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
src
let rhi :: Reg
rhi = Reg -> Reg
getHiVRegFromLo Reg
rlo
dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
Label
lbl1 <- NatM Label
getBlockIdNat
Label
lbl2 <- NatM Label
getBlockIdNat
Reg
tmp_r <- Format -> NatM Reg
getNewRegNat Format
format
(CFG -> CFG) -> NatM ()
updateCfgNat (Label -> Label -> EdgeWeight -> CFG -> CFG
addWeightEdge Label
bid Label
lbl1 110 (CFG -> CFG) -> (CFG -> CFG) -> CFG -> CFG
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Label -> Label -> EdgeWeight -> CFG -> CFG
addWeightEdge Label
lbl1 Label
lbl2 110 (CFG -> CFG) -> (CFG -> CFG) -> CFG -> CFG
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Label -> Label -> CFG -> CFG
addImmediateSuccessor Label
bid Label
lbl2)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
vcode OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
([ Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
rhi) (Reg -> Operand
OpReg Reg
tmp_r)
, Format -> Operand -> Operand -> Instr
OR Format
II32 (Reg -> Operand
OpReg Reg
rlo) (Reg -> Operand
OpReg Reg
tmp_r)
, Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt 64)) (Reg -> Operand
OpReg Reg
dst_r)
, Cond -> Label -> Instr
JXX Cond
EQQ Label
lbl2
, Cond -> Label -> Instr
JXX Cond
ALWAYS Label
lbl1
, Label -> Instr
NEWBLOCK Label
lbl1
, Format -> Operand -> Reg -> Instr
BSF Format
II32 (Reg -> Operand
OpReg Reg
rhi) Reg
dst_r
, Format -> Operand -> Operand -> Instr
ADD Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt 32)) (Reg -> Operand
OpReg Reg
dst_r)
, Format -> Operand -> Reg -> Instr
BSF Format
II32 (Reg -> Operand
OpReg Reg
rlo) Reg
tmp_r
, Cond -> Format -> Operand -> Reg -> Instr
CMOV Cond
NE Format
II32 (Reg -> Operand
OpReg Reg
tmp_r) Reg
dst_r
, Cond -> Label -> Instr
JXX Cond
ALWAYS Label
lbl2
, Label -> Instr
NEWBLOCK Label
lbl2
])
| Bool
otherwise = do
Reg -> OrdList Instr
code_src <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
src
Reg
src_r <- Format -> NatM Reg
getNewRegNat Format
format
Reg
tmp_r <- Format -> NatM Reg
getNewRegNat Format
format
let dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
False (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code_src Reg
src_r OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
([ Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
src_r) (Reg -> Operand
OpReg Reg
src_r) | Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 ] [Instr] -> [Instr] -> [Instr]
forall a. [a] -> [a] -> [a]
++
[ Format -> Operand -> Reg -> Instr
BSF Format
format (Reg -> Operand
OpReg Reg
src_r) Reg
tmp_r
, Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
bw)) (Reg -> Operand
OpReg Reg
dst_r)
, Cond -> Format -> Operand -> Reg -> Instr
CMOV Cond
NE Format
format (Reg -> Operand
OpReg Reg
tmp_r) Reg
dst_r
])
where
bw :: Alignment
bw = Width -> Alignment
widthInBits Width
width
platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
format :: Format
format = if Width
width Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W8 then Format
II16 else Width -> Format
intFormat Width
width
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_UF_Conv width :: Width
width)) dest_regs :: [CmmFormal]
dest_regs args :: [CmmExpr]
args bid :: Label
bid = do
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags
ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr (CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv
[ForeignHint
NoHint] [ForeignHint
NoHint]
CmmReturnInfo
CmmMayReturn)
DynFlags
-> Bool
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> Label
-> NatM (OrdList Instr)
genCCall DynFlags
dflags Bool
is32Bit ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args Label
bid
where
lbl :: CLabel
lbl = UnitId -> FastString -> CLabel
mkCmmCodeLabel UnitId
primUnitId (String -> FastString
fsLit (Width -> String
word2FloatLabel Width
width))
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_AtomicRMW width :: Width
width amop :: AtomicMachOp
amop))
[dst :: CmmFormal
dst] [addr :: CmmExpr
addr, n :: CmmExpr
n] bid :: Label
bid = do
Amode amode :: AddrMode
amode addr_code :: OrdList Instr
addr_code <-
if AtomicMachOp
amop AtomicMachOp -> [AtomicMachOp] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [AtomicMachOp
AMO_Add, AtomicMachOp
AMO_Sub]
then CmmExpr -> NatM Amode
getAmode CmmExpr
addr
else DynFlags -> Bool -> CmmExpr -> NatM Amode
getSimpleAmode DynFlags
dflags Bool
is32Bit CmmExpr
addr
Reg
arg <- Format -> NatM Reg
getNewRegNat Format
format
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
n
Bool
use_sse2 <- NatM Bool
sse2Enabled
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
OrdList Instr
code <- Reg -> Reg -> AddrMode -> NatM (OrdList Instr)
op_code Reg
dst_r Reg
arg AddrMode
amode
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
addr_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
arg_code Reg
arg OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
code
where
op_code :: Reg
-> Reg
-> AddrMode
-> NatM (OrdList Instr)
op_code :: Reg -> Reg -> AddrMode -> NatM (OrdList Instr)
op_code dst_r :: Reg
dst_r arg :: Reg
arg amode :: AddrMode
amode = case AtomicMachOp
amop of
AMO_Add -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Instr -> Instr
LOCK (Format -> Operand -> Operand -> Instr
XADD Format
format (Reg -> Operand
OpReg Reg
arg) (AddrMode -> Operand
OpAddr AddrMode
amode))
, Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
arg) (Reg -> Operand
OpReg Reg
dst_r)
]
AMO_Sub -> OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Instr
NEGI Format
format (Reg -> Operand
OpReg Reg
arg)
, Instr -> Instr
LOCK (Format -> Operand -> Operand -> Instr
XADD Format
format (Reg -> Operand
OpReg Reg
arg) (AddrMode -> Operand
OpAddr AddrMode
amode))
, Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
arg) (Reg -> Operand
OpReg Reg
dst_r)
]
AMO_And -> (Operand -> Operand -> OrdList Instr) -> NatM (OrdList Instr)
cmpxchg_code (\ src :: Operand
src dst :: Operand
dst -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ Format -> Operand -> Operand -> Instr
AND Format
format Operand
src Operand
dst)
AMO_Nand -> (Operand -> Operand -> OrdList Instr) -> NatM (OrdList Instr)
cmpxchg_code (\ src :: Operand
src dst :: Operand
dst -> [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
AND Format
format Operand
src Operand
dst
, Format -> Operand -> Instr
NOT Format
format Operand
dst
])
AMO_Or -> (Operand -> Operand -> OrdList Instr) -> NatM (OrdList Instr)
cmpxchg_code (\ src :: Operand
src dst :: Operand
dst -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ Format -> Operand -> Operand -> Instr
OR Format
format Operand
src Operand
dst)
AMO_Xor -> (Operand -> Operand -> OrdList Instr) -> NatM (OrdList Instr)
cmpxchg_code (\ src :: Operand
src dst :: Operand
dst -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Instr -> OrdList Instr) -> Instr -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ Format -> Operand -> Operand -> Instr
XOR Format
format Operand
src Operand
dst)
where
cmpxchg_code :: (Operand -> Operand -> OrdList Instr)
-> NatM (OrdList Instr)
cmpxchg_code :: (Operand -> Operand -> OrdList Instr) -> NatM (OrdList Instr)
cmpxchg_code instrs :: Operand -> Operand -> OrdList Instr
instrs = do
Label
lbl <- NatM Label
getBlockIdNat
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
format
Label -> Label -> NatM ()
addImmediateSuccessorNat Label
bid Label
lbl
(CFG -> CFG) -> NatM ()
updateCfgNat (Label -> Label -> EdgeWeight -> CFG -> CFG
addWeightEdge Label
lbl Label
lbl 0)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
[ Format -> Operand -> Operand -> Instr
MOV Format
format (AddrMode -> Operand
OpAddr AddrMode
amode) (Reg -> Operand
OpReg Reg
eax)
, Cond -> Label -> Instr
JXX Cond
ALWAYS Label
lbl
, Label -> Instr
NEWBLOCK Label
lbl
, Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
eax) (Reg -> Operand
OpReg Reg
dst_r)
, Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
eax) (Reg -> Operand
OpReg Reg
tmp)
]
OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Operand -> Operand -> OrdList Instr
instrs (Reg -> Operand
OpReg Reg
arg) (Reg -> Operand
OpReg Reg
tmp) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
[ Instr -> Instr
LOCK (Format -> Operand -> Operand -> Instr
CMPXCHG Format
format (Reg -> Operand
OpReg Reg
tmp) (AddrMode -> Operand
OpAddr AddrMode
amode))
, Cond -> Label -> Instr
JXX Cond
NE Label
lbl
]
format :: Format
format = Width -> Format
intFormat Width
width
genCCall dflags :: DynFlags
dflags _ (PrimTarget (MO_AtomicRead width :: Width
width)) [dst :: CmmFormal
dst] [addr :: CmmExpr
addr] _ = do
Reg -> OrdList Instr
load_code <- (Operand -> Operand -> Instr)
-> CmmExpr -> NatM (Reg -> OrdList Instr)
intLoadCode (Format -> Operand -> Operand -> Instr
MOV (Width -> Format
intFormat Width
width)) CmmExpr
addr
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
Bool
use_sse2 <- NatM Bool
sse2Enabled
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> OrdList Instr
load_code (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)))
genCCall _ _ (PrimTarget (MO_AtomicWrite width :: Width
width)) [] [addr :: CmmExpr
addr, val :: CmmExpr
val] _ = do
OrdList Instr
code <- Format -> CmmExpr -> CmmExpr -> NatM (OrdList Instr)
assignMem_IntCode (Width -> Format
intFormat Width
width) CmmExpr
addr CmmExpr
val
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Instr
MFENCE
genCCall dflags :: DynFlags
dflags is32Bit :: Bool
is32Bit (PrimTarget (MO_Cmpxchg width :: Width
width)) [dst :: CmmFormal
dst] [addr :: CmmExpr
addr, old :: CmmExpr
old, new :: CmmExpr
new] _ = do
Amode amode :: AddrMode
amode addr_code :: OrdList Instr
addr_code <- DynFlags -> Bool -> CmmExpr -> NatM Amode
getSimpleAmode DynFlags
dflags Bool
is32Bit CmmExpr
addr
Reg
newval <- Format -> NatM Reg
getNewRegNat Format
format
Reg -> OrdList Instr
newval_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
new
Reg
oldval <- Format -> NatM Reg
getNewRegNat Format
format
Reg -> OrdList Instr
oldval_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
old
Bool
use_sse2 <- NatM Bool
sse2Enabled
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
dst_r :: Reg
dst_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 (CmmFormal -> CmmReg
CmmLocal CmmFormal
dst)
code :: OrdList Instr
code = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL
[ Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
oldval) (Reg -> Operand
OpReg Reg
eax)
, Instr -> Instr
LOCK (Format -> Operand -> Operand -> Instr
CMPXCHG Format
format (Reg -> Operand
OpReg Reg
newval) (AddrMode -> Operand
OpAddr AddrMode
amode))
, Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
eax) (Reg -> Operand
OpReg Reg
dst_r)
]
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
addr_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
newval_code Reg
newval OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
oldval_code Reg
oldval
OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
code
where
format :: Format
format = Width -> Format
intFormat Width
width
genCCall _ is32Bit :: Bool
is32Bit target :: ForeignTarget
target dest_regs :: [CmmFormal]
dest_regs args :: [CmmExpr]
args bid :: Label
bid = do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
sse2 :: Bool
sse2 = DynFlags -> Bool
isSse2Enabled DynFlags
dflags
case (ForeignTarget
target, [CmmFormal]
dest_regs) of
(PrimTarget op :: CallishMachOp
op, []) ->
Label
-> CallishMachOp
-> Maybe CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
outOfLineCmmOp Label
bid CallishMachOp
op Maybe CmmFormal
forall a. Maybe a
Nothing [CmmExpr]
args
(PrimTarget op :: CallishMachOp
op, [r :: CmmFormal
r])
| Bool
sse2 -> case CallishMachOp
op of
MO_F32_Fabs -> case [CmmExpr]
args of
[x :: CmmExpr
x] -> Width -> CmmExpr -> NatM (OrdList Instr)
sse2FabsCode Width
W32 CmmExpr
x
_ -> String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments for fabs"
MO_F64_Fabs -> case [CmmExpr]
args of
[x :: CmmExpr
x] -> Width -> CmmExpr -> NatM (OrdList Instr)
sse2FabsCode Width
W64 CmmExpr
x
_ -> String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments for fabs"
MO_F32_Sqrt -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineSSE2Op (\fmt :: Format
fmt r :: Reg
r -> Format -> Operand -> Reg -> Instr
SQRT Format
fmt (Reg -> Operand
OpReg Reg
r)) Format
FF32 [CmmExpr]
args
MO_F64_Sqrt -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineSSE2Op (\fmt :: Format
fmt r :: Reg
r -> Format -> Operand -> Reg -> Instr
SQRT Format
fmt (Reg -> Operand
OpReg Reg
r)) Format
FF64 [CmmExpr]
args
_other_op :: CallishMachOp
_other_op -> Label
-> CallishMachOp
-> Maybe CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
outOfLineCmmOp Label
bid CallishMachOp
op (CmmFormal -> Maybe CmmFormal
forall a. a -> Maybe a
Just CmmFormal
r) [CmmExpr]
args
| Bool
otherwise -> do
CLabel
l1 <- NatM CLabel
getNewLabelNat
CLabel
l2 <- NatM CLabel
getNewLabelNat
if Bool
sse2
then Label
-> CallishMachOp
-> Maybe CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
outOfLineCmmOp Label
bid CallishMachOp
op (CmmFormal -> Maybe CmmFormal
forall a. a -> Maybe a
Just CmmFormal
r) [CmmExpr]
args
else case CallishMachOp
op of
MO_F32_Sqrt -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp Format -> Reg -> Reg -> Instr
GSQRT Format
FF32 [CmmExpr]
args
MO_F64_Sqrt -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp Format -> Reg -> Reg -> Instr
GSQRT Format
FF64 [CmmExpr]
args
MO_F32_Sin -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GSIN Format
s CLabel
l1 CLabel
l2) Format
FF32 [CmmExpr]
args
MO_F64_Sin -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GSIN Format
s CLabel
l1 CLabel
l2) Format
FF64 [CmmExpr]
args
MO_F32_Cos -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GCOS Format
s CLabel
l1 CLabel
l2) Format
FF32 [CmmExpr]
args
MO_F64_Cos -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GCOS Format
s CLabel
l1 CLabel
l2) Format
FF64 [CmmExpr]
args
MO_F32_Tan -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GTAN Format
s CLabel
l1 CLabel
l2) Format
FF32 [CmmExpr]
args
MO_F64_Tan -> (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp (\s :: Format
s -> Format -> CLabel -> CLabel -> Reg -> Reg -> Instr
GTAN Format
s CLabel
l1 CLabel
l2) Format
FF64 [CmmExpr]
args
_other_op :: CallishMachOp
_other_op -> Label
-> CallishMachOp
-> Maybe CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
outOfLineCmmOp Label
bid CallishMachOp
op (CmmFormal -> Maybe CmmFormal
forall a. a -> Maybe a
Just CmmFormal
r) [CmmExpr]
args
where
actuallyInlineFloatOp :: (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineFloatOp = Bool
-> (Format -> Reg -> Reg -> Instr)
-> Format
-> [CmmExpr]
-> NatM (OrdList Instr)
actuallyInlineFloatOp' Bool
False
actuallyInlineSSE2Op :: (Format -> Reg -> Reg -> Instr)
-> Format -> [CmmExpr] -> NatM (OrdList Instr)
actuallyInlineSSE2Op = Bool
-> (Format -> Reg -> Reg -> Instr)
-> Format
-> [CmmExpr]
-> NatM (OrdList Instr)
actuallyInlineFloatOp' Bool
True
actuallyInlineFloatOp' :: Bool
-> (Format -> Reg -> Reg -> Instr)
-> Format
-> [CmmExpr]
-> NatM (OrdList Instr)
actuallyInlineFloatOp' usesSSE :: Bool
usesSSE instr :: Format -> Reg -> Reg -> Instr
instr format :: Format
format [x :: CmmExpr
x]
= do Register
res <- Format -> (Reg -> Reg -> Instr) -> CmmExpr -> NatM Register
trivialUFCode Format
format (Format -> Reg -> Reg -> Instr
instr Format
format) CmmExpr
x
Reg -> OrdList Instr
any <- Register -> NatM (Reg -> OrdList Instr)
anyReg Register
res
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Reg -> OrdList Instr
any (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
usesSSE (CmmFormal -> CmmReg
CmmLocal CmmFormal
r)))
actuallyInlineFloatOp' _ _ _ args :: [CmmExpr]
args
= String -> NatM (OrdList Instr)
forall a. String -> a
panic (String -> NatM (OrdList Instr)) -> String -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ "genCCall.actuallyInlineFloatOp': bad number of arguments! ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Alignment -> String
forall a. Show a => a -> String
show ([CmmExpr] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length [CmmExpr]
args) String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
sse2FabsCode :: Width -> CmmExpr -> NatM InstrBlock
sse2FabsCode :: Width -> CmmExpr -> NatM (OrdList Instr)
sse2FabsCode w :: Width
w x :: CmmExpr
x = do
let fmt :: Format
fmt = Width -> Format
floatFormat Width
w
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let
const :: CmmLit
const | Format
FF32 <- Format
fmt = Integer -> Width -> CmmLit
CmmInt 0x7fffffff Width
W32
| Bool
otherwise = Integer -> Width -> CmmLit
CmmInt 0x7fffffffffffffff Width
W64
Amode amode :: AddrMode
amode amode_code :: OrdList Instr
amode_code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
const
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
fmt
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst = Reg -> OrdList Instr
x_code Reg
dst OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
amode_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
MOV Format
fmt (AddrMode -> Operand
OpAddr AddrMode
amode) (Reg -> Operand
OpReg Reg
tmp),
Format -> Operand -> Operand -> Instr
AND Format
fmt (Reg -> Operand
OpReg Reg
tmp) (Reg -> Operand
OpReg Reg
dst)
]
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ Reg -> OrdList Instr
code (Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
r))
(PrimTarget (MO_S_QuotRem width :: Width
width), _) -> Platform
-> Bool
-> Width
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
divOp1 Platform
platform Bool
True Width
width [CmmFormal]
dest_regs [CmmExpr]
args
(PrimTarget (MO_U_QuotRem width :: Width
width), _) -> Platform
-> Bool
-> Width
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
divOp1 Platform
platform Bool
False Width
width [CmmFormal]
dest_regs [CmmExpr]
args
(PrimTarget (MO_U_QuotRem2 width :: Width
width), _) -> Platform
-> Bool
-> Width
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
divOp2 Platform
platform Bool
False Width
width [CmmFormal]
dest_regs [CmmExpr]
args
(PrimTarget (MO_Add2 width :: Width
width), [res_h :: CmmFormal
res_h, res_l :: CmmFormal
res_l]) ->
case [CmmExpr]
args of
[arg_x :: CmmExpr
arg_x, arg_y :: CmmExpr
arg_y] ->
do Reg -> OrdList Instr
hCode <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg (CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt 0 Width
width))
let format :: Format
format = Width -> Format
intFormat Width
width
Reg -> OrdList Instr
lCode <- Register -> NatM (Reg -> OrdList Instr)
anyReg (Register -> NatM (Reg -> OrdList Instr))
-> NatM Register -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode Width
width (Format -> Operand -> Operand -> Instr
ADD_CC Format
format)
((Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just (Format -> Operand -> Operand -> Instr
ADD_CC Format
format)) CmmExpr
arg_x CmmExpr
arg_y
let reg_l :: Reg
reg_l = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_l)
reg_h :: Reg
reg_h = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_h)
code :: OrdList Instr
code = Reg -> OrdList Instr
hCode Reg
reg_h OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
lCode Reg
reg_l OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
ADC Format
format (Imm -> Operand
OpImm (Integer -> Imm
ImmInteger 0)) (Reg -> Operand
OpReg Reg
reg_h)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
_ -> String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments/results for add2"
(PrimTarget (MO_AddWordC width :: Width
width), [res_r :: CmmFormal
res_r, res_c :: CmmFormal
res_c]) ->
Platform
-> (Format -> Operand -> Operand -> Instr)
-> (Format -> Maybe (Operand -> Operand -> Instr))
-> Cond
-> Width
-> CmmFormal
-> CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
addSubIntC Platform
platform Format -> Operand -> Operand -> Instr
ADD_CC (Maybe (Operand -> Operand -> Instr)
-> Format -> Maybe (Operand -> Operand -> Instr)
forall a b. a -> b -> a
const Maybe (Operand -> Operand -> Instr)
forall a. Maybe a
Nothing) Cond
CARRY Width
width CmmFormal
res_r CmmFormal
res_c [CmmExpr]
args
(PrimTarget (MO_SubWordC width :: Width
width), [res_r :: CmmFormal
res_r, res_c :: CmmFormal
res_c]) ->
Platform
-> (Format -> Operand -> Operand -> Instr)
-> (Format -> Maybe (Operand -> Operand -> Instr))
-> Cond
-> Width
-> CmmFormal
-> CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
addSubIntC Platform
platform Format -> Operand -> Operand -> Instr
SUB_CC (Maybe (Operand -> Operand -> Instr)
-> Format -> Maybe (Operand -> Operand -> Instr)
forall a b. a -> b -> a
const Maybe (Operand -> Operand -> Instr)
forall a. Maybe a
Nothing) Cond
CARRY Width
width CmmFormal
res_r CmmFormal
res_c [CmmExpr]
args
(PrimTarget (MO_AddIntC width :: Width
width), [res_r :: CmmFormal
res_r, res_c :: CmmFormal
res_c]) ->
Platform
-> (Format -> Operand -> Operand -> Instr)
-> (Format -> Maybe (Operand -> Operand -> Instr))
-> Cond
-> Width
-> CmmFormal
-> CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
addSubIntC Platform
platform Format -> Operand -> Operand -> Instr
ADD_CC ((Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
forall a. a -> Maybe a
Just ((Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr))
-> (Format -> Operand -> Operand -> Instr)
-> Format
-> Maybe (Operand -> Operand -> Instr)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Format -> Operand -> Operand -> Instr
ADD_CC) Cond
OFLO Width
width CmmFormal
res_r CmmFormal
res_c [CmmExpr]
args
(PrimTarget (MO_SubIntC width :: Width
width), [res_r :: CmmFormal
res_r, res_c :: CmmFormal
res_c]) ->
Platform
-> (Format -> Operand -> Operand -> Instr)
-> (Format -> Maybe (Operand -> Operand -> Instr))
-> Cond
-> Width
-> CmmFormal
-> CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
addSubIntC Platform
platform Format -> Operand -> Operand -> Instr
SUB_CC (Maybe (Operand -> Operand -> Instr)
-> Format -> Maybe (Operand -> Operand -> Instr)
forall a b. a -> b -> a
const Maybe (Operand -> Operand -> Instr)
forall a. Maybe a
Nothing) Cond
OFLO Width
width CmmFormal
res_r CmmFormal
res_c [CmmExpr]
args
(PrimTarget (MO_U_Mul2 width :: Width
width), [res_h :: CmmFormal
res_h, res_l :: CmmFormal
res_l]) ->
case [CmmExpr]
args of
[arg_x :: CmmExpr
arg_x, arg_y :: CmmExpr
arg_y] ->
do (y_reg :: Operand
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getRegOrMem CmmExpr
arg_y
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg_x
let format :: Format
format = Width -> Format
intFormat Width
width
reg_h :: Reg
reg_h = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_h)
reg_l :: Reg
reg_l = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_l)
code :: OrdList Instr
code = OrdList Instr
y_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
x_code Reg
rax OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Instr
MUL2 Format
format Operand
y_reg,
Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
rdx) (Reg -> Operand
OpReg Reg
reg_h),
Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
rax) (Reg -> Operand
OpReg Reg
reg_l)]
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
_ -> String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments/results for mul2"
_ -> if Bool
is32Bit
then DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
genCCall32' DynFlags
dflags ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args
else DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
genCCall64' DynFlags
dflags ForeignTarget
target [CmmFormal]
dest_regs [CmmExpr]
args
where divOp1 :: Platform
-> Bool
-> Width
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
divOp1 platform :: Platform
platform signed :: Bool
signed width :: Width
width results :: [CmmFormal]
results [arg_x :: CmmExpr
arg_x, arg_y :: CmmExpr
arg_y]
= Platform
-> Bool
-> Width
-> [CmmFormal]
-> Maybe CmmExpr
-> CmmExpr
-> CmmExpr
-> NatM (OrdList Instr)
divOp Platform
platform Bool
signed Width
width [CmmFormal]
results Maybe CmmExpr
forall a. Maybe a
Nothing CmmExpr
arg_x CmmExpr
arg_y
divOp1 _ _ _ _ _
= String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments for divOp1"
divOp2 :: Platform
-> Bool
-> Width
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
divOp2 platform :: Platform
platform signed :: Bool
signed width :: Width
width results :: [CmmFormal]
results [arg_x_high :: CmmExpr
arg_x_high, arg_x_low :: CmmExpr
arg_x_low, arg_y :: CmmExpr
arg_y]
= Platform
-> Bool
-> Width
-> [CmmFormal]
-> Maybe CmmExpr
-> CmmExpr
-> CmmExpr
-> NatM (OrdList Instr)
divOp Platform
platform Bool
signed Width
width [CmmFormal]
results (CmmExpr -> Maybe CmmExpr
forall a. a -> Maybe a
Just CmmExpr
arg_x_high) CmmExpr
arg_x_low CmmExpr
arg_y
divOp2 _ _ _ _ _
= String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments for divOp2"
divOp :: Platform
-> Bool
-> Width
-> [CmmFormal]
-> Maybe CmmExpr
-> CmmExpr
-> CmmExpr
-> NatM (OrdList Instr)
divOp platform :: Platform
platform signed :: Bool
signed W8 [res_q :: CmmFormal
res_q, res_r :: CmmFormal
res_r] m_arg_x_high :: Maybe CmmExpr
m_arg_x_high arg_x_low :: CmmExpr
arg_x_low arg_y :: CmmExpr
arg_y =
let widen :: MachOp
widen | Bool
signed = Width -> Width -> MachOp
MO_SS_Conv Width
W8 Width
W16
| Bool
otherwise = Width -> Width -> MachOp
MO_UU_Conv Width
W8 Width
W16
arg_x_low_16 :: CmmExpr
arg_x_low_16 = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
widen [CmmExpr
arg_x_low]
arg_y_16 :: CmmExpr
arg_y_16 = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
widen [CmmExpr
arg_y]
m_arg_x_high_16 :: Maybe CmmExpr
m_arg_x_high_16 = (\p :: CmmExpr
p -> MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
widen [CmmExpr
p]) (CmmExpr -> CmmExpr) -> Maybe CmmExpr -> Maybe CmmExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe CmmExpr
m_arg_x_high
in Platform
-> Bool
-> Width
-> [CmmFormal]
-> Maybe CmmExpr
-> CmmExpr
-> CmmExpr
-> NatM (OrdList Instr)
divOp
Platform
platform Bool
signed Width
W16 [CmmFormal
res_q, CmmFormal
res_r]
Maybe CmmExpr
m_arg_x_high_16 CmmExpr
arg_x_low_16 CmmExpr
arg_y_16
divOp platform :: Platform
platform signed :: Bool
signed width :: Width
width [res_q :: CmmFormal
res_q, res_r :: CmmFormal
res_r]
m_arg_x_high :: Maybe CmmExpr
m_arg_x_high arg_x_low :: CmmExpr
arg_x_low arg_y :: CmmExpr
arg_y
= do let format :: Format
format = Width -> Format
intFormat Width
width
reg_q :: Reg
reg_q = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_q)
reg_r :: Reg
reg_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_r)
widen :: Instr
widen | Bool
signed = Format -> Instr
CLTD Format
format
| Bool
otherwise = Format -> Operand -> Operand -> Instr
XOR Format
format (Reg -> Operand
OpReg Reg
rdx) (Reg -> Operand
OpReg Reg
rdx)
instr :: Format -> Operand -> Instr
instr | Bool
signed = Format -> Operand -> Instr
IDIV
| Bool
otherwise = Format -> Operand -> Instr
DIV
(y_reg :: Operand
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getRegOrMem CmmExpr
arg_y
Reg -> OrdList Instr
x_low_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg_x_low
Reg -> OrdList Instr
x_high_code <- case Maybe CmmExpr
m_arg_x_high of
Just arg_x_high :: CmmExpr
arg_x_high ->
CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg_x_high
Nothing ->
(Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr))
-> (Reg -> OrdList Instr) -> NatM (Reg -> OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr -> Reg -> OrdList Instr
forall a b. a -> b -> a
const (OrdList Instr -> Reg -> OrdList Instr)
-> OrdList Instr -> Reg -> OrdList Instr
forall a b. (a -> b) -> a -> b
$ Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL Instr
widen
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ OrdList Instr
y_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
x_low_code Reg
rax OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
x_high_code Reg
rdx OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Instr
instr Format
format Operand
y_reg,
Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
rax) (Reg -> Operand
OpReg Reg
reg_q),
Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
rdx) (Reg -> Operand
OpReg Reg
reg_r)]
divOp _ _ _ _ _ _ _
= String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of results for divOp"
addSubIntC :: Platform
-> (Format -> Operand -> Operand -> Instr)
-> (Format -> Maybe (Operand -> Operand -> Instr))
-> Cond
-> Width
-> CmmFormal
-> CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
addSubIntC platform :: Platform
platform instr :: Format -> Operand -> Operand -> Instr
instr mrevinstr :: Format -> Maybe (Operand -> Operand -> Instr)
mrevinstr cond :: Cond
cond width :: Width
width
res_r :: CmmFormal
res_r res_c :: CmmFormal
res_c [arg_x :: CmmExpr
arg_x, arg_y :: CmmExpr
arg_y]
= do let format :: Format
format = Width -> Format
intFormat Width
width
Reg -> OrdList Instr
rCode <- Register -> NatM (Reg -> OrdList Instr)
anyReg (Register -> NatM (Reg -> OrdList Instr))
-> NatM Register -> NatM (Reg -> OrdList Instr)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode Width
width (Format -> Operand -> Operand -> Instr
instr Format
format)
(Format -> Maybe (Operand -> Operand -> Instr)
mrevinstr Format
format) CmmExpr
arg_x CmmExpr
arg_y
Reg
reg_tmp <- Format -> NatM Reg
getNewRegNat Format
II8
let reg_c :: Reg
reg_c = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_c)
reg_r :: Reg
reg_r = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
res_r)
code :: OrdList Instr
code = Reg -> OrdList Instr
rCode Reg
reg_r OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
reg_tmp) OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
reg_tmp) (Reg -> Operand
OpReg Reg
reg_c)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
addSubIntC _ _ _ _ _ _ _ _
= String -> NatM (OrdList Instr)
forall a. String -> a
panic "genCCall: Wrong number of arguments/results for addSubIntC"
genCCall32' :: DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmActual]
-> NatM InstrBlock
genCCall32' :: DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
genCCall32' dflags :: DynFlags
dflags target :: ForeignTarget
target dest_regs :: [CmmFormal]
dest_regs args :: [CmmExpr]
args = do
let
prom_args :: [CmmExpr]
prom_args = (CmmExpr -> CmmExpr) -> [CmmExpr] -> [CmmExpr]
forall a b. (a -> b) -> [a] -> [b]
map (DynFlags -> Width -> CmmExpr -> CmmExpr
maybePromoteCArg DynFlags
dflags Width
W32) [CmmExpr]
args
sizes :: [Alignment]
sizes = (CmmExpr -> Alignment) -> [CmmExpr] -> [Alignment]
forall a b. (a -> b) -> [a] -> [b]
map (CmmType -> Alignment
arg_size_bytes (CmmType -> Alignment)
-> (CmmExpr -> CmmType) -> CmmExpr -> Alignment
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags) ([CmmExpr] -> [CmmExpr]
forall a. [a] -> [a]
reverse [CmmExpr]
args)
raw_arg_size :: Alignment
raw_arg_size = [Alignment] -> Alignment
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Alignment]
sizes Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ DynFlags -> Alignment
wORD_SIZE DynFlags
dflags
arg_pad_size :: Alignment
arg_pad_size = (Alignment -> Alignment -> Alignment
forall a. Integral a => a -> a -> a
roundTo 16 (Alignment -> Alignment) -> Alignment -> Alignment
forall a b. (a -> b) -> a -> b
$ Alignment
raw_arg_size) Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
raw_arg_size
tot_arg_size :: Alignment
tot_arg_size = Alignment
raw_arg_size Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ Alignment
arg_pad_size Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- DynFlags -> Alignment
wORD_SIZE DynFlags
dflags
Alignment
delta0 <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
delta0 Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
arg_pad_size)
Bool
use_sse2 <- NatM Bool
sse2Enabled
[OrdList Instr]
push_codes <- (CmmExpr -> NatM (OrdList Instr))
-> [CmmExpr] -> NatM [OrdList Instr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Bool -> CmmExpr -> NatM (OrdList Instr)
push_arg Bool
use_sse2) ([CmmExpr] -> [CmmExpr]
forall a. [a] -> [a]
reverse [CmmExpr]
prom_args)
Alignment
delta <- NatM Alignment
getDeltaNat
MASSERT(delta == delta0 - tot_arg_size)
(callinsns :: OrdList Instr
callinsns,cconv :: ForeignConvention
cconv) <-
case ForeignTarget
target of
ForeignTarget (CmmLit (CmmLabel lbl :: CLabel
lbl)) conv :: ForeignConvention
conv
->
(OrdList Instr, ForeignConvention)
-> NatM (OrdList Instr, ForeignConvention)
forall (m :: * -> *) a. Monad m => a -> m a
return (Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Either Imm Reg -> [Reg] -> Instr
CALL (Imm -> Either Imm Reg
forall a b. a -> Either a b
Left Imm
fn_imm) []), ForeignConvention
conv)
where fn_imm :: Imm
fn_imm = CLabel -> Imm
ImmCLbl CLabel
lbl
ForeignTarget expr :: CmmExpr
expr conv :: ForeignConvention
conv
-> do { (dyn_r :: Reg
dyn_r, dyn_c :: OrdList Instr
dyn_c) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
; ASSERT( isWord32 (cmmExprType dflags expr) )
(OrdList Instr, ForeignConvention)
-> NatM (OrdList Instr, ForeignConvention)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
dyn_c OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Either Imm Reg -> [Reg] -> Instr
CALL (Reg -> Either Imm Reg
forall a b. b -> Either a b
Right Reg
dyn_r) [], ForeignConvention
conv) }
PrimTarget _
-> String -> NatM (OrdList Instr, ForeignConvention)
forall a. String -> a
panic (String -> NatM (OrdList Instr, ForeignConvention))
-> String -> NatM (OrdList Instr, ForeignConvention)
forall a b. (a -> b) -> a -> b
$ "genCCall: Can't handle PrimTarget call type here, error "
String -> String -> String
forall a. [a] -> [a] -> [a]
++ "probably because too many return values."
let push_code :: OrdList Instr
push_code
| Alignment
arg_pad_size Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
= [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Operand -> Instr
SUB Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
arg_pad_size)) (Reg -> Operand
OpReg Reg
esp),
Alignment -> Instr
DELTA (Alignment
delta0 Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
arg_pad_size)]
OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [OrdList Instr] -> OrdList Instr
forall a. [OrdList a] -> OrdList a
concatOL [OrdList Instr]
push_codes
| Bool
otherwise
= [OrdList Instr] -> OrdList Instr
forall a. [OrdList a] -> OrdList a
concatOL [OrdList Instr]
push_codes
pop_size :: Alignment
pop_size
| ForeignConvention StdCallConv _ _ _ <- ForeignConvention
cconv = Alignment
arg_pad_size
| Bool
otherwise = Alignment
tot_arg_size
call :: OrdList Instr
call = OrdList Instr
callinsns OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL (
(if Alignment
pop_sizeAlignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
==0 then [] else
[Format -> Operand -> Operand -> Instr
ADD Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
pop_size)) (Reg -> Operand
OpReg Reg
esp)])
[Instr] -> [Instr] -> [Instr]
forall a. [a] -> [a] -> [a]
++
[Alignment -> Instr
DELTA Alignment
delta0]
)
Alignment -> NatM ()
setDeltaNat Alignment
delta0
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
let
assign_code :: [CmmFormal] -> OrdList Instr
assign_code [] = OrdList Instr
forall a. OrdList a
nilOL
assign_code [dest :: CmmFormal
dest]
| CmmType -> Bool
isFloatType CmmType
ty =
if Bool
use_sse2
then let tmp_amode :: AddrMode
tmp_amode = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
esp)
EAIndex
EAIndexNone
(Alignment -> Imm
ImmInt 0)
fmt :: Format
fmt = Width -> Format
floatFormat Width
w
in [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [ Format -> Operand -> Operand -> Instr
SUB Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
b)) (Reg -> Operand
OpReg Reg
esp),
Alignment -> Instr
DELTA (Alignment
delta0 Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
b),
Format -> Reg -> AddrMode -> Instr
GST Format
fmt Reg
fake0 AddrMode
tmp_amode,
Format -> Operand -> Operand -> Instr
MOV Format
fmt (AddrMode -> Operand
OpAddr AddrMode
tmp_amode) (Reg -> Operand
OpReg Reg
r_dest),
Format -> Operand -> Operand -> Instr
ADD Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
b)) (Reg -> Operand
OpReg Reg
esp),
Alignment -> Instr
DELTA Alignment
delta0]
else Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Reg -> Reg -> Instr
GMOV Reg
fake0 Reg
r_dest)
| CmmType -> Bool
isWord64 CmmType
ty = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
eax) (Reg -> Operand
OpReg Reg
r_dest),
Format -> Operand -> Operand -> Instr
MOV Format
II32 (Reg -> Operand
OpReg Reg
edx) (Reg -> Operand
OpReg Reg
r_dest_hi)]
| Bool
otherwise = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV (Width -> Format
intFormat Width
w)
(Reg -> Operand
OpReg Reg
eax)
(Reg -> Operand
OpReg Reg
r_dest))
where
ty :: CmmType
ty = CmmFormal -> CmmType
localRegType CmmFormal
dest
w :: Width
w = CmmType -> Width
typeWidth CmmType
ty
b :: Alignment
b = Width -> Alignment
widthInBytes Width
w
r_dest_hi :: Reg
r_dest_hi = Reg -> Reg
getHiVRegFromLo Reg
r_dest
r_dest :: Reg
r_dest = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
use_sse2 (CmmFormal -> CmmReg
CmmLocal CmmFormal
dest)
assign_code many :: [CmmFormal]
many = String -> SDoc -> OrdList Instr
forall a. HasCallStack => String -> SDoc -> a
pprPanic "genCCall.assign_code - too many return values:" ([CmmFormal] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CmmFormal]
many)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
push_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
call OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[CmmFormal] -> OrdList Instr
assign_code [CmmFormal]
dest_regs)
where
arg_size_bytes :: CmmType -> Int
arg_size_bytes :: CmmType -> Alignment
arg_size_bytes ty :: CmmType
ty = Alignment -> Alignment -> Alignment
forall a. Ord a => a -> a -> a
max (Width -> Alignment
widthInBytes (CmmType -> Width
typeWidth CmmType
ty)) (Width -> Alignment
widthInBytes (DynFlags -> Width
wordWidth DynFlags
dflags))
roundTo :: a -> a -> a
roundTo a :: a
a x :: a
x | a
x a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = a
x
| Bool
otherwise = a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
a a -> a -> a
forall a. Num a => a -> a -> a
- (a
x a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
a)
push_arg :: Bool -> CmmActual
-> NatM InstrBlock
push_arg :: Bool -> CmmExpr -> NatM (OrdList Instr)
push_arg use_sse2 :: Bool
use_sse2 arg :: CmmExpr
arg
| CmmType -> Bool
isWord64 CmmType
arg_ty = do
ChildCode64 code :: OrdList Instr
code r_lo :: Reg
r_lo <- CmmExpr -> NatM ChildCode64
iselExpr64 CmmExpr
arg
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- 8)
let r_hi :: Reg
r_hi = Reg -> Reg
getHiVRegFromLo Reg
r_lo
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ( OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Instr
PUSH Format
II32 (Reg -> Operand
OpReg Reg
r_hi), Alignment -> Instr
DELTA (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- 4),
Format -> Operand -> Instr
PUSH Format
II32 (Reg -> Operand
OpReg Reg
r_lo), Alignment -> Instr
DELTA (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- 8),
Alignment -> Instr
DELTA (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-8)]
)
| CmmType -> Bool
isFloatType CmmType
arg_ty = do
(reg :: Reg
reg, code :: OrdList Instr
code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
arg
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
size)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [Format -> Operand -> Operand -> Instr
SUB Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
size)) (Reg -> Operand
OpReg Reg
esp),
Alignment -> Instr
DELTA (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
size),
let addr :: AddrMode
addr = EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
esp)
EAIndex
EAIndexNone
(Alignment -> Imm
ImmInt 0)
format :: Format
format = Width -> Format
floatFormat (CmmType -> Width
typeWidth CmmType
arg_ty)
in
if Bool
use_sse2
then Format -> Operand -> Operand -> Instr
MOV Format
format (Reg -> Operand
OpReg Reg
reg) (AddrMode -> Operand
OpAddr AddrMode
addr)
else Format -> Reg -> AddrMode -> Instr
GST Format
format Reg
reg AddrMode
addr
]
)
| Bool
otherwise = do
ASSERT((typeWidth arg_ty) <= W32) return ()
(operand :: Operand
operand, code :: OrdList Instr
code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
arg
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
size)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Instr
PUSH Format
II32 Operand
operand OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Alignment -> Instr
DELTA (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
size))
where
arg_ty :: CmmType
arg_ty = DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
arg
size :: Alignment
size = CmmType -> Alignment
arg_size_bytes CmmType
arg_ty
genCCall64' :: DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmActual]
-> NatM InstrBlock
genCCall64' :: DynFlags
-> ForeignTarget
-> [CmmFormal]
-> [CmmExpr]
-> NatM (OrdList Instr)
genCCall64' dflags :: DynFlags
dflags target :: ForeignTarget
target dest_regs :: [CmmFormal]
dest_regs args :: [CmmExpr]
args = do
let prom_args :: [CmmExpr]
prom_args = (CmmExpr -> CmmExpr) -> [CmmExpr] -> [CmmExpr]
forall a b. (a -> b) -> [a] -> [b]
map (DynFlags -> Width -> CmmExpr -> CmmExpr
maybePromoteCArg DynFlags
dflags Width
W32) [CmmExpr]
args
(stack_args :: [CmmExpr]
stack_args, int_regs_used :: [Reg]
int_regs_used, fp_regs_used :: [Reg]
fp_regs_used, load_args_code :: OrdList Instr
load_args_code, assign_args_code :: OrdList Instr
assign_args_code)
<-
if Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32
then [CmmExpr]
-> [Reg]
-> [Reg]
-> [(Reg, Reg)]
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args_win [CmmExpr]
prom_args [] [] (Platform -> [(Reg, Reg)]
allArgRegs Platform
platform) OrdList Instr
forall a. OrdList a
nilOL
else do
(stack_args :: [CmmExpr]
stack_args, aregs :: [Reg]
aregs, fregs :: [Reg]
fregs, load_args_code :: OrdList Instr
load_args_code, assign_args_code :: OrdList Instr
assign_args_code)
<- [CmmExpr]
-> [Reg]
-> [Reg]
-> OrdList Instr
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args [CmmExpr]
prom_args (Platform -> [Reg]
allIntArgRegs Platform
platform)
(Platform -> [Reg]
allFPArgRegs Platform
platform)
OrdList Instr
forall a. OrdList a
nilOL OrdList Instr
forall a. OrdList a
nilOL
let used_regs :: t a -> [a] -> [a]
used_regs rs :: t a
rs as :: [a]
as = [a] -> [a]
forall a. [a] -> [a]
reverse (Alignment -> [a] -> [a]
forall a. Alignment -> [a] -> [a]
drop (t a -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length t a
rs) ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
as))
fregs_used :: [Reg]
fregs_used = [Reg] -> [Reg] -> [Reg]
forall (t :: * -> *) a a. Foldable t => t a -> [a] -> [a]
used_regs [Reg]
fregs (Platform -> [Reg]
allFPArgRegs Platform
platform)
aregs_used :: [Reg]
aregs_used = [Reg] -> [Reg] -> [Reg]
forall (t :: * -> *) a a. Foldable t => t a -> [a] -> [a]
used_regs [Reg]
aregs (Platform -> [Reg]
allIntArgRegs Platform
platform)
([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CmmExpr]
stack_args, [Reg]
aregs_used, [Reg]
fregs_used, OrdList Instr
load_args_code
, OrdList Instr
assign_args_code)
let
arg_regs_used :: [Reg]
arg_regs_used = [Reg]
int_regs_used [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ [Reg]
fp_regs_used
arg_regs :: [Reg]
arg_regs = [Reg
eax] [Reg] -> [Reg] -> [Reg]
forall a. [a] -> [a] -> [a]
++ [Reg]
arg_regs_used
sse_regs :: Alignment
sse_regs = [Reg] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length [Reg]
fp_regs_used
arg_stack_slots :: Alignment
arg_stack_slots = if Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32
then [CmmExpr] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length [CmmExpr]
stack_args Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ [(Reg, Reg)] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length (Platform -> [(Reg, Reg)]
allArgRegs Platform
platform)
else [CmmExpr] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length [CmmExpr]
stack_args
tot_arg_size :: Alignment
tot_arg_size = Alignment
arg_size Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
* Alignment
arg_stack_slots
(real_size :: Alignment
real_size, adjust_rsp :: OrdList Instr
adjust_rsp) <-
if (Alignment
tot_arg_size Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ DynFlags -> Alignment
wORD_SIZE DynFlags
dflags) Alignment -> Alignment -> Alignment
forall a. Integral a => a -> a -> a
`rem` 16 Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
== 0
then (Alignment, OrdList Instr) -> NatM (Alignment, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Alignment
tot_arg_size, OrdList Instr
forall a. OrdList a
nilOL)
else do
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- DynFlags -> Alignment
wORD_SIZE DynFlags
dflags)
(Alignment, OrdList Instr) -> NatM (Alignment, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Alignment
tot_arg_size Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ DynFlags -> Alignment
wORD_SIZE DynFlags
dflags, [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
SUB Format
II64 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt (DynFlags -> Alignment
wORD_SIZE DynFlags
dflags))) (Reg -> Operand
OpReg Reg
rsp),
Alignment -> Instr
DELTA (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- DynFlags -> Alignment
wORD_SIZE DynFlags
dflags) ])
OrdList Instr
push_code <- [CmmExpr] -> OrdList Instr -> NatM (OrdList Instr)
push_args ([CmmExpr] -> [CmmExpr]
forall a. [a] -> [a]
reverse [CmmExpr]
stack_args) OrdList Instr
forall a. OrdList a
nilOL
OrdList Instr
lss_code <- if Platform -> OS
platformOS Platform
platform OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSMinGW32
then Alignment -> NatM (OrdList Instr)
leaveStackSpace ([(Reg, Reg)] -> Alignment
forall (t :: * -> *) a. Foldable t => t a -> Alignment
length (Platform -> [(Reg, Reg)]
allArgRegs Platform
platform))
else OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
forall a. OrdList a
nilOL
Alignment
delta <- NatM Alignment
getDeltaNat
(callinsns :: OrdList Instr
callinsns,_cconv :: ForeignConvention
_cconv) <-
case ForeignTarget
target of
ForeignTarget (CmmLit (CmmLabel lbl :: CLabel
lbl)) conv :: ForeignConvention
conv
->
(OrdList Instr, ForeignConvention)
-> NatM (OrdList Instr, ForeignConvention)
forall (m :: * -> *) a. Monad m => a -> m a
return (Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Either Imm Reg -> [Reg] -> Instr
CALL (Imm -> Either Imm Reg
forall a b. a -> Either a b
Left Imm
fn_imm) [Reg]
arg_regs), ForeignConvention
conv)
where fn_imm :: Imm
fn_imm = CLabel -> Imm
ImmCLbl CLabel
lbl
ForeignTarget expr :: CmmExpr
expr conv :: ForeignConvention
conv
-> do (dyn_r :: Reg
dyn_r, dyn_c :: OrdList Instr
dyn_c) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
expr
(OrdList Instr, ForeignConvention)
-> NatM (OrdList Instr, ForeignConvention)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
dyn_c OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Either Imm Reg -> [Reg] -> Instr
CALL (Reg -> Either Imm Reg
forall a b. b -> Either a b
Right Reg
dyn_r) [Reg]
arg_regs, ForeignConvention
conv)
PrimTarget _
-> String -> NatM (OrdList Instr, ForeignConvention)
forall a. String -> a
panic (String -> NatM (OrdList Instr, ForeignConvention))
-> String -> NatM (OrdList Instr, ForeignConvention)
forall a b. (a -> b) -> a -> b
$ "genCCall: Can't handle PrimTarget call type here, error "
String -> String -> String
forall a. [a] -> [a] -> [a]
++ "probably because too many return values."
let
assign_eax :: Alignment -> OrdList Instr
assign_eax n :: Alignment
n = Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
II32 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
n)) (Reg -> Operand
OpReg Reg
eax))
let call :: OrdList Instr
call = OrdList Instr
callinsns OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL (
(if Alignment
real_sizeAlignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
==0 then [] else
[Format -> Operand -> Operand -> Instr
ADD (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags)) (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
real_size)) (Reg -> Operand
OpReg Reg
esp)])
[Instr] -> [Instr] -> [Instr]
forall a. [a] -> [a] -> [a]
++
[Alignment -> Instr
DELTA (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ Alignment
real_size)]
)
Alignment -> NatM ()
setDeltaNat (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
+ Alignment
real_size)
let
assign_code :: [CmmFormal] -> OrdList Instr
assign_code [] = OrdList Instr
forall a. OrdList a
nilOL
assign_code [dest :: CmmFormal
dest] =
case CmmType -> Width
typeWidth CmmType
rep of
W32 | CmmType -> Bool
isFloatType CmmType
rep -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV (Width -> Format
floatFormat Width
W32)
(Reg -> Operand
OpReg Reg
xmm0)
(Reg -> Operand
OpReg Reg
r_dest))
W64 | CmmType -> Bool
isFloatType CmmType
rep -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV (Width -> Format
floatFormat Width
W64)
(Reg -> Operand
OpReg Reg
xmm0)
(Reg -> Operand
OpReg Reg
r_dest))
_ -> Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV (CmmType -> Format
cmmTypeFormat CmmType
rep) (Reg -> Operand
OpReg Reg
rax) (Reg -> Operand
OpReg Reg
r_dest))
where
rep :: CmmType
rep = CmmFormal -> CmmType
localRegType CmmFormal
dest
r_dest :: Reg
r_dest = Platform -> Bool -> CmmReg -> Reg
getRegisterReg Platform
platform Bool
True (CmmFormal -> CmmReg
CmmLocal CmmFormal
dest)
assign_code _many :: [CmmFormal]
_many = String -> OrdList Instr
forall a. String -> a
panic "genCCall.assign_code many"
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
adjust_rsp OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
push_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
load_args_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
assign_args_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
lss_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Alignment -> OrdList Instr
assign_eax Alignment
sse_regs OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
call OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
[CmmFormal] -> OrdList Instr
assign_code [CmmFormal]
dest_regs)
where platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
arg_size :: Alignment
arg_size = 8
load_args :: [CmmExpr]
-> [Reg]
-> [Reg]
-> InstrBlock
-> InstrBlock
-> NatM ([CmmExpr],[Reg],[Reg],InstrBlock,InstrBlock)
load_args :: [CmmExpr]
-> [Reg]
-> [Reg]
-> OrdList Instr
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args args :: [CmmExpr]
args [] [] code :: OrdList Instr
code acode :: OrdList Instr
acode =
([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CmmExpr]
args, [], [], OrdList Instr
code, OrdList Instr
acode)
load_args [] aregs :: [Reg]
aregs fregs :: [Reg]
fregs code :: OrdList Instr
code acode :: OrdList Instr
acode =
([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [Reg]
aregs, [Reg]
fregs, OrdList Instr
code, OrdList Instr
acode)
load_args (arg :: CmmExpr
arg : rest :: [CmmExpr]
rest) aregs :: [Reg]
aregs fregs :: [Reg]
fregs code :: OrdList Instr
code acode :: OrdList Instr
acode
| CmmType -> Bool
isFloatType CmmType
arg_rep = case [Reg]
fregs of
[] -> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
push_this_arg
(r :: Reg
r:rs :: [Reg]
rs) -> do
(code' :: OrdList Instr
code',acode' :: OrdList Instr
acode') <- Reg -> NatM (OrdList Instr, OrdList Instr)
reg_this_arg Reg
r
[CmmExpr]
-> [Reg]
-> [Reg]
-> OrdList Instr
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args [CmmExpr]
rest [Reg]
aregs [Reg]
rs OrdList Instr
code' OrdList Instr
acode'
| Bool
otherwise = case [Reg]
aregs of
[] -> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
push_this_arg
(r :: Reg
r:rs :: [Reg]
rs) -> do
(code' :: OrdList Instr
code',acode' :: OrdList Instr
acode') <- Reg -> NatM (OrdList Instr, OrdList Instr)
reg_this_arg Reg
r
[CmmExpr]
-> [Reg]
-> [Reg]
-> OrdList Instr
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args [CmmExpr]
rest [Reg]
rs [Reg]
fregs OrdList Instr
code' OrdList Instr
acode'
where
push_this_arg :: NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
push_this_arg = do
(args' :: [CmmExpr]
args',ars :: [Reg]
ars,frs :: [Reg]
frs,code' :: OrdList Instr
code',acode' :: OrdList Instr
acode')
<- [CmmExpr]
-> [Reg]
-> [Reg]
-> OrdList Instr
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args [CmmExpr]
rest [Reg]
aregs [Reg]
fregs OrdList Instr
code OrdList Instr
acode
([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmExpr
argCmmExpr -> [CmmExpr] -> [CmmExpr]
forall a. a -> [a] -> [a]
:[CmmExpr]
args', [Reg]
ars, [Reg]
frs, OrdList Instr
code', OrdList Instr
acode')
reg_this_arg :: Reg -> NatM (OrdList Instr, OrdList Instr)
reg_this_arg r :: Reg
r
| Bool -> CmmExpr -> Bool
isOperand Bool
False CmmExpr
arg = do
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg
(OrdList Instr, OrdList Instr)
-> NatM (OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code, (OrdList Instr
acode OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
arg_code Reg
r))
| (CmmExpr -> Bool) -> [CmmExpr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> CmmExpr -> Bool
isOperand Bool
False) [CmmExpr]
rest = do
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg
(OrdList Instr, OrdList Instr)
-> NatM (OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
arg_code Reg
r,OrdList Instr
acode)
| Bool
otherwise = do
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
arg_fmt
let
code' :: OrdList Instr
code' = OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
arg_code Reg
tmp
acode' :: OrdList Instr
acode' = OrdList Instr
acode OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Reg -> Reg -> Instr
reg2reg Format
arg_fmt Reg
tmp Reg
r
(OrdList Instr, OrdList Instr)
-> NatM (OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr
code',OrdList Instr
acode')
arg_rep :: CmmType
arg_rep = DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
arg
arg_fmt :: Format
arg_fmt = CmmType -> Format
cmmTypeFormat CmmType
arg_rep
load_args_win :: [CmmExpr]
-> [Reg]
-> [Reg]
-> [(Reg, Reg)]
-> InstrBlock
-> NatM ([CmmExpr],[Reg],[Reg],InstrBlock,InstrBlock)
load_args_win :: [CmmExpr]
-> [Reg]
-> [Reg]
-> [(Reg, Reg)]
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args_win args :: [CmmExpr]
args usedInt :: [Reg]
usedInt usedFP :: [Reg]
usedFP [] code :: OrdList Instr
code
= ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CmmExpr]
args, [Reg]
usedInt, [Reg]
usedFP, OrdList Instr
code, OrdList Instr
forall a. OrdList a
nilOL)
load_args_win [] usedInt :: [Reg]
usedInt usedFP :: [Reg]
usedFP _ code :: OrdList Instr
code
= ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [Reg]
usedInt, [Reg]
usedFP, OrdList Instr
code, OrdList Instr
forall a. OrdList a
nilOL)
load_args_win (arg :: CmmExpr
arg : rest :: [CmmExpr]
rest) usedInt :: [Reg]
usedInt usedFP :: [Reg]
usedFP
((ireg :: Reg
ireg, freg :: Reg
freg) : regs :: [(Reg, Reg)]
regs) code :: OrdList Instr
code
| CmmType -> Bool
isFloatType CmmType
arg_rep = do
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg
[CmmExpr]
-> [Reg]
-> [Reg]
-> [(Reg, Reg)]
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args_win [CmmExpr]
rest (Reg
ireg Reg -> [Reg] -> [Reg]
forall a. a -> [a] -> [a]
: [Reg]
usedInt) (Reg
freg Reg -> [Reg] -> [Reg]
forall a. a -> [a] -> [a]
: [Reg]
usedFP) [(Reg, Reg)]
regs
(OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
arg_code Reg
freg OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Operand -> Operand -> Instr
MOV Format
II64 (Reg -> Operand
OpReg Reg
freg) (Reg -> Operand
OpReg Reg
ireg))
| Bool
otherwise = do
Reg -> OrdList Instr
arg_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
arg
[CmmExpr]
-> [Reg]
-> [Reg]
-> [(Reg, Reg)]
-> OrdList Instr
-> NatM ([CmmExpr], [Reg], [Reg], OrdList Instr, OrdList Instr)
load_args_win [CmmExpr]
rest (Reg
ireg Reg -> [Reg] -> [Reg]
forall a. a -> [a] -> [a]
: [Reg]
usedInt) [Reg]
usedFP [(Reg, Reg)]
regs
(OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Reg -> OrdList Instr
arg_code Reg
ireg)
where
arg_rep :: CmmType
arg_rep = DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
arg
push_args :: [CmmExpr] -> OrdList Instr -> NatM (OrdList Instr)
push_args [] code :: OrdList Instr
code = OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
push_args (arg :: CmmExpr
arg:rest :: [CmmExpr]
rest) code :: OrdList Instr
code
| CmmType -> Bool
isFloatType CmmType
arg_rep = do
(arg_reg :: Reg
arg_reg, arg_code :: OrdList Instr
arg_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
arg
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
arg_size)
let code' :: OrdList Instr
code' = OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
arg_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
SUB (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags)) (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt Alignment
arg_size)) (Reg -> Operand
OpReg Reg
rsp),
Alignment -> Instr
DELTA (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
arg_size),
Format -> Operand -> Operand -> Instr
MOV (Width -> Format
floatFormat Width
width) (Reg -> Operand
OpReg Reg
arg_reg) (AddrMode -> Operand
OpAddr (DynFlags -> Alignment -> AddrMode
spRel DynFlags
dflags 0))]
[CmmExpr] -> OrdList Instr -> NatM (OrdList Instr)
push_args [CmmExpr]
rest OrdList Instr
code'
| Bool
otherwise = do
ASSERT(width <= W64) return ()
(arg_op :: Operand
arg_op, arg_code :: OrdList Instr
arg_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
arg
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
arg_size)
let code' :: OrdList Instr
code' = OrdList Instr
code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
arg_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Instr
PUSH Format
II64 Operand
arg_op,
Alignment -> Instr
DELTA (Alignment
deltaAlignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
-Alignment
arg_size)]
[CmmExpr] -> OrdList Instr -> NatM (OrdList Instr)
push_args [CmmExpr]
rest OrdList Instr
code'
where
arg_rep :: CmmType
arg_rep = DynFlags -> CmmExpr -> CmmType
cmmExprType DynFlags
dflags CmmExpr
arg
width :: Width
width = CmmType -> Width
typeWidth CmmType
arg_rep
leaveStackSpace :: Alignment -> NatM (OrdList Instr)
leaveStackSpace n :: Alignment
n = do
Alignment
delta <- NatM Alignment
getDeltaNat
Alignment -> NatM ()
setDeltaNat (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
n Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
* Alignment
arg_size)
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
SUB Format
II64 (Imm -> Operand
OpImm (Alignment -> Imm
ImmInt (Alignment
n Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
* DynFlags -> Alignment
wORD_SIZE DynFlags
dflags))) (Reg -> Operand
OpReg Reg
rsp),
Alignment -> Instr
DELTA (Alignment
delta Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
- Alignment
n Alignment -> Alignment -> Alignment
forall a. Num a => a -> a -> a
* Alignment
arg_size)]
maybePromoteCArg :: DynFlags -> Width -> CmmExpr -> CmmExpr
maybePromoteCArg :: DynFlags -> Width -> CmmExpr -> CmmExpr
maybePromoteCArg dflags :: DynFlags
dflags wto :: Width
wto arg :: CmmExpr
arg
| Width
wfrom Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
< Width
wto = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> Width -> MachOp
MO_UU_Conv Width
wfrom Width
wto) [CmmExpr
arg]
| Bool
otherwise = CmmExpr
arg
where
wfrom :: Width
wfrom = DynFlags -> CmmExpr -> Width
cmmExprWidth DynFlags
dflags CmmExpr
arg
outOfLineCmmOp :: BlockId -> CallishMachOp -> Maybe CmmFormal -> [CmmActual]
-> NatM InstrBlock
outOfLineCmmOp :: Label
-> CallishMachOp
-> Maybe CmmFormal
-> [CmmExpr]
-> NatM (OrdList Instr)
outOfLineCmmOp bid :: Label
bid mop :: CallishMachOp
mop res :: Maybe CmmFormal
res args :: [CmmExpr]
args
= do
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
CmmExpr
targetExpr <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags ReferenceKind
CallReference CLabel
lbl
let target :: ForeignTarget
target = CmmExpr -> ForeignConvention -> ForeignTarget
ForeignTarget CmmExpr
targetExpr
(CCallConv
-> [ForeignHint]
-> [ForeignHint]
-> CmmReturnInfo
-> ForeignConvention
ForeignConvention CCallConv
CCallConv [] [] CmmReturnInfo
CmmMayReturn)
Label -> CmmNode O O -> NatM (OrdList Instr)
forall e x. Label -> CmmNode e x -> NatM (OrdList Instr)
stmtToInstrs Label
bid (ForeignTarget -> [CmmFormal] -> [CmmExpr] -> CmmNode O O
CmmUnsafeForeignCall ForeignTarget
target ([Maybe CmmFormal] -> [CmmFormal]
forall a. [Maybe a] -> [a]
catMaybes [Maybe CmmFormal
res]) [CmmExpr]
args)
where
lbl :: CLabel
lbl = FastString
-> Maybe Alignment
-> ForeignLabelSource
-> FunctionOrData
-> CLabel
mkForeignLabel FastString
fn Maybe Alignment
forall a. Maybe a
Nothing ForeignLabelSource
ForeignLabelInThisPackage FunctionOrData
IsFunction
fn :: FastString
fn = case CallishMachOp
mop of
MO_F32_Sqrt -> String -> FastString
fsLit "sqrtf"
MO_F32_Fabs -> String -> FastString
fsLit "fabsf"
MO_F32_Sin -> String -> FastString
fsLit "sinf"
MO_F32_Cos -> String -> FastString
fsLit "cosf"
MO_F32_Tan -> String -> FastString
fsLit "tanf"
MO_F32_Exp -> String -> FastString
fsLit "expf"
MO_F32_Log -> String -> FastString
fsLit "logf"
MO_F32_Asin -> String -> FastString
fsLit "asinf"
MO_F32_Acos -> String -> FastString
fsLit "acosf"
MO_F32_Atan -> String -> FastString
fsLit "atanf"
MO_F32_Sinh -> String -> FastString
fsLit "sinhf"
MO_F32_Cosh -> String -> FastString
fsLit "coshf"
MO_F32_Tanh -> String -> FastString
fsLit "tanhf"
MO_F32_Pwr -> String -> FastString
fsLit "powf"
MO_F32_Asinh -> String -> FastString
fsLit "asinhf"
MO_F32_Acosh -> String -> FastString
fsLit "acoshf"
MO_F32_Atanh -> String -> FastString
fsLit "atanhf"
MO_F64_Sqrt -> String -> FastString
fsLit "sqrt"
MO_F64_Fabs -> String -> FastString
fsLit "fabs"
MO_F64_Sin -> String -> FastString
fsLit "sin"
MO_F64_Cos -> String -> FastString
fsLit "cos"
MO_F64_Tan -> String -> FastString
fsLit "tan"
MO_F64_Exp -> String -> FastString
fsLit "exp"
MO_F64_Log -> String -> FastString
fsLit "log"
MO_F64_Asin -> String -> FastString
fsLit "asin"
MO_F64_Acos -> String -> FastString
fsLit "acos"
MO_F64_Atan -> String -> FastString
fsLit "atan"
MO_F64_Sinh -> String -> FastString
fsLit "sinh"
MO_F64_Cosh -> String -> FastString
fsLit "cosh"
MO_F64_Tanh -> String -> FastString
fsLit "tanh"
MO_F64_Pwr -> String -> FastString
fsLit "pow"
MO_F64_Asinh -> String -> FastString
fsLit "asinh"
MO_F64_Acosh -> String -> FastString
fsLit "acosh"
MO_F64_Atanh -> String -> FastString
fsLit "atanh"
MO_Memcpy _ -> String -> FastString
fsLit "memcpy"
MO_Memset _ -> String -> FastString
fsLit "memset"
MO_Memmove _ -> String -> FastString
fsLit "memmove"
MO_Memcmp _ -> String -> FastString
fsLit "memcmp"
MO_PopCnt _ -> String -> FastString
fsLit "popcnt"
MO_BSwap _ -> String -> FastString
fsLit "bswap"
MO_Clz w :: Width
w -> String -> FastString
fsLit (String -> FastString) -> String -> FastString
forall a b. (a -> b) -> a -> b
$ Width -> String
clzLabel Width
w
MO_Ctz _ -> FastString
unsupported
MO_Pdep w :: Width
w -> String -> FastString
fsLit (String -> FastString) -> String -> FastString
forall a b. (a -> b) -> a -> b
$ Width -> String
pdepLabel Width
w
MO_Pext w :: Width
w -> String -> FastString
fsLit (String -> FastString) -> String -> FastString
forall a b. (a -> b) -> a -> b
$ Width -> String
pextLabel Width
w
MO_AtomicRMW _ _ -> String -> FastString
fsLit "atomicrmw"
MO_AtomicRead _ -> String -> FastString
fsLit "atomicread"
MO_AtomicWrite _ -> String -> FastString
fsLit "atomicwrite"
MO_Cmpxchg _ -> String -> FastString
fsLit "cmpxchg"
MO_UF_Conv _ -> FastString
unsupported
MO_S_QuotRem {} -> FastString
unsupported
MO_U_QuotRem {} -> FastString
unsupported
MO_U_QuotRem2 {} -> FastString
unsupported
MO_Add2 {} -> FastString
unsupported
MO_AddIntC {} -> FastString
unsupported
MO_SubIntC {} -> FastString
unsupported
MO_AddWordC {} -> FastString
unsupported
MO_SubWordC {} -> FastString
unsupported
MO_U_Mul2 {} -> FastString
unsupported
MO_ReadBarrier -> FastString
unsupported
MO_WriteBarrier -> FastString
unsupported
MO_Touch -> FastString
unsupported
(MO_Prefetch_Data _ ) -> FastString
unsupported
unsupported :: FastString
unsupported = String -> FastString
forall a. String -> a
panic ("outOfLineCmmOp: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ CallishMachOp -> String
forall a. Show a => a -> String
show CallishMachOp
mop
String -> String -> String
forall a. [a] -> [a] -> [a]
++ " not supported here")
genSwitch :: DynFlags -> CmmExpr -> SwitchTargets -> NatM InstrBlock
genSwitch :: DynFlags -> CmmExpr -> SwitchTargets -> NatM (OrdList Instr)
genSwitch dflags :: DynFlags
dflags expr :: CmmExpr
expr targets :: SwitchTargets
targets
| DynFlags -> Bool
positionIndependent DynFlags
dflags
= do
(reg :: Reg
reg,e_code :: OrdList Instr
e_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg (DynFlags -> CmmExpr -> Alignment -> CmmExpr
cmmOffset DynFlags
dflags CmmExpr
expr Alignment
offset)
CLabel
lbl <- NatM CLabel
getNewLabelNat
DynFlags
dflags <- NatM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let is32bit :: Bool
is32bit = Platform -> Bool
target32Bit (DynFlags -> Platform
targetPlatform DynFlags
dflags)
os :: OS
os = Platform -> OS
platformOS (DynFlags -> Platform
targetPlatform DynFlags
dflags)
rosection :: Section
rosection = case OS
os of
OSDarwin | Bool -> Bool
not Bool
is32bit -> SectionType -> CLabel -> Section
Section SectionType
Text CLabel
lbl
_ -> SectionType -> CLabel -> Section
Section SectionType
ReadOnlyData CLabel
lbl
CmmExpr
dynRef <- DynFlags -> ReferenceKind -> CLabel -> NatM CmmExpr
forall (m :: * -> *).
CmmMakeDynamicReferenceM m =>
DynFlags -> ReferenceKind -> CLabel -> m CmmExpr
cmmMakeDynamicReference DynFlags
dflags ReferenceKind
DataReference CLabel
lbl
(tableReg :: Reg
tableReg,t_code :: OrdList Instr
t_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg (CmmExpr -> NatM (Reg, OrdList Instr))
-> CmmExpr -> NatM (Reg, OrdList Instr)
forall a b. (a -> b) -> a -> b
$ CmmExpr
dynRef
let op :: Operand
op = AddrMode -> Operand
OpAddr (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex (Reg -> EABase
EABaseReg Reg
tableReg)
(Reg -> Alignment -> EAIndex
EAIndex Reg
reg (DynFlags -> Alignment
wORD_SIZE DynFlags
dflags)) (Alignment -> Imm
ImmInt 0))
Reg
offsetReg <- Format -> NatM Reg
getNewRegNat (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags))
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OrdList Instr -> NatM (OrdList Instr))
-> OrdList Instr -> NatM (OrdList Instr)
forall a b. (a -> b) -> a -> b
$ if Bool
is32bit Bool -> Bool -> Bool
|| OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
OSDarwin
then OrdList Instr
e_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
t_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
ADD (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags)) Operand
op (Reg -> Operand
OpReg Reg
tableReg),
Operand -> [Maybe JumpDest] -> Section -> CLabel -> Instr
JMP_TBL (Reg -> Operand
OpReg Reg
tableReg) [Maybe JumpDest]
ids Section
rosection CLabel
lbl
]
else
OrdList Instr
e_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
t_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
MOVSxL Format
II32 Operand
op (Reg -> Operand
OpReg Reg
offsetReg),
Format -> Operand -> Operand -> Instr
ADD (Width -> Format
intFormat (DynFlags -> Width
wordWidth DynFlags
dflags))
(Reg -> Operand
OpReg Reg
offsetReg)
(Reg -> Operand
OpReg Reg
tableReg),
Operand -> [Maybe JumpDest] -> Section -> CLabel -> Instr
JMP_TBL (Reg -> Operand
OpReg Reg
tableReg) [Maybe JumpDest]
ids Section
rosection CLabel
lbl
]
| Bool
otherwise
= do
(reg :: Reg
reg,e_code :: OrdList Instr
e_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg (DynFlags -> CmmExpr -> Alignment -> CmmExpr
cmmOffset DynFlags
dflags CmmExpr
expr Alignment
offset)
CLabel
lbl <- NatM CLabel
getNewLabelNat
let op :: Operand
op = AddrMode -> Operand
OpAddr (EABase -> EAIndex -> Imm -> AddrMode
AddrBaseIndex EABase
EABaseNone (Reg -> Alignment -> EAIndex
EAIndex Reg
reg (DynFlags -> Alignment
wORD_SIZE DynFlags
dflags)) (CLabel -> Imm
ImmCLbl CLabel
lbl))
code :: OrdList Instr
code = OrdList Instr
e_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Operand -> [Maybe JumpDest] -> Section -> CLabel -> Instr
JMP_TBL Operand
op [Maybe JumpDest]
ids (SectionType -> CLabel -> Section
Section SectionType
ReadOnlyData CLabel
lbl) CLabel
lbl
]
OrdList Instr -> NatM (OrdList Instr)
forall (m :: * -> *) a. Monad m => a -> m a
return OrdList Instr
code
where
(offset :: Alignment
offset, blockIds :: [Maybe Label]
blockIds) = SwitchTargets -> (Alignment, [Maybe Label])
switchTargetsToTable SwitchTargets
targets
ids :: [Maybe JumpDest]
ids = (Maybe Label -> Maybe JumpDest)
-> [Maybe Label] -> [Maybe JumpDest]
forall a b. (a -> b) -> [a] -> [b]
map ((Label -> JumpDest) -> Maybe Label -> Maybe JumpDest
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Label -> JumpDest
DestBlockId) [Maybe Label]
blockIds
generateJumpTableForInstr :: DynFlags -> Instr -> Maybe (NatCmmDecl (Alignment, CmmStatics) Instr)
generateJumpTableForInstr :: DynFlags
-> Instr -> Maybe (NatCmmDecl (Alignment, CmmStatics) Instr)
generateJumpTableForInstr dflags :: DynFlags
dflags (JMP_TBL _ ids :: [Maybe JumpDest]
ids section :: Section
section lbl :: CLabel
lbl)
= let getBlockId :: JumpDest -> Label
getBlockId (DestBlockId id :: Label
id) = Label
id
getBlockId _ = String -> Label
forall a. String -> a
panic "Non-Label target in Jump Table"
blockIds :: [Maybe Label]
blockIds = (Maybe JumpDest -> Maybe Label)
-> [Maybe JumpDest] -> [Maybe Label]
forall a b. (a -> b) -> [a] -> [b]
map ((JumpDest -> Label) -> Maybe JumpDest -> Maybe Label
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap JumpDest -> Label
getBlockId) [Maybe JumpDest]
ids
in NatCmmDecl (Alignment, CmmStatics) Instr
-> Maybe (NatCmmDecl (Alignment, CmmStatics) Instr)
forall a. a -> Maybe a
Just (DynFlags
-> [Maybe Label]
-> Section
-> CLabel
-> NatCmmDecl (Alignment, CmmStatics) Instr
forall h g.
DynFlags
-> [Maybe Label]
-> Section
-> CLabel
-> GenCmmDecl (Alignment, CmmStatics) h g
createJumpTable DynFlags
dflags [Maybe Label]
blockIds Section
section CLabel
lbl)
generateJumpTableForInstr _ _ = Maybe (NatCmmDecl (Alignment, CmmStatics) Instr)
forall a. Maybe a
Nothing
createJumpTable :: DynFlags -> [Maybe BlockId] -> Section -> CLabel
-> GenCmmDecl (Alignment, CmmStatics) h g
createJumpTable :: DynFlags
-> [Maybe Label]
-> Section
-> CLabel
-> GenCmmDecl (Alignment, CmmStatics) h g
createJumpTable dflags :: DynFlags
dflags ids :: [Maybe Label]
ids section :: Section
section lbl :: CLabel
lbl
= let jumpTable :: [CmmStatic]
jumpTable
| DynFlags -> Bool
positionIndependent DynFlags
dflags =
let ww :: Width
ww = DynFlags -> Width
wordWidth DynFlags
dflags
jumpTableEntryRel :: Maybe Label -> CmmStatic
jumpTableEntryRel Nothing
= CmmLit -> CmmStatic
CmmStaticLit (Integer -> Width -> CmmLit
CmmInt 0 Width
ww)
jumpTableEntryRel (Just blockid :: Label
blockid)
= CmmLit -> CmmStatic
CmmStaticLit (CLabel -> CLabel -> Alignment -> Width -> CmmLit
CmmLabelDiffOff CLabel
blockLabel CLabel
lbl 0 Width
ww)
where blockLabel :: CLabel
blockLabel = Label -> CLabel
blockLbl Label
blockid
in (Maybe Label -> CmmStatic) -> [Maybe Label] -> [CmmStatic]
forall a b. (a -> b) -> [a] -> [b]
map Maybe Label -> CmmStatic
jumpTableEntryRel [Maybe Label]
ids
| Bool
otherwise = (Maybe Label -> CmmStatic) -> [Maybe Label] -> [CmmStatic]
forall a b. (a -> b) -> [a] -> [b]
map (DynFlags -> Maybe Label -> CmmStatic
jumpTableEntry DynFlags
dflags) [Maybe Label]
ids
in Section
-> (Alignment, CmmStatics)
-> GenCmmDecl (Alignment, CmmStatics) h g
forall d h g. Section -> d -> GenCmmDecl d h g
CmmData Section
section (1, CLabel -> [CmmStatic] -> CmmStatics
Statics CLabel
lbl [CmmStatic]
jumpTable)
extractUnwindPoints :: [Instr] -> [UnwindPoint]
instrs :: [Instr]
instrs =
[ CLabel -> Map GlobalReg (Maybe UnwindExpr) -> UnwindPoint
UnwindPoint CLabel
lbl Map GlobalReg (Maybe UnwindExpr)
unwinds | UNWIND lbl :: CLabel
lbl unwinds :: Map GlobalReg (Maybe UnwindExpr)
unwinds <- [Instr]
instrs]
condIntReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
condIntReg cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y = do
CondCode _ cond :: Cond
cond cond_code :: OrdList Instr
cond_code <- Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condIntCode Cond
cond CmmExpr
x CmmExpr
y
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
II8
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
cond_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
tmp),
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
tmp) (Reg -> Operand
OpReg Reg
dst)
]
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
condFltReg :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM Register
condFltReg is32Bit :: Bool
is32Bit cond :: Cond
cond x :: CmmExpr
x y :: CmmExpr
y = NatM Register -> NatM Register -> NatM Register
forall a. NatM a -> NatM a -> NatM a
if_sse2 NatM Register
condFltReg_sse2 NatM Register
condFltReg_x87
where
condFltReg_x87 :: NatM Register
condFltReg_x87 = do
CondCode _ cond :: Cond
cond cond_code :: OrdList Instr
cond_code <- Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
cond CmmExpr
x CmmExpr
y
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
II8
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
cond_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
tmp),
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
tmp) (Reg -> Operand
OpReg Reg
dst)
]
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
condFltReg_sse2 :: NatM Register
condFltReg_sse2 = do
CondCode _ cond :: Cond
cond cond_code :: OrdList Instr
cond_code <- Cond -> CmmExpr -> CmmExpr -> NatM CondCode
condFltCode Cond
cond CmmExpr
x CmmExpr
y
Reg
tmp1 <- Format -> NatM Reg
getNewRegNat (Bool -> Format
archWordFormat Bool
is32Bit)
Reg
tmp2 <- Format -> NatM Reg
getNewRegNat (Bool -> Format
archWordFormat Bool
is32Bit)
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst =
OrdList Instr
cond_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
(case Cond
cond of
NE -> Reg -> OrdList Instr
or_unordered Reg
dst
GU -> Reg -> OrdList Instr
plain_test Reg
dst
GEU -> Reg -> OrdList Instr
plain_test Reg
dst
LTT -> ASSERT2(False, ppr "Should have been turned into >")
Reg -> OrdList Instr
and_ordered Reg
dst
LE -> ASSERT2(False, ppr "Should have been turned into >=")
Reg -> OrdList Instr
and_ordered Reg
dst
_ -> Reg -> OrdList Instr
and_ordered Reg
dst)
plain_test :: Reg -> OrdList Instr
plain_test dst :: Reg
dst = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
tmp1),
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
tmp1) (Reg -> Operand
OpReg Reg
dst)
]
or_unordered :: Reg -> OrdList Instr
or_unordered dst :: Reg
dst = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
tmp1),
Cond -> Operand -> Instr
SETCC Cond
PARITY (Reg -> Operand
OpReg Reg
tmp2),
Format -> Operand -> Operand -> Instr
OR Format
II8 (Reg -> Operand
OpReg Reg
tmp1) (Reg -> Operand
OpReg Reg
tmp2),
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
tmp2) (Reg -> Operand
OpReg Reg
dst)
]
and_ordered :: Reg -> OrdList Instr
and_ordered dst :: Reg
dst = [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Cond -> Operand -> Instr
SETCC Cond
cond (Reg -> Operand
OpReg Reg
tmp1),
Cond -> Operand -> Instr
SETCC Cond
NOTPARITY (Reg -> Operand
OpReg Reg
tmp2),
Format -> Operand -> Operand -> Instr
AND Format
II8 (Reg -> Operand
OpReg Reg
tmp1) (Reg -> Operand
OpReg Reg
tmp2),
Format -> Operand -> Operand -> Instr
MOVZxL Format
II8 (Reg -> Operand
OpReg Reg
tmp2) (Reg -> Operand
OpReg Reg
dst)
]
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
II32 Reg -> OrdList Instr
code)
trivialCode :: Width -> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialCode :: Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode width :: Width
width instr :: Operand -> Operand -> Instr
instr m :: Maybe (Operand -> Operand -> Instr)
m a :: CmmExpr
a b :: CmmExpr
b
= do Bool
is32Bit <- NatM Bool
is32BitPlatform
Bool
-> Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode' Bool
is32Bit Width
width Operand -> Operand -> Instr
instr Maybe (Operand -> Operand -> Instr)
m CmmExpr
a CmmExpr
b
trivialCode' :: Bool -> Width -> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialCode' :: Bool
-> Width
-> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialCode' is32Bit :: Bool
is32Bit width :: Width
width _ (Just revinstr :: Operand -> Operand -> Instr
revinstr) (CmmLit lit_a :: CmmLit
lit_a) b :: CmmExpr
b
| Bool -> CmmLit -> Bool
is32BitLit Bool
is32Bit CmmLit
lit_a = do
Reg -> OrdList Instr
b_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
b
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst
= Reg -> OrdList Instr
b_code Reg
dst OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Operand -> Operand -> Instr
revinstr (Imm -> Operand
OpImm (CmmLit -> Imm
litToImm CmmLit
lit_a)) (Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
intFormat Width
width) Reg -> OrdList Instr
code)
trivialCode' _ width :: Width
width instr :: Operand -> Operand -> Instr
instr _ a :: CmmExpr
a b :: CmmExpr
b
= Format
-> (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
genTrivialCode (Width -> Format
intFormat Width
width) Operand -> Operand -> Instr
instr CmmExpr
a CmmExpr
b
genTrivialCode :: Format -> (Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
genTrivialCode :: Format
-> (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
genTrivialCode rep :: Format
rep instr :: Operand -> Operand -> Instr
instr a :: CmmExpr
a b :: CmmExpr
b = do
(b_op :: Operand
b_op, b_code :: OrdList Instr
b_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getNonClobberedOperand CmmExpr
b
Reg -> OrdList Instr
a_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
a
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
rep
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst
| Reg
dst Reg -> Operand -> Bool
`regClashesWithOp` Operand
b_op =
OrdList Instr
b_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Instr -> OrdList Instr
forall a. a -> OrdList a
unitOL (Format -> Operand -> Operand -> Instr
MOV Format
rep Operand
b_op (Reg -> Operand
OpReg Reg
tmp)) OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
a_code Reg
dst OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Operand -> Operand -> Instr
instr (Reg -> Operand
OpReg Reg
tmp) (Reg -> Operand
OpReg Reg
dst)
| Bool
otherwise =
OrdList Instr
b_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
Reg -> OrdList Instr
a_code Reg
dst OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Operand -> Operand -> Instr
instr Operand
b_op (Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
rep Reg -> OrdList Instr
code)
regClashesWithOp :: Reg -> Operand -> Bool
reg :: Reg
reg regClashesWithOp :: Reg -> Operand -> Bool
`regClashesWithOp` OpReg reg2 :: Reg
reg2 = Reg
reg Reg -> Reg -> Bool
forall a. Eq a => a -> a -> Bool
== Reg
reg2
reg :: Reg
reg `regClashesWithOp` OpAddr amode :: AddrMode
amode = (Reg -> Bool) -> [Reg] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Reg -> Reg -> Bool
forall a. Eq a => a -> a -> Bool
==Reg
reg) (AddrMode -> [Reg]
addrModeRegs AddrMode
amode)
_ `regClashesWithOp` _ = Bool
False
trivialUCode :: Format -> (Operand -> Instr)
-> CmmExpr -> NatM Register
trivialUCode :: Format -> (Operand -> Instr) -> CmmExpr -> NatM Register
trivialUCode rep :: Format
rep instr :: Operand -> Instr
instr x :: CmmExpr
x = do
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst =
Reg -> OrdList Instr
x_code Reg
dst OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Operand -> Instr
instr (Reg -> Operand
OpReg Reg
dst)
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
rep Reg -> OrdList Instr
code)
trivialFCode_x87 :: (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 :: (Format -> Reg -> Reg -> Reg -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_x87 instr :: Format -> Reg -> Reg -> Reg -> Instr
instr x :: CmmExpr
x y :: CmmExpr
y = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getNonClobberedReg CmmExpr
x
(y_reg :: Reg
y_reg, y_code :: OrdList Instr
y_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
y
let
format :: Format
format = Format
FF80
code :: Reg -> OrdList Instr
code dst :: Reg
dst =
OrdList Instr
x_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL`
OrdList Instr
y_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Format -> Reg -> Reg -> Reg -> Instr
instr Format
format Reg
x_reg Reg
y_reg Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
trivialFCode_sse2 :: Width -> (Format -> Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialFCode_sse2 :: Width
-> (Format -> Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
trivialFCode_sse2 pk :: Width
pk instr :: Format -> Operand -> Operand -> Instr
instr x :: CmmExpr
x y :: CmmExpr
y
= Format
-> (Operand -> Operand -> Instr)
-> CmmExpr
-> CmmExpr
-> NatM Register
genTrivialCode Format
format (Format -> Operand -> Operand -> Instr
instr Format
format) CmmExpr
x CmmExpr
y
where format :: Format
format = Width -> Format
floatFormat Width
pk
trivialUFCode :: Format -> (Reg -> Reg -> Instr) -> CmmExpr -> NatM Register
trivialUFCode :: Format -> (Reg -> Reg -> Instr) -> CmmExpr -> NatM Register
trivialUFCode format :: Format
format instr :: Reg -> Reg -> Instr
instr x :: CmmExpr
x = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst =
OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL`
Reg -> Reg -> Instr
instr Reg
x_reg Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
format Reg -> OrdList Instr
code)
coerceInt2FP :: Width -> Width -> CmmExpr -> NatM Register
coerceInt2FP :: Width -> Width -> CmmExpr -> NatM Register
coerceInt2FP from :: Width
from to :: Width
to x :: CmmExpr
x = NatM Register -> NatM Register -> NatM Register
forall a. NatM a -> NatM a -> NatM a
if_sse2 NatM Register
coerce_sse2 NatM Register
coerce_x87
where
coerce_x87 :: NatM Register
coerce_x87 = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
opc :: Reg -> Reg -> Instr
opc = case Width
to of W32 -> Reg -> Reg -> Instr
GITOF; W64 -> Reg -> Reg -> Instr
GITOD;
n :: Width
n -> String -> Reg -> Reg -> Instr
forall a. String -> a
panic (String -> Reg -> Reg -> Instr) -> String -> Reg -> Reg -> Instr
forall a b. (a -> b) -> a -> b
$ "coerceInt2FP.x87: unhandled width ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Reg -> Reg -> Instr
opc Reg
x_reg Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
FF80 Reg -> OrdList Instr
code)
coerce_sse2 :: NatM Register
coerce_sse2 = do
(x_op :: Operand
x_op, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
x
let
opc :: Format -> Operand -> Reg -> Instr
opc = case Width
to of W32 -> Format -> Operand -> Reg -> Instr
CVTSI2SS; W64 -> Format -> Operand -> Reg -> Instr
CVTSI2SD
n :: Width
n -> String -> Format -> Operand -> Reg -> Instr
forall a. String -> a
panic (String -> Format -> Operand -> Reg -> Instr)
-> String -> Format -> Operand -> Reg -> Instr
forall a b. (a -> b) -> a -> b
$ "coerceInt2FP.sse: unhandled width ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Operand -> Reg -> Instr
opc (Width -> Format
intFormat Width
from) Operand
x_op Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
floatFormat Width
to) Reg -> OrdList Instr
code)
coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register
coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register
coerceFP2Int from :: Width
from to :: Width
to x :: CmmExpr
x = NatM Register -> NatM Register -> NatM Register
forall a. NatM a -> NatM a -> NatM a
if_sse2 NatM Register
coerceFP2Int_sse2 NatM Register
coerceFP2Int_x87
where
coerceFP2Int_x87 :: NatM Register
coerceFP2Int_x87 = do
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
opc :: Reg -> Reg -> Instr
opc = case Width
from of W32 -> Reg -> Reg -> Instr
GFTOI; W64 -> Reg -> Reg -> Instr
GDTOI
n :: Width
n -> String -> Reg -> Reg -> Instr
forall a. String -> a
panic (String -> Reg -> Reg -> Instr) -> String -> Reg -> Reg -> Instr
forall a b. (a -> b) -> a -> b
$ "coerceFP2Int.x87: unhandled width ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Reg -> Reg -> Instr
opc Reg
x_reg Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
intFormat Width
to) Reg -> OrdList Instr
code)
coerceFP2Int_sse2 :: NatM Register
coerceFP2Int_sse2 = do
(x_op :: Operand
x_op, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Operand, OrdList Instr)
getOperand CmmExpr
x
let
opc :: Format -> Operand -> Reg -> Instr
opc = case Width
from of W32 -> Format -> Operand -> Reg -> Instr
CVTTSS2SIQ; W64 -> Format -> Operand -> Reg -> Instr
CVTTSD2SIQ;
n :: Width
n -> String -> Format -> Operand -> Reg -> Instr
forall a. String -> a
panic (String -> Format -> Operand -> Reg -> Instr)
-> String -> Format -> Operand -> Reg -> Instr
forall a b. (a -> b) -> a -> b
$ "coerceFP2Init.sse: unhandled width ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Format -> Operand -> Reg -> Instr
opc (Width -> Format
intFormat Width
to) Operand
x_op Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (Width -> Format
intFormat Width
to) Reg -> OrdList Instr
code)
coerceFP2FP :: Width -> CmmExpr -> NatM Register
coerceFP2FP :: Width -> CmmExpr -> NatM Register
coerceFP2FP to :: Width
to x :: CmmExpr
x = do
Bool
use_sse2 <- NatM Bool
sse2Enabled
(x_reg :: Reg
x_reg, x_code :: OrdList Instr
x_code) <- CmmExpr -> NatM (Reg, OrdList Instr)
getSomeReg CmmExpr
x
let
opc :: Reg -> Reg -> Instr
opc | Bool
use_sse2 = case Width
to of W32 -> Reg -> Reg -> Instr
CVTSD2SS; W64 -> Reg -> Reg -> Instr
CVTSS2SD;
n :: Width
n -> String -> Reg -> Reg -> Instr
forall a. String -> a
panic (String -> Reg -> Reg -> Instr) -> String -> Reg -> Reg -> Instr
forall a b. (a -> b) -> a -> b
$ "coerceFP2FP: unhandled width ("
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ ")"
| Bool
otherwise = Reg -> Reg -> Instr
GDTOF
code :: Reg -> OrdList Instr
code dst :: Reg
dst = OrdList Instr
x_code OrdList Instr -> Instr -> OrdList Instr
forall a. OrdList a -> a -> OrdList a
`snocOL` Reg -> Reg -> Instr
opc Reg
x_reg Reg
dst
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any (if Bool
use_sse2 then Width -> Format
floatFormat Width
to else Format
FF80) Reg -> OrdList Instr
code)
sse2NegCode :: Width -> CmmExpr -> NatM Register
sse2NegCode :: Width -> CmmExpr -> NatM Register
sse2NegCode w :: Width
w x :: CmmExpr
x = do
let fmt :: Format
fmt = Width -> Format
floatFormat Width
w
Reg -> OrdList Instr
x_code <- CmmExpr -> NatM (Reg -> OrdList Instr)
getAnyReg CmmExpr
x
let
const :: CmmLit
const = case Format
fmt of
FF32 -> Integer -> Width -> CmmLit
CmmInt 0x80000000 Width
W32
FF64 -> Integer -> Width -> CmmLit
CmmInt 0x8000000000000000 Width
W64
x :: Format
x@Format
II8 -> Format -> CmmLit
forall a a. Show a => a -> a
wrongFmt Format
x
x :: Format
x@Format
II16 -> Format -> CmmLit
forall a a. Show a => a -> a
wrongFmt Format
x
x :: Format
x@Format
II32 -> Format -> CmmLit
forall a a. Show a => a -> a
wrongFmt Format
x
x :: Format
x@Format
II64 -> Format -> CmmLit
forall a a. Show a => a -> a
wrongFmt Format
x
x :: Format
x@Format
FF80 -> Format -> CmmLit
forall a a. Show a => a -> a
wrongFmt Format
x
where
wrongFmt :: a -> a
wrongFmt x :: a
x = String -> a
forall a. String -> a
panic (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ "sse2NegCode: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x
Amode amode :: AddrMode
amode amode_code :: OrdList Instr
amode_code <- Alignment -> CmmLit -> NatM Amode
memConstant (Width -> Alignment
widthInBytes Width
w) CmmLit
const
Reg
tmp <- Format -> NatM Reg
getNewRegNat Format
fmt
let
code :: Reg -> OrdList Instr
code dst :: Reg
dst = Reg -> OrdList Instr
x_code Reg
dst OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` OrdList Instr
amode_code OrdList Instr -> OrdList Instr -> OrdList Instr
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` [Instr] -> OrdList Instr
forall a. [a] -> OrdList a
toOL [
Format -> Operand -> Operand -> Instr
MOV Format
fmt (AddrMode -> Operand
OpAddr AddrMode
amode) (Reg -> Operand
OpReg Reg
tmp),
Format -> Operand -> Operand -> Instr
XOR Format
fmt (Reg -> Operand
OpReg Reg
tmp) (Reg -> Operand
OpReg Reg
dst)
]
Register -> NatM Register
forall (m :: * -> *) a. Monad m => a -> m a
return (Format -> (Reg -> OrdList Instr) -> Register
Any Format
fmt Reg -> OrdList Instr
code)
isVecExpr :: CmmExpr -> Bool
isVecExpr :: CmmExpr -> Bool
isVecExpr (CmmMachOp (MO_V_Insert {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_V_Extract {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_V_Add {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_V_Sub {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_V_Mul {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VS_Quot {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VS_Rem {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VS_Neg {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Insert {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Extract {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Add {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Sub {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Mul {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Quot {}) _) = Bool
True
isVecExpr (CmmMachOp (MO_VF_Neg {}) _) = Bool
True
isVecExpr (CmmMachOp _ [e :: CmmExpr
e]) = CmmExpr -> Bool
isVecExpr CmmExpr
e
isVecExpr _ = Bool
False
needLlvm :: NatM a
needLlvm :: NatM a
needLlvm =
String -> NatM a
forall a. String -> a
sorry (String -> NatM a) -> String -> NatM a
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ["The native code generator does not support vector"
,"instructions. Please use -fllvm."]
invertCondBranches :: CFG -> LabelMap a -> [NatBasicBlock Instr]
-> [NatBasicBlock Instr]
invertCondBranches :: CFG -> LabelMap a -> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
invertCondBranches cfg :: CFG
cfg keep :: LabelMap a
keep bs :: [NatBasicBlock Instr]
bs =
[NatBasicBlock Instr] -> [NatBasicBlock Instr]
invert [NatBasicBlock Instr]
bs
where
invert :: [NatBasicBlock Instr] -> [NatBasicBlock Instr]
invert :: [NatBasicBlock Instr] -> [NatBasicBlock Instr]
invert ((BasicBlock lbl1 :: Label
lbl1 ins :: [Instr]
ins@(_:_:_xs :: [Instr]
_xs)):b2 :: NatBasicBlock Instr
b2@(BasicBlock lbl2 :: Label
lbl2 _):bs :: [NatBasicBlock Instr]
bs)
|
(jmp1 :: Instr
jmp1,jmp2 :: Instr
jmp2) <- [Instr] -> (Instr, Instr)
forall a. [a] -> (a, a)
last2 [Instr]
ins
, JXX cond1 :: Cond
cond1 target1 :: Label
target1 <- Instr
jmp1
, Label
target1 Label -> Label -> Bool
forall a. Eq a => a -> a -> Bool
== Label
lbl2
, JXX ALWAYS target2 :: Label
target2 <- Instr
jmp2
, Just edgeInfo1 :: EdgeInfo
edgeInfo1 <- Label -> Label -> CFG -> Maybe EdgeInfo
getEdgeInfo Label
lbl1 Label
target1 CFG
cfg
, Just edgeInfo2 :: EdgeInfo
edgeInfo2 <- Label -> Label -> CFG -> Maybe EdgeInfo
getEdgeInfo Label
lbl1 Label
target2 CFG
cfg
, EdgeInfo -> TransitionSource
transitionSource EdgeInfo
edgeInfo1 TransitionSource -> TransitionSource -> Bool
forall a. Eq a => a -> a -> Bool
== EdgeInfo -> TransitionSource
transitionSource EdgeInfo
edgeInfo2
, (CmmSource cmmCondBranch :: CmmNode O C
cmmCondBranch) <- EdgeInfo -> TransitionSource
transitionSource EdgeInfo
edgeInfo1
, CmmCondBranch (CmmMachOp op :: MachOp
op _args :: [CmmExpr]
_args) _ _ _ <- CmmNode O C
cmmCondBranch
, Just _ <- MachOp -> Maybe Width
maybeIntComparison MachOp
op
, Just invCond :: Cond
invCond <- Cond -> Maybe Cond
maybeInvertCond Cond
cond1
= let jumps :: [Instr]
jumps =
case () of
_ | Bool -> Bool
not (KeyOf LabelMap -> LabelMap a -> Bool
forall (map :: * -> *) a. IsMap map => KeyOf map -> map a -> Bool
mapMember KeyOf LabelMap
Label
target1 LabelMap a
keep)
-> [Cond -> Label -> Instr
JXX Cond
invCond Label
target2]
| EdgeInfo -> EdgeWeight
edgeWeight EdgeInfo
edgeInfo2 EdgeWeight -> EdgeWeight -> Bool
forall a. Ord a => a -> a -> Bool
> EdgeInfo -> EdgeWeight
edgeWeight EdgeInfo
edgeInfo1
-> [Cond -> Label -> Instr
JXX Cond
invCond Label
target2, Cond -> Label -> Instr
JXX Cond
ALWAYS Label
target1]
| Bool
otherwise
-> [Instr
jmp1, Instr
jmp2]
in
(Label -> [Instr] -> NatBasicBlock Instr
forall i. Label -> [i] -> GenBasicBlock i
BasicBlock Label
lbl1
(Alignment -> [Instr] -> [Instr]
forall a. Alignment -> [a] -> [a]
dropTail 2 [Instr]
ins [Instr] -> [Instr] -> [Instr]
forall a. [a] -> [a] -> [a]
++ [Instr]
jumps))
NatBasicBlock Instr
-> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
forall a. a -> [a] -> [a]
: [NatBasicBlock Instr] -> [NatBasicBlock Instr]
invert (NatBasicBlock Instr
b2NatBasicBlock Instr
-> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
forall a. a -> [a] -> [a]
:[NatBasicBlock Instr]
bs)
invert (b :: NatBasicBlock Instr
b:bs :: [NatBasicBlock Instr]
bs) = NatBasicBlock Instr
b NatBasicBlock Instr
-> [NatBasicBlock Instr] -> [NatBasicBlock Instr]
forall a. a -> [a] -> [a]
: [NatBasicBlock Instr] -> [NatBasicBlock Instr]
invert [NatBasicBlock Instr]
bs
invert [] = []