More fixes to the SPARC native code generator
[ghc-hetmet.git] / compiler / nativeGen / MachCodeGen.hs
index f780636..6d16da8 100644 (file)
@@ -29,7 +29,9 @@ import MachInstrs
 import MachRegs
 import NCGMonad
 import PositionIndependentCode
-import RegAllocInfo ( mkBranchInstr )
+import RegAllocInfo    ( mkBranchInstr, mkRegRegMoveInstr )
+import MachRegs
+import PprMach
 
 -- Our intermediate code:
 import BlockId
@@ -57,6 +59,7 @@ import Data.Bits
 import Data.Word
 import Data.Int
 
+
 -- -----------------------------------------------------------------------------
 -- Top-level of the instruction selector
 
@@ -306,10 +309,10 @@ assignMem_I64Code addrTree valueTree = do
          mov_lo = ST II32 rlo (AddrRegImm src (ImmInt 4))
      return (vcode `appOL` code `snocOL` mov_hi `snocOL` mov_lo)
 
-assignReg_I64Code (CmmLocal (LocalReg u_dst pk _)) valueTree = do
+assignReg_I64Code (CmmLocal (LocalReg u_dst pk)) valueTree = do
      ChildCode64 vcode r_src_lo <- iselExpr64 valueTree    
      let 
-         r_dst_lo = mkVReg u_dst pk
+         r_dst_lo = mkVReg u_dst (cmmTypeSize pk)
          r_dst_hi = getHiVRegFromLo r_dst_lo
          r_src_hi = getHiVRegFromLo r_src_lo
          mov_lo = mkMOV r_src_lo r_dst_lo
@@ -336,10 +339,10 @@ iselExpr64 (CmmLoad addrTree ty) | isWord64 ty = do
                          rlo
           )
 
-iselExpr64 (CmmReg (CmmLocal (LocalReg uq ty))) isWord64 ty = do
-     r_dst_lo <-  getNewRegNat b32
+iselExpr64 (CmmReg (CmmLocal (LocalReg uq ty))) | isWord64 ty = do
+     r_dst_lo <-  getNewRegNat II32
      let r_dst_hi = getHiVRegFromLo r_dst_lo
-         r_src_lo = mkVReg uq b32
+         r_src_lo = mkVReg uq II32
          r_src_hi = getHiVRegFromLo r_src_lo
          mov_lo = mkMOV r_src_lo r_dst_lo
          mov_hi = mkMOV r_src_hi r_dst_hi
@@ -1393,24 +1396,38 @@ reg2reg size src dst
 
 #if sparc_TARGET_ARCH
 
+-- getRegister :: CmmExpr -> NatM Register
+
+-- Load a literal float into a float register.
+--     The actual literal is stored in a new data area, and we load it 
+--     at runtime.
 getRegister (CmmLit (CmmFloat f W32)) = do
+
+    -- a label for the new data area
     lbl <- getNewLabelNat
+    tmp <- getNewRegNat II32
+
     let code dst = toOL [
+            -- the data area         
            LDATA ReadOnlyData
                        [CmmDataLabel lbl,
                         CmmStaticLit (CmmFloat f W32)],
-           SETHI (HI (ImmCLbl lbl)) dst,
-           LD FF32 (AddrRegImm dst (LO (ImmCLbl lbl))) dst] 
+
+            -- load the literal
+           SETHI (HI (ImmCLbl lbl)) tmp,
+           LD II32 (AddrRegImm tmp (LO (ImmCLbl lbl))) dst] 
+
     return (Any FF32 code)
 
 getRegister (CmmLit (CmmFloat d W64)) = do
     lbl <- getNewLabelNat
+    tmp <- getNewRegNat II32
     let code dst = toOL [
            LDATA ReadOnlyData
                        [CmmDataLabel lbl,
                         CmmStaticLit (CmmFloat d W64)],
-           SETHI (HI (ImmCLbl lbl)) dst,
-           LD FF64 (AddrRegImm dst (LO (ImmCLbl lbl))) dst] 
+           SETHI (HI (ImmCLbl lbl)) tmp,
+           LD II64 (AddrRegImm tmp (LO (ImmCLbl lbl))) dst] 
     return (Any FF64 code)
 
 getRegister (CmmMachOp mop [x]) -- unary MachOps
@@ -1429,10 +1446,10 @@ getRegister (CmmMachOp mop [x]) -- unary MachOps
 
       -- Conversions which are a nop on sparc
       MO_UU_Conv from to
-       | from == to    -> conversionNop to  x
-      MO_UU_Conv W32 W8 -> trivialCode I8 (AND False) x (CmmLit (CmmInt 255 I8))
-      MO_UU_Conv W32 to -> conversionNop to x
-      MO_SS_Conv W32 to -> conversionNop to x
+       | from == to    -> conversionNop (intSize to)  x
+      MO_UU_Conv W32 W8 -> trivialCode W8 (AND False) x (CmmLit (CmmInt 255 W8))
+      MO_UU_Conv W32 to -> conversionNop (intSize to) x
+      MO_SS_Conv W32 to -> conversionNop (intSize to) x
 
       -- widenings
       MO_UU_Conv W8 W32  -> integerExtend False W8 W32  x
@@ -1526,8 +1543,8 @@ getRegister (CmmMachOp mop [x, y]) -- dyadic PrimOps
     imulMayOflo rep a b = do
          (a_reg, a_code) <- getSomeReg a
         (b_reg, b_code) <- getSomeReg b
-        res_lo <- getNewRegNat b32
-        res_hi <- getNewRegNat b32
+        res_lo <- getNewRegNat II32
+        res_hi <- getNewRegNat II32
         let
            shift_amt  = case rep of
                          W32 -> 31
@@ -1545,8 +1562,8 @@ getRegister (CmmMachOp mop [x, y]) -- dyadic PrimOps
 getRegister (CmmLoad mem pk) = do
     Amode src code <- getAmode mem
     let
-       code__2 dst = code `snocOL` LD pk src dst
-    return (Any pk code__2)
+       code__2 dst     = code `snocOL` LD (cmmTypeSize pk) src dst
+    return (Any (cmmTypeSize pk) code__2)
 
 getRegister (CmmLit (CmmInt i _))
   | fits13Bits i
@@ -1916,7 +1933,7 @@ getAmode (CmmMachOp (MO_Add rep) [x, y])
 -- XXX Is this same as "leaf" in Stix?
 getAmode (CmmLit lit)
   = do
-      tmp <- getNewRegNat b32
+      tmp <- getNewRegNat II32
       let
        code = unitOL (SETHI (HI imm__2) tmp)
       return (Amode (AddrRegImm tmp (LO imm__2)) code)
@@ -2306,9 +2323,9 @@ condFltCode cond x y = do
        pk2   = cmmExprType y
 
        code__2 =
-               if pk1 == pk2 then
+               if pk1 `cmmEqType` pk2 then
                    code1 `appOL` code2 `snocOL`
-                   FCMP True pk1 src1 src2
+                   FCMP True (cmmTypeSize pk1) src1 src2
                else if typeWidth pk1 == W32 then
                    code1 `snocOL` promote src1 `appOL` code2 `snocOL`
                    FCMP True FF64 tmp src2
@@ -2475,7 +2492,7 @@ assignReg_IntCode pk reg src = do
     r <- getRegister src
     return $ case r of
        Any _ code         -> code dst
-       Fixed _ freg fcode -> fcode `snocOL` OR False g0 (RIReg dst) freg
+       Fixed _ freg fcode -> fcode `snocOL` OR False g0 (RIReg freg) dst
     where
       dst = getRegisterReg reg
 
@@ -2570,21 +2587,20 @@ assignMem_FltCode pk addr src = do
     let
        pk__2   = cmmExprType src
        code__2 = code1 `appOL` code2 `appOL`
-           if   pk == pk__2 
+           if   sizeToWidth pk == typeWidth pk__2 
             then unitOL (ST pk src__2 dst__2)
-           else toOL [FxTOy pk__2 pk src__2 tmp1, ST pk tmp1 dst__2]
+           else toOL   [ FxTOy (cmmTypeSize pk__2) pk src__2 tmp1
+                       , ST    pk tmp1 dst__2]
     return code__2
 
 -- Floating point assignment to a register/temporary
--- ToDo: Verify correctness
-assignReg_FltCode pk reg src = do
-    r <- getRegister src
-    v1 <- getNewRegNat pk
-    return $ case r of
-        Any _ code         -> code dst
-       Fixed _ freg fcode -> fcode `snocOL` FMOV pk freg v1
-    where
-      dst = getRegisterReg reg
+assignReg_FltCode pk dstCmmReg srcCmmExpr = do
+    srcRegister <- getRegister srcCmmExpr
+    let dstReg = getRegisterReg dstCmmReg
+
+    return $ case srcRegister of
+        Any _ code                 -> code dstReg
+       Fixed _ srcFixedReg srcCode -> srcCode `snocOL` FMOV pk srcFixedReg dstReg
 
 #endif /* sparc_TARGET_ARCH */
 
@@ -2906,14 +2922,14 @@ genCondJump id bool = do
 
 #if sparc_TARGET_ARCH
 
-genCondJump (BlockId id) bool = do
+genCondJump bid bool = do
   CondCode is_float cond code <- getCondCode bool
   return (
        code `appOL` 
        toOL (
          if   is_float
-         then [NOP, BF cond False (ImmCLbl (mkAsmTempLabel id)), NOP]
-         else [BI cond False (ImmCLbl (mkAsmTempLabel id)), NOP]
+         then [NOP, BF cond False bid, NOP]
+         else [BI cond False bid, NOP]
        )
     )
 
@@ -3466,14 +3482,40 @@ genCCall target dest_regs argsAndHints = do
              in  if   nn <= 0
                  then (nilOL, nilOL)
                  else (unitOL (moveSp (-1*nn)), unitOL (moveSp (1*nn)))
+
         transfer_code
            = toOL (move_final vregs allArgRegs eXTRA_STK_ARGS_HERE)
+
+       -- assign the results, if necessary
+       assign_code []  = nilOL
+       
+       assign_code [CmmHinted dest _hint]      
+        = let  rep     = localRegType dest
+               width   = typeWidth rep
+               r_dest  = getRegisterReg (CmmLocal dest)
+
+               result
+                       | isFloatType rep 
+                       , W32   <- width
+                       = unitOL $ FMOV FF32 (RealReg $ fReg 0) r_dest
+                       
+                       | isFloatType rep
+                       , W64   <- width
+                       = unitOL $ FMOV FF64 (RealReg $ fReg 0) r_dest
+                       
+                       | not $ isFloatType rep
+                       , W32   <- width
+                       = unitOL $ mkRegRegMoveInstr (RealReg $ oReg 0) r_dest
+                       
+          in   result
+                               
     return (argcode       `appOL`
             move_sp_down  `appOL`
             transfer_code `appOL`
             callinsns     `appOL`
             unitOL NOP    `appOL`
-            move_sp_up)
+            move_sp_up   `appOL`
+           assign_code dest_regs)
   where
      -- move args from the integer vregs into which they have been 
      -- marshalled, into %o0 .. %o5, and the rest onto the stack.
@@ -3503,10 +3545,11 @@ genCCall target dest_regs argsAndHints = do
         | otherwise
         = do
          (src, code) <- getSomeReg arg
-          tmp <- getNewRegNat (cmmExprType arg)
+          tmp <- getNewRegNat (cmmTypeSize $ cmmExprType arg)
           let
-              pk   = cmmExprType arg
-          case pk of
+              pk       = cmmExprType arg
+              Just f0_high = fPair f0
+          case cmmTypeSize pk of
              FF64 -> do
                       v1 <- getNewRegNat II32
                       v2 <- getNewRegNat II32
@@ -3515,7 +3558,7 @@ genCCall target dest_regs argsAndHints = do
                         FMOV FF64 src f0                `snocOL`
                         ST   FF32  f0 (spRel 16)         `snocOL`
                         LD   II32  (spRel 16) v1         `snocOL`
-                        ST   FF32  (fPair f0) (spRel 16) `snocOL`
+                        ST   FF32  f0_high (spRel 16) `snocOL`
                         LD   II32  (spRel 16) v2
                         ,
                         [v1,v2]
@@ -3967,6 +4010,13 @@ genSwitch expr ids
                             BCTR [ id | Just id <- ids ]
                     ]
         return code
+#elif sparc_TARGET_ARCH
+genSwitch expr ids
+  | opt_PIC
+  = error "MachCodeGen: sparc genSwitch PIC not finished\n"
+  
+  | otherwise
+  = error "MachCodeGen: sparc genSwitch non-PIC not finished\n"
 #else
 #error "ToDo: genSwitch"
 #endif
@@ -4127,32 +4177,32 @@ condIntReg NE x y = do
     return (Any II32 code__2)
 
 condIntReg cond x y = do
-    BlockId lbl1 <- getBlockIdNat
-    BlockId lbl2 <- getBlockIdNat
+    bid1@(BlockId lbl1) <- getBlockIdNat
+    bid2@(BlockId lbl2) <- getBlockIdNat
     CondCode _ cond cond_code <- condIntCode cond x y
     let
        code__2 dst = cond_code `appOL` toOL [
-           BI cond False (ImmCLbl (mkAsmTempLabel lbl1)), NOP,
+           BI cond False bid1, NOP,
            OR False g0 (RIImm (ImmInt 0)) dst,
-           BI ALWAYS False (ImmCLbl (mkAsmTempLabel lbl2)), NOP,
-           NEWBLOCK (BlockId lbl1),
+           BI ALWAYS False bid2, NOP,
+           NEWBLOCK bid1,
            OR False g0 (RIImm (ImmInt 1)) dst,
-           NEWBLOCK (BlockId lbl2)]
+           NEWBLOCK bid2]
     return (Any II32 code__2)
 
 condFltReg cond x y = do
-    BlockId lbl1 <- getBlockIdNat
-    BlockId lbl2 <- getBlockIdNat
+    bid1@(BlockId lbl1) <- getBlockIdNat
+    bid2@(BlockId lbl2) <- getBlockIdNat
     CondCode _ cond cond_code <- condFltCode cond x y
     let
        code__2 dst = cond_code `appOL` toOL [ 
            NOP,
-           BF cond False (ImmCLbl (mkAsmTempLabel lbl1)), NOP,
+           BF cond False bid1, NOP,
            OR False g0 (RIImm (ImmInt 0)) dst,
-           BI ALWAYS False (ImmCLbl (mkAsmTempLabel lbl2)), NOP,
-           NEWBLOCK (BlockId lbl1),
+           BI ALWAYS False bid2, NOP,
+           NEWBLOCK bid1,
            OR False g0 (RIImm (ImmInt 1)) dst,
-           NEWBLOCK (BlockId lbl2)]
+           NEWBLOCK bid2]
     return (Any II32 code__2)
 
 #endif /* sparc_TARGET_ARCH */
@@ -4500,8 +4550,8 @@ trivialCode pk instr x y = do
 trivialFCode pk instr x y = do
     (src1, code1) <- getSomeReg x
     (src2, code2) <- getSomeReg y
-    tmp1 <- getNewRegNat (cmmExprType x)
-    tmp2 <- getNewRegNat (cmmExprType y)
+    tmp1 <- getNewRegNat (cmmTypeSize $ cmmExprType x)
+    tmp2 <- getNewRegNat (cmmTypeSize $ cmmExprType y)
     tmp <- getNewRegNat FF64
     let
        promote x = FxTOy FF32 FF64 x tmp
@@ -4510,7 +4560,7 @@ trivialFCode pk instr x y = do
        pk2   = cmmExprType y
 
        code__2 dst =
-               if pk1 == pk2 then
+               if pk1 `cmmEqType` pk2 then
                    code1 `appOL` code2 `snocOL`
                    instr (floatSize pk) src1 src2 dst
                else if typeWidth pk1 == W32 then
@@ -4519,7 +4569,8 @@ trivialFCode pk instr x y = do
                else
                    code1 `appOL` code2 `snocOL` promote src2 `snocOL`
                    instr FF64 src1 tmp dst
-    return (Any (if pk1 == pk2 then pk1 else cmmFloat W64) code__2)
+    return (Any (cmmTypeSize $ if pk1 `cmmEqType` pk2 then pk1 else cmmFloat W64) 
+               code__2)
 
 ------------
 trivialUCode size instr x = do
@@ -4733,17 +4784,20 @@ coerceFP2FP to x = do
 
 #if sparc_TARGET_ARCH
 
-coerceInt2FP pk1 pk2 x = do
+coerceInt2FP width1 width2 x = do
     (src, code) <- getSomeReg x
     let
        code__2 dst = code `appOL` toOL [
-           ST pk1 src (spRel (-2)),
-           LD pk1 (spRel (-2)) dst,
-           FxTOy pk1 pk2 dst dst]
-    return (Any pk2 code__2)
+           ST (intSize width1) src (spRel (-2)),
+           LD (intSize width1) (spRel (-2)) dst,
+           FxTOy (intSize width1) (floatSize width2) dst dst]
+    return (Any (floatSize $ width2) code__2)
 
 ------------
-coerceFP2Int pk fprep x = do
+coerceFP2Int width1 width2 x = do
+    let pk     = intSize width1
+        fprep  = floatSize width2
+
     (src, code) <- getSomeReg x
     reg <- getNewRegNat fprep
     tmp <- getNewRegNat pk