import MachInstrs
import MachRegs
import NCGMonad
-import PositionIndependentCode ( cmmMakeDynamicReference, initializePicBase )
+import PositionIndependentCode
import RegAllocInfo ( mkBranchInstr )
-- Our intermediate code:
#ifdef DEBUG
import Outputable ( assertPanic )
-import TRACE ( trace )
+import Debug.Trace ( trace )
#endif
import Control.Monad ( mapAndUnzipM )
-import Maybe ( fromJust )
-import DATA_BITS
-import DATA_WORD
+import Data.Maybe ( fromJust )
+import Data.Bits
+import Data.Word
-- -----------------------------------------------------------------------------
-- Top-level of the instruction selector
getRegister :: CmmExpr -> NatM Register
+#if !x86_64_TARGET_ARCH
+ -- on x86_64, we have %rip for PicBaseReg, but it's not a full-featured
+ -- register, it can only be used for rip-relative addressing.
getRegister (CmmReg (CmmGlobal PicBaseReg))
= do
reg <- getPicBaseNat wordRep
return (Fixed wordRep reg nilOL)
+#endif
getRegister (CmmReg reg)
= return (Fixed (cmmRegRep reg) (getRegisterReg reg) nilOL)
getRegister tree@(CmmRegOff _ _)
= getRegister (mangleIndexTree tree)
+
+#if WORD_SIZE_IN_BITS==32
+ -- for 32-bit architectuers, support some 64 -> 32 bit conversions:
+ -- TO_W_(x), TO_W_(x >> 32)
+
+getRegister (CmmMachOp (MO_U_Conv I64 I32)
+ [CmmMachOp (MO_U_Shr I64) [x,CmmLit (CmmInt 32 _)]]) = do
+ ChildCode64 code rlo <- iselExpr64 x
+ return $ Fixed I32 (getHiVRegFromLo rlo) code
+
+getRegister (CmmMachOp (MO_S_Conv I64 I32)
+ [CmmMachOp (MO_U_Shr I64) [x,CmmLit (CmmInt 32 _)]]) = do
+ ChildCode64 code rlo <- iselExpr64 x
+ return $ Fixed I32 (getHiVRegFromLo rlo) code
+
+getRegister (CmmMachOp (MO_U_Conv I64 I32) [x]) = do
+ ChildCode64 code rlo <- iselExpr64 x
+ return $ Fixed I32 rlo code
+
+getRegister (CmmMachOp (MO_S_Conv I64 I32) [x]) = do
+ ChildCode64 code rlo <- iselExpr64 x
+ return $ Fixed I32 rlo code
+
+#endif
+
-- end of machine-"independent" bit; here we go on the rest...
#if alpha_TARGET_ARCH
getRegister (CmmLit (CmmFloat f F32)) = do
lbl <- getNewLabelNat
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
Amode addr addr_code <- getAmode dynRef
let code dst =
LDATA ReadOnlyData
| otherwise = do
lbl <- getNewLabelNat
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
Amode addr addr_code <- getAmode dynRef
let code dst =
LDATA ReadOnlyData
#endif
#if x86_64_TARGET_ARCH
+getRegister (CmmMachOp (MO_Add I64) [CmmReg (CmmGlobal PicBaseReg),
+ CmmLit displacement])
+ = return $ Any I64 (\dst -> unitOL $
+ LEA I64 (OpAddr (ripRel (litToImm displacement))) (OpReg dst))
+#endif
+
+#if x86_64_TARGET_ARCH
getRegister (CmmMachOp (MO_S_Neg F32) [x]) = do
x_code <- getAnyReg x
lbl <- getNewLabelNat
MO_Not rep -> trivialUCode rep (NOT rep) x
-- Nop conversions
- -- TODO: these are only nops if the arg is not a fixed register that
- -- can't be byte-addressed.
- MO_U_Conv I32 I8 -> conversionNop I32 x
- MO_S_Conv I32 I8 -> conversionNop I32 x
- MO_U_Conv I16 I8 -> conversionNop I16 x
- MO_S_Conv I16 I8 -> conversionNop I16 x
- MO_U_Conv I32 I16 -> conversionNop I32 x
- MO_S_Conv I32 I16 -> conversionNop I32 x
+ MO_U_Conv I32 I8 -> toI8Reg I32 x
+ MO_S_Conv I32 I8 -> toI8Reg I32 x
+ MO_U_Conv I16 I8 -> toI8Reg I16 x
+ MO_S_Conv I16 I8 -> toI8Reg I16 x
+ MO_U_Conv I32 I16 -> toI16Reg I32 x
+ MO_S_Conv I32 I16 -> toI16Reg I32 x
#if x86_64_TARGET_ARCH
MO_U_Conv I64 I32 -> conversionNop I64 x
MO_S_Conv I64 I32 -> conversionNop I64 x
- MO_U_Conv I64 I16 -> conversionNop I64 x
- MO_S_Conv I64 I16 -> conversionNop I64 x
- MO_U_Conv I64 I8 -> conversionNop I64 x
- MO_S_Conv I64 I8 -> conversionNop I64 x
+ MO_U_Conv I64 I16 -> toI16Reg I64 x
+ MO_S_Conv I64 I16 -> toI16Reg I64 x
+ MO_U_Conv I64 I8 -> toI8Reg I64 x
+ MO_S_Conv I64 I8 -> toI8Reg I64 x
#endif
MO_U_Conv rep1 rep2 | rep1 == rep2 -> conversionNop rep1 x
instr from (OpReg reg) (OpReg dst)
return (Any to code)
+ toI8Reg new_rep expr
+ = do codefn <- getAnyReg expr
+ return (Any new_rep codefn)
+ -- HACK: use getAnyReg to get a byte-addressable register.
+ -- If the source was a Fixed register, this will add the
+ -- mov instruction to put it into the desired destination.
+ -- We're assuming that the destination won't be a fixed
+ -- non-byte-addressable register; it won't be, because all
+ -- fixed registers are word-sized.
+
+ toI16Reg = toI8Reg -- for now
+
conversionNop new_rep expr
= do e_code <- getRegister expr
return (swizzleRegisterRep e_code new_rep)
getRegister (CmmLit (CmmFloat f frep)) = do
lbl <- getNewLabelNat
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
Amode addr addr_code <- getAmode dynRef
let code dst =
LDATA ReadOnlyData [CmmDataLabel lbl,
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#if x86_64_TARGET_ARCH
+
+getAmode (CmmMachOp (MO_Add I64) [CmmReg (CmmGlobal PicBaseReg),
+ CmmLit displacement])
+ = return $ Amode (ripRel (litToImm displacement)) nilOL
+
+#endif
+
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
-- This is all just ridiculous, since it carefully undoes
MO_U_Lt rep -> condIntCode LU x y
MO_U_Le rep -> condIntCode LEU x y
- other -> pprPanic "getCondCode(x86,sparc)" (pprMachOp mop)
+ other -> pprPanic "getCondCode(x86,x86_64,sparc)" (ppr (CmmMachOp mop [x,y]))
getCondCode other = pprPanic "getCondCode(2)(x86,sparc)" (ppr other)
#if i386_TARGET_ARCH
+genCCall (CmmPrim MO_WriteBarrier) _ _ _ = return nilOL
+ -- write barrier compiles to no code on x86/x86-64;
+ -- we keep it this long in order to prevent earlier optimisations.
+
-- we only cope with a single result for foreign calls
genCCall (CmmPrim op) [(r,_)] args vols = do
case op of
-> Maybe [GlobalReg] -> NatM InstrBlock
outOfLineFloatOp mop res args vols
= do
- targetExpr <- cmmMakeDynamicReference addImportNat True lbl
+ targetExpr <- cmmMakeDynamicReference addImportNat CallReference lbl
let target = CmmForeignCall targetExpr CCallConv
if cmmRegRep res == F64
code2 <- stmtToInstrs (CmmAssign res (CmmReg tmp))
return (code1 `appOL` code2)
where
- lbl = mkForeignLabel fn Nothing True
+ lbl = mkForeignLabel fn Nothing False
fn = case mop of
MO_F32_Sqrt -> FSLIT("sqrtf")
#if x86_64_TARGET_ARCH
+genCCall (CmmPrim MO_WriteBarrier) _ _ _ = return nilOL
+ -- write barrier compiles to no code on x86/x86-64;
+ -- we keep it this long in order to prevent earlier optimisations.
+
genCCall (CmmPrim op) [(r,_)] args vols =
outOfLineFloatOp op r args vols
let
fp_regs_used = reverse (drop (length fregs) (reverse allFPArgRegs))
int_regs_used = reverse (drop (length aregs) (reverse allArgRegs))
- arg_regs = int_regs_used ++ fp_regs_used
+ arg_regs = [eax] ++ int_regs_used ++ fp_regs_used
-- for annotating the call instruction with
sse_regs = length fp_regs_used
)
outOfLineFloatOp mop =
do
- mopExpr <- cmmMakeDynamicReference addImportNat True $
+ mopExpr <- cmmMakeDynamicReference addImportNat CallReference $
mkForeignLabel functionName Nothing True
let mopLabelOrExpr = case mopExpr of
CmmLit (CmmLabel lbl) -> Left lbl
frame just before ccalling.
-}
+
+genCCall (CmmPrim MO_WriteBarrier) _ _ _
+ = return $ unitOL LWSYNC
+
genCCall target dest_regs argsAndHints vols
= ASSERT (not $ any (`elem` [I8,I16]) argReps)
-- we rely on argument promotion in the codeGen
outOfLineFloatOp mop =
do
- mopExpr <- cmmMakeDynamicReference addImportNat True $
+ mopExpr <- cmmMakeDynamicReference addImportNat CallReference $
mkForeignLabel functionName Nothing True
let mopLabelOrExpr = case mopExpr of
CmmLit (CmmLabel lbl) -> Left lbl
= do
(reg,e_code) <- getSomeReg expr
lbl <- getNewLabelNat
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
(tableReg,t_code) <- getSomeReg $ dynRef
let
jumpTable = map jumpTableEntryRel ids
op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
(EAIndex reg wORD_SIZE) (ImmInt 0))
+#if x86_64_TARGET_ARCH && darwin_TARGET_OS
+ -- on Mac OS X/x86_64, put the jump table in the text section
+ -- to work around a limitation of the linker.
+ -- ld64 is unable to handle the relocations for
+ -- .quad L1 - L0
+ -- if L0 is not preceded by a non-anonymous label in its section.
+
+ code = e_code `appOL` t_code `appOL` toOL [
+ ADD wordRep op (OpReg tableReg),
+ JMP_TBL (OpReg tableReg) [ id | Just id <- ids ],
+ LDATA Text (CmmDataLabel lbl : jumpTable)
+ ]
+#else
code = e_code `appOL` t_code `appOL` toOL [
LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable),
ADD wordRep op (OpReg tableReg),
JMP_TBL (OpReg tableReg) [ id | Just id <- ids ]
]
+#endif
return code
| otherwise
= do
(reg,e_code) <- getSomeReg expr
tmp <- getNewRegNat I32
lbl <- getNewLabelNat
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
(tableReg,t_code) <- getSomeReg $ dynRef
let
jumpTable = map jumpTableEntryRel ids
lbl <- getNewLabelNat
itmp <- getNewRegNat I32
ftmp <- getNewRegNat F64
- dynRef <- cmmMakeDynamicReference addImportNat False lbl
+ dynRef <- cmmMakeDynamicReference addImportNat DataReference lbl
Amode addr addr_code <- getAmode dynRef
let
code' dst = code `appOL` maybe_exts `appOL` toOL [