SPARC NCG: Fix format problem when converting float to int
[ghc-hetmet.git] / compiler / nativeGen / MachCodeGen.hs
index e90b40c..b685c9d 100644 (file)
@@ -3667,6 +3667,12 @@ genCCall target dest_regs argsAndHints = do
                        | not $ isFloatType rep
                        , W32   <- width
                        = unitOL $ mkRegRegMoveInstr (RealReg $ oReg 0) r_dest
+
+                       | not $ isFloatType rep
+                       , W64           <- width
+                       , r_dest_hi     <- getHiVRegFromLo r_dest
+                       = toOL  [ mkRegRegMoveInstr (RealReg $ oReg 0) r_dest_hi
+                               , mkRegRegMoveInstr (RealReg $ oReg 1) r_dest]
                        
           in   result
                                
@@ -4173,15 +4179,43 @@ genSwitch expr ids
         return code
 #elif sparc_TARGET_ARCH
 genSwitch expr ids
-  | opt_PIC
-  = error "MachCodeGen: sparc genSwitch PIC not finished\n"
+       | opt_PIC
+       = error "MachCodeGen: sparc genSwitch PIC not finished\n"
   
-  | otherwise
-  = error "MachCodeGen: sparc genSwitch non-PIC not finished\n"
+       | otherwise
+       = do    (e_reg, e_code) <- getSomeReg expr
+
+               base_reg        <- getNewRegNat II32
+               offset_reg      <- getNewRegNat II32
+               dst             <- getNewRegNat II32
+
+               label           <- getNewLabelNat
+               let jumpTable   = map jumpTableEntry ids
+
+               return $ e_code `appOL`
+                toOL   
+                       -- the jump table
+                       [ LDATA ReadOnlyData (CmmDataLabel label : jumpTable)
+
+                       -- load base of jump table
+                       , SETHI (HI (ImmCLbl label)) base_reg
+                       , OR    False base_reg (RIImm $ LO $ ImmCLbl label) base_reg
+                       
+                       -- the addrs in the table are 32 bits wide..
+                       , SLL   e_reg (RIImm $ ImmInt 2) offset_reg
+
+                       -- load and jump to the destination
+                       , LD    II32 (AddrRegReg base_reg offset_reg) dst
+                       , JMP   (AddrRegImm dst (ImmInt 0)) 
+                       , NOP ]
+
 #else
 #error "ToDo: genSwitch"
 #endif
 
+
+-- | Convert a BlockId to some CmmStatic data
+jumpTableEntry :: Maybe BlockId -> CmmStatic
 jumpTableEntry Nothing = CmmStaticLit (CmmInt 0 wordWidth)
 jumpTableEntry (Just (BlockId id)) = CmmStaticLit (CmmLabel blockLabel)
     where blockLabel = mkAsmTempLabel id
@@ -4954,21 +4988,33 @@ coerceInt2FP width1 width2 x = do
            FxTOy (intSize width1) (floatSize width2) dst dst]
     return (Any (floatSize $ width2) code__2)
 
-------------
-coerceFP2Int width1 width2 x = do
-    let pk     = intSize width1
-        fprep  = floatSize width2
 
-    (src, code) <- getSomeReg x
-    reg <- getNewRegNat fprep
-    tmp <- getNewRegNat pk
-    let
-       code__2 dst = ASSERT(fprep == FF64 || fprep == FF32)
-           code `appOL` toOL [
-           FxTOy fprep pk src tmp,
-           ST pk tmp (spRel (-2)),
-           LD pk (spRel (-2)) dst]
-    return (Any pk code__2)
+-- | Coerce a floating point value to integer
+--
+--   NOTE: On sparc v9 there are no instructions to move a value from an
+--        FP register directly to an int register, so we have to use a load/store.
+--
+coerceFP2Int width1 width2 x 
+ = do  let fsize1      = floatSize width1
+           fsize2      = floatSize width2
+       
+            isize2     = intSize   width2
+
+       (fsrc, code)    <- getSomeReg x
+       fdst            <- getNewRegNat fsize2
+    
+       let code2 dst   
+               =       code
+               `appOL` toOL
+                       -- convert float to int format, leaving it in a float reg.
+                       [ FxTOy fsize1 isize2 fsrc fdst
+
+                       -- store the int into mem, then load it back to move
+                       --      it into an actual int reg.
+                       , ST    fsize2 fdst (spRel (-2))
+                       , LD    isize2 (spRel (-2)) dst]
+
+       return (Any isize2 code2)
 
 ------------
 coerceDbl2Flt x = do