{-|
Module      : Htcc.Asm.Intrinsic.Register
Description : Types and classes of the x86_64 registers
Copyright   : (c) roki, 2019
License     : MIT
Maintainer  : falgon53@yahoo.co.jp
Stability   : experimental
Portability : POSIX

Types and classes of the x86_64 registers
-}
module Htcc.Asm.Intrinsic.Register (
    -- * Register class
    IsRegister (..),
    -- * Registers data types
    AccumulatorReg (..),
    BaseReg (..),
    CounterReg (..),
    DataReg (..),
    SrcIndexReg (..),
    DstIndexReg (..),
    BasePtrReg (..),
    StackPtrReg (..),
    ExtendedReg (..),
    Register (..),
    -- * Registers
    rax, eax, ax, ah, al,
    rbx, ebx, bx, bh, bl,
    rcx, ecx, cx, ch, cl,
    rdx, edx, dx, dh, dl,
    rsi, esi, si, sil,
    rdi, edi, di, dil,
    rbp, ebp, bp, bpl,
    rsp, esp, sp, spl,
    rn, rnd, rnw, rnb,
    -- * List of defined registers
    argRegs,
    popRegs
) where

import           Numeric.Natural

-- | The register type class
class Show a => IsRegister a where
    -- | The byte width of the register.
    byteWidth :: a -> Natural

-- | The accumulator register.
data AccumulatorReg = RAX -- ^ Full 64 bits of register
    | EAX -- ^ Lower 32 bits of register
    | AX -- ^ Lower 16 bits of register
    | AH -- ^ Lower 8 bits of register
    | AL -- ^ Upper 8 bits of `AX` register

instance Show AccumulatorReg where
    show :: AccumulatorReg -> String
show RAX = "rax"
    show EAX = "eax"
    show AX  = "ax"
    show AH  = "ah"
    show AL  = "al"

instance IsRegister AccumulatorReg where
    byteWidth :: AccumulatorReg -> Natural
byteWidth RAX = 8
    byteWidth EAX = 4
    byteWidth AX  = 2
    byteWidth AH  = 1
    byteWidth AL  = 1

instance Eq AccumulatorReg where
    == :: AccumulatorReg -> AccumulatorReg -> Bool
(==) = ((Natural -> Bool)
 -> (AccumulatorReg -> Natural) -> AccumulatorReg -> Bool)
-> (AccumulatorReg -> Natural)
-> (Natural -> Bool)
-> AccumulatorReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool)
-> (AccumulatorReg -> Natural) -> AccumulatorReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) AccumulatorReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> AccumulatorReg -> Bool)
-> (AccumulatorReg -> Natural -> Bool)
-> AccumulatorReg
-> AccumulatorReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (AccumulatorReg -> Natural) -> AccumulatorReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AccumulatorReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord AccumulatorReg where
    compare :: AccumulatorReg -> AccumulatorReg -> Ordering
compare = ((Natural -> Ordering)
 -> (AccumulatorReg -> Natural) -> AccumulatorReg -> Ordering)
-> (AccumulatorReg -> Natural)
-> (Natural -> Ordering)
-> AccumulatorReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (AccumulatorReg -> Natural) -> AccumulatorReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) AccumulatorReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> AccumulatorReg -> Ordering)
-> (AccumulatorReg -> Natural -> Ordering)
-> AccumulatorReg
-> AccumulatorReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (AccumulatorReg -> Natural)
-> AccumulatorReg
-> Natural
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AccumulatorReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Base register.
data BaseReg = RBX -- ^ Full 64 bits of register
    | EBX -- ^ Lower 32 bits of register
    | BX -- ^ Lower 16 bits of register
    | BH -- ^ Lower 8 bit register
    | BL -- ^ Upper 8 bit register of `BX` register

instance Show BaseReg where
    show :: BaseReg -> String
show RBX = "rbx"
    show EBX = "ebx"
    show BX  = "bx"
    show BH  = "bh"
    show BL  = "bl"

instance IsRegister BaseReg where
    byteWidth :: BaseReg -> Natural
byteWidth RBX = 8
    byteWidth EBX = 4
    byteWidth BX  = 2
    byteWidth BH  = 1
    byteWidth BL  = 1

instance Eq BaseReg where
    == :: BaseReg -> BaseReg -> Bool
(==) = ((Natural -> Bool) -> (BaseReg -> Natural) -> BaseReg -> Bool)
-> (BaseReg -> Natural) -> (Natural -> Bool) -> BaseReg -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool) -> (BaseReg -> Natural) -> BaseReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) BaseReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> BaseReg -> Bool)
-> (BaseReg -> Natural -> Bool) -> BaseReg -> BaseReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (BaseReg -> Natural) -> BaseReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BaseReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord BaseReg where
    compare :: BaseReg -> BaseReg -> Ordering
compare = ((Natural -> Ordering)
 -> (BaseReg -> Natural) -> BaseReg -> Ordering)
-> (BaseReg -> Natural)
-> (Natural -> Ordering)
-> BaseReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (BaseReg -> Natural) -> BaseReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) BaseReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> BaseReg -> Ordering)
-> (BaseReg -> Natural -> Ordering)
-> BaseReg
-> BaseReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (BaseReg -> Natural) -> BaseReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BaseReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Counter register.
data CounterReg = RCX -- ^ Full 64 bits of register
    | ECX -- ^ Lower 32 bits of register
    | CX -- ^ Lower 16 bits of register
    | CH -- ^ Lower 8 bit register
    | CL -- ^ Upper 8 bit register of `CX` register

instance Show CounterReg where
    show :: CounterReg -> String
show RCX = "rcx"
    show ECX = "ecx"
    show CX  = "cx"
    show CH  = "ch"
    show CL  = "cl"

instance IsRegister CounterReg where
    byteWidth :: CounterReg -> Natural
byteWidth RCX = 8
    byteWidth ECX = 4
    byteWidth CX  = 2
    byteWidth CH  = 1
    byteWidth CL  = 1

instance Eq CounterReg where
    == :: CounterReg -> CounterReg -> Bool
(==) = ((Natural -> Bool)
 -> (CounterReg -> Natural) -> CounterReg -> Bool)
-> (CounterReg -> Natural)
-> (Natural -> Bool)
-> CounterReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool) -> (CounterReg -> Natural) -> CounterReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) CounterReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> CounterReg -> Bool)
-> (CounterReg -> Natural -> Bool)
-> CounterReg
-> CounterReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (CounterReg -> Natural) -> CounterReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CounterReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord CounterReg where
    compare :: CounterReg -> CounterReg -> Ordering
compare = ((Natural -> Ordering)
 -> (CounterReg -> Natural) -> CounterReg -> Ordering)
-> (CounterReg -> Natural)
-> (Natural -> Ordering)
-> CounterReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (CounterReg -> Natural) -> CounterReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) CounterReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> CounterReg -> Ordering)
-> (CounterReg -> Natural -> Ordering)
-> CounterReg
-> CounterReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (CounterReg -> Natural) -> CounterReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CounterReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Data register.
data DataReg = RDX -- ^ Full 64 bits of register
    | EDX -- ^ Lower 32 bits of register
    | DX -- ^ Lower 16 bits of register
    | DH -- ^ Lower 8 bit register
    | DL -- ^ Upper 8 bit register of `DX` register

instance Show DataReg where
    show :: DataReg -> String
show RDX = "rdx"
    show EDX = "edx"
    show DX  = "dx"
    show DH  = "dh"
    show DL  = "dl"

instance IsRegister DataReg where
    byteWidth :: DataReg -> Natural
byteWidth RDX = 8
    byteWidth EDX = 4
    byteWidth DX  = 2
    byteWidth DH  = 1
    byteWidth DL  = 1

instance Eq DataReg where
    == :: DataReg -> DataReg -> Bool
(==) = ((Natural -> Bool) -> (DataReg -> Natural) -> DataReg -> Bool)
-> (DataReg -> Natural) -> (Natural -> Bool) -> DataReg -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool) -> (DataReg -> Natural) -> DataReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) DataReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> DataReg -> Bool)
-> (DataReg -> Natural -> Bool) -> DataReg -> DataReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (DataReg -> Natural) -> DataReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DataReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord DataReg where
    compare :: DataReg -> DataReg -> Ordering
compare = ((Natural -> Ordering)
 -> (DataReg -> Natural) -> DataReg -> Ordering)
-> (DataReg -> Natural)
-> (Natural -> Ordering)
-> DataReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (DataReg -> Natural) -> DataReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) DataReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> DataReg -> Ordering)
-> (DataReg -> Natural -> Ordering)
-> DataReg
-> DataReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (DataReg -> Natural) -> DataReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DataReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Source Index register.
data SrcIndexReg = RSI -- ^ Full 64 bits of register
    | ESI -- ^ Lower 32 bits of register
    | SI -- ^ Lower 16 bits of register
    | SIL -- ^ Lower 8 bits of register

instance Show SrcIndexReg where
    show :: SrcIndexReg -> String
show RSI = "rsi"
    show ESI = "esi"
    show SI  = "si"
    show SIL = "sil"

instance IsRegister SrcIndexReg where
    byteWidth :: SrcIndexReg -> Natural
byteWidth RSI = 8
    byteWidth ESI = 4
    byteWidth SI  = 2
    byteWidth SIL = 1

instance Eq SrcIndexReg where
    == :: SrcIndexReg -> SrcIndexReg -> Bool
(==) = ((Natural -> Bool)
 -> (SrcIndexReg -> Natural) -> SrcIndexReg -> Bool)
-> (SrcIndexReg -> Natural)
-> (Natural -> Bool)
-> SrcIndexReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool)
-> (SrcIndexReg -> Natural) -> SrcIndexReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) SrcIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> SrcIndexReg -> Bool)
-> (SrcIndexReg -> Natural -> Bool)
-> SrcIndexReg
-> SrcIndexReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (SrcIndexReg -> Natural) -> SrcIndexReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord SrcIndexReg where
    compare :: SrcIndexReg -> SrcIndexReg -> Ordering
compare = ((Natural -> Ordering)
 -> (SrcIndexReg -> Natural) -> SrcIndexReg -> Ordering)
-> (SrcIndexReg -> Natural)
-> (Natural -> Ordering)
-> SrcIndexReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (SrcIndexReg -> Natural) -> SrcIndexReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) SrcIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> SrcIndexReg -> Ordering)
-> (SrcIndexReg -> Natural -> Ordering)
-> SrcIndexReg
-> SrcIndexReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (SrcIndexReg -> Natural) -> SrcIndexReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SrcIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Destination Index register.
data DstIndexReg = RDI -- ^ Full 64 bits of register
    | EDI -- ^ Lower 32 bits of register
    | DI -- ^ Lower 16 bits of register
    | DIL -- ^ Lower 8 bits of register

instance Show DstIndexReg where
    show :: DstIndexReg -> String
show RDI = "rdi"
    show EDI = "edi"
    show DI  = "di"
    show DIL = "dil"

instance IsRegister DstIndexReg where
    byteWidth :: DstIndexReg -> Natural
byteWidth RDI = 8
    byteWidth EDI = 4
    byteWidth DI  = 2
    byteWidth DIL = 1

instance Eq DstIndexReg where
    == :: DstIndexReg -> DstIndexReg -> Bool
(==) = ((Natural -> Bool)
 -> (DstIndexReg -> Natural) -> DstIndexReg -> Bool)
-> (DstIndexReg -> Natural)
-> (Natural -> Bool)
-> DstIndexReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool)
-> (DstIndexReg -> Natural) -> DstIndexReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) DstIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> DstIndexReg -> Bool)
-> (DstIndexReg -> Natural -> Bool)
-> DstIndexReg
-> DstIndexReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (DstIndexReg -> Natural) -> DstIndexReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DstIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord DstIndexReg where
    compare :: DstIndexReg -> DstIndexReg -> Ordering
compare = ((Natural -> Ordering)
 -> (DstIndexReg -> Natural) -> DstIndexReg -> Ordering)
-> (DstIndexReg -> Natural)
-> (Natural -> Ordering)
-> DstIndexReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (DstIndexReg -> Natural) -> DstIndexReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) DstIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> DstIndexReg -> Ordering)
-> (DstIndexReg -> Natural -> Ordering)
-> DstIndexReg
-> DstIndexReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (DstIndexReg -> Natural) -> DstIndexReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DstIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Base Pointer register.
data BasePtrReg = RBP -- ^ Full 64 bits of register
    | EBP -- ^ Lower 32 bits of register
    | BP -- ^ Lower 16 bits of register
    | BPL -- ^ Lower 8 bits of register

instance Show BasePtrReg where
    show :: BasePtrReg -> String
show RBP = "rbp"
    show EBP = "ebp"
    show BP  = "bp"
    show BPL = "bpl"

instance IsRegister BasePtrReg where
    byteWidth :: BasePtrReg -> Natural
byteWidth RBP = 8
    byteWidth EBP = 4
    byteWidth BP  = 2
    byteWidth BPL = 1

instance Eq BasePtrReg where
    == :: BasePtrReg -> BasePtrReg -> Bool
(==) = ((Natural -> Bool)
 -> (BasePtrReg -> Natural) -> BasePtrReg -> Bool)
-> (BasePtrReg -> Natural)
-> (Natural -> Bool)
-> BasePtrReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool) -> (BasePtrReg -> Natural) -> BasePtrReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) BasePtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> BasePtrReg -> Bool)
-> (BasePtrReg -> Natural -> Bool)
-> BasePtrReg
-> BasePtrReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (BasePtrReg -> Natural) -> BasePtrReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BasePtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord BasePtrReg where
    compare :: BasePtrReg -> BasePtrReg -> Ordering
compare = ((Natural -> Ordering)
 -> (BasePtrReg -> Natural) -> BasePtrReg -> Ordering)
-> (BasePtrReg -> Natural)
-> (Natural -> Ordering)
-> BasePtrReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (BasePtrReg -> Natural) -> BasePtrReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) BasePtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> BasePtrReg -> Ordering)
-> (BasePtrReg -> Natural -> Ordering)
-> BasePtrReg
-> BasePtrReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (BasePtrReg -> Natural) -> BasePtrReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BasePtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The Stack Pointer register.
data StackPtrReg = RSP -- ^ Full 64 bits of register
    | ESP -- ^ Lower 32 bits of register
    | SP -- ^ Lower 16 bits of register
    | SPL -- ^ Lower 8 bits of register

instance Show StackPtrReg where
    show :: StackPtrReg -> String
show RSP = "rsp"
    show ESP = "esp"
    show SP  = "sp"
    show SPL = "spl"

instance IsRegister StackPtrReg where
    byteWidth :: StackPtrReg -> Natural
byteWidth RSP = 8
    byteWidth ESP = 4
    byteWidth SP  = 2
    byteWidth SPL = 1

instance Eq StackPtrReg where
    == :: StackPtrReg -> StackPtrReg -> Bool
(==) = ((Natural -> Bool)
 -> (StackPtrReg -> Natural) -> StackPtrReg -> Bool)
-> (StackPtrReg -> Natural)
-> (Natural -> Bool)
-> StackPtrReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool)
-> (StackPtrReg -> Natural) -> StackPtrReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) StackPtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> StackPtrReg -> Bool)
-> (StackPtrReg -> Natural -> Bool)
-> StackPtrReg
-> StackPtrReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (StackPtrReg -> Natural) -> StackPtrReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackPtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord StackPtrReg where
    compare :: StackPtrReg -> StackPtrReg -> Ordering
compare = ((Natural -> Ordering)
 -> (StackPtrReg -> Natural) -> StackPtrReg -> Ordering)
-> (StackPtrReg -> Natural)
-> (Natural -> Ordering)
-> StackPtrReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (StackPtrReg -> Natural) -> StackPtrReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) StackPtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> StackPtrReg -> Ordering)
-> (StackPtrReg -> Natural -> Ordering)
-> StackPtrReg
-> StackPtrReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (StackPtrReg -> Natural) -> StackPtrReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackPtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The extended general-purpose register (r8-r15).
data ExtendedReg = Rn Int -- ^ Full 64 bits of register
    | RnD Int -- ^ Lower 32 bits of register
    | RnW Int -- ^ Lower 16 bits of register
    | RnB Int -- ^ Lower 8 bits of register

instance Show ExtendedReg where
    show :: ExtendedReg -> String
show (Rn x :: Int
x)
        | Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 8 Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 15 = "r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x
        | Bool
otherwise = ShowS
forall a. HasCallStack => String -> a
error ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ "Extended registers should be " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ["r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ ", " | Int
n <- [8..14] :: [Int]] String -> ShowS
forall a. [a] -> [a] -> [a]
++ "or r15."
    show (RnD x :: Int
x)
        | Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 8 Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 15 = "r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "d"
        | Bool
otherwise = ShowS
forall a. HasCallStack => String -> a
error ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ "Extended registers should be " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ["r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ "d, " | Int
n <- [8..14] :: [Int]] String -> ShowS
forall a. [a] -> [a] -> [a]
++ "or r15d."
    show (RnW x :: Int
x)
        | Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 8 Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 15 = "r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "w"
        | Bool
otherwise = ShowS
forall a. HasCallStack => String -> a
error ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ "Extended registers should be " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ["r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ "w, " | Int
n <- [8..14] :: [Int]] String -> ShowS
forall a. [a] -> [a] -> [a]
++ "or r15w."
    show (RnB x :: Int
x)
        | Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 8 Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 15 = "r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "b"
        | Bool
otherwise = ShowS
forall a. HasCallStack => String -> a
error ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ "Extended registers should be " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ["r" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ "b, " | Int
n <- [8..14] :: [Int]] String -> ShowS
forall a. [a] -> [a] -> [a]
++ "or r15b."

instance IsRegister ExtendedReg where
    byteWidth :: ExtendedReg -> Natural
byteWidth (Rn _)  = 8
    byteWidth (RnD _) = 4
    byteWidth (RnW _) = 2
    byteWidth (RnB _) = 1

instance Bounded ExtendedReg where
    minBound :: ExtendedReg
minBound = Int -> ExtendedReg
Rn 8
    maxBound :: ExtendedReg
maxBound = Int -> ExtendedReg
Rn 15

instance Eq ExtendedReg where
    == :: ExtendedReg -> ExtendedReg -> Bool
(==) = ((Natural -> Bool)
 -> (ExtendedReg -> Natural) -> ExtendedReg -> Bool)
-> (ExtendedReg -> Natural)
-> (Natural -> Bool)
-> ExtendedReg
-> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool)
-> (ExtendedReg -> Natural) -> ExtendedReg -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ExtendedReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> ExtendedReg -> Bool)
-> (ExtendedReg -> Natural -> Bool)
-> ExtendedReg
-> ExtendedReg
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (ExtendedReg -> Natural) -> ExtendedReg -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord ExtendedReg where
    compare :: ExtendedReg -> ExtendedReg -> Ordering
compare = ((Natural -> Ordering)
 -> (ExtendedReg -> Natural) -> ExtendedReg -> Ordering)
-> (ExtendedReg -> Natural)
-> (Natural -> Ordering)
-> ExtendedReg
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (ExtendedReg -> Natural) -> ExtendedReg -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ExtendedReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> ExtendedReg -> Ordering)
-> (ExtendedReg -> Natural -> Ordering)
-> ExtendedReg
-> ExtendedReg
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (ExtendedReg -> Natural) -> ExtendedReg -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

-- | The registers.
data Register = Accumulator AccumulatorReg -- ^ The accumulator
    | Base BaseReg -- ^ The base
    | Counter CounterReg -- ^ The conuter
    | Data DataReg -- ^ The data
    | SrcIndex SrcIndexReg -- ^ The source index
    | DstIndex DstIndexReg -- ^ The destination index
    | BasePtr BasePtrReg -- ^ The base pointer index
    | StackPtr StackPtrReg -- ^ The stack pointer index
    | Extended  ExtendedReg -- ^ The extended general-purpose

instance Show Register where
    show :: Register -> String
show (Accumulator x :: AccumulatorReg
x) = AccumulatorReg -> String
forall a. Show a => a -> String
show AccumulatorReg
x
    show (Base x :: BaseReg
x)        = BaseReg -> String
forall a. Show a => a -> String
show BaseReg
x
    show (Counter x :: CounterReg
x)     = CounterReg -> String
forall a. Show a => a -> String
show CounterReg
x
    show (Data x :: DataReg
x)        = DataReg -> String
forall a. Show a => a -> String
show DataReg
x
    show (SrcIndex x :: SrcIndexReg
x)    = SrcIndexReg -> String
forall a. Show a => a -> String
show SrcIndexReg
x
    show (DstIndex x :: DstIndexReg
x)    = DstIndexReg -> String
forall a. Show a => a -> String
show DstIndexReg
x
    show (BasePtr x :: BasePtrReg
x)     = BasePtrReg -> String
forall a. Show a => a -> String
show BasePtrReg
x
    show (StackPtr x :: StackPtrReg
x)    = StackPtrReg -> String
forall a. Show a => a -> String
show StackPtrReg
x
    show (Extended x :: ExtendedReg
x)    = ExtendedReg -> String
forall a. Show a => a -> String
show ExtendedReg
x

instance IsRegister Register where
    byteWidth :: Register -> Natural
byteWidth (Accumulator x :: AccumulatorReg
x) = AccumulatorReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth AccumulatorReg
x
    byteWidth (Base x :: BaseReg
x)        = BaseReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth BaseReg
x
    byteWidth (Counter x :: CounterReg
x)     = CounterReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth CounterReg
x
    byteWidth (Data x :: DataReg
x)        = DataReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth DataReg
x
    byteWidth (SrcIndex x :: SrcIndexReg
x)    = SrcIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth SrcIndexReg
x
    byteWidth (DstIndex x :: DstIndexReg
x)    = DstIndexReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth DstIndexReg
x
    byteWidth (BasePtr x :: BasePtrReg
x)     = BasePtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth BasePtrReg
x
    byteWidth (StackPtr x :: StackPtrReg
x)    = StackPtrReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth StackPtrReg
x
    byteWidth (Extended x :: ExtendedReg
x)    = ExtendedReg -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ExtendedReg
x

instance Eq Register where
    == :: Register -> Register -> Bool
(==) = ((Natural -> Bool) -> (Register -> Natural) -> Register -> Bool)
-> (Register -> Natural) -> (Natural -> Bool) -> Register -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Bool) -> (Register -> Natural) -> Register -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) Register -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Bool) -> Register -> Bool)
-> (Register -> Natural -> Bool) -> Register -> Register -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Natural -> Natural -> Bool)
-> (Register -> Natural) -> Register -> Natural -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Register -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

instance Ord Register where
    compare :: Register -> Register -> Ordering
compare = ((Natural -> Ordering)
 -> (Register -> Natural) -> Register -> Ordering)
-> (Register -> Natural)
-> (Natural -> Ordering)
-> Register
-> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Natural -> Ordering)
-> (Register -> Natural) -> Register -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) Register -> Natural
forall a. IsRegister a => a -> Natural
byteWidth ((Natural -> Ordering) -> Register -> Ordering)
-> (Register -> Natural -> Ordering)
-> Register
-> Register
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> Natural -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Natural -> Natural -> Ordering)
-> (Register -> Natural) -> Register -> Natural -> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Register -> Natural
forall a. IsRegister a => a -> Natural
byteWidth

{-# INLINE rax #-}
-- | The rax register.
rax :: Register
rax :: Register
rax = AccumulatorReg -> Register
Accumulator AccumulatorReg
RAX

{-# INLINE eax #-}
-- | The eax register. Lower 32 bits of `rax`.
eax :: Register
eax :: Register
eax = AccumulatorReg -> Register
Accumulator AccumulatorReg
EAX

{-# INLINE ax #-}
-- | The ax register. Lower 16 bits of `rax`.
ax :: Register
ax :: Register
ax = AccumulatorReg -> Register
Accumulator AccumulatorReg
AX

{-# INLINE ah #-}
-- | The ah register. Lower 8 bits of `rax`.
ah :: Register
ah :: Register
ah = AccumulatorReg -> Register
Accumulator AccumulatorReg
AH

{-# INLINE al #-}
-- | The al register. Upper 8 bits of `ax`.
al :: Register
al :: Register
al = AccumulatorReg -> Register
Accumulator AccumulatorReg
AL

{-# INLINE rbx #-}
-- | The rbx register.
rbx :: Register
rbx :: Register
rbx = BaseReg -> Register
Base BaseReg
RBX

{-# INLINE ebx #-}
-- | The ebx register. Lower 32 bits of `rbx`.
ebx :: Register
ebx :: Register
ebx = BaseReg -> Register
Base BaseReg
RBX

{-# INLINE bx #-}
-- | The bx register. Lower 16 bits of `rbx`.
bx :: Register
bx :: Register
bx = BaseReg -> Register
Base BaseReg
BX

{-# INLINE bh #-}
-- | The bh register. Lower 8 bits of `rbx`.
bh :: Register
bh :: Register
bh = BaseReg -> Register
Base BaseReg
BH

{-# INLINE bl #-}
-- | The bl register. Upper 8 bits of `bx`.
bl :: Register
bl :: Register
bl = BaseReg -> Register
Base BaseReg
BL

{-# INLINE rcx #-}
-- | The rcx register.
rcx :: Register
rcx :: Register
rcx = CounterReg -> Register
Counter CounterReg
RCX

{-# INLINE ecx #-}
-- | The ecx register. Lower 32 bis of `rcx`.
ecx :: Register
ecx :: Register
ecx = CounterReg -> Register
Counter CounterReg
ECX

{-# INLINE cx #-}
-- | The cx register. Lower 16 bits of `rcx`.
cx :: Register
cx :: Register
cx = CounterReg -> Register
Counter CounterReg
CX

{-# INLINE ch #-}
-- | The ch register. Lower 8 bits of `rcx`.
ch :: Register
ch :: Register
ch = CounterReg -> Register
Counter CounterReg
CH

{-# INLINE cl #-}
-- | The cl register. Upper 8 bits of `cx`.
cl :: Register
cl :: Register
cl = CounterReg -> Register
Counter CounterReg
CL

{-# INLINE rdx #-}
-- | The rdx register.
rdx :: Register
rdx :: Register
rdx = DataReg -> Register
Data DataReg
RDX

{-# INLINE edx #-}
-- | The edx register. Lower 32 bits of `rdx`.
edx :: Register
edx :: Register
edx = DataReg -> Register
Data DataReg
EDX

{-# INLINE dx #-}
-- | The dx register. Lower 16 bits of `rdx`.
dx :: Register
dx :: Register
dx = DataReg -> Register
Data DataReg
DX

{-# INLINE dh #-}
-- | The dh register. Lower 8 bits of `rbx`.
dh :: Register
dh :: Register
dh = DataReg -> Register
Data DataReg
DH

{-# INLINE dl #-}
-- | The dl register. Upper 8 bits of `dx`.
dl :: Register
dl :: Register
dl = DataReg -> Register
Data DataReg
DL

{-# INLINE rsi #-}
-- | The rsi register.
rsi :: Register
rsi :: Register
rsi = SrcIndexReg -> Register
SrcIndex SrcIndexReg
RSI

{-# INLINE esi #-}
-- | The esi register. Lower 32 bits of `rsi`.
esi :: Register
esi :: Register
esi = SrcIndexReg -> Register
SrcIndex SrcIndexReg
ESI

{-# INLINE si #-}
-- | The si register. Lower 16 bits of `rsi`.
si :: Register
si :: Register
si = SrcIndexReg -> Register
SrcIndex SrcIndexReg
SI

{-# INLINE sil #-}
-- | The sil register. Lower 8 bits of `rsi`.
sil :: Register
sil :: Register
sil = SrcIndexReg -> Register
SrcIndex SrcIndexReg
SIL

{-# INLINE rdi #-}
-- | The rdi register.
rdi :: Register
rdi :: Register
rdi = DstIndexReg -> Register
DstIndex DstIndexReg
RDI

{-# INLINE edi #-}
-- | The edi register. Lower 32 bits of `rdi`.
edi :: Register
edi :: Register
edi = DstIndexReg -> Register
DstIndex DstIndexReg
EDI

{-# INLINE di #-}
-- | The di register. Lower 16 bits of `rdi`.
di :: Register
di :: Register
di = DstIndexReg -> Register
DstIndex DstIndexReg
DI

{-# INLINE dil #-}
-- | The dil register. Lower 8 bits of `rdi`.
dil :: Register
dil :: Register
dil = DstIndexReg -> Register
DstIndex DstIndexReg
DIL

{-# INLINE rbp #-}
-- | The rbp register.
rbp :: Register
rbp :: Register
rbp = BasePtrReg -> Register
BasePtr BasePtrReg
RBP

{-# INLINE ebp #-}
-- | The ebp register. Lower 32 bits of `rbp`.
ebp :: Register
ebp :: Register
ebp = BasePtrReg -> Register
BasePtr BasePtrReg
EBP

{-# INLINE bp #-}
-- | The bp register. Lower 16 bits of `rbp`.
bp :: Register
bp :: Register
bp = BasePtrReg -> Register
BasePtr BasePtrReg
BP

{-# INLINE bpl #-}
-- | The bpl register. Lower 8 bits of `rbp`.
bpl :: Register
bpl :: Register
bpl = BasePtrReg -> Register
BasePtr BasePtrReg
BPL

{-# INLINE rsp #-}
-- | The rsp register.
rsp :: Register
rsp :: Register
rsp = StackPtrReg -> Register
StackPtr StackPtrReg
RSP

{-# INLINE esp #-}
-- | The esp register. Lower 32 bits of `rsp`.
esp :: Register
esp :: Register
esp = StackPtrReg -> Register
StackPtr StackPtrReg
ESP

{-# INLINE sp #-}
-- | The sp register. Lower 16 bits of `rsp`.
sp :: Register
sp :: Register
sp = StackPtrReg -> Register
StackPtr StackPtrReg
SP

{-# INLINE spl #-}
-- | The spl register. Lower 8 bits of `rsp`.
spl :: Register
spl :: Register
spl = StackPtrReg -> Register
StackPtr StackPtrReg
SPL

{-# INLINE rn #-}
-- | The rn register (r8-r15).
rn :: Int -> Register
rn :: Int -> Register
rn = ExtendedReg -> Register
Extended (ExtendedReg -> Register)
-> (Int -> ExtendedReg) -> Int -> Register
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ExtendedReg
Rn

{-# INLINE rnd #-}
-- | The rnd register (r8d-r15d). Lower 32 bits of `rn`.
rnd :: Int -> Register
rnd :: Int -> Register
rnd = ExtendedReg -> Register
Extended (ExtendedReg -> Register)
-> (Int -> ExtendedReg) -> Int -> Register
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ExtendedReg
RnD

{-# INLINE rnw #-}
-- | The rnw register (r8w-r15w). Lower 16 bits of `rn`.
rnw :: Int -> Register
rnw :: Int -> Register
rnw = ExtendedReg -> Register
Extended (ExtendedReg -> Register)
-> (Int -> ExtendedReg) -> Int -> Register
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ExtendedReg
RnW

{-# INLINE rnb #-}
-- | The rnb register (r8b-r15b). Lower 8 bits of `rn`.
rnb :: Int -> Register
rnb :: Int -> Register
rnb = ExtendedReg -> Register
Extended (ExtendedReg -> Register)
-> (Int -> ExtendedReg) -> Int -> Register
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ExtendedReg
RnB

{-# INLINE argRegs #-}
-- | `argRegs` is a list of each @Register@ used in the function call.
-- In the list, the registers used for the first to sixth arguments are arranged in ascending order.
argRegs :: [[Register]]
argRegs :: [[Register]]
argRegs = [[Register
dil, Register
di, Register
edi, Register
rdi], [Register
sil, Register
si, Register
esi, Register
rsi], [Register
dl, Register
dx, Register
edx, Register
rdx], [Register
cl, Register
cx, Register
ecx, Register
rcx], [Int -> Register
rnb 8, Int -> Register
rnw 8, Int -> Register
rnd 8, Int -> Register
rn 8], [Int -> Register
rnb 9, Int -> Register
rnw 9, Int -> Register
rnd 9, Int -> Register
rn 9]]

{-# INLINE popRegs #-}
-- | `popRegs` is a list of registers used to @pop@ arguments from the stack in function calls.
-- This is equivalent to the following, but is defined explicitly for reducing time completity.
--
-- >>> popRegs 3 == map maximum (reverse (take 3 argRegs))
popRegs :: Int -> [Register]
popRegs :: Int -> [Register]
popRegs = (Int -> [Register] -> [Register])
-> [Register] -> Int -> [Register]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [Register] -> [Register]
forall a. Int -> [a] -> [a]
drop [Int -> Register
rn 9, Int -> Register
rn 8, Register
rcx, Register
rdx, Register
rsi, Register
rdi] (Int -> [Register]) -> (Int -> Int) -> Int -> [Register]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (6Int -> Int -> Int
forall a. Num a => a -> a -> a
-)