module GHC.CmmToAsm.AArch64.Instr
where
import GHC.Prelude
import GHC.CmmToAsm.AArch64.Cond
import GHC.CmmToAsm.AArch64.Regs
import GHC.CmmToAsm.Instr (RegUsage(..))
import GHC.CmmToAsm.Format
import GHC.CmmToAsm.Types
import GHC.CmmToAsm.Utils
import GHC.CmmToAsm.Config
import GHC.Platform.Reg
import GHC.Platform.Regs
import GHC.Cmm.BlockId
import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Label
import GHC.Cmm
import GHC.Cmm.CLabel
import GHC.Utils.Outputable
import GHC.Platform
import GHC.Types.Unique.Supply
import GHC.Utils.Panic
import Control.Monad (replicateM)
import Data.Maybe (fromMaybe)
import GHC.Stack
stackFrameHeaderSize :: Platform -> Int
stackFrameHeaderSize _ = 64
spillSlotSize :: Int
spillSlotSize = 8
stackAlign :: Int
stackAlign = 16
maxSpillSlots :: NCGConfig -> Int
maxSpillSlots config
= let platform = ncgPlatform config
in ((ncgSpillPreallocSize config stackFrameHeaderSize platform)
`div` spillSlotSize) 1
spillSlotToOffset :: NCGConfig -> Int -> Int
spillSlotToOffset config slot
= stackFrameHeaderSize (ncgPlatform config) + spillSlotSize * slot
instance Outputable RegUsage where
ppr (RU reads writes) = text "RegUsage(reads:" <+> ppr reads <> comma <+> text "writes:" <+> ppr writes <> char ')'
regUsageOfInstr :: Platform -> Instr -> RegUsage
regUsageOfInstr platform instr = case instr of
ANN _ i -> regUsageOfInstr platform i
ADD dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
CMN l r -> usage (regOp l ++ regOp r, [])
CMP l r -> usage (regOp l ++ regOp r, [])
MSUB dst src1 src2 src3 -> usage (regOp src1 ++ regOp src2 ++ regOp src3, regOp dst)
MUL dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
NEG dst src -> usage (regOp src, regOp dst)
SMULH dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
SMULL dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
SDIV dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
SUB dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
UDIV dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
SBFM dst src _ _ -> usage (regOp src, regOp dst)
UBFM dst src _ _ -> usage (regOp src, regOp dst)
SBFX dst src _ _ -> usage (regOp src, regOp dst)
UBFX dst src _ _ -> usage (regOp src, regOp dst)
SXTB dst src -> usage (regOp src, regOp dst)
UXTB dst src -> usage (regOp src, regOp dst)
SXTH dst src -> usage (regOp src, regOp dst)
UXTH dst src -> usage (regOp src, regOp dst)
AND dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
ASR dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
BIC dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
BICS dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
EON dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
EOR dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
LSL dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
LSR dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
MOV dst src -> usage (regOp src, regOp dst)
MOVK dst src -> usage (regOp src, regOp dst)
MVN dst src -> usage (regOp src, regOp dst)
ORR dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
ROR dst src1 src2 -> usage (regOp src1 ++ regOp src2, regOp dst)
TST src1 src2 -> usage (regOp src1 ++ regOp src2, [])
J t -> usage (regTarget t, [])
B t -> usage (regTarget t, [])
BCOND _ t -> usage (regTarget t, [])
BL t ps _rs -> usage (regTarget t ++ ps, callerSavedRegisters)
CSET dst _ -> usage ([], regOp dst)
CBZ src _ -> usage (regOp src, [])
CBNZ src _ -> usage (regOp src, [])
STR _ src dst -> usage (regOp src ++ regOp dst, [])
LDR _ dst src -> usage (regOp src, regOp dst)
STP _ src1 src2 dst -> usage (regOp src1 ++ regOp src2 ++ regOp dst, [])
LDP _ dst1 dst2 src -> usage (regOp src, regOp dst1 ++ regOp dst2)
DMBSY -> usage ([], [])
FCVT dst src -> usage (regOp src, regOp dst)
SCVTF dst src -> usage (regOp src, regOp dst)
FCVTZS dst src -> usage (regOp src, regOp dst)
FABS dst src -> usage (regOp src, regOp dst)
_ -> panic "regUsageOfInstr"
where
usage (src, dst) = RU (filter (interesting platform) src)
(filter (interesting platform) dst)
regAddr :: AddrMode -> [Reg]
regAddr (AddrRegReg r1 r2) = [r1, r2]
regAddr (AddrRegImm r1 _) = [r1]
regAddr (AddrReg r1) = [r1]
regOp :: Operand -> [Reg]
regOp (OpReg _ r1) = [r1]
regOp (OpRegExt _ r1 _ _) = [r1]
regOp (OpRegShift _ r1 _ _) = [r1]
regOp (OpAddr a) = regAddr a
regOp (OpImm _) = []
regOp (OpImmShift _ _ _) = []
regTarget :: Target -> [Reg]
regTarget (TBlock _) = []
regTarget (TLabel _) = []
regTarget (TReg r1) = [r1]
interesting :: Platform -> Reg -> Bool
interesting _ (RegVirtual _) = True
interesting _ (RegReal (RealRegSingle (1))) = False
interesting platform (RegReal (RealRegSingle i)) = freeReg platform i
interesting _ (RegReal (RealRegPair{}))
= panic "AArch64.Instr.interesting: no reg pairs on this arch"
callerSavedRegisters :: [Reg]
callerSavedRegisters
= map regSingle [0..18]
++ map regSingle [32..39]
++ map regSingle [48..63]
patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
patchRegsOfInstr instr env = case instr of
ANN d i -> ANN d (patchRegsOfInstr i env)
ADD o1 o2 o3 -> ADD (patchOp o1) (patchOp o2) (patchOp o3)
CMN o1 o2 -> CMN (patchOp o1) (patchOp o2)
CMP o1 o2 -> CMP (patchOp o1) (patchOp o2)
MSUB o1 o2 o3 o4 -> MSUB (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)
MUL o1 o2 o3 -> MUL (patchOp o1) (patchOp o2) (patchOp o3)
NEG o1 o2 -> NEG (patchOp o1) (patchOp o2)
SMULH o1 o2 o3 -> SMULH (patchOp o1) (patchOp o2) (patchOp o3)
SMULL o1 o2 o3 -> SMULL (patchOp o1) (patchOp o2) (patchOp o3)
SDIV o1 o2 o3 -> SDIV (patchOp o1) (patchOp o2) (patchOp o3)
SUB o1 o2 o3 -> SUB (patchOp o1) (patchOp o2) (patchOp o3)
UDIV o1 o2 o3 -> UDIV (patchOp o1) (patchOp o2) (patchOp o3)
SBFM o1 o2 o3 o4 -> SBFM (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)
UBFM o1 o2 o3 o4 -> UBFM (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)
SBFX o1 o2 o3 o4 -> SBFX (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)
UBFX o1 o2 o3 o4 -> UBFX (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)
SXTB o1 o2 -> SXTB (patchOp o1) (patchOp o2)
UXTB o1 o2 -> UXTB (patchOp o1) (patchOp o2)
SXTH o1 o2 -> SXTH (patchOp o1) (patchOp o2)
UXTH o1 o2 -> UXTH (patchOp o1) (patchOp o2)
AND o1 o2 o3 -> AND (patchOp o1) (patchOp o2) (patchOp o3)
ANDS o1 o2 o3 -> ANDS (patchOp o1) (patchOp o2) (patchOp o3)
ASR o1 o2 o3 -> ASR (patchOp o1) (patchOp o2) (patchOp o3)
BIC o1 o2 o3 -> BIC (patchOp o1) (patchOp o2) (patchOp o3)
BICS o1 o2 o3 -> BICS (patchOp o1) (patchOp o2) (patchOp o3)
EON o1 o2 o3 -> EON (patchOp o1) (patchOp o2) (patchOp o3)
EOR o1 o2 o3 -> EOR (patchOp o1) (patchOp o2) (patchOp o3)
LSL o1 o2 o3 -> LSL (patchOp o1) (patchOp o2) (patchOp o3)
LSR o1 o2 o3 -> LSR (patchOp o1) (patchOp o2) (patchOp o3)
MOV o1 o2 -> MOV (patchOp o1) (patchOp o2)
MOVK o1 o2 -> MOVK (patchOp o1) (patchOp o2)
MVN o1 o2 -> MVN (patchOp o1) (patchOp o2)
ORR o1 o2 o3 -> ORR (patchOp o1) (patchOp o2) (patchOp o3)
ROR o1 o2 o3 -> ROR (patchOp o1) (patchOp o2) (patchOp o3)
TST o1 o2 -> TST (patchOp o1) (patchOp o2)
J t -> J (patchTarget t)
B t -> B (patchTarget t)
BL t rs ts -> BL (patchTarget t) rs ts
BCOND c t -> BCOND c (patchTarget t)
CSET o c -> CSET (patchOp o) c
CBZ o l -> CBZ (patchOp o) l
CBNZ o l -> CBNZ (patchOp o) l
STR f o1 o2 -> STR f (patchOp o1) (patchOp o2)
LDR f o1 o2 -> LDR f (patchOp o1) (patchOp o2)
STP f o1 o2 o3 -> STP f (patchOp o1) (patchOp o2) (patchOp o3)
LDP f o1 o2 o3 -> LDP f (patchOp o1) (patchOp o2) (patchOp o3)
DMBSY -> DMBSY
FCVT o1 o2 -> FCVT (patchOp o1) (patchOp o2)
SCVTF o1 o2 -> SCVTF (patchOp o1) (patchOp o2)
FCVTZS o1 o2 -> FCVTZS (patchOp o1) (patchOp o2)
FABS o1 o2 -> FABS (patchOp o1) (patchOp o2)
_ -> pprPanic "patchRegsOfInstr" (text $ show instr)
where
patchOp :: Operand -> Operand
patchOp (OpReg w r) = OpReg w (env r)
patchOp (OpRegExt w r x s) = OpRegExt w (env r) x s
patchOp (OpRegShift w r m s) = OpRegShift w (env r) m s
patchOp (OpAddr a) = OpAddr (patchAddr a)
patchOp op = op
patchTarget :: Target -> Target
patchTarget (TReg r) = TReg (env r)
patchTarget t = t
patchAddr :: AddrMode -> AddrMode
patchAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
patchAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
patchAddr (AddrReg r) = AddrReg (env r)
isJumpishInstr :: Instr -> Bool
isJumpishInstr instr = case instr of
ANN _ i -> isJumpishInstr i
CBZ{} -> True
CBNZ{} -> True
J{} -> True
B{} -> True
BL{} -> True
BCOND{} -> True
_ -> False
jumpDestsOfInstr :: Instr -> [BlockId]
jumpDestsOfInstr (ANN _ i) = jumpDestsOfInstr i
jumpDestsOfInstr (CBZ _ t) = [ id | TBlock id <- [t]]
jumpDestsOfInstr (CBNZ _ t) = [ id | TBlock id <- [t]]
jumpDestsOfInstr (J t) = [id | TBlock id <- [t]]
jumpDestsOfInstr (B t) = [id | TBlock id <- [t]]
jumpDestsOfInstr (BL t _ _) = [ id | TBlock id <- [t]]
jumpDestsOfInstr (BCOND _ t) = [ id | TBlock id <- [t]]
jumpDestsOfInstr _ = []
patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr
patchJumpInstr instr patchF
= case instr of
ANN d i -> ANN d (patchJumpInstr i patchF)
CBZ r (TBlock bid) -> CBZ r (TBlock (patchF bid))
CBNZ r (TBlock bid) -> CBNZ r (TBlock (patchF bid))
J (TBlock bid) -> J (TBlock (patchF bid))
B (TBlock bid) -> B (TBlock (patchF bid))
BL (TBlock bid) ps rs -> BL (TBlock (patchF bid)) ps rs
BCOND c (TBlock bid) -> BCOND c (TBlock (patchF bid))
_ -> pprPanic "patchJumpInstr" (text $ show instr)
mkSpillInstr
:: HasCallStack
=> NCGConfig
-> Reg
-> Int
-> Int
-> [Instr]
mkSpillInstr config reg delta slot =
case (spillSlotToOffset config slot) delta of
imm | 256 <= imm && imm <= 255 -> [ mkStrSp imm ]
imm | imm > 0 && imm .&. 0x7 == 0x0 && imm <= 0xfff -> [ mkStrSp imm ]
imm | imm > 0xfff && imm <= 0xffffff && imm .&. 0x7 == 0x0 -> [ mkIp0SpillAddr (imm .&~. 0xfff)
, mkStrIp0 (imm .&. 0xfff)
]
imm -> pprPanic "mkSpillInstr" (text "Unable to spill into" <+> int imm)
where
a .&~. b = a .&. (complement b)
fmt = case reg of
RegReal (RealRegSingle n) | n < 32 -> II64
_ -> FF64
mkIp0SpillAddr imm = ANN (text "Spill: IP0 <- SP + " <> int imm) $ ADD ip0 sp (OpImm (ImmInt imm))
mkStrSp imm = ANN (text "Spill@" <> int (off delta)) $ STR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 31) (ImmInt imm)))
mkStrIp0 imm = ANN (text "Spill@" <> int (off delta)) $ STR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 16) (ImmInt imm)))
off = spillSlotToOffset config slot
mkLoadInstr
:: NCGConfig
-> Reg
-> Int
-> Int
-> [Instr]
mkLoadInstr config reg delta slot =
case (spillSlotToOffset config slot) delta of
imm | 256 <= imm && imm <= 255 -> [ mkLdrSp imm ]
imm | imm > 0 && imm .&. 0x7 == 0x0 && imm <= 0xfff -> [ mkLdrSp imm ]
imm | imm > 0xfff && imm <= 0xffffff && imm .&. 0x7 == 0x0 -> [ mkIp0SpillAddr (imm .&~. 0xfff)
, mkLdrIp0 (imm .&. 0xfff)
]
imm -> pprPanic "mkSpillInstr" (text "Unable to spill into" <+> int imm)
where
a .&~. b = a .&. (complement b)
fmt = case reg of
RegReal (RealRegSingle n) | n < 32 -> II64
_ -> FF64
mkIp0SpillAddr imm = ANN (text "Reload: IP0 <- SP + " <> int imm) $ ADD ip0 sp (OpImm (ImmInt imm))
mkLdrSp imm = ANN (text "Reload@" <> int (off delta)) $ LDR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 31) (ImmInt imm)))
mkLdrIp0 imm = ANN (text "Reload@" <> int (off delta)) $ LDR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 16) (ImmInt imm)))
off = spillSlotToOffset config slot
takeDeltaInstr :: Instr -> Maybe Int
takeDeltaInstr (ANN _ i) = takeDeltaInstr i
takeDeltaInstr (DELTA i) = Just i
takeDeltaInstr _ = Nothing
isMetaInstr :: Instr -> Bool
isMetaInstr instr
= case instr of
ANN _ i -> isMetaInstr i
COMMENT{} -> True
MULTILINE_COMMENT{} -> True
LOCATION{} -> True
LDATA{} -> True
NEWBLOCK{} -> True
DELTA{} -> True
PUSH_STACK_FRAME -> True
POP_STACK_FRAME -> True
_ -> False
mkRegRegMoveInstr :: Reg -> Reg -> Instr
mkRegRegMoveInstr src dst = ANN (text "Reg->Reg Move: " <> ppr src <> text " -> " <> ppr dst) $ MOV (OpReg W64 dst) (OpReg W64 src)
takeRegRegMoveInstr :: Instr -> Maybe (Reg,Reg)
takeRegRegMoveInstr _ = Nothing
mkJumpInstr :: BlockId -> [Instr]
mkJumpInstr id = [B (TBlock id)]
mkStackAllocInstr :: Platform -> Int -> [Instr]
mkStackAllocInstr platform n
| n == 0 = []
| n > 0 && n < 4096 = [ ANN (text "Alloc More Stack") $ SUB sp sp (OpImm (ImmInt n)) ]
| n > 0 = ANN (text "Alloc More Stack") (SUB sp sp (OpImm (ImmInt 4095))) : mkStackAllocInstr platform (n 4095)
mkStackAllocInstr _platform n = pprPanic "mkStackAllocInstr" (int n)
mkStackDeallocInstr :: Platform -> Int -> [Instr]
mkStackDeallocInstr platform n
| n == 0 = []
| n > 0 && n < 4096 = [ ANN (text "Dealloc More Stack") $ ADD sp sp (OpImm (ImmInt n)) ]
| n > 0 = ANN (text "Dealloc More Stack") (ADD sp sp (OpImm (ImmInt 4095))) : mkStackDeallocInstr platform (n 4095)
mkStackDeallocInstr _platform n = pprPanic "mkStackDeallocInstr" (int n)
allocMoreStack
:: Platform
-> Int
-> NatCmmDecl statics GHC.CmmToAsm.AArch64.Instr.Instr
-> UniqSM (NatCmmDecl statics GHC.CmmToAsm.AArch64.Instr.Instr, [(BlockId,BlockId)])
allocMoreStack _ _ top@(CmmData _ _) = return (top,[])
allocMoreStack platform slots proc@(CmmProc info lbl live (ListGraph code)) = do
let entries = entryBlocks proc
uniqs <- replicateM (length entries) getUniqueM
let
delta = ((x + stackAlign 1) `quot` stackAlign) * stackAlign
where x = slots * spillSlotSize
alloc = mkStackAllocInstr platform delta
dealloc = mkStackDeallocInstr platform delta
retargetList = (zip entries (map mkBlockId uniqs))
new_blockmap :: LabelMap BlockId
new_blockmap = mapFromList retargetList
insert_stack_insn (BasicBlock id insns)
| Just new_blockid <- mapLookup id new_blockmap
= [ BasicBlock id $ alloc ++ [ B (TBlock new_blockid) ]
, BasicBlock new_blockid block' ]
| otherwise
= [ BasicBlock id block' ]
where
block' = foldr insert_dealloc [] insns
insert_dealloc insn r = case insn of
J _ -> dealloc ++ (insn : r)
ANN _ (J _) -> dealloc ++ (insn : r)
_other | jumpDestsOfInstr insn /= []
-> patchJumpInstr insn retarget : r
_other -> insn : r
where retarget b = fromMaybe b (mapLookup b new_blockmap)
new_code = concatMap insert_stack_insn code
return (CmmProc info lbl live (ListGraph new_code), retargetList)
data Instr
= COMMENT SDoc
| MULTILINE_COMMENT SDoc
| ANN SDoc Instr
| LOCATION Int Int Int String
| LDATA Section RawCmmStatics
| NEWBLOCK BlockId
| DELTA Int
| SXTB Operand Operand
| UXTB Operand Operand
| SXTH Operand Operand
| UXTH Operand Operand
| PUSH_STACK_FRAME
| POP_STACK_FRAME
| ADD Operand Operand Operand
| CMN Operand Operand
| CMP Operand Operand
| MSUB Operand Operand Operand Operand
| MUL Operand Operand Operand
| NEG Operand Operand
| SDIV Operand Operand Operand
| SMULH Operand Operand Operand
| SMULL Operand Operand Operand
| SUB Operand Operand Operand
| UDIV Operand Operand Operand
| SBFM Operand Operand Operand Operand
| UBFM Operand Operand Operand Operand
| SBFX Operand Operand Operand Operand
| UBFX Operand Operand Operand Operand
| AND Operand Operand Operand
| ANDS Operand Operand Operand
| ASR Operand Operand Operand
| BIC Operand Operand Operand
| BICS Operand Operand Operand
| EON Operand Operand Operand
| EOR Operand Operand Operand
| LSL Operand Operand Operand
| LSR Operand Operand Operand
| MOV Operand Operand
| MOVK Operand Operand
| MVN Operand Operand
| ORN Operand Operand Operand
| ORR Operand Operand Operand
| ROR Operand Operand Operand
| TST Operand Operand
| STR Format Operand Operand
| LDR Format Operand Operand
| STP Format Operand Operand Operand
| LDP Format Operand Operand Operand
| CSET Operand Cond
| CBZ Operand Target
| CBNZ Operand Target
| J Target
| B Target
| BL Target [Reg] [Reg]
| BCOND Cond Target
| DMBSY
| FCVT Operand Operand
| SCVTF Operand Operand
| FCVTZS Operand Operand
| FABS Operand Operand
instance Show Instr where
show (LDR _f o1 o2) = "LDR " ++ show o1 ++ ", " ++ show o2
show (MOV o1 o2) = "MOV " ++ show o1 ++ ", " ++ show o2
show _ = "missing"
data Target
= TBlock BlockId
| TLabel CLabel
| TReg Reg
data ExtMode
= EUXTB | EUXTH | EUXTW | EUXTX
| ESXTB | ESXTH | ESXTW | ESXTX
deriving (Eq, Show)
data ShiftMode
= SLSL | SLSR | SASR | SROR
deriving (Eq, Show)
type ExtShift = Int
type RegShift = Int
data Operand
= OpReg Width Reg
| OpRegExt Width Reg ExtMode ExtShift
| OpRegShift Width Reg ShiftMode RegShift
| OpImm Imm
| OpImmShift Imm ShiftMode RegShift
| OpAddr AddrMode
deriving (Eq, Show)
opReg :: Width -> Reg -> Operand
opReg = OpReg
xzr, wzr, sp, ip0 :: Operand
xzr = OpReg W64 (RegReal (RealRegSingle (1)))
wzr = OpReg W32 (RegReal (RealRegSingle (1)))
sp = OpReg W64 (RegReal (RealRegSingle 31))
ip0 = OpReg W64 (RegReal (RealRegSingle 16))
_x :: Int -> Operand
_x i = OpReg W64 (RegReal (RealRegSingle i))
x0, x1, x2, x3, x4, x5, x6, x7 :: Operand
x8, x9, x10, x11, x12, x13, x14, x15 :: Operand
x16, x17, x18, x19, x20, x21, x22, x23 :: Operand
x24, x25, x26, x27, x28, x29, x30, x31 :: Operand
x0 = OpReg W64 (RegReal (RealRegSingle 0))
x1 = OpReg W64 (RegReal (RealRegSingle 1))
x2 = OpReg W64 (RegReal (RealRegSingle 2))
x3 = OpReg W64 (RegReal (RealRegSingle 3))
x4 = OpReg W64 (RegReal (RealRegSingle 4))
x5 = OpReg W64 (RegReal (RealRegSingle 5))
x6 = OpReg W64 (RegReal (RealRegSingle 6))
x7 = OpReg W64 (RegReal (RealRegSingle 7))
x8 = OpReg W64 (RegReal (RealRegSingle 8))
x9 = OpReg W64 (RegReal (RealRegSingle 9))
x10 = OpReg W64 (RegReal (RealRegSingle 10))
x11 = OpReg W64 (RegReal (RealRegSingle 11))
x12 = OpReg W64 (RegReal (RealRegSingle 12))
x13 = OpReg W64 (RegReal (RealRegSingle 13))
x14 = OpReg W64 (RegReal (RealRegSingle 14))
x15 = OpReg W64 (RegReal (RealRegSingle 15))
x16 = OpReg W64 (RegReal (RealRegSingle 16))
x17 = OpReg W64 (RegReal (RealRegSingle 17))
x18 = OpReg W64 (RegReal (RealRegSingle 18))
x19 = OpReg W64 (RegReal (RealRegSingle 19))
x20 = OpReg W64 (RegReal (RealRegSingle 20))
x21 = OpReg W64 (RegReal (RealRegSingle 21))
x22 = OpReg W64 (RegReal (RealRegSingle 22))
x23 = OpReg W64 (RegReal (RealRegSingle 23))
x24 = OpReg W64 (RegReal (RealRegSingle 24))
x25 = OpReg W64 (RegReal (RealRegSingle 25))
x26 = OpReg W64 (RegReal (RealRegSingle 26))
x27 = OpReg W64 (RegReal (RealRegSingle 27))
x28 = OpReg W64 (RegReal (RealRegSingle 28))
x29 = OpReg W64 (RegReal (RealRegSingle 29))
x30 = OpReg W64 (RegReal (RealRegSingle 30))
x31 = OpReg W64 (RegReal (RealRegSingle 31))
_d :: Int -> Operand
_d = OpReg W64 . RegReal . RealRegSingle
d0, d1, d2, d3, d4, d5, d6, d7 :: Operand
d8, d9, d10, d11, d12, d13, d14, d15 :: Operand
d16, d17, d18, d19, d20, d21, d22, d23 :: Operand
d24, d25, d26, d27, d28, d29, d30, d31 :: Operand
d0 = OpReg W64 (RegReal (RealRegSingle 32))
d1 = OpReg W64 (RegReal (RealRegSingle 33))
d2 = OpReg W64 (RegReal (RealRegSingle 34))
d3 = OpReg W64 (RegReal (RealRegSingle 35))
d4 = OpReg W64 (RegReal (RealRegSingle 36))
d5 = OpReg W64 (RegReal (RealRegSingle 37))
d6 = OpReg W64 (RegReal (RealRegSingle 38))
d7 = OpReg W64 (RegReal (RealRegSingle 39))
d8 = OpReg W64 (RegReal (RealRegSingle 40))
d9 = OpReg W64 (RegReal (RealRegSingle 41))
d10 = OpReg W64 (RegReal (RealRegSingle 42))
d11 = OpReg W64 (RegReal (RealRegSingle 43))
d12 = OpReg W64 (RegReal (RealRegSingle 44))
d13 = OpReg W64 (RegReal (RealRegSingle 45))
d14 = OpReg W64 (RegReal (RealRegSingle 46))
d15 = OpReg W64 (RegReal (RealRegSingle 47))
d16 = OpReg W64 (RegReal (RealRegSingle 48))
d17 = OpReg W64 (RegReal (RealRegSingle 49))
d18 = OpReg W64 (RegReal (RealRegSingle 50))
d19 = OpReg W64 (RegReal (RealRegSingle 51))
d20 = OpReg W64 (RegReal (RealRegSingle 52))
d21 = OpReg W64 (RegReal (RealRegSingle 53))
d22 = OpReg W64 (RegReal (RealRegSingle 54))
d23 = OpReg W64 (RegReal (RealRegSingle 55))
d24 = OpReg W64 (RegReal (RealRegSingle 56))
d25 = OpReg W64 (RegReal (RealRegSingle 57))
d26 = OpReg W64 (RegReal (RealRegSingle 58))
d27 = OpReg W64 (RegReal (RealRegSingle 59))
d28 = OpReg W64 (RegReal (RealRegSingle 60))
d29 = OpReg W64 (RegReal (RealRegSingle 61))
d30 = OpReg W64 (RegReal (RealRegSingle 62))
d31 = OpReg W64 (RegReal (RealRegSingle 63))
opRegUExt :: Width -> Reg -> Operand
opRegUExt W64 r = OpRegExt W64 r EUXTX 0
opRegUExt W32 r = OpRegExt W32 r EUXTW 0
opRegUExt W16 r = OpRegExt W16 r EUXTH 0
opRegUExt W8 r = OpRegExt W8 r EUXTB 0
opRegUExt w _r = pprPanic "opRegUExt" (text $ show w)
opRegSExt :: Width -> Reg -> Operand
opRegSExt W64 r = OpRegExt W64 r ESXTX 0
opRegSExt W32 r = OpRegExt W32 r ESXTW 0
opRegSExt W16 r = OpRegExt W16 r ESXTH 0
opRegSExt W8 r = OpRegExt W8 r ESXTB 0
opRegSExt w _r = pprPanic "opRegSExt" (text $ show w)