{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE CPP #-}

module GHC.CmmToAsm.AArch64.Ppr (pprNatCmmDecl, pprInstr) where

import GHC.Prelude hiding (EQ)

import GHC.CmmToAsm.AArch64.Instr
import GHC.CmmToAsm.AArch64.Regs
import GHC.CmmToAsm.AArch64.Cond
import GHC.CmmToAsm.Ppr
import GHC.CmmToAsm.Format
import GHC.Platform.Reg
import GHC.CmmToAsm.Config
import GHC.CmmToAsm.Types
import GHC.CmmToAsm.Utils

import GHC.Cmm hiding (topInfoTable)
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
import GHC.Types.Basic (Alignment, mkAlignment, alignmentBytes)

import GHC.Cmm.BlockId
import GHC.Cmm.CLabel

import GHC.Types.Unique ( pprUniqueAlways, getUnique )
import GHC.Platform
import GHC.Utils.Outputable

import GHC.Utils.Panic

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
. RegNo -> Alignment
mkAlignment) (NCGConfig -> Maybe RegNo
ncgProcAlignment NCGConfig
config)
   where
      platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config

pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc
pprNatCmmDecl :: forall doc.
IsDoc doc =>
NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc
pprNatCmmDecl NCGConfig
config (CmmData Section
section 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 -> RawCmmStatics -> doc
pprDatas NCGConfig
config RawCmmStatics
dats

pprNatCmmDecl NCGConfig
config proc :: NatCmmDecl 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 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
$$
        -- do not
        -- pprProcAlignment config $$
        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
$$
        (if NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
         then forall doc. IsDoc doc => Line doc -> doc
line (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 => Char -> doc
char Char
':') 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
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
$$
      -- pprProcAlignment config $$
      (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 => Char -> doc
char Char
':')
          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
$$
      -- 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 RawCmmStatics Instr -> SDoc #-}
{-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

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 => Char -> doc
char Char
':')

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
"\t.balign " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (Alignment -> RegNo
alignmentBytes Alignment
alignment)

-- | 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
    -- .balign is stable, whereas .align is platform dependent.
    = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
text String
"\t.balign 8") --  always 8

-- | Print section header and appropriate alignment for that section.
--
-- This one will emit the header:
--
--     .section .text
--     .balign 8
--
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
"AArch64.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

-- | 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) (forall a. a -> a
id {-detectTrivialDeadlock-} [Instr]
optInstrs)) forall doc. IsDoc doc => doc -> doc -> doc
$$
    (if  NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
      then forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkAsmTempEndLabel CLabel
asmLbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
':')
      else forall doc. IsOutput doc => doc
empty
    )
  where
    -- Filter out identity moves. E.g. mov x18, x18 will be dropped.
    optInstrs :: [Instr]
optInstrs = forall a. (a -> Bool) -> [a] -> [a]
filter Instr -> Bool
f [Instr]
instrs
      where f :: Instr -> Bool
f (MOV Operand
o1 Operand
o2) | Operand
o1 forall a. Eq a => a -> a -> Bool
== Operand
o2 = Bool
False
            f Instr
_ = Bool
True

    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
info_lbl [CmmStatic]
info) ->
          --  pprAlignForSection platform Text $$
           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
info_lbl forall doc. IsDoc doc => doc -> doc -> doc
$$
           doc
c forall doc. IsDoc doc => doc -> doc -> doc
$$
           (if NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
             then forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (CLabel -> CLabel
mkAsmTempEndLabel CLabel
info_lbl) forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
':')
             else forall doc. IsOutput doc => doc
empty)
    -- 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 -> RawCmmStatics -> doc
-- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
pprDatas :: forall doc. IsDoc doc => NCGConfig -> RawCmmStatics -> doc
pprDatas NCGConfig
config (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 RegNo
_) = 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 (CmmStaticsRaw CLabel
lbl [CmmStatic]
dats)
  = forall doc. IsDoc doc => [doc] -> doc
vcat (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 RegNo
_) = forall doc. IsDoc doc => Line doc -> doc
line (forall doc. IsLine doc => String -> doc
pprFileEmbed String
path)

pprData NCGConfig
config (CmmUninitialised RegNo
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 => RegNo -> doc
int RegNo
bytes
                else forall doc. IsLine doc => String -> doc
text String
".skip "  forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
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
"\t.globl " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)

-- Note [Always use objects for info tables]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- See discussion in X86.Ppr for why this is necessary.  Essentially we need to
-- ensure that we never pass function symbols when we might want to lookup the
-- info table.  If we did, we could end up with procedure linking tables
-- (PLT)s, and thus the lookup wouldn't point to the function, but into the
-- jump table.
--
-- Fun fact: The LLVMMangler exists to patch this issue su on the LLVM side as
-- well.
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
    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)

-- this is called pprTypeAndSizeDecl in PPC.Ppr
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

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

        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.short\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
II64 CmmLit
_ = [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]

        ppr_item Format
FF32  (CmmFloat Rational
r Width
_)
           = let bs :: [Word8]
bs = Float -> [Word8]
floatToBytes (forall a. Fractional a => Rational -> a
fromRational Rational
r)
             in  forall a b. (a -> b) -> [a] -> [b]
map (\Word8
b -> forall doc. IsLine doc => String -> doc
text String
"\t.byte\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b)) [Word8]
bs

        ppr_item Format
FF64 (CmmFloat Rational
r Width
_)
           = let bs :: [Word8]
bs = Double -> [Word8]
doubleToBytes (forall a. Fractional a => Rational -> a
fromRational Rational
r)
             in  forall a b. (a -> b) -> [a] -> [b]
map (\Word8
b -> forall doc. IsLine doc => String -> doc
text String
"\t.byte\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b)) [Word8]
bs

        ppr_item Format
_ CmmLit
_ = forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"pprDataItem:ppr_item" (forall doc. IsLine doc => String -> doc
text forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show CmmLit
lit)

pprImm :: IsLine doc => Platform -> Imm -> doc
pprImm :: forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
_ (ImmInt RegNo
i)     = forall doc. IsLine doc => RegNo -> doc
int RegNo
i
pprImm Platform
_ (ImmInteger Integer
i) = forall doc. IsLine doc => Integer -> doc
integer Integer
i
pprImm Platform
p (ImmCLbl CLabel
l)    = forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
p CLabel
l
pprImm Platform
p (ImmIndex CLabel
l RegNo
i) = forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
p 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 => RegNo -> doc
int RegNo
i
pprImm Platform
_ (ImmLit FastString
s)     = forall doc. IsLine doc => FastString -> doc
ftext FastString
s

-- TODO: See pprIm below for why this is a bad idea!
pprImm Platform
_ (ImmFloat Rational
f)
  | Rational
f forall a. Eq a => a -> a -> Bool
== Rational
0 = forall doc. IsLine doc => String -> doc
text String
"wzr"
  | Bool
otherwise = forall doc. IsLine doc => Float -> doc
float (forall a. Fractional a => Rational -> a
fromRational Rational
f)
pprImm Platform
_ (ImmDouble Rational
d)
  | Rational
d forall a. Eq a => a -> a -> Bool
== Rational
0 = forall doc. IsLine doc => String -> doc
text String
"xzr"
  | Bool
otherwise = forall doc. IsLine doc => Double -> doc
double (forall a. Fractional a => Rational -> a
fromRational Rational
d)

pprImm Platform
p (ImmConstantSum Imm
a Imm
b) = forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
p 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
p Imm
b
pprImm Platform
p (ImmConstantDiff Imm
a Imm
b) = forall doc. IsLine doc => Platform -> Imm -> doc
pprImm Platform
p 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
p Imm
b forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
rparen


-- aarch64 GNU as uses // for comments.
asmComment :: SDoc -> SDoc
asmComment :: SDoc -> SDoc
asmComment SDoc
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
<+> SDoc
c

asmDoubleslashComment :: SDoc -> SDoc
asmDoubleslashComment :: SDoc -> SDoc
asmDoubleslashComment SDoc
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
<+> SDoc
c

asmMultilineComment :: SDoc -> SDoc
asmMultilineComment :: SDoc -> SDoc
asmMultilineComment SDoc
c = forall doc. IsOutput doc => doc -> doc
whenPprDebug forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"/*" SDoc -> SDoc -> SDoc
$+$ SDoc
c SDoc -> SDoc -> SDoc
$+$ forall doc. IsLine doc => String -> doc
text String
"*/"

pprIm :: IsLine doc => Platform -> Imm -> doc
pprIm :: forall doc. IsLine doc => Platform -> Imm -> doc
pprIm Platform
platform Imm
im = case Imm
im of
  ImmInt RegNo
i     -> forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
i
  ImmInteger Integer
i -> forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Integer -> doc
integer Integer
i

  -- TODO: This will only work for
  -- The floating point value must be expressible as ±n ÷ 16 × 2^r,
  -- where n and r are integers such that 16 ≤ n ≤ 31 and -3 ≤ r ≤ 4.
  -- and 0 needs to be encoded as wzr/xzr.
  --
  -- Except for 0, we might want to either split it up into enough
  -- ADD operations into an Integer register and then just bit copy it into
  -- the double register? See the toBytes + fromRational above for data items.
  -- This is something the x86 backend does.
  --
  -- We could also just turn them into statics :-/ Which is what the
  -- PowerPC backend does.
  ImmFloat Rational
f | Rational
f forall a. Eq a => a -> a -> Bool
== Rational
0 -> forall doc. IsLine doc => String -> doc
text String
"wzr"
  ImmFloat Rational
f -> forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Float -> doc
float (forall a. Fractional a => Rational -> a
fromRational Rational
f)
  ImmDouble Rational
d | Rational
d forall a. Eq a => a -> a -> Bool
== Rational
0 -> forall doc. IsLine doc => String -> doc
text String
"xzr"
  ImmDouble Rational
d -> forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Double -> doc
double (forall a. Fractional a => Rational -> a
fromRational Rational
d)
  -- =<lbl> pseudo instruction!
  ImmCLbl CLabel
l    -> 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
l
  ImmIndex CLabel
l RegNo
o -> 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
l forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma 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 => RegNo -> doc
int RegNo
o forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Char -> doc
char Char
']'
  Imm
_            -> forall a. HasCallStack => String -> a
panic String
"AArch64.pprIm"

pprExt :: IsLine doc => ExtMode -> doc
pprExt :: forall doc. IsLine doc => ExtMode -> doc
pprExt ExtMode
EUXTB = forall doc. IsLine doc => String -> doc
text String
"uxtb"
pprExt ExtMode
EUXTH = forall doc. IsLine doc => String -> doc
text String
"uxth"
pprExt ExtMode
EUXTW = forall doc. IsLine doc => String -> doc
text String
"uxtw"
pprExt ExtMode
EUXTX = forall doc. IsLine doc => String -> doc
text String
"uxtx"
pprExt ExtMode
ESXTB = forall doc. IsLine doc => String -> doc
text String
"sxtb"
pprExt ExtMode
ESXTH = forall doc. IsLine doc => String -> doc
text String
"sxth"
pprExt ExtMode
ESXTW = forall doc. IsLine doc => String -> doc
text String
"sxtw"
pprExt ExtMode
ESXTX = forall doc. IsLine doc => String -> doc
text String
"sxtx"

pprShift :: IsLine doc => ShiftMode -> doc
pprShift :: forall doc. IsLine doc => ShiftMode -> doc
pprShift ShiftMode
SLSL = forall doc. IsLine doc => String -> doc
text String
"lsl"
pprShift ShiftMode
SLSR = forall doc. IsLine doc => String -> doc
text String
"lsr"
pprShift ShiftMode
SASR = forall doc. IsLine doc => String -> doc
text String
"asr"
pprShift ShiftMode
SROR = forall doc. IsLine doc => String -> doc
text String
"ror"

pprOp :: IsLine doc => Platform -> Operand -> doc
pprOp :: forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
plat Operand
op = case Operand
op of
  OpReg Width
w Reg
r           -> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
w Reg
r
  OpRegExt Width
w Reg
r ExtMode
x RegNo
0 -> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
w 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 => ExtMode -> doc
pprExt ExtMode
x
  OpRegExt Width
w Reg
r ExtMode
x RegNo
i -> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
w 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 => ExtMode -> doc
pprExt ExtMode
x forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma 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 => RegNo -> doc
int RegNo
i
  OpRegShift Width
w Reg
r ShiftMode
s RegNo
i -> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
w 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 => ShiftMode -> doc
pprShift ShiftMode
s 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 => RegNo -> doc
int RegNo
i
  OpImm Imm
im          -> forall doc. IsLine doc => Platform -> Imm -> doc
pprIm Platform
plat Imm
im
  OpImmShift Imm
im ShiftMode
s RegNo
i -> forall doc. IsLine doc => Platform -> Imm -> doc
pprIm Platform
plat Imm
im forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => ShiftMode -> doc
pprShift ShiftMode
s 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 => RegNo -> doc
int RegNo
i
  -- TODO: Address computation always use registers as 64bit -- is this correct?
  OpAddr (AddrRegReg Reg
r1 Reg
r2) -> forall doc. IsLine doc => Char -> doc
char Char
'[' forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r1 forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r2 forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Char -> doc
char Char
']'
  OpAddr (AddrRegImm Reg
r1 Imm
im) -> forall doc. IsLine doc => Char -> doc
char Char
'[' forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r1 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 -> Imm -> doc
pprImm Platform
plat Imm
im forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Char -> doc
char Char
']'
  OpAddr (AddrReg Reg
r1)       -> forall doc. IsLine doc => Char -> doc
char Char
'[' forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r1 forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Char -> doc
char Char
']'

pprReg :: forall doc. IsLine doc => Width -> Reg -> doc
pprReg :: forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
w Reg
r = case Reg
r of
  RegReal    (RealRegSingle RegNo
i) -> Width -> RegNo -> doc
ppr_reg_no Width
w RegNo
i
  -- virtual regs should not show up, but this is helpful for debugging.
  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 (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
  Reg
_                            -> forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"AArch64.pprReg" (forall doc. IsLine doc => String -> doc
text forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Reg
r)

  where
    ppr_reg_no :: Width -> Int -> doc
    ppr_reg_no :: Width -> RegNo -> doc
ppr_reg_no Width
w RegNo
31
         | Width
w forall a. Eq a => a -> a -> Bool
== Width
W64 = forall doc. IsLine doc => String -> doc
text String
"sp"
         | Width
w forall a. Eq a => a -> a -> Bool
== Width
W32 = forall doc. IsLine doc => String -> doc
text String
"wsp"

    ppr_reg_no Width
w RegNo
i
         | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
0, Width
w forall a. Eq a => a -> a -> Bool
== Width
W32 = forall doc. IsLine doc => String -> doc
text String
"wzr"
         | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
0, Width
w forall a. Eq a => a -> a -> Bool
== Width
W64 = forall doc. IsLine doc => String -> doc
text String
"xzr"
         | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
0 = forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"Invalid Zero Reg" (forall a. Outputable a => a -> SDoc
ppr Width
w forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => RegNo -> doc
int RegNo
i)
         -- General Purpose Registers
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
31, Width
w forall a. Eq a => a -> a -> Bool
== Width
W8  = forall doc. IsLine doc => String -> doc
text String
"w" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
i      -- there are no byte or half
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
31, Width
w forall a. Eq a => a -> a -> Bool
== Width
W16 = forall doc. IsLine doc => String -> doc
text String
"w" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
i      -- words... word will do.
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
31, Width
w forall a. Eq a => a -> a -> Bool
== Width
W32 = forall doc. IsLine doc => String -> doc
text String
"w" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
i
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
31, Width
w forall a. Eq a => a -> a -> Bool
== Width
W64 = forall doc. IsLine doc => String -> doc
text String
"x" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
i
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
31 = forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"Invalid Reg" (forall a. Outputable a => a -> SDoc
ppr Width
w forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => RegNo -> doc
int RegNo
i)
         -- Floating Point Registers
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
63, Width
w forall a. Eq a => a -> a -> Bool
== Width
W8  = forall doc. IsLine doc => String -> doc
text String
"b" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (RegNo
iforall a. Num a => a -> a -> a
-RegNo
32)
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
63, Width
w forall a. Eq a => a -> a -> Bool
== Width
W16 = forall doc. IsLine doc => String -> doc
text String
"h" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (RegNo
iforall a. Num a => a -> a -> a
-RegNo
32)
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
63, Width
w forall a. Eq a => a -> a -> Bool
== Width
W32 = forall doc. IsLine doc => String -> doc
text String
"s" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (RegNo
iforall a. Num a => a -> a -> a
-RegNo
32)
         | RegNo
i forall a. Ord a => a -> a -> Bool
<= RegNo
63, Width
w forall a. Eq a => a -> a -> Bool
== Width
W64 = forall doc. IsLine doc => String -> doc
text String
"d" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int (RegNo
iforall a. Num a => a -> a -> a
-RegNo
32)
         -- no support for 'q'uad in GHC's NCG yet.
         | Bool
otherwise = forall doc. IsLine doc => String -> doc
text String
"very naughty powerpc register"

isFloatOp :: Operand -> Bool
isFloatOp :: Operand -> Bool
isFloatOp (OpReg Width
_ (RegReal (RealRegSingle RegNo
i))) | RegNo
i forall a. Ord a => a -> a -> Bool
> RegNo
31 = Bool
True
isFloatOp (OpReg Width
_ (RegVirtual (VirtualRegF Unique
_))) = Bool
True
isFloatOp (OpReg Width
_ (RegVirtual (VirtualRegD Unique
_))) = Bool
True
isFloatOp Operand
_ = Bool
False

pprInstr :: IsDoc doc => Platform -> Instr -> doc
pprInstr :: forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
instr = case Instr
instr of
  -- Meta Instructions ---------------------------------------------------------
  -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable
  COMMENT SDoc
s  -> forall doc. IsDoc doc => SDoc -> HDoc -> doc
dualDoc (SDoc -> SDoc
asmComment SDoc
s) forall doc. IsOutput doc => doc
empty
  MULTILINE_COMMENT SDoc
s -> forall doc. IsDoc doc => SDoc -> HDoc -> doc
dualDoc (SDoc -> SDoc
asmMultilineComment SDoc
s) forall doc. IsOutput doc => doc
empty
  ANN SDoc
d Instr
i -> forall doc. IsDoc doc => SDoc -> HDoc -> doc
dualDoc (forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
i forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
asmDoubleslashComment SDoc
d) (forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform Instr
i)

  LOCATION RegNo
file RegNo
line' RegNo
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 => RegNo -> doc
int RegNo
file forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => RegNo -> doc
int RegNo
line' forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => RegNo -> doc
int RegNo
col)
  DELTA RegNo
d   -> forall doc. IsDoc doc => SDoc -> HDoc -> doc
dualDoc (SDoc -> SDoc
asmComment forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tdelta = " forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
d) forall doc. IsOutput doc => doc
empty
               -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable
  NEWBLOCK BlockId
_ -> forall a. HasCallStack => String -> a
panic String
"PprInstr: NEWBLOCK"
  LDATA Section
_ RawCmmStatics
_  -> forall a. HasCallStack => String -> a
panic String
"pprInstr: LDATA"

  -- Pseudo Instructions -------------------------------------------------------

  Instr
PUSH_STACK_FRAME -> forall doc. IsDoc doc => [Line doc] -> doc
lines_ [forall doc. IsLine doc => String -> doc
text String
"\tstp x29, x30, [sp, #-16]!",
                              forall doc. IsLine doc => String -> doc
text String
"\tmov x29, sp"]

  Instr
POP_STACK_FRAME -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tldp x29, x30, [sp], #16"
  -- ===========================================================================
  -- AArch64 Instruction Set
  -- 1. Arithmetic Instructions ------------------------------------------------
  ADD  Operand
o1 Operand
o2 Operand
o3
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tfadd") Operand
o1 Operand
o2 Operand
o3
    | Bool
otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tadd") Operand
o1 Operand
o2 Operand
o3
  CMN  Operand
o1 Operand
o2    -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tcmn") Operand
o1 Operand
o2
  CMP  Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfcmp") Operand
o1 Operand
o2
    | Bool
otherwise -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tcmp") Operand
o1 Operand
o2
  MSUB Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 (forall doc. IsLine doc => String -> doc
text String
"\tmsub") Operand
o1 Operand
o2 Operand
o3 Operand
o4
  MUL  Operand
o1 Operand
o2 Operand
o3
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tfmul") Operand
o1 Operand
o2 Operand
o3
    | Bool
otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tmul") Operand
o1 Operand
o2 Operand
o3
  SMULH Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tsmulh") Operand
o1 Operand
o2 Operand
o3
  SMULL Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tsmull") Operand
o1 Operand
o2 Operand
o3
  NEG  Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfneg") Operand
o1 Operand
o2
    | Bool
otherwise -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tneg") Operand
o1 Operand
o2
  SDIV Operand
o1 Operand
o2 Operand
o3 | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o3
    -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tfdiv") Operand
o1 Operand
o2 Operand
o3
  SDIV Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tsdiv") Operand
o1 Operand
o2 Operand
o3

  SUB  Operand
o1 Operand
o2 Operand
o3
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tfsub") Operand
o1 Operand
o2 Operand
o3
    | Bool
otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tsub")  Operand
o1 Operand
o2 Operand
o3
  UDIV Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tudiv") Operand
o1 Operand
o2 Operand
o3

  -- 2. Bit Manipulation Instructions ------------------------------------------
  SBFM Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 (forall doc. IsLine doc => String -> doc
text String
"\tsbfm") Operand
o1 Operand
o2 Operand
o3 Operand
o4
  UBFM Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 (forall doc. IsLine doc => String -> doc
text String
"\tubfm") Operand
o1 Operand
o2 Operand
o3 Operand
o4
  -- signed and unsigned bitfield extract
  SBFX Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 (forall doc. IsLine doc => String -> doc
text String
"\tsbfx") Operand
o1 Operand
o2 Operand
o3 Operand
o4
  UBFX Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 (forall doc. IsLine doc => String -> doc
text String
"\tubfx") Operand
o1 Operand
o2 Operand
o3 Operand
o4
  SXTB Operand
o1 Operand
o2       -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tsxtb") Operand
o1 Operand
o2
  UXTB Operand
o1 Operand
o2       -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tuxtb") Operand
o1 Operand
o2
  SXTH Operand
o1 Operand
o2       -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tsxth") Operand
o1 Operand
o2
  UXTH Operand
o1 Operand
o2       -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tuxth") Operand
o1 Operand
o2

  -- 3. Logical and Move Instructions ------------------------------------------
  AND Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tand") Operand
o1 Operand
o2 Operand
o3
  ANDS Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tands") Operand
o1 Operand
o2 Operand
o3
  ASR Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tasr") Operand
o1 Operand
o2 Operand
o3
  BIC Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tbic") Operand
o1 Operand
o2 Operand
o3
  BICS Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tbics") Operand
o1 Operand
o2 Operand
o3
  EON Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\teon") Operand
o1 Operand
o2 Operand
o3
  EOR Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\teor") Operand
o1 Operand
o2 Operand
o3
  LSL Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tlsl") Operand
o1 Operand
o2 Operand
o3
  LSR Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tlsr") Operand
o1 Operand
o2 Operand
o3
  MOV Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
|| Operand -> Bool
isFloatOp Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfmov") Operand
o1 Operand
o2
    | Bool
otherwise                    -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tmov") Operand
o1 Operand
o2
  MOVK Operand
o1 Operand
o2    -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tmovk") Operand
o1 Operand
o2
  MVN Operand
o1 Operand
o2     -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tmvn") Operand
o1 Operand
o2
  ORN Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\torn") Operand
o1 Operand
o2 Operand
o3
  ORR Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\torr") Operand
o1 Operand
o2 Operand
o3
  ROR Operand
o1 Operand
o2 Operand
o3  -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tror") Operand
o1 Operand
o2 Operand
o3
  TST Operand
o1 Operand
o2     -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\ttst") Operand
o1 Operand
o2

  -- 4. Branch Instructions ----------------------------------------------------
  J Target
t            -> forall doc. IsDoc doc => Platform -> Instr -> doc
pprInstr Platform
platform (Target -> Instr
B Target
t)
  B (TBlock BlockId
bid) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tb" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (Unique -> CLabel
mkLocalBlockLabel (forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  B (TLabel CLabel
lbl) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tb" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl
  B (TReg Reg
r)     -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tbr" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r

  BL (TBlock BlockId
bid) [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
"\tbl" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (Unique -> CLabel
mkLocalBlockLabel (forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  BL (TLabel CLabel
lbl) [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
"\tbl" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl
  BL (TReg Reg
r)     [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
"\tblr" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Width -> Reg -> doc
pprReg Width
W64 Reg
r

  BCOND Cond
c (TBlock BlockId
bid) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Cond -> doc
pprBcond Cond
c forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform (Unique -> CLabel
mkLocalBlockLabel (forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  BCOND Cond
c (TLabel CLabel
lbl) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\t" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Cond -> doc
pprBcond Cond
c forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl
  BCOND Cond
_ (TReg Reg
_)     -> forall a. HasCallStack => String -> a
panic String
"AArch64.ppr: No conditional branching to registers!"

  -- 5. Atomic Instructions ----------------------------------------------------
  -- 6. Conditional Instructions -----------------------------------------------
  CSET Operand
o Cond
c  -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcset" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Cond -> doc
pprCond Cond
c

  CBZ Operand
o (TBlock BlockId
bid) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcbz" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o 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 Platform
platform (Unique -> CLabel
mkLocalBlockLabel (forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  CBZ Operand
o (TLabel CLabel
lbl) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcbz" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o 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 Platform
platform CLabel
lbl
  CBZ Operand
_ (TReg Reg
_)     -> forall a. HasCallStack => String -> a
panic String
"AArch64.ppr: No conditional (cbz) branching to registers!"

  CBNZ Operand
o (TBlock BlockId
bid) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcbnz" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o 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 Platform
platform (Unique -> CLabel
mkLocalBlockLabel (forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  CBNZ Operand
o (TLabel CLabel
lbl) -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tcbnz" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o 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 Platform
platform CLabel
lbl
  CBNZ Operand
_ (TReg Reg
_)     -> forall a. HasCallStack => String -> a
panic String
"AArch64.ppr: No conditional (cbnz) branching to registers!"

  -- 7. Load and Store Instructions --------------------------------------------
  -- NOTE: GHC may do whacky things where it only load the lower part of an
  --       address. Not observing the correct size when loading will lead
  --       inevitably to crashes.
  STR Format
_f o1 :: Operand
o1@(OpReg Width
W8 (RegReal (RealRegSingle RegNo
i))) Operand
o2 | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
32 ->
    Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tstrb") Operand
o1 Operand
o2
  STR Format
_f o1 :: Operand
o1@(OpReg Width
W16 (RegReal (RealRegSingle RegNo
i))) Operand
o2 | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
32 ->
    Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tstrh") Operand
o1 Operand
o2
  STR Format
_f Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tstr") Operand
o1 Operand
o2
  STLR Format
_f Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tstlr") Operand
o1 Operand
o2

#if defined(darwin_HOST_OS)
  LDR _f o1 (OpImm (ImmIndex lbl' off)) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmIndex lbl off)) | isForeignLabel lbl ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmIndex lbl off)) ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
    op_add o1 (pprAsmLabel platform lbl <> text "@pageoff") $$
    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmCLbl lbl')) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")

  LDR _f o1 (OpImm (ImmCLbl lbl)) | isForeignLabel lbl ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")

  LDR _f o1 (OpImm (ImmCLbl lbl)) ->
    op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
    op_add o1 (pprAsmLabel platform lbl <> text "@pageoff")

#else
  LDR Format
_f Operand
o1 (OpImm (ImmIndex CLabel
lbl' RegNo
off)) | Just (DynamicLinkerLabelInfo
_info, CLabel
lbl) <- CLabel -> Maybe (DynamicLinkerLabelInfo, CLabel)
dynamicLinkerLabelInfo CLabel
lbl' ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_ldr Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got_lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_add Operand
o1 (forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
off) -- TODO: check that off is in 12bits.

  LDR Format
_f Operand
o1 (OpImm (ImmIndex CLabel
lbl RegNo
off)) | CLabel -> Bool
isForeignLabel CLabel
lbl ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_ldr Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got_lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_add Operand
o1 (forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
off) -- TODO: check that off is in 12bits.

  LDR Format
_f Operand
o1 (OpImm (ImmIndex CLabel
lbl RegNo
off)) ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_add Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_add Operand
o1 (forall doc. IsLine doc => Char -> doc
char Char
'#' forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => RegNo -> doc
int RegNo
off) -- TODO: check that off is in 12bits.

  LDR Format
_f Operand
o1 (OpImm (ImmCLbl CLabel
lbl')) | Just (DynamicLinkerLabelInfo
_info, CLabel
lbl) <- CLabel -> Maybe (DynamicLinkerLabelInfo, CLabel)
dynamicLinkerLabelInfo CLabel
lbl' ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_ldr Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got_lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)

  LDR Format
_f Operand
o1 (OpImm (ImmCLbl CLabel
lbl)) | CLabel -> Bool
isForeignLabel CLabel
lbl ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_ldr Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":got_lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)

  LDR Format
_f Operand
o1 (OpImm (ImmCLbl CLabel
lbl)) ->
    Operand -> Line doc -> doc
op_adrp Operand
o1 (forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl) forall doc. IsDoc doc => doc -> doc -> doc
$$
    Operand -> Line doc -> doc
op_add Operand
o1 (forall doc. IsLine doc => String -> doc
text String
":lo12:" forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Platform -> CLabel -> doc
pprAsmLabel Platform
platform CLabel
lbl)

#endif

  LDR Format
_f o1 :: Operand
o1@(OpReg Width
W8 (RegReal (RealRegSingle RegNo
i))) Operand
o2 | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
32 ->
    Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tldrb") Operand
o1 Operand
o2
  LDR Format
_f o1 :: Operand
o1@(OpReg Width
W16 (RegReal (RealRegSingle RegNo
i))) Operand
o2 | RegNo
i forall a. Ord a => a -> a -> Bool
< RegNo
32 ->
    Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tldrh") Operand
o1 Operand
o2
  LDR Format
_f Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tldr") Operand
o1 Operand
o2
  LDAR Format
_f Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tldar") Operand
o1 Operand
o2

  STP Format
_f Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tstp") Operand
o1 Operand
o2 Operand
o3
  LDP Format
_f Operand
o1 Operand
o2 Operand
o3 -> Line doc -> Operand -> Operand -> Operand -> doc
op3 (forall doc. IsLine doc => String -> doc
text String
"\tldp") Operand
o1 Operand
o2 Operand
o3

  -- 8. Synchronization Instructions -------------------------------------------
  Instr
DMBSY -> forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tdmb sy"
  -- 9. Floating Point Instructions --------------------------------------------
  FCVT Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfcvt") Operand
o1 Operand
o2
  SCVTF Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tscvtf") Operand
o1 Operand
o2
  FCVTZS Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfcvtzs") Operand
o1 Operand
o2
  FABS Operand
o1 Operand
o2 -> Line doc -> Operand -> Operand -> doc
op2 (forall doc. IsLine doc => String -> doc
text String
"\tfabs") Operand
o1 Operand
o2
 where op2 :: Line doc -> Operand -> Operand -> doc
op2 Line doc
op Operand
o1 Operand
o2        = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ Line doc
op forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 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 -> Operand -> doc
pprOp Platform
platform Operand
o2
       op3 :: Line doc -> Operand -> Operand -> Operand -> doc
op3 Line doc
op Operand
o1 Operand
o2 Operand
o3     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ Line doc
op forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 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 -> Operand -> doc
pprOp Platform
platform Operand
o2 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 -> Operand -> doc
pprOp Platform
platform Operand
o3
       op4 :: Line doc -> Operand -> Operand -> Operand -> Operand -> doc
op4 Line doc
op Operand
o1 Operand
o2 Operand
o3 Operand
o4  = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ Line doc
op forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 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 -> Operand -> doc
pprOp Platform
platform Operand
o2 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 -> Operand -> doc
pprOp Platform
platform Operand
o3 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 -> Operand -> doc
pprOp Platform
platform Operand
o4
       op_ldr :: Operand -> Line doc -> doc
op_ldr Operand
o1 Line doc
rest      = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tldr" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma 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 -> Operand -> doc
pprOp Platform
platform Operand
o1 forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> Line doc
rest forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => String -> doc
text String
"]"
       op_adrp :: Operand -> Line doc -> doc
op_adrp Operand
o1 Line doc
rest     = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tadrp" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> Line doc
rest
       op_add :: Operand -> Line doc -> doc
op_add Operand
o1 Line doc
rest      = forall doc. IsDoc doc => Line doc -> doc
line forall a b. (a -> b) -> a -> b
$ forall doc. IsLine doc => String -> doc
text String
"\tadd" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => Platform -> Operand -> doc
pprOp Platform
platform Operand
o1 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 -> Operand -> doc
pprOp Platform
platform Operand
o1 forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
comma forall doc. IsLine doc => doc -> doc -> doc
<+> Line doc
rest

pprBcond :: IsLine doc => Cond -> doc
pprBcond :: forall doc. IsLine doc => Cond -> doc
pprBcond Cond
c = forall doc. IsLine doc => String -> doc
text String
"b." forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => Cond -> doc
pprCond Cond
c

pprCond :: IsLine doc => Cond -> doc
pprCond :: forall doc. IsLine doc => Cond -> doc
pprCond Cond
c = case Cond
c of
  Cond
ALWAYS -> forall doc. IsLine doc => String -> doc
text String
"al" -- Always
  Cond
EQ     -> forall doc. IsLine doc => String -> doc
text String
"eq" -- Equal
  Cond
NE     -> forall doc. IsLine doc => String -> doc
text String
"ne" -- Not Equal

  Cond
SLT    -> forall doc. IsLine doc => String -> doc
text String
"lt" -- Signed less than                  ; Less than, or unordered
  Cond
SLE    -> forall doc. IsLine doc => String -> doc
text String
"le" -- Signed less than or equal         ; Less than or equal, or unordered
  Cond
SGE    -> forall doc. IsLine doc => String -> doc
text String
"ge" -- Signed greater than or equal      ; Greater than or equal
  Cond
SGT    -> forall doc. IsLine doc => String -> doc
text String
"gt" -- Signed greater than               ; Greater than

  Cond
ULT    -> forall doc. IsLine doc => String -> doc
text String
"lo" -- Carry clear/ unsigned lower       ; less than
  Cond
ULE    -> forall doc. IsLine doc => String -> doc
text String
"ls" -- Unsigned lower or same            ; Less than or equal
  Cond
UGE    -> forall doc. IsLine doc => String -> doc
text String
"hs" -- Carry set/unsigned higher or same ; Greater than or equal, or unordered
  Cond
UGT    -> forall doc. IsLine doc => String -> doc
text String
"hi" -- Unsigned higher                   ; Greater than, or unordered

  Cond
NEVER  -> forall doc. IsLine doc => String -> doc
text String
"nv" -- Never
  Cond
VS     -> forall doc. IsLine doc => String -> doc
text String
"vs" -- Overflow                          ; Unordered (at least one NaN operand)
  Cond
VC     -> forall doc. IsLine doc => String -> doc
text String
"vc" -- No overflow                       ; Not unordered

  -- Ordered variants.  Respecting NaN.
  Cond
OLT    -> forall doc. IsLine doc => String -> doc
text String
"mi"
  Cond
OLE    -> forall doc. IsLine doc => String -> doc
text String
"ls"
  Cond
OGE    -> forall doc. IsLine doc => String -> doc
text String
"ge"
  Cond
OGT    -> forall doc. IsLine doc => String -> doc
text String
"gt"

  -- Unordered
  Cond
UOLT   -> forall doc. IsLine doc => String -> doc
text String
"lt"
  Cond
UOLE   -> forall doc. IsLine doc => String -> doc
text String
"le"
  Cond
UOGE   -> forall doc. IsLine doc => String -> doc
text String
"pl"
  Cond
UOGT   -> forall doc. IsLine doc => String -> doc
text String
"hi"