{-# LANGUAGE FlexibleInstances #-}

module X86.Instruction (Instruction, canonicalize, addressof) where

import           Base (orElse)
import           Data.Word (Word64)
import           Generic.Address (AddressWord64(..), GenericAddress (..))
import           Generic.Instruction (GenericInstruction(..))
import           Generic.Operand (GenericOperand(..))
import           Generic.HasSize (HasSize(sizeof))
import           X86.Opcode (Opcode(..), isCall, isJump, isCondJump, isRet, isHalt)
import           X86.Prefix (Prefix)
import           X86.Register (Register(..))

type Instruction = GenericInstruction AddressWord64 Register Prefix Opcode Int

instance HasSize Instruction where
  sizeof :: Instruction -> Int
sizeof Instruction
i = Instruction -> Maybe Int
forall label storage prefix opcode annotation.
GenericInstruction label storage prefix opcode annotation
-> Maybe annotation
annot Instruction
i Maybe Int -> Int -> Int
forall a. Eq a => Maybe a -> a -> a
`orElse` Int
0

addressof :: GenericInstruction AddressWord64 storage prefix opcode annotation
-> Word64
addressof (Instruction (AddressWord64 Word64
a) Maybe prefix
_ opcode
_ Maybe (GenericOperand storage)
_ [GenericOperand storage]
_ Maybe annotation
_) = Word64
a

-- | Canonicalizes an instruction by making sure there is at most one output and inputs/outputs are syntactically clear.
-- | For example, the IMUL instruction comes in different flavors that hide the actual inputs and outputs to multiple registers
canonicalize :: Instruction -> [Instruction]
canonicalize :: Instruction -> [Instruction]
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
PUSH Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1] Maybe Int
annot) =
  let si :: Int
si = GenericOperand Register -> Int
forall a. HasSize a => a -> Int
sizeof GenericOperand Register
op1
  in [ AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         AddressWord64
label
         Maybe Prefix
prefix
         Opcode
SUB
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RSP)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RSP, Word64 -> GenericOperand Register
forall storage. Word64 -> GenericOperand storage
Immediate (Word64 -> GenericOperand Register)
-> Word64 -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
si]
         Maybe Int
annot
     , AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         AddressWord64
label
         Maybe Prefix
prefix
         Opcode
MOV
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ GenericAddress Register -> Int -> GenericOperand Register
forall storage.
GenericAddress storage -> Int -> GenericOperand storage
Memory (Register -> GenericAddress Register
forall storage. storage -> GenericAddress storage
AddressStorage Register
RSP) Int
si)
         [GenericOperand Register
op1]
         Maybe Int
forall a. Maybe a
Nothing]
-- POP
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
POP Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1] Maybe Int
annot) =
  let si :: Int
si = GenericOperand Register -> Int
forall a. HasSize a => a -> Int
sizeof GenericOperand Register
op1
  in [ AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         AddressWord64
label
         Maybe Prefix
prefix
         Opcode
MOV
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
op1)
         [GenericAddress Register -> Int -> GenericOperand Register
forall storage.
GenericAddress storage -> Int -> GenericOperand storage
Memory (Register -> GenericAddress Register
forall storage. storage -> GenericAddress storage
AddressStorage Register
RSP) Int
si]
         Maybe Int
annot
     , AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         AddressWord64
label
         Maybe Prefix
prefix
         Opcode
ADD
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RSP)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RSP, Word64 -> GenericOperand Register
forall storage. Word64 -> GenericOperand storage
Immediate (Word64 -> GenericOperand Register)
-> Word64 -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
si]
         Maybe Int
forall a. Maybe a
Nothing]
-- LEAVE 
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
LEAVE Maybe (GenericOperand Register)
Nothing [] Maybe Int
annot) =
  AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RSP) [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RBP] Maybe Int
annot
  Instruction -> [Instruction] -> [Instruction]
forall a. a -> [a] -> [a]
:Instruction -> [Instruction]
canonicalize (AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
POP Maybe (GenericOperand Register)
forall a. Maybe a
Nothing [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RBP] Maybe Int
annot)
-- XCHG
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
XCHG Maybe (GenericOperand Register)
Nothing [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot) =
  [
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
TEMP) [GenericOperand Register
dst] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
dst) [GenericOperand Register
src] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
src) [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
TEMP] Maybe Int
annot
  ]
-- XADD
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
XADD Maybe (GenericOperand Register)
Nothing [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot) =
  [
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
ADD (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
TEMP) [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
src) [GenericOperand Register
dst] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
MOV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
dst) [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
TEMP] Maybe Int
annot
  ]
-- CMPXCHG
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
CMPXCHG Maybe (GenericOperand Register)
Nothing [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot) =
  [
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
CMPXCHG (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
RAX) [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
CMPXCHG (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ GenericOperand Register
dst) [GenericOperand Register
dst,GenericOperand Register
src] Maybe Int
annot
  ]
-- XGETBV
canonicalize (Instruction AddressWord64
label Maybe Prefix
prefix Opcode
XGETBV Maybe (GenericOperand Register)
Nothing [] Maybe Int
annot) =
  [
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
XGETBV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
EDX) [] Maybe Int
annot,
    AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
XGETBV (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage Register
EAX) [] Maybe Int
annot
  ]
-- The remaining cases
canonicalize i :: Instruction
i@(Instruction AddressWord64
label Maybe Prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
Nothing [GenericOperand Register]
ops Maybe Int
annot)
  | Opcode
mnemonic Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Opcode
CBW, Opcode
CWDE, Opcode
CDQE] = Instruction -> [Instruction]
forall label storage prefix annotation.
GenericInstruction label storage prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_sextend1 Instruction
i
  | Opcode
mnemonic Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Opcode
CWD, Opcode
CDQ, Opcode
CQO] = Instruction -> [Instruction]
forall label storage prefix annotation.
GenericInstruction label storage prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_sextend2 Instruction
i
  | Opcode
mnemonic Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Opcode
MUL, Opcode
IMUL] = Instruction -> [Instruction]
forall label prefix annotation.
GenericInstruction label Register prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_mul Instruction
i
  | Opcode
mnemonic Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Opcode
DIV, Opcode
IDIV] = Instruction -> [Instruction]
forall label prefix annotation.
GenericInstruction label Register prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_div Instruction
i
  | Opcode
mnemonic Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Opcode
MOVS,Opcode
MOVSB,Opcode
MOVSW,Opcode
MOVSD,Opcode
MOVSQ] Bool -> Bool -> Bool
&& Maybe Prefix
prefix Maybe Prefix -> Maybe Prefix -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Prefix
forall a. Maybe a
Nothing Bool -> Bool -> Bool
&& [GenericOperand Register] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [GenericOperand Register]
ops Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 = 
    [AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
mnemonic (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ [GenericOperand Register] -> GenericOperand Register
forall a. [a] -> a
head [GenericOperand Register]
ops) ([GenericOperand Register] -> [GenericOperand Register]
forall a. [a] -> [a]
tail [GenericOperand Register]
ops) Maybe Int
annot]
  | Opcode -> Bool
mnemonic_reads_from_all_operands Opcode
mnemonic =
    [AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
mnemonic (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ [GenericOperand Register] -> GenericOperand Register
forall a. [a] -> a
head [GenericOperand Register]
ops) [GenericOperand Register]
ops Maybe Int
annot]
  | Opcode -> Bool
mnemonic_reads_from_all_but_first_operands Opcode
mnemonic =
    [AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
mnemonic (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ [GenericOperand Register] -> GenericOperand Register
forall a. [a] -> a
head [GenericOperand Register]
ops) ([GenericOperand Register] -> [GenericOperand Register]
forall a. [a] -> [a]
tail [GenericOperand Register]
ops) Maybe Int
annot]
  | Opcode -> Bool
remove_destination Opcode
mnemonic = [AddressWord64
-> Maybe Prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe Int
-> Instruction
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction AddressWord64
label Maybe Prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
forall a. Maybe a
Nothing [] Maybe Int
annot]
  | Opcode -> Bool
do_not_modify Opcode
mnemonic = [Instruction
i]
  | Bool
otherwise = [Char] -> [Instruction]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [Instruction]) -> [Char] -> [Instruction]
forall a b. (a -> b) -> a -> b
$ [Char]
"Cannot canonicalize instruction: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Instruction -> [Char]
forall a. Show a => a -> [Char]
show Instruction
i
canonicalize Instruction
_ = [Char] -> [Instruction]
forall a. HasCallStack => [Char] -> a
error [Char]
"Unknown instruction"

-- CBW / CWDE / CDQE
canonicalize_sextend1 :: GenericInstruction label storage prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_sextend1 (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand storage)
Nothing [] Maybe annotation
annot) =
  let srcs :: [Register]
srcs = case Opcode
mnemonic of
        Opcode
CBW  -> [Register
AX, Register
AL]
        Opcode
CWDE -> [Register
EAX, Register
AX]
        Opcode
CDQE -> [Register
RAX, Register
EAX]
        Opcode
_    -> [Char] -> [Register]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid extend sources"
  in [ label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         Opcode
mnemonic
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1]
         Maybe annotation
annot]
canonicalize_sextend1 GenericInstruction label storage prefix Opcode annotation
_ = [Char]
-> [GenericInstruction label Register prefix Opcode annotation]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid extend instruction"

-- CWD / CDQ / CQO
canonicalize_sextend2 :: GenericInstruction label storage prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_sextend2 (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand storage)
Nothing [] Maybe annotation
annot) =
  let srcs :: [Register]
srcs = case Opcode
mnemonic of
        Opcode
CWD -> [Register
DX, Register
AX]
        Opcode
CDQ -> [Register
EDX, Register
EAX]
        Opcode
CQO -> [Register
RDX, Register
RAX]
        Opcode
_   -> [Char] -> [Register]
forall a. HasCallStack => [Char] -> a
error [Char]
"invalid extends source"
  in [ label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         Opcode
mnemonic
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1]
         Maybe annotation
annot ]
canonicalize_sextend2 GenericInstruction label storage prefix Opcode annotation
_ = [Char]
-> [GenericInstruction label Register prefix Opcode annotation]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid extend instruction"

-- MUL /IMUL (1)
canonicalize_mul :: GenericInstruction label Register prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_mul (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1] Maybe annotation
annot) =
  let srcs :: [Register]
srcs = case GenericOperand Register -> Int
forall a. HasSize a => a -> Int
sizeof GenericOperand Register
op1 of
        Int
8 -> [Register
RDX, Register
RAX]
        Int
4 -> [Register
EDX, Register
EAX]
        Int
2 -> [Register
DX, Register
AX]
        Int
1 -> [Register
AH, Register
AL]
        Int
_ -> [Char] -> [Register]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid operand size"
  in [ label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         (Opcode -> Opcode
hipart Opcode
mnemonic)
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1, GenericOperand Register
op1]
         Maybe annotation
annot
     , label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         (Opcode -> Opcode
lowpart Opcode
mnemonic)
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1, GenericOperand Register
op1]
         Maybe annotation
forall a. Maybe a
Nothing]
-- MUL /IMUL (2)
canonicalize_mul (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1, GenericOperand Register
op2] Maybe annotation
annot) =
  [label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction label
label Maybe prefix
prefix Opcode
mnemonic (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
op1) [GenericOperand Register
op1, GenericOperand Register
op2] Maybe annotation
annot]
-- MUL /IMUL (3)
canonicalize_mul
  (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1, GenericOperand Register
op2, GenericOperand Register
op3] Maybe annotation
annot) =
  [label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction label
label Maybe prefix
prefix Opcode
mnemonic (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just GenericOperand Register
op1) [GenericOperand Register
op2, GenericOperand Register
op3] Maybe annotation
annot]
canonicalize_mul GenericInstruction label Register prefix Opcode annotation
_ = [Char]
-> [GenericInstruction label Register prefix Opcode annotation]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid mul operation"

-- DIV /IDIV (1)
canonicalize_div :: GenericInstruction label Register prefix Opcode annotation
-> [GenericInstruction label Register prefix Opcode annotation]
canonicalize_div (Instruction label
label Maybe prefix
prefix Opcode
mnemonic Maybe (GenericOperand Register)
Nothing [GenericOperand Register
op1] Maybe annotation
annot) =
  let srcs :: [Register]
srcs = case GenericOperand Register -> Int
forall a. HasSize a => a -> Int
sizeof GenericOperand Register
op1 of
        Int
8 -> [Register
RDX, Register
RAX]
        Int
4 -> [Register
EDX, Register
EAX]
        Int
2 -> [Register
DX, Register
AX]
        Int
1 -> [Register
AH, Register
AL]
        Int
_ -> [Char] -> [Register]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid operand size"
  in [ label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         (Opcode -> Opcode
hipart Opcode
mnemonic)
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs, Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1, GenericOperand Register
op1]
         Maybe annotation
annot
     , label
-> Maybe prefix
-> Opcode
-> Maybe (GenericOperand Register)
-> [GenericOperand Register]
-> Maybe annotation
-> GenericInstruction label Register prefix Opcode annotation
forall label storage prefix opcode annotation.
label
-> Maybe prefix
-> opcode
-> Maybe (GenericOperand storage)
-> [GenericOperand storage]
-> Maybe annotation
-> GenericInstruction label storage prefix opcode annotation
Instruction
         label
label
         Maybe prefix
prefix
         (Opcode -> Opcode
lowpart Opcode
mnemonic)
         (GenericOperand Register -> Maybe (GenericOperand Register)
forall a. a -> Maybe a
Just (GenericOperand Register -> Maybe (GenericOperand Register))
-> GenericOperand Register -> Maybe (GenericOperand Register)
forall a b. (a -> b) -> a -> b
$ Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1)
         [Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register] -> Register
forall a. [a] -> a
head [Register]
srcs, Register -> GenericOperand Register
forall storage. storage -> GenericOperand storage
Storage (Register -> GenericOperand Register)
-> Register -> GenericOperand Register
forall a b. (a -> b) -> a -> b
$ [Register]
srcs [Register] -> Int -> Register
forall a. [a] -> Int -> a
!! Int
1, GenericOperand Register
op1]
         Maybe annotation
forall a. Maybe a
Nothing]
canonicalize_div GenericInstruction label Register prefix Opcode annotation
_ = [Char]
-> [GenericInstruction label Register prefix Opcode annotation]
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid div instruction"

-- Does the instruction read from all operands, inlcuding the first one?
mnemonic_reads_from_all_operands :: Opcode -> Bool
mnemonic_reads_from_all_operands Opcode
mnemonic = Opcode
mnemonic
  Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Opcode
ADD
         , Opcode
SUB
         , Opcode
NEG
         , Opcode
INC
         , Opcode
DEC
         , Opcode
ADC
         , Opcode
SBB
         , Opcode
ROL
         , Opcode
ROR
         , Opcode
SHL
         , Opcode
SHR
         , Opcode
SAL
         , Opcode
SAR
         , Opcode
SHLD
         , Opcode
SHRD
         , Opcode
XOR
         , Opcode
OR
         , Opcode
AND
         , Opcode
NOT
         , Opcode
BT
         , Opcode
BTC
         , Opcode
BTR
         , Opcode
BTS
         , Opcode
BSWAP
         , Opcode
XORPD
         , Opcode
XORPS
         , Opcode
SUBPS
         , Opcode
ANDPD
         , Opcode
ANDNPD
         , Opcode
ORPD
         , Opcode
SUBPD
         , Opcode
ADDPD
         , Opcode
HADDPD
         , Opcode
MINSD
         , Opcode
MAXSD
         , Opcode
POR
         , Opcode
PAND
         , Opcode
PANDN
         , Opcode
PXOR
         , Opcode
VPOR
         , Opcode
VPAND
         , Opcode
VPANDN
         , Opcode
VPXOR
         , Opcode
PUNPCKLQDQ
         , Opcode
PUNPCKLBW
         , Opcode
PUNPCKLDQ
         , Opcode
PCMPGTD
         , Opcode
PCMPEQB
         , Opcode
PCMPEQD
         , Opcode
PCMPGTB
         , Opcode
PCMPGTD
         , Opcode
PADDD
         , Opcode
PADDB
         , Opcode
PADDQ
         , Opcode
PSUBD
         , Opcode
PSUBB
         , Opcode
PSUBQ
         , Opcode
PMULLD
         , Opcode
PMINSD
         , Opcode
PMAXSD
         , Opcode
PMINUD
         , Opcode
PMAXUD
         , Opcode
PMAXUQ
         , Opcode
PMAXUQ
         , Opcode
PMULUDQ
         , Opcode
PSRLD
         , Opcode
PSRLW
         , Opcode
PSRLDQ
         , Opcode
PSLLDQ
         , Opcode
PSLLD
         , Opcode
PSLLQ
         , Opcode
PSRLQ
         , Opcode
PSUBUSB
         , Opcode
PSUBUSW
         , Opcode
PINSRB
         , Opcode
PINSRQ
         , Opcode
PINSRD
         , Opcode
PEXTRB
         , Opcode
PEXTRD
         , Opcode
PEXTRQ
         , Opcode
PBLENDW
         , Opcode
PCLMULQDQ
         , Opcode
PACKSSDW
         , Opcode
PACKSSWB
         , Opcode
PHADDD 
         , Opcode
SUBSS
         , Opcode
ADDSS
         , Opcode
DIVSS
         , Opcode
MULSS
         , Opcode
ROUNDSS
         , Opcode
SUBSD
         , Opcode
ADDSD
         , Opcode
DIVSD
         , Opcode
MULSD
         , Opcode
ROUNDSD
         , Opcode
UNPCKLPD
         , Opcode
CMOVO
         , Opcode
CMOVNO
         , Opcode
CMOVS
         , Opcode
CMOVNS
         , Opcode
CMOVE
         , Opcode
CMOVZ
         , Opcode
CMOVNE
         , Opcode
CMOVNZ
         , Opcode
CMOVB
         , Opcode
CMOVNAE
         , Opcode
CMOVC
         , Opcode
CMOVNB
         , Opcode
CMOVAE
         , Opcode
CMOVNC
         , Opcode
CMOVBE
         , Opcode
CMOVNA
         , Opcode
CMOVA
         , Opcode
CMOVNBE
         , Opcode
CMOVL
         , Opcode
CMOVNGE
         , Opcode
CMOVG
         , Opcode
CMOVGE
         , Opcode
CMOVNL
         , Opcode
CMOVLE
         , Opcode
CMOVNG
         , Opcode
CMOVNLE
         , Opcode
CMOVP
         , Opcode
CMOVPE
         , Opcode
CMOVNP
         , Opcode
CMOVPO

      ]

-- Does the instruction read from all operands, except for the first one?
mnemonic_reads_from_all_but_first_operands :: Opcode -> Bool
mnemonic_reads_from_all_but_first_operands Opcode
mnemonic = Opcode
mnemonic
  Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Opcode
LEA
         , Opcode
MOV
         , Opcode
MOVZX
         , Opcode
MOVSX
         , Opcode
MOVSXD
         , Opcode
MOVAPS
         , Opcode
MOVAPD
         , Opcode
MOVABS
         , Opcode
MOVUPD
         , Opcode
MOVUPS
         , Opcode
MOVDQU
         , Opcode
MOVDQA
         , Opcode
MOVD
         , Opcode
MOVQ
         , Opcode
MOVLPD
         , Opcode
MOVLPS
         , Opcode
MOVSD
         , Opcode
MOVSS
         , Opcode
MOVHPD
         , Opcode
MOVHPS
         , Opcode
VMOVD
         , Opcode
VMOVAPD
         , Opcode
VMOVAPS
         , Opcode
SETO
         , Opcode
SETNO
         , Opcode
SETS
         , Opcode
SETNS
         , Opcode
SETE
         , Opcode
SETZ
         , Opcode
SETNE
         , Opcode
SETNZ
         , Opcode
SETB
         , Opcode
SETNAE
         , Opcode
SETC
         , Opcode
SETNB
         , Opcode
SETAE
         , Opcode
SETNC
         , Opcode
SETBE
         , Opcode
SETNA
         , Opcode
SETA
         , Opcode
SETNBE
         , Opcode
SETL
         , Opcode
SETNGE
         , Opcode
SETGE
         , Opcode
SETNL
         , Opcode
SETLE
         , Opcode
SETNG
         , Opcode
SETG
         , Opcode
SETNLE
         , Opcode
SETP
         , Opcode
SETPE
         , Opcode
SETNP
         , Opcode
SETPO
         , Opcode
BSR
         , Opcode
BSF
         , Opcode
CVTSS2SD
         , Opcode
CVTSI2SS
         , Opcode
CVTSI2SD
         , Opcode
CVTSD2SS
         , Opcode
CVTTSS2SI
         , Opcode
CVTTSD2SI
         , Opcode
CVTTPD2DQ
         , Opcode
CVTDQ2PD
         , Opcode
MOVMSKPD
         , Opcode
MOVMSKPS
         , Opcode
PMOVSXDQ
         , Opcode
PMOVZXDQ
         , Opcode
PMOVSXBD
         , Opcode
PMOVZXBD
         , Opcode
UNPCKLPS
         , Opcode
BLENDVPD
         , Opcode
BLENDVPS
         , Opcode
EXTRACTPS
         , Opcode
VINSERTF128
         , Opcode
VEXTRACTI128
         , Opcode
VEXTRACTF128
         , Opcode
VPERM2F128
         , Opcode
VPERM2I128
         , Opcode
VPALIGNR
         , Opcode
PALIGNR
         , Opcode
SHUFPS
         , Opcode
PSHUFB
         , Opcode
PSHUFD
         , Opcode
VPSHUFB
         , Opcode
VPSHUFD
         , Opcode
PSHUFLW
         , Opcode
STOS,Opcode
STOSB,Opcode
STOSD,Opcode
STOSQ
         , Opcode
FST, Opcode
FSTP, Opcode
FIST, Opcode
FISTP, Opcode
FISTTP
         , Opcode
FSTCW, Opcode
FNSTCW
        ]

-- Does the instruction not make state change?
-- For example, NOP or ENDBR64
remove_destination :: Opcode -> Bool
remove_destination :: Opcode -> Bool
remove_destination Opcode
mnemonic =
  Opcode
mnemonic
  Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Opcode
NOP
         , Opcode
ENDBR64
         , Opcode
UD2
         , Opcode
WAIT
         , Opcode
MFENCE
         , Opcode
CLFLUSH
         , Opcode
COMISD, Opcode
UCOMISD
         -- ST registers are not considered state
         , Opcode
FILD, Opcode
FLD, Opcode
FXCH
         , Opcode
FADD, Opcode
FADDP, Opcode
FIADD
         , Opcode
FSUB, Opcode
FSUBP, Opcode
FISUB
         , Opcode
FSUBR, Opcode
FSUBRP, Opcode
FISUBR
         , Opcode
FMUL, Opcode
FMULP, Opcode
FIMUL
         , Opcode
FDIV, Opcode
FDIVP, Opcode
FIDIV
         , Opcode
FDIVR, Opcode
FDIVRP, Opcode
FIDIVR
         , Opcode
FCOMI, Opcode
FCOMIP, Opcode
FUCOMI, Opcode
FUCOMIP
         , Opcode
FLDCW, Opcode
FCHS, Opcode
FLDZ, Opcode
FLD1, Opcode
FLDPI
         , Opcode
FCMOVB, Opcode
FCMOVE, Opcode
FCMOVBE, Opcode
FCMOVU, Opcode
FCMOVNB, Opcode
FCMOVNE, Opcode
FCMOVNBE, Opcode
FCMOVNU
         , Opcode
SCAS, Opcode
SCASB, Opcode
SCASD
         , Opcode
EMMS
         , Opcode
CLD
     ]

-- Does the instruction need no modification?
-- For example, instructions without destination (CMP, TEST) or function calls and returns.
do_not_modify :: Opcode -> Bool
do_not_modify :: Opcode -> Bool
do_not_modify Opcode
mnemonic = Opcode -> Bool
isCall Opcode
mnemonic
  Bool -> Bool -> Bool
|| Opcode -> Bool
isJump Opcode
mnemonic
  Bool -> Bool -> Bool
|| Opcode -> Bool
isCondJump Opcode
mnemonic
  Bool -> Bool -> Bool
|| Opcode -> Bool
isRet Opcode
mnemonic
  Bool -> Bool -> Bool
|| Opcode -> Bool
isHalt Opcode
mnemonic
  Bool -> Bool -> Bool
|| Opcode
mnemonic
  Opcode -> [Opcode] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Opcode
CMP
         , Opcode
TEST
         , Opcode
CMPS
         , Opcode
CMPSB
         , Opcode
CMPSW
         , Opcode
CMPSD
         , Opcode
PTEST
         , Opcode
UCOMISS
         , Opcode
COMISS
         , Opcode
UCOMISD
         , Opcode
CMPLTSD
         , Opcode
CMPEQSD
         , Opcode
CMPNEQSD
         , Opcode
CMPEQSD
         , Opcode
CMPLTSD
         , Opcode
CMPNLESD
         , Opcode
CMPNEQSD
         , Opcode
CMPNLESD
         ]
-- TODO:
-- BLENDVP, BLENDVPS read from XMM0 sometimes as well?
-- VANDPS: depends on number of operands (3 or 2)
-- SYSRET

lowpart :: Opcode -> Opcode
lowpart Opcode
IMUL = Opcode
IMUL_LO
lowpart Opcode
MUL  = Opcode
MUL_LO
lowpart Opcode
IDIV = Opcode
IDIV_LO
lowpart Opcode
DIV  = Opcode
DIV_LO
hipart :: Opcode -> Opcode
hipart Opcode
IMUL  = Opcode
IMUL_HI
hipart Opcode
MUL   = Opcode
MUL_HI
hipart Opcode
IDIV  = Opcode
IDIV_HI
hipart Opcode
DIV   = Opcode
DIV_HI