Don't generate stub files when -fno-code is given.
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachInstrs.hs
index e48e1a9..0f718d3 100644 (file)
@@ -14,28 +14,25 @@ module MachInstrs (
 
        -- * Machine instructions
        Instr(..),
-       Cond(..),
-#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH
+       Cond(..), condUnsigned, condToSigned, condToUnsigned,
+
+#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH && !x86_64_TARGET_ARCH
        Size(..), machRepSize,
 #endif
        RI(..),
 
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
        Operand(..),
+#endif
+#if i386_TARGET_ARCH
        i386_insert_ffrees,
 #endif
 #if sparc_TARGET_ARCH
        riZero, fpRelEA, moveSp, fPair,
 #endif
-#if powerpc_TARGET_ARCH
-       condUnsigned, condToSigned,
-#endif
-       DestInfo(..), hasDestInfo, pprDests,
-
     ) where
 
 #include "HsVersions.h"
-#include "../includes/ghcconfig.h"
 
 import MachRegs
 import Cmm
@@ -43,8 +40,8 @@ import MachOp         ( MachRep(..) )
 import CLabel           ( CLabel, pprCLabel )
 import Panic           ( panic )
 import Outputable
-import Config           ( cLeadingUnderscore )
 import FastString
+import Constants       ( wORD_SIZE )
 
 import GLAEXTS
 
@@ -73,7 +70,7 @@ data Cond
   | ULE                -- For CMP only
   | ULT                -- For CMP only
 #endif
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
   = ALWAYS     -- What's really used? ToDo
   | EQQ
   | GE
@@ -89,6 +86,8 @@ data Cond
   | POS
   | CARRY
   | OFLO
+  | PARITY
+  | NOTPARITY
 #endif
 #if sparc_TARGET_ARCH
   = ALWAYS     -- What's really used? ToDo
@@ -123,6 +122,23 @@ data Cond
 #endif
     deriving Eq  -- to make an assertion work
 
+condUnsigned GU  = True
+condUnsigned LU  = True
+condUnsigned GEU = True
+condUnsigned LEU = True
+condUnsigned _   = False
+
+condToSigned GU  = GTT
+condToSigned LU  = LTT
+condToSigned GEU = GE
+condToSigned LEU = LE
+condToSigned x   = x
+
+condToUnsigned GTT = GU
+condToUnsigned LTT = LU
+condToUnsigned GE  = GEU
+condToUnsigned LE  = LEU
+condToUnsigned x   = x
 
 -- -----------------------------------------------------------------------------
 -- Sizes on this architecture
@@ -130,7 +146,7 @@ data Cond
 -- ToDo: it's not clear to me that we need separate signed-vs-unsigned sizes
 -- here.  I've removed them from the x86 version, we'll see what happens --SDM
 
-#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH
+#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH && !x86_64_TARGET_ARCH
 data Size
 #if alpha_TARGET_ARCH
     = B            -- byte
@@ -364,7 +380,7 @@ bit or 64 bit precision.
 --SDM 1/2003
 -}
 
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
 
 -- data Instr continues...
 
@@ -372,6 +388,9 @@ bit or 64 bit precision.
        | MOV         MachRep Operand Operand
        | MOVZxL      MachRep Operand Operand -- size is the size of operand 1
        | MOVSxL      MachRep Operand Operand -- size is the size of operand 1
+       -- x86_64 note: plain mov into a 32-bit register always zero-extends
+       -- into the 64-bit reg, in contrast to the 8 and 16-bit movs which
+       -- don't affect the high bits of the register.
 
 -- Load effective address (also a very useful three-operand add instruction :-)
        | LEA         MachRep Operand Operand
@@ -380,11 +399,10 @@ bit or 64 bit precision.
        | ADD         MachRep Operand Operand
        | ADC         MachRep Operand Operand
        | SUB         MachRep Operand Operand
-       | IMUL        MachRep Operand Operand   -- signed int mul
-       | MUL         MachRep Operand Operand   -- unsigned int mul
 
-        | IMUL64      Reg Reg
-       -- operand1:operand2 := (operand1[31:0] *signed operand2[31:0])
+       | MUL         MachRep Operand Operand
+       | IMUL        MachRep Operand Operand   -- signed int mul
+        | IMUL2       MachRep Operand -- %edx:%eax = operand * %eax
 
        | DIV         MachRep Operand   -- eax := eax:edx/op, edx := eax:edx%op
        | IDIV        MachRep Operand   -- ditto, but signed
@@ -404,6 +422,7 @@ bit or 64 bit precision.
         | BT          MachRep Imm Operand
        | NOP
 
+#if i386_TARGET_ARCH
 -- Float Arithmetic.
 
 -- Note that we cheat by treating G{ABS,MOV,NEG} of doubles 
@@ -443,6 +462,32 @@ bit or 64 bit precision.
        | GTAN        MachRep Reg Reg -- src, dst
        
         | GFREE         -- do ffree on all x86 regs; an ugly hack
+#endif
+
+#if x86_64_TARGET_ARCH
+-- SSE2 floating point: we use a restricted set of the available SSE2
+-- instructions for floating-point.
+
+       -- use MOV for moving (either movss or movsd (movlpd better?))
+
+       | CVTSS2SD      Reg Reg         -- F32 to F64
+       | CVTSD2SS      Reg Reg         -- F64 to F32
+       | CVTSS2SI      Operand Reg     -- F32 to I32/I64 (with rounding)
+       | CVTSD2SI      Operand Reg     -- F64 to I32/I64 (with rounding)
+       | CVTSI2SS      Operand Reg     -- I32/I64 to F32
+       | CVTSI2SD      Operand Reg     -- I32/I64 to F64
+
+       -- use ADD & SUB for arithmetic.  In both cases, operands
+       -- are  Operand Reg.
+
+       -- SSE2 floating-point division:
+       | FDIV          MachRep Operand Operand   -- divisor, dividend(dst)
+
+       -- use CMP for comparisons.  ucomiss and ucomisd instructions
+       -- compare single/double prec floating point respectively.
+
+       | SQRT          MachRep Operand Reg     -- src, dst
+#endif
 
 -- Comparison
        | TEST          MachRep Operand Operand
@@ -453,30 +498,37 @@ bit or 64 bit precision.
        | PUSH          MachRep Operand
        | POP           MachRep Operand
        -- both unused (SDM):
-       -- | PUSHA
-       -- | POPA
+       --  | PUSHA
+       --  | POPA
 
 -- Jumping around.
        | JMP         Operand
        | JXX         Cond BlockId  -- includes unconditional branches
        | JMP_TBL     Operand [BlockId]  -- table jump
-       | CALL        (Either Imm Reg)
+       | CALL        (Either Imm Reg) [Reg]
 
 -- Other things.
-       | CLTD -- sign extend %eax into %edx:%eax
+       | CLTD MachRep   -- sign extend %eax into %edx:%eax
 
-       | FETCHGOT    Reg  -- pseudo-insn for position-independent code
+       | FETCHGOT    Reg  -- pseudo-insn for ELF position-independent code
                            -- pretty-prints as
                            --       call 1f
                            -- 1:    popl %reg
                            --       addl __GLOBAL_OFFSET_TABLE__+.-1b, %reg
-                    
+       | FETCHPC     Reg  -- pseudo-insn for Darwin position-independent code
+                           -- pretty-prints as
+                           --       call 1f
+                           -- 1:    popl %reg
+
+
 data Operand
   = OpReg  Reg         -- register
   | OpImm  Imm         -- immediate value
   | OpAddr AddrMode    -- memory reference
 
+#endif /* i386 or x86_64 */
 
+#if i386_TARGET_ARCH
 i386_insert_ffrees :: [Instr] -> [Instr]
 i386_insert_ffrees insns
    | any is_G_instr insns
@@ -486,9 +538,9 @@ i386_insert_ffrees insns
 
 ffree_before_nonlocal_transfers insn
    = case insn of
-        CALL _  -> [GFREE, insn]
-        JMP _   -> [GFREE, insn]
-        other   -> [insn]
+        CALL _ _ -> [GFREE, insn]
+        JMP _    -> [GFREE, insn]
+        other    -> [insn]
 
 
 -- if you ever add a new FP insn to the fake x86 FP insn set,
@@ -496,18 +548,17 @@ ffree_before_nonlocal_transfers insn
 is_G_instr :: Instr -> Bool
 is_G_instr instr
    = case instr of
-        GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True;
-        GLDZ _ -> True; GLD1 _ -> True;
-        GFTOI _ _ -> True; GDTOI _ _ -> True;
-        GITOF _ _ -> True; GITOD _ _ -> True;
+        GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True
+        GLDZ _ -> True; GLD1 _ -> True
+        GFTOI _ _ -> True; GDTOI _ _ -> True
+        GITOF _ _ -> True; GITOD _ _ -> True
        GADD _ _ _ _ -> True; GDIV _ _ _ _ -> True
        GSUB _ _ _ _ -> True; GMUL _ _ _ _ -> True
        GCMP _ _ _ -> True; GABS _ _ _ -> True
        GNEG _ _ _ -> True; GSQRT _ _ _ -> True
-        GSIN _ _ _ -> True; GCOS _ _ _ -> True; GTAN _ _ _ -> True;
+        GSIN _ _ _ -> True; GCOS _ _ _ -> True; GTAN _ _ _ -> True
         GFREE -> panic "is_G_instr: GFREE (!)"
         other -> False
-
 #endif /* i386_TARGET_ARCH */
 
 
@@ -561,12 +612,9 @@ is_G_instr instr
              | BI            Cond Bool Imm -- cond, annul?, target
              | BF            Cond Bool Imm -- cond, annul?, target
 
-             | JMP           DestInfo AddrMode      -- target
+             | JMP           AddrMode     -- target
              | CALL          (Either Imm Reg) Int Bool -- target, args, terminal
 
-data RI = RIReg Reg
-       | RIImm Imm
-
 riZero :: RI -> Bool
 
 riZero (RIImm (ImmInt 0))          = True
@@ -579,12 +627,12 @@ riZero _                      = False
 -- alas -- can't have fpRelEA here because of module dependencies.
 fpRelEA :: Int -> Reg -> Instr
 fpRelEA n dst
-   = ADD False False fp (RIImm (ImmInt (n * BYTES_PER_WORD))) dst
+   = ADD False False fp (RIImm (ImmInt (n * wORD_SIZE))) dst
 
 -- Code to shift the stack pointer by n words.
 moveSp :: Int -> Instr
 moveSp n
-   = ADD False False sp (RIImm (ImmInt (n * BYTES_PER_WORD))) sp
+   = ADD False False sp (RIImm (ImmInt (n * wORD_SIZE))) sp
 
 -- Produce the second-half-of-a-double register given the first half.
 fPair :: Reg -> Reg
@@ -671,33 +719,4 @@ fPair other = pprPanic "fPair(sparc NCG)" (ppr other)
              | FETCHPC Reg            -- pseudo-instruction:
                                       -- bcl to next insn, mflr reg
              
-condUnsigned GU = True
-condUnsigned LU = True
-condUnsigned GEU = True
-condUnsigned LEU = True
-condUnsigned _ = False
-
-condToSigned GU = GTT
-condToSigned LU = LTT
-condToSigned GEU = GE
-condToSigned LEU = LE
-condToSigned x = x
 #endif /* powerpc_TARGET_ARCH */
-
-
--- -----------------------------------------------------------------------------
--- DestInfo
-
--- ToDo: might not be needed anymore --SDM
-
--- used by insnFuture in RegAllocInfo.lhs
-data DestInfo
-   = NoDestInfo             -- no supplied dests; infer from context
-   | DestInfo [CLabel]      -- precisely these dests and no others
-
-hasDestInfo NoDestInfo   = False
-hasDestInfo (DestInfo _) = True
-
-pprDests :: DestInfo -> SDoc
-pprDests NoDestInfo      = text "NoDestInfo"
-pprDests (DestInfo dsts) = brackets (hsep (map pprCLabel dsts))