never executed always true always false
    1 {-# LANGUAGE LambdaCase #-}
    2 {-# LANGUAGE MultiParamTypeClasses #-}
    3 {-# LANGUAGE FlexibleInstances #-}
    4 
    5 
    6 -----------------------------------------------------------------------------
    7 --
    8 -- Pretty-printing assembly language
    9 --
   10 -- (c) The University of Glasgow 1993-2005
   11 --
   12 -----------------------------------------------------------------------------
   13 
   14 {-# OPTIONS_GHC -fno-warn-orphans #-}
   15 module GHC.CmmToAsm.SPARC.Ppr (
   16         pprNatCmmDecl,
   17         pprBasicBlock,
   18         pprData,
   19         pprInstr,
   20         pprFormat,
   21         pprImm,
   22         pprDataItem
   23 )
   24 
   25 where
   26 
   27 import GHC.Prelude
   28 
   29 import Data.Word
   30 import qualified Data.Array.Unsafe as U ( castSTUArray )
   31 import Data.Array.ST
   32 
   33 import Control.Monad.ST
   34 
   35 import GHC.CmmToAsm.SPARC.Regs
   36 import GHC.CmmToAsm.SPARC.Instr
   37 import GHC.CmmToAsm.SPARC.Cond
   38 import GHC.CmmToAsm.SPARC.Imm
   39 import GHC.CmmToAsm.SPARC.AddrMode
   40 import GHC.CmmToAsm.SPARC.Base
   41 import GHC.Platform.Reg
   42 import GHC.CmmToAsm.Format
   43 import GHC.CmmToAsm.Ppr
   44 import GHC.CmmToAsm.Config
   45 import GHC.CmmToAsm.Types
   46 import GHC.CmmToAsm.Utils
   47 
   48 import GHC.Cmm hiding (topInfoTable)
   49 import GHC.Cmm.Ppr() -- For Outputable instances
   50 import GHC.Cmm.BlockId
   51 import GHC.Cmm.CLabel
   52 import GHC.Cmm.Dataflow.Label
   53 import GHC.Cmm.Dataflow.Collections
   54 
   55 import GHC.Types.Unique ( pprUniqueAlways )
   56 import GHC.Utils.Outputable
   57 import GHC.Utils.Panic
   58 import GHC.Platform
   59 
   60 -- -----------------------------------------------------------------------------
   61 -- Printing this stuff out
   62 
   63 pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc
   64 pprNatCmmDecl config (CmmData section dats) =
   65   pprSectionAlign config section
   66   $$ pprDatas (ncgPlatform config) dats
   67 
   68 pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
   69   let platform = ncgPlatform config in
   70   case topInfoTable proc of
   71     Nothing ->
   72         -- special case for code without info table:
   73         pprSectionAlign config (Section Text lbl) $$
   74         pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed
   75         vcat (map (pprBasicBlock platform top_info) blocks)
   76 
   77     Just (CmmStaticsRaw info_lbl _) ->
   78       (if platformHasSubsectionsViaSymbols platform
   79           then pprSectionAlign config dspSection $$
   80                pdoc platform (mkDeadStripPreventer info_lbl) <> char ':'
   81           else empty) $$
   82       vcat (map (pprBasicBlock platform top_info) blocks) $$
   83       -- above: Even the first block gets a label, because with branch-chain
   84       -- elimination, it might be the target of a goto.
   85       (if platformHasSubsectionsViaSymbols platform
   86        then
   87        -- See Note [Subsections Via Symbols] in X86/Ppr.hs
   88                 text "\t.long "
   89             <+> pdoc platform info_lbl
   90             <+> char '-'
   91             <+> pdoc platform (mkDeadStripPreventer info_lbl)
   92        else empty)
   93 
   94 dspSection :: Section
   95 dspSection = Section Text $
   96     panic "subsections-via-symbols doesn't combine with split-sections"
   97 
   98 pprBasicBlock :: Platform -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
   99 pprBasicBlock platform info_env (BasicBlock blockid instrs)
  100   = maybe_infotable $$
  101     pprLabel platform (blockLbl blockid) $$
  102     vcat (map (pprInstr platform) instrs)
  103   where
  104     maybe_infotable = case mapLookup blockid info_env of
  105        Nothing   -> empty
  106        Just (CmmStaticsRaw info_lbl info) ->
  107            pprAlignForSection Text $$
  108            vcat (map (pprData platform) info) $$
  109            pprLabel platform info_lbl
  110 
  111 
  112 pprDatas :: Platform -> RawCmmStatics -> SDoc
  113 -- See note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
  114 pprDatas platform (CmmStaticsRaw alias [CmmStaticLit (CmmLabel lbl), CmmStaticLit ind, _, _])
  115   | lbl == mkIndStaticInfoLabel
  116   , let labelInd (CmmLabelOff l _) = Just l
  117         labelInd (CmmLabel l) = Just l
  118         labelInd _ = Nothing
  119   , Just ind' <- labelInd ind
  120   , alias `mayRedirectTo` ind'
  121   = pprGloblDecl platform alias
  122     $$ text ".equiv" <+> pdoc platform alias <> comma <> pdoc platform (CmmLabel ind')
  123 pprDatas platform (CmmStaticsRaw lbl dats) = vcat (pprLabel platform lbl : map (pprData platform) dats)
  124 
  125 pprData :: Platform -> CmmStatic -> SDoc
  126 pprData platform d = case d of
  127    CmmString str          -> pprString str
  128    CmmFileEmbed path      -> pprFileEmbed path
  129    CmmUninitialised bytes -> text ".skip " <> int bytes
  130    CmmStaticLit lit       -> pprDataItem platform lit
  131 
  132 pprGloblDecl :: Platform -> CLabel -> SDoc
  133 pprGloblDecl platform lbl
  134   | not (externallyVisibleCLabel lbl) = empty
  135   | otherwise = text ".global " <> pdoc platform lbl
  136 
  137 pprTypeAndSizeDecl :: Platform -> CLabel -> SDoc
  138 pprTypeAndSizeDecl platform lbl
  139     = if platformOS platform == OSLinux && externallyVisibleCLabel lbl
  140       then text ".type " <> pdoc platform lbl <> text ", @object"
  141       else empty
  142 
  143 pprLabel :: Platform -> CLabel -> SDoc
  144 pprLabel platform lbl =
  145    pprGloblDecl platform lbl
  146    $$ pprTypeAndSizeDecl platform lbl
  147    $$ (pdoc platform lbl <> char ':')
  148 
  149 -- -----------------------------------------------------------------------------
  150 -- pprInstr: print an 'Instr'
  151 
  152 instance OutputableP Platform Instr where
  153     pdoc = pprInstr
  154 
  155 
  156 -- | Pretty print a register.
  157 pprReg :: Reg -> SDoc
  158 pprReg reg
  159  = case reg of
  160         RegVirtual vr
  161          -> case vr of
  162                 VirtualRegI   u -> text "%vI_"   <> pprUniqueAlways u
  163                 VirtualRegHi  u -> text "%vHi_"  <> pprUniqueAlways u
  164                 VirtualRegF   u -> text "%vF_"   <> pprUniqueAlways u
  165                 VirtualRegD   u -> text "%vD_"   <> pprUniqueAlways u
  166 
  167 
  168         RegReal rr
  169          -> case rr of
  170                 RealRegSingle r1
  171                  -> pprReg_ofRegNo r1
  172 
  173                 RealRegPair r1 r2
  174                  -> text "(" <> pprReg_ofRegNo r1
  175                  <> vbar     <> pprReg_ofRegNo r2
  176                  <> text ")"
  177 
  178 
  179 
  180 -- | Pretty print a register name, based on this register number.
  181 --   The definition has been unfolded so we get a jump-table in the
  182 --   object code. This function is called quite a lot when emitting
  183 --   the asm file..
  184 --
  185 pprReg_ofRegNo :: Int -> SDoc
  186 pprReg_ofRegNo i
  187  = case i of {
  188          0 -> text "%g0";   1 -> text "%g1";
  189          2 -> text "%g2";   3 -> text "%g3";
  190          4 -> text "%g4";   5 -> text "%g5";
  191          6 -> text "%g6";   7 -> text "%g7";
  192          8 -> text "%o0";   9 -> text "%o1";
  193         10 -> text "%o2";  11 -> text "%o3";
  194         12 -> text "%o4";  13 -> text "%o5";
  195         14 -> text "%o6";  15 -> text "%o7";
  196         16 -> text "%l0";  17 -> text "%l1";
  197         18 -> text "%l2";  19 -> text "%l3";
  198         20 -> text "%l4";  21 -> text "%l5";
  199         22 -> text "%l6";  23 -> text "%l7";
  200         24 -> text "%i0";  25 -> text "%i1";
  201         26 -> text "%i2";  27 -> text "%i3";
  202         28 -> text "%i4";  29 -> text "%i5";
  203         30 -> text "%i6";  31 -> text "%i7";
  204         32 -> text "%f0";  33 -> text "%f1";
  205         34 -> text "%f2";  35 -> text "%f3";
  206         36 -> text "%f4";  37 -> text "%f5";
  207         38 -> text "%f6";  39 -> text "%f7";
  208         40 -> text "%f8";  41 -> text "%f9";
  209         42 -> text "%f10"; 43 -> text "%f11";
  210         44 -> text "%f12"; 45 -> text "%f13";
  211         46 -> text "%f14"; 47 -> text "%f15";
  212         48 -> text "%f16"; 49 -> text "%f17";
  213         50 -> text "%f18"; 51 -> text "%f19";
  214         52 -> text "%f20"; 53 -> text "%f21";
  215         54 -> text "%f22"; 55 -> text "%f23";
  216         56 -> text "%f24"; 57 -> text "%f25";
  217         58 -> text "%f26"; 59 -> text "%f27";
  218         60 -> text "%f28"; 61 -> text "%f29";
  219         62 -> text "%f30"; 63 -> text "%f31";
  220         _  -> text "very naughty sparc register" }
  221 
  222 
  223 -- | Pretty print a format for an instruction suffix.
  224 pprFormat :: Format -> SDoc
  225 pprFormat x
  226  = case x of
  227         II8     -> text "ub"
  228         II16    -> text "uh"
  229         II32    -> text ""
  230         II64    -> text "d"
  231         FF32    -> text ""
  232         FF64    -> text "d"
  233 
  234 
  235 -- | Pretty print a format for an instruction suffix.
  236 --      eg LD is 32bit on sparc, but LDD is 64 bit.
  237 pprStFormat :: Format -> SDoc
  238 pprStFormat x
  239  = case x of
  240         II8   -> text "b"
  241         II16  -> text "h"
  242         II32  -> text ""
  243         II64  -> text "x"
  244         FF32  -> text ""
  245         FF64  -> text "d"
  246 
  247 
  248 
  249 -- | Pretty print a condition code.
  250 pprCond :: Cond -> SDoc
  251 pprCond c
  252  = case c of
  253         ALWAYS  -> text ""
  254         NEVER   -> text "n"
  255         GEU     -> text "geu"
  256         LU      -> text "lu"
  257         EQQ     -> text "e"
  258         GTT     -> text "g"
  259         GE      -> text "ge"
  260         GU      -> text "gu"
  261         LTT     -> text "l"
  262         LE      -> text "le"
  263         LEU     -> text "leu"
  264         NE      -> text "ne"
  265         NEG     -> text "neg"
  266         POS     -> text "pos"
  267         VC      -> text "vc"
  268         VS      -> text "vs"
  269 
  270 
  271 -- | Pretty print an address mode.
  272 pprAddr :: Platform -> AddrMode -> SDoc
  273 pprAddr platform am
  274  = case am of
  275         AddrRegReg r1 (RegReal (RealRegSingle 0))
  276          -> pprReg r1
  277 
  278         AddrRegReg r1 r2
  279          -> hcat [ pprReg r1, char '+', pprReg r2 ]
  280 
  281         AddrRegImm r1 (ImmInt i)
  282          | i == 0               -> pprReg r1
  283          | not (fits13Bits i)   -> largeOffsetError i
  284          | otherwise            -> hcat [ pprReg r1, pp_sign, int i ]
  285          where
  286                 pp_sign = if i > 0 then char '+' else empty
  287 
  288         AddrRegImm r1 (ImmInteger i)
  289          | i == 0               -> pprReg r1
  290          | not (fits13Bits i)   -> largeOffsetError i
  291          | otherwise            -> hcat [ pprReg r1, pp_sign, integer i ]
  292          where
  293                 pp_sign = if i > 0 then char '+' else empty
  294 
  295         AddrRegImm r1 imm
  296          -> hcat [ pprReg r1, char '+', pprImm platform imm ]
  297 
  298 
  299 -- | Pretty print an immediate value.
  300 pprImm :: Platform -> Imm -> SDoc
  301 pprImm platform imm
  302  = case imm of
  303         ImmInt i        -> int i
  304         ImmInteger i    -> integer i
  305         ImmCLbl l       -> pdoc platform l
  306         ImmIndex l i    -> pdoc platform l <> char '+' <> int i
  307         ImmLit s        -> s
  308 
  309         ImmConstantSum a b
  310          -> pprImm platform a <> char '+' <> pprImm platform b
  311 
  312         ImmConstantDiff a b
  313          -> pprImm platform a <> char '-' <> lparen <> pprImm platform b <> rparen
  314 
  315         LO i
  316          -> hcat [ text "%lo(", pprImm platform i, rparen ]
  317 
  318         HI i
  319          -> hcat [ text "%hi(", pprImm platform i, rparen ]
  320 
  321         -- these should have been converted to bytes and placed
  322         --      in the data section.
  323         ImmFloat _      -> text "naughty float immediate"
  324         ImmDouble _     -> text "naughty double immediate"
  325 
  326 
  327 -- | Pretty print a section \/ segment header.
  328 --      On SPARC all the data sections must be at least 8 byte aligned
  329 --      incase we store doubles in them.
  330 --
  331 pprSectionAlign :: NCGConfig -> Section -> SDoc
  332 pprSectionAlign config sec@(Section seg _) =
  333     pprSectionHeader config sec $$
  334     pprAlignForSection seg
  335 
  336 -- | Print appropriate alignment for the given section type.
  337 pprAlignForSection :: SectionType -> SDoc
  338 pprAlignForSection seg =
  339     case seg of
  340       Text                    -> text ".align 4"
  341       Data                    -> text ".align 8"
  342       ReadOnlyData            -> text ".align 8"
  343       RelocatableReadOnlyData -> text ".align 8"
  344       UninitialisedData       -> text ".align 8"
  345       ReadOnlyData16          -> text ".align 16"
  346       -- TODO: This is copied from the ReadOnlyData case, but it can likely be
  347       -- made more efficient.
  348       CString                 -> text ".align 8"
  349       OtherSection _          -> panic "PprMach.pprSectionHeader: unknown section"
  350 
  351 -- | Pretty print a data item.
  352 pprDataItem :: Platform -> CmmLit -> SDoc
  353 pprDataItem platform lit
  354   = vcat (ppr_item (cmmTypeFormat $ cmmLitType platform lit) lit)
  355     where
  356         imm = litToImm lit
  357 
  358         ppr_item II8   _        = [text "\t.byte\t" <> pprImm platform imm]
  359         ppr_item II32  _        = [text "\t.long\t" <> pprImm platform imm]
  360 
  361         ppr_item FF32  (CmmFloat r _)
  362          = let bs = floatToBytes (fromRational r)
  363            in  map (\b -> text "\t.byte\t" <> pprImm platform (ImmInt b)) bs
  364 
  365         ppr_item FF64 (CmmFloat r _)
  366          = let bs = doubleToBytes (fromRational r)
  367            in  map (\b -> text "\t.byte\t" <> pprImm platform (ImmInt b)) bs
  368 
  369         ppr_item II16  _        = [text "\t.short\t" <> pprImm platform imm]
  370         ppr_item II64  _        = [text "\t.quad\t"  <> pprImm platform imm]
  371         ppr_item _ _            = panic "SPARC.Ppr.pprDataItem: no match"
  372 
  373 floatToBytes :: Float -> [Int]
  374 floatToBytes f
  375    = runST (do
  376         arr <- newArray_ ((0::Int),3)
  377         writeArray arr 0 f
  378         arr <- castFloatToWord8Array arr
  379         i0 <- readArray arr 0
  380         i1 <- readArray arr 1
  381         i2 <- readArray arr 2
  382         i3 <- readArray arr 3
  383         return (map fromIntegral [i0,i1,i2,i3])
  384      )
  385 
  386 castFloatToWord8Array :: STUArray s Int Float -> ST s (STUArray s Int Word8)
  387 castFloatToWord8Array = U.castSTUArray
  388 
  389 
  390 asmComment :: SDoc -> SDoc
  391 asmComment c = whenPprDebug $ text "#" <+> c
  392 
  393 
  394 -- | Pretty print an instruction.
  395 pprInstr :: Platform -> Instr -> SDoc
  396 pprInstr platform = \case
  397    COMMENT s -> asmComment s
  398    DELTA d   -> asmComment $ text ("\tdelta = " ++ show d)
  399 
  400    -- Newblocks and LData should have been slurped out before producing the .s file.
  401    NEWBLOCK _ -> panic "X86.Ppr.pprInstr: NEWBLOCK"
  402    LDATA _ _  -> panic "PprMach.pprInstr: LDATA"
  403 
  404    -- 64 bit FP loads are expanded into individual instructions in CodeGen.Expand
  405    LD FF64 _ reg
  406         | RegReal (RealRegSingle{})     <- reg
  407         -> panic "SPARC.Ppr: not emitting potentially misaligned LD FF64 instr"
  408 
  409    LD format addr reg
  410         -> hcat [
  411                text "\tld",
  412                pprFormat format,
  413                char '\t',
  414                lbrack,
  415                pprAddr platform addr,
  416                pp_rbracket_comma,
  417                pprReg reg
  418             ]
  419 
  420    -- 64 bit FP stores are expanded into individual instructions in CodeGen.Expand
  421    ST FF64 reg _
  422         | RegReal (RealRegSingle{}) <- reg
  423         -> panic "SPARC.Ppr: not emitting potentially misaligned ST FF64 instr"
  424 
  425    -- no distinction is made between signed and unsigned bytes on stores for the
  426    -- Sparc opcodes (at least I cannot see any, and gas is nagging me --SOF),
  427    -- so we call a special-purpose pprFormat for ST..
  428    ST format reg addr
  429         -> hcat [
  430                text "\tst",
  431                pprStFormat format,
  432                char '\t',
  433                pprReg reg,
  434                pp_comma_lbracket,
  435                pprAddr platform addr,
  436                rbrack
  437             ]
  438 
  439 
  440    ADD x cc reg1 ri reg2
  441         | not x && not cc && riZero ri
  442         -> hcat [ text "\tmov\t", pprReg reg1, comma, pprReg reg2 ]
  443 
  444         | otherwise
  445         -> pprRegRIReg platform (if x then text "addx" else text "add") cc reg1 ri reg2
  446 
  447 
  448    SUB x cc reg1 ri reg2
  449         | not x && cc && reg2 == g0
  450         -> hcat [ text "\tcmp\t", pprReg reg1, comma, pprRI platform ri ]
  451 
  452         | not x && not cc && riZero ri
  453         -> hcat [ text "\tmov\t", pprReg reg1, comma, pprReg reg2 ]
  454 
  455         | otherwise
  456         -> pprRegRIReg platform (if x then text "subx" else text "sub") cc reg1 ri reg2
  457 
  458    AND  b reg1 ri reg2 -> pprRegRIReg platform (text "and")  b reg1 ri reg2
  459 
  460    ANDN b reg1 ri reg2 -> pprRegRIReg platform (text "andn") b reg1 ri reg2
  461 
  462    OR b reg1 ri reg2
  463         | not b && reg1 == g0
  464         -> let doit = hcat [ text "\tmov\t", pprRI platform ri, comma, pprReg reg2 ]
  465            in  case ri of
  466                    RIReg rrr | rrr == reg2 -> empty
  467                    _                       -> doit
  468 
  469         | otherwise
  470         -> pprRegRIReg platform (text "or") b reg1 ri reg2
  471 
  472    ORN b reg1 ri reg2 -> pprRegRIReg platform (text "orn") b reg1 ri reg2
  473 
  474    XOR  b reg1 ri reg2 -> pprRegRIReg platform (text "xor")  b reg1 ri reg2
  475    XNOR b reg1 ri reg2 -> pprRegRIReg platform (text "xnor") b reg1 ri reg2
  476 
  477    SLL reg1 ri reg2 -> pprRegRIReg platform (text "sll") False reg1 ri reg2
  478    SRL reg1 ri reg2 -> pprRegRIReg platform (text "srl") False reg1 ri reg2
  479    SRA reg1 ri reg2 -> pprRegRIReg platform (text "sra") False reg1 ri reg2
  480 
  481    RDY rd -> text "\trd\t%y," <> pprReg rd
  482    WRY reg1 reg2
  483         -> text "\twr\t"
  484                 <> pprReg reg1
  485                 <> char ','
  486                 <> pprReg reg2
  487                 <> char ','
  488                 <> text "%y"
  489 
  490    SMUL b reg1 ri reg2 -> pprRegRIReg platform (text "smul")  b reg1 ri reg2
  491    UMUL b reg1 ri reg2 -> pprRegRIReg platform (text "umul")  b reg1 ri reg2
  492    SDIV b reg1 ri reg2 -> pprRegRIReg platform (text "sdiv")  b reg1 ri reg2
  493    UDIV b reg1 ri reg2 -> pprRegRIReg platform (text "udiv")  b reg1 ri reg2
  494 
  495    SETHI imm reg
  496       -> hcat [
  497             text "\tsethi\t",
  498             pprImm platform imm,
  499             comma,
  500             pprReg reg
  501          ]
  502 
  503    NOP -> text "\tnop"
  504 
  505    FABS format reg1 reg2
  506         -> pprFormatRegReg (text "fabs") format reg1 reg2
  507 
  508    FADD format reg1 reg2 reg3
  509         -> pprFormatRegRegReg (text "fadd") format reg1 reg2 reg3
  510 
  511    FCMP e format reg1 reg2
  512         -> pprFormatRegReg (if e then text "fcmpe" else text "fcmp")
  513                            format reg1 reg2
  514 
  515    FDIV format reg1 reg2 reg3
  516         -> pprFormatRegRegReg (text "fdiv") format reg1 reg2 reg3
  517 
  518    FMOV format reg1 reg2
  519         -> pprFormatRegReg (text "fmov") format reg1 reg2
  520 
  521    FMUL format reg1 reg2 reg3
  522         -> pprFormatRegRegReg (text "fmul") format reg1 reg2 reg3
  523 
  524    FNEG format reg1 reg2
  525         -> pprFormatRegReg (text "fneg") format reg1 reg2
  526 
  527    FSQRT format reg1 reg2
  528         -> pprFormatRegReg (text "fsqrt") format reg1 reg2
  529 
  530    FSUB format reg1 reg2 reg3
  531         -> pprFormatRegRegReg (text "fsub") format reg1 reg2 reg3
  532 
  533    FxTOy format1 format2 reg1 reg2
  534       -> hcat [
  535             text "\tf",
  536             (case format1 of
  537                 II32  -> text "ito"
  538                 FF32  -> text "sto"
  539                 FF64  -> text "dto"
  540                 _     -> panic "SPARC.Ppr.pprInstr.FxToY: no match"),
  541             (case format2 of
  542                 II32  -> text "i\t"
  543                 II64  -> text "x\t"
  544                 FF32  -> text "s\t"
  545                 FF64  -> text "d\t"
  546                 _     -> panic "SPARC.Ppr.pprInstr.FxToY: no match"),
  547             pprReg reg1, comma, pprReg reg2
  548          ]
  549 
  550 
  551    BI cond b blockid
  552       -> hcat [
  553             text "\tb", pprCond cond,
  554             if b then pp_comma_a else empty,
  555             char '\t',
  556             pdoc platform (blockLbl blockid)
  557          ]
  558 
  559    BF cond b blockid
  560       -> hcat [
  561             text "\tfb", pprCond cond,
  562             if b then pp_comma_a else empty,
  563             char '\t',
  564             pdoc platform (blockLbl blockid)
  565          ]
  566 
  567    JMP addr -> text "\tjmp\t" <> pprAddr platform addr
  568    JMP_TBL op _ _ -> pprInstr platform (JMP op)
  569 
  570    CALL (Left imm) n _
  571       -> hcat [ text "\tcall\t", pprImm platform imm, comma, int n ]
  572 
  573    CALL (Right reg) n _
  574       -> hcat [ text "\tcall\t", pprReg reg, comma, int n ]
  575 
  576 
  577 -- | Pretty print a RI
  578 pprRI :: Platform -> RI -> SDoc
  579 pprRI platform = \case
  580    RIReg r -> pprReg r
  581    RIImm r -> pprImm platform r
  582 
  583 
  584 -- | Pretty print a two reg instruction.
  585 pprFormatRegReg :: SDoc -> Format -> Reg -> Reg -> SDoc
  586 pprFormatRegReg name format reg1 reg2
  587   = hcat [
  588         char '\t',
  589         name,
  590         (case format of
  591             FF32 -> text "s\t"
  592             FF64 -> text "d\t"
  593             _    -> panic "SPARC.Ppr.pprFormatRegReg: no match"),
  594 
  595         pprReg reg1,
  596         comma,
  597         pprReg reg2
  598     ]
  599 
  600 
  601 -- | Pretty print a three reg instruction.
  602 pprFormatRegRegReg :: SDoc -> Format -> Reg -> Reg -> Reg -> SDoc
  603 pprFormatRegRegReg name format reg1 reg2 reg3
  604   = hcat [
  605         char '\t',
  606         name,
  607         (case format of
  608             FF32  -> text "s\t"
  609             FF64  -> text "d\t"
  610             _    -> panic "SPARC.Ppr.pprFormatRegReg: no match"),
  611         pprReg reg1,
  612         comma,
  613         pprReg reg2,
  614         comma,
  615         pprReg reg3
  616     ]
  617 
  618 
  619 -- | Pretty print an instruction of two regs and a ri.
  620 pprRegRIReg :: Platform -> SDoc -> Bool -> Reg -> RI -> Reg -> SDoc
  621 pprRegRIReg platform name b reg1 ri reg2
  622   = hcat [
  623         char '\t',
  624         name,
  625         if b then text "cc\t" else char '\t',
  626         pprReg reg1,
  627         comma,
  628         pprRI platform ri,
  629         comma,
  630         pprReg reg2
  631     ]
  632 
  633 {-
  634 pprRIReg :: SDoc -> Bool -> RI -> Reg -> SDoc
  635 pprRIReg name b ri reg1
  636   = hcat [
  637         char '\t',
  638         name,
  639         if b then text "cc\t" else char '\t',
  640         pprRI ri,
  641         comma,
  642         pprReg reg1
  643     ]
  644 -}
  645 
  646 {-
  647 pp_ld_lbracket :: SDoc
  648 pp_ld_lbracket    = text "\tld\t["
  649 -}
  650 
  651 pp_rbracket_comma :: SDoc
  652 pp_rbracket_comma = text "],"
  653 
  654 
  655 pp_comma_lbracket :: SDoc
  656 pp_comma_lbracket = text ",["
  657 
  658 
  659 pp_comma_a :: SDoc
  660 pp_comma_a        = text ",a"