[project @ 1999-02-04 13:45:24 by simonpj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachCode.lhs
index 8c2b594..0fd076d 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The AQUA Project, Glasgow University, 1996
+% (c) The AQUA Project, Glasgow University, 1996-1998
 %
 \section[MachCode]{Generating machine code}
 
@@ -9,32 +9,30 @@ This is a big module, but, if you pay attention to
 structure should not be too overwhelming.
 
 \begin{code}
+module MachCode ( stmt2Instrs, asmVoid, InstrList ) where
+
 #include "HsVersions.h"
 #include "nativeGen/NCG.h"
 
-module MachCode ( stmt2Instrs, asmVoid, SYN_IE(InstrList) ) where
-
-IMP_Ubiq(){-uitious-}
-
 import MachMisc                -- may differ per-platform
 import MachRegs
 
 import AbsCSyn         ( MagicId )
 import AbsCUtils       ( magicIdPrimRep )
+import CallConv                ( CallConv )
 import CLabel          ( isAsmTemp, CLabel )
 import Maybes          ( maybeToBool, expectJust )
 import OrdList         -- quite a bit of it
-import Outputable      ( PprStyle(..) )
-import Pretty          ( ptext, rational )
 import PrimRep         ( isFloatingRep, PrimRep(..) )
-import PrimOp          ( PrimOp(..), showPrimOp )
+import PrimOp          ( PrimOp(..) )
+import CallConv                ( cCallConv )
 import Stix            ( getUniqLabelNCG, StixTree(..),
                          StixReg(..), CodeSegment(..)
                        )
 import UniqSupply      ( returnUs, thenUs, mapUs, mapAndUnzipUs,
-                         mapAccumLUs, SYN_IE(UniqSM)
+                         mapAccumLUs, UniqSM
                        )
-import Util            ( panic, assertPanic )
+import Outputable
 \end{code}
 
 Code extractor for an entire stix tree---stix statement level.
@@ -51,7 +49,7 @@ stmt2Instrs stmt = case stmt of
 
     StJump arg            -> genJump arg
     StCondJump lab arg    -> genCondJump lab arg
-    StCall fn VoidRep args -> genCCall fn VoidRep args
+    StCall fn cconv VoidRep args -> genCCall fn cconv VoidRep args
 
     StAssign pk dst src
       | isFloatingRep pk -> assignFltCode pk dst src
@@ -80,6 +78,9 @@ stmt2Instrs stmt = case stmt of
            returnUs (mkSeqInstrs [LABEL lbl,
                                   ASCII True (_UNPK_ s)],
                                   ImmCLbl lbl)
+       -- the linker can handle simple arithmetic...
+       getData (StIndex rep (StCLbl lbl) (StInt off)) =
+               returnUs (id, ImmIndex lbl (fromInteger (off * sizeOf rep)))
 \end{code}
 
 %************************************************************************
@@ -160,6 +161,9 @@ maybeImm (StLitLbl s) = Just (ImmLab s)
 maybeImm (StLitLit s) = Just (strImmLit (cvtLitLit (_UNPK_ s)))
 maybeImm (StCLbl   l) = Just (ImmCLbl l)
 
+maybeImm (StIndex rep (StCLbl l) (StInt off)) = 
+       Just (ImmIndex l (fromInteger (off * sizeOf rep)))
+
 maybeImm (StInt i)
   | i >= toInteger minInt && i <= toInteger maxInt
   = Just (ImmInt (fromInteger i))
@@ -216,8 +220,8 @@ getRegister (StReg (StixTemp u pk))
 
 getRegister tree@(StIndex _ _ _) = getRegister (mangleIndexTree tree)
 
-getRegister (StCall fn kind args)
-  = genCCall fn kind args          `thenUs` \ call ->
+getRegister (StCall fn cconv kind args)
+  = genCCall fn cconv kind args            `thenUs` \ call ->
     returnUs (Fixed kind reg call)
   where
     reg = if isFloatingRep kind
@@ -312,7 +316,7 @@ getRegister (StPrim primop [x]) -- unary PrimOps
       Double2FloatOp -> coerceFltCode x
       Float2DoubleOp -> coerceFltCode x
 
-      other_op -> getRegister (StCall fn DoubleRep [x])
+      other_op -> getRegister (StCall fn cCallConv DoubleRep [x])
        where
          fn = case other_op of
                 FloatExpOp    -> SLIT("exp")
@@ -392,6 +396,9 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       IntQuotOp -> trivialCode (DIV Q False) x y
       IntRemOp  -> trivialCode (REM Q False) x y
 
+      WordQuotOp -> trivialCode (DIV Q True) x y
+      WordRemOp  -> trivialCode (REM Q True) x y
+
       FloatAddOp -> trivialFCode  FloatRep (FADD TF) x y
       FloatSubOp -> trivialFCode  FloatRep (FSUB TF) x y
       FloatMulOp -> trivialFCode  FloatRep (FMUL TF) x y
@@ -406,15 +413,14 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       OrOp   -> trivialCode OR  x y
       XorOp  -> trivialCode XOR x y
       SllOp  -> trivialCode SLL x y
-      SraOp  -> trivialCode SRA x y
       SrlOp  -> trivialCode SRL x y
 
-      ISllOp -> panic "AlphaGen:isll"
-      ISraOp -> panic "AlphaGen:isra"
-      ISrlOp -> panic "AlphaGen:isrl"
+      ISllOp -> trivialCode SLL x y -- was: panic "AlphaGen:isll"
+      ISraOp -> trivialCode SRA x y -- was: panic "AlphaGen:isra"
+      ISrlOp -> trivialCode SRL x y -- was: panic "AlphaGen:isrl"
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") DoubleRep [x,y])
-      DoublePowerOp -> getRegister (StCall SLIT("pow") DoubleRep [x,y])
+      FloatPowerOp  -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [x,y])
+      DoublePowerOp -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [x,y])
   where
     {- ------------------------------------------------------------
        Some bizarre special code for getting condition codes into
@@ -502,8 +508,6 @@ getRegister leaf
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
-getRegister (StReg (StixTemp u pk)) = returnUs (Fixed pk (UnmappedReg u pk) id)
-
 getRegister (StDouble 0.0)
   = let
        code dst = mkSeqInstrs [FLDZ]
@@ -559,7 +563,7 @@ getRegister (StPrim primop [x]) -- unary PrimOps
                          then StPrim Float2DoubleOp [x]
                          else x
        in
-       getRegister (StCall fn DoubleRep [x])
+       getRegister (StCall fn cCallConv DoubleRep [x])
        where
        (is_float_op, fn)
          = case primop of
@@ -671,17 +675,15 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
        -}
           
       SllOp -> shift_code (SHL L) x y {-False-}
-      SraOp -> shift_code (SAR L) x y {-False-}
       SrlOp -> shift_code (SHR L) x y {-False-}
 
-      {- ToDo: nuke? -}
-      ISllOp -> panic "I386Gen:isll"
-      ISraOp -> panic "I386Gen:isra"
-      ISrlOp -> panic "I386Gen:isrl"
+      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"
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") 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") DoubleRep [x, y])
+      DoublePowerOp -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [x, y])
   where
     shift_code :: (Operand -> Operand -> Instr)
               -> StixTree
@@ -752,7 +754,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            src1 = registerName register tmp
            src2 = ImmInt (fromInteger y)
            code__2 dst = code .
-                         mkSeqInstr (LEA sz (OpAddr (Address (Just src1) Nothing src2)) (OpReg dst))
+                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2)) (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
@@ -809,7 +811,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            code2 = registerCode register2 tmp2 asmVoid
            src2  = registerName register2 tmp2
            code__2 dst = asmParThen [code1, code2] .
-                         mkSeqInstr (LEA sz (OpAddr (Address (Just src1) (Just (src2,1)) (ImmInt 0))) (OpReg dst))
+                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) (Just (src2,1)) (ImmInt 0))) (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
@@ -824,7 +826,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
            src1 = registerName register tmp
            src2 = ImmInt (-(fromInteger y))
            code__2 dst = code .
-                         mkSeqInstr (LEA sz (OpAddr (Address (Just src1) Nothing src2)) (OpReg dst))
+                         mkSeqInstr (LEA sz (OpAddr (AddrBaseIndex (Just src1) Nothing src2)) (OpReg dst))
        in
        returnUs (Any IntRep code__2)
 
@@ -867,10 +869,10 @@ 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 (Address (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 (Address (Just ebx) Nothing (ImmInt OFFSET_R1)))]
+                                  IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)))]
        in
        returnUs (Fixed IntRep (if is_division then eax else edx) code__2)
 
@@ -890,10 +892,10 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
                                         CLTD,
                                         IDIV sz (OpReg src2)]
                      else mkSeqInstrs [ -- we put src2 in (ebx)
-                                        MOV L (OpReg src2) (OpAddr (Address (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 (Address (Just ebx) Nothing (ImmInt OFFSET_R1)))]
+                                        IDIV sz (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)))]
        in
        returnUs (Fixed IntRep (if is_division then eax else edx) code__2)
        -----------------------
@@ -973,7 +975,7 @@ getRegister (StPrim primop [x]) -- unary PrimOps
                          then StPrim Float2DoubleOp [x]
                          else x
        in
-       getRegister (StCall fn DoubleRep [x])
+       getRegister (StCall fn cCallConv DoubleRep [x])
        where
        (is_float_op, fn)
          = case primop of
@@ -1008,7 +1010,7 @@ getRegister (StPrim primop [x]) -- unary PrimOps
              DoubleSinhOp  -> (False, SLIT("sinh"))
              DoubleCoshOp  -> (False, SLIT("cosh"))
              DoubleTanhOp  -> (False, SLIT("tanh"))
-             _             -> panic ("Monadic PrimOp not handled: " ++ showPrimOp PprDebug primop)
+             _             -> panic ("Monadic PrimOp not handled: " ++ show primop)
 
 getRegister (StPrim primop [x, y]) -- dyadic PrimOps
   = case primop of
@@ -1076,18 +1078,18 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       OrOp  -> trivialCode (OR  False) x y
       XorOp -> trivialCode (XOR False) x y
       SllOp -> trivialCode SLL x y
-      SraOp -> trivialCode SRA x y
       SrlOp -> trivialCode SRL x y
 
-      ISllOp -> panic "SparcGen:isll"
-      ISraOp -> panic "SparcGen:isra"
-      ISrlOp -> panic "SparcGen:isrl"
+      ISllOp -> trivialCode SLL x y  --was: panic "SparcGen:isll"
+      ISraOp -> trivialCode SRA x y  --was: panic "SparcGen:isra"
+      ISrlOp -> trivialCode SRL x y  --was: panic "SparcGen:isrl"
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") 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") DoubleRep [x, y])
+      DoublePowerOp -> getRegister (StCall SLIT("pow") cCallConv DoubleRep [x, y])
+--      _ -> panic "Prim op " ++ (showPrimOp primop) ++ " not handled!"
   where
-    imul_div fn x y = getRegister (StCall fn IntRep [x, y])
+    imul_div fn x y = getRegister (StCall fn cCallConv IntRep [x, y])
 
 getRegister (StInd pk mem)
   = getAmode mem                   `thenUs` \ amode ->
@@ -1130,7 +1132,7 @@ getRegister leaf
 
 @Amode@s: Memory addressing modes passed up the tree.
 \begin{code}
-data Amode = Amode Address InstrBlock
+data Amode = Amode MachRegsAddr InstrBlock
 
 amodeAddr (Amode addr _) = addr
 amodeCode (Amode _ code) = code
@@ -1194,7 +1196,7 @@ getAmode (StPrim IntSubOp [x, StInt i])
        reg  = registerName register tmp
        off  = ImmInt (-(fromInteger i))
     in
-    returnUs (Amode (Address (Just reg) Nothing off) code)
+    returnUs (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
 getAmode (StPrim IntAddOp [x, StInt i])
   | maybeToBool imm
@@ -1214,7 +1216,7 @@ getAmode (StPrim IntAddOp [x, StInt i])
        reg  = registerName register tmp
        off  = ImmInt (fromInteger i)
     in
-    returnUs (Amode (Address (Just reg) Nothing off) code)
+    returnUs (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
 getAmode (StPrim IntAddOp [x, y])
   = getNewRegNCG PtrRep                `thenUs` \ tmp1 ->
@@ -1228,7 +1230,7 @@ getAmode (StPrim IntAddOp [x, y])
        reg2  = registerName register2 tmp2
        code__2 = asmParThen [code1, code2]
     in
-    returnUs (Amode (Address (Just reg1) (Just (reg2,4)) (ImmInt 0)) code__2)
+    returnUs (Amode (AddrBaseIndex (Just reg1) (Just (reg2,4)) (ImmInt 0)) code__2)
 
 getAmode leaf
   | maybeToBool imm
@@ -1248,7 +1250,7 @@ getAmode other
        reg  = registerName register tmp
        off  = Nothing
     in
-    returnUs (Amode (Address (Just reg) Nothing (ImmInt 0)) code)
+    returnUs (Amode (AddrBaseIndex (Just reg) Nothing (ImmInt 0)) code)
 
 #endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2236,13 +2238,14 @@ register allocator.
 \begin{code}
 genCCall
     :: FAST_STRING     -- function to call
+    -> CallConv
     -> PrimRep         -- type of the result
     -> [StixTree]      -- arguments (of mixed type)
     -> UniqSM InstrBlock
 
 #if alpha_TARGET_ARCH
 
-genCCall fn kind args
+genCCall fn cconv kind args
   = mapAccumLUs get_arg (allArgRegs, eXTRA_STK_ARGS_HERE) args
                                    `thenUs` \ ((unused,_), argCode) ->
     let
@@ -2310,7 +2313,7 @@ genCCall fn kind args
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
-genCCall fn kind [StInt i]
+genCCall fn cconv kind [StInt i]
   | fn == SLIT ("PerformGC_wrapper")
   = let
      call = [MOV L (OpImm (ImmInt (fromInteger i))) (OpReg eax),
@@ -2324,22 +2327,23 @@ genCCall fn kind [StInt i]
        call = [MOV L (OpImm (ImmInt (fromInteger i))) (OpReg eax),
                MOV L (OpImm (ImmCLbl lbl))
                      -- this is hardwired
-                     (OpAddr (Address (Just ebx) Nothing (ImmInt 104))),
+                     (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt 104))),
                JMP (OpImm (ImmLit (ptext (if underscorePrefix then (SLIT ("_PerformGC_wrapper")) else (SLIT ("PerformGC_wrapper")))))),
                LABEL lbl]
     in
     returnInstrs call
 -}
 
-genCCall fn kind args
+genCCall fn cconv kind args
   = mapUs get_call_arg args `thenUs` \ argCode ->
     let
        nargs = length args
+
 {- OLD: Since there's no attempt at stealing %esp at the moment, 
    restoring %esp from MainRegTable.rCstkptr is not done.  -- SOF 97/09
    (ditto for saving away old-esp in MainRegTable.Hp (!!) )
-       code1 = asmParThen [asmSeq [ -- MOV L (OpReg esp) (OpAddr (Address (Just ebx) Nothing (ImmInt 80))),
-                       MOV L (OpAddr (Address (Just ebx) Nothing (ImmInt 100))) (OpReg esp)
+       code1 = asmParThen [asmSeq [ -- MOV L (OpReg esp) (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt 80))),
+                       MOV L (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt 100))) (OpReg esp)
                                   ]
                           ]
 -}
@@ -2349,7 +2353,7 @@ genCCall fn kind args
                ADD L (OpImm (ImmInt (nargs * 4))) (OpReg esp) --,
                
                -- Don't restore %esp (see above)
-               -- MOV L (OpAddr (Address (Just ebx) Nothing (ImmInt 80))) (OpReg esp)
+               -- MOV L (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt 80))) (OpReg esp)
                ]
     in
     returnSeq (code2) call
@@ -2402,7 +2406,7 @@ genCCall fn kind args
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if sparc_TARGET_ARCH
 
-genCCall fn kind args
+genCCall fn cconv kind args
   = mapAccumLUs get_arg (allArgRegs, eXTRA_STK_ARGS_HERE) args
                                    `thenUs` \ ((unused,_), argCode) ->
     let
@@ -3146,8 +3150,8 @@ coerceInt2FP pk x
 
        code__2 dst = code . mkSeqInstrs [
        -- to fix: should spill instead of using R1
-                     MOV L (OpReg src) (OpAddr (Address (Just ebx) Nothing (ImmInt OFFSET_R1))),
-                     FILD (primRepToSize pk) (Address (Just ebx) Nothing (ImmInt OFFSET_R1)) dst]
+                     MOV L (OpReg src) (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))),
+                     FILD (primRepToSize pk) (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)) dst]
     in
     returnUs (Any pk code__2)
 
@@ -3160,11 +3164,10 @@ coerceFP2Int x
        src  = registerName register tmp
        pk   = registerRep register
 
-       code__2 dst = let
-                     in code . mkSeqInstrs [
+       code__2 dst = code . mkSeqInstrs [
                                FRNDINT,
-                               FIST L (Address (Just ebx) Nothing (ImmInt OFFSET_R1)),
-                               MOV L (OpAddr (Address (Just ebx) Nothing (ImmInt OFFSET_R1))) (OpReg dst)]
+                               FIST L (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1)),
+                               MOV L (OpAddr (AddrBaseIndex (Just ebx) Nothing (ImmInt OFFSET_R1))) (OpReg dst)]
     in
     returnUs (Any IntRep code__2)