[project @ 2004-08-13 10:45:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachCode.lhs
index 01b9c6e..2876efd 100644 (file)
@@ -18,25 +18,45 @@ import MachMisc             -- may differ per-platform
 import MachRegs
 import OrdList         ( OrdList, nilOL, isNilOL, unitOL, appOL, toOL,
                          snocOL, consOL, concatOL )
+import MachOp          ( MachOp(..), pprMachOp )
 import AbsCUtils       ( magicIdPrimRep )
+import PprAbsC         ( pprMagicId )
 import ForeignCall     ( CCallConv(..) )
-import CLabel          ( isAsmTemp, CLabel, labelDynamic )
-import Maybes          ( maybeToBool, expectJust )
-import PrimRep         ( isFloatingRep, PrimRep(..) )
-import PrimOp          ( PrimOp(..) )
-import Stix            ( getNatLabelNCG, StixTree(..),
-                         StixReg(..), CodeSegment(..), 
+import CLabel          ( CLabel, labelDynamic )
+#if sparc_TARGET_ARCH || alpha_TARGET_ARCH
+import CLabel          ( isAsmTemp )
+#endif
+import Maybes          ( maybeToBool )
+import PrimRep         ( isFloatingRep, is64BitRep, PrimRep(..),
+#if powerpc_TARGET_ARCH
+                         getPrimRepSize,
+#endif
+                         getPrimRepSizeInBytes )
+import Stix            ( getNatLabelNCG, StixStmt(..), StixExpr(..),
+                         StixReg(..), pprStixReg, StixVReg(..), CodeSegment(..), 
                           DestInfo, hasDestInfo,
-                          pprStixTree, 
+                          pprStixExpr, repOfStixExpr,
                           NatM, thenNat, returnNat, mapNat, 
                           mapAndUnzipNat, mapAccumLNat,
-                          getDeltaNat, setDeltaNat
+                          getDeltaNat, setDeltaNat, 
+                         IF_ARCH_powerpc(addImportNat COMMA,)
+                          ncgPrimopMoan,
+                         ncg_target_is_32bit
                        )
-import Outputable
+import Pretty
+import Outputable      ( panic, pprPanic, showSDoc )
+import qualified Outputable
 import CmdLineOpts     ( opt_Static )
+import Stix            ( pprStixStmt )
 
-infixr 3 `bind`
+import Maybe           ( fromMaybe )
+
+-- DEBUGGING ONLY
+import Outputable      ( assertPanic )
+import FastString
+import TRACE           ( trace )
 
+infixr 3 `bind`
 \end{code}
 
 @InstrBlock@s are the insn sequences generated by the insn selectors.
@@ -45,94 +65,26 @@ left-to-right traversal (pre-order?) yields the insns in the correct
 order.
 
 \begin{code}
-
 type InstrBlock = OrdList Instr
 
 x `bind` f = f x
 
+isLeft (Left _)  = True
+isLeft (Right _) = False
+
+unLeft (Left x) = x
 \end{code}
 
 Code extractor for an entire stix tree---stix statement level.
 
 \begin{code}
-stmtsToInstrs :: [StixTree] -> NatM InstrBlock
+stmtsToInstrs :: [StixStmt] -> NatM InstrBlock
 stmtsToInstrs stmts
-   = liftStrings stmts [] []           `thenNat` \ lifted ->
-     mapNat stmtToInstrs lifted                `thenNat` \ instrss ->
+   = mapNat stmtToInstrs stmts         `thenNat` \ instrss ->
      returnNat (concatOL instrss)
 
 
--- Lift StStrings out of top-level StDatas, putting them at the end of
--- the block, and replacing them with StCLbls which refer to the lifted-out strings. 
-{- Motivation for this hackery provided by the following bug:
-   Stix:
-      (DataSegment)
-      Bogon.ping_closure :
-      (Data P_ Addr.A#_static_info)
-      (Data StgAddr (Str `alalal'))
-      (Data P_ (0))
-   results in:
-      .data
-              .align 8
-      .global Bogon_ping_closure
-      Bogon_ping_closure:
-              .long   Addr_Azh_static_info
-              .long   .Ln1a8
-      .Ln1a8:
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x00
-              .long   0
-   ie, the Str is planted in-line, when what we really meant was to place
-   a _reference_ to the string there.  liftStrings will lift out all such
-   strings in top-level data and place them at the end of the block.
-
-   This is still a rather half-baked solution -- to do the job entirely right
-   would mean a complete traversal of all the Stixes, but there's currently no
-   real need for it, and it would be slow.  Also, potentially there could be
-   literal types other than strings which need lifting out?
--}
-
-liftStrings :: [StixTree]    -- originals
-            -> [StixTree]    -- (reverse) originals with strings lifted out
-            -> [(CLabel, FAST_STRING)]   -- lifted strs, and their new labels
-            -> NatM [StixTree]
-
--- First, examine the original trees and lift out strings in top-level StDatas.
-liftStrings (st:sts) acc_stix acc_strs
-   = case st of
-        StData sz datas
-           -> lift datas acc_strs      `thenNat` \ (datas_done, acc_strs1) ->
-              liftStrings sts ((StData sz datas_done):acc_stix) acc_strs1
-        other 
-           -> liftStrings sts (other:acc_stix) acc_strs
-     where
-        -- Handle a top-level StData
-        lift []     acc_strs = returnNat ([], acc_strs)
-        lift (d:ds) acc_strs
-           = lift ds acc_strs          `thenNat` \ (ds_done, acc_strs1) ->
-             case d of
-                StString s 
-                   -> getNatLabelNCG   `thenNat` \ lbl ->
-                      returnNat ((StCLbl lbl):ds_done, ((lbl,s):acc_strs1))
-                other
-                   -> returnNat (other:ds_done, acc_strs1)
-
--- When we've run out of original trees, emit the lifted strings.
-liftStrings [] acc_stix acc_strs
-   = returnNat (reverse acc_stix ++ concatMap f acc_strs)
-     where
-        f (lbl,str) = [StSegment RoDataSegment, 
-                       StLabel lbl, 
-                       StString str, 
-                       StSegment TextSegment]
-
-
-stmtToInstrs :: StixTree {- a stix statement -} -> NatM InstrBlock
+stmtToInstrs :: StixStmt -> NatM InstrBlock
 stmtToInstrs stmt = case stmt of
     StComment s    -> returnNat (unitOL (COMMENT s))
     StSegment seg  -> returnNat (unitOL (SEGMENT seg))
@@ -147,13 +99,21 @@ stmtToInstrs stmt = case stmt of
     StJump dsts arg       -> genJump dsts (derefDLL arg)
     StCondJump lab arg    -> genCondJump lab (derefDLL arg)
 
-    -- A call returning void, ie one done for its side-effects
-    StCall fn cconv VoidRep args -> genCCall fn
-                                             cconv VoidRep (map derefDLL args)
-
-    StAssign pk dst src
-      | isFloatingRep pk -> assignFltCode pk (derefDLL dst) (derefDLL src)
-      | otherwise       -> assignIntCode pk (derefDLL dst) (derefDLL src)
+    -- A call returning void, ie one done for its side-effects.  Note
+    -- that this is the only StVoidable we handle.
+    StVoidable (StCall fn cconv VoidRep args) 
+       -> genCCall fn cconv VoidRep (map derefDLL args)
+
+    StAssignMem pk addr src
+      | isFloatingRep pk -> assignMem_FltCode pk (derefDLL addr) (derefDLL src)
+      | ncg_target_is_32bit
+        && is64BitRep pk -> assignMem_I64Code    (derefDLL addr) (derefDLL src)
+      | otherwise       -> assignMem_IntCode pk (derefDLL addr) (derefDLL src)
+    StAssignReg pk reg src
+      | isFloatingRep pk -> assignReg_FltCode pk reg (derefDLL src)
+      | ncg_target_is_32bit
+        && is64BitRep pk -> assignReg_I64Code    reg (derefDLL src)
+      | otherwise       -> assignReg_IntCode pk reg (derefDLL src)
 
     StFallThrough lbl
        -- When falling through on the Alpha, we still have to load pv
@@ -166,7 +126,7 @@ stmtToInstrs stmt = case stmt of
         returnNat (DATA (primRepToSize kind) imms  
                     `consOL`  concatOL codes)
       where
-       getData :: StixTree -> NatM (InstrBlock, Imm)
+       getData :: StixExpr -> NatM (InstrBlock, Imm)
        getData (StInt i)        = returnNat (nilOL, ImmInteger i)
        getData (StDouble d)     = returnNat (nilOL, ImmDouble d)
        getData (StFloat d)      = returnNat (nilOL, ImmFloat d)
@@ -175,19 +135,22 @@ stmtToInstrs stmt = case stmt of
        -- the linker can handle simple arithmetic...
        getData (StIndex rep (StCLbl lbl) (StInt off)) =
                returnNat (nilOL,
-                           ImmIndex lbl (fromInteger off * sizeOf rep))
+                           ImmIndex lbl (fromInteger off * getPrimRepSizeInBytes rep))
 
     -- Top-level lifted-out string.  The segment will already have been set
-    -- (see liftStrings above).
-    StString str
-      -> returnNat (unitOL (ASCII True (_UNPK_ str)))
+    -- (see Stix.liftStrings).
+    StDataString str
+      -> returnNat (unitOL (ASCII True (unpackFS str)))
 
+#ifdef DEBUG
+    other -> pprPanic "stmtToInstrs" (pprStixStmt other)
+#endif
 
 -- Walk a Stix tree, and insert dereferences to CLabels which are marked
 -- as labelDynamic.  stmt2Instrs calls derefDLL selectively, because
 -- not all such CLabel occurrences need this dereferencing -- SRTs don't
 -- for one.
-derefDLL :: StixTree -> StixTree
+derefDLL :: StixExpr -> StixExpr
 derefDLL tree
    | opt_Static   -- short out the entire deal if not doing DLLs
    = tree
@@ -201,17 +164,17 @@ derefDLL tree
                               else t
                 -- all the rest are boring
                 StIndex pk base offset -> StIndex pk (qq base) (qq offset)
-                StPrim pk args         -> StPrim pk (map qq args)
+                StMachOp mop args      -> StMachOp mop (map qq args)
                 StInd pk addr          -> StInd pk (qq addr)
-                StCall who cc pk args  -> StCall who cc pk (map qq args)
+                StCall (Left nm) cc pk args -> StCall (Left nm) cc pk (map qq args)
+                StCall (Right f) cc pk args -> StCall (Right (qq f)) cc pk (map qq args)
                 StInt    _             -> t
                 StFloat  _             -> t
                 StDouble _             -> t
                 StString _             -> t
                 StReg    _             -> t
-                StScratchWord _        -> t
                 _                      -> pprPanic "derefDLL: unhandled case" 
-                                                   (pprStixTree t)
+                                                   (pprStixExpr t)
 \end{code}
 
 %************************************************************************
@@ -221,39 +184,40 @@ derefDLL tree
 %************************************************************************
 
 \begin{code}
-mangleIndexTree :: StixTree -> StixTree
+mangleIndexTree :: StixExpr -> StixExpr
 
 mangleIndexTree (StIndex pk base (StInt i))
-  = StPrim IntAddOp [base, off]
+  = StMachOp MO_Nat_Add [base, off]
   where
-    off = StInt (i * toInteger (sizeOf pk))
+    off = StInt (i * toInteger (getPrimRepSizeInBytes pk))
 
 mangleIndexTree (StIndex pk base off)
-  = StPrim IntAddOp [
+  = StMachOp MO_Nat_Add [
        base,
        let s = shift pk
-       in  if s == 0 then off else StPrim SllOp [off, StInt (toInteger s)]
-      ]
+       in  if s == 0 then off 
+                     else StMachOp MO_Nat_Shl [off, StInt (toInteger s)]
+    ]
   where
     shift :: PrimRep -> Int
-    shift rep = case sizeOf rep of
+    shift rep = case getPrimRepSizeInBytes rep of
                    1 -> 0
                    2 -> 1
                    4 -> 2
                    8 -> 3
                    other -> pprPanic "MachCode.mangleIndexTree.shift: unhandled rep size" 
-                                     (int other)
+                                     (Outputable.int other)
 \end{code}
 
 \begin{code}
-maybeImm :: StixTree -> Maybe Imm
+maybeImm :: StixExpr -> Maybe Imm
 
 maybeImm (StCLbl l)       
    = Just (ImmCLbl l)
 maybeImm (StIndex rep (StCLbl l) (StInt off)) 
-   = Just (ImmIndex l (fromInteger off * sizeOf rep))
+   = Just (ImmIndex l (fromInteger off * getPrimRepSizeInBytes rep))
 maybeImm (StInt i)
-  | i >= toInteger minInt && i <= toInteger maxInt
+  | i >= toInteger (minBound::Int) && i <= toInteger (maxBound::Int)
   = Just (ImmInt (fromInteger i))
   | otherwise
   = Just (ImmInteger i)
@@ -263,6 +227,311 @@ maybeImm _ = Nothing
 
 %************************************************************************
 %*                                                                     *
+\subsection{The @Register64@ type}
+%*                                                                     *
+%************************************************************************
+
+Simple support for generating 64-bit code (ie, 64 bit values and 64
+bit assignments) on 32-bit platforms.  Unlike the main code generator
+we merely shoot for generating working code as simply as possible, and
+pay little attention to code quality.  Specifically, there is no
+attempt to deal cleverly with the fixed-vs-floating register
+distinction; all values are generated into (pairs of) floating
+registers, even if this would mean some redundant reg-reg moves as a
+result.  Only one of the VRegUniques is returned, since it will be
+of the VRegUniqueLo form, and the upper-half VReg can be determined
+by applying getHiVRegFromLo to it.
+
+\begin{code}
+
+data ChildCode64       -- a.k.a "Register64"
+   = ChildCode64 
+        InstrBlock     -- code
+        VRegUnique     -- unique for the lower 32-bit temporary
+       -- which contains the result; use getHiVRegFromLo to find
+       -- the other VRegUnique.
+       -- Rules of this simplified insn selection game are
+       -- therefore that the returned VRegUnique may be modified
+
+assignMem_I64Code :: StixExpr -> StixExpr -> NatM InstrBlock
+assignReg_I64Code :: StixReg  -> StixExpr -> NatM InstrBlock
+iselExpr64        :: StixExpr -> NatM ChildCode64
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#if i386_TARGET_ARCH
+
+assignMem_I64Code addrTree valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vrlo) ->
+     getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     let rlo = VirtualRegI vrlo
+         rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         -- Little-endian store
+         mov_lo = MOV L (OpReg rlo)
+                        (OpAddr (AddrBaseIndex (Just reg_addr) Nothing (ImmInt 0)))
+         mov_hi = MOV L (OpReg rhi)
+                        (OpAddr (AddrBaseIndex (Just reg_addr) Nothing (ImmInt 4)))
+     in
+         returnNat (vcode `appOL` code_addr `snocOL` mov_lo `snocOL` mov_hi)
+
+assignReg_I64Code (StixTemp (StixVReg u_dst pk)) valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vr_src_lo) ->
+     let 
+         r_dst_lo = mkVReg u_dst IntRep
+         r_src_lo = VirtualRegI vr_src_lo
+         r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = MOV L (OpReg r_src_lo) (OpReg r_dst_lo)
+         mov_hi = MOV L (OpReg r_src_hi) (OpReg r_dst_hi)
+     in
+         returnNat (
+            vcode `snocOL` mov_lo `snocOL` mov_hi
+         )
+
+assignReg_I64Code lvalue valueTree
+   = pprPanic "assignReg_I64Code(i386): invalid lvalue"
+              (pprStixReg lvalue)
+
+
+
+iselExpr64 (StInd pk addrTree)
+   | is64BitRep pk
+   = getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     getNewRegNCG IntRep               `thenNat` \ rlo ->
+     let rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         mov_lo = MOV L (OpAddr (AddrBaseIndex (Just reg_addr) Nothing (ImmInt 0)))
+                        (OpReg rlo)
+         mov_hi = MOV L (OpAddr (AddrBaseIndex (Just reg_addr) Nothing (ImmInt 4)))
+                        (OpReg rhi)
+     in
+         returnNat (
+            ChildCode64 (code_addr `snocOL` mov_lo `snocOL` mov_hi) 
+                        (getVRegUnique rlo)
+         )
+
+iselExpr64 (StReg (StixTemp (StixVReg vu pk)))
+   | is64BitRep pk
+   = getNewRegNCG IntRep               `thenNat` \ r_dst_lo ->
+     let r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_lo = mkVReg vu IntRep
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = MOV L (OpReg r_src_lo) (OpReg r_dst_lo)
+         mov_hi = MOV L (OpReg r_src_hi) (OpReg r_dst_hi)
+     in
+         returnNat (
+            ChildCode64 (toOL [mov_lo, mov_hi]) (getVRegUnique r_dst_lo)
+         )
+         
+iselExpr64 (StCall fn cconv kind args)
+  | is64BitRep kind
+  = genCCall fn cconv kind args                        `thenNat` \ call ->
+    getNewRegNCG IntRep                                `thenNat` \ r_dst_lo ->
+    let r_dst_hi = getHiVRegFromLo r_dst_lo
+        mov_lo = MOV L (OpReg eax) (OpReg r_dst_lo)
+        mov_hi = MOV L (OpReg edx) (OpReg r_dst_hi)
+    in
+    returnNat (
+       ChildCode64 (call `snocOL` mov_lo `snocOL` mov_hi) 
+                   (getVRegUnique r_dst_lo)
+    )
+
+iselExpr64 expr
+   = pprPanic "iselExpr64(i386)" (pprStixExpr expr)
+
+#endif /* i386_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#if sparc_TARGET_ARCH
+
+assignMem_I64Code addrTree valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vrlo) ->
+     getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     let rlo = VirtualRegI vrlo
+         rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         -- Big-endian store
+         mov_hi = ST W rhi (AddrRegImm reg_addr (ImmInt 0))
+         mov_lo = ST W rlo (AddrRegImm reg_addr (ImmInt 4))
+     in
+         returnNat (vcode `appOL` code_addr `snocOL` mov_hi `snocOL` mov_lo)
+
+
+assignReg_I64Code (StixTemp (StixVReg u_dst pk)) valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vr_src_lo) ->
+     let 
+         r_dst_lo = mkVReg u_dst IntRep
+         r_src_lo = VirtualRegI vr_src_lo
+         r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = mkMOV r_src_lo r_dst_lo
+         mov_hi = mkMOV r_src_hi r_dst_hi
+         mkMOV sreg dreg = OR False g0 (RIReg sreg) dreg
+     in
+         returnNat (
+            vcode `snocOL` mov_hi `snocOL` mov_lo
+         )
+assignReg_I64Code lvalue valueTree
+   = pprPanic "assignReg_I64Code(sparc): invalid lvalue"
+              (pprStixReg lvalue)
+
+
+-- Don't delete this -- it's very handy for debugging.
+--iselExpr64 expr 
+--   | trace ("iselExpr64: " ++ showSDoc (pprStixExpr expr)) False
+--   = panic "iselExpr64(???)"
+
+iselExpr64 (StInd pk addrTree)
+   | is64BitRep pk
+   = getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     getNewRegNCG IntRep               `thenNat` \ rlo ->
+     let rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         mov_hi = LD W (AddrRegImm reg_addr (ImmInt 0)) rhi
+         mov_lo = LD W (AddrRegImm reg_addr (ImmInt 4)) rlo
+     in
+         returnNat (
+            ChildCode64 (code_addr `snocOL` mov_hi `snocOL` mov_lo) 
+                        (getVRegUnique rlo)
+         )
+
+iselExpr64 (StReg (StixTemp (StixVReg vu pk)))
+   | is64BitRep pk
+   = getNewRegNCG IntRep               `thenNat` \ r_dst_lo ->
+     let r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_lo = mkVReg vu IntRep
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = mkMOV r_src_lo r_dst_lo
+         mov_hi = mkMOV r_src_hi r_dst_hi
+         mkMOV sreg dreg = OR False g0 (RIReg sreg) dreg
+     in
+         returnNat (
+            ChildCode64 (toOL [mov_hi, mov_lo]) (getVRegUnique r_dst_lo)
+         )
+
+iselExpr64 (StCall fn cconv kind args)
+  | is64BitRep kind
+  = genCCall fn cconv kind args                        `thenNat` \ call ->
+    getNewRegNCG IntRep                                `thenNat` \ r_dst_lo ->
+    let r_dst_hi = getHiVRegFromLo r_dst_lo
+        mov_lo = mkMOV o0 r_dst_lo
+        mov_hi = mkMOV o1 r_dst_hi
+        mkMOV sreg dreg = OR False g0 (RIReg sreg) dreg
+    in
+    returnNat (
+       ChildCode64 (call `snocOL` mov_hi `snocOL` mov_lo) 
+                   (getVRegUnique r_dst_lo)
+    )
+
+iselExpr64 expr
+   = pprPanic "iselExpr64(sparc)" (pprStixExpr expr)
+
+#endif /* sparc_TARGET_ARCH */
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#if powerpc_TARGET_ARCH
+
+assignMem_I64Code addrTree valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vrlo) ->
+     getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     let rlo = VirtualRegI vrlo
+         rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         -- Big-endian store
+         mov_hi = ST W rhi (AddrRegImm reg_addr (ImmInt 0))
+         mov_lo = ST W rlo (AddrRegImm reg_addr (ImmInt 4))
+     in
+         returnNat (vcode `appOL` code_addr `snocOL` mov_hi `snocOL` mov_lo)
+
+
+assignReg_I64Code (StixTemp (StixVReg u_dst pk)) valueTree
+   = iselExpr64 valueTree              `thenNat` \ (ChildCode64 vcode vr_src_lo) ->
+     let 
+         r_dst_lo = mkVReg u_dst IntRep
+         r_src_lo = VirtualRegI vr_src_lo
+         r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = MR r_dst_lo r_src_lo
+         mov_hi = MR r_dst_hi r_src_hi
+     in
+         returnNat (
+            vcode `snocOL` mov_hi `snocOL` mov_lo
+         )
+assignReg_I64Code lvalue valueTree
+   = pprPanic "assignReg_I64Code(powerpc): invalid lvalue"
+              (pprStixReg lvalue)
+
+
+-- Don't delete this -- it's very handy for debugging.
+--iselExpr64 expr 
+--   | trace ("iselExpr64: " ++ showSDoc (pprStixExpr expr)) False
+--   = panic "iselExpr64(???)"
+
+iselExpr64 (StInd pk addrTree)
+   | is64BitRep pk
+   = getRegister addrTree              `thenNat` \ register_addr ->
+     getNewRegNCG IntRep               `thenNat` \ t_addr ->
+     getNewRegNCG IntRep               `thenNat` \ rlo ->
+     let rhi = getHiVRegFromLo rlo
+         code_addr = registerCode register_addr t_addr
+         reg_addr  = registerName register_addr t_addr
+         mov_hi = LD W rhi (AddrRegImm reg_addr (ImmInt 0))
+         mov_lo = LD W rlo (AddrRegImm reg_addr (ImmInt 4))
+     in
+         returnNat (
+            ChildCode64 (code_addr `snocOL` mov_hi `snocOL` mov_lo) 
+                        (getVRegUnique rlo)
+         )
+
+iselExpr64 (StReg (StixTemp (StixVReg vu pk)))
+   | is64BitRep pk
+   = getNewRegNCG IntRep               `thenNat` \ r_dst_lo ->
+     let r_dst_hi = getHiVRegFromLo r_dst_lo
+         r_src_lo = mkVReg vu IntRep
+         r_src_hi = getHiVRegFromLo r_src_lo
+         mov_lo = MR r_dst_lo r_src_lo
+         mov_hi = MR r_dst_hi r_src_hi
+     in
+         returnNat (
+            ChildCode64 (toOL [mov_hi, mov_lo]) (getVRegUnique r_dst_lo)
+         )
+
+iselExpr64 (StCall fn cconv kind args)
+  | is64BitRep kind
+  = genCCall fn cconv kind args                        `thenNat` \ call ->
+    getNewRegNCG IntRep                                `thenNat` \ r_dst_lo ->
+    let r_dst_hi = getHiVRegFromLo r_dst_lo
+        mov_lo = MR r_dst_lo r4
+        mov_hi = MR r_dst_hi r3
+    in
+    returnNat (
+       ChildCode64 (call `snocOL` mov_hi `snocOL` mov_lo) 
+                   (getVRegUnique r_dst_lo)
+    )
+
+iselExpr64 expr
+   = pprPanic "iselExpr64(powerpc)" (pprStixExpr expr)
+
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\end{code}
+
+%************************************************************************
+%*                                                                     *
 \subsection{The @Register@ type}
 %*                                                                     *
 %************************************************************************
@@ -282,22 +551,26 @@ registerCode (Fixed _ _ code) reg = code
 registerCode (Any _ code) reg = code reg
 
 registerCodeF (Fixed _ _ code) = code
-registerCodeF (Any _ _)        = pprPanic "registerCodeF" empty
+registerCodeF (Any _ _)        = panic "registerCodeF"
 
 registerCodeA (Any _ code)  = code
-registerCodeA (Fixed _ _ _) = pprPanic "registerCodeA" empty
+registerCodeA (Fixed _ _ _) = panic "registerCodeA"
 
 registerName :: Register -> Reg -> Reg
 registerName (Fixed _ reg _) _ = reg
 registerName (Any _ _)   reg   = reg
 
 registerNameF (Fixed _ reg _) = reg
-registerNameF (Any _ _)       = pprPanic "registerNameF" empty
+registerNameF (Any _ _)       = panic "registerNameF"
 
 registerRep :: Register -> PrimRep
 registerRep (Fixed pk _ _) = pk
 registerRep (Any   pk _) = pk
 
+swizzleRegisterRep :: Register -> PrimRep -> Register
+swizzleRegisterRep (Fixed _ reg code) rep = Fixed rep reg code
+swizzleRegisterRep (Any _ codefn)     rep = Any rep codefn
+
 {-# INLINE registerCode  #-}
 {-# INLINE registerCodeF #-}
 {-# INLINE registerName  #-}
@@ -315,25 +588,45 @@ isAny = not . isFixed
 
 Generate code to get a subtree into a @Register@:
 \begin{code}
-getRegister :: StixTree -> NatM Register
 
-getRegister (StReg (StixMagicId stgreg))
-  = case (magicIdRegMaybe stgreg) of
-      Just reg -> returnNat (Fixed (magicIdPrimRep stgreg) reg nilOL)
-                  -- cannae be Nothing
+getRegisterReg :: StixReg -> NatM Register
+getRegister :: StixExpr -> NatM Register
+
 
-getRegister (StReg (StixTemp u pk))
+getRegisterReg (StixMagicId mid)
+  = case get_MagicId_reg_or_addr mid of
+       Left (RealReg rrno) 
+          -> let pk = magicIdPrimRep mid
+             in  returnNat (Fixed pk (RealReg rrno) nilOL)
+       Right baseRegAddr 
+          -- By this stage, the only MagicIds remaining should be the
+          -- ones which map to a real machine register on this platform.  Hence ...
+          -> pprPanic "getRegisterReg-memory" (pprMagicId mid)
+
+getRegisterReg (StixTemp (StixVReg u pk))
   = returnNat (Fixed pk (mkVReg u pk) nilOL)
 
-getRegister tree@(StIndex _ _ _) = getRegister (mangleIndexTree tree)
+-------------
+
+-- Don't delete this -- it's very handy for debugging.
+--getRegister expr 
+--   | trace ("getRegiste: " ++ showSDoc (pprStixExpr expr)) False
+--   = panic "getRegister(???)"
+
+getRegister (StReg reg) 
+  = getRegisterReg reg
+
+getRegister tree@(StIndex _ _ _) 
+  = getRegister (mangleIndexTree tree)
 
 getRegister (StCall fn cconv kind args)
+  | not (ncg_target_is_32bit && is64BitRep kind)
   = genCCall fn cconv kind args            `thenNat` \ call ->
     returnNat (Fixed kind reg call)
   where
     reg = if isFloatingRep kind
-         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,)))
+         then IF_ARCH_alpha( f0, IF_ARCH_i386( fake0, IF_ARCH_sparc( f0, IF_ARCH_powerpc( f1,))))
+         else IF_ARCH_alpha( v0, IF_ARCH_i386( eax, IF_ARCH_sparc( o0, IF_ARCH_powerpc( r3,))))
 
 getRegister (StString s)
   = getNatLabelNCG                 `thenNat` \ lbl ->
@@ -343,7 +636,7 @@ getRegister (StString s)
        code dst = toOL [
            SEGMENT RoDataSegment,
            LABEL lbl,
-           ASCII True (_UNPK_ s),
+           ASCII True (unpackFS s),
            SEGMENT TextSegment,
 #if alpha_TARGET_ARCH
            LDA dst (AddrImm imm_lbl)
@@ -355,12 +648,15 @@ getRegister (StString s)
            SETHI (HI imm_lbl) dst,
            OR False dst (RIImm (LO imm_lbl)) dst
 #endif
+#if powerpc_TARGET_ARCH
+           LIS dst (HI imm_lbl),
+           OR dst dst (RIImm (LO imm_lbl))
+#endif
            ]
     in
     returnNat (Any PtrRep code)
 
-
-
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 -- end of machine-"independent" bit; here we go on the rest...
 
 #if alpha_TARGET_ARCH
@@ -401,30 +697,30 @@ getRegister (StPrim primop [x]) -- unary PrimOps
       other_op -> getRegister (StCall fn CCallConv DoubleRep [x])
        where
          fn = case other_op of
-                FloatExpOp    -> SLIT("exp")
-                FloatLogOp    -> SLIT("log")
-                FloatSqrtOp   -> SLIT("sqrt")
-                FloatSinOp    -> SLIT("sin")
-                FloatCosOp    -> SLIT("cos")
-                FloatTanOp    -> SLIT("tan")
-                FloatAsinOp   -> SLIT("asin")
-                FloatAcosOp   -> SLIT("acos")
-                FloatAtanOp   -> SLIT("atan")
-                FloatSinhOp   -> SLIT("sinh")
-                FloatCoshOp   -> SLIT("cosh")
-                FloatTanhOp   -> SLIT("tanh")
-                DoubleExpOp   -> SLIT("exp")
-                DoubleLogOp   -> SLIT("log")
-                DoubleSqrtOp  -> SLIT("sqrt")
-                DoubleSinOp   -> SLIT("sin")
-                DoubleCosOp   -> SLIT("cos")
-                DoubleTanOp   -> SLIT("tan")
-                DoubleAsinOp  -> SLIT("asin")
-                DoubleAcosOp  -> SLIT("acos")
-                DoubleAtanOp  -> SLIT("atan")
-                DoubleSinhOp  -> SLIT("sinh")
-                DoubleCoshOp  -> SLIT("cosh")
-                DoubleTanhOp  -> SLIT("tanh")
+                FloatExpOp    -> FSLIT("exp")
+                FloatLogOp    -> FSLIT("log")
+                FloatSqrtOp   -> FSLIT("sqrt")
+                FloatSinOp    -> FSLIT("sin")
+                FloatCosOp    -> FSLIT("cos")
+                FloatTanOp    -> FSLIT("tan")
+                FloatAsinOp   -> FSLIT("asin")
+                FloatAcosOp   -> FSLIT("acos")
+                FloatAtanOp   -> FSLIT("atan")
+                FloatSinhOp   -> FSLIT("sinh")
+                FloatCoshOp   -> FSLIT("cosh")
+                FloatTanhOp   -> FSLIT("tanh")
+                DoubleExpOp   -> FSLIT("exp")
+                DoubleLogOp   -> FSLIT("log")
+                DoubleSqrtOp  -> FSLIT("sqrt")
+                DoubleSinOp   -> FSLIT("sin")
+                DoubleCosOp   -> FSLIT("cos")
+                DoubleTanOp   -> FSLIT("tan")
+                DoubleAsinOp  -> FSLIT("asin")
+                DoubleAcosOp  -> FSLIT("acos")
+                DoubleAtanOp  -> FSLIT("atan")
+                DoubleSinhOp  -> FSLIT("sinh")
+                DoubleCoshOp  -> FSLIT("cosh")
+                DoubleTanhOp  -> FSLIT("tanh")
   where
     pr = panic "MachCode.getRegister: no primrep needed for Alpha"
 
@@ -457,7 +753,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       AddrNeOp -> int_NE_code x y
       AddrLtOp -> trivialCode (CMP ULT) x y
       AddrLeOp -> trivialCode (CMP ULE) x y
-
+       
       FloatGtOp -> cmpF_code (FCMP TF LE) EQQ x y
       FloatGeOp -> cmpF_code (FCMP TF LTT) EQQ x y
       FloatEqOp -> cmpF_code (FCMP TF EQQ) NE x y
@@ -494,6 +790,10 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       DoubleMulOp -> trivialFCode  DoubleRep (FMUL TF) x y
       DoubleDivOp -> trivialFCode  DoubleRep (FDIV TF) x y
 
+      AddrAddOp  -> trivialCode (ADD Q False) x y
+      AddrSubOp  -> trivialCode (SUB Q False) x y
+      AddrRemOp  -> trivialCode (REM Q True) x y
+
       AndOp  -> trivialCode AND x y
       OrOp   -> trivialCode OR  x y
       XorOp  -> trivialCode XOR x y
@@ -504,8 +804,8 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
       ISraOp -> trivialCode SRA x y -- was: panic "AlphaGen:isra"
       ISrlOp -> trivialCode SRL x y -- was: panic "AlphaGen:isrl"
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") CCallConv DoubleRep [x,y])
-      DoublePowerOp -> getRegister (StCall SLIT("pow") CCallConv DoubleRep [x,y])
+      FloatPowerOp  -> getRegister (StCall FSLIT("pow") CCallConv DoubleRep [x,y])
+      DoublePowerOp -> getRegister (StCall FSLIT("pow") CCallConv DoubleRep [x,y])
   where
     {- ------------------------------------------------------------
        Some bizarre special code for getting condition codes into
@@ -589,8 +889,10 @@ getRegister leaf
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
 getRegister (StFloat f)
@@ -628,172 +930,212 @@ getRegister (StDouble d)
     in
     returnNat (Any DoubleRep code)
 
--- Calculate the offset for (i+1) words above the _initial_
--- %esp value by first determining the current offset of it.
-getRegister (StScratchWord i)
-   | i >= 0 && i < 6
-   = getDeltaNat `thenNat` \ current_stack_offset ->
-     let j = i+1   - (current_stack_offset `div` 4)
-         code dst
-           = unitOL (LEA L (OpAddr (spRel j)) (OpReg dst))
-     in 
-     returnNat (Any PtrRep code)
-
-getRegister (StPrim primop [x]) -- unary PrimOps
-  = case primop of
-      IntNegOp  -> trivialUCode (NEGI L) x
-      NotOp    -> trivialUCode (NOT L) 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
-
-      FloatSinOp  -> trivialUFCode FloatRep  (GSIN F) x
-      DoubleSinOp -> trivialUFCode DoubleRep (GSIN DF) x
 
-      FloatCosOp  -> trivialUFCode FloatRep  (GCOS F) x
-      DoubleCosOp -> trivialUFCode DoubleRep (GCOS DF) x
-
-      FloatTanOp  -> trivialUFCode FloatRep  (GTAN F) x
-      DoubleTanOp -> trivialUFCode DoubleRep (GTAN DF) x
-
-      Double2FloatOp -> trivialUFCode FloatRep  GDTOF x
-      Float2DoubleOp -> trivialUFCode DoubleRep GFTOD x
-
-      OrdOp -> coerceIntCode IntRep x
-      ChrOp -> chrCode x
-
-      Float2IntOp  -> coerceFP2Int x
-      Int2FloatOp  -> coerceInt2FP FloatRep x
-      Double2IntOp -> coerceFP2Int x
-      Int2DoubleOp -> coerceInt2FP DoubleRep x
-
-      other_op ->
-       getRegister (StCall fn CCallConv DoubleRep [x])
-       where
+getRegister (StMachOp mop [x]) -- unary MachOps
+  = case mop of
+      MO_NatS_Neg  -> trivialUCode (NEGI L) x
+      MO_Nat_Not   -> trivialUCode (NOT L) x
+      MO_32U_to_8U -> trivialUCode (AND L (OpImm (ImmInt 255))) x
+
+      MO_Flt_Neg  -> trivialUFCode FloatRep  (GNEG F) x
+      MO_Dbl_Neg  -> trivialUFCode DoubleRep (GNEG DF) x
+
+      MO_Flt_Sqrt -> trivialUFCode FloatRep  (GSQRT F) x
+      MO_Dbl_Sqrt -> trivialUFCode DoubleRep (GSQRT DF) x
+
+      MO_Flt_Sin  -> trivialUFCode FloatRep  (GSIN F) x
+      MO_Dbl_Sin  -> trivialUFCode DoubleRep (GSIN DF) x
+
+      MO_Flt_Cos  -> trivialUFCode FloatRep  (GCOS F) x
+      MO_Dbl_Cos  -> trivialUFCode DoubleRep (GCOS DF) x
+
+      MO_Flt_Tan  -> trivialUFCode FloatRep  (GTAN F) x
+      MO_Dbl_Tan  -> trivialUFCode DoubleRep (GTAN DF) x
+
+      MO_Flt_to_NatS -> coerceFP2Int FloatRep x
+      MO_NatS_to_Flt -> coerceInt2FP FloatRep x
+      MO_Dbl_to_NatS -> coerceFP2Int DoubleRep x
+      MO_NatS_to_Dbl -> coerceInt2FP DoubleRep x
+
+      -- Conversions which are a nop on x86
+      MO_32U_to_NatS  -> conversionNop IntRep    x
+      MO_32S_to_NatS  -> conversionNop IntRep    x
+      MO_NatS_to_32U  -> conversionNop WordRep   x
+      MO_32U_to_NatU  -> conversionNop WordRep   x
+
+      MO_NatU_to_NatS -> conversionNop IntRep    x
+      MO_NatS_to_NatU -> conversionNop WordRep   x
+      MO_NatP_to_NatU -> conversionNop WordRep   x
+      MO_NatU_to_NatP -> conversionNop PtrRep    x
+      MO_NatS_to_NatP -> conversionNop PtrRep    x
+      MO_NatP_to_NatS -> conversionNop IntRep    x
+
+      MO_Dbl_to_Flt   -> conversionNop FloatRep  x
+      MO_Flt_to_Dbl   -> conversionNop DoubleRep x
+
+      -- sign-extending widenings
+      MO_8U_to_NatU   -> integerExtend False 24 x
+      MO_8S_to_NatS   -> integerExtend True  24 x
+      MO_16U_to_NatU  -> integerExtend False 16 x
+      MO_16S_to_NatS  -> integerExtend True  16 x
+      MO_8U_to_32U    -> integerExtend False 24 x
+
+      other_op 
+         -> getRegister (
+               (if is_float_op then demote else id)
+               (StCall (Left fn) CCallConv DoubleRep 
+                       [(if is_float_op then promote else id) x])
+            )
+      where
+        integerExtend signed nBits x
+           = getRegister (
+                StMachOp (if signed then MO_Nat_Sar else MO_Nat_Shr) 
+                         [StMachOp MO_Nat_Shl [x, StInt nBits], StInt nBits]
+             )
+
+        conversionNop new_rep expr
+            = getRegister expr         `thenNat` \ e_code ->
+              returnNat (swizzleRegisterRep e_code new_rep)
+
+        promote x = StMachOp MO_Flt_to_Dbl [x]
+        demote  x = StMachOp MO_Dbl_to_Flt [x]
        (is_float_op, fn)
-         = case primop of
-             FloatExpOp    -> (True,  SLIT("exp"))
-             FloatLogOp    -> (True,  SLIT("log"))
-
-             FloatAsinOp   -> (True,  SLIT("asin"))
-             FloatAcosOp   -> (True,  SLIT("acos"))
-             FloatAtanOp   -> (True,  SLIT("atan"))
-
-             FloatSinhOp   -> (True,  SLIT("sinh"))
-             FloatCoshOp   -> (True,  SLIT("cosh"))
-             FloatTanhOp   -> (True,  SLIT("tanh"))
-
-             DoubleExpOp   -> (False, SLIT("exp"))
-             DoubleLogOp   -> (False, SLIT("log"))
-
-             DoubleAsinOp  -> (False, SLIT("asin"))
-             DoubleAcosOp  -> (False, SLIT("acos"))
-             DoubleAtanOp  -> (False, SLIT("atan"))
-
-             DoubleSinhOp  -> (False, SLIT("sinh"))
-             DoubleCoshOp  -> (False, SLIT("cosh"))
-             DoubleTanhOp  -> (False, SLIT("tanh"))
-
-              other
-                 -> pprPanic "getRegister(x86,unary primop)" 
-                             (pprStixTree (StPrim primop [x]))
-
-getRegister (StPrim primop [x, y]) -- dyadic PrimOps
-  = case primop of
-      CharGtOp -> condIntReg GTT x y
-      CharGeOp -> condIntReg GE x y
-      CharEqOp -> condIntReg EQQ x y
-      CharNeOp -> condIntReg NE x y
-      CharLtOp -> condIntReg LTT x y
-      CharLeOp -> condIntReg LE x y
-
-      IntGtOp  -> condIntReg GTT x y
-      IntGeOp  -> condIntReg GE x y
-      IntEqOp  -> condIntReg EQQ x y
-      IntNeOp  -> condIntReg NE x y
-      IntLtOp  -> condIntReg LTT x y
-      IntLeOp  -> condIntReg LE x y
-
-      WordGtOp -> condIntReg GU  x y
-      WordGeOp -> condIntReg GEU x y
-      WordEqOp -> condIntReg EQQ  x y
-      WordNeOp -> condIntReg NE  x y
-      WordLtOp -> condIntReg LU  x y
-      WordLeOp -> condIntReg LEU x y
-
-      AddrGtOp -> condIntReg GU  x y
-      AddrGeOp -> condIntReg GEU x y
-      AddrEqOp -> condIntReg EQQ  x y
-      AddrNeOp -> condIntReg NE  x y
-      AddrLtOp -> condIntReg LU  x y
-      AddrLeOp -> condIntReg LEU x y
-
-      FloatGtOp -> condFltReg GTT x y
-      FloatGeOp -> condFltReg GE x y
-      FloatEqOp -> condFltReg EQQ x y
-      FloatNeOp -> condFltReg NE x y
-      FloatLtOp -> condFltReg LTT x y
-      FloatLeOp -> condFltReg LE x y
-
-      DoubleGtOp -> condFltReg GTT x y
-      DoubleGeOp -> condFltReg GE x y
-      DoubleEqOp -> condFltReg EQQ x y
-      DoubleNeOp -> condFltReg NE x y
-      DoubleLtOp -> condFltReg LTT x y
-      DoubleLeOp -> condFltReg LE x y
-
-      IntAddOp  -> add_code L x y
-      IntSubOp  -> sub_code L x y
-      IntQuotOp -> trivialCode (IQUOT L) Nothing x y
-      IntRemOp  -> trivialCode (IREM L) Nothing x y
-      IntMulOp  -> let op = IMUL L in trivialCode op (Just op) x y
-
-      WordAddOp  -> add_code L x y
-      WordSubOp  -> sub_code L x y
-      WordMulOp  -> let op = IMUL L in trivialCode op (Just op) 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 GADD x y
-      DoubleSubOp -> trivialFCode DoubleRep GSUB x y
-      DoubleMulOp -> trivialFCode DoubleRep GMUL x y
-      DoubleDivOp -> trivialFCode DoubleRep GDIV x y
-
-      AndOp -> let op = AND L in trivialCode op (Just op) x y
-      OrOp  -> let op = OR  L in trivialCode op (Just op) x y
-      XorOp -> let op = XOR L in trivialCode op (Just op) x y
+         = case mop of
+             MO_Flt_Exp   -> (True,  FSLIT("exp"))
+             MO_Flt_Log   -> (True,  FSLIT("log"))
+
+             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_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(x86) - binary StMachOp (2)" 
+                                (pprMachOp mop)
+
+
+getRegister (StMachOp mop [x, y]) -- dyadic MachOps
+  = case mop of
+      MO_32U_Gt  -> condIntReg GTT x y
+      MO_32U_Ge  -> condIntReg GE x y
+      MO_32U_Eq  -> condIntReg EQQ x y
+      MO_32U_Ne  -> condIntReg NE x y
+      MO_32U_Lt  -> condIntReg LTT x y
+      MO_32U_Le  -> condIntReg LE x y
+
+      MO_Nat_Eq   -> condIntReg EQQ x y
+      MO_Nat_Ne   -> condIntReg NE x y
+
+      MO_NatS_Gt  -> condIntReg GTT x y
+      MO_NatS_Ge  -> condIntReg GE x y
+      MO_NatS_Lt  -> condIntReg LTT x y
+      MO_NatS_Le  -> condIntReg LE x y
+
+      MO_NatU_Gt  -> condIntReg GU  x y
+      MO_NatU_Ge  -> condIntReg GEU x y
+      MO_NatU_Lt  -> condIntReg LU  x y
+      MO_NatU_Le  -> condIntReg LEU x y
+
+      MO_Flt_Gt -> condFltReg GTT x y
+      MO_Flt_Ge -> condFltReg GE x y
+      MO_Flt_Eq -> condFltReg EQQ x y
+      MO_Flt_Ne -> condFltReg NE x y
+      MO_Flt_Lt -> condFltReg LTT x y
+      MO_Flt_Le -> condFltReg LE x y
+
+      MO_Dbl_Gt -> condFltReg GTT x y
+      MO_Dbl_Ge -> condFltReg GE x y
+      MO_Dbl_Eq -> condFltReg EQQ x y
+      MO_Dbl_Ne -> condFltReg NE x y
+      MO_Dbl_Lt -> condFltReg LTT x y
+      MO_Dbl_Le -> condFltReg LE x y
+
+      MO_Nat_Add   -> add_code L x y
+      MO_Nat_Sub   -> sub_code L x y
+      MO_NatS_Quot -> trivialCode (IQUOT L) Nothing x y
+      MO_NatS_Rem  -> trivialCode (IREM L) Nothing x y
+      MO_NatU_Quot -> trivialCode (QUOT L) Nothing x y
+      MO_NatU_Rem  -> trivialCode (REM L) Nothing x y
+      MO_NatS_Mul  -> let op = IMUL L in trivialCode op (Just op) x y
+      MO_NatU_Mul  -> let op = MUL L in trivialCode op (Just op) x y
+      MO_NatS_MulMayOflo -> imulMayOflo x y
+
+      MO_Flt_Add -> trivialFCode  FloatRep  GADD x y
+      MO_Flt_Sub -> trivialFCode  FloatRep  GSUB x y
+      MO_Flt_Mul -> trivialFCode  FloatRep  GMUL x y
+      MO_Flt_Div -> trivialFCode  FloatRep  GDIV x y
+
+      MO_Dbl_Add -> trivialFCode DoubleRep GADD x y
+      MO_Dbl_Sub -> trivialFCode DoubleRep GSUB x y
+      MO_Dbl_Mul -> trivialFCode DoubleRep GMUL x y
+      MO_Dbl_Div -> trivialFCode DoubleRep GDIV x y
+
+      MO_Nat_And -> let op = AND L in trivialCode op (Just op) x y
+      MO_Nat_Or  -> let op = OR  L in trivialCode op (Just op) x y
+      MO_Nat_Xor -> let op = XOR L in trivialCode op (Just op) x y
 
        {- Shift ops on x86s have constraints on their source, it
           either has to be Imm, CL or 1
            => trivialCode's is not restrictive enough (sigh.)
-       -}
-          
-      SllOp  -> shift_code (SHL L) x y {-False-}
-      SrlOp  -> shift_code (SHR L) x y {-False-}
-      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])
-                      where promote x = StPrim Float2DoubleOp [x]
-      DoublePowerOp -> getRegister (StCall SLIT("pow") CCallConv DoubleRep 
-                                           [x, y])
-      other
-         -> pprPanic "getRegister(x86,dyadic primop)" 
-                     (pprStixTree (StPrim primop [x, y]))
+       -}         
+      MO_Nat_Shl  -> shift_code (SHL L) x y {-False-}
+      MO_Nat_Shr  -> shift_code (SHR L) x y {-False-}
+      MO_Nat_Sar  -> shift_code (SAR L) x y {-False-}
+
+      MO_Flt_Pwr  -> getRegister (demote 
+                                 (StCall (Left FSLIT("pow")) CCallConv DoubleRep 
+                                         [promote x, promote y])
+                                 )
+      MO_Dbl_Pwr -> getRegister (StCall (Left FSLIT("pow")) CCallConv DoubleRep 
+                                        [x, y])
+      other -> pprPanic "getRegister(x86) - binary StMachOp (1)" (pprMachOp mop)
   where
+    promote x = StMachOp MO_Flt_to_Dbl [x]
+    demote x  = StMachOp MO_Dbl_to_Flt [x]
+
+    --------------------
+    imulMayOflo :: StixExpr -> StixExpr -> NatM Register
+    imulMayOflo a1 a2
+       = getNewRegNCG IntRep           `thenNat` \ t1 ->
+         getNewRegNCG IntRep           `thenNat` \ t2 ->
+         getNewRegNCG IntRep           `thenNat` \ res_lo ->
+         getNewRegNCG IntRep           `thenNat` \ res_hi ->
+         getRegister a1                        `thenNat` \ reg1 ->
+         getRegister a2                `thenNat` \ reg2 ->
+         let code1 = registerCode reg1 t1
+             code2 = registerCode reg2 t2
+             src1  = registerName reg1 t1
+             src2  = registerName reg2 t2
+             code dst = code1 `appOL` code2 `appOL`
+                        toOL [
+                           MOV L (OpReg src1) (OpReg res_hi),
+                           MOV L (OpReg src2) (OpReg res_lo),
+                           IMUL64 res_hi res_lo,               -- result in res_hi:res_lo
+                           SAR L (ImmInt 31) (OpReg res_lo),   -- sign extend lower part
+                           SUB L (OpReg res_hi) (OpReg res_lo),        -- compare against upper
+                           MOV L (OpReg res_lo) (OpReg dst)
+                           -- dst==0 if high part == sign extended low part
+                        ]
+         in
+            returnNat (Any IntRep code)
 
     --------------------
     shift_code :: (Imm -> Operand -> Instr)
-              -> StixTree
-              -> StixTree
+              -> StixExpr
+              -> StixExpr
               -> NatM Register
 
       {- Case1: shift length as immediate -}
@@ -846,7 +1188,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
                     code_val `snocOL`
                     MOV L (OpReg src_val) r_dst `appOL`
                     toOL [
-                       COMMENT (_PK_ "begin shift sequence"),
+                       COMMENT (mkFastString "begin shift sequence"),
                        MOV L (OpReg src_val) r_dst,
                        MOV L (OpReg src_amt) r_tmp,
 
@@ -875,13 +1217,13 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
                        instr (ImmInt 1) r_dst,
                        LABEL lbl_after,
                                            
-                       COMMENT (_PK_ "end shift sequence")
+                       COMMENT (mkFastString "end shift sequence")
                     ]
        in
        returnNat (Any IntRep code__2)
 
     --------------------
-    add_code :: Size -> StixTree -> StixTree -> NatM Register
+    add_code :: Size -> StixExpr -> StixExpr -> NatM Register
 
     add_code sz x (StInt y)
       = getRegister x          `thenNat` \ register ->
@@ -900,7 +1242,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
     add_code sz x y = trivialCode (ADD sz) (Just (ADD sz)) x y
 
     --------------------
-    sub_code :: Size -> StixTree -> StixTree -> NatM Register
+    sub_code :: Size -> StixExpr -> StixExpr -> NatM Register
 
     sub_code sz x (StInt y)
       = getRegister x          `thenNat` \ register ->
@@ -918,8 +1260,8 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
 
     sub_code sz x y = trivialCode (SUB sz) Nothing x y
 
-
 getRegister (StInd pk mem)
+  | not (is64BitRep pk)
   = getAmode mem                   `thenNat` \ amode ->
     let
        code = amodeCode amode
@@ -956,13 +1298,15 @@ getRegister leaf
     in
        returnNat (Any PtrRep code)
   | otherwise
-  = pprPanic "getRegister(x86)" (pprStixTree leaf)
+  = ncgPrimopMoan "getRegister(x86)" (pprStixExpr leaf)
   where
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 getRegister (StFloat d)
@@ -991,169 +1335,197 @@ getRegister (StDouble d)
     in
        returnNat (Any DoubleRep code)
 
--- The 6-word scratch area is immediately below the frame pointer.
--- Below that is the spill area.
-getRegister (StScratchWord i)
-   | i >= 0 && i < 6
-   = let
-         code dst = unitOL (fpRelEA (i-6) dst)
-     in 
-     returnNat (Any PtrRep code)
 
+getRegister (StMachOp mop [x]) -- unary PrimOps
+  = case mop of
+      MO_NatS_Neg      -> trivialUCode (SUB False False g0) x
+      MO_Nat_Not       -> trivialUCode (XNOR False g0) x
+      MO_32U_to_8U     -> trivialCode (AND False) x (StInt 255)
 
-getRegister (StPrim primop [x]) -- unary PrimOps
-  = case primop of
-      IntNegOp       -> trivialUCode (SUB False False g0) x
-      NotOp          -> trivialUCode (XNOR False g0) x
+      MO_Flt_Neg       -> trivialUFCode FloatRep (FNEG F) x
+      MO_Dbl_Neg       -> trivialUFCode DoubleRep (FNEG DF) x
 
-      FloatNegOp     -> trivialUFCode FloatRep (FNEG F) x
-      DoubleNegOp    -> trivialUFCode DoubleRep (FNEG DF) x
+      MO_Dbl_to_Flt    -> coerceDbl2Flt x
+      MO_Flt_to_Dbl    -> coerceFlt2Dbl x
 
-      Double2FloatOp -> trivialUFCode FloatRep  (FxTOy DF F) x
-      Float2DoubleOp -> trivialUFCode DoubleRep (FxTOy F DF) x
+      MO_Flt_to_NatS   -> coerceFP2Int FloatRep x
+      MO_NatS_to_Flt   -> coerceInt2FP FloatRep x
+      MO_Dbl_to_NatS   -> coerceFP2Int DoubleRep x
+      MO_NatS_to_Dbl   -> coerceInt2FP DoubleRep x
 
-      OrdOp          -> coerceIntCode IntRep x
-      ChrOp          -> chrCode x
+      -- Conversions which are a nop on sparc
+      MO_32U_to_NatS   -> conversionNop IntRep   x
+      MO_32S_to_NatS  -> conversionNop IntRep   x
+      MO_NatS_to_32U   -> conversionNop WordRep  x
+      MO_32U_to_NatU   -> conversionNop WordRep  x
 
-      Float2IntOp    -> coerceFP2Int x
-      Int2FloatOp    -> coerceInt2FP FloatRep x
-      Double2IntOp   -> coerceFP2Int x
-      Int2DoubleOp   -> coerceInt2FP DoubleRep x
+      MO_NatU_to_NatS -> conversionNop IntRep    x
+      MO_NatS_to_NatU -> conversionNop WordRep   x
+      MO_NatP_to_NatU -> conversionNop WordRep   x
+      MO_NatU_to_NatP -> conversionNop PtrRep    x
+      MO_NatS_to_NatP -> conversionNop PtrRep    x
+      MO_NatP_to_NatS -> conversionNop IntRep    x
+
+      -- sign-extending widenings
+      MO_8U_to_32U    -> integerExtend False 24 x
+      MO_8U_to_NatU   -> integerExtend False 24 x
+      MO_8S_to_NatS   -> integerExtend True  24 x
+      MO_16U_to_NatU  -> integerExtend False 16 x
+      MO_16S_to_NatS  -> integerExtend True  16 x
 
       other_op ->
-        let
-           fixed_x = if   is_float_op  -- promote to double
-                     then StPrim Float2DoubleOp [x]
-                     else x
+        let fixed_x = if   is_float_op  -- promote to double
+                      then StMachOp MO_Flt_to_Dbl [x]
+                      else x
        in
-       getRegister (StCall fn CCallConv DoubleRep [fixed_x])
-       where
-       (is_float_op, fn)
-         = case primop of
-             FloatExpOp    -> (True,  SLIT("exp"))
-             FloatLogOp    -> (True,  SLIT("log"))
-             FloatSqrtOp   -> (True,  SLIT("sqrt"))
-
-             FloatSinOp    -> (True,  SLIT("sin"))
-             FloatCosOp    -> (True,  SLIT("cos"))
-             FloatTanOp    -> (True,  SLIT("tan"))
-
-             FloatAsinOp   -> (True,  SLIT("asin"))
-             FloatAcosOp   -> (True,  SLIT("acos"))
-             FloatAtanOp   -> (True,  SLIT("atan"))
-
-             FloatSinhOp   -> (True,  SLIT("sinh"))
-             FloatCoshOp   -> (True,  SLIT("cosh"))
-             FloatTanhOp   -> (True,  SLIT("tanh"))
-
-             DoubleExpOp   -> (False, SLIT("exp"))
-             DoubleLogOp   -> (False, SLIT("log"))
-             DoubleSqrtOp  -> (False, SLIT("sqrt"))
-
-             DoubleSinOp   -> (False, SLIT("sin"))
-             DoubleCosOp   -> (False, SLIT("cos"))
-             DoubleTanOp   -> (False, SLIT("tan"))
-
-             DoubleAsinOp  -> (False, SLIT("asin"))
-             DoubleAcosOp  -> (False, SLIT("acos"))
-             DoubleAtanOp  -> (False, SLIT("atan"))
-
-             DoubleSinhOp  -> (False, SLIT("sinh"))
-             DoubleCoshOp  -> (False, SLIT("cosh"))
-             DoubleTanhOp  -> (False, SLIT("tanh"))
-
-              other
-                 -> pprPanic "getRegister(sparc,monadicprimop)" 
-                             (pprStixTree (StPrim primop [x]))
-
-getRegister (StPrim primop [x, y]) -- dyadic PrimOps
-  = case primop of
-      CharGtOp -> condIntReg GTT x y
-      CharGeOp -> condIntReg GE x y
-      CharEqOp -> condIntReg EQQ x y
-      CharNeOp -> condIntReg NE x y
-      CharLtOp -> condIntReg LTT x y
-      CharLeOp -> condIntReg LE x y
-
-      IntGtOp  -> condIntReg GTT x y
-      IntGeOp  -> condIntReg GE x y
-      IntEqOp  -> condIntReg EQQ x y
-      IntNeOp  -> condIntReg NE x y
-      IntLtOp  -> condIntReg LTT x y
-      IntLeOp  -> condIntReg LE x y
-
-      WordGtOp -> condIntReg GU  x y
-      WordGeOp -> condIntReg GEU x y
-      WordEqOp -> condIntReg EQQ  x y
-      WordNeOp -> condIntReg NE  x y
-      WordLtOp -> condIntReg LU  x y
-      WordLeOp -> condIntReg LEU x y
-
-      AddrGtOp -> condIntReg GU  x y
-      AddrGeOp -> condIntReg GEU x y
-      AddrEqOp -> condIntReg EQQ  x y
-      AddrNeOp -> condIntReg NE  x y
-      AddrLtOp -> condIntReg LU  x y
-      AddrLeOp -> condIntReg LEU x y
-
-      FloatGtOp -> condFltReg GTT x y
-      FloatGeOp -> condFltReg GE x y
-      FloatEqOp -> condFltReg EQQ x y
-      FloatNeOp -> condFltReg NE x y
-      FloatLtOp -> condFltReg LTT x y
-      FloatLeOp -> condFltReg LE x y
-
-      DoubleGtOp -> condFltReg GTT x y
-      DoubleGeOp -> condFltReg GE x y
-      DoubleEqOp -> condFltReg EQQ x y
-      DoubleNeOp -> condFltReg NE x y
-      DoubleLtOp -> condFltReg LTT x y
-      DoubleLeOp -> condFltReg LE x y
-
-      IntAddOp -> trivialCode (ADD False False) x y
-      IntSubOp -> trivialCode (SUB False False) x y
-
-       -- ToDo: teach about V8+ SPARC mul/div instructions
-      IntMulOp  -> imul_div SLIT(".umul") x y
-      IntQuotOp -> imul_div SLIT(".div")  x y
-      IntRemOp  -> imul_div SLIT(".rem")  x y
-
-      WordAddOp -> trivialCode (ADD False False) x y
-      WordSubOp -> trivialCode (SUB False False) x y
-      WordMulOp -> imul_div SLIT(".umul") x y
-
-      FloatAddOp  -> trivialFCode FloatRep  FADD x y
-      FloatSubOp  -> trivialFCode FloatRep  FSUB x y
-      FloatMulOp  -> trivialFCode FloatRep  FMUL x y
-      FloatDivOp  -> trivialFCode FloatRep  FDIV x y
-
-      DoubleAddOp -> trivialFCode DoubleRep FADD x y
-      DoubleSubOp -> trivialFCode DoubleRep FSUB x y
-      DoubleMulOp -> trivialFCode DoubleRep FMUL x y
-      DoubleDivOp -> trivialFCode DoubleRep FDIV x y
-
-      AndOp -> trivialCode (AND False) x y
-      OrOp  -> trivialCode (OR  False) x y
-      XorOp -> trivialCode (XOR False) x y
-      SllOp -> trivialCode SLL x y
-      SrlOp -> trivialCode SRL x y
-
-      ISllOp -> trivialCode SLL x y
-      ISraOp -> trivialCode SRA x y
-      ISrlOp -> trivialCode SRL x 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])
-
-      other
-         -> pprPanic "getRegister(sparc,dyadic primop)" 
-                     (pprStixTree (StPrim primop [x, y]))
+       getRegister (StCall (Left fn) CCallConv DoubleRep [fixed_x])
+    where
+        integerExtend signed nBits x
+           = getRegister (
+                StMachOp (if signed then MO_Nat_Sar else MO_Nat_Shr) 
+                         [StMachOp MO_Nat_Shl [x, StInt nBits], StInt nBits]
+             )
+        conversionNop new_rep expr
+            = 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(sparc) - binary StMachOp (2)" 
+                                (pprMachOp mop)
+
+
+getRegister (StMachOp mop [x, y]) -- dyadic PrimOps
+  = case mop of
+      MO_32U_Gt  -> condIntReg GTT x y
+      MO_32U_Ge  -> condIntReg GE x y
+      MO_32U_Eq  -> condIntReg EQQ x y
+      MO_32U_Ne  -> condIntReg NE x y
+      MO_32U_Lt  -> condIntReg LTT x y
+      MO_32U_Le  -> condIntReg LE x y
+
+      MO_Nat_Eq   -> condIntReg EQQ x y
+      MO_Nat_Ne   -> condIntReg NE x y
+
+      MO_NatS_Gt  -> condIntReg GTT x y
+      MO_NatS_Ge  -> condIntReg GE x y
+      MO_NatS_Lt  -> condIntReg LTT x y
+      MO_NatS_Le  -> condIntReg LE x y
+
+      MO_NatU_Gt  -> condIntReg GU  x y
+      MO_NatU_Ge  -> condIntReg GEU x y
+      MO_NatU_Lt  -> condIntReg LU  x y
+      MO_NatU_Le  -> condIntReg LEU x y
+
+      MO_Flt_Gt -> condFltReg GTT x y
+      MO_Flt_Ge -> condFltReg GE x y
+      MO_Flt_Eq -> condFltReg EQQ x y
+      MO_Flt_Ne -> condFltReg NE x y
+      MO_Flt_Lt -> condFltReg LTT x y
+      MO_Flt_Le -> condFltReg LE x y
+
+      MO_Dbl_Gt -> condFltReg GTT x y
+      MO_Dbl_Ge -> condFltReg GE x y
+      MO_Dbl_Eq -> condFltReg EQQ x y
+      MO_Dbl_Ne -> condFltReg NE x y
+      MO_Dbl_Lt -> condFltReg LTT x y
+      MO_Dbl_Le -> condFltReg LE x y
+
+      MO_Nat_Add -> trivialCode (ADD False False) x y
+      MO_Nat_Sub -> trivialCode (SUB False False) x y
+
+      MO_NatS_Mul  -> trivialCode (SMUL False) x y
+      MO_NatU_Mul  -> trivialCode (UMUL False) x y
+      MO_NatS_MulMayOflo -> imulMayOflo x y
+
+      -- 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
+      MO_Flt_Div   -> trivialFCode FloatRep  FDIV x y
+
+      MO_Dbl_Add   -> trivialFCode DoubleRep FADD x y
+      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_Nat_And   -> trivialCode (AND False) x y
+      MO_Nat_Or    -> trivialCode (OR  False) x y
+      MO_Nat_Xor   -> trivialCode (XOR False) x y
+
+      MO_Nat_Shl   -> trivialCode SLL x y
+      MO_Nat_Shr   -> trivialCode SRL x y
+      MO_Nat_Sar   -> trivialCode SRA 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]
+      MO_Dbl_Pwr -> getRegister (StCall (Left FSLIT("pow")) CCallConv DoubleRep 
+                                        [x, y])
+
+      other -> pprPanic "getRegister(sparc) - binary StMachOp (1)" (pprMachOp mop)
   where
-    imul_div fn x y = getRegister (StCall fn CCallConv IntRep [x, y])
+    idiv fn x y = getRegister (StCall (Left fn) CCallConv IntRep [x, y])
+
+    --------------------
+    imulMayOflo :: StixExpr -> StixExpr -> NatM Register
+    imulMayOflo a1 a2
+       = getNewRegNCG IntRep           `thenNat` \ t1 ->
+         getNewRegNCG IntRep           `thenNat` \ t2 ->
+         getNewRegNCG IntRep           `thenNat` \ res_lo ->
+         getNewRegNCG IntRep           `thenNat` \ res_hi ->
+         getRegister a1                        `thenNat` \ reg1 ->
+         getRegister a2                `thenNat` \ reg2 ->
+         let code1 = registerCode reg1 t1
+             code2 = registerCode reg2 t2
+             src1  = registerName reg1 t1
+             src2  = registerName reg2 t2
+             code dst = code1 `appOL` code2 `appOL`
+                        toOL [
+                           SMUL False src1 (RIReg src2) res_lo,
+                           RDY res_hi,
+                           SRA res_lo (RIImm (ImmInt 31)) res_lo,
+                           SUB False False res_lo (RIReg res_hi) dst
+                        ]
+         in
+            returnNat (Any IntRep code)
 
 getRegister (StInd pk mem)
   = getAmode mem                   `thenNat` \ amode ->
@@ -1182,12 +1554,241 @@ getRegister leaf
     in
        returnNat (Any PtrRep code)
   | otherwise
-  = pprPanic "getRegister(sparc)" (pprStixTree leaf)
+  = ncgPrimopMoan "getRegister(sparc)" (pprStixExpr leaf)
   where
     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
+  = case mop of
+      MO_NatS_Neg  -> trivialUCode NEG x
+      MO_Nat_Not   -> trivialUCode NOT x
+      MO_32U_to_8U     -> trivialCode AND x (StInt 255)
+
+      MO_Flt_to_NatS -> coerceFP2Int FloatRep x
+      MO_NatS_to_Flt -> coerceInt2FP FloatRep x
+      MO_Dbl_to_NatS -> coerceFP2Int DoubleRep x
+      MO_NatS_to_Dbl -> coerceInt2FP DoubleRep x
+
+      -- Conversions which are a nop on PPC
+      MO_NatS_to_32U  -> conversionNop WordRep   x
+      MO_32U_to_NatS  -> conversionNop IntRep    x
+      MO_32U_to_NatU  -> conversionNop WordRep   x
+
+      MO_NatU_to_NatS -> conversionNop IntRep    x
+      MO_NatS_to_NatU -> conversionNop WordRep   x
+      MO_NatP_to_NatU -> conversionNop WordRep   x
+      MO_NatU_to_NatP -> conversionNop PtrRep    x
+      MO_NatS_to_NatP -> conversionNop PtrRep    x
+      MO_NatP_to_NatS -> conversionNop IntRep    x
+
+      MO_Dbl_to_Flt   -> conversionNop FloatRep  x
+      MO_Flt_to_Dbl   -> conversionNop DoubleRep x
+
+      -- sign-extending widenings      ###PPC This is inefficient: use ext* instructions
+      MO_8U_to_NatU   -> integerExtend False 24 x
+      MO_8S_to_NatS   -> integerExtend True  24 x
+      MO_16U_to_NatU  -> integerExtend False 16 x
+      MO_16S_to_NatS  -> integerExtend True  16 x
+      MO_8U_to_32U    -> integerExtend False 24 x
+
+      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 (
+                StMachOp (if signed then MO_Nat_Sar else MO_Nat_Shr) 
+                         [StMachOp MO_Nat_Shl [x, StInt nBits], StInt nBits]
+             )
+        conversionNop new_rep expr
+            = 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
+      MO_32U_Ge  -> condIntReg GE x y
+      MO_32U_Eq  -> condIntReg EQQ x y
+      MO_32U_Ne  -> condIntReg NE x y
+      MO_32U_Lt  -> condIntReg LTT x y
+      MO_32U_Le  -> condIntReg LE x y
+
+      MO_Nat_Eq   -> condIntReg EQQ x y
+      MO_Nat_Ne   -> condIntReg NE x y
+
+      MO_NatS_Gt  -> condIntReg GTT x y
+      MO_NatS_Ge  -> condIntReg GE x y
+      MO_NatS_Lt  -> condIntReg LTT x y
+      MO_NatS_Le  -> condIntReg LE x y
+
+      MO_NatU_Gt  -> condIntReg GU  x y
+      MO_NatU_Ge  -> condIntReg GEU x y
+      MO_NatU_Lt  -> condIntReg LU  x y
+      MO_NatU_Le  -> condIntReg LEU x y
+
+      MO_Flt_Gt -> condFltReg GTT x y
+      MO_Flt_Ge -> condFltReg GE x y
+      MO_Flt_Eq -> condFltReg EQQ x y
+      MO_Flt_Ne -> condFltReg NE x y
+      MO_Flt_Lt -> condFltReg LTT x y
+      MO_Flt_Le -> condFltReg LE x y
+
+      MO_Dbl_Gt -> condFltReg GTT x y
+      MO_Dbl_Ge -> condFltReg GE x y
+      MO_Dbl_Eq -> condFltReg EQQ x y
+      MO_Dbl_Ne -> condFltReg NE x y
+      MO_Dbl_Lt -> condFltReg LTT x y
+      MO_Dbl_Le -> condFltReg LE x y
+
+      MO_Nat_Add -> trivialCode ADD x y
+      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
+
+      MO_Nat_Shl   -> trivialCode SLW x y
+      MO_Nat_Shr   -> trivialCode SRW x y
+      MO_Nat_Sar   -> trivialCode SRAW 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
+      MO_Flt_Div   -> trivialFCode FloatRep  FDIV x y
+
+      MO_Dbl_Add   -> trivialFCode DoubleRep FADD x y
+      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 
+                                         [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)
+  = getAmode mem                   `thenNat` \ amode ->
+    let
+       code = amodeCode amode
+       src   = amodeAddr amode
+       size = primRepToSize pk
+       code__2 dst = code `snocOL` LD size dst src
+    in
+       returnNat (Any pk code__2)
+
+getRegister (StInt i)
+  | fits16Bits i
+  = let
+       src = ImmInt (fromInteger i)
+       code dst = unitOL (LI dst src)
+    in
+       returnNat (Any IntRep code)
+
+getRegister (StFloat d)
+  = getNatLabelNCG                 `thenNat` \ lbl ->
+    getNewRegNCG PtrRep            `thenNat` \ tmp ->
+    let code dst = toOL [
+           SEGMENT RoDataSegment,
+           LABEL lbl,
+           DATA F [ImmFloat d],
+           SEGMENT TextSegment,
+           LIS tmp (HA (ImmCLbl lbl)),
+           LD F dst (AddrRegImm tmp (LO (ImmCLbl lbl)))]
+    in
+       returnNat (Any FloatRep code)
+
+getRegister (StDouble d)
+  = getNatLabelNCG                 `thenNat` \ lbl ->
+    getNewRegNCG PtrRep            `thenNat` \ tmp ->
+    let code dst = toOL [
+           SEGMENT RoDataSegment,
+           LABEL lbl,
+           DATA DF [ImmDouble d],
+           SEGMENT TextSegment,
+           LIS tmp (HA (ImmCLbl lbl)),
+           LD DF dst (AddrRegImm tmp (LO (ImmCLbl lbl)))]
+    in
+       returnNat (Any DoubleRep code)
+
+getRegister leaf
+  | maybeToBool imm
+  = let
+       code dst = toOL [
+           LIS dst (HI imm__2),
+           OR dst dst (RIImm (LO imm__2))]
+    in
+       returnNat (Any PtrRep code)
+  | otherwise
+  = ncgPrimopMoan "getRegister(powerpc)" (pprStixExpr leaf)
+  where
+    imm = maybeImm leaf
+    imm__2 = case imm of Just x -> x
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 \end{code}
 
 %************************************************************************
@@ -1221,10 +1822,12 @@ temporary, then do the other computation, and then use the temporary:
     ... (tmp) ...
 
 \begin{code}
-getAmode :: StixTree -> NatM Amode
+getAmode :: StixExpr -> NatM Amode
 
 getAmode tree@(StIndex _ _ _) = getAmode (mangleIndexTree tree)
 
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if alpha_TARGET_ARCH
 
 getAmode (StPrim IntSubOp [x, StInt i])
@@ -1263,11 +1866,15 @@ getAmode other
     in
     returnNat (Amode (AddrReg reg) code)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
-getAmode (StPrim IntSubOp [x, StInt i])
+-- This is all just ridiculous, since it carefully undoes 
+-- what mangleIndexTree has just done.
+getAmode (StMachOp MO_Nat_Sub [x, StInt i])
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
     let
@@ -1277,14 +1884,14 @@ getAmode (StPrim IntSubOp [x, StInt i])
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
-getAmode (StPrim IntAddOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
   | maybeToBool imm
   = returnNat (Amode (ImmAddr imm__2 (fromInteger i)) nilOL)
   where
     imm    = maybeImm x
     imm__2 = case imm of Just x -> x
 
-getAmode (StPrim IntAddOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
     let
@@ -1294,7 +1901,7 @@ getAmode (StPrim IntAddOp [x, StInt i])
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
-getAmode (StPrim IntAddOp [x, StPrim SllOp [y, StInt shift]])
+getAmode (StMachOp MO_Nat_Add [x, StMachOp MO_Nat_Shl [y, StInt shift]])
   | shift == 0 || shift == 1 || shift == 2 || shift == 3
   = getNewRegNCG PtrRep                `thenNat` \ tmp1 ->
     getNewRegNCG IntRep        `thenNat` \ tmp2 ->
@@ -1327,11 +1934,13 @@ getAmode other
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing (ImmInt 0)) code)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
-getAmode (StPrim IntSubOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Sub [x, StInt i])
   | fits13Bits (-i)
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
@@ -1343,7 +1952,7 @@ getAmode (StPrim IntSubOp [x, StInt i])
     returnNat (Amode (AddrRegImm reg off) code)
 
 
-getAmode (StPrim IntAddOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
   | fits13Bits i
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
@@ -1354,7 +1963,7 @@ getAmode (StPrim IntAddOp [x, StInt i])
     in
     returnNat (Amode (AddrRegImm reg off) code)
 
-getAmode (StPrim IntAddOp [x, y])
+getAmode (StMachOp MO_Nat_Add [x, y])
   = getNewRegNCG PtrRep        `thenNat` \ tmp1 ->
     getNewRegNCG IntRep        `thenNat` \ tmp2 ->
     getRegister x              `thenNat` \ register1 ->
@@ -1389,7 +1998,55 @@ 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])
+  | fits16Bits (-i)
+  = getNewRegNCG PtrRep                `thenNat` \ tmp ->
+    getRegister x              `thenNat` \ register ->
+    let
+       code = registerCode register tmp
+       reg  = registerName register tmp
+       off  = ImmInt (-(fromInteger i))
+    in
+    returnNat (Amode (AddrRegImm reg off) code)
+
+
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
+  | fits16Bits i
+  = getNewRegNCG PtrRep                `thenNat` \ tmp ->
+    getRegister x              `thenNat` \ register ->
+    let
+       code = registerCode register tmp
+       reg  = registerName register tmp
+       off  = ImmInt (fromInteger i)
+    in
+    returnNat (Amode (AddrRegImm reg off) code)
+
+getAmode leaf
+  | maybeToBool imm
+  = getNewRegNCG PtrRep            `thenNat` \ tmp ->
+    let
+       code = unitOL (LIS tmp (HA imm__2))
+    in
+    returnNat (Amode (AddrRegImm tmp (LO imm__2)) code)
+  where
+    imm    = maybeImm leaf
+    imm__2 = case imm of Just x -> x
+
+getAmode other
+  = getNewRegNCG PtrRep                `thenNat` \ tmp ->
+    getRegister other          `thenNat` \ register ->
+    let
+       code = registerCode register tmp
+       reg  = registerName register tmp
+       off  = ImmInt 0
+    in
+    returnNat (Amode (AddrRegImm reg off) code)
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -1402,69 +2059,71 @@ Condition codes passed up the tree.
 \begin{code}
 data CondCode = CondCode Bool Cond InstrBlock
 
-condName  (CondCode _ cond _)     = cond
+condName  (CondCode _ cond _)    = cond
 condFloat (CondCode is_float _ _) = is_float
-condCode  (CondCode _ _ code)     = code
+condCode  (CondCode _ _ code)    = code
 \end{code}
 
 Set up a condition code for a conditional branch.
 
 \begin{code}
-getCondCode :: StixTree -> NatM CondCode
+getCondCode :: StixExpr -> NatM CondCode
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 #if alpha_TARGET_ARCH
 getCondCode = panic "MachCode.getCondCode: not on Alphas"
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-#if i386_TARGET_ARCH || sparc_TARGET_ARCH
+#if i386_TARGET_ARCH || sparc_TARGET_ARCH || powerpc_TARGET_ARCH
 -- yes, they really do seem to want exactly the same!
 
-getCondCode (StPrim primop [x, y])
-  = case primop of
-      CharGtOp -> condIntCode GTT  x y
-      CharGeOp -> condIntCode GE   x y
-      CharEqOp -> condIntCode EQQ  x y
-      CharNeOp -> condIntCode NE   x y
-      CharLtOp -> condIntCode LTT  x y
-      CharLeOp -> condIntCode LE   x y
+getCondCode (StMachOp mop [x, y])
+  = case mop of
+      MO_32U_Gt -> condIntCode GTT  x y
+      MO_32U_Ge -> condIntCode GE   x y
+      MO_32U_Eq -> condIntCode EQQ  x y
+      MO_32U_Ne -> condIntCode NE   x y
+      MO_32U_Lt -> condIntCode LTT  x y
+      MO_32U_Le -> condIntCode LE   x y
  
-      IntGtOp  -> condIntCode GTT  x y
-      IntGeOp  -> condIntCode GE   x y
-      IntEqOp  -> condIntCode EQQ  x y
-      IntNeOp  -> condIntCode NE   x y
-      IntLtOp  -> condIntCode LTT  x y
-      IntLeOp  -> condIntCode LE   x y
-
-      WordGtOp -> condIntCode GU   x y
-      WordGeOp -> condIntCode GEU  x y
-      WordEqOp -> condIntCode EQQ  x y
-      WordNeOp -> condIntCode NE   x y
-      WordLtOp -> condIntCode LU   x y
-      WordLeOp -> condIntCode LEU  x y
-
-      AddrGtOp -> condIntCode GU   x y
-      AddrGeOp -> condIntCode GEU  x y
-      AddrEqOp -> condIntCode EQQ  x y
-      AddrNeOp -> condIntCode NE   x y
-      AddrLtOp -> condIntCode LU   x y
-      AddrLeOp -> condIntCode LEU  x y
-
-      FloatGtOp -> condFltCode GTT x y
-      FloatGeOp -> condFltCode GE  x y
-      FloatEqOp -> condFltCode EQQ x y
-      FloatNeOp -> condFltCode NE  x y
-      FloatLtOp -> condFltCode LTT x y
-      FloatLeOp -> condFltCode LE  x y
-
-      DoubleGtOp -> condFltCode GTT x y
-      DoubleGeOp -> condFltCode GE  x y
-      DoubleEqOp -> condFltCode EQQ x y
-      DoubleNeOp -> condFltCode NE  x y
-      DoubleLtOp -> condFltCode LTT x y
-      DoubleLeOp -> condFltCode LE  x y
-
-#endif {- i386_TARGET_ARCH || sparc_TARGET_ARCH -}
+      MO_Nat_Eq  -> condIntCode EQQ  x y
+      MO_Nat_Ne  -> condIntCode NE   x y
+
+      MO_NatS_Gt -> condIntCode GTT  x y
+      MO_NatS_Ge -> condIntCode GE   x y
+      MO_NatS_Lt -> condIntCode LTT  x y
+      MO_NatS_Le -> condIntCode LE   x y
+
+      MO_NatU_Gt -> condIntCode GU   x y
+      MO_NatU_Ge -> condIntCode GEU  x y
+      MO_NatU_Lt -> condIntCode LU   x y
+      MO_NatU_Le -> condIntCode LEU  x y
+
+      MO_Flt_Gt -> condFltCode GTT x y
+      MO_Flt_Ge -> condFltCode GE  x y
+      MO_Flt_Eq -> condFltCode EQQ x y
+      MO_Flt_Ne -> condFltCode NE  x y
+      MO_Flt_Lt -> condFltCode LTT x y
+      MO_Flt_Le -> condFltCode LE  x y
+
+      MO_Dbl_Gt -> condFltCode GTT x y
+      MO_Dbl_Ge -> condFltCode GE  x y
+      MO_Dbl_Eq -> condFltCode EQQ x y
+      MO_Dbl_Ne -> condFltCode NE  x y
+      MO_Dbl_Lt -> condFltCode LTT x y
+      MO_Dbl_Le -> condFltCode LE  x y
+
+      other -> pprPanic "getCondCode(x86,sparc,powerpc)" (pprMachOp mop)
+
+getCondCode other =  pprPanic "getCondCode(2)(x86,sparc,powerpc)" (pprStixExpr other)
+
+#endif /* i386_TARGET_ARCH || sparc_TARGET_ARCH || powerpc_TARGET_ARCH */
+
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 % -----------------
@@ -1473,31 +2132,28 @@ getCondCode (StPrim primop [x, y])
 passed back up the tree.
 
 \begin{code}
-condIntCode, condFltCode :: Cond -> StixTree -> StixTree -> NatM CondCode
+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
 
 -- memory vs immediate
 condIntCode cond (StInd pk x) y
-  | maybeToBool imm
+  | Just i <- maybeImm y
   = getAmode x                 `thenNat` \ amode ->
     let
        code1 = amodeCode amode
        x__2  = amodeAddr amode
         sz    = primRepToSize pk
        code__2 = code1 `snocOL`
-                 CMP sz (OpImm imm__2) (OpAddr x__2)
+                 CMP sz (OpImm i) (OpAddr x__2)
     in
     returnNat (CondCode False cond code__2)
-  where
-    imm    = maybeImm y
-    imm__2 = case imm of Just x -> x
 
 -- anything vs zero
 condIntCode cond x (StInt 0)
@@ -1513,19 +2169,16 @@ condIntCode cond x (StInt 0)
 
 -- anything vs immediate
 condIntCode cond x y
-  | maybeToBool imm
+  | Just i <- maybeImm y
   = getRegister x              `thenNat` \ register1 ->
     getNewRegNCG IntRep                `thenNat` \ tmp1 ->
     let
        code1 = registerCode register1 tmp1
        src1  = registerName register1 tmp1
        code__2 = code1 `snocOL`
-                  CMP L (OpImm imm__2) (OpReg src1)
+                  CMP L (OpImm i) (OpReg src1)
     in
     returnNat (CondCode False cond code__2)
-  where
-    imm    = maybeImm y
-    imm__2 = case imm of Just x -> x
 
 -- memory vs anything
 condIntCode cond (StInd pk x) y
@@ -1600,7 +2253,8 @@ condIntCode cond x y
 
 -----------
 condFltCode cond x y
-  = getRegister x              `thenNat` \ register1 ->
+  = ASSERT(cond `elem` ([EQQ, NE, LE, LTT, GE, GTT]))
+    getRegister x              `thenNat` \ register1 ->
     getRegister y              `thenNat` \ register2 ->
     getNewRegNCG (registerRep register1)
                                `thenNat` \ tmp1 ->
@@ -1608,7 +2262,6 @@ condFltCode cond x y
                                `thenNat` \ tmp2 ->
     getNewRegNCG DoubleRep     `thenNat` \ tmp ->
     let
-       pk1   = registerRep register1
        code1 = registerCode register1 tmp1
        src1  = registerName register1 tmp1
 
@@ -1618,31 +2271,22 @@ condFltCode cond x y
        code__2 | isAny register1
                 = code1 `appOL`   -- result in tmp1
                   code2 `snocOL`
-                 GCMP (primRepToSize pk1) tmp1 src2
+                 GCMP cond tmp1 src2
                   
                 | otherwise
                 = code1 `snocOL` 
                   GMOV src1 tmp1 `appOL`
                   code2 `snocOL`
-                 GCMP (primRepToSize pk1) tmp1 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
+                 GCMP cond tmp1 src2
     in
-    returnNat (CondCode True (fix_FP_cond cond) code__2)
-
+    -- The GCMP insn does the test and sets the zero flag if comparable
+    -- 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 -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 condIntCode cond x (StInt y)
@@ -1705,7 +2349,59 @@ condFltCode cond x y
     in
     returnNat (CondCode True cond code__2)
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
+
+#if powerpc_TARGET_ARCH
+
+condIntCode cond x (StInt y)
+  | fits16Bits y
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG IntRep                `thenNat` \ tmp ->
+    let
+       code = registerCode register tmp
+       src1 = registerName register tmp
+       src2 = ImmInt (fromInteger y)
+       code__2 = code `snocOL` 
+           (if condUnsigned cond then CMPL else CMP) W src1 (RIImm src2)
+    in
+    returnNat (CondCode False cond code__2)
+
+condIntCode cond 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 = code1 `appOL` code2 `snocOL`
+                 (if condUnsigned cond then CMPL else CMP) W src1 (RIReg src2)
+    in
+    returnNat (CondCode False cond code__2)
+
+condFltCode cond x y
+  = getRegister x              `thenNat` \ register1 ->
+    getRegister y              `thenNat` \ register2 ->
+    getNewRegNCG (registerRep register1)
+                               `thenNat` \ tmp1 ->
+    getNewRegNCG (registerRep register2)
+                               `thenNat` \ tmp2 ->
+    let
+       code1 = registerCode register1 tmp1
+       src1  = registerName register1 tmp1
+       code2 = registerCode register2 tmp2
+       src2  = registerName register2 tmp2
+       code__2 = code1 `appOL` code2 `snocOL`
+                 FCMP src1 src2
+    in
+    returnNat (CondCode False cond code__2)
+
+#endif /* powerpc_TARGET_ARCH */
+
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -1723,8 +2419,13 @@ generation for the right hand side.  This only fails when the right
 hand side is forced into a fixed register (e.g. the result of a call).
 
 \begin{code}
-assignIntCode, assignFltCode
-       :: PrimRep -> StixTree -> StixTree -> NatM InstrBlock
+assignMem_IntCode :: PrimRep -> StixExpr -> StixExpr -> NatM InstrBlock
+assignReg_IntCode :: PrimRep -> StixReg  -> StixExpr -> NatM InstrBlock
+
+assignMem_FltCode :: PrimRep -> StixExpr -> StixExpr -> NatM InstrBlock
+assignReg_FltCode :: PrimRep -> StixReg  -> StixExpr -> NatM InstrBlock
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 #if alpha_TARGET_ARCH
 
@@ -1755,14 +2456,15 @@ assignIntCode pk dst src
     in
     returnNat code__2
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
--- Destination of an assignment can only be reg or mem.
--- This is the mem case.
-assignIntCode pk (StInd _ dst) src
-  = getAmode dst               `thenNat` \ amode ->
+-- non-FP assignment to memory
+assignMem_IntCode pk addr src
+  = getAmode addr              `thenNat` \ amode ->
     get_op_RI src              `thenNat` \ (codesrc, opsrc) ->
     getNewRegNCG PtrRep         `thenNat` \ tmp ->
     let
@@ -1779,7 +2481,6 @@ assignIntCode pk (StInd _ dst) src
                 = codesrc `snocOL`
                  MOV (primRepToSize pk) opsrc (OpAddr dst__a)
                 | otherwise
-
                 = codea `snocOL` 
                   LEA L (OpAddr dst__a) (OpReg tmp) `appOL`
                   codesrc `snocOL`
@@ -1789,15 +2490,12 @@ assignIntCode pk (StInd _ dst) src
     returnNat code
   where
     get_op_RI
-       :: StixTree
+       :: StixExpr
        -> NatM (InstrBlock,Operand)    -- code, operator
 
     get_op_RI op
-      | maybeToBool imm
-      = returnNat (nilOL, OpImm imm_op)
-      where
-       imm    = maybeImm op
-       imm_op = case imm of Just x -> x
+      | Just x <- maybeImm op
+      = returnNat (nilOL, OpImm x)
 
     get_op_RI op
       = getRegister op                 `thenNat` \ register ->
@@ -1809,15 +2507,13 @@ assignIntCode pk (StInd _ dst) src
        returnNat (code, OpReg reg)
 
 -- Assign; dst is a reg, rhs is mem
-assignIntCode pk dst (StInd pks src)
+assignReg_IntCode pk reg (StInd pks src)
   = getNewRegNCG PtrRep            `thenNat` \ tmp ->
     getAmode src                   `thenNat` \ amode ->
-    getRegister dst                `thenNat` \ reg_dst ->
+    getRegisterReg reg             `thenNat` \ reg_dst ->
     let
        c_addr  = amodeCode amode
        am_addr = amodeAddr amode
-
-       c_dst = registerCode reg_dst tmp  -- should be empty
        r_dst = registerName reg_dst tmp
        szs   = primRepToSize pks
         opc   = case szs of
@@ -1828,40 +2524,35 @@ assignIntCode pk dst (StInd pks src)
             L  -> MOV L
             Lu -> MOV L
 
-       code  | isNilOL c_dst
-              = c_addr `snocOL`
+       code  = c_addr `snocOL`
                 opc (OpAddr am_addr) (OpReg r_dst)
-              | otherwise
-              = pprPanic "assignIntCode(x86): bad dst(2)" empty
     in
     returnNat code
 
 -- dst is a reg, but src could be anything
-assignIntCode pk dst src
-  = getRegister dst                `thenNat` \ registerd ->
+assignReg_IntCode pk reg src
+  = getRegisterReg reg             `thenNat` \ registerd ->
     getRegister src                `thenNat` \ registers ->
     getNewRegNCG IntRep            `thenNat` \ tmp ->
     let 
         r_dst = registerName registerd tmp
-        c_dst = registerCode registerd tmp -- should be empty
         r_src = registerName registers r_dst
         c_src = registerCode registers r_dst
-        
-        code | isNilOL c_dst
-             = c_src `snocOL` 
+         
+        code = c_src `snocOL` 
                MOV L (OpReg r_src) (OpReg r_dst)
-             | otherwise
-             = pprPanic "assignIntCode(x86): bad dst(3)" empty
     in
     returnNat code
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
-assignIntCode pk (StInd _ dst) src
-  = getNewRegNCG IntRep            `thenNat` \ tmp ->
-    getAmode dst                   `thenNat` \ amode ->
+assignMem_IntCode pk addr src
+  = getNewRegNCG IntRep                    `thenNat` \ tmp ->
+    getAmode addr                          `thenNat` \ amode ->
     getRegister src                        `thenNat` \ register ->
     let
        code1   = amodeCode amode
@@ -1873,11 +2564,12 @@ assignIntCode pk (StInd _ dst) src
     in
     returnNat code__2
 
-assignIntCode pk dst src
-  = getRegister dst                        `thenNat` \ register1 ->
-    getRegister src                        `thenNat` \ register2 ->
+assignReg_IntCode pk reg src
+  = getRegister src                        `thenNat` \ register2 ->
+    getRegisterReg reg                     `thenNat` \ register1 ->
+    getNewRegNCG IntRep                    `thenNat` \ tmp ->
     let
-       dst__2  = registerName register1 g0
+       dst__2  = registerName register1 tmp
        code    = registerCode register2 dst__2
        src__2  = registerName register2 dst__2
        code__2 = if isFixed register2
@@ -1886,13 +2578,48 @@ assignIntCode pk dst src
     in
     returnNat code__2
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
+
+#if powerpc_TARGET_ARCH
+
+assignMem_IntCode pk addr src
+  = getNewRegNCG IntRep                    `thenNat` \ tmp ->
+    getAmode addr                          `thenNat` \ amode ->
+    getRegister src                        `thenNat` \ register ->
+    let
+       code1   = amodeCode amode
+       dst__2  = amodeAddr amode
+       code2   = registerCode register tmp
+       src__2  = registerName register tmp
+       sz      = primRepToSize pk
+       code__2 = code1 `appOL` code2 `snocOL` ST sz src__2 dst__2
+    in
+    returnNat code__2
+
+assignReg_IntCode pk reg src
+  = getRegister src                        `thenNat` \ register2 ->
+    getRegisterReg reg                     `thenNat` \ register1 ->
+    let
+       dst__2  = registerName register1 (panic "###PPC where are we assigning this int???")
+       code    = registerCode register2 dst__2
+       src__2  = registerName register2 dst__2
+       code__2 = if isFixed register2
+                 then code `snocOL` MR dst__2 src__2
+                 else code
+    in
+    returnNat code__2
+
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 % --------------------------------
 Floating-point assignments:
 % --------------------------------
+
 \begin{code}
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if alpha_TARGET_ARCH
 
 assignFltCode pk (StInd _ dst) src
@@ -1922,15 +2649,14 @@ assignFltCode pk dst src
     in
     returnNat code__2
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
--- dst is memory
-assignFltCode pk (StInd pk_dst addr) src
-   | pk /= pk_dst
-   = pprPanic "assignFltCode(x86): src/ind sz mismatch" empty
-   | otherwise
+-- Floating point assignment to memory
+assignMem_FltCode pk addr src
    = getRegister src      `thenNat`  \ reg_src  ->
      getRegister addr     `thenNat`  \ reg_addr ->
      getNewRegNCG pk      `thenNat`  \ tmp_src  ->
@@ -1951,36 +2677,33 @@ assignFltCode pk (StInd pk_dst addr) src
      in
      returnNat code
 
--- dst must be a (FP) register
-assignFltCode pk dst src
-  = getRegister dst                `thenNat` \ reg_dst ->
+-- Floating point assignment to a register/temporary
+assignReg_FltCode pk reg src
+  = getRegisterReg reg             `thenNat` \ reg_dst ->
     getRegister src                `thenNat` \ reg_src ->
     getNewRegNCG pk                 `thenNat` \ tmp ->
     let
        r_dst = registerName reg_dst tmp
-        c_dst = registerCode reg_dst tmp -- should be empty
-
        r_src = registerName reg_src r_dst
        c_src = registerCode reg_src r_dst
 
-       code | isNilOL c_dst
-             = if   isFixed reg_src
+       code = if   isFixed reg_src
                then c_src `snocOL` GMOV r_src r_dst
                else c_src
-             | otherwise
-             = pprPanic "assignFltCode(x86): lhs is not mem or reg" 
-                        empty
     in
     returnNat code
 
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
-assignFltCode pk (StInd _ dst) src
+-- Floating point assignment to memory
+assignMem_FltCode pk addr src
   = getNewRegNCG pk                `thenNat` \ tmp1 ->
-    getAmode dst                   `thenNat` \ amode ->
+    getAmode addr                  `thenNat` \ amode ->
     getRegister src                `thenNat` \ register ->
     let
        sz      = primRepToSize pk
@@ -2000,8 +2723,10 @@ assignFltCode pk (StInd _ dst) src
     in
     returnNat code__2
 
-assignFltCode pk dst src
-  = getRegister dst                        `thenNat` \ register1 ->
+-- Floating point assignment to a register/temporary
+-- Why is this so bizarrely ugly?
+assignReg_FltCode pk reg src
+  = getRegisterReg reg                     `thenNat` \ register1 ->
     getRegister src                        `thenNat` \ register2 ->
     let 
         pk__2   = registerRep register2 
@@ -2011,14 +2736,9 @@ assignFltCode pk dst src
     let
        sz      = primRepToSize pk
        dst__2  = registerName register1 g0    -- must be Fixed
-
        reg__2  = if pk /= pk__2 then tmp else dst__2
        code    = registerCode register2 reg__2
-
        src__2  = registerName register2 reg__2
-
        code__2 = 
                if pk /= pk__2 then
                     code `snocOL` FxTOy sz__2 sz src__2 dst__2
@@ -2029,7 +2749,47 @@ assignFltCode pk dst src
     in
     returnNat code__2
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
+
+#if powerpc_TARGET_ARCH
+
+-- Floating point assignment to memory
+assignMem_FltCode pk addr src
+  = getNewRegNCG pk                `thenNat` \ tmp1 ->
+    getAmode addr                  `thenNat` \ amode ->
+    getRegister src                `thenNat` \ register ->
+    let
+       sz      = primRepToSize pk
+       dst__2  = amodeAddr amode
+
+       code1   = amodeCode amode
+       code2   = registerCode register tmp1
+
+       src__2  = registerName register tmp1
+       pk__2   = registerRep register
+
+       code__2 = code1 `appOL` code2 `snocOL` ST sz src__2 dst__2
+    in
+    returnNat code__2
+
+-- Floating point assignment to a register/temporary
+assignReg_FltCode pk reg src
+  = getRegisterReg reg             `thenNat` \ reg_dst ->
+    getRegister src                `thenNat` \ reg_src ->
+    getNewRegNCG pk                 `thenNat` \ tmp ->
+    let
+       r_dst = registerName reg_dst tmp
+       r_src = registerName reg_src r_dst
+       c_src = registerCode reg_src r_dst
+
+       code = if   isFixed reg_src
+               then c_src `snocOL` MR r_dst r_src
+               else c_src
+    in
+    returnNat code
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -2047,7 +2807,9 @@ branch instruction.  Other CLabels are assumed to be far away.
 register allocator.
 
 \begin{code}
-genJump :: DestInfo -> StixTree{-the branch target-} -> NatM InstrBlock
+genJump :: DestInfo -> StixExpr{-the branch target-} -> NatM InstrBlock
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 #if alpha_TARGET_ARCH
 
@@ -2070,8 +2832,10 @@ genJump tree
     else
     returnNat (code . mkSeqInstr (JMP zeroh (AddrReg pv) 0))
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
 genJump dsts (StInd pk mem)
@@ -2098,14 +2862,16 @@ genJump dsts tree
     imm    = maybeImm tree
     target = case imm of Just x -> x
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 genJump dsts (StCLbl lbl)
   | hasDestInfo dsts = panic "genJump(sparc): CLbl and dsts"
   | isAsmTemp lbl    = returnNat (toOL [BI ALWAYS False target, NOP])
-  | otherwise        = returnNat (toOL [CALL target 0 True, NOP])
+  | otherwise        = returnNat (toOL [CALL (Left target) 0 True, NOP])
   where
     target = ImmCLbl lbl
 
@@ -2118,7 +2884,26 @@ 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)
+  | hasDestInfo dsts = panic "genJump(powerpc): CLbl and dsts"
+  | otherwise        = returnNat (toOL [BCC ALWAYS lbl])
+
+genJump dsts tree
+  = getRegister tree                       `thenNat` \ register ->
+    getNewRegNCG PtrRep            `thenNat` \ tmp ->
+    let
+       code   = registerCode register tmp
+       target = registerName register tmp
+    in
+    returnNat (code `snocOL` MTCTR target `snocOL` BCTR dsts)
+#endif /* sparc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -2149,9 +2934,11 @@ allocator.
 \begin{code}
 genCondJump
     :: CLabel      -- the branch target
-    -> StixTree     -- the condition on which to branch
+    -> StixExpr     -- the condition on which to branch
     -> NatM InstrBlock
 
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if alpha_TARGET_ARCH
 
 genCondJump lbl (StPrim op [x, StInt 0])
@@ -2293,8 +3080,10 @@ genCondJump lbl (StPrim op [x, y])
        AddrLtOp -> (CMP ULT, NE)
        AddrLeOp -> (CMP ULE, NE)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
 genCondJump lbl bool
@@ -2305,8 +3094,10 @@ genCondJump lbl bool
     in
     returnNat (code `snocOL` JXX cond lbl)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 genCondJump lbl bool
@@ -2325,7 +3116,25 @@ genCondJump lbl bool
        )
     )
 
-#endif {- sparc_TARGET_ARCH -}
+#endif /* sparc_TARGET_ARCH */
+
+#if powerpc_TARGET_ARCH
+
+genCondJump lbl bool
+  = getCondCode bool               `thenNat` \ condition ->
+    let
+       code   = condCode condition
+       cond   = condName condition
+       target = ImmCLbl lbl
+    in
+    returnNat (
+       code `snocOL` BCC cond lbl    )
+
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -2343,12 +3152,14 @@ register allocator.
 
 \begin{code}
 genCCall
-    :: FAST_STRING     -- function to call
+    :: (Either FastString StixExpr)    -- function to call
     -> CCallConv
     -> PrimRep         -- type of the result
-    -> [StixTree]      -- arguments (of mixed type)
+    -> [StixExpr]      -- arguments (of mixed type)
     -> NatM InstrBlock
 
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if alpha_TARGET_ARCH
 
 genCCall fn cconv kind args
@@ -2415,50 +3226,49 @@ genCCall fn cconv kind args
        in
        returnNat (([], offset + 1), code . mkSeqInstr (ST sz src (spRel offset)))
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
-genCCall fn cconv kind [StInt i]
-  | fn == SLIT ("PerformGC_wrapper")
-  = let call = toOL [
-                  MOV L (OpImm (ImmInt (fromInteger i))) (OpReg eax),
-                 CALL (ImmLit (ptext (if   underscorePrefix 
-                                       then (SLIT ("_PerformGC_wrapper"))
-                                       else (SLIT ("PerformGC_wrapper")))))
-               ]
+genCCall fn cconv ret_rep args
+  = mapNat push_arg
+           (reverse args)      `thenNat` \ sizes_n_codes ->
+    getDeltaNat                `thenNat` \ delta ->
+    let (sizes, push_codes) = unzip sizes_n_codes
+        tot_arg_size        = sum sizes
     in
-    returnNat call
-
-
-genCCall fn cconv kind args
-  = mapNat get_call_arg
-           (reverse args)  `thenNat` \ sizes_n_codes ->
-    getDeltaNat            `thenNat` \ delta ->
-    let (sizes, codes) = unzip sizes_n_codes
-        tot_arg_size   = sum sizes
-       code2          = concatOL codes
-       call = toOL (
-                  [CALL (fn__2 tot_arg_size)]
-                  ++
+    -- deal with static vs dynamic call targets
+    (case fn of
+        Left t_static 
+           -> returnNat (unitOL (CALL (Left (fn__2 tot_arg_size))))
+        Right dyn 
+           -> get_op dyn `thenNat` \ (dyn_c, dyn_r, dyn_rep) ->
+              ASSERT(case dyn_rep of { L -> True; _ -> False})
+              returnNat (dyn_c `snocOL` CALL (Right dyn_r))
+    ) 
+                               `thenNat` \ callinsns ->
+    let        push_code = concatOL push_codes
+       call = callinsns `appOL`
+               toOL (
                        -- Deallocate parameters after call for ccall;
                        -- but not for stdcall (callee does it)
                   (if cconv == StdCallConv then [] else 
                   [ADD L (OpImm (ImmInt tot_arg_size)) (OpReg esp)])
                   ++
-
                   [DELTA (delta + tot_arg_size)]
                )
     in
     setDeltaNat (delta + tot_arg_size) `thenNat` \ _ ->
-    returnNat (code2 `appOL` call)
+    returnNat (push_code `appOL` call)
 
   where
     -- function names that begin with '.' are assumed to be special
     -- internally generated names like '.mul,' which don't get an
     -- underscore prefix
     -- ToDo:needed (WDP 96/03) ???
-    fn_u  = _UNPK_ fn
+    fn_u  = unpackFS (unLeft fn)
     fn__2 tot_arg_size
        | head fn_u == '.'
        = ImmLit (text (fn_u ++ stdcallsize tot_arg_size))
@@ -2474,14 +3284,26 @@ genCCall fn cconv kind args
     arg_size _  = 4
 
     ------------
-    get_call_arg :: StixTree{-current argument-}
+    push_arg :: StixExpr{-current argument-}
                     -> NatM (Int, InstrBlock)  -- argsz, code
 
-    get_call_arg arg
-      = get_op arg               `thenNat` \ (code, reg, sz) ->
-        getDeltaNat               `thenNat` \ delta ->
-        arg_size sz               `bind`    \ size ->
-        setDeltaNat (delta-size)  `thenNat` \ _ ->
+    push_arg arg
+      | is64BitRep arg_rep
+      = iselExpr64 arg                 `thenNat` \ (ChildCode64 code vr_lo) ->
+        getDeltaNat                    `thenNat` \ delta ->
+        setDeltaNat (delta - 8)                `thenNat` \ _ ->
+        let r_lo = VirtualRegI vr_lo
+            r_hi = getHiVRegFromLo r_lo
+        in  returnNat (8,
+                       code `appOL`
+                       toOL [PUSH L (OpReg r_hi), DELTA (delta - 4),
+                             PUSH L (OpReg r_lo), DELTA (delta - 8)]
+            )
+      | otherwise
+      = get_op arg                     `thenNat` \ (code, reg, sz) ->
+        getDeltaNat                    `thenNat` \ delta ->
+        arg_size sz                    `bind`    \ size ->
+        setDeltaNat (delta-size)       `thenNat` \ _ ->
         if   (case sz of DF -> True; F -> True; _ -> False)
         then returnNat (size,
                         code `appOL`
@@ -2496,9 +3318,12 @@ genCCall fn cconv kind args
                         PUSH L (OpReg reg) `snocOL`
                         DELTA (delta-size)
                        )
+      where
+         arg_rep = repOfStixExpr arg
+
     ------------
     get_op
-       :: StixTree
+       :: StixExpr
        -> NatM (InstrBlock, Reg, Size) -- code, reg, size
 
     get_op op
@@ -2513,8 +3338,10 @@ genCCall fn cconv kind args
        in
        returnNat (code, reg, sz)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 {- 
    The SPARC calling convention is an absolute
@@ -2548,26 +3375,36 @@ genCCall fn cconv kind args
 
 genCCall fn cconv kind args
   = mapNat arg_to_int_vregs args `thenNat` \ argcode_and_vregs ->
-    let (argcodes, vregss) = unzip argcode_and_vregs
-        argcode            = concatOL argcodes
-        vregs              = concat vregss
+    let 
+        (argcodes, vregss) = unzip argcode_and_vregs
         n_argRegs          = length allArgRegs
         n_argRegs_used     = min (length vregs) n_argRegs
+        vregs              = concat vregss
+    in
+    -- deal with static vs dynamic call targets
+    (case fn of
+        Left t_static
+           -> returnNat (unitOL (CALL (Left fn__2) n_argRegs_used False))
+        Right dyn
+           -> arg_to_int_vregs dyn `thenNat` \ (dyn_c, [dyn_r]) ->
+              returnNat (dyn_c `snocOL` CALL (Right dyn_r) n_argRegs_used False)
+    )
+                               `thenNat` \ callinsns ->
+    let
+        argcode = concatOL argcodes
         (move_sp_down, move_sp_up)
-           = let nn = length vregs - n_argRegs 
-                                   + 1 -- (for the road)
+           = let diff = length vregs - n_argRegs
+                 nn   = if odd diff then diff + 1 else diff -- keep 8-byte alignment
              in  if   nn <= 0
                  then (nilOL, nilOL)
                  else (unitOL (moveSp (-1*nn)), unitOL (moveSp (1*nn)))
         transfer_code
            = toOL (move_final vregs allArgRegs eXTRA_STK_ARGS_HERE)
-        call
-           = unitOL (CALL fn__2 n_argRegs_used False)
     in
         returnNat (argcode       `appOL`
                    move_sp_down  `appOL`
                    transfer_code `appOL`
-                   call          `appOL`
+                   callinsns     `appOL`
                    unitOL NOP    `appOL`
                    move_sp_up)
   where
@@ -2575,9 +3412,10 @@ genCCall fn cconv kind args
      -- internally generated names like '.mul,' which don't get an
      -- underscore prefix
      -- ToDo:needed (WDP 96/03) ???
-     fn__2 = case (_HEAD_ fn) of
-               '.' -> ImmLit (ptext fn)
-               _   -> ImmLab False (ptext fn)
+     fn_static = unLeft fn
+     fn__2 = case (headFS fn_static) of
+               '.' -> ImmLit (ftext fn_static)
+               _   -> ImmLab False (ftext fn_static)
 
      -- move args from the integer vregs into which they have been 
      -- marshalled, into %o0 .. %o5, and the rest onto the stack.
@@ -2596,8 +3434,14 @@ genCCall fn cconv kind args
 
      -- generate code to calculate an argument, and move it into one
      -- or two integer vregs.
-     arg_to_int_vregs :: StixTree -> NatM (OrdList Instr, [Reg])
+     arg_to_int_vregs :: StixExpr -> NatM (OrdList Instr, [Reg])
      arg_to_int_vregs arg
+        | is64BitRep (repOfStixExpr arg)
+        = iselExpr64 arg               `thenNat` \ (ChildCode64 code vr_lo) ->
+          let r_lo = VirtualRegI vr_lo
+              r_hi = getHiVRegFromLo r_lo
+          in  returnNat (code, [r_hi, r_lo])
+        | otherwise
         = getRegister arg                     `thenNat` \ register ->
           getNewRegNCG (registerRep register) `thenNat` \ tmp ->
           let code = registerCode register tmp
@@ -2635,7 +3479,239 @@ 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 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
+    floating point registers, or on the stack. Stack space is
+    always reserved for parameters, even if they are passed in registers.
+    The called routine may choose to save parameters from registers
+    to the corresponding space on the stack.
+    The parameter area should be part of the caller's stack frame,
+    allocated in the caller's prologue code (large enough to hold
+    the parameter lists for all called routines). The NCG already
+    uses the space that we should use as a parameter area for register
+    spilling, so we allocate a new stack frame just before ccalling.
+    That way we don't need to decide beforehand how much space to
+    reserve for parameters.
+-}
+
+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 $ (24 +) $ max 32 $ (4 *) $ sum $ map getPrimRepSize argReps
+       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) = 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 
+                                            (FSLIT("L_")
+                                            `appendFS` lbl
+                                            `appendFS` FSLIT("$stub")))
+                                          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 [] _ _ _ accumCode accumUsed = (accumCode, accumUsed)
+    move_final ((Left vr,rep):vregs) gprs fprs stackOffset accumCode accumUsed
+       | not (is64BitRep rep) =
+       case rep of
+           FloatRep ->
+               move_final vregs (drop 1 gprs) (drop 1 fprs) (stackOffset+4)
+                   (accumCode `snocOL`
+                       (case fprs of
+                           fpr : fprs -> MR fpr vr
+                           [] -> ST F vr (AddrRegImm sp (ImmInt stackOffset))))
+                   ((take 1 fprs) ++ accumUsed)
+           DoubleRep ->
+               move_final vregs (drop 2 gprs) (drop 1 fprs) (stackOffset+8)
+                   (accumCode `snocOL`
+                       (case fprs of
+                           fpr : fprs -> MR fpr vr
+                           [] -> ST DF vr (AddrRegImm sp (ImmInt stackOffset))))
+                   ((take 1 fprs) ++ accumUsed)
+           VoidRep -> panic "MachCode.genCCall(powerpc): void parameter"
+           _ ->
+               move_final vregs (drop 1 gprs) fprs (stackOffset+4)
+                   (accumCode `snocOL`
+                       (case gprs of
+                           gpr : gprs -> MR gpr vr
+                           [] -> ST W vr (AddrRegImm sp (ImmInt stackOffset))))
+                   ((take 1 gprs) ++ accumUsed)
+               
+    move_final ((Right (vr_hi,vr_lo),rep):vregs) gprs fprs stackOffset accumCode accumUsed
+       | is64BitRep rep =
+       let
+           storeWord vr (gpr:_) offset = MR gpr vr
+           storeWord vr [] offset = ST W vr (AddrRegImm sp (ImmInt offset))
+       in
+           move_final vregs (drop 2 gprs) fprs (stackOffset+8)
+               (accumCode
+                   `snocOL` storeWord vr_hi gprs stackOffset
+                   `snocOL` storeWord vr_lo (drop 1 gprs) (stackOffset+4))
+               ((take 2 gprs) ++ accumUsed)
+#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}
 
 %************************************************************************
@@ -2657,14 +3733,17 @@ the right hand side of an assignment).
 register allocator.
 
 \begin{code}
-condIntReg, condFltReg :: Cond -> StixTree -> StixTree -> NatM Register
+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 */
 
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
 condIntReg cond x y
@@ -2697,8 +3776,10 @@ condFltReg cond x y
     in
     returnNat (Any IntRep code__2)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 condIntReg EQQ x (StInt 0)
@@ -2794,7 +3875,37 @@ 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
+  = getNatLabelNCG             `thenNat` \ lbl ->
+    condIntCode cond x y       `thenNat` \ condition ->
+    let
+       code = condCode condition
+       cond = condName condition
+       code__2 dst = (LI dst (ImmInt 1) `consOL` code) `appOL` toOL [
+           BCC cond lbl,
+           LI dst (ImmInt 0),
+           LABEL lbl]
+    in
+    returnNat (Any IntRep code__2)
+
+condFltReg cond x y
+  = getNatLabelNCG             `thenNat` \ lbl ->
+    condFltCode cond x y       `thenNat` \ condition ->
+    let
+       code = condCode condition
+       cond = condName condition
+       code__2 dst = (LI dst (ImmInt 1) `consOL` code) `appOL` toOL [
+           BCC cond lbl,
+           LI dst (ImmInt 0),
+           LABEL lbl]
+    in
+    returnNat (Any IntRep code__2)
+#endif /* powerpc_TARGET_ARCH */
+
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 \end{code}
 
 %************************************************************************
@@ -2818,8 +3929,9 @@ trivialCode
       ,IF_ARCH_i386 ((Operand -> Operand -> Instr) 
                      -> Maybe (Operand -> Operand -> Instr)
       ,IF_ARCH_sparc((Reg -> RI -> Reg -> Instr)
-      ,)))
-    -> StixTree -> StixTree -- the two arguments
+      ,IF_ARCH_powerpc((Reg -> Reg -> RI -> Instr)
+      ,))))
+    -> StixExpr -> StixExpr -- the two arguments
     -> NatM Register
 
 trivialFCode
@@ -2827,16 +3939,18 @@ trivialFCode
     -> IF_ARCH_alpha((Reg -> Reg -> Reg -> Instr)
       ,IF_ARCH_sparc((Size -> Reg -> Reg -> Reg -> Instr)
       ,IF_ARCH_i386 ((Size -> Reg -> Reg -> Reg -> Instr)
-      ,)))
-    -> StixTree -> StixTree -- the two arguments
+      ,IF_ARCH_powerpc((Size -> Reg -> Reg -> Reg -> Instr)
+      ,))))
+    -> StixExpr -> StixExpr -- the two arguments
     -> NatM Register
 
 trivialUCode
     :: IF_ARCH_alpha((RI -> Reg -> Instr)
       ,IF_ARCH_i386 ((Operand -> Instr)
       ,IF_ARCH_sparc((RI -> Reg -> Instr)
-      ,)))
-    -> StixTree        -- the one argument
+      ,IF_ARCH_powerpc((Reg -> Reg -> Instr)
+      ,))))
+    -> StixExpr        -- the one argument
     -> NatM Register
 
 trivialUFCode
@@ -2844,10 +3958,13 @@ trivialUFCode
     -> IF_ARCH_alpha((Reg -> Reg -> Instr)
       ,IF_ARCH_i386 ((Reg -> Reg -> Instr)
       ,IF_ARCH_sparc((Reg -> Reg -> Instr)
-      ,)))
-    -> StixTree -- the one argument
+      ,IF_ARCH_powerpc((Reg -> Reg -> Instr)
+      ,))))
+    -> StixExpr -- the one argument
     -> NatM Register
 
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if alpha_TARGET_ARCH
 
 trivialCode instr x (StInt y)
@@ -2916,8 +4033,10 @@ trivialUFCode _ instr x
     in
     returnNat (Any DoubleRep code__2)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 \end{code}
 The Rules of the Game are:
@@ -3095,8 +4214,10 @@ trivialUFCode pk instr x
     in
     returnNat (Any pk code__2)
 
-#endif {- i386_TARGET_ARCH -}
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 trivialCode instr x (StInt y)
@@ -3181,7 +4302,127 @@ 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)
+  | fits16Bits y
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG IntRep                `thenNat` \ tmp ->
+    let
+       code = registerCode register tmp
+       src1 = registerName register tmp
+       src2 = ImmInt (fromInteger y)
+       code__2 dst = code `snocOL` instr dst src1 (RIImm src2)
+    in
+    returnNat (Any IntRep code__2)
+
+trivialCode instr 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 `snocOL`
+                     instr dst src1 (RIReg src2)
+    in
+    returnNat (Any IntRep code__2)
+
+trivialCode2 :: (Reg -> Reg -> Reg -> Instr)
+    -> StixExpr -> StixExpr -> NatM Register
+trivialCode2 instr 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 `snocOL`
+                     instr dst src1 src2
+    in
+    returnNat (Any IntRep code__2)
+    
+trivialFCode pk instr x y
+  = getRegister x              `thenNat` \ register1 ->
+    getRegister y              `thenNat` \ register2 ->
+    getNewRegNCG (registerRep register1)
+                               `thenNat` \ tmp1 ->
+    getNewRegNCG (registerRep register2)
+                               `thenNat` \ tmp2 ->
+    -- getNewRegNCG DoubleRep          `thenNat` \ tmp ->
+    let
+       -- promote x = FxTOy F DF x tmp
+
+       pk1   = registerRep register1
+       code1 = registerCode register1 tmp1
+       src1  = registerName register1 tmp1
+
+       pk2   = registerRep register2
+       code2 = registerCode register2 tmp2
+       src2  = registerName register2 tmp2
+
+       dstRep = if pk1 == FloatRep && pk2 == FloatRep then FloatRep else DoubleRep
+
+       code__2 dst =
+                   code1 `appOL` code2 `snocOL`
+                   instr (primRepToSize dstRep) dst src1 src2
+    in
+    returnNat (Any dstRep code__2)
+
+trivialUCode instr x
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG IntRep                `thenNat` \ tmp ->
+    let
+       code = registerCode register tmp
+       src  = registerName register tmp
+       code__2 dst = code `snocOL` instr dst src
+    in
+    returnNat (Any IntRep code__2)
+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}
 
 %************************************************************************
@@ -3190,40 +4431,26 @@ trivialUFCode pk instr x
 %*                                                                     *
 %************************************************************************
 
-@coerce(Int|Flt)Code@ are simple coercions that don't require any code
-to be generated.  Here we just change the type on the Register passed
-on up.  The code is machine-independent.
-
 @coerce(Int2FP|FP2Int)@ are more complicated integer/float
 conversions.  We have to store temporaries in memory to move
 between the integer and the floating point register sets.
 
-\begin{code}
-coerceIntCode :: PrimRep -> StixTree -> NatM Register
-coerceFltCode ::           StixTree -> NatM Register
-
-coerceInt2FP :: PrimRep -> StixTree -> NatM Register
-coerceFP2Int ::           StixTree -> NatM Register
+@coerceDbl2Flt@ and @coerceFlt2Dbl@ are done this way because we
+pretend, on sparc at least, that double and float regs are seperate
+kinds, so the value has to be computed into one kind before being
+explicitly "converted" to live in the other kind.
 
-coerceIntCode pk x
-  = getRegister x              `thenNat` \ register ->
-    returnNat (
-    case register of
-       Fixed _ reg code -> Fixed pk reg code
-       Any   _ code     -> Any   pk code
-    )
+\begin{code}
+coerceInt2FP :: PrimRep -> StixExpr -> NatM Register
+coerceFP2Int :: PrimRep -> StixExpr -> NatM Register
 
--------------
-coerceFltCode x
-  = getRegister x              `thenNat` \ register ->
-    returnNat (
-    case register of
-       Fixed _ reg code -> Fixed DoubleRep reg code
-       Any   _ code     -> Any   DoubleRep code
-    )
+coerceDbl2Flt :: StixExpr -> NatM Register
+coerceFlt2Dbl :: StixExpr -> NatM Register
 \end{code}
 
 \begin{code}
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if alpha_TARGET_ARCH
 
 coerceInt2FP _ x
@@ -3255,8 +4482,10 @@ coerceFP2Int x
     in
     returnNat (Any IntRep code__2)
 
-#endif {- alpha_TARGET_ARCH -}
+#endif /* alpha_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if i386_TARGET_ARCH
 
 coerceInt2FP pk x
@@ -3271,7 +4500,7 @@ coerceInt2FP pk x
     returnNat (Any pk code__2)
 
 ------------
-coerceFP2Int x
+coerceFP2Int fprep x
   = getRegister x              `thenNat` \ register ->
     getNewRegNCG DoubleRep     `thenNat` \ tmp ->
     let
@@ -3284,8 +4513,14 @@ coerceFP2Int x
     in
     returnNat (Any IntRep code__2)
 
-#endif {- i386_TARGET_ARCH -}
+------------
+coerceDbl2Flt x = panic "MachCode.coerceDbl2Flt: unused on x86"
+coerceFlt2Dbl x = panic "MachCode.coerceFlt2Dbl: unused on x86"
+
+#endif /* i386_TARGET_ARCH */
+
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
 #if sparc_TARGET_ARCH
 
 coerceInt2FP pk x
@@ -3303,74 +4538,91 @@ coerceInt2FP pk x
     returnNat (Any pk code__2)
 
 ------------
-coerceFP2Int x
-  = getRegister x              `thenNat` \ register ->
-    getNewRegNCG IntRep                `thenNat` \ reg ->
+coerceFP2Int fprep x
+  = ASSERT(fprep == DoubleRep || fprep == FloatRep)
+    getRegister x              `thenNat` \ register ->
+    getNewRegNCG fprep         `thenNat` \ reg ->
     getNewRegNCG FloatRep      `thenNat` \ tmp ->
     let
        code = registerCode register reg
        src  = registerName register reg
-       pk   = registerRep  register
-
        code__2 dst = code `appOL` toOL [
-           FxTOy (primRepToSize pk) W src tmp,
+           FxTOy (primRepToSize fprep) W src tmp,
            ST W tmp (spRel (-2)),
            LD W (spRel (-2)) dst]
     in
     returnNat (Any IntRep code__2)
 
-#endif {- sparc_TARGET_ARCH -}
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Coercing integer to @Char@...}
-%*                                                                     *
-%************************************************************************
-
-Integer to character conversion.
+------------
+coerceDbl2Flt x
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG DoubleRep     `thenNat` \ tmp ->
+    let code = registerCode register tmp
+        src  = registerName register tmp
+    in
+        returnNat (Any FloatRep 
+                       (\dst -> code `snocOL` FxTOy DF F src dst)) 
 
-\begin{code}
-chrCode :: StixTree -> NatM Register
+------------
+coerceFlt2Dbl x
+  = getRegister x              `thenNat` \ register ->
+    getNewRegNCG FloatRep      `thenNat` \ tmp ->
+    let code = registerCode register tmp
+        src  = registerName register tmp
+    in
+        returnNat (Any DoubleRep
+                       (\dst -> code `snocOL` FxTOy F DF src dst)) 
 
-#if alpha_TARGET_ARCH
+#endif /* sparc_TARGET_ARCH */
 
--- TODO: This is probably wrong, but I don't know Alpha assembler.
--- It should coerce a 64-bit value to a 32-bit value.
+#if powerpc_TARGET_ARCH
+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)
 
-chrCode x
-  = getRegister x              `thenNat` \ register ->
-    getNewRegNCG IntRep                `thenNat` \ reg ->
+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 . mkSeqInstr (ZAPNOT src (RIImm (ImmInt 1)) dst)
+       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 {- alpha_TARGET_ARCH -}
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#if i386_TARGET_ARCH
-
-chrCode x
-  = getRegister x              `thenNat` \ register ->
-    returnNat (
-    case register of
-       Fixed _ reg code -> Fixed IntRep reg code
-       Any   _ code     -> Any   IntRep code
-    )
-
-#endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#if sparc_TARGET_ARCH
-
-chrCode x
-  = getRegister x              `thenNat` \ register ->
-    returnNat (
-    case register of
-       Fixed _ reg code -> Fixed IntRep reg code
-       Any   _ code     -> Any   IntRep code
-    )
-
-#endif {- sparc_TARGET_ARCH -}
 \end{code}