[project @ 2000-02-28 12:02:31 by sewardj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachMisc.lhs
index f9947a4..ddbc1fd 100644 (file)
@@ -24,8 +24,9 @@ module MachMisc (
 
        Instr(..),  IF_ARCH_i386(Operand(..) COMMA,)
        Cond(..),
-       Size(..)
-       
+       Size(..),
+        IF_ARCH_i386(i386_insert_ffrees COMMA,)        
+
 #if alpha_TARGET_ARCH
        , RI(..)
 #endif
@@ -41,7 +42,7 @@ module MachMisc (
 
 import AbsCSyn         ( MagicId(..) ) 
 import AbsCUtils       ( magicIdPrimRep )
-import CLabel           ( CLabel )
+import CLabel           ( CLabel, isAsmTemp )
 import Const           ( mkMachInt, Literal(..) )
 import MachRegs                ( stgReg, callerSaves, RegLoc(..),
                          Imm(..), Reg(..), 
@@ -76,7 +77,7 @@ fmtAsmLbl s
      -}
      '$' : s
      ,{-otherwise-}
-     s
+     '.':'L':s
      )
 
 ---------------------------
@@ -300,6 +301,7 @@ data Size
     | L
     | F            -- IEEE single-precision floating pt
     | DF    -- IEEE single-precision floating pt
+    | F80   -- Intel 80-bit internal FP format; only used for spilling
 #endif
 #if sparc_TARGET_ARCH
     = B     -- byte (signed)
@@ -319,7 +321,7 @@ primRepToSize CodePtrRep    = IF_ARCH_alpha( Q,      IF_ARCH_i386( L, IF_ARCH_sparc(
 primRepToSize DataPtrRep    = IF_ARCH_alpha( Q,         IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
 primRepToSize RetRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
 primRepToSize CostCentreRep = IF_ARCH_alpha( Q,         IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
-primRepToSize CharRep      = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
+primRepToSize CharRep      = IF_ARCH_alpha( BU, IF_ARCH_i386( B, IF_ARCH_sparc( BU,)))
 primRepToSize IntRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
 primRepToSize WordRep      = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
 primRepToSize AddrRep      = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
@@ -350,6 +352,8 @@ data Instr
            String              -- the literal string
   | DATA    Size
            [Imm]
+  | DELTA   Int                 -- specify current stack offset for
+                                -- benefit of subsequent passes
 \end{code}
 
 \begin{code}
@@ -463,6 +467,16 @@ FP stack, the operation done, and the result copied back into the
 relevant register.  There are only six %fake registers because 2 are
 needed for the translation, and x86 has 8 in total.
 
+The translation is inefficient but is simple and it works.  A cleverer
+translation would handle a sequence of insns, simulating the FP stack
+contents, would not impose a fixed mapping from %fake to %st regs, and
+hopefully could avoid most of the redundant reg-reg moves of the
+current translation.
+
+We might as well make use of whatever unique FP facilities Intel have
+chosen to bless us with (let's not be churlish, after all).
+Hence GLDZ and GLD1.  Bwahahahahahahaha!
+
 \begin{code}
 #if i386_TARGET_ARCH
 
@@ -471,8 +485,8 @@ needed for the translation, and x86 has 8 in total.
 -- Moves.
 
              | MOV           Size Operand Operand
-             | MOVZX         Size Operand Operand -- size is the size of operand 2
-             | MOVSX         Size Operand Operand -- size is the size of operand 2
+             | MOVZxL        Size Operand Operand -- size is the size of operand 1
+             | MOVSxL        Size Operand Operand -- size is the size of operand 1
 
 -- Load effective address (also a very useful three-operand add instruction :-)
 
@@ -496,22 +510,27 @@ needed for the translation, and x86 has 8 in total.
              | XOR           Size Operand Operand
              | NOT           Size Operand
              | NEGI          Size Operand -- NEG instruction (name clash with Cond)
-             | SHL           Size Operand Operand -- 1st operand must be an Imm or CL
-             | SAR           Size Operand Operand -- 1st operand must be an Imm or CL
-             | SHR           Size Operand Operand -- 1st operand must be an Imm or CL
+             | SHL           Size Imm Operand -- Only immediate shifts allowed
+             | SAR           Size Imm Operand -- Only immediate shifts allowed
+             | SHR           Size Imm Operand -- Only immediate shifts allowed
+              | BT            Size Imm Operand
              | NOP
 
--- Float Arithmetic. -- ToDo for 386
+-- Float Arithmetic.
 
--- Note that we cheat by treating G{ABS,MOV,NEG} of doubles as single instructions
--- right up until we spit them out.
+-- Note that we cheat by treating G{ABS,MOV,NEG} of doubles 
+-- as single instructions right up until we spit them out.
 
               -- all the 3-operand fake fp insns are src1 src2 dst
               -- and furthermore are constrained to be fp regs only.
+              -- IMPORTANT: keep is_G_insn up to date with any changes here
              | GMOV          Reg Reg -- src(fpreg), dst(fpreg)
               | GLD           Size MachRegsAddr Reg -- src, dst(fpreg)
               | GST           Size Reg MachRegsAddr -- src(fpreg), dst
 
+              | GLDZ          Reg -- dst(fpreg)
+              | GLD1          Reg -- dst(fpreg)
+
              | GFTOD         Reg Reg -- src(fpreg), dst(fpreg)
               | GFTOI         Reg Reg -- src(fpreg), dst(intreg)
 
@@ -531,7 +550,11 @@ needed for the translation, and x86 has 8 in total.
              | GABS          Size Reg Reg -- src, dst
              | GNEG          Size Reg Reg -- src, dst
              | GSQRT         Size Reg Reg -- src, dst
+             | GSIN          Size Reg Reg -- src, dst
+             | GCOS          Size Reg Reg -- src, dst
+             | GTAN          Size Reg Reg -- src, dst
 
+              | GFREE         -- do ffree on all x86 regs; an ugly hack
 -- Comparison
 
              | TEST          Size Operand Operand
@@ -560,6 +583,40 @@ data Operand
   | OpImm  Imm         -- immediate value
   | OpAddr MachRegsAddr        -- memory reference
 
+
+i386_insert_ffrees :: [Instr] -> [Instr]
+i386_insert_ffrees insns
+   | any is_G_instr insns
+   = concatMap ffree_before_nonlocal_transfers insns
+   | otherwise
+   = insns
+
+ffree_before_nonlocal_transfers insn
+   = case insn of
+        CALL _                                      -> [GFREE, insn]
+        JMP (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> [insn]
+        JMP _                                       -> [GFREE, insn]
+        other                                       -> [insn]
+
+
+-- if you ever add a new FP insn to the fake x86 FP insn set,
+-- you must update this too
+is_G_instr :: Instr -> Bool
+is_G_instr instr
+   = case instr of
+        GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True;
+        GLDZ _ -> True; GLD1 _ -> True;
+        GFTOD _ _ -> True; GFTOI _ _ -> True;
+        GDTOF _ _ -> 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;
+        GFREE -> panic "is_G_instr: GFREE (!)"
+        other -> False
+
 #endif {- i386_TARGET_ARCH -}
 \end{code}