never executed always true always false
    1 
    2 
    3 -----------------------------------------------------------------------------
    4 --
    5 -- Machine-dependent assembly language
    6 --
    7 -- (c) The University of Glasgow 1993-2004
    8 --
    9 -----------------------------------------------------------------------------
   10 module GHC.CmmToAsm.SPARC.Instr
   11    ( Instr(..)
   12    , RI(..)
   13    , riZero
   14    , fpRelEA
   15    , moveSp
   16    , isUnconditionalJump
   17    , maxSpillSlots
   18    , patchRegsOfInstr
   19    , patchJumpInstr
   20    , mkRegRegMoveInstr
   21    , mkLoadInstr
   22    , mkSpillInstr
   23    , mkJumpInstr
   24    , takeDeltaInstr
   25    , isMetaInstr
   26    , isJumpishInstr
   27    , jumpDestsOfInstr
   28    , takeRegRegMoveInstr
   29    , regUsageOfInstr
   30    )
   31 where
   32 
   33 import GHC.Prelude
   34 import GHC.Platform
   35 
   36 import GHC.CmmToAsm.SPARC.Stack
   37 import GHC.CmmToAsm.SPARC.Imm
   38 import GHC.CmmToAsm.SPARC.AddrMode
   39 import GHC.CmmToAsm.SPARC.Cond
   40 import GHC.CmmToAsm.SPARC.Regs
   41 import GHC.CmmToAsm.SPARC.Base
   42 import GHC.CmmToAsm.Reg.Target
   43 import GHC.CmmToAsm.Format
   44 import GHC.CmmToAsm.Config
   45 import GHC.CmmToAsm.Instr (RegUsage(..), noUsage)
   46 
   47 import GHC.Platform.Reg.Class
   48 import GHC.Platform.Reg
   49 import GHC.Platform.Regs
   50 
   51 import GHC.Cmm.CLabel
   52 import GHC.Cmm.BlockId
   53 import GHC.Cmm
   54 import GHC.Utils.Outputable
   55 import GHC.Utils.Panic
   56 
   57 
   58 -- | Register or immediate
   59 data RI
   60         = RIReg Reg
   61         | RIImm Imm
   62 
   63 -- | Check if a RI represents a zero value.
   64 --      - a literal zero
   65 --      - register %g0, which is always zero.
   66 --
   67 riZero :: RI -> Bool
   68 riZero (RIImm (ImmInt 0))                       = True
   69 riZero (RIImm (ImmInteger 0))                   = True
   70 riZero (RIReg (RegReal (RealRegSingle 0)))      = True
   71 riZero _                                        = False
   72 
   73 
   74 -- | Calculate the effective address which would be used by the
   75 --      corresponding fpRel sequence.
   76 fpRelEA :: Int -> Reg -> Instr
   77 fpRelEA n dst
   78    = ADD False False fp (RIImm (ImmInt (n * wordLength))) dst
   79 
   80 
   81 -- | Code to shift the stack pointer by n words.
   82 moveSp :: Int -> Instr
   83 moveSp n
   84    = ADD False False sp (RIImm (ImmInt (n * wordLength))) sp
   85 
   86 -- | An instruction that will cause the one after it never to be exectuted
   87 isUnconditionalJump :: Instr -> Bool
   88 isUnconditionalJump ii
   89  = case ii of
   90         CALL{}          -> True
   91         JMP{}           -> True
   92         JMP_TBL{}       -> True
   93         BI ALWAYS _ _   -> True
   94         BF ALWAYS _ _   -> True
   95         _               -> False
   96 
   97 
   98 -- | SPARC instruction set.
   99 --      Not complete. This is only the ones we need.
  100 --
  101 data Instr
  102 
  103         -- meta ops --------------------------------------------------
  104         -- comment pseudo-op
  105         = COMMENT SDoc
  106 
  107         -- some static data spat out during code generation.
  108         -- Will be extracted before pretty-printing.
  109         | LDATA   Section RawCmmStatics
  110 
  111         -- Start a new basic block.  Useful during codegen, removed later.
  112         -- Preceding instruction should be a jump, as per the invariants
  113         -- for a BasicBlock (see Cmm).
  114         | NEWBLOCK BlockId
  115 
  116         -- specify current stack offset for benefit of subsequent passes.
  117         | DELTA   Int
  118 
  119         -- real instrs -----------------------------------------------
  120         -- Loads and stores.
  121         | LD            Format AddrMode Reg             -- format, src, dst
  122         | ST            Format Reg AddrMode             -- format, src, dst
  123 
  124         -- Int Arithmetic.
  125         --      x:   add/sub with carry bit.
  126         --              In SPARC V9 addx and friends were renamed addc.
  127         --
  128         --      cc:  modify condition codes
  129         --
  130         | ADD           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
  131         | SUB           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
  132 
  133         | UMUL          Bool Reg RI Reg                 --     cc?, src1, src2, dst
  134         | SMUL          Bool Reg RI Reg                 --     cc?, src1, src2, dst
  135 
  136 
  137         -- The SPARC divide instructions perform 64bit by 32bit division
  138         --   The Y register is xored into the first operand.
  139 
  140         --   On _some implementations_ the Y register is overwritten by
  141         --   the remainder, so we have to make sure it is 0 each time.
  142 
  143         --   dst <- ((Y `shiftL` 32) `or` src1) `div` src2
  144         | UDIV          Bool Reg RI Reg                 --     cc?, src1, src2, dst
  145         | SDIV          Bool Reg RI Reg                 --     cc?, src1, src2, dst
  146 
  147         | RDY           Reg                             -- move contents of Y register to reg
  148         | WRY           Reg  Reg                        -- Y <- src1 `xor` src2
  149 
  150         -- Logic operations.
  151         | AND           Bool Reg RI Reg                 -- cc?, src1, src2, dst
  152         | ANDN          Bool Reg RI Reg                 -- cc?, src1, src2, dst
  153         | OR            Bool Reg RI Reg                 -- cc?, src1, src2, dst
  154         | ORN           Bool Reg RI Reg                 -- cc?, src1, src2, dst
  155         | XOR           Bool Reg RI Reg                 -- cc?, src1, src2, dst
  156         | XNOR          Bool Reg RI Reg                 -- cc?, src1, src2, dst
  157         | SLL           Reg RI Reg                      -- src1, src2, dst
  158         | SRL           Reg RI Reg                      -- src1, src2, dst
  159         | SRA           Reg RI Reg                      -- src1, src2, dst
  160 
  161         -- Load immediates.
  162         | SETHI         Imm Reg                         -- src, dst
  163 
  164         -- Do nothing.
  165         -- Implemented by the assembler as SETHI 0, %g0, but worth an alias
  166         | NOP
  167 
  168         -- Float Arithmetic.
  169         -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single
  170         -- instructions right up until we spit them out.
  171         --
  172         | FABS          Format Reg Reg                  -- src dst
  173         | FADD          Format Reg Reg Reg              -- src1, src2, dst
  174         | FCMP          Bool Format Reg Reg             -- exception?, src1, src2, dst
  175         | FDIV          Format Reg Reg Reg              -- src1, src2, dst
  176         | FMOV          Format Reg Reg                  -- src, dst
  177         | FMUL          Format Reg Reg Reg              -- src1, src2, dst
  178         | FNEG          Format Reg Reg                  -- src, dst
  179         | FSQRT         Format Reg Reg                  -- src, dst
  180         | FSUB          Format Reg Reg Reg              -- src1, src2, dst
  181         | FxTOy         Format Format Reg Reg           -- src, dst
  182 
  183         -- Jumping around.
  184         | BI            Cond Bool BlockId               -- cond, annul?, target
  185         | BF            Cond Bool BlockId               -- cond, annul?, target
  186 
  187         | JMP           AddrMode                        -- target
  188 
  189         -- With a tabled jump we know all the possible destinations.
  190         -- We also need this info so we can work out what regs are live across the jump.
  191         --
  192         | JMP_TBL       AddrMode [Maybe BlockId] CLabel
  193 
  194         | CALL          (Either Imm Reg) Int Bool       -- target, args, terminal
  195 
  196 
  197 -- | regUsage returns the sets of src and destination registers used
  198 --      by a particular instruction.  Machine registers that are
  199 --      pre-allocated to stgRegs are filtered out, because they are
  200 --      uninteresting from a register allocation standpoint.  (We wouldn't
  201 --      want them to end up on the free list!)  As far as we are concerned,
  202 --      the fixed registers simply don't exist (for allocation purposes,
  203 --      anyway).
  204 
  205 --      regUsage doesn't need to do any trickery for jumps and such.  Just
  206 --      state precisely the regs read and written by that insn.  The
  207 --      consequences of control flow transfers, as far as register
  208 --      allocation goes, are taken care of by the register allocator.
  209 --
  210 regUsageOfInstr :: Platform -> Instr -> RegUsage
  211 regUsageOfInstr platform instr
  212  = case instr of
  213     LD    _ addr reg            -> usage (regAddr addr,         [reg])
  214     ST    _ reg addr            -> usage (reg : regAddr addr,   [])
  215     ADD   _ _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  216     SUB   _ _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  217     UMUL    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  218     SMUL    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  219     UDIV    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  220     SDIV    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  221     RDY       rd                -> usage ([],                   [rd])
  222     WRY       r1 r2             -> usage ([r1, r2],             [])
  223     AND     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  224     ANDN    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  225     OR      _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  226     ORN     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  227     XOR     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  228     XNOR    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  229     SLL       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  230     SRL       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  231     SRA       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
  232     SETHI   _ reg               -> usage ([],                   [reg])
  233     FABS    _ r1 r2             -> usage ([r1],                 [r2])
  234     FADD    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
  235     FCMP    _ _  r1 r2          -> usage ([r1, r2],             [])
  236     FDIV    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
  237     FMOV    _ r1 r2             -> usage ([r1],                 [r2])
  238     FMUL    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
  239     FNEG    _ r1 r2             -> usage ([r1],                 [r2])
  240     FSQRT   _ r1 r2             -> usage ([r1],                 [r2])
  241     FSUB    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
  242     FxTOy   _ _  r1 r2          -> usage ([r1],                 [r2])
  243 
  244     JMP     addr                -> usage (regAddr addr, [])
  245     JMP_TBL addr _ _            -> usage (regAddr addr, [])
  246 
  247     CALL  (Left _  )  _ True    -> noUsage
  248     CALL  (Left _  )  n False   -> usage (argRegs n, callClobberedRegs)
  249     CALL  (Right reg) _ True    -> usage ([reg], [])
  250     CALL  (Right reg) n False   -> usage (reg : (argRegs n), callClobberedRegs)
  251     _                           -> noUsage
  252 
  253   where
  254     usage (src, dst)
  255      = RU (filter (interesting platform) src)
  256           (filter (interesting platform) dst)
  257 
  258     regAddr (AddrRegReg r1 r2)  = [r1, r2]
  259     regAddr (AddrRegImm r1 _)   = [r1]
  260 
  261     regRI (RIReg r)             = [r]
  262     regRI  _                    = []
  263 
  264 
  265 -- | Interesting regs are virtuals, or ones that are allocatable
  266 --      by the register allocator.
  267 interesting :: Platform -> Reg -> Bool
  268 interesting platform reg
  269  = case reg of
  270         RegVirtual _                    -> True
  271         RegReal (RealRegSingle r1)      -> freeReg platform r1
  272         RegReal (RealRegPair r1 _)      -> freeReg platform r1
  273 
  274 
  275 
  276 -- | Apply a given mapping to tall the register references in this instruction.
  277 patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
  278 patchRegsOfInstr instr env = case instr of
  279     LD    fmt addr reg          -> LD fmt (fixAddr addr) (env reg)
  280     ST    fmt reg addr          -> ST fmt (env reg) (fixAddr addr)
  281 
  282     ADD   x cc r1 ar r2         -> ADD   x cc  (env r1) (fixRI ar) (env r2)
  283     SUB   x cc r1 ar r2         -> SUB   x cc  (env r1) (fixRI ar) (env r2)
  284     UMUL    cc r1 ar r2         -> UMUL    cc  (env r1) (fixRI ar) (env r2)
  285     SMUL    cc r1 ar r2         -> SMUL    cc  (env r1) (fixRI ar) (env r2)
  286     UDIV    cc r1 ar r2         -> UDIV    cc  (env r1) (fixRI ar) (env r2)
  287     SDIV    cc r1 ar r2         -> SDIV    cc  (env r1) (fixRI ar) (env r2)
  288     RDY   rd                    -> RDY         (env rd)
  289     WRY   r1 r2                 -> WRY         (env r1) (env r2)
  290     AND   b r1 ar r2            -> AND   b     (env r1) (fixRI ar) (env r2)
  291     ANDN  b r1 ar r2            -> ANDN  b     (env r1) (fixRI ar) (env r2)
  292     OR    b r1 ar r2            -> OR    b     (env r1) (fixRI ar) (env r2)
  293     ORN   b r1 ar r2            -> ORN   b     (env r1) (fixRI ar) (env r2)
  294     XOR   b r1 ar r2            -> XOR   b     (env r1) (fixRI ar) (env r2)
  295     XNOR  b r1 ar r2            -> XNOR  b     (env r1) (fixRI ar) (env r2)
  296     SLL   r1 ar r2              -> SLL         (env r1) (fixRI ar) (env r2)
  297     SRL   r1 ar r2              -> SRL         (env r1) (fixRI ar) (env r2)
  298     SRA   r1 ar r2              -> SRA         (env r1) (fixRI ar) (env r2)
  299 
  300     SETHI imm reg               -> SETHI imm (env reg)
  301 
  302     FABS  s r1 r2               -> FABS    s   (env r1) (env r2)
  303     FADD  s r1 r2 r3            -> FADD    s   (env r1) (env r2) (env r3)
  304     FCMP  e s r1 r2             -> FCMP e  s   (env r1) (env r2)
  305     FDIV  s r1 r2 r3            -> FDIV    s   (env r1) (env r2) (env r3)
  306     FMOV  s r1 r2               -> FMOV    s   (env r1) (env r2)
  307     FMUL  s r1 r2 r3            -> FMUL    s   (env r1) (env r2) (env r3)
  308     FNEG  s r1 r2               -> FNEG    s   (env r1) (env r2)
  309     FSQRT s r1 r2               -> FSQRT   s   (env r1) (env r2)
  310     FSUB  s r1 r2 r3            -> FSUB    s   (env r1) (env r2) (env r3)
  311     FxTOy s1 s2 r1 r2           -> FxTOy s1 s2 (env r1) (env r2)
  312 
  313     JMP     addr                -> JMP     (fixAddr addr)
  314     JMP_TBL addr ids l          -> JMP_TBL (fixAddr addr) ids l
  315 
  316     CALL  (Left i) n t          -> CALL (Left i) n t
  317     CALL  (Right r) n t         -> CALL (Right (env r)) n t
  318     _                           -> instr
  319 
  320   where
  321     fixAddr (AddrRegReg r1 r2)  = AddrRegReg   (env r1) (env r2)
  322     fixAddr (AddrRegImm r1 i)   = AddrRegImm   (env r1) i
  323 
  324     fixRI (RIReg r)             = RIReg (env r)
  325     fixRI other                 = other
  326 
  327 
  328 --------------------------------------------------------------------------------
  329 isJumpishInstr :: Instr -> Bool
  330 isJumpishInstr instr
  331  = case instr of
  332         BI{}            -> True
  333         BF{}            -> True
  334         JMP{}           -> True
  335         JMP_TBL{}       -> True
  336         CALL{}          -> True
  337         _               -> False
  338 
  339 jumpDestsOfInstr :: Instr -> [BlockId]
  340 jumpDestsOfInstr insn
  341   = case insn of
  342         BI   _ _ id     -> [id]
  343         BF   _ _ id     -> [id]
  344         JMP_TBL _ ids _ -> [id | Just id <- ids]
  345         _               -> []
  346 
  347 
  348 patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr
  349 patchJumpInstr insn patchF
  350   = case insn of
  351         BI cc annul id  -> BI cc annul (patchF id)
  352         BF cc annul id  -> BF cc annul (patchF id)
  353         JMP_TBL n ids l -> JMP_TBL n (map (fmap patchF) ids) l
  354         _               -> insn
  355 
  356 
  357 --------------------------------------------------------------------------------
  358 -- | Make a spill instruction.
  359 --      On SPARC we spill below frame pointer leaving 2 words/spill
  360 mkSpillInstr
  361     :: NCGConfig
  362     -> Reg      -- ^ register to spill
  363     -> Int      -- ^ current stack delta
  364     -> Int      -- ^ spill slot to use
  365     -> [Instr]
  366 
  367 mkSpillInstr config reg _ slot
  368  = let  platform = ncgPlatform config
  369         off      = spillSlotToOffset config slot
  370         off_w    = 1 + (off `div` 4)
  371         fmt      = case targetClassOfReg platform reg of
  372                         RcInteger -> II32
  373                         RcFloat   -> FF32
  374                         RcDouble  -> FF64
  375 
  376     in [ST fmt reg (fpRel (negate off_w))]
  377 
  378 
  379 -- | Make a spill reload instruction.
  380 mkLoadInstr
  381     :: NCGConfig
  382     -> Reg      -- ^ register to load into
  383     -> Int      -- ^ current stack delta
  384     -> Int      -- ^ spill slot to use
  385     -> [Instr]
  386 
  387 mkLoadInstr config reg _ slot
  388   = let platform = ncgPlatform config
  389         off      = spillSlotToOffset config slot
  390         off_w    = 1 + (off `div` 4)
  391         fmt      = case targetClassOfReg platform reg of
  392                         RcInteger -> II32
  393                         RcFloat   -> FF32
  394                         RcDouble  -> FF64
  395 
  396         in [LD fmt (fpRel (- off_w)) reg]
  397 
  398 
  399 --------------------------------------------------------------------------------
  400 -- | See if this instruction is telling us the current C stack delta
  401 takeDeltaInstr
  402         :: Instr
  403         -> Maybe Int
  404 
  405 takeDeltaInstr instr
  406  = case instr of
  407         DELTA i         -> Just i
  408         _               -> Nothing
  409 
  410 
  411 isMetaInstr
  412         :: Instr
  413         -> Bool
  414 
  415 isMetaInstr instr
  416  = case instr of
  417         COMMENT{}       -> True
  418         LDATA{}         -> True
  419         NEWBLOCK{}      -> True
  420         DELTA{}         -> True
  421         _               -> False
  422 
  423 
  424 -- | Make a reg-reg move instruction.
  425 --      On SPARC v8 there are no instructions to move directly between
  426 --      floating point and integer regs. If we need to do that then we
  427 --      have to go via memory.
  428 --
  429 mkRegRegMoveInstr
  430     :: Platform
  431     -> Reg
  432     -> Reg
  433     -> Instr
  434 
  435 mkRegRegMoveInstr platform src dst
  436         | srcClass      <- targetClassOfReg platform src
  437         , dstClass      <- targetClassOfReg platform dst
  438         , srcClass == dstClass
  439         = case srcClass of
  440                 RcInteger -> ADD  False False src (RIReg g0) dst
  441                 RcDouble  -> FMOV FF64 src dst
  442                 RcFloat   -> FMOV FF32 src dst
  443 
  444         | otherwise
  445         = panic "SPARC.Instr.mkRegRegMoveInstr: classes of src and dest not the same"
  446 
  447 
  448 -- | Check whether an instruction represents a reg-reg move.
  449 --      The register allocator attempts to eliminate reg->reg moves whenever it can,
  450 --      by assigning the src and dest temporaries to the same real register.
  451 --
  452 takeRegRegMoveInstr :: Instr -> Maybe (Reg,Reg)
  453 takeRegRegMoveInstr instr
  454  = case instr of
  455         ADD False False src (RIReg src2) dst
  456          | g0 == src2           -> Just (src, dst)
  457 
  458         FMOV FF64 src dst       -> Just (src, dst)
  459         FMOV FF32  src dst      -> Just (src, dst)
  460         _                       -> Nothing
  461 
  462 
  463 -- | Make an unconditional branch instruction.
  464 mkJumpInstr
  465         :: BlockId
  466         -> [Instr]
  467 
  468 mkJumpInstr id
  469  =       [BI ALWAYS False id
  470         , NOP]                  -- fill the branch delay slot.