floating-point fix for x86_64
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachCodeGen.hs
index e552660..32dad13 100644 (file)
@@ -735,12 +735,14 @@ getRegister leaf
 
 getRegister (CmmLit (CmmFloat f F32)) = do
     lbl <- getNewLabelNat
-    let code dst = toOL [
+    dynRef <- cmmMakeDynamicReference addImportNat False lbl
+    Amode addr addr_code <- getAmode dynRef
+    let code dst =
            LDATA ReadOnlyData
                        [CmmDataLabel lbl,
-                        CmmStaticLit (CmmFloat f F32)],
-           GLD F32 (ImmAddr (ImmCLbl lbl) 0) dst
-           ]
+                        CmmStaticLit (CmmFloat f F32)]
+           `consOL` (addr_code `snocOL`
+           GLD F32 addr dst)
     -- in
     return (Any F32 code)
 
@@ -756,12 +758,14 @@ getRegister (CmmLit (CmmFloat d F64))
 
   | otherwise = do
     lbl <- getNewLabelNat
-    let code dst = toOL [
+    dynRef <- cmmMakeDynamicReference addImportNat False lbl
+    Amode addr addr_code <- getAmode dynRef
+    let code dst =
            LDATA ReadOnlyData
                        [CmmDataLabel lbl,
-                        CmmStaticLit (CmmFloat d F64)],
-           GLD F64 (ImmAddr (ImmCLbl lbl) 0) dst
-           ]
+                        CmmStaticLit (CmmFloat d F64)]
+           `consOL` (addr_code `snocOL`
+           GLD F64 addr dst)
     -- in
     return (Any F64 code)
 
@@ -1109,12 +1113,14 @@ getRegister e@(CmmMachOp mop [x, y]) -- dyadic MachOps
 
     --------------------
     add_code :: MachRep -> CmmExpr -> CmmExpr -> NatM Register
-    add_code rep x (CmmLit (CmmInt y _)) = add_int rep x y
+    add_code rep x (CmmLit (CmmInt y _))
+       | not (is64BitInteger y) = add_int rep x y
     add_code rep x y = trivialCode rep (ADD rep) (Just (ADD rep)) x y
 
     --------------------
     sub_code :: MachRep -> CmmExpr -> CmmExpr -> NatM Register
-    sub_code rep x (CmmLit (CmmInt y _)) = add_int rep x (-y)
+    sub_code rep x (CmmLit (CmmInt y _))
+       | not (is64BitInteger (-y)) = add_int rep x (-y)
     sub_code rep x y = trivialCode rep (SUB rep) Nothing x y
 
     -- our three-operand add instruction:
@@ -1968,13 +1974,16 @@ getRegOrMem e = do
     return (OpReg reg, code)
 
 #if x86_64_TARGET_ARCH
-is64BitLit (CmmInt i I64) = i > 0x7fffffff || i < -0x80000000
+is64BitLit (CmmInt i I64) = is64BitInteger i
    -- assume that labels are in the range 0-2^31-1: this assumes the
    -- small memory model (see gcc docs, -mcmodel=small).
 #endif
 is64BitLit x = False
 #endif
 
+is64BitInteger :: Integer -> Bool
+is64BitInteger i = i > 0x7fffffff || i < -0x80000000
+
 -- -----------------------------------------------------------------------------
 --  The 'CondCode' type:  Condition codes passed up the tree.
 
@@ -3057,40 +3066,49 @@ genCCall target dest_regs args vols = do
 outOfLineFloatOp :: CallishMachOp -> CmmReg -> [(CmmExpr,MachHint)]
   -> Maybe [GlobalReg] -> NatM InstrBlock
 outOfLineFloatOp mop res args vols
-  | cmmRegRep res == F64
-  = stmtToInstrs (CmmCall target [(res,FloatHint)] args vols)
-
-  | otherwise
-  = do uq <- getUniqueNat
-       let 
-        tmp = CmmLocal (LocalReg uq F64)
-       -- in
-       code1 <- stmtToInstrs (CmmCall target [(tmp,FloatHint)] (map promote args) vols)
-       code2 <- stmtToInstrs (CmmAssign res (demote (CmmReg tmp)))
-       return (code1 `appOL` code2)
+  = do
+      targetExpr <- cmmMakeDynamicReference addImportNat True lbl
+      let target = CmmForeignCall targetExpr CCallConv
+        
+      if cmmRegRep res == F64
+        then
+          stmtToInstrs (CmmCall target [(res,FloatHint)] args vols)  
+        else do
+          uq <- getUniqueNat
+          let 
+            tmp = CmmLocal (LocalReg uq F64)
+          -- in
+          code1 <- stmtToInstrs (CmmCall target [(tmp,FloatHint)]
+                                         (map promote args) vols)
+          code2 <- stmtToInstrs (CmmAssign res (demote (CmmReg tmp)))
+          return (code1 `appOL` code2)
   where
+#if i386_TARGET_ARCH
         promote (x,hint) = (CmmMachOp (MO_S_Conv F32 F64) [x], hint)
         demote  x = CmmMachOp (MO_S_Conv F64 F32) [x]
+#else
+        promote (x,hint) = (x,hint)
+        demote  x = x
+#endif
 
-       target = CmmForeignCall (CmmLit lbl) CCallConv
-       lbl = CmmLabel (mkForeignLabel fn Nothing False)
+       lbl = mkForeignLabel fn Nothing True
 
        fn = case mop of
-             MO_F32_Sqrt  -> FSLIT("sqrt")
-             MO_F32_Sin   -> FSLIT("sin")
-             MO_F32_Cos   -> FSLIT("cos")
-             MO_F32_Tan   -> FSLIT("tan")
-             MO_F32_Exp   -> FSLIT("exp")
-             MO_F32_Log   -> FSLIT("log")
-
-             MO_F32_Asin  -> FSLIT("asin")
-             MO_F32_Acos  -> FSLIT("acos")
-             MO_F32_Atan  -> FSLIT("atan")
-
-             MO_F32_Sinh  -> FSLIT("sinh")
-             MO_F32_Cosh  -> FSLIT("cosh")
-             MO_F32_Tanh  -> FSLIT("tanh")
-             MO_F32_Pwr   -> FSLIT("pow")
+             MO_F32_Sqrt  -> FSLIT("sqrtf")
+             MO_F32_Sin   -> FSLIT("sinf")
+             MO_F32_Cos   -> FSLIT("cosf")
+             MO_F32_Tan   -> FSLIT("tanf")
+             MO_F32_Exp   -> FSLIT("expf")
+             MO_F32_Log   -> FSLIT("logf")
+
+             MO_F32_Asin  -> FSLIT("asinf")
+             MO_F32_Acos  -> FSLIT("acosf")
+             MO_F32_Atan  -> FSLIT("atanf")
+
+             MO_F32_Sinh  -> FSLIT("sinhf")
+             MO_F32_Cosh  -> FSLIT("coshf")
+             MO_F32_Tanh  -> FSLIT("tanhf")
+             MO_F32_Pwr   -> FSLIT("powf")
 
              MO_F64_Sqrt  -> FSLIT("sqrt")
              MO_F64_Sin   -> FSLIT("sin")
@@ -3716,18 +3734,44 @@ genCCall target dest_regs argsAndHints vols
 genSwitch :: CmmExpr -> [Maybe BlockId] -> NatM InstrBlock
 
 #if i386_TARGET_ARCH || x86_64_TARGET_ARCH
-genSwitch expr ids = do
-  (reg,e_code) <- getSomeReg expr
-  lbl <- getNewLabelNat
-  let
-       jumpTable = map jumpTableEntry ids
-       op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg wORD_SIZE) (ImmCLbl lbl))
-       code = e_code `appOL` toOL [
-               LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable),
-               JMP_TBL op [ id | Just id <- ids ]
-            ]
-  -- in
-  return code
+genSwitch expr ids
+  | opt_PIC
+  = do
+        (reg,e_code) <- getSomeReg expr
+        lbl <- getNewLabelNat
+        dynRef <- cmmMakeDynamicReference addImportNat False lbl
+        (tableReg,t_code) <- getSomeReg $ dynRef
+        let
+            jumpTable = map jumpTableEntryRel ids
+            
+            jumpTableEntryRel Nothing
+                = CmmStaticLit (CmmInt 0 wordRep)
+            jumpTableEntryRel (Just (BlockId id))
+                = CmmStaticLit (CmmLabelDiffOff blockLabel lbl 0)
+                where blockLabel = mkAsmTempLabel id
+
+            op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
+                                       (EAIndex reg wORD_SIZE) (ImmInt 0))
+
+            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 ]
+                    ]
+        return code
+  | otherwise
+  = do
+        (reg,e_code) <- getSomeReg expr
+        lbl <- getNewLabelNat
+        let
+            jumpTable = map jumpTableEntry ids
+            op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg wORD_SIZE) (ImmCLbl lbl))
+            code = e_code `appOL` toOL [
+                    LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable),
+                    JMP_TBL op [ id | Just id <- ids ]
+                 ]
+        -- in
+        return code
 #elif powerpc_TARGET_ARCH
 genSwitch expr ids 
   | opt_PIC