[project @ 2000-01-24 17:24:23 by sewardj]
authorsewardj <unknown>
Mon, 24 Jan 2000 17:24:24 +0000 (17:24 +0000)
committersewardj <unknown>
Mon, 24 Jan 2000 17:24:24 +0000 (17:24 +0000)
Major reworking of the x86 floating point code generation.

Intel, in their infinite wisdom, selected a stack model for floating
point registers on x86.  That might have made sense back in 1979 --
nowadays we can see it for the nonsense it really is.  A stack model
fits poorly with the existing nativeGen infrastructure, which assumes
flat integer and FP register sets.  Prior to this commit, nativeGen
could not generate correct x86 FP code -- to do so would have meant
somehow working the register-stack paradigm into the register
allocator and spiller, which sounds very difficult.

We have decided to cheat, and go for a simple fix which requires no
infrastructure modifications, at the expense of generating ropey but
correct FP code.  All notions of the x86 FP stack and its insns have
been removed.  Instead, we pretend (to the instruction selector and
register allocator) that x86 has six floating point registers, %fake0
.. %fake5, which can be used in the usual flat manner.  We further
claim that x86 has floating point instructions very similar to SPARC
and Alpha, that is, a simple 3-operand register-register arrangement.
Code generation and register allocation proceed on this basis.

When we come to print out the final assembly, our convenient fiction
is converted to dismal reality.  Each fake instruction is
independently converted to a series of real x86 instructions.
%fake0 .. %fake5 are mapped to %st(0) .. %st(5).  To do reg-reg
arithmetic operations, the two operands are pushed onto the top of the
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.

ghc/compiler/nativeGen/AsmCodeGen.lhs
ghc/compiler/nativeGen/MachCode.lhs
ghc/compiler/nativeGen/MachMisc.lhs
ghc/compiler/nativeGen/MachRegs.lhs
ghc/compiler/nativeGen/PprMach.lhs
ghc/compiler/nativeGen/RegAllocInfo.lhs
ghc/compiler/nativeGen/StixPrim.lhs

index 9309d47..13a59ef 100644 (file)
@@ -84,18 +84,10 @@ nativeCodeGen :: AbstractC -> UniqSupply -> (SDoc, SDoc)
 nativeCodeGen absC us
    = let (stixRaw, us1) = initUs us (genCodeAbstractC absC)
          stixOpt        = map (map genericOpt) stixRaw
-         stixFinal      = map x86floatFix stixOpt
-         insns          = initUs_ us1 (codeGen stixFinal)
-         debug_stix     = vcat (map pprStixTrees stixFinal)
+         insns          = initUs_ us1 (codeGen stixOpt)
+         debug_stix     = vcat (map pprStixTrees stixOpt)
      in 
          (debug_stix, insns)
-
-#if i386_TARGET_ARCH
-x86floatFix = floatFix
-#else
-x86floatFix = id
-#endif
-
 \end{code}
 
 @codeGen@ is the top-level code-generation function:
@@ -108,7 +100,10 @@ codeGen stixFinal
        static_instrss = scheduleMachCode dynamic_codes
         docs           = map (vcat . map pprInstr) static_instrss       
     in
-    returnUs (vcat (intersperse (char ' ' $$ char ' ') docs))
+    returnUs (vcat (intersperse (char ' ' 
+                                 $$ text "# ___stg_split_marker" 
+                                 $$ char ' ') 
+                    docs))
 \end{code}
 
 Top level code generator for a chunk of stix code:
@@ -292,64 +287,3 @@ Anything else is just too hard.
 \begin{code}
 primOpt op args = StPrim op args
 \end{code}
-
------------------------------------------------------------------------------
-Fix up floating point operations for x86.
-
-The problem is that the code generator can't handle the weird register
-naming scheme for floating point registers on the x86, so we have to
-deal with memory-resident floating point values wherever possible.
-
-We therefore can't stand references to floating-point kinded temporary
-variables, and try to translate them into memory addresses wherever
-possible.
-
-\begin{code}
-floatFix :: [StixTree] -> [StixTree]
-floatFix trees = fltFix emptyUFM trees
-
-fltFix         :: UniqFM StixTree      -- mapping tmp vars to memory locations
-       -> [StixTree]
-       -> [StixTree]
-fltFix locs [] = []
-
--- The case we're interested in: loading a temporary from a memory
--- address.  Eliminate the instruction and replace all future references
--- to the temporary with the memory address.
-fltFix locs ((StAssign rep (StReg (StixTemp uq _)) loc) : trees)
-  | isFloatingRep rep  = fltFix (addToUFM locs uq loc) trees
-
-fltFix locs ((StAssign rep src dst) : trees)
-  = StAssign rep (fltFix1 locs src) (fltFix1 locs dst) : fltFix locs trees
-  
-fltFix locs (tree : trees)
-  = fltFix1 locs tree : fltFix locs trees
-
-
-fltFix1 :: UniqFM StixTree -> StixTree -> StixTree
-fltFix1 locs r@(StReg (StixTemp uq rep))
-  | isFloatingRep rep = case lookupUFM locs uq of
-                               Nothing   -> panic "fltFix1"
-                               Just tree -> tree
-
-fltFix1 locs (StIndex rep l r) =
-  StIndex rep (fltFix1 locs l) (fltFix1 locs r)
-
-fltFix1 locs (StInd rep tree) =
-  StInd rep (fltFix1 locs tree)
-
-fltFix1 locs (StAssign rep dst src) = panic "fltFix1: StAssign"
-
-fltFix1 locs (StJump tree) = StJump (fltFix1 locs tree)
-
-fltFix1 locs (StCondJump lbl tree) =
-  StCondJump lbl (fltFix1 locs tree)
-
-fltFix1 locs (StPrim op trees) = 
-  StPrim op (map (fltFix1 locs) trees)
-
-fltFix1 locs (StCall f conv rep trees) =
-  StCall f conv rep (map (fltFix1 locs) trees)
-fltFix1 locs tree = tree
-\end{code}
index 86d3c31..7ba0869 100644 (file)
@@ -247,7 +247,7 @@ getRegister (StCall fn cconv kind args)
     returnUs (Fixed kind reg call)
   where
     reg = if isFloatingRep kind
-         then IF_ARCH_alpha( f0, IF_ARCH_i386( st0, IF_ARCH_sparc( f0,)))
+         then IF_ARCH_alpha( f0, IF_ARCH_i386( fake0, IF_ARCH_sparc( f0,)))
          else IF_ARCH_alpha( v0, IF_ARCH_i386( eax, IF_ARCH_sparc( o0,)))
 
 getRegister (StString s)
@@ -505,42 +505,32 @@ getRegister leaf
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
-getRegister (StDouble 0.0)
-  = let
-       code dst = mkSeqInstrs [FLDZ]
-    in
-    returnUs (Any DoubleRep code)
-
-getRegister (StDouble 1.0)
-  = let
-       code dst = mkSeqInstrs [FLD1]
-    in
-    returnUs (Any DoubleRep code)
-
 getRegister (StDouble d)
   = getUniqLabelNCG                `thenUs` \ lbl ->
-    --getNewRegNCG PtrRep          `thenUs` \ tmp ->
     let code dst = mkSeqInstrs [
            SEGMENT DataSegment,
            LABEL lbl,
            DATA DF [ImmDouble d],
            SEGMENT TextSegment,
-           FLD DF (OpImm (ImmCLbl lbl))
+           GLD DF (ImmAddr (ImmCLbl lbl) 0) dst
            ]
     in
     returnUs (Any DoubleRep code)
 
+
 getRegister (StPrim primop [x]) -- unary PrimOps
   = case primop of
       IntNegOp  -> trivialUCode (NEGI L) x
-
       NotOp    -> trivialUCode (NOT L) x
 
-      FloatNegOp  -> trivialUFCode FloatRep FCHS x
-      FloatSqrtOp -> trivialUFCode FloatRep FSQRT x
-      DoubleNegOp -> trivialUFCode DoubleRep FCHS x
+      FloatNegOp  -> trivialUFCode FloatRep  (GNEG F) x
+      DoubleNegOp -> trivialUFCode DoubleRep (GNEG DF) x
+
+      FloatSqrtOp  -> trivialUFCode FloatRep  (GSQRT F) x
+      DoubleSqrtOp -> trivialUFCode DoubleRep (GSQRT DF) x
 
-      DoubleSqrtOp -> trivialUFCode DoubleRep FSQRT x
+      Double2FloatOp -> trivialUFCode FloatRep  GDTOF x
+      Float2DoubleOp -> trivialUFCode DoubleRep GFTOD x
 
       OrdOp -> coerceIntCode IntRep x
       ChrOp -> chrCode x
@@ -550,14 +540,11 @@ getRegister (StPrim primop [x]) -- unary PrimOps
       Double2IntOp -> coerceFP2Int x
       Int2DoubleOp -> coerceInt2FP DoubleRep x
 
-      Double2FloatOp -> coerceFltCode x
-      Float2DoubleOp -> coerceFltCode x
-
       other_op ->
         let
-           fixed_x = if is_float_op  -- promote to double
-                         then StPrim Float2DoubleOp [x]
-                         else x
+           fixed_x = if   is_float_op  -- promote to double
+                     then StPrim Float2DoubleOp [x]
+                     else x
        in
        getRegister (StCall fn cCallConv DoubleRep [x])
        where
@@ -651,15 +638,15 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       IntRemOp  -> quot_code L x y False{-remainder-}
       IntMulOp  -> trivialCode (IMUL L) x y {-True-}
 
-      FloatAddOp -> trivialFCode  FloatRep  FADD FADD  FADDP FADDP  x y
-      FloatSubOp -> trivialFCode  FloatRep  FSUB FSUBR FSUBP FSUBRP x y
-      FloatMulOp -> trivialFCode  FloatRep  FMUL FMUL  FMULP FMULP  x y
-      FloatDivOp -> trivialFCode  FloatRep  FDIV FDIVR FDIVP FDIVRP x y
+      FloatAddOp -> trivialFCode  FloatRep  GADD x y
+      FloatSubOp -> trivialFCode  FloatRep  GSUB x y
+      FloatMulOp -> trivialFCode  FloatRep  GMUL x y
+      FloatDivOp -> trivialFCode  FloatRep  GDIV x y
 
-      DoubleAddOp -> trivialFCode DoubleRep FADD FADD  FADDP FADDP  x y
-      DoubleSubOp -> trivialFCode DoubleRep FSUB FSUBR FSUBP FSUBRP x y
-      DoubleMulOp -> trivialFCode DoubleRep FMUL FMUL  FMULP FMULP  x y
-      DoubleDivOp -> trivialFCode DoubleRep FDIV FDIVR FDIVP FDIVRP x y
+      DoubleAddOp -> trivialFCode DoubleRep GADD x y
+      DoubleSubOp -> trivialFCode DoubleRep GSUB x y
+      DoubleMulOp -> trivialFCode DoubleRep GMUL x y
+      DoubleDivOp -> trivialFCode DoubleRep GDIV x y
 
       AndOp -> trivialCode (AND L) x y {-True-}
       OrOp  -> trivialCode (OR L)  x y {-True-}
@@ -673,18 +660,23 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       SllOp -> shift_code (SHL L) x y {-False-}
       SrlOp -> shift_code (SHR L) x y {-False-}
 
-      ISllOp -> shift_code (SHL L) x y {-False-}  --was:panic "I386Gen:isll"
-      ISraOp -> shift_code (SAR L) x y {-False-}  --was:panic "I386Gen:isra"
-      ISrlOp -> shift_code (SHR L) x y {-False-}  --was:panic "I386Gen:isrl"
+      ISllOp -> shift_code (SHL L) x y {-False-}
+      ISraOp -> shift_code (SAR L) x y {-False-}
+      ISrlOp -> shift_code (SHR L) x y {-False-}
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [promote x, promote y])
+      FloatPowerOp  -> getRegister (StCall SLIT("pow") cCallConv DoubleRep 
+                                           [promote x, promote y])
                       where promote x = StPrim Float2DoubleOp [x]
-      DoublePowerOp -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [x, y])
+      DoublePowerOp -> getRegister (StCall SLIT("pow") cCallConv DoubleRep 
+                                           [x, y])
   where
+
+    --------------------
     shift_code :: (Operand -> Operand -> Instr)
               -> StixTree
               -> StixTree
               -> UniqSM Register
+
       {- Case1: shift length as immediate -}
       -- Code is the same as the first eq. for trivialCode -- sigh.
     shift_code instr x y{-amount-}
@@ -715,7 +707,6 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
     shift_code instr x y{-amount-}
      = getRegister y           `thenUs` \ register1 ->  
        getRegister x           `thenUs` \ register2 ->
---       getNewRegNCG IntRep   `thenUs` \ dst ->
        let
        -- Note: we force the shift length to be loaded
        -- into ECX, so that we can use CL when shifting.
@@ -740,6 +731,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
        in
        returnUs (Fixed IntRep eax code__2)
 
+    --------------------
     add_code :: Size -> StixTree -> StixTree -> UniqSM Register
 
     add_code sz x (StInt y)
@@ -749,51 +741,13 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            code = registerCode register tmp
            src1 = registerName register tmp
            src2 = ImmInt (fromInteger y)
-           code__2 dst = code .
-                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2)) (OpReg dst))
-       in
-       returnUs (Any IntRep code__2)
-{-
-    add_code sz x (StInd _ mem)
-      = getRegister x          `thenUs` \ register1 ->
-       --getNewRegNCG (registerRep register1)
-       --                      `thenUs` \ tmp1 ->
-       getAmode mem            `thenUs` \ amode ->
-       let
-           code2 = amodeCode amode
-           src2  = amodeAddr amode
-
-           code__2 dst = let code1 = registerCode register1 dst
-                             src1  = registerName register1 dst
-                         in asmParThen [code2 asmVoid,code1 asmVoid] .
-                            if isFixed register1 && src1 /= dst
-                            then mkSeqInstrs [MOV L (OpReg src1) (OpReg dst),
-                                              ADD sz (OpAddr src2)  (OpReg dst)]
-                            else
-                                   mkSeqInstrs [ADD sz (OpAddr src2) (OpReg src1)]
+           code__2 dst 
+               = code .
+                mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2)) 
+                                    (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
-    add_code sz (StInd _ mem) y
-      = getRegister y          `thenUs` \ register2 ->
-       --getNewRegNCG (registerRep register2)
-       --                      `thenUs` \ tmp2 ->
-       getAmode mem            `thenUs` \ amode ->
-       let
-           code1 = amodeCode amode
-           src1  = amodeAddr amode
-
-           code__2 dst = let code2 = registerCode register2 dst
-                             src2  = registerName register2 dst
-                         in asmParThen [code1 asmVoid,code2 asmVoid] .
-                            if isFixed register2 && src2 /= dst
-                            then mkSeqInstrs [MOV L (OpReg src2) (OpReg dst),
-                                              ADD sz (OpAddr src1)  (OpReg dst)]
-                            else
-                                   mkSeqInstrs [ADD sz (OpAddr src1) (OpReg src2)]
-       in
-       returnUs (Any IntRep code__2)
--}
     add_code sz x y
       = getRegister x          `thenUs` \ register1 ->
        getRegister y           `thenUs` \ register2 ->
@@ -804,8 +758,11 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            src1  = registerName register1 tmp1
            code2 = registerCode register2 tmp2 asmVoid
            src2  = registerName register2 tmp2
-           code__2 dst = asmParThen [code1, code2] .
-                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) (Just (src2,1)) (ImmInt 0))) (OpReg dst))
+           code__2 dst 
+               = asmParThen [code1, code2] .
+                mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) (Just (src2,1)) 
+                                                           (ImmInt 0))) 
+                                    (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
@@ -819,8 +776,10 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            code = registerCode register tmp
            src1 = registerName register tmp
            src2 = ImmInt (-(fromInteger y))
-           code__2 dst = code .
-                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2)) (OpReg dst))
+           code__2 dst 
+               = code .
+                mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2))
+                                    (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
@@ -863,10 +822,14 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            src2    = ImmInt (fromInteger i)
            code__2 = asmParThen [code1] .
                      mkSeqInstrs [-- we put src2 in (ebx)
-                                  MOV L (OpImm src2) (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))),
-                                  MOV L (OpReg src1) (OpReg eax),
-                                  CLTD,
-                                  IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)))]
+                        MOV L (OpImm src2) 
+                               (OpAddr (AddrBaseIndex (Just ebx) Nothing 
+                                                      (ImmInt OFFSET_R1))),
+                        MOV L (OpReg src1) (OpReg eax),
+                        CLTD,
+                        IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing 
+                                         (ImmInt OFFSET_R1)))
+                      ]
        in
        returnUs (Fixed IntRep (if is_division then eax else edx) code__2)
 
@@ -882,14 +845,20 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            src2    = registerName register2 tmp2
            code__2 = asmParThen [code1, code2] .
                      if src2 == ecx || src2 == esi
-                     then mkSeqInstrs [ MOV L (OpReg src1) (OpReg eax),
-                                        CLTD,
-                                        IDIV sz (OpReg src2)]
+                     then mkSeqInstrs [ 
+                              MOV L (OpReg src1) (OpReg eax),
+                             CLTD,
+                             IDIV sz (OpReg src2)
+                           ]
                      else mkSeqInstrs [ -- we put src2 in (ebx)
-                                        MOV L (OpReg src2) (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))),
-                                        MOV L (OpReg src1) (OpReg eax),
-                                        CLTD,
-                                        IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)))]
+                             MOV L (OpReg src2) 
+                                    (OpAddr (AddrBaseIndex (Just ebx) Nothing 
+                                                           (ImmInt OFFSET_R1))),
+                             MOV L (OpReg src1) (OpReg eax),
+                             CLTD,
+                             IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing 
+                                                             (ImmInt OFFSET_R1)))
+                           ]
        in
        returnUs (Fixed IntRep (if is_division then eax else edx) code__2)
        -----------------------
@@ -898,16 +867,15 @@ getRegister (StInd pk mem)
   = getAmode mem                   `thenUs` \ amode ->
     let
        code = amodeCode amode
-       src   = amodeAddr amode
+       src  = amodeAddr amode
        size = primRepToSize pk
        code__2 dst = code .
                      if pk == DoubleRep || pk == FloatRep
-                     then mkSeqInstr (FLD {-DF-} size (OpAddr src))
+                     then mkSeqInstr (GLD size src dst)
                      else mkSeqInstr (MOV size (OpAddr src) (OpReg dst))
     in
        returnUs (Any pk code__2)
 
-
 getRegister (StInt i)
   = let
        src = ImmInt (fromInteger i)
@@ -1485,26 +1453,6 @@ condIntCode cond x y
     returnUs (CondCode False cond code__2)
 
 -----------
-
-condFltCode cond x (StDouble 0.0)
-  = getRegister x              `thenUs` \ register1 ->
-    getNewRegNCG (registerRep register1)
-                               `thenUs` \ tmp1 ->
-    let
-       pk1   = registerRep register1
-       code1 = registerCode register1 tmp1
-       src1  = registerName register1 tmp1
-
-       code__2 = asmParThen [code1 asmVoid] .
-                 mkSeqInstrs [FTST, FSTP DF (OpReg st0), -- or FLDZ, FUCOMPP ?
-                              FNSTSW,
-                              --AND HB (OpImm (ImmInt 68)) (OpReg eax),
-                              --XOR HB (OpImm (ImmInt 64)) (OpReg eax)
-                              SAHF
-                             ]
-    in
-    returnUs (CondCode True (fix_FP_cond cond) code__2)
-
 condFltCode cond x y
   = getRegister x              `thenUs` \ register1 ->
     getRegister y              `thenUs` \ register2 ->
@@ -1512,35 +1460,33 @@ condFltCode cond x y
                                `thenUs` \ tmp1 ->
     getNewRegNCG (registerRep register2)
                                `thenUs` \ tmp2 ->
+    getNewRegNCG DoubleRep     `thenUs` \ tmp ->
     let
        pk1   = registerRep register1
        code1 = registerCode register1 tmp1
        src1  = registerName register1 tmp1
 
+       pk2   = registerRep register2
        code2 = registerCode register2 tmp2
        src2  = registerName register2 tmp2
 
-       code__2 = asmParThen [code2 asmVoid, code1 asmVoid] .
-                 mkSeqInstrs [FUCOMPP,
-                              FNSTSW,
-                              --AND HB (OpImm (ImmInt 68)) (OpReg eax),
-                              --XOR HB (OpImm (ImmInt 64)) (OpReg eax)
-                              SAHF
-                             ]
+       code__2 =   asmParThen [code1 asmVoid, code2 asmVoid] .
+                   mkSeqInstr (GCMP (primRepToSize pk1) src1 src2)
+
+        {- On the 486, the flags set by FP compare are the unsigned ones!
+           (This looks like a HACK to me.  WDP 96/03)
+        -}
+        fix_FP_cond :: Cond -> Cond
+
+        fix_FP_cond GE  = GEU
+        fix_FP_cond GTT  = GU
+        fix_FP_cond LTT  = LU
+        fix_FP_cond LE  = LEU
+        fix_FP_cond any = any
     in
     returnUs (CondCode True (fix_FP_cond cond) code__2)
 
-{- On the 486, the flags set by FP compare are the unsigned ones!
-   (This looks like a HACK to me.  WDP 96/03)
--}
-
-fix_FP_cond :: Cond -> Cond
 
-fix_FP_cond GE  = GEU
-fix_FP_cond GTT  = GU
-fix_FP_cond LTT  = LU
-fix_FP_cond LE  = LEU
-fix_FP_cond any = any
 
 #endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1798,7 +1744,6 @@ assignFltCode pk (StInd pk_dst dst) (StInd pk_src src)
   = getNewRegNCG IntRep            `thenUs` \ tmp ->
     getAmode src                   `thenUs` \ amodesrc ->
     getAmode dst                   `thenUs` \ amodedst ->
-    --getRegister src                      `thenUs` \ register ->
     let
        codesrc1 = amodeCode amodesrc asmVoid
        addrsrc1 = amodeAddr amodesrc
@@ -1819,38 +1764,38 @@ assignFltCode pk (StInd pk_dst dst) (StInd pk_src src)
     returnUs code__2
 
 assignFltCode pk (StInd _ dst) src
-  = --getNewRegNCG pk              `thenUs` \ tmp ->
+  = getNewRegNCG pk                `thenUs` \ tmp ->
     getAmode dst                   `thenUs` \ amode ->
-    getRegister src                        `thenUs` \ register ->
+    getRegister src                `thenUs` \ register ->
     let
        sz      = primRepToSize pk
        dst__2  = amodeAddr amode
 
        code1   = amodeCode amode asmVoid
-       code2   = registerCode register {-tmp-}st0 asmVoid
+       code2   = registerCode register tmp asmVoid
 
-       --src__2= registerName register tmp
-       pk__2   = registerRep register
-       sz__2   = primRepToSize pk__2
+       src__2  = registerName register tmp
 
        code__2 = asmParThen [code1, code2] .
-                 mkSeqInstr (FSTP sz (OpAddr dst__2))
+                 mkSeqInstr (GST sz src__2 dst__2)
     in
     returnUs code__2
 
 assignFltCode pk dst src
   = getRegister dst                        `thenUs` \ register1 ->
     getRegister src                        `thenUs` \ register2 ->
-    --getNewRegNCG (registerRep register2)
-    --                             `thenUs` \ tmp ->
+    getNewRegNCG pk                         `thenUs` \ tmp ->
     let
-       sz      = primRepToSize pk
-       dst__2  = registerName register1 st0 --tmp
-
-       code    = registerCode register2 dst__2
+        -- the register which is dst
+       dst__2  = registerName register1 tmp
+        -- the register into which src is computed, preferably dst__2
        src__2  = registerName register2 dst__2
+        -- code to compute src into src__2
+       code    = registerCode register2 dst__2
 
-       code__2 = code
+       code__2 = if isFixed register2
+                  then code . mkSeqInstr (GMOV src__2 dst__2)
+                  else code
     in
     returnUs code__2
 
@@ -2345,22 +2290,23 @@ genCCall fn cconv kind args
     get_call_arg arg
       = get_op arg             `thenUs` \ (code, op, sz) ->
         case sz of
-           DF -> returnUs (sz,
+           DF -> --getNewRegNCG DoubleRep `thenUs` \ tmp ->
+                 returnUs (sz,
                            code .
-                           mkSeqInstr (FLD L op) .
+                           --mkSeqInstr (GLD DF op tmp) .
                            mkSeqInstr (SUB L (OpImm (ImmInt 8)) (OpReg esp)) .
-                           mkSeqInstr (FSTP DF (OpAddr (AddrBaseIndex 
+                           mkSeqInstr (GST DF {-tmp-}op (AddrBaseIndex 
                                                           (Just esp) 
-                                                          Nothing (ImmInt 0))))
+                                                          Nothing (ImmInt 0)))
                           )
           _  -> returnUs (sz,
-                           code . mkSeqInstr (PUSH sz op))
+                           code . mkSeqInstr (PUSH sz (OpReg op)))
 
     ------------
     get_op
        :: StixTree
-       -> UniqSM (InstrBlock,Operand, Size)    -- code, operator, size
-
+       -> UniqSM (InstrBlock, {-Operand-}Reg, Size)    -- code, operator, size
+{-
     get_op (StInt i)
       = returnUs (asmParThen [], OpImm (ImmInt (fromInteger i)), L)
 
@@ -2372,7 +2318,7 @@ genCCall fn cconv kind args
            sz   = primRepToSize pk
        in
        returnUs (code, OpAddr addr, sz)
-
+-}
     get_op op
       = getRegister op         `thenUs` \ register ->
        getNewRegNCG (registerRep register)
@@ -2383,7 +2329,7 @@ genCCall fn cconv kind args
            pk   = registerRep  register
            sz   = primRepToSize pk
        in
-       returnUs (code, OpReg reg, sz)
+       returnUs (code, {-OpReg-} reg, sz)
 
 #endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2665,12 +2611,7 @@ trivialFCode
     :: PrimRep
     -> IF_ARCH_alpha((Reg -> Reg -> Reg -> Instr)
       ,IF_ARCH_sparc((Size -> Reg -> Reg -> Reg -> Instr)
-      ,IF_ARCH_i386 (
-             {-this bizarre type for i386 seems a little too weird (WDP 96/03)-}
-              (Size -> Operand -> Instr)
-           -> (Size -> Operand -> Instr) {-reversed instr-}
-           -> Instr {-pop-}
-           -> Instr {-reversed instr: pop-}
+      ,IF_ARCH_i386 ((Size -> Reg -> Reg -> Reg -> Instr)
       ,)))
     -> StixTree -> StixTree -- the two arguments
     -> UniqSM Register
@@ -2686,7 +2627,7 @@ trivialUCode
 trivialUFCode
     :: PrimRep
     -> IF_ARCH_alpha((Reg -> Reg -> Instr)
-      ,IF_ARCH_i386 (Instr
+      ,IF_ARCH_i386 ((Reg -> Reg -> Instr)
       ,IF_ARCH_sparc((Reg -> Reg -> Instr)
       ,)))
     -> StixTree -- the one argument
@@ -2767,7 +2708,6 @@ trivialUFCode _ instr x
 trivialCode instr x y
   | maybeToBool imm
   = getRegister x              `thenUs` \ register1 ->
-    --getNewRegNCG IntRep      `thenUs` \ tmp1 ->
     let
        code__2 dst = let code1 = registerCode register1 dst
                          src1  = registerName register1 dst
@@ -2786,7 +2726,6 @@ trivialCode instr x y
 trivialCode instr x y
   | maybeToBool imm
   = getRegister y              `thenUs` \ register1 ->
-    --getNewRegNCG IntRep      `thenUs` \ tmp1 ->
     let
        code__2 dst = let code1 = registerCode register1 dst
                          src1  = registerName register1 dst
@@ -2801,48 +2740,10 @@ trivialCode instr x y
   where
     imm = maybeImm x
     imm__2 = case imm of Just x -> x
-{-
-trivialCode instr x (StInd pk mem)
-  = getRegister x              `thenUs` \ register ->
-    --getNewRegNCG IntRep      `thenUs` \ tmp ->
-    getAmode mem               `thenUs` \ amode ->
-    let
-       code2 = amodeCode amode asmVoid
-       src2  = amodeAddr amode
-       code__2 dst = let code1 = registerCode register dst asmVoid
-                         src1  = registerName register dst
-                     in asmParThen [code1, code2] .
-                        if isFixed register && src1 /= dst
-                        then mkSeqInstrs [MOV L (OpReg src1) (OpReg dst),
-                                          instr (OpAddr src2)  (OpReg dst)]
-                        else
-                               mkSeqInstr (instr (OpAddr src2) (OpReg src1))
-    in
-    returnUs (Any pk code__2)
 
-trivialCode instr (StInd pk mem) y
-  = getRegister y              `thenUs` \ register ->
-    --getNewRegNCG IntRep      `thenUs` \ tmp ->
-    getAmode mem               `thenUs` \ amode ->
-    let
-       code2 = amodeCode amode asmVoid
-       src2  = amodeAddr amode
-       code__2 dst = let
-                         code1 = registerCode register dst asmVoid
-                         src1  = registerName register dst
-                     in asmParThen [code1, code2] .
-                        if isFixed register && src1 /= dst
-                        then mkSeqInstrs [MOV L (OpReg src1) (OpReg dst),
-                                          instr (OpAddr src2)  (OpReg dst)]
-                        else
-                               mkSeqInstr (instr (OpAddr src2) (OpReg src1))
-    in
-    returnUs (Any pk code__2)
--}
 trivialCode instr x y
   = getRegister x              `thenUs` \ register1 ->
     getRegister y              `thenUs` \ register2 ->
-    --getNewRegNCG IntRep      `thenUs` \ tmp1 ->
     getNewRegNCG IntRep                `thenUs` \ tmp2 ->
     let
        code2 = registerCode register2 tmp2 asmVoid
@@ -2862,7 +2763,6 @@ trivialCode instr x y
 -----------
 trivialUCode instr x
   = getRegister x              `thenUs` \ register ->
---    getNewRegNCG IntRep      `thenUs` \ tmp ->
     let
        code__2 dst = let
                          code = registerCode register dst
@@ -2875,10 +2775,9 @@ trivialUCode instr x
     returnUs (Any IntRep code__2)
 
 -----------
+{-
 trivialFCode pk _ instrr _ _ (StInd pk' mem) y
   = getRegister y              `thenUs` \ register2 ->
-    --getNewRegNCG (registerRep register2)
-    --                         `thenUs` \ tmp2 ->
     getAmode mem               `thenUs` \ amode ->
     let
        code1 = amodeCode amode
@@ -2894,8 +2793,6 @@ trivialFCode pk _ instrr _ _ (StInd pk' mem) y
 
 trivialFCode pk instr _ _ _ x (StInd pk' mem)
   = getRegister x              `thenUs` \ register1 ->
-    --getNewRegNCG (registerRep register1)
-    --                         `thenUs` \ tmp1 ->
     getAmode mem               `thenUs` \ amode ->
     let
        code2 = amodeCode amode
@@ -2912,10 +2809,6 @@ trivialFCode pk instr _ _ _ x (StInd pk' mem)
 trivialFCode pk _ _ _ instrpr x y
   = getRegister x              `thenUs` \ register1 ->
     getRegister y              `thenUs` \ register2 ->
-    --getNewRegNCG (registerRep register1)
-    --                         `thenUs` \ tmp1 ->
-    --getNewRegNCG (registerRep register2)
-    --                         `thenUs` \ tmp2 ->
     getNewRegNCG DoubleRep     `thenUs` \ tmp ->
     let
        pk1   = registerRep register1
@@ -2931,8 +2824,38 @@ trivialFCode pk _ _ _ instrpr x y
                         mkSeqInstr instrpr
     in
     returnUs (Any pk1 code__2)
+-}
+
+trivialFCode pk instr x y
+  = getRegister x              `thenUs` \ register1 ->
+    getRegister y              `thenUs` \ register2 ->
+    getNewRegNCG DoubleRep     `thenUs` \ tmp1 ->
+    getNewRegNCG DoubleRep     `thenUs` \ tmp2 ->
+    let
+       code1 = registerCode register1 tmp1
+       src1  = registerName register1 tmp1
+
+       code2 = registerCode register2 tmp2
+       src2  = registerName register2 tmp2
+
+       code__2 dst = asmParThen [code1 asmVoid, code2 asmVoid] .
+                     mkSeqInstr (instr (primRepToSize pk) src1 src2 dst)
+    in
+    returnUs (Any DoubleRep code__2)
+
 
 -------------
+trivialUFCode pk instr x
+  = getRegister x              `thenUs` \ register ->
+    getNewRegNCG pk            `thenUs` \ tmp ->
+    let
+       code = registerCode register tmp
+       src  = registerName register tmp
+       code__2 dst = code . mkSeqInstr (instr src dst)
+    in
+    returnUs (Any pk code__2)
+
+{-
 trivialUFCode pk instr (StInd pk' mem)
   = getAmode mem               `thenUs` \ amode ->
     let
@@ -2945,7 +2868,6 @@ trivialUFCode pk instr (StInd pk' mem)
 
 trivialUFCode pk instr x
   = getRegister x              `thenUs` \ register ->
-    --getNewRegNCG pk          `thenUs` \ tmp ->
     let
        code__2 dst = let
                          code = registerCode register dst
@@ -2953,7 +2875,7 @@ trivialUFCode pk instr x
                      in code . mkSeqInstrs [instr]
     in
     returnUs (Any pk code__2)
-
+-}
 #endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if sparc_TARGET_ARCH
@@ -3124,11 +3046,9 @@ coerceInt2FP pk x
     let
        code = registerCode register reg
        src  = registerName register reg
-
-       code__2 dst = code . mkSeqInstrs [
-       -- to fix: should spill instead of using R1
-                     MOV L (OpReg src) (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))),
-                     FILD (primRepToSize pk) (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)) dst]
+        opc  = case pk of FloatRep -> GITOF ; DoubleRep -> GITOD
+        code__2 dst = code . 
+                      mkSeqInstr (opc src dst)
     in
     returnUs (Any pk code__2)
 
@@ -3141,10 +3061,9 @@ coerceFP2Int x
        src  = registerName register tmp
        pk   = registerRep register
 
-       code__2 dst = code . mkSeqInstrs [
-                               FRNDINT,
-                               FIST L (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)),
-                               MOV L (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))) (OpReg dst)]
+        opc  = case pk of FloatRep -> GFTOI ; DoubleRep -> GDTOI
+        code__2 dst = code . 
+                      mkSeqInstr (opc src dst)
     in
     returnUs (Any IntRep code__2)
 
index 3c593e0..d72de13 100644 (file)
@@ -475,49 +475,34 @@ data RI
 
 -- Float Arithmetic. -- ToDo for 386
 
--- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
+-- Note that we cheat by treating G{ABS,MOV,NEG} of doubles as single instructions
 -- right up until we spit them out.
 
-             | SAHF          -- stores ah into flags
-             | FABS
-             | FADD          Size Operand -- src
-             | FADDP
-             | FIADD         Size MachRegsAddr -- src
-             | FCHS
-             | FCOM          Size Operand -- src
-             | FCOS
-             | FDIV          Size Operand -- src
-             | FDIVP
-             | FIDIV         Size MachRegsAddr -- src
-             | FDIVR         Size Operand -- src
-             | FDIVRP
-             | FIDIVR        Size MachRegsAddr -- src
-             | FICOM         Size MachRegsAddr -- src
-             | FILD          Size MachRegsAddr Reg -- src, dst
-             | FIST          Size MachRegsAddr -- dst
-             | FLD           Size Operand -- src
-             | FLD1
-             | FLDZ
-             | FMUL          Size Operand -- src
-             | FMULP
-             | FIMUL         Size MachRegsAddr -- src
-             | FRNDINT
-             | FSIN
-             | FSQRT
-             | FST           Size Operand -- dst
-             | FSTP          Size Operand -- dst
-             | FSUB          Size Operand -- src
-             | FSUBP
-             | FISUB         Size MachRegsAddr -- src
-             | FSUBR         Size Operand -- src
-             | FSUBRP
-             | FISUBR        Size MachRegsAddr -- src
-             | FTST
-             | FCOMP         Size Operand -- src
-             | FUCOMPP
-             | FXCH
-             | FNSTSW
-             | FNOP
+              -- all the 3-operand fake fp insns are src1 src2 dst
+              -- and furthermore are constrained to be fp regs only.
+             | GMOV          Reg Reg -- src(fpreg), dst(fpreg)
+              | GLD           Size MachRegsAddr Reg -- src, dst(fpreg)
+              | GST           Size Reg MachRegsAddr -- src(fpreg), dst
+
+             | GFTOD         Reg Reg -- src(fpreg), dst(fpreg)
+              | GFTOI         Reg Reg -- src(fpreg), dst(intreg)
+
+             | GDTOF         Reg Reg -- src(fpreg), dst(fpreg)
+              | GDTOI         Reg Reg -- src(fpreg), dst(intreg)
+
+              | GITOF         Reg Reg -- src(intreg), dst(fpreg)
+              | GITOD         Reg Reg -- src(intreg), dst(fpreg)
+
+             | GADD          Size Reg Reg Reg -- src1, src2, dst
+             | GDIV          Size Reg Reg Reg -- src1, src2, dst
+             | GSUB          Size Reg Reg Reg -- src1, src2, dst
+             | GMUL          Size Reg Reg Reg -- src1, src2, dst
+
+             | GCMP          Size Reg Reg -- src1, src2
+
+             | GABS          Size Reg Reg -- src, dst
+             | GNEG          Size Reg Reg -- src, dst
+             | GSQRT         Size Reg Reg -- src, dst
 
 -- Comparison
 
index f5e02cb..7bafa78 100644 (file)
@@ -46,7 +46,7 @@ module MachRegs (
 #endif
 #if i386_TARGET_ARCH
        , eax, ebx, ecx, edx, esi, esp
-       , st0, st1, st2, st3, st4, st5, st6, st7
+       , fake0, fake1, fake2, fake3, fake4, fake5
 #endif
 #if sparc_TARGET_ARCH
        , allArgRegs
@@ -370,7 +370,10 @@ Intel x86 architecture:
 - Only ebx, esi, edi and esp are available across a C call (they are callee-saves).
 - Registers 0-7 have 16-bit counterparts (ax, bx etc.)
 - Registers 0-3 have 8 bit counterparts (ah, bh etc.)
-- Registers 8-15 hold extended floating point values.
+- Registers 8-13 are fakes; we pretend x86 has 6 conventionally-addressable
+  fp registers, and 3-operand insns for them, and we translate this into
+  real stack-based x86 fp code after register allocation.
+
 \begin{code}
 #if i386_TARGET_ARCH
 
@@ -378,7 +381,7 @@ gReg,fReg :: Int -> Int
 gReg x = x
 fReg x = (8 + x)
 
-st0, st1, st2, st3, st4, st5, st6, st7, eax, ebx, ecx, edx, esp :: Reg
+fake0, fake1, fake2, fake3, fake4, fake5, eax, ebx, ecx, edx, esp :: Reg
 eax = realReg (gReg 0)
 ebx = realReg (gReg 1)
 ecx = realReg (gReg 2)
@@ -387,15 +390,12 @@ esi = realReg (gReg 4)
 edi = realReg (gReg 5)
 ebp = realReg (gReg 6)
 esp = realReg (gReg 7)
-st0 = realReg (fReg 0)
-st1 = realReg (fReg 1)
-st2 = realReg (fReg 2)
-st3 = realReg (fReg 3)
-st4 = realReg (fReg 4)
-st5 = realReg (fReg 5)
-st6 = realReg (fReg 6)
-st7 = realReg (fReg 7)
-
+fake0 = realReg (fReg 0)
+fake1 = realReg (fReg 1)
+fake2 = realReg (fReg 2)
+fake3 = realReg (fReg 3)
+fake4 = realReg (fReg 4)
+fake5 = realReg (fReg 5)
 #endif
 \end{code}
 
@@ -474,14 +474,12 @@ names in the header files.  Gag me with a spoon, eh?
 #define edi 5
 #define ebp 6
 #define esp 7
-#define st0 8
-#define st1 9
-#define st2 10
-#define st3 11
-#define st4 12
-#define st5 13
-#define st6 14
-#define st7 15
+#define fake0 8
+#define fake1 9
+#define fake2 10
+#define fake3 11
+#define fake4 12
+#define fake5 13
 #endif
 #if sparc_TARGET_ARCH
 #define g0 0
@@ -765,7 +763,7 @@ reservedRegs
 freeRegs :: [Reg]
 freeRegs
   = freeMappedRegs IF_ARCH_alpha( [0..63],
-                  IF_ARCH_i386(  [0..15],
+                  IF_ARCH_i386(  [0..13],
                   IF_ARCH_sparc( [0..63],)))
 
 -------------------------------
index 304a4a2..eddbe80 100644 (file)
@@ -94,14 +94,14 @@ pprReg IF_ARCH_i386(s,) r
        _ -> SLIT("very naughty I386 byte register")
       })
 
-    {- UNUSED:
+{- UNUSED:
     ppr_reg_no HB i = ptext
       (case i of {
        ILIT( 0) -> SLIT("%ah");  ILIT( 1) -> SLIT("%bh");
        ILIT( 2) -> SLIT("%ch");  ILIT( 3) -> SLIT("%dh");
        _ -> SLIT("very naughty I386 high byte register")
       })
-    -}
+-}
 
 {- UNUSED:
     ppr_reg_no S i = ptext
@@ -125,21 +125,17 @@ pprReg IF_ARCH_i386(s,) r
 
     ppr_reg_no F i = ptext
       (case i of {
-       --ToDo: rm these (???)
-       ILIT( 8) -> SLIT("%st(0)");  ILIT( 9) -> SLIT("%st(1)");
-       ILIT(10) -> SLIT("%st(2)");  ILIT(11) -> SLIT("%st(3)");
-       ILIT(12) -> SLIT("%st(4)");  ILIT(13) -> SLIT("%st(5)");
-       ILIT(14) -> SLIT("%st(6)");  ILIT(15) -> SLIT("%st(7)");
+       ILIT( 8) -> SLIT("%fake0");  ILIT( 9) -> SLIT("%fake1");
+       ILIT(10) -> SLIT("%fake2");  ILIT(11) -> SLIT("%fake3");
+       ILIT(12) -> SLIT("%fake4");  ILIT(13) -> SLIT("%fake5");
        _ -> SLIT("very naughty I386 float register")
       })
 
     ppr_reg_no DF i = ptext
       (case i of {
-       --ToDo: rm these (???)
-       ILIT( 8) -> SLIT("%st(0)");  ILIT( 9) -> SLIT("%st(1)");
-       ILIT(10) -> SLIT("%st(2)");  ILIT(11) -> SLIT("%st(3)");
-       ILIT(12) -> SLIT("%st(4)");  ILIT(13) -> SLIT("%st(5)");
-       ILIT(14) -> SLIT("%st(6)");  ILIT(15) -> SLIT("%st(7)");
+       ILIT( 8) -> SLIT("%fake0");  ILIT( 9) -> SLIT("%fake1");
+       ILIT(10) -> SLIT("%fake2");  ILIT(11) -> SLIT("%fake3");
+       ILIT(12) -> SLIT("%fake4");  ILIT(13) -> SLIT("%fake5");
        _ -> SLIT("very naughty I386 float register")
       })
 #endif
@@ -405,7 +401,7 @@ pprInstr (SEGMENT TextSegment)
     = ptext
         IF_ARCH_alpha(SLIT("\t.text\n\t.align 3") {-word boundary-}
        ,IF_ARCH_sparc(SLIT("\t.text\n\t.align 4") {-word boundary-}
-       ,IF_ARCH_i386(SLIT(".text\n\t.align 4") {-needs per-OS variation!-}
+       ,IF_ARCH_i386(SLIT(".text\n\t.align 4,0x90") {-needs per-OS variation!-}
        ,)))
 
 pprInstr (SEGMENT DataSegment)
@@ -998,70 +994,111 @@ pprInstr (JMP (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
 pprInstr (JMP op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
 
 pprInstr (CALL imm)
-  = hcat [ ptext SLIT("\tcall "), pprImm imm ]
-
-pprInstr SAHF = ptext SLIT("\tsahf")
-pprInstr FABS = ptext SLIT("\tfabs")
-
-pprInstr (FADD sz src@(OpAddr _))
-  = hcat [ptext SLIT("\tfadd"), pprSize sz, space, pprOperand sz src]
-pprInstr (FADD sz src)
-  = ptext SLIT("\tfadd")
-pprInstr FADDP
-  = ptext SLIT("\tfaddp")
-pprInstr (FMUL sz src)
-  = hcat [ptext SLIT("\tfmul"), pprSize sz, space, pprOperand sz src]
-pprInstr FMULP
-  = ptext SLIT("\tfmulp")
-pprInstr (FIADD size op) = pprSizeAddr SLIT("fiadd") size op
-pprInstr FCHS = ptext SLIT("\tfchs")
-pprInstr (FCOM size op) = pprSizeOp SLIT("fcom") size op
-pprInstr FCOS = ptext SLIT("\tfcos")
-pprInstr (FIDIV size op) = pprSizeAddr SLIT("fidiv") size op
-pprInstr (FDIV sz src)
-  = hcat [ptext SLIT("\tfdiv"), pprSize sz, space, pprOperand sz src]
-pprInstr FDIVP
-  = ptext SLIT("\tfdivp")
-pprInstr (FDIVR sz src)
-  = hcat [ptext SLIT("\tfdivr"), pprSize sz, space, pprOperand sz src]
-pprInstr FDIVRP
-  = ptext SLIT("\tfdivpr")
-pprInstr (FIDIVR size op) = pprSizeAddr SLIT("fidivr") size op
-pprInstr (FICOM size op) = pprSizeAddr SLIT("ficom") size op
-pprInstr (FILD sz op reg) = pprSizeAddrReg SLIT("fild") sz op reg
-pprInstr (FIST size op) = pprSizeAddr SLIT("fist") size op
-pprInstr (FLD sz (OpImm (ImmCLbl src)))
-  = hcat [ptext SLIT("\tfld"),pprSize sz,space,pprCLabel_asm src]
-pprInstr (FLD sz src)
-  = hcat [ptext SLIT("\tfld"),pprSize sz,space,pprOperand sz src]
-pprInstr FLD1 = ptext SLIT("\tfld1")
-pprInstr FLDZ = ptext SLIT("\tfldz")
-pprInstr (FIMUL size op) = pprSizeAddr SLIT("fimul") size op
-pprInstr FRNDINT = ptext SLIT("\tfrndint")
-pprInstr FSIN = ptext SLIT("\tfsin")
-pprInstr FSQRT = ptext SLIT("\tfsqrt")
-pprInstr (FST sz dst)
-  = hcat [ptext SLIT("\tfst"), pprSize sz, space, pprOperand sz dst]
-pprInstr (FSTP sz dst)
-  = hcat [ptext SLIT("\tfstp"), pprSize sz, space, pprOperand sz dst]
-pprInstr (FISUB size op) = pprSizeAddr SLIT("fisub") size op
-pprInstr (FSUB sz src)
-  = hcat [ptext SLIT("\tfsub"), pprSize sz, space, pprOperand sz src]
-pprInstr FSUBP
-  = ptext SLIT("\tfsubp")
-pprInstr (FSUBR size src)
-  = pprSizeOp SLIT("fsubr") size src
-pprInstr FSUBRP
-  = ptext SLIT("\tfsubpr")
-pprInstr (FISUBR size op)
-  = pprSizeAddr SLIT("fisubr") size op
-pprInstr FTST = ptext SLIT("\tftst")
-pprInstr (FCOMP sz op)
-  = hcat [ptext SLIT("\tfcomp"), pprSize sz, space, pprOperand sz op]
-pprInstr FUCOMPP = ptext SLIT("\tfucompp")
-pprInstr FXCH = ptext SLIT("\tfxch")
-pprInstr FNSTSW = ptext SLIT("\tfnstsw %ax")
-pprInstr FNOP = ptext SLIT("")
+   = hcat [ ptext SLIT("\tffree %st(0) ; call "), pprImm imm ]
+
+
+-- Simulating a flat register set on the x86 FP stack is tricky.
+-- you have to free %st(7) before pushing anything on the FP reg stack
+-- so as to preclude the possibility of a FP stack overflow exception.
+-- ToDo: make gpop into a single instruction, FST
+pprInstr g@(GMOV src dst) 
+   = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1])
+
+-- GLD sz addr dst ==> FFREE %st(7) ; FLDsz addr ; FXCH (dst+1) ; FINCSTP
+pprInstr g@(GLD sz addr dst)
+ = pprG g (hcat [gtab, text "ffree %st(7) ; fld", pprSize sz, gsp, 
+                 pprAddr addr, gsemi, gpop dst 1])
+
+-- GST sz src addr ==> FFREE %st(7) ; FLD dst ; FSTPsz addr
+pprInstr g@(GST sz src addr)
+ = pprG g (hcat [gtab, gpush src 0, gsemi, 
+                 text "fstp", pprSize sz, gsp, pprAddr addr])
+
+pprInstr g@(GFTOD src dst) 
+   = pprG g bogus
+pprInstr g@(GFTOI src dst) 
+   = pprG g bogus
+
+pprInstr g@(GDTOF src dst) 
+   = pprG g bogus
+pprInstr g@(GDTOI src dst) 
+   = pprG g bogus
+
+pprInstr g@(GITOF src dst) 
+   = pprG g bogus
+pprInstr g@(GITOD src dst) 
+   = pprG g bogus
+
+pprInstr g@(GCMP sz src1 src2) 
+   = pprG g (hcat [gtab, text "pushl %eax ; ",
+                   gpush src2 0, gsemi, gpush src1 1]
+             $$
+             hcat [gtab, text "fcompp ; fstsw %ax ; sahf ; popl %eax"])
+
+pprInstr g@(GABS sz src dst)
+   = pprG g bogus
+pprInstr g@(GNEG sz src dst)
+   = pprG g bogus
+pprInstr g@(GSQRT sz src dst)
+   = pprG g bogus
+
+pprInstr g@(GADD sz src1 src2 dst)
+   = pprG g (hcat [gtab, gpush src1 0, 
+                   text " ; fadd ", greg src2 1, text ",%st(0)",
+                   gsemi, gpop dst 1])
+pprInstr g@(GSUB sz src1 src2 dst)
+   = pprG g (hcat [gtab, gpush src1 0, 
+                   text " ; fsub ", greg src2 1, text ",%st(0)",
+                   gsemi, gpop dst 1])
+pprInstr g@(GMUL sz src1 src2 dst)
+   = pprG g (hcat [gtab, gpush src1 0, 
+                   text " ; fmul ", greg src2 1, text ",%st(0)",
+                   gsemi, gpop dst 1])
+pprInstr g@(GDIV sz src1 src2 dst)
+   = pprG g (hcat [gtab, gpush src1 0, 
+                   text " ; fdiv ", greg src2 1, text ",%st(0)",
+                   gsemi, gpop dst 1])
+
+--------------------------
+gpush reg offset
+   = hcat [text "ffree %st(7) ; fld ", greg reg offset]
+gpop reg offset
+   = hcat [text "fxch ", greg reg offset, gsemi, text "fincstp"]
+
+bogus = text "\tbogus"
+greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')'
+gsemi = text " ; "
+gtab  = char '\t'
+gsp   = char ' '
+gregno (FixedReg i) = I# i
+gregno (MappedReg i) = I# i
+
+pprG :: Instr -> SDoc -> SDoc
+pprG fake actual
+   = (char '#' <> pprGInstr fake) $$ actual
+
+pprGInstr (GMOV src dst)   = pprSizeRegReg SLIT("gmov") DF src dst
+pprGInstr (GLD sz src dst) = pprSizeAddrReg SLIT("gld") sz src dst
+pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst
+
+pprGInstr (GFTOD src dst) = pprSizeSizeRegReg SLIT("gftod") F DF src dst
+pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L  src dst
+
+pprGInstr (GDTOF src dst) = pprSizeSizeRegReg SLIT("gdtof") DF F src dst
+pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst
+
+pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F  src dst
+pprGInstr (GITOD src dst) = pprSizeSizeRegReg SLIT("gitod") L DF src dst
+
+pprGInstr (GCMP sz src dst) = pprSizeRegReg SLIT("gcmp") sz src dst
+pprGInstr (GABS sz src dst) = pprSizeRegReg SLIT("gabs") sz src dst
+pprGInstr (GNEG sz src dst) = pprSizeRegReg SLIT("gneg") sz src dst
+pprGInstr (GSQRT sz src dst) = pprSizeRegReg SLIT("gsqrt") sz src dst
+
+pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg SLIT("gadd") sz src1 src2 dst
+pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg SLIT("gsub") sz src1 src2 dst
+pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg SLIT("gmul") sz src1 src2 dst
+pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg SLIT("gdiv") sz src1 src2 dst
 \end{code}
 
 Continue with I386-only printing bits and bobs:
@@ -1121,6 +1158,45 @@ pprSizeOpReg name size op1 reg
        pprReg size reg
     ]
 
+pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> SDoc
+pprSizeRegReg name size reg1 reg2
+  = hcat [
+       char '\t',
+       ptext name,
+       pprSize size,
+       space,
+       pprReg size reg1,
+        comma,
+        pprReg size reg2
+    ]
+
+pprSizeSizeRegReg :: FAST_STRING -> Size -> Size -> Reg -> Reg -> SDoc
+pprSizeSizeRegReg name size1 size2 reg1 reg2
+  = hcat [
+       char '\t',
+       ptext name,
+       pprSize size1,
+        pprSize size2,
+       space,
+       pprReg size1 reg1,
+        comma,
+        pprReg size2 reg2
+    ]
+
+pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> SDoc
+pprSizeRegRegReg name size reg1 reg2 reg3
+  = hcat [
+       char '\t',
+       ptext name,
+       pprSize size,
+       space,
+       pprReg size reg1,
+        comma,
+        pprReg size reg2,
+        comma,
+        pprReg size reg3
+    ]
+
 pprSizeAddr :: FAST_STRING -> Size -> MachRegsAddr -> SDoc
 pprSizeAddr name size op
   = hcat [
@@ -1143,6 +1219,18 @@ pprSizeAddrReg name size op dst
        pprReg size dst
     ]
 
+pprSizeRegAddr :: FAST_STRING -> Size -> Reg -> MachRegsAddr -> SDoc
+pprSizeRegAddr name size src op
+  = hcat [
+       char '\t',
+       ptext name,
+       pprSize size,
+       space,
+       pprReg size src,
+       comma,
+       pprAddr op
+    ]
+
 pprOpOp :: FAST_STRING -> Size -> Operand -> Operand -> SDoc
 pprOpOp name size op1 op2
   = hcat [
index 811a39a..e3965e8 100644 (file)
@@ -64,6 +64,7 @@ import OrdList                ( mkUnitList )
 import PrimRep         ( PrimRep(..) )
 import UniqSet         -- quite a bit of it
 import Outputable
+import PprMach         ( pprInstr )
 \end{code}
 
 %************************************************************************
@@ -379,48 +380,36 @@ regUsage instr = case instr of
     CALL imm           -> usage [] callClobberedRegs
     CLTD               -> usage [eax] [edx]
     NOP                        -> usage [] []
-    SAHF               -> usage [eax] []
-    FABS               -> usage [st0] [st0]
-    FADD sz src                -> usage (st0:opToReg src) [st0] -- allFPRegs
-    FADDP              -> usage [st0,st1] [st0] -- allFPRegs
-    FIADD sz asrc      -> usage (addrToRegs asrc) [st0]
-    FCHS               -> usage [st0] [st0]
-    FCOM sz src                -> usage (st0:opToReg src) []
-    FCOS               -> usage [st0] [st0]
-    FDIV sz src        -> usage (st0:opToReg src) [st0]
-    FDIVP              -> usage [st0,st1] [st0]
-    FDIVRP             -> usage [st0,st1] [st0]
-    FIDIV sz asrc      -> usage (addrToRegs asrc) [st0]
-    FDIVR sz src       -> usage (st0:opToReg src) [st0]
-    FIDIVR sz asrc     -> usage (addrToRegs asrc) [st0]
-    FICOM sz asrc      -> usage (addrToRegs asrc) []
-    FILD sz asrc dst   -> usage (addrToRegs asrc) [dst] -- allFPRegs
-    FIST sz adst       -> usage (st0:addrToRegs adst) []
-    FLD         sz src         -> usage (opToReg src) [st0] -- allFPRegs
-    FLD1               -> usage [] [st0] -- allFPRegs
-    FLDZ               -> usage [] [st0] -- allFPRegs
-    FMUL sz src        -> usage (st0:opToReg src) [st0]
-    FMULP              -> usage [st0,st1] [st0]
-    FIMUL sz asrc      -> usage (addrToRegs asrc) [st0]
-    FRNDINT            -> usage [st0] [st0]
-    FSIN               -> usage [st0] [st0]
-    FSQRT              -> usage [st0] [st0]
-    FST sz (OpReg r)   -> usage [st0] [r]
-    FST sz dst         -> usage (st0:opToReg dst) []
-    FSTP sz (OpReg r)  -> usage [st0] [r] -- allFPRegs
-    FSTP sz dst                -> usage (st0:opToReg dst) [] -- allFPRegs
-    FSUB sz src                -> usage (st0:opToReg src) [st0] -- allFPRegs
-    FSUBR sz src       -> usage (st0:opToReg src) [st0] -- allFPRegs
-    FISUB sz asrc      -> usage (addrToRegs asrc) [st0]
-    FSUBP              -> usage [st0,st1] [st0] -- allFPRegs
-    FSUBRP             -> usage [st0,st1] [st0] -- allFPRegs
-    FISUBR sz asrc     -> usage (addrToRegs asrc) [st0]
-    FTST               -> usage [st0] []
-    FCOMP sz op                -> usage (st0:opToReg op) [st0] -- allFPRegs
-    FUCOMPP            -> usage [st0, st1] [st0, st1] --  allFPRegs
-    FXCH               -> usage [st0, st1] [st0, st1]
-    FNSTSW             -> usage [] [eax]
-    _                  -> noUsage
+
+    GMOV src dst       -> usage [src] [dst]
+    GLD sz src dst     -> usage (addrToRegs src) [dst]
+    GST sz src dst     -> usage [src] (addrToRegs dst)
+
+    GFTOD src dst      -> usage [src] [dst]
+    GFTOI src dst      -> usage [src] [dst]
+
+    GDTOF src dst      -> usage [src] [dst]
+    GDTOI src dst      -> usage [src] [dst]
+
+    GITOF src dst      -> usage [src] [dst]
+    GITOD src dst      -> usage [src] [dst]
+
+    GADD sz s1 s2 dst  -> usage [s1,s2] [dst]
+    GSUB sz s1 s2 dst  -> usage [s1,s2] [dst]
+    GMUL sz s1 s2 dst  -> usage [s1,s2] [dst]
+    GDIV sz s1 s2 dst  -> usage [s1,s2] [dst]
+
+    GCMP sz src1 src2  -> usage [src1,src2] []
+    GABS sz src dst    -> usage [src] [dst]
+    GNEG sz src dst    -> usage [src] [dst]
+    GSQRT sz src dst   -> usage [src] [dst]
+
+    COMMENT _          -> noUsage
+    SEGMENT _          -> noUsage
+    LABEL _            -> noUsage
+    ASCII _ _          -> noUsage
+    DATA _ _           -> noUsage
+    _                  -> error ("regUsage: " ++ showSDoc (pprInstr instr)) --noUsage
  where
     usage2 :: Operand -> Operand -> RegUsage
     usage2 op (OpReg reg) = usage (opToReg op) [reg]
@@ -429,10 +418,10 @@ regUsage instr = case instr of
     usage1 :: Operand -> RegUsage
     usage1 (OpReg reg)    = usage [reg] [reg]
     usage1 (OpAddr ea)    = usage (addrToRegs ea) []
-    allFPRegs = [st0,st1,st2,st3,st4,st5,st6,st7]
+    allFPRegs = [fake0,fake1,fake2,fake3,fake4,fake5]
 
     --callClobberedRegs = [ eax, ecx, edx ] -- according to gcc, anyway.
-    callClobberedRegs = [eax]
+    callClobberedRegs = [eax,fake0,fake1,fake2,fake3,fake4,fake5]
 
 -- General purpose register collecting functions.
 
@@ -672,32 +661,39 @@ patchRegs instr env = case instr of
     POP  sz op         -> patch1 (POP  sz) op
     SETCC cond op      -> patch1 (SETCC cond) op
     JMP op             -> patch1 JMP op
-    FADD sz src                -> FADD sz (patchOp src)
-    FIADD sz asrc      -> FIADD sz (lookupAddr asrc)
-    FCOM sz src                -> patch1 (FCOM sz) src
-    FDIV sz src        -> FDIV sz (patchOp src)
-    --FDIVP sz src     -> FDIVP sz (patchOp src)
-    FIDIV sz asrc      -> FIDIV sz (lookupAddr asrc)
-    FDIVR sz src       -> FDIVR sz (patchOp src)
-    --FDIVRP sz src    -> FDIVRP sz (patchOp src)
-    FIDIVR sz asrc     -> FIDIVR sz (lookupAddr asrc)
-    FICOM sz asrc      -> FICOM sz (lookupAddr asrc)
-    FILD sz asrc dst   -> FILD sz (lookupAddr asrc) (env dst)
-    FIST sz adst       -> FIST sz (lookupAddr adst)
-    FLD        sz src          -> patch1 (FLD sz) (patchOp src)
-    FMUL sz src        -> FMUL sz (patchOp src)
-    --FMULP sz src     -> FMULP sz (patchOp src)
-    FIMUL sz asrc      -> FIMUL sz (lookupAddr asrc)
-    FST sz dst         -> FST sz (patchOp dst)
-    FSTP sz dst                -> FSTP sz (patchOp dst)
-    FSUB sz src                -> FSUB sz (patchOp src)
-    --FSUBP sz src     -> FSUBP sz (patchOp src)
-    FISUB sz asrc      -> FISUB sz (lookupAddr asrc)
-    FSUBR sz src       -> FSUBR sz (patchOp src)
-    --FSUBRP sz src    -> FSUBRP sz (patchOp src)
-    FISUBR sz asrc     -> FISUBR sz (lookupAddr asrc)
-    FCOMP sz src       -> FCOMP sz (patchOp src)
-    _                  -> instr
+
+    GMOV src dst       -> GMOV (env src) (env dst)
+    GLD sz src dst     -> GLD sz (lookupAddr src) (env dst)
+    GST sz src dst     -> GST sz (env src) (lookupAddr dst)
+
+    GFTOD src dst      -> GFTOD (env src) (env dst)
+    GFTOI src dst      -> GFTOI (env src) (env dst)
+
+    GDTOF src dst      -> GDTOF (env src) (env dst)
+    GDTOI src dst      -> GDTOI (env src) (env dst)
+
+    GITOF src dst      -> GITOF (env src) (env dst)
+    GITOD src dst      -> GITOD (env src) (env dst)
+
+    GADD sz s1 s2 dst  -> GADD sz (env s1) (env s2) (env dst)
+    GSUB sz s1 s2 dst  -> GSUB sz (env s1) (env s2) (env dst)
+    GMUL sz s1 s2 dst  -> GMUL sz (env s1) (env s2) (env dst)
+    GDIV sz s1 s2 dst  -> GDIV sz (env s1) (env s2) (env dst)
+
+    GCMP sz src1 src2  -> GCMP sz (env src1) (env src2)
+    GABS sz src dst    -> GABS sz (env src) (env dst)
+    GNEG sz src dst    -> GNEG sz (env src) (env dst)
+    GSQRT sz src dst   -> GSQRT sz (env src) (env dst)
+
+    COMMENT _          -> instr
+    SEGMENT _          -> instr
+    LABEL _            -> instr
+    ASCII _ _          -> instr
+    DATA _ _           -> instr
+    JXX _ _            -> instr
+    CALL _             -> instr
+    CLTD               -> instr
+    _                  -> error ("patchInstr: " ++ showSDoc (pprInstr instr)) --instr
   where
     patch1 insn op      = insn (patchOp op)
     patch2 insn src dst = insn (patchOp src) (patchOp dst)
@@ -765,10 +761,15 @@ patchRegs instr env = case instr of
 
 Spill to memory, and load it back...
 
+JRS, 000122: on x86, don't spill directly below the stack pointer, since 
+some insn sequences (int <-> conversions) use this as a temp location.
+Leave 16 bytes of slop.
+
 \begin{code}
 spillReg, loadReg :: Reg -> Reg -> InstrList
 
 spillReg dyn (MemoryReg i pk)
+  | i >= 0  -- JRS paranoia
   = let
        sz = primRepToSize pk
     in
@@ -777,7 +778,9 @@ spillReg dyn (MemoryReg i pk)
         IF_ARCH_alpha( ST sz dyn (spRel i)
 
        {-I386: spill below stack pointer leaving 2 words/spill-}
-       ,IF_ARCH_i386 ( MOV sz (OpReg dyn) (OpAddr (spRel (-2 * i)))
+       ,IF_ARCH_i386 ( if pk == FloatRep || pk == DoubleRep
+                        then GST sz dyn (spRel (-16 + (-2 * i)))
+                        else MOV sz (OpReg dyn) (OpAddr (spRel (-16 + (-2 * i))))
 
        {-SPARC: spill below frame pointer leaving 2 words/spill-}
        ,IF_ARCH_sparc( ST sz dyn (fpRel (-2 * i))
@@ -786,12 +789,15 @@ spillReg dyn (MemoryReg i pk)
 
 ----------------------------
 loadReg (MemoryReg i pk) dyn
+  | i >= 0  -- JRS paranoia
   = let
        sz = primRepToSize pk
     in
     mkUnitList (
         IF_ARCH_alpha( LD  sz dyn (spRel i)
-       ,IF_ARCH_i386 ( MOV sz (OpAddr (spRel (-2 * i))) (OpReg dyn)
+       ,IF_ARCH_i386 ( if   pk == FloatRep || pk == DoubleRep
+                        then GLD sz (spRel (-16 + (-2 * i))) dyn
+                        else MOV sz (OpAddr (spRel (-16 + (-2 * i)))) (OpReg dyn)
        ,IF_ARCH_sparc( LD  sz (fpRel (-2 * i)) dyn
        ,)))
     )
index c9323ec..ff5332d 100644 (file)
@@ -159,7 +159,7 @@ primCode [] WriteArrayOp [obj, ix, v]
        obj' = amodeToStix obj
        ix' = amodeToStix ix
        v' = amodeToStix v
-       base = StIndex IntRep obj' arrHS
+       base = StIndex IntRep obj' arrHS --(StInt (toInteger 3))
        assign = StAssign PtrRep (StInd PtrRep (StIndex PtrRep base ix')) v'
     in
     returnUs (\xs -> assign : xs)