[project @ 2004-08-13 10:45:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachCode.lhs
index e9fbdf4..2876efd 100644 (file)
@@ -14,7 +14,6 @@ module MachCode ( stmtsToInstrs, InstrBlock ) where
 #include "HsVersions.h"
 #include "nativeGen/NCG.h"
 
-import Unique          ( Unique )
 import MachMisc                -- may differ per-platform
 import MachRegs
 import OrdList         ( OrdList, nilOL, isNilOL, unitOL, appOL, toOL,
@@ -37,11 +36,10 @@ import Stix         ( getNatLabelNCG, StixStmt(..), StixExpr(..),
                          StixReg(..), pprStixReg, StixVReg(..), CodeSegment(..), 
                           DestInfo, hasDestInfo,
                           pprStixExpr, repOfStixExpr,
-                          liftStrings,
                           NatM, thenNat, returnNat, mapNat, 
                           mapAndUnzipNat, mapAccumLNat,
-                          getDeltaNat, setDeltaNat, getUniqueNat,
-                         IF_OS_darwin(addImportNat COMMA,)
+                          getDeltaNat, setDeltaNat, 
+                         IF_ARCH_powerpc(addImportNat COMMA,)
                           ncgPrimopMoan,
                          ncg_target_is_32bit
                        )
@@ -51,6 +49,8 @@ import qualified Outputable
 import CmdLineOpts     ( opt_Static )
 import Stix            ( pprStixStmt )
 
+import Maybe           ( fromMaybe )
+
 -- DEBUGGING ONLY
 import Outputable      ( assertPanic )
 import FastString
@@ -344,7 +344,7 @@ iselExpr64 (StCall fn cconv kind args)
 iselExpr64 expr
    = pprPanic "iselExpr64(i386)" (pprStixExpr expr)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -436,7 +436,7 @@ iselExpr64 (StCall fn cconv kind args)
 iselExpr64 expr
    = pprPanic "iselExpr64(sparc)" (pprStixExpr expr)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 #if powerpc_TARGET_ARCH
@@ -524,7 +524,7 @@ iselExpr64 (StCall fn cconv kind args)
 iselExpr64 expr
    = pprPanic "iselExpr64(powerpc)" (pprStixExpr expr)
 
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -889,7 +889,7 @@ getRegister leaf
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1303,7 +1303,7 @@ getRegister leaf
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1559,7 +1559,7 @@ getRegister leaf
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 getRegister (StMachOp mop [x]) -- unary MachOps
@@ -1595,8 +1595,10 @@ getRegister (StMachOp mop [x]) -- unary MachOps
       MO_16S_to_NatS  -> integerExtend True  16 x
       MO_8U_to_32U    -> integerExtend False 24 x
 
-      other -> pprPanic "getRegister(powerpc) - unary StMachOp" 
-                                (pprMachOp mop)
+      MO_Flt_Neg      -> trivialUFCode FloatRep FNEG x
+      MO_Dbl_Neg      -> trivialUFCode FloatRep FNEG x
+
+      other_op -> getRegister (StCall (Left fn) CCallConv DoubleRep [x])
     where
         integerExtend signed nBits x
            = getRegister (
@@ -1607,6 +1609,44 @@ getRegister (StMachOp mop [x]) -- unary MachOps
             = getRegister expr         `thenNat` \ e_code ->
               returnNat (swizzleRegisterRep e_code new_rep)
 
+       (is_float_op, fn)
+         = case mop of
+             MO_Flt_Exp    -> (True,  FSLIT("exp"))
+             MO_Flt_Log    -> (True,  FSLIT("log"))
+             MO_Flt_Sqrt   -> (True,  FSLIT("sqrt"))
+
+             MO_Flt_Sin    -> (True,  FSLIT("sin"))
+             MO_Flt_Cos    -> (True,  FSLIT("cos"))
+             MO_Flt_Tan    -> (True,  FSLIT("tan"))
+
+             MO_Flt_Asin   -> (True,  FSLIT("asin"))
+             MO_Flt_Acos   -> (True,  FSLIT("acos"))
+             MO_Flt_Atan   -> (True,  FSLIT("atan"))
+
+             MO_Flt_Sinh   -> (True,  FSLIT("sinh"))
+             MO_Flt_Cosh   -> (True,  FSLIT("cosh"))
+             MO_Flt_Tanh   -> (True,  FSLIT("tanh"))
+
+             MO_Dbl_Exp    -> (False, FSLIT("exp"))
+             MO_Dbl_Log    -> (False, FSLIT("log"))
+             MO_Dbl_Sqrt   -> (False, FSLIT("sqrt"))
+
+             MO_Dbl_Sin    -> (False, FSLIT("sin"))
+             MO_Dbl_Cos    -> (False, FSLIT("cos"))
+             MO_Dbl_Tan    -> (False, FSLIT("tan"))
+
+             MO_Dbl_Asin   -> (False, FSLIT("asin"))
+             MO_Dbl_Acos   -> (False, FSLIT("acos"))
+             MO_Dbl_Atan   -> (False, FSLIT("atan"))
+
+             MO_Dbl_Sinh   -> (False, FSLIT("sinh"))
+             MO_Dbl_Cosh   -> (False, FSLIT("cosh"))
+             MO_Dbl_Tanh   -> (False, FSLIT("tanh"))
+             
+             other -> pprPanic "getRegister(powerpc) - unary StMachOp" 
+                                (pprMachOp mop)
+
+
 getRegister (StMachOp mop [x, y]) -- dyadic PrimOps
   = case mop of
       MO_32U_Gt  -> condIntReg GTT x y
@@ -1644,14 +1684,23 @@ getRegister (StMachOp mop [x, y]) -- dyadic PrimOps
       MO_Dbl_Le -> condFltReg LE x y
 
       MO_Nat_Add -> trivialCode ADD x y
-      MO_Nat_Sub -> trivialCode SUBF y x
+      MO_Nat_Sub -> fromMaybe (trivialCode2 SUBF y x) $
+        case y of    -- subfi ('substract from' with immediate) doesn't exist
+          StInt imm -> if fits16Bits imm && imm /= (-32768)
+            then Just $ trivialCode ADD x (StInt (-imm))
+            else Nothing
+          _ -> Nothing
 
       MO_NatS_Mul -> trivialCode MULLW x y
       MO_NatU_Mul -> trivialCode MULLW x y
+      -- MO_NatS_MulMayOflo -> 
 
       MO_NatS_Quot -> trivialCode2 DIVW x y
       MO_NatU_Quot -> trivialCode2 DIVWU x y
       
+      MO_NatS_Rem  -> remainderCode DIVW x y
+      MO_NatU_Rem  -> remainderCode DIVWU x y
+      
       MO_Nat_And   -> trivialCode AND x y
       MO_Nat_Or    -> trivialCode OR x y
       MO_Nat_Xor   -> trivialCode XOR x y
@@ -1659,17 +1708,7 @@ getRegister (StMachOp mop [x, y]) -- dyadic PrimOps
       MO_Nat_Shl   -> trivialCode SLW x y
       MO_Nat_Shr   -> trivialCode SRW x y
       MO_Nat_Sar   -> trivialCode SRAW x y
-
-     {-  MO_NatS_Mul  -> trivialCode (SMUL False) x y
-      MO_NatU_Mul  -> trivialCode (UMUL False) x y
-      MO_NatS_MulMayOflo -> imulMayOflo x y
-                           imulMayOflo
-     -- ToDo: teach about V8+ SPARC div instructions
-      MO_NatS_Quot -> idiv FSLIT(".div")  x y
-      MO_NatS_Rem  -> idiv FSLIT(".rem")  x y
-      MO_NatU_Quot -> idiv FSLIT(".udiv")  x y
-      MO_NatU_Rem  -> idiv FSLIT(".urem")  x y -}
-
+                           
       MO_Flt_Add   -> trivialFCode FloatRep  FADD x y
       MO_Flt_Sub   -> trivialFCode FloatRep  FSUB x y
       MO_Flt_Mul   -> trivialFCode FloatRep  FMUL x y
@@ -1679,13 +1718,12 @@ getRegister (StMachOp mop [x, y]) -- dyadic PrimOps
       MO_Dbl_Sub   -> trivialFCode DoubleRep FSUB x y
       MO_Dbl_Mul   -> trivialFCode DoubleRep FMUL x y
       MO_Dbl_Div   -> trivialFCode DoubleRep FDIV x y
-{-
+
       MO_Flt_Pwr  -> getRegister (StCall (Left FSLIT("pow")) CCallConv DoubleRep 
-                                         [promote x, promote y])
-                      where promote x = StMachOp MO_Flt_to_Dbl [x]
+                                         [x, y])
       MO_Dbl_Pwr -> getRegister (StCall (Left FSLIT("pow")) CCallConv DoubleRep 
                                         [x, y])
-       -}
+       
       other -> pprPanic "getRegister(powerpc) - binary StMachOp (1)" (pprMachOp mop)
 
 getRegister (StInd pk mem)
@@ -1745,7 +1783,7 @@ getRegister leaf
   where
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1828,7 +1866,7 @@ getAmode other
     in
     returnNat (Amode (AddrReg reg) code)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1896,7 +1934,7 @@ getAmode other
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing (ImmInt 0)) code)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1960,7 +1998,7 @@ getAmode other
     in
     returnNat (Amode (AddrRegImm reg off) code)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #ifdef powerpc_TARGET_ARCH
 getAmode (StMachOp MO_Nat_Sub [x, StInt i])
@@ -2006,7 +2044,7 @@ getAmode other
        off  = ImmInt 0
     in
     returnNat (Amode (AddrRegImm reg off) code)
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -2035,7 +2073,7 @@ getCondCode :: StixExpr -> NatM CondCode
 
 #if alpha_TARGET_ARCH
 getCondCode = panic "MachCode.getCondCode: not on Alphas"
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2082,7 +2120,7 @@ getCondCode (StMachOp mop [x, y])
 
 getCondCode other =  pprPanic "getCondCode(2)(x86,sparc,powerpc)" (pprStixExpr other)
 
-#endif {- i386_TARGET_ARCH || sparc_TARGET_ARCH || powerpc_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH || sparc_TARGET_ARCH || powerpc_TARGET_ARCH */
 
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2099,7 +2137,7 @@ condIntCode, condFltCode :: Cond -> StixExpr -> StixExpr -> NatM CondCode
 #if alpha_TARGET_ARCH
 condIntCode = panic "MachCode.condIntCode: not on Alphas"
 condFltCode = panic "MachCode.condFltCode: not on Alphas"
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
@@ -2245,7 +2283,7 @@ condFltCode cond x y
     -- and true.  Hence we always supply EQQ as the condition to test.
     returnNat (CondCode True EQQ code__2)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2311,7 +2349,7 @@ condFltCode cond x y
     in
     returnNat (CondCode True cond code__2)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 
@@ -2360,7 +2398,7 @@ condFltCode cond x y
     in
     returnNat (CondCode False cond code__2)
 
-#endif {- powerpc_TARGET_ARCH -} 
+#endif /* powerpc_TARGET_ARCH */
 
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2418,7 +2456,7 @@ assignIntCode pk dst src
     in
     returnNat code__2
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2506,7 +2544,7 @@ assignReg_IntCode pk reg src
     in
     returnNat code
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2540,7 +2578,7 @@ assignReg_IntCode pk reg src
     in
     returnNat code__2
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 
@@ -2571,7 +2609,7 @@ assignReg_IntCode pk reg src
     in
     returnNat code__2
 
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -2611,7 +2649,7 @@ assignFltCode pk dst src
     in
     returnNat code__2
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2656,7 +2694,7 @@ assignReg_FltCode pk reg src
     returnNat code
 
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2711,7 +2749,7 @@ assignReg_FltCode pk reg src
     in
     returnNat code__2
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 
@@ -2729,15 +2767,8 @@ assignMem_FltCode pk addr src
 
        src__2  = registerName register tmp1
        pk__2   = registerRep register
-       sz__2   = primRepToSize pk__2
 
-       code__2 = if pk__2 == DoubleRep || pk == pk__2
-           then code1 `appOL` code2 `snocOL` ST sz src__2 dst__2
-           else panic "###PPC MachCode.assignMem_FltCode: FloatRep"
-       {- code__2 = code1 `appOL` code2 `appOL`
-           if   pk == pk__2 
-            then unitOL (ST sz src__2 dst__2)
-           else toOL [FxTOy sz__2 sz src__2 tmp1, ST sz tmp1 dst__2] -}
+       code__2 = code1 `appOL` code2 `snocOL` ST sz src__2 dst__2
     in
     returnNat code__2
 
@@ -2756,7 +2787,7 @@ assignReg_FltCode pk reg src
                else c_src
     in
     returnNat code
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -2801,7 +2832,7 @@ genJump tree
     else
     returnNat (code . mkSeqInstr (JMP zeroh (AddrReg pv) 0))
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2831,7 +2862,7 @@ genJump dsts tree
     imm    = maybeImm tree
     target = case imm of Just x -> x
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -2853,11 +2884,12 @@ genJump dsts tree
     in
     returnNat (code `snocOL` JMP dsts (AddrRegReg target g0) `snocOL` NOP)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 genJump dsts (StCLbl lbl)
-    = returnNat (toOL [BCC ALWAYS lbl])
+  | hasDestInfo dsts = panic "genJump(powerpc): CLbl and dsts"
+  | otherwise        = returnNat (toOL [BCC ALWAYS lbl])
 
 genJump dsts tree
   = getRegister tree                       `thenNat` \ register ->
@@ -2866,8 +2898,8 @@ genJump dsts tree
        code   = registerCode register tmp
        target = registerName register tmp
     in
-    returnNat (code `snocOL` MTCTR target `snocOL` BCTR)
-#endif {- sparc_TARGET_ARCH -}
+    returnNat (code `snocOL` MTCTR target `snocOL` BCTR dsts)
+#endif /* sparc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3048,7 +3080,7 @@ genCondJump lbl (StPrim op [x, y])
        AddrLtOp -> (CMP ULT, NE)
        AddrLeOp -> (CMP ULE, NE)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3062,7 +3094,7 @@ genCondJump lbl bool
     in
     returnNat (code `snocOL` JXX cond lbl)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3084,7 +3116,7 @@ genCondJump lbl bool
        )
     )
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 
@@ -3098,7 +3130,7 @@ genCondJump lbl bool
     returnNat (
        code `snocOL` BCC cond lbl    )
 
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3194,7 +3226,7 @@ genCCall fn cconv kind args
        in
        returnNat (([], offset + 1), code . mkSeqInstr (ST sz src (spRel offset)))
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3306,7 +3338,7 @@ genCCall fn cconv ret_rep args
        in
        returnNat (code, reg, sz)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3447,11 +3479,13 @@ genCCall fn cconv kind args
                    , 
                    [v1]
                 )
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
+
+#if darwin_TARGET_OS
 {-
-    The PowerPC calling convention (at least for Darwin/Mac OS X)
+    The PowerPC calling convention for Darwin/Mac OS X
     is described in Apple's document
     "Inside Mac OS X - Mach-O Runtime Architecture".
     Parameters may be passed in general-purpose registers, in
@@ -3558,7 +3592,124 @@ genCCall fn cconv kind args
                    `snocOL` storeWord vr_hi gprs stackOffset
                    `snocOL` storeWord vr_lo (drop 1 gprs) (stackOffset+4))
                ((take 2 gprs) ++ accumUsed)
-#endif {- powerpc_TARGET_ARCH -}
+#else
+
+{-
+    PowerPC Linux uses the System V Release 4 Calling Convention
+    for PowerPC. It is described in the
+    "System V Application Binary Interface PowerPC Processor Supplement".
+    
+    Like the Darwin/Mac OS X code above, this allocates a new stack frame
+    so that the parameter area doesn't conflict with the spill slots.
+-}
+
+genCCall fn cconv kind args
+  = mapNat prepArg args `thenNat` \ preppedArgs ->
+    let
+       (argReps,argCodes,vregs) = unzip3 preppedArgs
+
+           -- size of linkage area + size of arguments, in bytes
+       stackDelta = roundTo16 finalStack
+       roundTo16 x | x `mod` 16 == 0 = x
+                   | otherwise = x + 16 - (x `mod` 16)
+
+       move_sp_down = toOL [STU W sp (AddrRegImm sp (ImmInt (-stackDelta))), DELTA (-stackDelta)]
+       move_sp_up = toOL [ADD sp sp (RIImm (ImmInt stackDelta)), DELTA 0]
+
+       (moveFinalCode,usedRegs,finalStack) =
+            move_final (zip vregs argReps)
+                      allArgRegs allFPArgRegs
+                      eXTRA_STK_ARGS_HERE
+                      (toOL []) []
+
+       passArguments = concatOL argCodes
+           `appOL` move_sp_down
+           `appOL` moveFinalCode
+    in 
+       case fn of
+           Left lbl ->
+               addImportNat lbl                        `thenNat` \ _ ->
+               returnNat (passArguments
+                           `snocOL`    BL (ImmLit $ ftext  lbl)
+                                          usedRegs
+                           `appOL`     move_sp_up)
+           Right dyn ->
+               getRegister dyn                         `thenNat` \ dynReg ->
+               getNewRegNCG (registerRep dynReg)       `thenNat` \ tmp ->
+               returnNat (registerCode dynReg tmp
+                           `appOL`     passArguments
+                           `snocOL`    MTCTR (registerName dynReg tmp)
+                           `snocOL`    BCTRL usedRegs
+                           `appOL`     move_sp_up)
+    where
+    prepArg arg
+        | is64BitRep (repOfStixExpr arg)
+        = iselExpr64 arg               `thenNat` \ (ChildCode64 code vr_lo) ->
+          let r_lo = VirtualRegI vr_lo
+              r_hi = getHiVRegFromLo r_lo
+          in  returnNat (repOfStixExpr arg, code, Right (r_hi,r_lo))
+       | otherwise
+       = getRegister arg                       `thenNat` \ register ->
+         getNewRegNCG (registerRep register)   `thenNat` \ tmp ->
+         returnNat (registerRep register, registerCode register tmp, Left (registerName register tmp))
+    move_final [] _ _ stackOffset accumCode accumUsed = (accumCode, accumUsed, stackOffset)
+    move_final ((Left vr,rep):vregs) gprs fprs stackOffset accumCode accumUsed
+       | not (is64BitRep rep) =
+       case rep of
+           FloatRep ->
+                case fprs of
+                    fpr : fprs' -> move_final vregs gprs fprs' stackOffset
+                                              (accumCode `snocOL` MR fpr vr)
+                                              (fpr : accumUsed)
+                    [] -> move_final vregs gprs fprs (stackOffset+4)
+                                     (accumCode `snocOL`
+                                        ST F vr (AddrRegImm sp (ImmInt stackOffset)))
+                                     accumUsed
+           DoubleRep ->
+                case fprs of
+                    fpr : fprs' -> move_final vregs gprs fprs' stackOffset
+                                              (accumCode `snocOL` MR fpr vr)
+                                              (fpr : accumUsed)
+                    [] -> move_final vregs gprs fprs (stackOffset+8)
+                                     (accumCode `snocOL`
+                                        ST DF vr (AddrRegImm sp (ImmInt stackOffset)))
+                                     accumUsed
+           VoidRep -> panic "MachCode.genCCall(powerpc): void parameter"
+           _ ->
+                case gprs of
+                    gpr : gprs' -> move_final vregs gprs' fprs stackOffset
+                                              (accumCode `snocOL` MR gpr vr)
+                                              (gpr : accumUsed)
+                    [] -> move_final vregs gprs fprs (stackOffset+4)
+                                     (accumCode `snocOL`
+                                        ST W vr (AddrRegImm sp (ImmInt stackOffset)))
+                                     accumUsed
+               
+    move_final ((Right (vr_hi,vr_lo),rep):vregs) gprs fprs stackOffset accumCode accumUsed
+       | is64BitRep rep =
+            case gprs of
+                hireg : loreg : regs | even (length gprs) ->
+                    move_final vregs regs fprs stackOffset
+                               (regCode hireg loreg) accumUsed
+                _skipped : hireg : loreg : regs ->
+                    move_final vregs regs fprs stackOffset
+                               (regCode hireg loreg) accumUsed
+                _ -> -- only one or no regs left
+                    move_final vregs [] fprs (stackOffset+8)
+                               stackCode accumUsed
+       where
+            stackCode =
+                accumCode
+                    `snocOL` ST W vr_hi (AddrRegImm sp (ImmInt stackOffset))
+                    `snocOL` ST W vr_lo (AddrRegImm sp (ImmInt (stackOffset+4)))
+            regCode hireg loreg =
+                accumCode
+                    `snocOL` MR hireg vr_hi
+                    `snocOL` MR loreg vr_lo
+
+#endif                
+                
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -3589,7 +3740,7 @@ condIntReg, condFltReg :: Cond -> StixExpr -> StixExpr -> NatM Register
 #if alpha_TARGET_ARCH
 condIntReg = panic "MachCode.condIntReg (not on Alpha)"
 condFltReg = panic "MachCode.condFltReg (not on Alpha)"
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3625,7 +3776,7 @@ condFltReg cond x y
     in
     returnNat (Any IntRep code__2)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -3724,7 +3875,7 @@ condFltReg cond x y
     in
     returnNat (Any IntRep code__2)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 condIntReg cond x y
@@ -3752,7 +3903,7 @@ condFltReg cond x y
            LABEL lbl]
     in
     returnNat (Any IntRep code__2)
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -3882,7 +4033,7 @@ trivialUFCode _ instr x
     in
     returnNat (Any DoubleRep code__2)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -4063,7 +4214,7 @@ trivialUFCode pk instr x
     in
     returnNat (Any pk code__2)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -4151,7 +4302,7 @@ trivialUFCode pk instr x
     in
     returnNat (Any pk code__2)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
 trivialCode instr x (StInt y)
@@ -4217,13 +4368,13 @@ trivialFCode pk instr x y
        code2 = registerCode register2 tmp2
        src2  = registerName register2 tmp2
 
+       dstRep = if pk1 == FloatRep && pk2 == FloatRep then FloatRep else DoubleRep
+
        code__2 dst =
-               if pk1 == pk2 then
                    code1 `appOL` code2 `snocOL`
-                   instr (primRepToSize pk) dst src1 src2
-               else panic "###PPC MachCode.trivialFCode: type mismatch"
+                   instr (primRepToSize dstRep) dst src1 src2
     in
-    returnNat (Any (if pk1 == pk2 then pk1 else DoubleRep) code__2)
+    returnNat (Any dstRep code__2)
 
 trivialUCode instr x
   = getRegister x              `thenNat` \ register ->
@@ -4234,8 +4385,42 @@ trivialUCode instr x
        code__2 dst = code `snocOL` instr dst src
     in
     returnNat (Any IntRep code__2)
-trivialUFCode pk instr x  = panic "###PPC MachCode.trivialUFCode"
-#endif {- powerpc_TARGET_ARCH -}
+trivialUFCode pk instr x
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG (registerRep register)
+                               `thenNat` \ tmp ->
+    let
+       code = registerCode register tmp
+       src  = registerName register tmp
+       code__2 dst = code `snocOL` instr dst src
+    in
+    returnNat (Any pk code__2)
+  
+-- There is no "remainder" instruction on the PPC, so we have to do
+-- it the hard way.
+-- The "div" parameter is the division instruction to use (DIVW or DIVWU)
+
+remainderCode :: (Reg -> Reg -> Reg -> Instr)
+    -> StixExpr -> StixExpr -> NatM Register
+remainderCode div x y
+  = getRegister x              `thenNat` \ register1 ->
+    getRegister y              `thenNat` \ register2 ->
+    getNewRegNCG IntRep                `thenNat` \ tmp1 ->
+    getNewRegNCG IntRep                `thenNat` \ tmp2 ->
+    let
+       code1 = registerCode register1 tmp1
+       src1  = registerName register1 tmp1
+       code2 = registerCode register2 tmp2
+       src2  = registerName register2 tmp2
+       code__2 dst = code1 `appOL` code2 `appOL` toOL [
+               div dst src1 src2,
+               MULLW dst dst (RIReg src2),
+               SUBF dst dst src1
+           ]
+    in
+    returnNat (Any IntRep code__2)
+
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
@@ -4297,7 +4482,7 @@ coerceFP2Int x
     in
     returnNat (Any IntRep code__2)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -4332,7 +4517,7 @@ coerceFP2Int fprep x
 coerceDbl2Flt x = panic "MachCode.coerceDbl2Flt: unused on x86"
 coerceFlt2Dbl x = panic "MachCode.coerceFlt2Dbl: unused on x86"
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -4388,14 +4573,56 @@ coerceFlt2Dbl x
         returnNat (Any DoubleRep
                        (\dst -> code `snocOL` FxTOy F DF src dst)) 
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
 
 #if powerpc_TARGET_ARCH
-coerceInt2FP pk x      = panic "###PPC MachCode.coerceInt2FP"
-coerceFP2Int fprep x   = panic "###PPC MachCode.coerceFP2Int"
+coerceInt2FP pk x
+  = ASSERT(pk == DoubleRep)
+    getRegister x                  `thenNat` \ register ->
+    getNewRegNCG IntRep                    `thenNat` \ reg ->
+    getNatLabelNCG                 `thenNat` \ lbl ->
+    getNewRegNCG PtrRep            `thenNat` \ itmp ->
+    getNewRegNCG DoubleRep         `thenNat` \ ftmp ->
+    let
+        code = registerCode register reg
+       src  = registerName register reg
+       code__2 dst = code `appOL` toOL [
+               SEGMENT RoDataSegment,
+               LABEL lbl,
+               DATA W [ImmInt 0x43300000, ImmInt 0x80000000],
+               SEGMENT TextSegment,
+               XORIS itmp src (ImmInt 0x8000),
+               ST W itmp (spRel (-1)),
+               LIS itmp (ImmInt 0x4330),
+               ST W itmp (spRel (-2)),
+               LD DF ftmp (spRel (-2)),
+               LIS itmp (HA (ImmCLbl lbl)),
+               LD DF dst (AddrRegImm itmp (LO (ImmCLbl lbl))),
+               FSUB DF dst ftmp dst
+           ]
+    in
+       returnNat (Any DoubleRep code__2)
+
+coerceFP2Int fprep x
+  = ASSERT(fprep == DoubleRep || fprep == FloatRep)
+    getRegister x              `thenNat` \ register ->
+    getNewRegNCG fprep         `thenNat` \ reg ->
+    getNewRegNCG DoubleRep     `thenNat` \ tmp ->
+    let
+       code = registerCode register reg
+       src  = registerName register reg
+       code__2 dst = code `appOL` toOL [
+               -- convert to int in FP reg
+           FCTIWZ tmp src,
+               -- store value (64bit) from FP to stack
+           ST DF tmp (spRel (-2)),
+               -- read low word of value (high word is undefined)
+           LD W dst (spRel (-1))]      
+    in
+    returnNat (Any IntRep code__2)
 coerceDbl2Flt x                = panic "###PPC MachCode.coerceDbl2Flt"
 coerceFlt2Dbl x                = panic "###PPC MachCode.coerceFlt2Dbl"
-#endif {- powerpc_TARGET_ARCH -}
+#endif /* powerpc_TARGET_ARCH */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}