Merge in new code generator branch.
[ghc-hetmet.git] / compiler / nativeGen / SPARC / Instr.hs
index 6dc6477..79b4629 100644 (file)
 
 module SPARC.Instr (
        RI(..),
+       riZero,
+
+       fpRelEA,
+       moveSp,
+       
+       isUnconditionalJump,
+       
        Instr(..),
        maxSpillSlots
 )
 
 where
 
-import SPARC.Regs
+import SPARC.Stack
+import SPARC.Imm
+import SPARC.AddrMode
 import SPARC.Cond
+import SPARC.Regs
+import SPARC.RegPlate
+import SPARC.Base
+import TargetReg
 import Instruction
 import RegClass
 import Reg
 import Size
 
 import BlockId
-import Cmm
-import Outputable
-import Constants       (rESERVED_C_STACK_BYTES )
+import OldCmm
 import FastString
 import FastBool
-
-import GHC.Exts
+import Outputable
 
 
 -- | Register or immediate
@@ -39,6 +49,40 @@ data RI
        = RIReg Reg
        | RIImm Imm
 
+-- | Check if a RI represents a zero value.
+--     - a literal zero
+--     - register %g0, which is always zero.
+--
+riZero :: RI -> Bool   
+riZero (RIImm (ImmInt 0))                      = True
+riZero (RIImm (ImmInteger 0))                  = True
+riZero (RIReg (RegReal (RealRegSingle 0)))     = True
+riZero _                                       = False
+
+
+-- | Calculate the effective address which would be used by the
+--     corresponding fpRel sequence. 
+fpRelEA :: Int -> Reg -> Instr
+fpRelEA n dst
+   = ADD False False fp (RIImm (ImmInt (n * wordLength))) dst
+
+
+-- | Code to shift the stack pointer by n words.
+moveSp :: Int -> Instr
+moveSp n
+   = ADD False False sp (RIImm (ImmInt (n * wordLength))) sp
+
+-- | An instruction that will cause the one after it never to be exectuted
+isUnconditionalJump :: Instr -> Bool
+isUnconditionalJump ii
+ = case ii of
+       CALL{}          -> True
+       JMP{}           -> True
+       JMP_TBL{}       -> True
+       BI ALWAYS _ _   -> True
+       BF ALWAYS _ _   -> True
+       _               -> False
+
 
 -- | instance for sparc instruction set
 instance Instruction Instr where
@@ -83,6 +127,11 @@ data Instr
        | ST            Size Reg AddrMode               -- size, src, dst
 
        -- Int Arithmetic.
+       --      x:   add/sub with carry bit. 
+       --              In SPARC V9 addx and friends were renamed addc. 
+       --
+       --      cc:  modify condition codes
+       -- 
        | ADD           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
        | SUB           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
 
@@ -222,11 +271,9 @@ sparc_regUsageOfInstr instr
 interesting :: Reg -> Bool
 interesting reg
  = case reg of
-       VirtualRegI  _  -> True
-       VirtualRegHi _  -> True
-       VirtualRegF  _  -> True
-       VirtualRegD  _  -> True
-       RealReg i       -> isFastTrue (freeReg i)
+       RegVirtual _                    -> True
+       RegReal (RealRegSingle r1)      -> isFastTrue (freeReg r1)
+       RegReal (RealRegPair r1 _)      -> isFastTrue (freeReg r1)
 
 
 
@@ -322,17 +369,18 @@ sparc_mkSpillInstr
 sparc_mkSpillInstr reg _ slot
  = let off     = spillSlotToOffset slot
         off_w  = 1 + (off `div` 4)
-        sz     = case regClass reg of
+        sz     = case targetClassOfReg reg of
                        RcInteger -> II32
                        RcFloat   -> FF32
                        RcDouble  -> FF64
+                       _         -> panic "sparc_mkSpillInstr"
                
     in ST sz reg (fpRel (negate off_w))
 
 
 -- | Make a spill reload instruction.
 sparc_mkLoadInstr
-       :: Reg          -- ^ register to load
+       :: Reg          -- ^ register to load into
        -> Int          -- ^ current stack delta
        -> Int          -- ^ spill slot to use
        -> Instr
@@ -340,36 +388,14 @@ sparc_mkLoadInstr
 sparc_mkLoadInstr reg _ slot
   = let off     = spillSlotToOffset slot
        off_w   = 1 + (off `div` 4)
-        sz     = case regClass reg of
+        sz     = case targetClassOfReg reg of
                        RcInteger -> II32
                        RcFloat   -> FF32
                        RcDouble  -> FF64
+                       _         -> panic "sparc_mkLoadInstr"
 
         in LD sz (fpRel (- off_w)) reg
 
--- | Convert a spill slot number to a *byte* offset, with no sign.
---
-spillSlotToOffset :: Int -> Int
-spillSlotToOffset slot
-       | slot >= 0 && slot < maxSpillSlots
-       = 64 + spillSlotSize * slot
-
-       | otherwise
-       = pprPanic "spillSlotToOffset:" 
-                     (   text "invalid spill location: " <> int slot
-                     $$  text "maxSpillSlots:          " <> int maxSpillSlots)
-
-
--- | We need 8 bytes because our largest registers are 64 bit.
-spillSlotSize :: Int
-spillSlotSize = 8
-
-
--- | The maximum number of spill slots available on the C stack.
---     If we use up all of the slots, then we're screwed.
-maxSpillSlots :: Int
-maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
-
 
 --------------------------------------------------------------------------------
 -- | See if this instruction is telling us the current C stack delta
@@ -407,10 +433,17 @@ sparc_mkRegRegMoveInstr
        -> Instr
 
 sparc_mkRegRegMoveInstr src dst
- = case regClass src of
-       RcInteger -> ADD  False False src (RIReg g0) dst
-       RcDouble  -> FMOV FF64 src dst
-       RcFloat   -> FMOV FF32 src dst
+       | srcClass      <- targetClassOfReg src
+       , dstClass      <- targetClassOfReg dst
+       , srcClass == dstClass
+       = case srcClass of
+               RcInteger -> ADD  False False src (RIReg g0) dst
+               RcDouble  -> FMOV FF64 src dst
+               RcFloat   -> FMOV FF32 src dst
+                _         -> panic "sparc_mkRegRegMoveInstr"
+       
+       | otherwise
+       = panic "SPARC.Instr.mkRegRegMoveInstr: classes of src and dest not the same"
 
 
 -- | Check whether an instruction represents a reg-reg move.