{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}

-----------------------------------------------------------------------------
--
-- Pretty-printing assembly language
--
-- (c) The University of Glasgow 1993-2005
--
-----------------------------------------------------------------------------

module GHC.CmmToAsm.X86.Ppr (
        pprNatCmmDecl,
        pprInstr,
)

where

import GHC.Prelude

import GHC.Platform
import GHC.Platform.Reg

import GHC.CmmToAsm.X86.Regs
import GHC.CmmToAsm.X86.Instr
import GHC.CmmToAsm.X86.Cond
import GHC.CmmToAsm.Config
import GHC.CmmToAsm.Format
import GHC.CmmToAsm.Types
import GHC.CmmToAsm.Utils
import GHC.CmmToAsm.Ppr

import GHC.Cmm              hiding (topInfoTable)
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
import GHC.Cmm.BlockId
import GHC.Cmm.CLabel
import GHC.Cmm.DebugBlock (pprUnwindTable)

import GHC.Types.Basic (Alignment, mkAlignment, alignmentBytes)
import GHC.Types.Unique ( pprUniqueAlways )

import GHC.Utils.Outputable
import GHC.Utils.Panic

import Data.Word

-- Note [Subsections Via Symbols]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- If we are using the .subsections_via_symbols directive
-- (available on recent versions of Darwin),
-- we have to make sure that there is some kind of reference
-- from the entry code to a label on the _top_ of the info table,
-- so that the linker will not think it is unreferenced and dead-strip
-- it. That's why the label is called a DeadStripPreventer (_dsp).
--
-- The LLVM code gen already creates `iTableSuf` symbols, where
-- the X86 would generate the DeadStripPreventer (_dsp) symbol.
-- Therefore all that is left for llvm code gen, is to ensure
-- that all the `iTableSuf` symbols are marked as used.
-- As of this writing the documentation regarding the
-- .subsections_via_symbols and -dead_strip can be found at
-- <https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html#//apple_ref/doc/uid/TP30000823-TPXREF101>

pprProcAlignment :: IsDoc doc => NCGConfig -> doc
pprProcAlignment :: forall doc. IsDoc doc => NCGConfig -> doc
pprProcAlignment NCGConfig
config = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall doc. IsOutput doc => doc
empty (forall doc. IsDoc doc => Platform -> Alignment -> doc
pprAlign Platform
platform forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Alignment
mkAlignment) (NCGConfig -> Maybe Int
ncgProcAlignment NCGConfig
config)
   where
      platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config

pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> doc
pprNatCmmDecl :: forall doc.
IsDoc doc =>
NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> doc
pprNatCmmDecl NCGConfig
config (CmmData Section
section (Alignment, RawCmmStatics)
dats) =
  forall doc. IsDoc doc => NCGConfig -> Section -> doc
pprSectionAlign NCGConfig
config Section
section forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc.
IsDoc doc =>
NCGConfig -> (Alignment, RawCmmStatics) -> doc
pprDatas NCGConfig
config (Alignment, RawCmmStatics)
dats

pprNatCmmDecl NCGConfig
config proc :: NatCmmDecl (Alignment, RawCmmStatics) Instr
proc@(CmmProc LabelMap RawCmmStatics
top_info CLabel
lbl [GlobalReg]
_ (ListGraph [GenBasicBlock Instr]
blocks)) =
  let platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config in
  forall doc. IsDoc doc => NCGConfig -> doc
pprProcAlignment NCGConfig
config forall doc. IsDoc doc => doc -> doc -> doc
$$
  case forall a i b. GenCmmDecl a (LabelMap i) (ListGraph b) -> Maybe i
topInfoTable NatCmmDecl (Alignment, RawCmmStatics) Instr
proc of
    Maybe RawCmmStatics
Nothing ->
        -- special case for code without info table:
        forall doc. IsDoc doc => NCGConfig -> Section -> doc
pprSectionAlign NCGConfig
config (SectionType -> CLabel -> Section
Section SectionType
Text CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
        forall doc. IsDoc doc => NCGConfig -> doc
pprProcAlignment NCGConfig
config forall doc. IsDoc doc => doc -> doc -> doc
$$
        forall doc. IsDoc doc => NCGConfig -> CLabel -> doc
pprProcLabel NCGConfig
config CLabel
lbl forall doc. IsDoc doc => doc -> doc -> doc
$$
        forall doc. IsDoc doc => Platform -> CLabel -> doc
pprLabel Platform
platform CLabel
lbl forall doc. IsDoc doc => doc -> doc -> doc
$$ -- blocks guaranteed not null, so label needed
        forall doc. IsDoc doc => [doc] -> doc
vcat (forall a b. (a -> b) -> [a] -> [b]
map (forall doc.
IsDoc doc =>
NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
pprBasicBlock NCGConfig
config LabelMap RawCmmStatics
top_info) [GenBasicBlock Instr]
blocks) forall doc. IsDoc doc => doc -> doc -> doc
$$
        forall doc. IsOutput doc => Bool -> doc -> doc
ppWhen (NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config) (forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprBlockEndLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprProcEndLabel Platform
platform CLabel
lbl)) forall doc. IsDoc doc => doc -> doc -> doc
$$
        forall doc. IsDoc doc => Platform -> CLabel -> doc
pprSizeDecl Platform
platform CLabel
lbl

    Just (CmmStaticsRaw CLabel
info_lbl [CmmStatic]
_) ->
      forall doc. IsDoc doc => NCGConfig -> Section -> doc
pprSectionAlign NCGConfig
config (SectionType -> CLabel -> Section
Section SectionType
Text CLabel
info_lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
      forall doc. IsDoc doc => NCGConfig -> doc
pprProcAlignment NCGConfig
config forall doc. IsDoc doc => doc -> doc -> doc
$$
      forall doc. IsDoc doc => NCGConfig -> CLabel -> doc
pprProcLabel NCGConfig
config CLabel
lbl forall doc. IsDoc doc => doc -> doc -> doc
$$
      (if Platform -> Bool
platformHasSubsectionsViaSymbols Platform
platform
          then forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkDeadStripPreventer CLabel
info_lbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon)
          else forall doc. IsOutput doc => doc
empty) forall doc. IsDoc doc => doc -> doc -> doc
$$
      forall doc. IsDoc doc => [doc] -> doc
vcat (forall a b. (a -> b) -> [a] -> [b]
map (forall doc.
IsDoc doc =>
NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
pprBasicBlock NCGConfig
config LabelMap RawCmmStatics
top_info) [GenBasicBlock Instr]
blocks) forall doc. IsDoc doc => doc -> doc -> doc
$$
      forall doc. IsOutput doc => Bool -> doc -> doc
ppWhen (NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config) (forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprProcEndLabel Platform
platform CLabel
info_lbl)) forall doc. IsDoc doc => doc -> doc -> doc
$$
      -- above: Even the first block gets a label, because with branch-chain
      -- elimination, it might be the target of a goto.
      (if Platform -> Bool
platformHasSubsectionsViaSymbols Platform
platform
       then -- See Note [Subsections Via Symbols]
                forall doc. IsDoc doc => Line doc -> doc
line
              forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\t.long "
            forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
info_lbl
            forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Char -> doc
char Char
'-'
            forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkDeadStripPreventer CLabel
info_lbl)
       else forall doc. IsOutput doc => doc
empty) forall doc. IsDoc doc => doc -> doc -> doc
$$
      forall doc. IsDoc doc => Platform -> CLabel -> doc
pprSizeDecl Platform
platform CLabel
info_lbl
{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc #-}
{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

-- | Output an internal proc label. See Note [Internal proc labels] in CLabel.
pprProcLabel :: IsDoc doc => NCGConfig -> CLabel -> doc
pprProcLabel :: forall doc. IsDoc doc => NCGConfig -> CLabel -> doc
pprProcLabel NCGConfig
config CLabel
lbl
  | NCGConfig -> Bool
ncgExposeInternalSymbols NCGConfig
config
  , Just Line doc
lbl' <- forall doc. IsLine doc => Module -> CLabel -> Maybe doc
ppInternalProcLabel (NCGConfig -> Module
ncgThisModule NCGConfig
config) CLabel
lbl
  = forall doc. IsDoc doc => Line doc -> doc
line (Line doc
lbl' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon)
  | Bool
otherwise
  = forall doc. IsOutput doc => doc
empty

pprProcEndLabel :: IsLine doc => Platform -> CLabel -- ^ Procedure name
                -> doc
pprProcEndLabel :: forall doc. IsLine doc => Platform -> CLabel -> doc
pprProcEndLabel Platform
platform CLabel
lbl =
    forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkAsmTempProcEndLabel CLabel
lbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon

pprBlockEndLabel :: IsLine doc => Platform -> CLabel -- ^ Block name
                 -> doc
pprBlockEndLabel :: forall doc. IsLine doc => Platform -> CLabel -> doc
pprBlockEndLabel Platform
platform CLabel
lbl =
    forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkAsmTempEndLabel CLabel
lbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon

-- | Output the ELF .size directive.
pprSizeDecl :: IsDoc doc => Platform -> CLabel -> doc
pprSizeDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
pprSizeDecl Platform
platform CLabel
lbl
 = if OS -> Bool
osElfTarget (Platform -> OS
platformOS Platform
platform)
   then forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
"\t.size" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => String -> doc
text String
", .-" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)
   else forall doc. IsOutput doc => doc
empty

pprBasicBlock :: IsDoc doc => NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> doc
pprBasicBlock :: forall doc.
IsDoc doc =>
NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
pprBasicBlock NCGConfig
config LabelMap RawCmmStatics
info_env (BasicBlock BlockId
blockid [Instr]
instrs)
  = doc -> doc
maybe_infotable forall a b. (a -> b) -> a -> b
$
    forall doc. IsDoc doc => Platform -> CLabel -> doc
pprLabel Platform
platform CLabel
asmLbl forall doc. IsDoc doc => doc -> doc -> doc
$$
    forall doc. IsDoc doc => [doc] -> doc
vcat (forall a b. (a -> b) -> [a] -> [b]
map (forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform) [Instr]
instrs) forall doc. IsDoc doc => doc -> doc -> doc
$$
    forall doc. IsOutput doc => Bool -> doc -> doc
ppWhen (NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config) (
      -- Emit both end labels since this may end up being a standalone
      -- top-level block
      forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprBlockEndLabel Platform
platform CLabel
asmLbl
         forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprProcEndLabel Platform
platform CLabel
asmLbl)
    )
  where
    asmLbl :: CLabel
asmLbl = BlockId -> CLabel
blockLbl BlockId
blockid
    platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config
    maybe_infotable :: doc -> doc
maybe_infotable doc
c = case forall (map :: * -> *) a.
IsMap map =>
KeyOf map -> map a -> Maybe a
mapLookup BlockId
blockid LabelMap RawCmmStatics
info_env of
       Maybe RawCmmStatics
Nothing -> doc
c
       Just (CmmStaticsRaw CLabel
infoLbl [CmmStatic]
info) ->
           forall doc. IsDoc doc => Platform -> SectionType -> doc
pprAlignForSection Platform
platform SectionType
Text forall doc. IsDoc doc => doc -> doc -> doc
$$
           doc
infoTableLoc forall doc. IsDoc doc => doc -> doc -> doc
$$
           forall doc. IsDoc doc => [doc] -> doc
vcat (forall a b. (a -> b) -> [a] -> [b]
map (forall doc. IsDoc doc => NCGConfig -> CmmStatic -> doc
pprData NCGConfig
config) [CmmStatic]
info) forall doc. IsDoc doc => doc -> doc -> doc
$$
           forall doc. IsDoc doc => Platform -> CLabel -> doc
pprLabel Platform
platform CLabel
infoLbl forall doc. IsDoc doc => doc -> doc -> doc
$$
           doc
c forall doc. IsDoc doc => doc -> doc -> doc
$$
           forall doc. IsOutput doc => Bool -> doc -> doc
ppWhen (NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config) (forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkAsmTempEndLabel CLabel
infoLbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon))

    -- Make sure the info table has the right .loc for the block
    -- coming right after it. See Note [Info Offset]
    infoTableLoc :: doc
infoTableLoc = case [Instr]
instrs of
      (l :: Instr
l@LOCATION{} : [Instr]
_) -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
l
      [Instr]
_other             -> forall doc. IsOutput doc => doc
empty


pprDatas :: IsDoc doc => NCGConfig -> (Alignment, RawCmmStatics) -> doc
-- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
pprDatas :: forall doc.
IsDoc doc =>
NCGConfig -> (Alignment, RawCmmStatics) -> doc
pprDatas NCGConfig
config (Alignment
_, CmmStaticsRaw CLabel
alias [CmmStaticLit (CmmLabel CLabel
lbl), CmmStaticLit CmmLit
ind, CmmStatic
_, CmmStatic
_])
  | CLabel
lbl forall a. Eq a => a -> a -> Bool
== CLabel
mkIndStaticInfoLabel
  , let labelInd :: CmmLit -> Maybe CLabel
labelInd (CmmLabelOff CLabel
l Int
_) = forall a. a -> Maybe a
Just CLabel
l
        labelInd (CmmLabel CLabel
l) = forall a. a -> Maybe a
Just CLabel
l
        labelInd CmmLit
_ = forall a. Maybe a
Nothing
  , Just CLabel
ind' <- CmmLit -> Maybe CLabel
labelInd CmmLit
ind
  , CLabel
alias CLabel -> CLabel -> Bool
`mayRedirectTo` CLabel
ind'
  = forall doc. IsDoc doc => Platform -> CLabel -> doc
pprGloblDecl (NCGConfig -> Platform
ncgPlatform NCGConfig
config) CLabel
alias
    forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
".equiv" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel (NCGConfig -> Platform
ncgPlatform NCGConfig
config) CLabel
alias forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel (NCGConfig -> Platform
ncgPlatform NCGConfig
config) CLabel
ind')

pprDatas NCGConfig
config (Alignment
align, (CmmStaticsRaw CLabel
lbl [CmmStatic]
dats))
 = forall doc. IsDoc doc => [doc] -> doc
vcat (forall doc. IsDoc doc => Platform -> Alignment -> doc
pprAlign Platform
platform Alignment
align forall a. a -> [a] -> [a]
: forall doc. IsDoc doc => Platform -> CLabel -> doc
pprLabel Platform
platform CLabel
lbl forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map (forall doc. IsDoc doc => NCGConfig -> CmmStatic -> doc
pprData NCGConfig
config) [CmmStatic]
dats)
   where
      platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config

pprData :: IsDoc doc => NCGConfig -> CmmStatic -> doc
pprData :: forall doc. IsDoc doc => NCGConfig -> CmmStatic -> doc
pprData NCGConfig
_config (CmmString ByteString
str) = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => ByteString -> doc
pprString ByteString
str)
pprData NCGConfig
_config (CmmFileEmbed String
path Int
_) = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
pprFileEmbed String
path)

pprData NCGConfig
config (CmmUninitialised Int
bytes)
 = forall doc. IsDoc doc => Line doc -> doc
line
 forall a b. (a -> b) -> a -> b
$ let platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config
   in if Platform -> OS
platformOS Platform
platform forall a. Eq a => a -> a -> Bool
== OS
OSDarwin
         then forall doc. IsLine doc => String -> doc
text String
".space " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
bytes
         else forall doc. IsLine doc => String -> doc
text String
".skip "  forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
bytes

pprData NCGConfig
config (CmmStaticLit CmmLit
lit) = forall doc. IsDoc doc => NCGConfig -> CmmLit -> doc
pprDataItem NCGConfig
config CmmLit
lit

pprGloblDecl :: IsDoc doc => Platform -> CLabel -> doc
pprGloblDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
pprGloblDecl Platform
platform CLabel
lbl
  | Bool -> Bool
not (CLabel -> Bool
externallyVisibleCLabel CLabel
lbl) = forall doc. IsOutput doc => doc
empty
  | Bool
otherwise = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
".globl " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)

pprLabelType' :: IsLine doc => Platform -> CLabel -> doc
pprLabelType' :: forall doc. IsLine doc => Platform -> CLabel -> doc
pprLabelType' Platform
platform CLabel
lbl =
  if CLabel -> Bool
isCFunctionLabel CLabel
lbl Bool -> Bool -> Bool
|| Bool
functionOkInfoTable then
    forall doc. IsLine doc => String -> doc
text String
"@function"
  else
    forall doc. IsLine doc => String -> doc
text String
"@object"
  where
    {-
    NOTE: This is a bit hacky.

    With the `tablesNextToCode` info tables look like this:
    ```
      <info table data>
    label_info:
      <info table code>
    ```
    So actually info table label points exactly to the code and we can mark
    the label as @function. (This is required to make perf and potentially other
    tools to work on Haskell binaries).
    This usually works well but it can cause issues with a linker.
    A linker uses different algorithms for the relocation depending on
    the symbol type.For some reason, a linker will generate JUMP_SLOT relocation
    when constructor info table is referenced from a data section.
    This only happens with static constructor call so
    we mark _con_info symbols as `@object` to avoid the issue with relocations.

    @SimonMarlow hack explanation:
    "The reasoning goes like this:

    * The danger when we mark a symbol as `@function` is that the linker will
      redirect it to point to the PLT and use a `JUMP_SLOT` relocation when
      the symbol refers to something outside the current shared object.
      A PLT / JUMP_SLOT reference only works for symbols that we jump to, not
      for symbols representing data,, nor for info table symbol references which
      we expect to point directly to the info table.
    * GHC generates code that might refer to any info table symbol from the text
      segment, but that's OK, because those will be explicit GOT references
      generated by the code generator.
    * When we refer to info tables from the data segment, it's either
      * a FUN_STATIC/THUNK_STATIC local to this module
      * a `con_info` that could be from anywhere

    So, the only info table symbols that we might refer to from the data segment
    of another shared object are `con_info` symbols, so those are the ones we
    need to exclude from getting the @function treatment.
    "

    A good place to check for more
    https://gitlab.haskell.org/ghc/ghc/wikis/commentary/position-independent-code

    Another possible hack is to create an extra local function symbol for
    every code-like thing to give the needed information for to the tools
    but mess up with the relocation. https://phabricator.haskell.org/D4730
    -}
    functionOkInfoTable :: Bool
functionOkInfoTable = Platform -> Bool
platformTablesNextToCode Platform
platform Bool -> Bool -> Bool
&&
      CLabel -> Bool
isInfoTableLabel CLabel
lbl Bool -> Bool -> Bool
&& Bool -> Bool
not (CLabel -> Bool
isCmmInfoTableLabel CLabel
lbl) Bool -> Bool -> Bool
&& Bool -> Bool
not (CLabel -> Bool
isConInfoTableLabel CLabel
lbl)


pprTypeDecl :: IsDoc doc => Platform -> CLabel -> doc
pprTypeDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
pprTypeDecl Platform
platform CLabel
lbl
    = if OS -> Bool
osElfTarget (Platform -> OS
platformOS Platform
platform) Bool -> Bool -> Bool
&& CLabel -> Bool
externallyVisibleCLabel CLabel
lbl
      then forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
".type " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => String -> doc
text String
", " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprLabelType' Platform
platform CLabel
lbl)
      else forall doc. IsOutput doc => doc
empty

pprLabel :: IsDoc doc => Platform -> CLabel -> doc
pprLabel :: forall doc. IsDoc doc => Platform -> CLabel -> doc
pprLabel Platform
platform CLabel
lbl =
   forall doc. IsDoc doc => Platform -> CLabel -> doc
pprGloblDecl Platform
platform CLabel
lbl
   forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Platform -> CLabel -> doc
pprTypeDecl Platform
platform CLabel
lbl
   forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon)

pprAlign :: IsDoc doc => Platform -> Alignment -> doc
pprAlign :: forall doc. IsDoc doc => Platform -> Alignment -> doc
pprAlign Platform
platform Alignment
alignment
        = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
".align " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int (Platform -> Int
alignmentOn Platform
platform)
  where
        bytes :: Int
bytes = Alignment -> Int
alignmentBytes Alignment
alignment
        alignmentOn :: Platform -> Int
alignmentOn Platform
platform = if Platform -> OS
platformOS Platform
platform forall a. Eq a => a -> a -> Bool
== OS
OSDarwin
                               then Int -> Int
log2 Int
bytes
                               else      Int
bytes

        log2 :: Int -> Int  -- cache the common ones
        log2 :: Int -> Int
log2 Int
1 = Int
0
        log2 Int
2 = Int
1
        log2 Int
4 = Int
2
        log2 Int
8 = Int
3
        log2 Int
n = Int
1 forall a. Num a => a -> a -> a
+ Int -> Int
log2 (Int
n forall a. Integral a => a -> a -> a
`quot` Int
2)

pprReg :: forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg :: forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
f Reg
r
  = case Reg
r of
      RegReal    (RealRegSingle Int
i) ->
          if Platform -> Bool
target32Bit Platform
platform then Format -> Int -> doc
ppr32_reg_no Format
f Int
i
                                  else Format -> Int -> doc
ppr64_reg_no Format
f Int
i
      RegVirtual (VirtualRegI  Unique
u)  -> forall doc. IsLine doc => String -> doc
text String
"%vI_"   forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Unique -> doc
pprUniqueAlways Unique
u
      RegVirtual (VirtualRegHi Unique
u)  -> forall doc. IsLine doc => String -> doc
text String
"%vHi_"  forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Unique -> doc
pprUniqueAlways Unique
u
      RegVirtual (VirtualRegF  Unique
u)  -> forall doc. IsLine doc => String -> doc
text String
"%vF_"   forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Unique -> doc
pprUniqueAlways Unique
u
      RegVirtual (VirtualRegD  Unique
u)  -> forall doc. IsLine doc => String -> doc
text String
"%vD_"   forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Unique -> doc
pprUniqueAlways Unique
u

  where
    ppr32_reg_no :: Format -> Int -> doc
    ppr32_reg_no :: Format -> Int -> doc
ppr32_reg_no Format
II8   = forall doc. IsLine doc => Int -> doc
ppr32_reg_byte
    ppr32_reg_no Format
II16  = forall {a} {doc}. (Eq a, Num a, IsLine doc) => a -> doc
ppr32_reg_word
    ppr32_reg_no Format
_     = forall doc. IsLine doc => Int -> doc
ppr32_reg_long

    ppr32_reg_byte :: Int -> doc
ppr32_reg_byte Int
i =
      case Int
i of {
         Int
0 -> forall doc. IsLine doc => String -> doc
text String
"%al";     Int
1 -> forall doc. IsLine doc => String -> doc
text String
"%bl";
         Int
2 -> forall doc. IsLine doc => String -> doc
text String
"%cl";     Int
3 -> forall doc. IsLine doc => String -> doc
text String
"%dl";
        Int
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty I386 byte register: " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
i
      }

    ppr32_reg_word :: a -> doc
ppr32_reg_word a
i =
      case a
i of {
         a
0 -> forall doc. IsLine doc => String -> doc
text String
"%ax";     a
1 -> forall doc. IsLine doc => String -> doc
text String
"%bx";
         a
2 -> forall doc. IsLine doc => String -> doc
text String
"%cx";     a
3 -> forall doc. IsLine doc => String -> doc
text String
"%dx";
         a
4 -> forall doc. IsLine doc => String -> doc
text String
"%si";     a
5 -> forall doc. IsLine doc => String -> doc
text String
"%di";
         a
6 -> forall doc. IsLine doc => String -> doc
text String
"%bp";     a
7 -> forall doc. IsLine doc => String -> doc
text String
"%sp";
        a
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty I386 word register"
      }

    ppr32_reg_long :: Int -> doc
ppr32_reg_long Int
i =
      case Int
i of {
         Int
0 -> forall doc. IsLine doc => String -> doc
text String
"%eax";    Int
1 -> forall doc. IsLine doc => String -> doc
text String
"%ebx";
         Int
2 -> forall doc. IsLine doc => String -> doc
text String
"%ecx";    Int
3 -> forall doc. IsLine doc => String -> doc
text String
"%edx";
         Int
4 -> forall doc. IsLine doc => String -> doc
text String
"%esi";    Int
5 -> forall doc. IsLine doc => String -> doc
text String
"%edi";
         Int
6 -> forall doc. IsLine doc => String -> doc
text String
"%ebp";    Int
7 -> forall doc. IsLine doc => String -> doc
text String
"%esp";
         Int
_  -> forall doc. IsLine doc => Int -> doc
ppr_reg_float Int
i
      }

    ppr64_reg_no :: Format -> Int -> doc
    ppr64_reg_no :: Format -> Int -> doc
ppr64_reg_no Format
II8   = forall doc. IsLine doc => Int -> doc
ppr64_reg_byte
    ppr64_reg_no Format
II16  = forall {a} {doc}. (Eq a, Num a, IsLine doc) => a -> doc
ppr64_reg_word
    ppr64_reg_no Format
II32  = forall {a} {doc}. (Eq a, Num a, IsLine doc) => a -> doc
ppr64_reg_long
    ppr64_reg_no Format
_     = forall doc. IsLine doc => Int -> doc
ppr64_reg_quad

    ppr64_reg_byte :: Int -> doc
ppr64_reg_byte Int
i =
      case Int
i of {
         Int
0 -> forall doc. IsLine doc => String -> doc
text String
"%al";      Int
1 -> forall doc. IsLine doc => String -> doc
text String
"%bl";
         Int
2 -> forall doc. IsLine doc => String -> doc
text String
"%cl";      Int
3 -> forall doc. IsLine doc => String -> doc
text String
"%dl";
         Int
4 -> forall doc. IsLine doc => String -> doc
text String
"%sil";     Int
5 -> forall doc. IsLine doc => String -> doc
text String
"%dil"; -- new 8-bit regs!
         Int
6 -> forall doc. IsLine doc => String -> doc
text String
"%bpl";     Int
7 -> forall doc. IsLine doc => String -> doc
text String
"%spl";
         Int
8 -> forall doc. IsLine doc => String -> doc
text String
"%r8b";     Int
9 -> forall doc. IsLine doc => String -> doc
text String
"%r9b";
        Int
10 -> forall doc. IsLine doc => String -> doc
text String
"%r10b";   Int
11 -> forall doc. IsLine doc => String -> doc
text String
"%r11b";
        Int
12 -> forall doc. IsLine doc => String -> doc
text String
"%r12b";   Int
13 -> forall doc. IsLine doc => String -> doc
text String
"%r13b";
        Int
14 -> forall doc. IsLine doc => String -> doc
text String
"%r14b";   Int
15 -> forall doc. IsLine doc => String -> doc
text String
"%r15b";
        Int
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty x86_64 byte register: " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
i
      }

    ppr64_reg_word :: a -> doc
ppr64_reg_word a
i =
      case a
i of {
         a
0 -> forall doc. IsLine doc => String -> doc
text String
"%ax";      a
1 -> forall doc. IsLine doc => String -> doc
text String
"%bx";
         a
2 -> forall doc. IsLine doc => String -> doc
text String
"%cx";      a
3 -> forall doc. IsLine doc => String -> doc
text String
"%dx";
         a
4 -> forall doc. IsLine doc => String -> doc
text String
"%si";      a
5 -> forall doc. IsLine doc => String -> doc
text String
"%di";
         a
6 -> forall doc. IsLine doc => String -> doc
text String
"%bp";      a
7 -> forall doc. IsLine doc => String -> doc
text String
"%sp";
         a
8 -> forall doc. IsLine doc => String -> doc
text String
"%r8w";     a
9 -> forall doc. IsLine doc => String -> doc
text String
"%r9w";
        a
10 -> forall doc. IsLine doc => String -> doc
text String
"%r10w";   a
11 -> forall doc. IsLine doc => String -> doc
text String
"%r11w";
        a
12 -> forall doc. IsLine doc => String -> doc
text String
"%r12w";   a
13 -> forall doc. IsLine doc => String -> doc
text String
"%r13w";
        a
14 -> forall doc. IsLine doc => String -> doc
text String
"%r14w";   a
15 -> forall doc. IsLine doc => String -> doc
text String
"%r15w";
        a
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty x86_64 word register"
      }

    ppr64_reg_long :: a -> doc
ppr64_reg_long a
i =
      case a
i of {
         a
0 -> forall doc. IsLine doc => String -> doc
text String
"%eax";    a
1  -> forall doc. IsLine doc => String -> doc
text String
"%ebx";
         a
2 -> forall doc. IsLine doc => String -> doc
text String
"%ecx";    a
3  -> forall doc. IsLine doc => String -> doc
text String
"%edx";
         a
4 -> forall doc. IsLine doc => String -> doc
text String
"%esi";    a
5  -> forall doc. IsLine doc => String -> doc
text String
"%edi";
         a
6 -> forall doc. IsLine doc => String -> doc
text String
"%ebp";    a
7  -> forall doc. IsLine doc => String -> doc
text String
"%esp";
         a
8 -> forall doc. IsLine doc => String -> doc
text String
"%r8d";    a
9  -> forall doc. IsLine doc => String -> doc
text String
"%r9d";
        a
10 -> forall doc. IsLine doc => String -> doc
text String
"%r10d";   a
11 -> forall doc. IsLine doc => String -> doc
text String
"%r11d";
        a
12 -> forall doc. IsLine doc => String -> doc
text String
"%r12d";   a
13 -> forall doc. IsLine doc => String -> doc
text String
"%r13d";
        a
14 -> forall doc. IsLine doc => String -> doc
text String
"%r14d";   a
15 -> forall doc. IsLine doc => String -> doc
text String
"%r15d";
        a
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty x86_64 register"
      }

    ppr64_reg_quad :: Int -> doc
ppr64_reg_quad Int
i =
      case Int
i of {
         Int
0 -> forall doc. IsLine doc => String -> doc
text String
"%rax";     Int
1 -> forall doc. IsLine doc => String -> doc
text String
"%rbx";
         Int
2 -> forall doc. IsLine doc => String -> doc
text String
"%rcx";     Int
3 -> forall doc. IsLine doc => String -> doc
text String
"%rdx";
         Int
4 -> forall doc. IsLine doc => String -> doc
text String
"%rsi";     Int
5 -> forall doc. IsLine doc => String -> doc
text String
"%rdi";
         Int
6 -> forall doc. IsLine doc => String -> doc
text String
"%rbp";     Int
7 -> forall doc. IsLine doc => String -> doc
text String
"%rsp";
         Int
8 -> forall doc. IsLine doc => String -> doc
text String
"%r8";      Int
9 -> forall doc. IsLine doc => String -> doc
text String
"%r9";
        Int
10 -> forall doc. IsLine doc => String -> doc
text String
"%r10";    Int
11 -> forall doc. IsLine doc => String -> doc
text String
"%r11";
        Int
12 -> forall doc. IsLine doc => String -> doc
text String
"%r12";    Int
13 -> forall doc. IsLine doc => String -> doc
text String
"%r13";
        Int
14 -> forall doc. IsLine doc => String -> doc
text String
"%r14";    Int
15 -> forall doc. IsLine doc => String -> doc
text String
"%r15";
        Int
_  -> forall doc. IsLine doc => Int -> doc
ppr_reg_float Int
i
      }

ppr_reg_float :: IsLine doc => Int -> doc
ppr_reg_float :: forall doc. IsLine doc => Int -> doc
ppr_reg_float Int
i = case Int
i of
        Int
16 -> forall doc. IsLine doc => String -> doc
text String
"%xmm0" ;   Int
17 -> forall doc. IsLine doc => String -> doc
text String
"%xmm1"
        Int
18 -> forall doc. IsLine doc => String -> doc
text String
"%xmm2" ;   Int
19 -> forall doc. IsLine doc => String -> doc
text String
"%xmm3"
        Int
20 -> forall doc. IsLine doc => String -> doc
text String
"%xmm4" ;   Int
21 -> forall doc. IsLine doc => String -> doc
text String
"%xmm5"
        Int
22 -> forall doc. IsLine doc => String -> doc
text String
"%xmm6" ;   Int
23 -> forall doc. IsLine doc => String -> doc
text String
"%xmm7"
        Int
24 -> forall doc. IsLine doc => String -> doc
text String
"%xmm8" ;   Int
25 -> forall doc. IsLine doc => String -> doc
text String
"%xmm9"
        Int
26 -> forall doc. IsLine doc => String -> doc
text String
"%xmm10";   Int
27 -> forall doc. IsLine doc => String -> doc
text String
"%xmm11"
        Int
28 -> forall doc. IsLine doc => String -> doc
text String
"%xmm12";   Int
29 -> forall doc. IsLine doc => String -> doc
text String
"%xmm13"
        Int
30 -> forall doc. IsLine doc => String -> doc
text String
"%xmm14";   Int
31 -> forall doc. IsLine doc => String -> doc
text String
"%xmm15"
        Int
_  -> forall doc. IsLine doc => String -> doc
text String
"very naughty x86 register"

pprFormat :: IsLine doc => Format -> doc
pprFormat :: forall doc. IsLine doc => Format -> doc
pprFormat Format
x = case Format
x of
  Format
II8   -> forall doc. IsLine doc => String -> doc
text String
"b"
  Format
II16  -> forall doc. IsLine doc => String -> doc
text String
"w"
  Format
II32  -> forall doc. IsLine doc => String -> doc
text String
"l"
  Format
II64  -> forall doc. IsLine doc => String -> doc
text String
"q"
  Format
FF32  -> forall doc. IsLine doc => String -> doc
text String
"ss"      -- "scalar single-precision float" (SSE2)
  Format
FF64  -> forall doc. IsLine doc => String -> doc
text String
"sd"      -- "scalar double-precision float" (SSE2)

pprFormat_x87 :: IsLine doc => Format -> doc
pprFormat_x87 :: forall doc. IsLine doc => Format -> doc
pprFormat_x87 Format
x = case Format
x of
  Format
FF32  -> forall doc. IsLine doc => String -> doc
text String
"s"
  Format
FF64  -> forall doc. IsLine doc => String -> doc
text String
"l"
  Format
_     -> forall a. HasCallStack => String -> a
panic String
"X86.Ppr.pprFormat_x87"


pprCond :: IsLine doc => Cond -> doc
pprCond :: forall doc. IsLine doc => Cond -> doc
pprCond Cond
c = case Cond
c of {
  Cond
GEU     -> forall doc. IsLine doc => String -> doc
text String
"ae";   Cond
LU   -> forall doc. IsLine doc => String -> doc
text String
"b";
  Cond
EQQ     -> forall doc. IsLine doc => String -> doc
text String
"e";    Cond
GTT  -> forall doc. IsLine doc => String -> doc
text String
"g";
  Cond
GE      -> forall doc. IsLine doc => String -> doc
text String
"ge";   Cond
GU   -> forall doc. IsLine doc => String -> doc
text String
"a";
  Cond
LTT     -> forall doc. IsLine doc => String -> doc
text String
"l";    Cond
LE   -> forall doc. IsLine doc => String -> doc
text String
"le";
  Cond
LEU     -> forall doc. IsLine doc => String -> doc
text String
"be";   Cond
NE   -> forall doc. IsLine doc => String -> doc
text String
"ne";
  Cond
NEG     -> forall doc. IsLine doc => String -> doc
text String
"s";    Cond
POS  -> forall doc. IsLine doc => String -> doc
text String
"ns";
  Cond
CARRY   -> forall doc. IsLine doc => String -> doc
text String
"c";   Cond
OFLO  -> forall doc. IsLine doc => String -> doc
text String
"o";
  Cond
PARITY  -> forall doc. IsLine doc => String -> doc
text String
"p";   Cond
NOTPARITY -> forall doc. IsLine doc => String -> doc
text String
"np";
  Cond
ALWAYS  -> forall doc. IsLine doc => String -> doc
text String
"mp"}


pprImm :: IsLine doc => Platform -> Imm -> doc
pprImm :: forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform = \case
   ImmInt Int
i            -> forall doc. IsLine doc => Int -> doc
int Int
i
   ImmInteger Integer
i        -> forall doc. IsLine doc => Integer -> doc
integer Integer
i
   ImmCLbl CLabel
l           -> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
l
   ImmIndex CLabel
l Int
i        -> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
l forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'+' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
i
   ImmLit FastString
s            -> forall doc. IsLine doc => FastString -> doc
ftext FastString
s
   ImmFloat Rational
f          -> forall doc. IsLine doc => Float -> doc
float forall a b. (a -> b) -> a -> b
$ forall a. Fractional a => Rational -> a
fromRational Rational
f
   ImmDouble Rational
d         -> forall doc. IsLine doc => Double -> doc
double forall a b. (a -> b) -> a -> b
$ forall a. Fractional a => Rational -> a
fromRational Rational
d
   ImmConstantSum Imm
a Imm
b  -> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
a forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'+' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
b
   ImmConstantDiff Imm
a Imm
b -> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
a forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'-' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
lparen forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
b forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
rparen



pprAddr :: IsLine doc => Platform -> AddrMode -> doc
pprAddr :: forall doc. IsLine doc => Platform -> AddrMode -> doc
pprAddr Platform
platform (ImmAddr Imm
imm Int
off)
  = let pp_imm :: doc
pp_imm = forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm
    in
    if (Int
off forall a. Eq a => a -> a -> Bool
== Int
0) then
        doc
pp_imm
    else if (Int
off forall a. Ord a => a -> a -> Bool
< Int
0) then
        doc
pp_imm forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
off
    else
        doc
pp_imm forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'+' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
off

pprAddr Platform
platform (AddrBaseIndex EABase
base EAIndex
index Imm
displacement)
  = let
        pp_disp :: doc
pp_disp  = Imm -> doc
ppr_disp Imm
displacement
        pp_off :: doc -> doc
pp_off doc
p = doc
pp_disp forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
'(' forall doc. IsLine doc => doc -> doc -> doc
<> doc
p forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
')'
        pp_reg :: Reg -> doc
pp_reg Reg
r = forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Reg
r
    in
    case (EABase
base, EAIndex
index) of
      (EABase
EABaseNone,  EAIndex
EAIndexNone) -> doc
pp_disp
      (EABaseReg Reg
b, EAIndex
EAIndexNone) -> doc -> doc
pp_off (Reg -> doc
pp_reg Reg
b)
      (EABase
EABaseRip,   EAIndex
EAIndexNone) -> doc -> doc
pp_off (forall doc. IsLine doc => String -> doc
text String
"%rip")
      (EABase
EABaseNone,  EAIndex Reg
r Int
i) -> doc -> doc
pp_off (forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<> Reg -> doc
pp_reg Reg
r forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
i)
      (EABaseReg Reg
b, EAIndex Reg
r Int
i) -> doc -> doc
pp_off (Reg -> doc
pp_reg Reg
b forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<> Reg -> doc
pp_reg Reg
r
                                       forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
i)
      (EABase, EAIndex)
_                         -> forall a. HasCallStack => String -> a
panic String
"X86.Ppr.pprAddr: no match"

  where
    ppr_disp :: Imm -> doc
ppr_disp (ImmInt Int
0) = forall doc. IsOutput doc => doc
empty
    ppr_disp Imm
imm        = forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm

-- | Print section header and appropriate alignment for that section.
pprSectionAlign :: IsDoc doc => NCGConfig -> Section -> doc
pprSectionAlign :: forall doc. IsDoc doc => NCGConfig -> Section -> doc
pprSectionAlign NCGConfig
_config (Section (OtherSection String
_) CLabel
_) =
     forall a. HasCallStack => String -> a
panic String
"X86.Ppr.pprSectionAlign: unknown section"
pprSectionAlign NCGConfig
config sec :: Section
sec@(Section SectionType
seg CLabel
_) =
    forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => NCGConfig -> Section -> doc
pprSectionHeader NCGConfig
config Section
sec) forall doc. IsDoc doc => doc -> doc -> doc
$$
    forall doc. IsDoc doc => Platform -> SectionType -> doc
pprAlignForSection (NCGConfig -> Platform
ncgPlatform NCGConfig
config) SectionType
seg

-- | Print appropriate alignment for the given section type.
pprAlignForSection :: IsDoc doc => Platform -> SectionType -> doc
pprAlignForSection :: forall doc. IsDoc doc => Platform -> SectionType -> doc
pprAlignForSection Platform
platform SectionType
seg = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$
    forall doc. IsLine doc => String -> doc
text String
".align " forall doc. IsLine doc => doc -> doc -> doc
<>
    case Platform -> OS
platformOS Platform
platform of
      -- Darwin: alignments are given as shifts.
      OS
OSDarwin
       | Platform -> Bool
target32Bit Platform
platform ->
          case SectionType
seg of
           SectionType
CString           -> forall doc. IsLine doc => Int -> doc
int Int
1
           SectionType
_                 -> forall doc. IsLine doc => Int -> doc
int Int
2
       | Bool
otherwise ->
          case SectionType
seg of
           SectionType
CString           -> forall doc. IsLine doc => Int -> doc
int Int
1
           SectionType
_                 -> forall doc. IsLine doc => Int -> doc
int Int
3
      -- Other: alignments are given as bytes.
      OS
_
       | Platform -> Bool
target32Bit Platform
platform ->
          case SectionType
seg of
           SectionType
Text              -> forall doc. IsLine doc => String -> doc
text String
"4,0x90"
           SectionType
CString           -> forall doc. IsLine doc => Int -> doc
int Int
1
           SectionType
_                 -> forall doc. IsLine doc => Int -> doc
int Int
4
       | Bool
otherwise ->
          case SectionType
seg of
           SectionType
CString           -> forall doc. IsLine doc => Int -> doc
int Int
1
           SectionType
_                 -> forall doc. IsLine doc => Int -> doc
int Int
8

pprDataItem :: IsDoc doc => NCGConfig -> CmmLit -> doc
pprDataItem :: forall doc. IsDoc doc => NCGConfig -> CmmLit -> doc
pprDataItem NCGConfig
config CmmLit
lit
  = forall doc. IsDoc doc => [Line doc] -> doc
lines_ (Format -> CmmLit -> [Line doc]
ppr_item (CmmType -> Format
cmmTypeFormat forall a b. (a -> b) -> a -> b
$ Platform -> CmmLit -> CmmType
cmmLitType Platform
platform CmmLit
lit) CmmLit
lit)
    where
        platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config
        imm :: Imm
imm = CmmLit -> Imm
litToImm CmmLit
lit

        -- These seem to be common:
        ppr_item :: Format -> CmmLit -> [Line doc]
ppr_item Format
II8   CmmLit
_ = [forall doc. IsLine doc => String -> doc
text String
"\t.byte\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]
        ppr_item Format
II16  CmmLit
_ = [forall doc. IsLine doc => String -> doc
text String
"\t.word\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]
        ppr_item Format
II32  CmmLit
_ = [forall doc. IsLine doc => String -> doc
text String
"\t.long\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]

        ppr_item Format
FF32 CmmLit
_ = [forall doc. IsLine doc => String -> doc
text String
"\t.float\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]
        ppr_item Format
FF64 CmmLit
_ = [forall doc. IsLine doc => String -> doc
text String
"\t.double\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]

        ppr_item Format
II64 CmmLit
_
            = case Platform -> OS
platformOS Platform
platform of
              OS
OSDarwin
               | Platform -> Bool
target32Bit Platform
platform ->
                  case CmmLit
lit of
                  CmmInt Integer
x Width
_ ->
                      [forall doc. IsLine doc => String -> doc
text String
"\t.long\t"
                          forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
x :: Word32)),
                       forall doc. IsLine doc => String -> doc
text String
"\t.long\t"
                          forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral
                              (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
x forall a. Bits a => a -> Int -> a
`shiftR` Int
32) :: Word32))]
                  CmmLit
_ -> forall a. HasCallStack => String -> a
panic String
"X86.Ppr.ppr_item: no match for II64"
              OS
_ -> [forall doc. IsLine doc => String -> doc
text String
"\t.quad\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm]


asmComment :: IsLine doc => doc -> doc
asmComment :: forall doc. IsLine doc => doc -> doc
asmComment doc
c = forall doc. IsOutput doc => doc -> doc
whenPprDebug forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"# " forall doc. IsLine doc => doc -> doc -> doc
<> doc
c

pprInstr :: forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr :: forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
i = case Instr
i of
   COMMENT FastString
s
      -> forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => doc -> doc
asmComment (forall doc. IsLine doc => FastString -> doc
ftext FastString
s))

   LOCATION Int
file Int
line' Int
col String
_name
      -> forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
"\t.loc " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Int -> doc
int Int
file forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Int -> doc
int Int
line' forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Int -> doc
int Int
col)

   DELTA Int
d
      -> forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => doc -> doc
asmComment forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text (String
"\tdelta = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Int
d))

   NEWBLOCK BlockId
_
      -> forall a. HasCallStack => String -> a
panic String
"pprInstr: NEWBLOCK"

   UNWIND CLabel
lbl UnwindTable
d
      -> forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => doc -> doc
asmComment (forall doc. IsLine doc => String -> doc
text String
"\tunwind = " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> UnwindTable -> doc
pprUnwindTable Platform
platform UnwindTable
d))
         forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon)

   LDATA Section
_ (Alignment, RawCmmStatics)
_
      -> forall a. HasCallStack => String -> a
panic String
"pprInstr: LDATA"

{-
   SPILL reg slot
      -> hcat [
           text "\tSPILL",
           char ' ',
           pprUserReg reg,
           comma,
           text "SLOT" <> parens (int slot)]

   RELOAD slot reg
      -> hcat [
        text "\tRELOAD",
        char ' ',
        text "SLOT" <> parens (int slot),
        comma,
        pprUserReg reg]
-}

   -- Replace 'mov $0x0,%reg' by 'xor %reg,%reg', which is smaller and cheaper.
   -- The code generator catches most of these already, but not all.
   MOV Format
format (OpImm (ImmInt Int
0)) dst :: Operand
dst@(OpReg Reg
_)
     -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform (Format -> Operand -> Operand -> Instr
XOR Format
format' Operand
dst Operand
dst)
        where format' :: Format
format' = case Format
format of
                Format
II64 -> Format
II32          -- 32-bit version is equivalent, and smaller
                Format
_    -> Format
format

   MOV Format
format Operand
src Operand
dst
     -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"mov") Format
format Operand
src Operand
dst

   CMOV Cond
cc Format
format Operand
src Reg
dst
     -> Line doc -> Format -> Cond -> Operand -> Reg -> doc
pprCondOpReg (forall doc. IsLine doc => String -> doc
text String
"cmov") Format
format Cond
cc Operand
src Reg
dst

   MOVZxL Format
II32 Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"mov") Format
II32 Operand
src Operand
dst
        -- 32-to-64 bit zero extension on x86_64 is accomplished by a simple
        -- movl.  But we represent it as a MOVZxL instruction, because
        -- the reg alloc would tend to throw away a plain reg-to-reg
        -- move, and we still want it to do that.

   MOVZxL Format
formats Operand
src Operand
dst
      -> Line doc -> Format -> Format -> Operand -> Operand -> doc
pprFormatOpOpCoerce (forall doc. IsLine doc => String -> doc
text String
"movz") Format
formats Format
II32 Operand
src Operand
dst
        -- zero-extension only needs to extend to 32 bits: on x86_64,
        -- the remaining zero-extension to 64 bits is automatic, and the 32-bit
        -- instruction is shorter.

   MOVSxL Format
formats Operand
src Operand
dst
      -> Line doc -> Format -> Format -> Operand -> Operand -> doc
pprFormatOpOpCoerce (forall doc. IsLine doc => String -> doc
text String
"movs") Format
formats (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Operand
src Operand
dst

   -- here we do some patching, since the physical registers are only set late
   -- in the code generation.
   LEA Format
format (OpAddr (AddrBaseIndex (EABaseReg Reg
reg1) (EAIndex Reg
reg2 Int
1) (ImmInt Int
0))) dst :: Operand
dst@(OpReg Reg
reg3)
      | Reg
reg1 forall a. Eq a => a -> a -> Bool
== Reg
reg3
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"add") Format
format (Reg -> Operand
OpReg Reg
reg2) Operand
dst

   LEA Format
format (OpAddr (AddrBaseIndex (EABaseReg Reg
reg1) (EAIndex Reg
reg2 Int
1) (ImmInt Int
0))) dst :: Operand
dst@(OpReg Reg
reg3)
      | Reg
reg2 forall a. Eq a => a -> a -> Bool
== Reg
reg3
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"add") Format
format (Reg -> Operand
OpReg Reg
reg1) Operand
dst

   LEA Format
format (OpAddr (AddrBaseIndex (EABaseReg Reg
reg1) EAIndex
EAIndexNone Imm
displ)) dst :: Operand
dst@(OpReg Reg
reg3)
      | Reg
reg1 forall a. Eq a => a -> a -> Bool
== Reg
reg3
      -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform (Format -> Operand -> Operand -> Instr
ADD Format
format (Imm -> Operand
OpImm Imm
displ) Operand
dst)

   LEA Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"lea") Format
format Operand
src Operand
dst

   ADD Format
format (OpImm (ImmInt (-1))) Operand
dst
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"dec") Format
format Operand
dst

   ADD Format
format (OpImm (ImmInt Int
1)) Operand
dst
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"inc") Format
format Operand
dst

   ADD Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"add") Format
format Operand
src Operand
dst

   ADC Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"adc") Format
format Operand
src Operand
dst

   SUB Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"sub") Format
format Operand
src Operand
dst

   SBB Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"sbb") Format
format Operand
src Operand
dst

   IMUL Format
format Operand
op1 Operand
op2
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"imul") Format
format Operand
op1 Operand
op2

   ADD_CC Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"add") Format
format Operand
src Operand
dst

   SUB_CC Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"sub") Format
format Operand
src Operand
dst

   -- Use a 32-bit instruction when possible as it saves a byte.
   -- Notably, extracting the tag bits of a pointer has this form.
   -- TODO: we could save a byte in a subsequent CMP instruction too,
   -- but need something like a peephole pass for this
   AND Format
II64 src :: Operand
src@(OpImm (ImmInteger Integer
mask)) Operand
dst
      | Integer
0 forall a. Ord a => a -> a -> Bool
<= Integer
mask Bool -> Bool -> Bool
&& Integer
mask forall a. Ord a => a -> a -> Bool
< Integer
0xffffffff
      -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform (Format -> Operand -> Operand -> Instr
AND Format
II32 Operand
src Operand
dst)

   AND Format
FF32 Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"andps") Format
FF32 Operand
src Operand
dst

   AND Format
FF64 Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"andpd") Format
FF64 Operand
src Operand
dst

   AND Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"and") Format
format Operand
src Operand
dst

   OR  Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"or")  Format
format Operand
src Operand
dst

   XOR Format
FF32 Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"xorps") Format
FF32 Operand
src Operand
dst

   XOR Format
FF64 Operand
src Operand
dst
      ->  Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"xorpd") Format
FF64 Operand
src Operand
dst

   XOR Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"xor") Format
format Operand
src Operand
dst

   POPCNT Format
format Operand
src Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"popcnt") Format
format Operand
src (Reg -> Operand
OpReg Reg
dst)

   LZCNT Format
format Operand
src Reg
dst
      ->  Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"lzcnt") Format
format Operand
src (Reg -> Operand
OpReg Reg
dst)

   TZCNT Format
format Operand
src Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"tzcnt") Format
format Operand
src (Reg -> Operand
OpReg Reg
dst)

   BSF Format
format Operand
src Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"bsf") Format
format Operand
src (Reg -> Operand
OpReg Reg
dst)

   BSR Format
format Operand
src Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprOpOp (forall doc. IsLine doc => String -> doc
text String
"bsr") Format
format Operand
src (Reg -> Operand
OpReg Reg
dst)

   PDEP Format
format Operand
src Operand
mask Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> Reg -> doc
pprFormatOpOpReg (forall doc. IsLine doc => String -> doc
text String
"pdep") Format
format Operand
src Operand
mask Reg
dst

   PEXT Format
format Operand
src Operand
mask Reg
dst
      -> Line doc -> Format -> Operand -> Operand -> Reg -> doc
pprFormatOpOpReg (forall doc. IsLine doc => String -> doc
text String
"pext") Format
format Operand
src Operand
mask Reg
dst

   PREFETCH PrefetchVariant
NTA Format
format Operand
src
      -> Line doc -> Format -> Operand -> doc
pprFormatOp_ (forall doc. IsLine doc => String -> doc
text String
"prefetchnta") Format
format Operand
src

   PREFETCH PrefetchVariant
Lvl0 Format
format Operand
src
      -> Line doc -> Format -> Operand -> doc
pprFormatOp_ (forall doc. IsLine doc => String -> doc
text String
"prefetcht0") Format
format Operand
src

   PREFETCH PrefetchVariant
Lvl1 Format
format Operand
src
      -> Line doc -> Format -> Operand -> doc
pprFormatOp_ (forall doc. IsLine doc => String -> doc
text String
"prefetcht1") Format
format Operand
src

   PREFETCH PrefetchVariant
Lvl2 Format
format Operand
src
      -> Line doc -> Format -> Operand -> doc
pprFormatOp_ (forall doc. IsLine doc => String -> doc
text String
"prefetcht2") Format
format Operand
src

   NOT Format
format Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"not") Format
format Operand
op

   BSWAP Format
format Reg
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"bswap") Format
format (Reg -> Operand
OpReg Reg
op)

   NEGI Format
format Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"neg") Format
format Operand
op

   SHL Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprShift (forall doc. IsLine doc => String -> doc
text String
"shl") Format
format Operand
src Operand
dst

   SAR Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprShift (forall doc. IsLine doc => String -> doc
text String
"sar") Format
format Operand
src Operand
dst

   SHR Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprShift (forall doc. IsLine doc => String -> doc
text String
"shr") Format
format Operand
src Operand
dst

   BT Format
format Imm
imm Operand
src
      -> Line doc -> Format -> Imm -> Operand -> doc
pprFormatImmOp (forall doc. IsLine doc => String -> doc
text String
"bt") Format
format Imm
imm Operand
src

   CMP Format
format Operand
src Operand
dst
     | Format -> Bool
isFloatFormat Format
format -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"ucomi") Format
format Operand
src Operand
dst -- SSE2
     | Bool
otherwise            -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"cmp")   Format
format Operand
src Operand
dst

   TEST Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"test") Format
format' Operand
src Operand
dst
         where
        -- Match instructions like 'test $0x3,%esi' or 'test $0x7,%rbx'.
        -- We can replace them by equivalent, but smaller instructions
        -- by reducing the size of the immediate operand as far as possible.
        -- (We could handle masks larger than a single byte too,
        -- but it would complicate the code considerably
        -- and tag checks are by far the most common case.)
        -- The mask must have the high bit clear for this smaller encoding
        -- to be completely equivalent to the original; in particular so
        -- that the signed comparison condition bits are the same as they
        -- would be if doing a full word comparison. See #13425.
          format' :: Format
format' = case (Operand
src,Operand
dst) of
           (OpImm (ImmInteger Integer
mask), OpReg Reg
dstReg)
             | Integer
0 forall a. Ord a => a -> a -> Bool
<= Integer
mask Bool -> Bool -> Bool
&& Integer
mask forall a. Ord a => a -> a -> Bool
< Integer
128 -> Platform -> Reg -> Format
minSizeOfReg Platform
platform Reg
dstReg
           (Operand, Operand)
_ -> Format
format
          minSizeOfReg :: Platform -> Reg -> Format
minSizeOfReg Platform
platform (RegReal (RealRegSingle Int
i))
            | Platform -> Bool
target32Bit Platform
platform Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
<= Int
3        = Format
II8  -- al, bl, cl, dl
            | Platform -> Bool
target32Bit Platform
platform Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
<= Int
7        = Format
II16 -- si, di, bp, sp
            | Bool -> Bool
not (Platform -> Bool
target32Bit Platform
platform) Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
<= Int
15 = Format
II8  -- al .. r15b
          minSizeOfReg Platform
_ Reg
_ = Format
format                 -- other

   PUSH Format
format Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"push") Format
format Operand
op

   POP Format
format Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"pop") Format
format Operand
op

-- both unused (SDM):
-- PUSHA -> text "\tpushal"
-- POPA  -> text "\tpopal"

   Instr
NOP
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tnop"

   CLTD Format
II8
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcbtw"

   CLTD Format
II16
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcwtd"

   CLTD Format
II32
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcltd"

   CLTD Format
II64
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcqto"

   CLTD Format
x
      -> forall a. HasCallStack => String -> a
panic forall a b. (a -> b) -> a -> b
$ String
"pprInstr: CLTD " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Format
x

   SETCC Cond
cond Operand
op
      -> Line doc -> Cond -> Line doc -> doc
pprCondInstr (forall doc. IsLine doc => String -> doc
text String
"set") Cond
cond (Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
II8 Operand
op)

   XCHG Format
format Operand
src Reg
val
      -> Line doc -> Format -> Operand -> Reg -> doc
pprFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"xchg") Format
format Operand
src Reg
val

   JXX Cond
cond BlockId
blockid
      -> Line doc -> Cond -> Line doc -> doc
pprCondInstr (forall doc. IsLine doc => String -> doc
text String
"j") Cond
cond (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lab)
         where lab :: CLabel
lab = BlockId -> CLabel
blockLbl BlockId
blockid

   JXX_GBL Cond
cond Imm
imm
      -> Line doc -> Cond -> Line doc -> doc
pprCondInstr (forall doc. IsLine doc => String -> doc
text String
"j") Cond
cond (forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm)

   JMP (OpImm Imm
imm) [Reg]
_
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tjmp " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm

   JMP Operand
op [Reg]
_
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tjmp *" forall doc. IsLine doc => doc -> doc -> doc
<> Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Operand
op

   JMP_TBL Operand
op [Maybe JumpDest]
_ Section
_ CLabel
_
      -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform (Operand -> [Reg] -> Instr
JMP Operand
op [])

   CALL (Left Imm
imm) [Reg]
_
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcall " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm

   CALL (Right Reg
reg) [Reg]
_
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcall *" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Reg
reg

   IDIV Format
fmt Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"idiv") Format
fmt Operand
op

   DIV Format
fmt Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"div")  Format
fmt Operand
op

   IMUL2 Format
fmt Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"imul") Format
fmt Operand
op

   -- x86_64 only
   MUL Format
format Operand
op1 Operand
op2
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"mul") Format
format Operand
op1 Operand
op2

   MUL2 Format
format Operand
op
      -> Line doc -> Format -> Operand -> doc
pprFormatOp (forall doc. IsLine doc => String -> doc
text String
"mul") Format
format Operand
op

   FDIV Format
format Operand
op1 Operand
op2
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"div") Format
format Operand
op1 Operand
op2

   SQRT Format
format Operand
op1 Reg
op2
      -> Line doc -> Format -> Operand -> Reg -> doc
pprFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"sqrt") Format
format Operand
op1 Reg
op2

   CVTSS2SD Reg
from Reg
to
      -> Line doc -> Reg -> Reg -> doc
pprRegReg (forall doc. IsLine doc => String -> doc
text String
"cvtss2sd") Reg
from Reg
to

   CVTSD2SS Reg
from Reg
to
      -> Line doc -> Reg -> Reg -> doc
pprRegReg (forall doc. IsLine doc => String -> doc
text String
"cvtsd2ss") Reg
from Reg
to

   CVTTSS2SIQ Format
fmt Operand
from Reg
to
      -> Line doc -> Format -> Format -> Operand -> Reg -> doc
pprFormatFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"cvttss2si") Format
FF32 Format
fmt Operand
from Reg
to

   CVTTSD2SIQ Format
fmt Operand
from Reg
to
      -> Line doc -> Format -> Format -> Operand -> Reg -> doc
pprFormatFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"cvttsd2si") Format
FF64 Format
fmt Operand
from Reg
to

   CVTSI2SS Format
fmt Operand
from Reg
to
      -> Line doc -> Format -> Operand -> Reg -> doc
pprFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"cvtsi2ss") Format
fmt Operand
from Reg
to

   CVTSI2SD Format
fmt Operand
from Reg
to
      -> Line doc -> Format -> Operand -> Reg -> doc
pprFormatOpReg (forall doc. IsLine doc => String -> doc
text String
"cvtsi2sd") Format
fmt Operand
from Reg
to

       -- FETCHGOT for PIC on ELF platforms
   FETCHGOT Reg
reg
      -> forall doc. IsDoc doc => [Line doc] -> doc
lines_ [ forall doc. IsLine doc => String -> doc
text String
"\tcall 1f",
                  forall doc. IsLine doc => [doc] -> doc
hcat [ forall doc. IsLine doc => String -> doc
text String
"1:\tpopl\t", forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
II32 Reg
reg ],
                  forall doc. IsLine doc => [doc] -> doc
hcat [ forall doc. IsLine doc => String -> doc
text String
"\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), ",
                         forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
II32 Reg
reg ]
                ]

    -- FETCHPC for PIC on Darwin/x86
    -- get the instruction pointer into a register
    -- (Terminology note: the IP is called Program Counter on PPC,
    --  and it's a good thing to use the same name on both platforms)
   FETCHPC Reg
reg
      -> forall doc. IsDoc doc => [Line doc] -> doc
lines_ [ forall doc. IsLine doc => String -> doc
text String
"\tcall 1f",
                  forall doc. IsLine doc => [doc] -> doc
hcat [ forall doc. IsLine doc => String -> doc
text String
"1:\tpopl\t", forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
II32 Reg
reg ]
                ]

   -- the
   -- GST fmt src addr ==> FLD dst ; FSTPsz addr
   g :: Instr
g@(X87Store Format
fmt  AddrMode
addr)
      -> Instr -> Line doc -> doc
pprX87 Instr
g (forall doc. IsLine doc => [doc] -> doc
hcat [Line doc
gtab, forall doc. IsLine doc => String -> doc
text String
"fstp", forall doc. IsLine doc => Format -> doc
pprFormat_x87 Format
fmt, Line doc
gsp, forall doc. IsLine doc => Platform -> AddrMode -> doc
pprAddr Platform
platform AddrMode
addr])

   -- Atomics
   LOCK Instr
i
      -> forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
"\tlock") forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
i

   Instr
MFENCE
      -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tmfence"

   XADD Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"xadd") Format
format Operand
src Operand
dst

   CMPXCHG Format
format Operand
src Operand
dst
      -> Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp (forall doc. IsLine doc => String -> doc
text String
"cmpxchg") Format
format Operand
src Operand
dst


  where
   gtab :: Line doc
   gtab :: Line doc
gtab  = forall doc. IsLine doc => Char -> doc
char Char
'\t'

   gsp :: Line doc
   gsp :: Line doc
gsp   = forall doc. IsLine doc => Char -> doc
char Char
' '



   pprX87 :: Instr -> Line doc -> doc
   pprX87 :: Instr -> Line doc -> doc
pprX87 Instr
fake Line doc
actual
      = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> Instr -> Line doc
pprX87Instr Instr
fake) forall doc. IsDoc doc => doc -> doc -> doc
$$ forall doc. IsDoc doc => Line doc -> doc
line Line doc
actual

   pprX87Instr :: Instr -> Line doc
   pprX87Instr :: Instr -> Line doc
pprX87Instr (X87Store Format
fmt AddrMode
dst) = Line doc -> Format -> AddrMode -> Line doc
pprFormatAddr (forall doc. IsLine doc => String -> doc
text String
"gst") Format
fmt AddrMode
dst
   pprX87Instr Instr
_ = forall a. HasCallStack => String -> a
panic String
"X86.Ppr.pprX87Instr: no match"

   pprDollImm :: Imm -> Line doc
   pprDollImm :: Imm -> Line doc
pprDollImm Imm
i = forall doc. IsLine doc => String -> doc
text String
"$" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
i


   pprOperand :: Platform -> Format -> Operand -> Line doc
   pprOperand :: Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
f Operand
op = case Operand
op of
      OpReg Reg
r   -> forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
f Reg
r
      OpImm Imm
i   -> Imm -> Line doc
pprDollImm Imm
i
      OpAddr AddrMode
ea -> forall doc. IsLine doc => Platform -> AddrMode -> doc
pprAddr Platform
platform AddrMode
ea


   pprMnemonic_  :: Line doc -> Line doc
   pprMnemonic_ :: Line doc -> Line doc
pprMnemonic_ Line doc
name =
      forall doc. IsLine doc => Char -> doc
char Char
'\t' forall doc. IsLine doc => doc -> doc -> doc
<> Line doc
name forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
space


   pprMnemonic  :: Line doc -> Format -> Line doc
   pprMnemonic :: Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format =
      forall doc. IsLine doc => Char -> doc
char Char
'\t' forall doc. IsLine doc => doc -> doc -> doc
<> Line doc
name forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Format -> doc
pprFormat Format
format forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
space


   pprFormatImmOp :: Line doc -> Format -> Imm -> Operand -> doc
   pprFormatImmOp :: Line doc -> Format -> Imm -> Operand -> doc
pprFormatImmOp Line doc
name Format
format Imm
imm Operand
op1
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           forall doc. IsLine doc => Char -> doc
char Char
'$',
           forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
platform Imm
imm,
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1
       ]


   pprFormatOp_ :: Line doc -> Format -> Operand -> doc
   pprFormatOp_ :: Line doc -> Format -> Operand -> doc
pprFormatOp_ Line doc
name Format
format Operand
op1
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Line doc
pprMnemonic_ Line doc
name ,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1
       ]

   pprFormatOp :: Line doc -> Format -> Operand -> doc
   pprFormatOp :: Line doc -> Format -> Operand -> doc
pprFormatOp Line doc
name Format
format Operand
op1
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1
       ]


   pprFormatOpOp :: Line doc -> Format -> Operand -> Operand -> doc
   pprFormatOpOp :: Line doc -> Format -> Operand -> Operand -> doc
pprFormatOpOp Line doc
name Format
format Operand
op1 Operand
op2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1,
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op2
       ]


   pprOpOp :: Line doc -> Format -> Operand -> Operand -> doc
   pprOpOp :: Line doc -> Format -> Operand -> Operand -> doc
pprOpOp Line doc
name Format
format Operand
op1 Operand
op2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Line doc
pprMnemonic_ Line doc
name,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1,
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op2
       ]

   pprRegReg :: Line doc -> Reg -> Reg -> doc
   pprRegReg :: Line doc -> Reg -> Reg -> doc
pprRegReg Line doc
name Reg
reg1 Reg
reg2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Line doc
pprMnemonic_ Line doc
name,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Reg
reg1,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Reg
reg2
       ]


   pprFormatOpReg :: Line doc -> Format -> Operand -> Reg -> doc
   pprFormatOpReg :: Line doc -> Format -> Operand -> Reg -> doc
pprFormatOpReg Line doc
name Format
format Operand
op1 Reg
reg2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform (Bool -> Format
archWordFormat (Platform -> Bool
target32Bit Platform
platform)) Reg
reg2
       ]

   pprCondOpReg :: Line doc -> Format -> Cond -> Operand -> Reg -> doc
   pprCondOpReg :: Line doc -> Format -> Cond -> Operand -> Reg -> doc
pprCondOpReg Line doc
name Format
format Cond
cond Operand
op1 Reg
reg2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           forall doc. IsLine doc => Char -> doc
char Char
'\t',
           Line doc
name,
           forall doc. IsLine doc => Cond -> doc
pprCond Cond
cond,
           forall doc. IsLine doc => doc
space,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
format Reg
reg2
       ]

   pprFormatFormatOpReg :: Line doc -> Format -> Format -> Operand -> Reg -> doc
   pprFormatFormatOpReg :: Line doc -> Format -> Format -> Operand -> Reg -> doc
pprFormatFormatOpReg Line doc
name Format
format1 Format
format2 Operand
op1 Reg
reg2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format2,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format1 Operand
op1,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
format2 Reg
reg2
       ]

   pprFormatOpOpReg :: Line doc -> Format -> Operand -> Operand -> Reg -> doc
   pprFormatOpOpReg :: Line doc -> Format -> Operand -> Operand -> Reg -> doc
pprFormatOpOpReg Line doc
name Format
format Operand
op1 Operand
op2 Reg
reg3
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op1,
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
op2,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> Format -> Reg -> doc
pprReg Platform
platform Format
format Reg
reg3
       ]



   pprFormatAddr :: Line doc -> Format -> AddrMode -> Line doc
   pprFormatAddr :: Line doc -> Format -> AddrMode -> Line doc
pprFormatAddr Line doc
name Format
format  AddrMode
op
     = forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           forall doc. IsLine doc => doc
comma,
           forall doc. IsLine doc => Platform -> AddrMode -> doc
pprAddr Platform
platform AddrMode
op
       ]

   pprShift :: Line doc -> Format -> Operand -> Operand -> doc
   pprShift :: Line doc -> Format -> Operand -> Operand -> doc
pprShift Line doc
name Format
format Operand
src Operand
dest
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [
           Line doc -> Format -> Line doc
pprMnemonic Line doc
name Format
format,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
II8 Operand
src,  -- src is 8-bit sized
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format Operand
dest
       ]


   pprFormatOpOpCoerce :: Line doc -> Format -> Format -> Operand -> Operand -> doc
   pprFormatOpOpCoerce :: Line doc -> Format -> Format -> Operand -> Operand -> doc
pprFormatOpOpCoerce Line doc
name Format
format1 Format
format2 Operand
op1 Operand
op2
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [ forall doc. IsLine doc => Char -> doc
char Char
'\t', Line doc
name, forall doc. IsLine doc => Format -> doc
pprFormat Format
format1, forall doc. IsLine doc => Format -> doc
pprFormat Format
format2, forall doc. IsLine doc => doc
space,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format1 Operand
op1,
           forall doc. IsLine doc => doc
comma,
           Platform -> Format -> Operand -> Line doc
pprOperand Platform
platform Format
format2 Operand
op2
       ]


   pprCondInstr :: Line doc -> Cond -> Line doc -> doc
   pprCondInstr :: Line doc -> Cond -> Line doc -> doc
pprCondInstr Line doc
name Cond
cond Line doc
arg
     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => [doc] -> doc
hcat [ forall doc. IsLine doc => Char -> doc
char Char
'\t', Line doc
name, forall doc. IsLine doc => Cond -> doc
pprCond Cond
cond, forall doc. IsLine doc => doc
space, Line doc
arg]