harpy 0.4.1 → 0.4.2
raw patch · 6 files changed
+659/−3304 lines, 6 filesdep +disassemblerdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: disassembler
Dependency ranges changed: base
API changes (from Hackage documentation)
- Harpy.Call: conv[a126I] :: FunPtr () -> IO ()
- Harpy.Call: conv[a128f] :: FunPtr (Word32 -> Word32) -> Word32 -> IO Word32
- Harpy.Call: conv[a12dF] :: FunPtr (Ptr a[a12dy] -> Ptr b[a12dz] -> Ptr c[a12dA] -> Ptr d[a12dB] -> Ptr e[a12dC] -> Ptr f[a12dD] -> Ptr g[a12dE] -> ()) -> Ptr a[a12dy] -> Ptr b[a12dz] -> Ptr c[a12dA] -> Ptr d[a12dB] -> Ptr e[a12dC] -> Ptr f[a12dD] -> Ptr g[a12dE] -> IO ()
- Harpy.X86Assembler: instance Eq XMMReg
- Harpy.X86Assembler: instance Ord XMMReg
- Harpy.X86Disassembler: instance Eq InstrOperandSize
- Harpy.X86Disassembler: instance Eq Instruction
- Harpy.X86Disassembler: instance Eq Opcode
- Harpy.X86Disassembler: instance Eq Operand
- Harpy.X86Disassembler: instance Show InstrOperandSize
- Harpy.X86Disassembler: instance Show Instruction
- Harpy.X86Disassembler: instance Show Opcode
+ Harpy.Call: conv[aaAB] :: FunPtr () -> IO ()
+ Harpy.Call: conv[aaC8] :: FunPtr (Word32 -> Word32) -> Word32 -> IO Word32
+ Harpy.Call: conv[aaHy] :: FunPtr (Ptr a[aaHr] -> Ptr b[aaHs] -> Ptr c[aaHt] -> Ptr d[aaHu] -> Ptr e[aaHv] -> Ptr f[aaHw] -> Ptr g[aaHx] -> ()) -> Ptr a[aaHr] -> Ptr b[aaHs] -> Ptr c[aaHt] -> Ptr d[aaHu] -> Ptr e[aaHv] -> Ptr f[aaHw] -> Ptr g[aaHx] -> IO ()
+ Harpy.X86Assembler: class Faddp a b
+ Harpy.X86Assembler: class Fdivp a b
+ Harpy.X86Assembler: class Fiadd a b
+ Harpy.X86Assembler: class Fidiv a b
+ Harpy.X86Assembler: class Fimul a b
+ Harpy.X86Assembler: class Fisub a b
+ Harpy.X86Assembler: class Fmulp a b
+ Harpy.X86Assembler: class Fsubp a b
+ Harpy.X86Assembler: class Loop a
+ Harpy.X86Assembler: class Movlps a b
+ Harpy.X86Assembler: class Movss a b
+ Harpy.X86Assembler: class Movups a b
+ Harpy.X86Assembler: class (XMMLocation b) => XMMLoc a b | a -> b
+ Harpy.X86Assembler: cvtdq2ps :: (XMMLoc xmm a) => XMMReg -> xmm -> CodeGen e s ()
+ Harpy.X86Assembler: cvttps2dq :: (XMMLoc xmm a) => XMMReg -> xmm -> CodeGen e s ()
+ Harpy.X86Assembler: faddp :: (Faddp a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fdivp :: (Fdivp a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fiadd16 :: (Fiadd a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fiadd32 :: (Fiadd a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fidiv16 :: (Fidiv a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fidiv32 :: (Fidiv a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fimul16 :: (Fimul a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fimul32 :: (Fimul a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fisub16 :: (Fisub a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fisub32 :: (Fisub a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fmulp :: (Fmulp a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: fsubp :: (Fsubp a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: haddpd :: (XMMLoc xmm a) => XMMReg -> xmm -> CodeGen e s ()
+ Harpy.X86Assembler: haddps :: (XMMLoc xmm a) => XMMReg -> xmm -> CodeGen e s ()
+ Harpy.X86Assembler: instance Cmp (Disp, Reg32) (Ptr a)
+ Harpy.X86Assembler: instance Cmp Addr (Ptr a)
+ Harpy.X86Assembler: instance Cmp Ind (Ptr a)
+ Harpy.X86Assembler: instance Cmp Reg32 (Ptr a)
+ Harpy.X86Assembler: instance Fadd FPReg FPTopReg
+ Harpy.X86Assembler: instance Faddp FPReg FPTopReg
+ Harpy.X86Assembler: instance Fdiv FPReg FPTopReg
+ Harpy.X86Assembler: instance Fdivp FPReg FPTopReg
+ Harpy.X86Assembler: instance Fiadd FPTopReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Fiadd FPTopReg Ind
+ Harpy.X86Assembler: instance Fidiv FPTopReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Fidiv FPTopReg Ind
+ Harpy.X86Assembler: instance Fimul FPTopReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Fimul FPTopReg Ind
+ Harpy.X86Assembler: instance Fisub FPTopReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Fisub FPTopReg Ind
+ Harpy.X86Assembler: instance Fmul FPReg FPTopReg
+ Harpy.X86Assembler: instance Fmulp FPReg FPTopReg
+ Harpy.X86Assembler: instance Fsub FPReg FPTopReg
+ Harpy.X86Assembler: instance Fsubp FPReg FPTopReg
+ Harpy.X86Assembler: instance Ja (Ptr a)
+ Harpy.X86Assembler: instance Jae (Ptr a)
+ Harpy.X86Assembler: instance Jb (Ptr a)
+ Harpy.X86Assembler: instance Jbe (Ptr a)
+ Harpy.X86Assembler: instance Jc (Ptr a)
+ Harpy.X86Assembler: instance Je (Ptr a)
+ Harpy.X86Assembler: instance Jg (Ptr a)
+ Harpy.X86Assembler: instance Jge (Ptr a)
+ Harpy.X86Assembler: instance Jl (Ptr a)
+ Harpy.X86Assembler: instance Jle (Ptr a)
+ Harpy.X86Assembler: instance Jna (Ptr a)
+ Harpy.X86Assembler: instance Jnae (Ptr a)
+ Harpy.X86Assembler: instance Jnb (Ptr a)
+ Harpy.X86Assembler: instance Jnbe (Ptr a)
+ Harpy.X86Assembler: instance Jnc (Ptr a)
+ Harpy.X86Assembler: instance Jne (Ptr a)
+ Harpy.X86Assembler: instance Jng (Ptr a)
+ Harpy.X86Assembler: instance Jnge (Ptr a)
+ Harpy.X86Assembler: instance Jnl (Ptr a)
+ Harpy.X86Assembler: instance Jnle (Ptr a)
+ Harpy.X86Assembler: instance Jno (Ptr a)
+ Harpy.X86Assembler: instance Jnp (Ptr a)
+ Harpy.X86Assembler: instance Jns (Ptr a)
+ Harpy.X86Assembler: instance Jnz (Ptr a)
+ Harpy.X86Assembler: instance Jo (Ptr a)
+ Harpy.X86Assembler: instance Jp (Ptr a)
+ Harpy.X86Assembler: instance Jpe (Ptr a)
+ Harpy.X86Assembler: instance Jpo (Ptr a)
+ Harpy.X86Assembler: instance Js (Ptr a)
+ Harpy.X86Assembler: instance Jz (Ptr a)
+ Harpy.X86Assembler: instance Loop Label
+ Harpy.X86Assembler: instance Loop Word8
+ Harpy.X86Assembler: instance Mov (Disp, Reg32) (Ptr a)
+ Harpy.X86Assembler: instance Mov (Disp, Reg32, Reg32, Scale) (Ptr a)
+ Harpy.X86Assembler: instance Mov (Disp, Reg32, Scale) (Ptr a)
+ Harpy.X86Assembler: instance Mov (Reg32, Reg32, Scale) (Ptr a)
+ Harpy.X86Assembler: instance Mov Addr (Ptr a)
+ Harpy.X86Assembler: instance Mov Ind (Ptr a)
+ Harpy.X86Assembler: instance Mov Reg32 (Ptr a)
+ Harpy.X86Assembler: instance Movlps (Disp, Reg32) XMMReg
+ Harpy.X86Assembler: instance Movlps Addr XMMReg
+ Harpy.X86Assembler: instance Movlps Ind XMMReg
+ Harpy.X86Assembler: instance Movlps XMMReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Movlps XMMReg Addr
+ Harpy.X86Assembler: instance Movlps XMMReg Ind
+ Harpy.X86Assembler: instance Movlps XMMReg XMMReg
+ Harpy.X86Assembler: instance Movss (Disp, Reg32) XMMReg
+ Harpy.X86Assembler: instance Movss Addr XMMReg
+ Harpy.X86Assembler: instance Movss Ind XMMReg
+ Harpy.X86Assembler: instance Movss XMMReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Movss XMMReg Addr
+ Harpy.X86Assembler: instance Movss XMMReg Ind
+ Harpy.X86Assembler: instance Movss XMMReg XMMReg
+ Harpy.X86Assembler: instance Movups (Disp, Reg32) XMMReg
+ Harpy.X86Assembler: instance Movups Addr XMMReg
+ Harpy.X86Assembler: instance Movups Ind XMMReg
+ Harpy.X86Assembler: instance Movups XMMReg (Disp, Reg32)
+ Harpy.X86Assembler: instance Movups XMMReg Addr
+ Harpy.X86Assembler: instance Movups XMMReg Ind
+ Harpy.X86Assembler: instance Movups XMMReg XMMReg
+ Harpy.X86Assembler: instance XMMLoc (Disp, Reg32) MemBase
+ Harpy.X86Assembler: instance XMMLoc Addr Mem
+ Harpy.X86Assembler: instance XMMLoc Ind MemBase
+ Harpy.X86Assembler: instance XMMLoc XMMReg XMMReg
+ Harpy.X86Assembler: movlps :: (Movlps a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: movss :: (Movss a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: movups :: (Movups a b) => a -> b -> CodeGen e s ()
+ Harpy.X86Assembler: ptrToInt :: Ptr a -> Int
+ Harpy.X86Assembler: ptrToWord32 :: Ptr a -> Word32
+ Harpy.X86Assembler: shufpd :: (XMMLoc xmm a) => XMMReg -> xmm -> Word8 -> CodeGen e s ()
+ Harpy.X86Assembler: shufps :: (XMMLoc xmm a) => XMMReg -> xmm -> Word8 -> CodeGen e s ()
+ Harpy.X86Assembler: xmmLocLowLevel :: (XMMLoc a b) => a -> b
+ Harpy.X86CodeGen: FInt16 :: FIntSize
+ Harpy.X86CodeGen: FInt32 :: FIntSize
+ Harpy.X86CodeGen: FInt64 :: FIntSize
+ Harpy.X86CodeGen: Mem :: Word32 -> Mem
+ Harpy.X86CodeGen: MemBase :: Word8 -> Word32 -> MemBase
+ Harpy.X86CodeGen: XMMReg :: Word8 -> XMMReg
+ Harpy.X86CodeGen: class XMMLocation xmm
+ Harpy.X86CodeGen: data FIntSize
+ Harpy.X86CodeGen: data MemBase
+ Harpy.X86CodeGen: instance Eq XMMReg
+ Harpy.X86CodeGen: instance Ord XMMReg
+ Harpy.X86CodeGen: instance XMMLocation Mem
+ Harpy.X86CodeGen: instance XMMLocation MemBase
+ Harpy.X86CodeGen: instance XMMLocation XMMReg
+ Harpy.X86CodeGen: newtype Mem
+ Harpy.X86CodeGen: newtype XMMReg
+ Harpy.X86CodeGen: x86_branch_pointer :: Int -> Ptr a -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_cvtdq2ps :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_cvttps2dq :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fdecstp :: CodeGen e s ()
+ Harpy.X86CodeGen: x86_fincstp :: CodeGen e s ()
+ Harpy.X86CodeGen: x86_haddpd :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_haddps :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movlpd_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movlpd_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movlps_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movlps_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movsd_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movsd_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movss_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movss_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movupd_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movupd_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movups_from_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_movups_to_reg :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_shufpd :: (XMMLocation xmm) => Word8 -> xmm -> Word8 -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_shufps :: (XMMLocation xmm) => Word8 -> xmm -> Word8 -> CodeGen e s ()
+ Harpy.X86CodeGen: xmm_location_emit :: (XMMLocation xmm) => Word8 -> xmm -> CodeGen e s ()
- Harpy.X86Assembler: loop :: Word8 -> CodeGen e s ()
+ Harpy.X86Assembler: loop :: (Loop a) => a -> CodeGen e s ()
- Harpy.X86Assembler: loope :: Word8 -> CodeGen e s ()
+ Harpy.X86Assembler: loope :: (Loop a) => a -> CodeGen e s ()
- Harpy.X86Assembler: loopne :: Word8 -> CodeGen e s ()
+ Harpy.X86Assembler: loopne :: (Loop a) => a -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fild :: Word32 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fild :: Word32 -> FIntSize -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fild_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fild_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fist_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fist_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fist_pop :: Word32 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fist_pop :: Word32 -> FIntSize -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fist_pop_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fist_pop_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()
- Harpy.X86CodeGen: x86_fp_op_reg :: Int -> Word8 -> Bool -> CodeGen e s ()
+ Harpy.X86CodeGen: x86_fp_op_reg :: Word8 -> Word8 -> Bool -> CodeGen e s ()
- Harpy.X86Disassembler: data InstrOperandSize
+ Harpy.X86Disassembler: data InstrOperandSize :: *
- Harpy.X86Disassembler: data Instruction
+ Harpy.X86Disassembler: data Instruction :: *
- Harpy.X86Disassembler: data Opcode
+ Harpy.X86Disassembler: data Opcode :: *
- Harpy.X86Disassembler: data Operand
+ Harpy.X86Disassembler: data Operand :: *
- Harpy.X86Disassembler: data ShowStyle
+ Harpy.X86Disassembler: data ShowStyle :: *
Files
- Harpy/CodeGenMonad.hs +15/−19
- Harpy/X86Assembler.hs +371/−18
- Harpy/X86CodeGen.hs +222/−29
- Harpy/X86Disassembler.hs +20/−3233
- NEWS +23/−0
- harpy.cabal +8/−5
Harpy/CodeGenMonad.hs view
@@ -452,11 +452,11 @@ performFixup :: Ptr Word8 -> Int -> FixupEntry -> CodeGen e s () performFixup labBuf labOfs (FixupEntry{fueBuffer = buf, fueOfs = ofs, fueKind = knd}) =- do let diff = (labBuf `plusPtr` labOfs) `minusPtr` (buf `plusPtr` (ofs + 4))+ do let diff = (labBuf `plusPtr` labOfs) `minusPtr` (buf `plusPtr` ofs) liftIO $ case knd of- Fixup8 -> pokeByteOff buf ofs (fromIntegral diff :: Word8)- Fixup16 -> pokeByteOff buf ofs (fromIntegral diff :: Word16)- Fixup32 -> pokeByteOff buf ofs (fromIntegral diff :: Word32)+ Fixup8 -> pokeByteOff buf ofs (fromIntegral diff - 1 :: Word8)+ Fixup16 -> pokeByteOff buf ofs (fromIntegral diff - 2 :: Word16)+ Fixup32 -> pokeByteOff buf ofs (fromIntegral diff - 4 :: Word32) Fixup32Absolute -> pokeByteOff buf ofs (fromIntegral (ptrToWordPtr (labBuf `plusPtr` labOfs)) :: Word32) return () @@ -480,14 +480,12 @@ do state <- getInternalState let base = buffer state ptr = bufferOfs state+ fue = FixupEntry{fueBuffer = base,+ fueOfs = ptr + ofs,+ fueKind = knd} case Map.lookup lab (definedLabels state) of- Just (labBuf, labOfs, _) -> performFixup labBuf labOfs (FixupEntry{fueBuffer = base,- fueOfs = ptr + ofs,- fueKind = knd})- Nothing -> setInternalState state{pendingFixups = Map.insertWith (++) lab [FixupEntry{fueBuffer = base,- fueOfs = ptr + ofs,- fueKind = knd}]- (pendingFixups state)}+ Just (labBuf, labOfs, _) -> performFixup labBuf labOfs fue+ Nothing -> setInternalState state{pendingFixups = Map.insertWith (++) lab [fue] (pendingFixups state)} -- | Return the address of a label, fail if the label is not yet defined. labelAddress :: Label -> CodeGen e s (Ptr a)@@ -521,12 +519,10 @@ ins i@(Dis.PseudoInstruction{}) = return [i] ins i@(Dis.Instruction{Dis.address = addr}) = do state <- getInternalState- let labs = Map.toList (definedLabels state)- lab = find (\ (_, (buf, ofs, _)) -> fromIntegral (ptrToWordPtr (buf `plusPtr` ofs)) == addr) labs- case lab of- Nothing -> return [i]- Just (l, (buf, ofs, name)) -> return [Dis.PseudoInstruction addr- (case name of+ let allLabs = Map.toList (definedLabels state)+ labs = filter (\ (_, (buf, ofs, _)) -> fromIntegral (ptrToWordPtr (buf `plusPtr` ofs)) == addr) allLabs+ createLabel (l, (buf, ofs, name)) = Dis.PseudoInstruction addr+ (case name of "" -> "label " ++ show l ++ " [" ++ @@ -534,8 +530,8 @@ "]" _ -> name ++ ": [" ++ hex32 (fromIntegral (ptrToWordPtr (buf `plusPtr` ofs))) ++ - "]"), - i]+ "]")+ return $ fmap createLabel labs ++ [i] hex32 :: Int -> String hex32 i = let w :: Word32
Harpy/X86Assembler.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances,FunctionalDependencies #-} -------------------------------------------------------------------------- -- | -- Module : Harpy.X86Assembler@@ -13,7 +13,10 @@ -- which determines the addressing modes from the types of the -- operands. ---------------------------------------------------------------------------module Harpy.X86Assembler where+module Harpy.X86Assembler (+ module Harpy.X86Assembler,+ XMMReg(..),+ ) where import Harpy.X86CodeGen import Harpy.CodeGenMonad@@ -77,8 +80,10 @@ esi = Reg32 6 edi = Reg32 7 +{- newtype XMMReg = XMMReg Word8 deriving (Eq, Ord)+-} xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 :: XMMReg xmm0 = XMMReg 0@@ -654,6 +659,9 @@ instance Cmp Reg32 Word32 where cmp (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_cmp dest (fromIntegral imm) +instance Cmp Reg32 (Ptr a) where+ cmp (Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_reg_imm x86_cmp dest (ptrToInt ptr)+ instance Cmp Reg32 Label where cmp (Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes@@ -663,6 +671,9 @@ instance Cmp Addr Word32 where cmp (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest (fromIntegral imm) +instance Cmp Addr (Ptr a) where+ cmp (Addr dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest (ptrToWord32 ptr)+ instance Cmp Addr Label where cmp (Addr dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_alu_mem_imm x86_cmp dest 0xf0f0f0f0@@ -671,6 +682,9 @@ instance Cmp (Disp, Reg32) Word32 where cmp (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp (fromIntegral imm) +instance Cmp (Disp, Reg32) (Ptr a) where+ cmp (Disp disp, Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp (ptrToWord32 ptr)+ instance Cmp (Disp, Reg32) Label where cmp (Disp disp, Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest disp 0xf0f0f0f0@@ -679,6 +693,9 @@ instance Cmp Ind Word32 where cmp (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 (fromIntegral imm) +instance Cmp Ind (Ptr a) where+ cmp (Ind (Reg32 dest)) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 (ptrToWord32 ptr)+ instance Cmp Ind Label where cmp (Ind (Reg32 dest)) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_alu_membase_imm x86_cmp dest 0 0xf0f0f0f0@@ -1127,6 +1144,9 @@ instance Mov Reg32 Word32 where mov (Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest (fromIntegral imm) +instance Mov Reg32 (Ptr a) where+ mov (Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest (ptrToWord32 ptr)+ instance Mov Reg32 Label where mov (Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_reg_imm dest 0 emitFixup lab (-4) Fixup32Absolute@@ -1140,6 +1160,9 @@ instance Mov Addr Word32 where mov (Addr dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest imm 4 +instance Mov Addr (Ptr a) where+ mov (Addr dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest (ptrToWord32 ptr) 4+ instance Mov Addr Label where mov (Addr dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_mem_imm dest 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1159,6 +1182,9 @@ instance Mov (Disp, Reg32) Word32 where mov (Disp disp, Reg32 dest) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp imm 4 +instance Mov (Disp, Reg32) (Ptr a) where+ mov (Disp disp, Reg32 dest) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp (ptrToWord32 ptr) 4+ instance Mov (Disp, Reg32) Label where mov (Disp disp, Reg32 dest) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest disp 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1166,6 +1192,9 @@ instance Mov Ind Word32 where mov (Ind (Reg32 dest)) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 imm 4 +instance Mov Ind (Ptr a) where+ mov (Ind (Reg32 dest)) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 (ptrToWord32 ptr) 4+ instance Mov Ind Label where mov (Ind (Reg32 dest)) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_membase_imm dest 0 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1179,6 +1208,9 @@ instance Mov (Reg32, Reg32, Scale) Word32 where mov (Reg32 base, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) imm 4 +instance Mov (Reg32, Reg32, Scale) (Ptr a) where+ mov (Reg32 base, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) (ptrToWord32 ptr) 4+ instance Mov (Reg32, Reg32, Scale) Label where mov (Reg32 base, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm base 0 index (scaleToShift scale) 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1192,6 +1224,9 @@ instance Mov (Disp, Reg32, Scale) Word32 where mov (Disp disp, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) imm 4 +instance Mov (Disp, Reg32, Scale) (Ptr a) where+ mov (Disp disp, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) (ptrToWord32 ptr) 4+ instance Mov (Disp, Reg32, Scale) Label where mov (Disp disp, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm x86_nobasereg disp index (scaleToShift scale) 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1208,6 +1243,10 @@ mov (Disp disp, Reg32 5, Reg32 index, scale) imm = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) imm 4 mov _ _ = onlyEbp +instance Mov (Disp, Reg32, Reg32, Scale) (Ptr a) where+ mov (Disp disp, Reg32 5, Reg32 index, scale) ptr = ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) (ptrToWord32 ptr) 4+ mov _ _ = onlyEbp+ instance Mov (Disp, Reg32, Reg32, Scale) Label where mov (Disp disp, Reg32 5, Reg32 index, scale) lab = do ensureBufferSize x86_max_instruction_bytes >> x86_mov_memindex_imm 5 disp index (scaleToShift scale) 0 4 emitFixup lab (-4) Fixup32Absolute@@ -1539,17 +1578,25 @@ popfd = ensureBufferSize x86_max_instruction_bytes >> x86_popfd --- loop according to ECX couter--loop :: Word8 -> CodeGen e s ()-loop w = ensureBufferSize x86_max_instruction_bytes >> x86_loop w+-- loop according to ECX counter -loope :: Word8 -> CodeGen e s ()-loope w = ensureBufferSize x86_max_instruction_bytes >> x86_loope w+class Loop a where+ loop :: a -> CodeGen e s ()+ loope :: a -> CodeGen e s ()+ loopne :: a -> CodeGen e s () -loopne :: Word8 -> CodeGen e s ()-loopne w = ensureBufferSize x86_max_instruction_bytes >> x86_loopne w+instance Loop Word8 where+ loop w = ensureBufferSize x86_max_instruction_bytes >> x86_loop w+ loope w = ensureBufferSize x86_max_instruction_bytes >> x86_loope w+ loopne w = ensureBufferSize x86_max_instruction_bytes >> x86_loopne w +instance Loop Label where+ loop l = do ensureBufferSize x86_max_instruction_bytes >> x86_loop 0+ emitFixup l (-1) Fixup8+ loope l = do ensureBufferSize x86_max_instruction_bytes >> x86_loope 0+ emitFixup l (-1) Fixup8+ loopne l = do ensureBufferSize x86_max_instruction_bytes >> x86_loopne 0+ emitFixup l (-1) Fixup8 -- jump @@ -1592,6 +1639,9 @@ instance Ja Word32 where ja imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_a imm False +instance Ja (Ptr a) where+ ja ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_a ptr False+ instance Ja Label where ja l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_a 0 False emitFixup l (-4) Fixup32@@ -1605,6 +1655,9 @@ instance Jae Word32 where jae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ae imm False +instance Jae (Ptr a) where+ jae ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ae ptr False+ instance Jae Label where jae l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ae 0 False emitFixup l (-4) Fixup32@@ -1618,6 +1671,9 @@ instance Jb Word32 where jb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_b imm False +instance Jb (Ptr a) where+ jb ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_b ptr False+ instance Jb Label where jb l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_b 0 False emitFixup l (-4) Fixup32@@ -1631,6 +1687,9 @@ instance Jbe Word32 where jbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_be imm False +instance Jbe (Ptr a) where+ jbe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_be ptr False+ instance Jbe Label where jbe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_be 0 False emitFixup l (-4) Fixup32@@ -1644,6 +1703,9 @@ instance Jc Word32 where jc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_c imm False +instance Jc (Ptr a) where+ jc ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_c ptr False+ instance Jc Label where jc l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_c 0 False emitFixup l (-4) Fixup32@@ -1657,6 +1719,9 @@ instance Je Word32 where je imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_e imm False +instance Je (Ptr a) where+ je ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_e ptr False+ instance Je Label where je l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_e 0 False emitFixup l (-4) Fixup32@@ -1670,6 +1735,9 @@ instance Jna Word32 where jna imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_na imm False +instance Jna (Ptr a) where+ jna ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_na ptr False+ instance Jna Label where jna l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_na 0 False emitFixup l (-4) Fixup32@@ -1683,6 +1751,9 @@ instance Jnae Word32 where jnae imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nae imm False +instance Jnae (Ptr a) where+ jnae ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nae ptr False+ instance Jnae Label where jnae l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nae 0 False emitFixup l (-4) Fixup32@@ -1696,6 +1767,9 @@ instance Jnb Word32 where jnb imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nb imm False +instance Jnb (Ptr a) where+ jnb ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nb ptr False+ instance Jnb Label where jnb l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nb 0 False emitFixup l (-4) Fixup32@@ -1709,6 +1783,9 @@ instance Jnbe Word32 where jnbe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nbe imm False +instance Jnbe (Ptr a) where+ jnbe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nbe ptr False+ instance Jnbe Label where jnbe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nbe 0 False emitFixup l (-4) Fixup32@@ -1722,6 +1799,9 @@ instance Jnc Word32 where jnc imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nc imm False +instance Jnc (Ptr a) where+ jnc ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nc ptr False+ instance Jnc Label where jnc l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nc 0 False emitFixup l (-4) Fixup32@@ -1735,6 +1815,9 @@ instance Jne Word32 where jne imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ne imm False +instance Jne (Ptr a) where+ jne ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ne ptr False+ instance Jne Label where jne l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ne 0 False emitFixup l (-4) Fixup32@@ -1748,6 +1831,9 @@ instance Jnp Word32 where jnp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_np imm False +instance Jnp (Ptr a) where+ jnp ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_np ptr False+ instance Jnp Label where jnp l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_np 0 False emitFixup l (-4) Fixup32@@ -1761,6 +1847,9 @@ instance Jnz Word32 where jnz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nz imm False +instance Jnz (Ptr a) where+ jnz ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_nz ptr False+ instance Jnz Label where jnz l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_nz 0 False emitFixup l (-4) Fixup32@@ -1774,6 +1863,9 @@ instance Jp Word32 where jp imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_p imm False +instance Jp (Ptr a) where+ jp ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_p ptr False+ instance Jp Label where jp l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_p 0 False emitFixup l (-4) Fixup32@@ -1787,6 +1879,9 @@ instance Jpe Word32 where jpe imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_pe imm False +instance Jpe (Ptr a) where+ jpe ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_pe ptr False+ instance Jpe Label where jpe l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_pe 0 False emitFixup l (-4) Fixup32@@ -1800,6 +1895,9 @@ instance Jpo Word32 where jpo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_po imm False +instance Jpo (Ptr a) where+ jpo ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_po ptr False+ instance Jpo Label where jpo l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_po 0 False emitFixup l (-4) Fixup32@@ -1813,6 +1911,9 @@ instance Jz Word32 where jz imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_z imm False +instance Jz (Ptr a) where+ jz ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_z ptr False+ instance Jz Label where jz l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_z 0 False emitFixup l (-4) Fixup32@@ -1826,6 +1927,9 @@ instance Jg Word32 where jg imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt imm True +instance Jg (Ptr a) where+ jg ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_gt ptr True+ instance Jg Label where jg l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt 0 True emitFixup l (-4) Fixup32@@ -1839,6 +1943,9 @@ instance Jge Word32 where jge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge imm True +instance Jge (Ptr a) where+ jge ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ge ptr True+ instance Jge Label where jge l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge 0 True emitFixup l (-4) Fixup32@@ -1852,6 +1959,9 @@ instance Jl Word32 where jl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt imm True +instance Jl (Ptr a) where+ jl ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_lt ptr True+ instance Jl Label where jl l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt 0 True emitFixup l (-4) Fixup32@@ -1865,6 +1975,9 @@ instance Jle Word32 where jle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le imm True +instance Jle (Ptr a) where+ jle ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_le ptr True+ instance Jle Label where jle l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le 0 True emitFixup l (-4) Fixup32@@ -1878,6 +1991,9 @@ instance Jng Word32 where jng imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le imm True +instance Jng (Ptr a) where+ jng ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_le ptr True+ instance Jng Label where jng l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_le 0 True emitFixup l (-4) Fixup32@@ -1891,6 +2007,9 @@ instance Jnge Word32 where jnge imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt imm True +instance Jnge (Ptr a) where+ jnge ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_lt ptr True+ instance Jnge Label where jnge l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_lt 0 True emitFixup l (-4) Fixup32@@ -1904,6 +2023,9 @@ instance Jnl Word32 where jnl imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge imm True +instance Jnl (Ptr a) where+ jnl ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ge ptr True+ instance Jnl Label where jnl l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ge 0 True emitFixup l (-4) Fixup32@@ -1917,6 +2039,9 @@ instance Jnle Word32 where jnle imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt imm True +instance Jnle (Ptr a) where+ jnle ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_gt ptr True+ instance Jnle Label where jnle l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_gt 0 True emitFixup l (-4) Fixup32@@ -1930,6 +2055,9 @@ instance Jno Word32 where jno imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_no imm True +instance Jno (Ptr a) where+ jno ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_no ptr True+ instance Jno Label where jno l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_no 0 True emitFixup l (-4) Fixup32@@ -1943,6 +2071,9 @@ instance Jns Word32 where jns imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ns imm True +instance Jns (Ptr a) where+ jns ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_ns ptr True+ instance Jns Label where jns l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_ns 0 True emitFixup l (-4) Fixup32@@ -1956,6 +2087,9 @@ instance Jo Word32 where jo imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_o imm True +instance Jo (Ptr a) where+ jo ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_o ptr True+ instance Jo Label where jo l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_o 0 True emitFixup l (-4) Fixup32@@ -1969,6 +2103,9 @@ instance Js Word32 where js imm = ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_s imm True +instance Js (Ptr a) where+ js ptr = ensureBufferSize x86_max_instruction_bytes >> x86_branch_pointer x86_cc_s ptr True+ instance Js Label where js l = do ensureBufferSize x86_max_instruction_bytes >> x86_branch32 x86_cc_s 0 True emitFixup l (-4) Fixup32@@ -2988,7 +3125,30 @@ instance Fadd FPTopReg Ind where fadd FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fadd r 0 True +instance Fadd FPReg FPTopReg where+ fadd (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fadd idx False ++class Faddp a b where+ faddp :: a -> b -> CodeGen e s ()++instance Faddp FPReg FPTopReg where+ faddp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fadd idx True+++class Fiadd a b where+ fiadd32 :: a -> b -> CodeGen e s ()+ fiadd16 :: a -> b -> CodeGen e s ()++instance Fiadd FPTopReg (Disp, Reg32) where+ fiadd32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r d True+ fiadd16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r d False++instance Fiadd FPTopReg Ind where+ fiadd32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r 0 True+ fiadd16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fadd r 0 False++ class Fsub a b where fsub :: a -> b -> CodeGen e s () @@ -3004,7 +3164,30 @@ instance Fsub FPTopReg Ind where fsub FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fsub r 0 True +instance Fsub FPReg FPTopReg where+ fsub (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fsub idx False ++class Fsubp a b where+ fsubp :: a -> b -> CodeGen e s ()++instance Fsubp FPReg FPTopReg where+ fsubp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fsub idx True+++class Fisub a b where+ fisub32 :: a -> b -> CodeGen e s ()+ fisub16 :: a -> b -> CodeGen e s ()++instance Fisub FPTopReg (Disp, Reg32) where+ fisub32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r d True+ fisub16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r d False++instance Fisub FPTopReg Ind where+ fisub32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r 0 True+ fisub16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fsub r 0 False++ class Fsubr a b where fsubr :: a -> b -> CodeGen e s () @@ -3036,7 +3219,30 @@ instance Fmul FPTopReg Ind where fmul FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fmul r 0 True +instance Fmul FPReg FPTopReg where+ fmul (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fmul idx False ++class Fmulp a b where+ fmulp :: a -> b -> CodeGen e s ()++instance Fmulp FPReg FPTopReg where+ fmulp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fmul idx True+++class Fimul a b where+ fimul32 :: a -> b -> CodeGen e s ()+ fimul16 :: a -> b -> CodeGen e s ()++instance Fimul FPTopReg (Disp, Reg32) where+ fimul32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r d True+ fimul16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r d False++instance Fimul FPTopReg Ind where+ fimul32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r 0 True+ fimul16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fmul r 0 False++ class Fdiv a b where fdiv :: a -> b -> CodeGen e s () @@ -3052,7 +3258,30 @@ instance Fdiv FPTopReg Ind where fdiv FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_membase x86_fdiv r 0 True +instance Fdiv FPReg FPTopReg where+ fdiv (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fdiv idx False ++class Fdivp a b where+ fdivp :: a -> b -> CodeGen e s ()++instance Fdivp FPReg FPTopReg where+ fdivp (FPReg idx) FPTopReg = ensureBufferSize x86_max_instruction_bytes >> x86_fp_op_reg x86_fdiv idx True+++class Fidiv a b where+ fidiv32 :: a -> b -> CodeGen e s ()+ fidiv16 :: a -> b -> CodeGen e s ()++instance Fidiv FPTopReg (Disp, Reg32) where+ fidiv32 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r d True+ fidiv16 FPTopReg (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r d False++instance Fidiv FPTopReg Ind where+ fidiv32 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r 0 True+ fidiv16 FPTopReg (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fp_int_op_membase x86_fdiv r 0 False++ class Fdivr a b where fdivr :: a -> b -> CodeGen e s () @@ -3199,36 +3428,36 @@ fild :: a -> CodeGen e s () instance Fild Addr where - fild (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fild a False+ fild (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fild a FInt32 instance Fild (Disp, Reg32) where - fild (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r d False+ fild (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r d FInt32 instance Fild Ind where - fild (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r 0 False+ fild (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fild_membase r 0 FInt32 class Fist a where fist :: a -> CodeGen e s () instance Fist (Disp, Reg32) where - fist (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r d False+ fist (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r d FInt32 instance Fist Ind where - fist (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r 0 False+ fist (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_membase r 0 FInt32 class Fistp a where fistp :: a -> CodeGen e s () instance Fistp Addr where- fistp (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop a False+ fistp (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop a FInt32 instance Fistp (Disp, Reg32) where - fistp (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r d False+ fistp (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r d FInt32 instance Fistp Ind where - fistp (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r 0 False+ fistp (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_fist_pop_membase r 0 FInt32 class Sqrtsd a b where@@ -3676,6 +3905,31 @@ maxps (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_max_sse_reg_membase x86_sse_ps xd r d +class Movss a b where+ movss :: a -> b -> CodeGen e s ()++instance Movss XMMReg XMMReg where+ movss (XMMReg xd) (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_reg x86_sse_ss xd xs++instance Movss XMMReg Addr where+ movss (XMMReg xd) (Addr a) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_mem x86_sse_ss xd a++instance Movss Addr XMMReg where+ movss (Addr a) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_mem_reg x86_sse_ss a xd++instance Movss XMMReg Ind where+ movss (XMMReg xd) (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_ss xd r 0++instance Movss Ind XMMReg where+ movss (Ind (Reg32 r)) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_ss r 0 xd++instance Movss XMMReg (Disp, Reg32) where+ movss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_reg_membase x86_sse_ss xd r d++instance Movss (Disp, Reg32) XMMReg where+ movss (Disp d, Reg32 r) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_ss r d xd++ class Movsd a b where movsd :: a -> b -> CodeGen e s () @@ -3701,6 +3955,56 @@ movsd (Disp d, Reg32 r) (XMMReg xd) = ensureBufferSize x86_max_instruction_bytes >> x86_mov_sse_membase_reg x86_sse_sd r d xd +class Movups a b where+ movups :: a -> b -> CodeGen e s ()++instance Movups XMMReg XMMReg where+ movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)++instance Movups XMMReg Addr where+ movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)++instance Movups Addr XMMReg where+ movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)++instance Movups XMMReg Ind where+ movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)++instance Movups Ind XMMReg where+ movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)++instance Movups XMMReg (Disp, Reg32) where+ movups (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movups_to_reg xd (xmmLocLowLevel xs)++instance Movups (Disp, Reg32) XMMReg where+ movups xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movups_from_reg xs (xmmLocLowLevel xd)+++class Movlps a b where+ movlps :: a -> b -> CodeGen e s ()++instance Movlps XMMReg XMMReg where+ movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)++instance Movlps XMMReg Addr where+ movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)++instance Movlps Addr XMMReg where+ movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel xd)++instance Movlps XMMReg Ind where+ movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)++instance Movlps Ind XMMReg where+ movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel xd)++instance Movlps XMMReg (Disp, Reg32) where+ movlps (XMMReg xd) xs = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_to_reg xd (xmmLocLowLevel xs)++instance Movlps (Disp, Reg32) XMMReg where+ movlps xd (XMMReg xs) = ensureBufferSize x86_max_instruction_bytes >> x86_movlps_from_reg xs (xmmLocLowLevel xd)++ class Comisd a b where comisd :: a -> b -> CodeGen e s () @@ -3765,6 +4069,49 @@ ucomiss (XMMReg xd) (Disp d, Reg32 r) = ensureBufferSize x86_max_instruction_bytes >> x86_ucomiss_reg_membase xd r d +class XMMLocation b => XMMLoc a b | a -> b where+ xmmLocLowLevel :: a -> b++instance XMMLoc XMMReg XMMReg where+ xmmLocLowLevel = id++instance XMMLoc Addr Mem where+ xmmLocLowLevel (Addr a) = Mem a++instance XMMLoc Ind MemBase where+ xmmLocLowLevel (Ind (Reg32 r)) = MemBase r 0++instance XMMLoc (Disp, Reg32) MemBase where+ xmmLocLowLevel (Disp d, Reg32 r) = MemBase r d+++haddps :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()+haddps (XMMReg dreg) reg =+ x86_haddps dreg (xmmLocLowLevel reg)++haddpd :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()+haddpd (XMMReg dreg) reg =+ x86_haddpd dreg (xmmLocLowLevel reg)+++shufps :: XMMLoc xmm a => XMMReg -> xmm -> Word8 -> CodeGen e s ()+shufps (XMMReg dreg) reg src =+ x86_shufps dreg (xmmLocLowLevel reg) src++shufpd :: XMMLoc xmm a => XMMReg -> xmm -> Word8 -> CodeGen e s ()+shufpd (XMMReg dreg) reg src =+ x86_shufpd dreg (xmmLocLowLevel reg) src+++cvtdq2ps :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()+cvtdq2ps (XMMReg dreg) reg =+ x86_cvtdq2ps dreg (xmmLocLowLevel reg)++cvttps2dq :: XMMLoc xmm a => XMMReg -> xmm -> CodeGen e s ()+cvttps2dq (XMMReg dreg) reg =+ x86_cvttps2dq dreg (xmmLocLowLevel reg)++ class Prefetchnta a where prefetchnta :: a -> CodeGen e s () @@ -3813,3 +4160,9 @@ instance Prefetch2 Ind where prefetch2 (Ind (Reg32 r)) = ensureBufferSize x86_max_instruction_bytes >> x86_prefetch2_regp r ++ptrToWord32 :: Ptr a -> Word32+ptrToWord32 = fromIntegral . ptrToIntPtr++ptrToInt :: Ptr a -> Int+ptrToInt = fromIntegral . ptrToIntPtr
Harpy/X86CodeGen.hs view
@@ -112,7 +112,7 @@ x86_prolog, x86_epilog, x86_enter, x86_leave, x86_ret, x86_ret_imm, -- ** Jump and branch- x86_jecxz, x86_branch, x86_branch32, x86_branch8,+ x86_jecxz, x86_branch, x86_branch_pointer, x86_branch32, x86_branch8, x86_jump_membase, x86_jump_pointer, x86_jump_mem, x86_jump_reg, x86_jump32, x86_jump8, x86_loopne, x86_loope, x86_loop, @@ -169,10 +169,12 @@ x86_fld, x86_fld_membase, x86_fld80_mem, x86_fld80_membase, x86_fld_reg, x86_fldz, x86_fld1, x86_fldpi, x86_fst, x86_fst_membase, x86_fst80_mem, x86_fst80_membase,+ FIntSize(..), x86_fist_pop, x86_fist_pop_membase, x86_fstsw, x86_fist_membase, x86_fild, x86_fild_membase, x86_fsin, x86_fcos, x86_fabs, x86_ftst, x86_fxam, x86_fpatan, x86_fprem, x86_fprem1, x86_frndint, x86_fsqrt, x86_fptan,+ x86_fincstp, x86_fdecstp, -- ** SSE instructions x86_sse_ps, x86_sse_pd, x86_sse_ss, x86_sse_sd, x86_add_sse_reg_reg, x86_add_sse_reg_mem, x86_add_sse_reg_membase,@@ -187,6 +189,17 @@ x86_ucomiss_reg_reg, x86_ucomiss_reg_mem, x86_ucomiss_reg_membase, x86_comisd_reg_reg, x86_comisd_reg_mem, x86_comisd_reg_membase, x86_comiss_reg_reg, x86_comiss_reg_mem, x86_comiss_reg_membase,+ XMMReg(XMMReg), Mem(Mem), MemBase(MemBase),+ XMMLocation(xmm_location_emit),+ x86_movss_to_reg, x86_movss_from_reg,+ x86_movsd_to_reg, x86_movsd_from_reg,+ x86_movlps_to_reg, x86_movlps_from_reg,+ x86_movlpd_to_reg, x86_movlpd_from_reg,+ x86_movups_to_reg, x86_movups_from_reg,+ x86_movupd_to_reg, x86_movupd_from_reg,+ x86_haddps, x86_haddpd,+ x86_shufps, x86_shufpd,+ x86_cvtdq2ps, x86_cvttps2dq, -- ** Prefetch instructions x86_prefetch0_mem, x86_prefetch1_mem, x86_prefetch2_mem, x86_prefetchnta_mem, x86_prefetch0_membase, x86_prefetch1_membase, x86_prefetch2_membase, x86_prefetchnta_membase,@@ -1028,11 +1041,11 @@ x86_fp_op opc index = do emit8 0xd8 emit8 (0xc0 + (opc `shiftL` 3) + (index .&. 0x07))-x86_fp_op_reg :: Int -> Word8 -> Bool -> CodeGen e s ()+x86_fp_op_reg :: Word8 -> Word8 -> Bool -> CodeGen e s () x86_fp_op_reg opc index pop_stack = do let opcMap = [ 0, 1, 2, 3, 5, 4, 7, 6, 8] emit8 (if pop_stack then 0xde else 0xdc) - emit8 (0xc0 + ((opcMap !! opc) `shiftL` 3) + (index .&. 0x07))+ emit8 (0xc0 + ((opcMap !! fromIntegral opc) `shiftL` 3) + (index .&. 0x07)) -- @x86_fp_int_op_membase@@ -1078,6 +1091,9 @@ x86_fucomi index = emit8 0xdb >> emit8 (0xe8 + (index .&. 0x07)) x86_fucomip :: Word8 -> CodeGen e s () x86_fucomip index = emit8 0xdf >> emit8 (0xe8 + (index .&. 0x07))++data FIntSize = FInt16 | FInt32 | FInt64+ x86_fld :: Word32 -> Bool -> CodeGen e s () x86_fld mem is_double = do emit8 (if is_double then 0xdd else 0xd9) @@ -1091,16 +1107,18 @@ x86_fld80_membase :: Word8 -> Word32 -> CodeGen e s () x86_fld80_membase basereg disp = emit8 0xdb >> x86_membase_emit 5 basereg disp -x86_fild :: Word32 -> Bool -> CodeGen e s ()-x86_fild mem is_long = - if is_long- then emit8 0xdf >> x86_mem_emit 5 mem - else emit8 0xdb >> x86_mem_emit 0 mem -x86_fild_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()-x86_fild_membase basereg disp is_long = - if is_long- then emit8 0xdf >> x86_membase_emit 5 basereg disp - else emit8 0xdb >> x86_membase_emit 0 basereg disp +x86_fild :: Word32 -> FIntSize -> CodeGen e s ()+x86_fild mem size =+ case size of+ FInt16 -> emit8 0xdf >> x86_mem_emit 0 mem+ FInt32 -> emit8 0xdb >> x86_mem_emit 0 mem+ FInt64 -> emit8 0xdf >> x86_mem_emit 5 mem+x86_fild_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()+x86_fild_membase basereg disp size =+ case size of+ FInt16 -> emit8 0xdb >> x86_membase_emit 0 basereg disp + FInt32 -> emit8 0xdb >> x86_membase_emit 0 basereg disp + FInt64 -> emit8 0xdf >> x86_membase_emit 5 basereg disp x86_fld_reg :: Word8 -> CodeGen e s () x86_fld_reg index = emit8 0xd9 >> emit8 (0xc0 + (index .&. 0x07))@@ -1124,30 +1142,39 @@ x86_fst80_membase :: Word8 -> Word32 -> CodeGen e s () x86_fst80_membase basereg disp = emit8 0xdb >> x86_membase_emit 7 basereg disp -x86_fist_pop :: Word32 -> Bool -> CodeGen e s ()-x86_fist_pop mem is_long = - if is_long- then emit8 0xdf >> x86_mem_emit 7 mem - else emit8 0xdb >> x86_mem_emit 3 mem -x86_fist_pop_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()-x86_fist_pop_membase basereg disp is_long = - if is_long- then emit8 0xdf >> x86_membase_emit 7 basereg disp - else emit8 0xdb >> x86_membase_emit 3 basereg disp +x86_fist_pop :: Word32 -> FIntSize -> CodeGen e s ()+x86_fist_pop mem size =+ case size of+ FInt16 -> emit8 0xdf >> x86_mem_emit 3 mem+ FInt32 -> emit8 0xdb >> x86_mem_emit 3 mem+ FInt64 -> emit8 0xdf >> x86_mem_emit 7 mem+x86_fist_pop_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()+x86_fist_pop_membase basereg disp size =+ case size of+ FInt16 -> emit8 0xdf >> x86_membase_emit 3 basereg disp+ FInt32 -> emit8 0xdb >> x86_membase_emit 3 basereg disp+ FInt64 -> emit8 0xdf >> x86_membase_emit 7 basereg disp x86_fstsw :: CodeGen e s () x86_fstsw = emit8 0x9b >> emit8 0xdf >> emit8 0xe0 -- @x86_fist_membase -- Converts content of ST(0) to integer and stores it at memory location -- addressed by [basereg + disp].--- is_int specifies whether destination is int32 (TRUE) or int16 (FALSE).+-- size specifies whether destination is int32 or int16. -x86_fist_membase :: Word8 -> Word32 -> Bool -> CodeGen e s ()-x86_fist_membase basereg disp is_int = - if is_int- then emit8 0xdb >> x86_membase_emit 2 basereg disp - else emit8 0xdf >> x86_membase_emit 2 basereg disp +x86_fist_membase :: Word8 -> Word32 -> FIntSize -> CodeGen e s ()+x86_fist_membase basereg disp size = + case size of+ FInt16 -> emit8 0xdf >> x86_membase_emit 2 basereg disp + FInt32 -> emit8 0xdb >> x86_membase_emit 2 basereg disp + FInt64 -> error "fist does not support 64 bit access" +x86_fincstp :: CodeGen e s ()+x86_fincstp = emit8 0xd9 >> emit8 0xf7 ++x86_fdecstp :: CodeGen e s ()+x86_fdecstp = emit8 0xd9 >> emit8 0xf6 + -- PUSH instruction. x86_push_reg :: Word8 -> CodeGen e s ()@@ -1272,6 +1299,14 @@ if x86_is_imm8 offset then x86_branch8 cond (fromIntegral offset) is_signed else x86_branch32 cond (fromIntegral (offset - 4)) is_signed++x86_branch_pointer :: Int -> Ptr a -> Bool -> CodeGen e s ()+x86_branch_pointer cond target is_signed =+ do inst <- getCodeOffset+ base <- getBasePtr+ let ptr = base `plusPtr` inst+ x86_branch32 cond (fromIntegral (target `minusPtr` ptr - 5)) is_signed+ {- x86_branch_disp cond disp is_signed = do let offset = disp - 2@@ -1929,6 +1964,164 @@ do emit8 0x0f emit8 0x2e x86_membase_emit dreg basereg disp+++newtype XMMReg = XMMReg Word8+ deriving (Eq, Ord)++newtype Mem = Mem Word32++data MemBase = MemBase Word8 Word32+++class XMMLocation xmm where+ xmm_location_emit :: Word8 -> xmm -> CodeGen e s ()++instance XMMLocation XMMReg where+ xmm_location_emit dreg (XMMReg reg) =+ x86_reg_emit dreg reg++instance XMMLocation Mem where+ xmm_location_emit dreg (Mem mem) =+ x86_mem_emit dreg mem++instance XMMLocation MemBase where+ xmm_location_emit dreg (MemBase basereg disp) =+ x86_membase_emit dreg basereg disp+++x86_movss_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movss_to_reg dreg reg =+ do emit8 0xf3+ emit8 0x0f+ emit8 0x10+ xmm_location_emit dreg reg++x86_movss_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movss_from_reg dreg reg =+ do emit8 0xf3+ emit8 0x0f+ emit8 0x11+ xmm_location_emit dreg reg++x86_movsd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movsd_to_reg dreg reg =+ do emit8 0xf2+ emit8 0x0f+ emit8 0x10+ xmm_location_emit dreg reg++x86_movsd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movsd_from_reg dreg reg =+ do emit8 0xf2+ emit8 0x0f+ emit8 0x11+ xmm_location_emit dreg reg+++-- | xmm must not be a register+x86_movlps_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movlps_to_reg dreg reg =+ do emit8 0x0f+ emit8 0x12+ xmm_location_emit dreg reg++-- | xmm must not be a register+x86_movlps_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movlps_from_reg dreg reg =+ do emit8 0x0f+ emit8 0x13+ xmm_location_emit dreg reg++-- | xmm must not be a register+x86_movlpd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movlpd_to_reg dreg reg =+ do emit8 0x66+ emit8 0x0f+ emit8 0x12+ xmm_location_emit dreg reg++-- | xmm must not be a register+x86_movlpd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movlpd_from_reg dreg reg =+ do emit8 0x66+ emit8 0x0f+ emit8 0x13+ xmm_location_emit dreg reg+++x86_movups_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movups_to_reg dreg reg =+ do emit8 0x0f+ emit8 0x10+ xmm_location_emit dreg reg++x86_movups_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movups_from_reg dreg reg =+ do emit8 0x0f+ emit8 0x11+ xmm_location_emit dreg reg++x86_movupd_to_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movupd_to_reg dreg reg =+ do emit8 0x66+ emit8 0x0f+ emit8 0x10+ xmm_location_emit dreg reg++x86_movupd_from_reg :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_movupd_from_reg dreg reg =+ do emit8 0x66+ emit8 0x0f+ emit8 0x11+ xmm_location_emit dreg reg+++x86_haddps :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_haddps dreg reg =+ do emit8 0xf2+ emit8 0x0f+ emit8 0x7c+ xmm_location_emit dreg reg++x86_haddpd :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_haddpd dreg reg =+ do emit8 0x66+ emit8 0x0f+ emit8 0x7c+ xmm_location_emit dreg reg+++x86_shufps :: XMMLocation xmm => Word8 -> xmm -> Word8 -> CodeGen e s ()+x86_shufps dreg reg src =+ do emit8 0x0f+ emit8 0xc6+ xmm_location_emit dreg reg+ emit8 src++x86_shufpd :: XMMLocation xmm => Word8 -> xmm -> Word8 -> CodeGen e s ()+x86_shufpd dreg reg src =+ do emit8 0x66+ emit8 0x0f+ emit8 0xc6+ xmm_location_emit dreg reg+ emit8 src+++x86_cvtdq2ps :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_cvtdq2ps dreg reg =+ do emit8 0x0f+ emit8 0x5b+ xmm_location_emit dreg reg++x86_cvttps2dq :: XMMLocation xmm => Word8 -> xmm -> CodeGen e s ()+x86_cvttps2dq dreg reg =+ do emit8 0xf3+ emit8 0x0f+ emit8 0x5b+ xmm_location_emit dreg reg++ -- ============================================================================= -- Prefetching instructions.
Harpy/X86Disassembler.hs view
@@ -10,3236 +10,23 @@ -- -- Disassembler for x86 machine code. ----- This is a disassembler for object code for the x86 architecture.--- It provides functions for disassembling byte arrays, byte lists and--- memory blocks containing raw binary code.--- --- Features:------ - Disassembles memory blocks, lists or arrays of bytes into lists of--- instructions.------ - Abstract instructions provide as much information as possible about--- opcodes, addressing modes or operand sizes, allowing for detailed--- output.------ - Provides functions for displaying instructions in Intel or AT&T--- style (like the GNU tools)------ Differences to GNU tools, like gdb or objdump:------ - Displacements are shown in decimal, with sign if negative.------ Missing: ------ - LOCK and repeat prefixes are recognized, but not contained in the--- opcodes of instructions.------ - Support for 16-bit addressing modes. Could be added when needed.------ - Complete disassembly of all 64-bit instructions. I have tried to--- disassemble them properly but have been limited to the information--- in the docs, because I have no 64-bit machine to test on. This will--- probably change when I get GNU as to produce 64-bit object files.------ - Not all MMX and SSE/SSE2/SSE3 instructions are decoded yet. This is--- just a matter of missing time.------ - segment override prefixes are decoded, but not appended to memory--- references------ On the implementation:------ This disassembler uses the Parsec parser combinators, working on byte--- lists. This proved to be very convenient, as the combinators keep--- track of the current position, etc.-----------------------------------------------------------------------------module Harpy.X86Disassembler(- -- * Types- Opcode,- Operand(..),- InstrOperandSize(..),- Instruction(..),- ShowStyle(..),- -- * Functions- disassembleBlock,- disassembleList,- disassembleArray,- showIntel,- showAtt- ) where--import Text.ParserCombinators.Parsec-import Control.Monad.State-import System.IO-import Data.List-import Data.Char-import Data.Array.IArray-import Numeric-import Foreign---- | All opcodes are represented by this enumeration type.--data Opcode = InvalidOpcode- | AAA- | AAD- | AAM- | AAS- | ADC- | ADD- | ADDPD- | ADDPS- | ADDSD- | ADDSS- | ADDSUBPD- | ADDUBPS- | AND- | ANDNPD- | ANDNPS- | ANDPD- | ANDPS- | ARPL- | BOUND- | BSF- | BSR- | BT- | BTC- | BTR- | BTS- | CALL- | CALLF- | CBW- | CDQ- | CDQE- | CLC- | CLD- | CLFLUSH- | CLI- | CLTS- | CMC- | CMOVA- | CMOVB- | CMOVBE- | CMOVE- | CMOVG- | CMOVGE- | CMOVL- | CMOVLE- | CMOVNB- | CMOVNE- | CMOVNO- | CMOVNP- | CMOVNS- | CMOVO- | CMOVP- | CMOVS- | CMP- | CMPS- | CMPXCHG- | CMPXCHG16B- | CMPXCHG8B- | COMISD- | COMISS- | CPUID- | CWD- | CWDE- | DAA- | DAS- | DEC- | DIV- | DIVPD- | DIVPS- | DIVSD- | DIVSS- | EMMS- | ENTER- | FABS- | FADD- | FADDP- | FBLD- | FBSTP- | FCHS- | FCLEX- | FCMOVB- | FCMOVBE- | FCMOVE- | FCMOVNB- | FCMOVNBE- | FCMOVNE- | FCMOVNU- | FCMOVU- | FCOM- | FCOMI- | FCOMIP- | FCOMP- | FCOMPP- | FDIV- | FDIVP- | FDIVR- | FDIVRP- | FFREE- | FIADD- | FICOM- | FICOMP- | FIDIV- | FIDIVR- | FILD- | FIMUL- | FINIT- | FIST- | FISTP- | FISTPP- | FISTTP- | FISUB- | FISUBR- | FLD- | FLD1- | FLDCW- | FLDENV- | FLDL2E- | FLDL2T- | FLDLG2- | FLDLN2- | FLDPI- | FLDZ- | FMUL- | FMULP- | FNOP- | FRSTOR- | FSAVE- | FST- | FSTCW- | FSTENV- | FSTP- | FSTSW- | FSUB- | FSUBP- | FSUBR- | FSUBRP- | FTST- | FUCOM- | FUCOMI- | FUCOMIP- | FUCOMP- | FUCOMPP- | FXAM- | FXCH- | FXRSTOR- | FXSAVE- | HADDPD- | HADDPS- | HLT- | HSUBPD- | HSUBPS- | IDIV- | IMUL- | BSWAP- | IN- | INC- | INS- | INT- | INT3- | INTO- | INVD- | INVLPG- | IRET- | JA- | JB- | JBE- | JCXZ- | JE- | JG- | JGE- | JL- | JLE- | JMP- | JMPF- | JMPN- | JNB- | JNE- | JNO- | JNP- | JNS- | JO- | JP- | JS- | LAHF- | LAR- | LDDQU- | LDMXCSR- | LDS- | LEA- | LEAVE- | LES- | LFENCE- | LFS- | LGDT- | LGS- | LIDT- | LLDT- | LMSW- | LODS- | LOOP- | LOOPE- | LOOPNE- | LSL- | LSS- | LTR- | MASKMOVQ- | MAXPD- | MAXPS- | MAXSD- | MAXSS- | MFENCE- | MINPD- | MINPS- | MINSD- | MINSS- | MONITOR- | MOV - | MOVAPD- | MOVAPS- | MOVDDUP- | MOVHPD- | MOVHPS- | MOVLHPS- | MOVLPD- | MOVLPS- | MOVLSDUP- | MOVMSKPD- | MOVMSKPS- | MOVNTDQ- | MOVNTPD- | MOVNTPS- | MOVNTQ- | MOVQ- | MOVS- | MOVSD- | MOVSLDUP- | MOVSS- | MOVSXB- | MOVSXD- | MOVSXW- | MOVUPD- | MOVUPS- | MOVZXB- | MOVZXW- | MUL- | MULPD- | MULPS- | MULSD- | MULSS- | MWAIT- | NEG- | NOP- | NOT- | OR- | ORPD- | ORPS- | OUT- | OUTS- | PADDB- | PADDD- | PADDQ- | PADDSB- | PADDSW- | PADDUSB- | PADDUSW- | PADDW- | PAND- | PANDN- | PAUSE- | PAVGB- | PAVGW- | PMADDWD- | PMAXSW- | PMAXUB- | PMINSW- | PMINUB- | PMOVMSKB- | PMULHUW- | PMULHW- | PMULLW- | PMULUDQ- | POP- | POPA- | POPAD- | POPF- | POPFD- | POPFQ- | POR- | PREFETCHNTA- | PREFETCHT0- | PREFETCHT1- | PREFETCHT2- | PSADBW- | PSLLD- | PSLLDQ- | PSLLQ- | PSLLW- | PSRAD- | PSRAW- | PSRLD- | PSRLDQ- | PSRLQ- | PSRLW- | PSUBB- | PSUBD- | PSUBQ- | PSUBSB- | PSUBSQ- | PSUBUSB- | PSUBUSW- | PSUBW- | PUSH- | PUSHA- | PUSHAD- | PUSHF- | PUSHFD- | PUSHFQ- | PXOR- | RCL- | RCPPS- | RCPSS- | RCR- | RDMSR- | RDPMC- | RDTSC- | RET- | RETF- | ROL- | ROR- | RSM- | RSQRTPS- | RSQRTSS- | SAHF- | SAR- | SBB- | SCAS- | SETA- | SETB- | SETBE- | SETE- | SETG- | SETGE- | SETL- | SETLE- | SETNB- | SETNE- | SETNO- | SETNP- | SETNS- | SETO- | SETP- | SETS- | SFENCE- | SGDT- | SHL- | SHLD- | SHR- | SHRD- | SIDT- | SLDT- | SMSW- | SQRTPD- | SQRTPS- | SQRTSD- | SQRTSS- | STC- | STD- | STI- | STMXCSR- | STOS- | STR- | SUB- | SUBPD- | SUBPS- | SUBSD- | SUBSS- | SWAPGS- | SYSCALL- | SYSENTER- | SYSEXIT- | TEST- | UCOMISD- | UCOMISS- | UD2- | UNPCKHPD- | UNPCKHPS- | UNPCKLPD- | UNPCKLPS- | VERR- | VERW- | VMCALL- | VMCLEAR- | VMLAUNCH- | VMPTRLD- | VMPTRST- | VMREAD- | VMRESUME- | VMWRITE- | VMXOFF- | VMXON- | WAIT- | WBINVD- | WRMSR- | XADD- | XCHG- | XLAT- | XOR- | XORPD- | XORPS- deriving (Show, Eq)---- Display an opcode in lower case.--showOp :: Opcode -> String-showOp = (map toLower) . show---- | All operands are in one of the following locations:------ - Constants in the instruction stream------ - Memory locations------ - Registers------ Memory locations are referred to by on of several addressing modes:------ - Absolute (address in instruction stream)------ - Register-indirect (address in register)------ - Register-indirect with displacement------ - Base-Index with scale------ - Base-Index with scale and displacement ------ Displacements can be encoded as 8 or 32-bit immediates in the--- instruction stream, but are encoded as Int in instructions for--- simplicity.----data Operand = OpImm Word32 -- ^ Immediate value- | OpAddr Word32 InstrOperandSize -- ^ Absolute address- | OpReg String Int -- ^ Register- | OpFPReg Int -- ^ Floating-point register- | OpInd String InstrOperandSize -- ^Register-indirect- | OpIndDisp String Int InstrOperandSize- -- ^ Register-indirect with displacement- | OpBaseIndex String String Int InstrOperandSize- -- ^ Base plus scaled index- | OpIndexDisp String Int Int InstrOperandSize- -- ^ Scaled index with displacement- | OpBaseIndexDisp String String Int Int InstrOperandSize- -- ^ Base plus scaled index with displacement- deriving (Eq)---- Show an operand in AT&T style.--showAttOps (OpImm w) = showImm w-showAttOps (OpAddr w _) = showAddr w-showAttOps (OpReg s num) = "%" ++ s-showAttOps (OpFPReg 0) = "%st"-showAttOps (OpFPReg i) = "%st(" ++ show i ++ ")"-showAttOps (OpInd s _) = "(%" ++ s ++ ")"-showAttOps (OpIndDisp s disp _) = show disp ++ "(%" ++ s ++ ")"-showAttOps (OpBaseIndex b i s _) = "(%" ++ b ++ ",%" ++ i ++ "," ++ show s ++ ")"-showAttOps (OpIndexDisp i s disp _) = show disp ++ "(%" ++ i ++ "," ++ - show s ++ ")"-showAttOps (OpBaseIndexDisp b i s disp _) = show disp ++ "(%" ++ b ++ ",%" ++ - i ++ "," ++ show s ++ ")"---- Show an operand in Intel style.--showIntelOps opsize (OpImm w) = showIntelImm w-showIntelOps opsize (OpAddr w sz) = opInd sz ++ "[" ++ showIntelAddr w ++ "]"-showIntelOps opsize (OpReg s num) = s-showIntelOps opsize (OpFPReg 0) = "st"-showIntelOps opsize (OpFPReg i) = "st(" ++ show i ++ ")"-showIntelOps opsize (OpInd s sz) = opInd sz ++ "[" ++ s ++ "]"-showIntelOps opsize (OpIndDisp s disp sz) = - opInd sz ++ "[" ++ s ++ - (if disp < 0 then "" else "+") ++ show disp ++ "]"-showIntelOps opsize (OpBaseIndex b i s sz) = - opInd sz ++ "[" ++ b ++ "+" ++ i ++ "*" ++ show s ++ "]"-showIntelOps opsize (OpIndexDisp i s disp sz) = - opInd sz ++ "[" ++ i ++ "*" ++ show s ++ - (if disp < 0 then "" else "+") ++ show disp ++ "]"-showIntelOps opsize (OpBaseIndexDisp b i s disp sz) = - opInd sz ++ "[" ++ b ++ "+" ++ i ++ "*" ++ show s ++ - (if disp < 0 then "" else "+") ++ - show disp ++ "]"-opInd OPNONE = ""-opInd OP8 = "byte ptr "-opInd OP16 = "word ptr "-opInd OP32 = "dword ptr "-opInd OPF32 = "dword ptr "-opInd OP64 = "qword ptr "-opInd OPF64 = "qword ptr "-opInd OPF80 = "tbyte ptr "-opInd OP128 = "dqword ptr "---- | Encodes the default and currently active operand or address size. Can--- be changed with the operand- or address-size prefixes 0x66 and 0x67.--data OperandSize = BIT16 | BIT32---- | Some opcodes can operate on data of several widths. This information--- is encoded in instructions using the following enumeration type..--data InstrOperandSize = OPNONE -- ^ No operand size specified- | OP8 -- ^ 8-bit integer operand- | OP16 -- ^ 16-bit integer operand- | OP32 -- ^ 32-bit integer operand- | OP64 -- ^ 64-bit integer operand- | OP128 -- ^ 128-bit integer operand- | OPF32 -- ^ 32-bit floating point operand- | OPF64 -- ^ 64-bit floating point operand- | OPF80 -- ^ 80-bit floating point operand- deriving (Show, Eq)----- | The disassembly routines return lists of the following datatype. It--- encodes both invalid byte sequences (with a useful error message, if--- possible), or a valid instruction. Both variants contain the list of--- opcode bytes from which the instruction was decoded and the address of--- the instruction.--data Instruction = - BadInstruction Word8 String Int [Word8] -- ^ Invalid instruction- | PseudoInstruction Int String -- ^ Pseudo instruction, e.g. label- | Instruction { opcode :: Opcode, -- ^ Opcode of the instruction- opsize :: InstrOperandSize, -- ^ Operand size, if any- operands :: [Operand], -- ^ Instruction operands- address :: Int, -- ^ Start address of instruction- bytes ::[Word8] -- ^ Instruction bytes- } -- ^ Valid instruction- deriving (Eq)--instance Show Instruction where- show = showIntel--data Instr = Bad Word8 String- | Instr Opcode InstrOperandSize [Operand]---- Show an integer as an 8-digit hexadecimal number with leading zeroes.--hex32 :: Int -> String-hex32 i =- let w :: Word32- w = fromIntegral i- s = showHex w ""- in take (8 - length s) (repeat '0') ++ s---- Show a byte as an 2-digit hexadecimal number with leading zeroes.--hex8 :: Word8 -> String-hex8 i =- let s = showHex i ""- in take (2 - length s) ['0','0'] ++ s----- | Instructions can be displayed either in Intel or AT&T style (like in--- GNU tools).------ Intel style:------ - Destination operand comes first, source second.------ - No register or immediate prefixes.------ - Memory operands are annotated with operand size.------ - Hexadecimal numbers are suffixed with @H@ and prefixed with @0@ if--- necessary.------ AT&T style:------ - Source operand comes first, destination second.------ - Register names are prefixes with @%@.------ - Immediates are prefixed with @$@.------ - Hexadecimal numbers are prefixes with @0x@------ - Opcodes are suffixed with operand size, when ambiguous otherwise.-data ShowStyle = IntelStyle -- ^ Show in Intel style- | AttStyle -- ^ Show in AT&T style---- | Show an instruction in Intel style.--showIntel :: Instruction -> [Char]-showIntel (BadInstruction b desc pos bytes) =- showPosBytes pos bytes ++- "(" ++ desc ++ ", byte=" ++ show b ++ ")"-showIntel (PseudoInstruction pos s) =- hex32 pos ++ " " ++ s-showIntel (Instruction op opsize [] pos bytes) = - showPosBytes pos bytes ++- showOp op-showIntel (Instruction op opsize ops pos bytes) = - showPosBytes pos bytes ++- enlarge (showOp op) 6 ++ " " ++- concat (intersperse "," (map (showIntelOps opsize) ops))---- | Show an instruction in AT&T style.--showAtt :: Instruction -> [Char]-showAtt (BadInstruction b desc pos bytes) = - showPosBytes pos bytes ++- "(" ++ desc ++ ", byte=" ++ show b ++ ")"-showAtt (PseudoInstruction pos s) =- hex32 pos ++ " " ++ s-showAtt (Instruction op opsize [] pos bytes) = - showPosBytes pos bytes ++- showOp op ++ showInstrSuffix [] opsize-showAtt (Instruction op opsize ops pos bytes) = - showPosBytes pos bytes ++- enlarge (showOp op ++ showInstrSuffix ops opsize) 6 ++ " " ++- concat (intersperse "," (map showAttOps (reverse ops)))--showPosBytes pos bytes =- hex32 pos ++ " " ++ - enlarge (concat (intersperse " " (map hex8 bytes))) 30--enlarge s i = s ++ take (i - length s) (repeat ' ')--opSizeSuffix OPNONE = ""-opSizeSuffix OP8 = "b"-opSizeSuffix OP16 = "w"-opSizeSuffix OP32 = "l"-opSizeSuffix OP64 = "q"-opSizeSuffix OP128 = "dq"-opSizeSuffix OPF32 = "s"-opSizeSuffix OPF64 = "l"-opSizeSuffix OPF80 = "t"--showInstrSuffix [] sz = opSizeSuffix sz-showInstrSuffix ((OpImm _) : os) s = showInstrSuffix os s---showInstrSuffix ((OpReg _ _) : []) s = ""-showInstrSuffix ((OpReg _ _) : os) s = showInstrSuffix os OPNONE-showInstrSuffix ((OpFPReg _) : os) s = showInstrSuffix os s-showInstrSuffix ((OpAddr _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpAddr _ sz) : os) s = opSizeSuffix sz-showInstrSuffix ((OpInd _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpInd _ sz) : os) s = opSizeSuffix sz-showInstrSuffix ((OpIndDisp _ _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpIndDisp _ _ sz) : os) s = opSizeSuffix sz-showInstrSuffix ((OpBaseIndex _ _ _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpBaseIndex _ _ _ sz) : os) s = opSizeSuffix sz-showInstrSuffix ((OpIndexDisp _ _ _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpIndexDisp _ _ _ sz) : os) s = opSizeSuffix sz-showInstrSuffix ((OpBaseIndexDisp _ _ _ _ OPNONE) : os) s = showInstrSuffix os s-showInstrSuffix ((OpBaseIndexDisp _ _ _ _ sz) : os) s = opSizeSuffix sz---- showInstrOperandSize ops OPNONE | noRegop ops = ""--- showInstrOperandSize ops OP8 | noRegop ops = "b"--- showInstrOperandSize ops OP16 | noRegop ops = "w"--- showInstrOperandSize ops OP32 | noRegop ops = "l"--- showInstrOperandSize ops OPF32 | noRegop ops = "s"--- showInstrOperandSize ops OP64 | noRegop ops = "q"--- showInstrOperandSize ops OPF64 | noRegop ops = "l"--- showInstrOperandSize ops OPF80 | noRegop ops = "e"--- showInstrOperandSize ops OP128 | noRegop ops = ""--- showInstrOperandSize _ _ = ""---- noRegop ops = null (filter isRegop ops)--- isRegop (OpReg _ _) = True--- isRegop _ = False---- Show an immediate value in hexadecimal.--showImm :: Word32 -> String-showImm i =- "$0x" ++ showHex i ""--showIntelImm :: Word32 -> String-showIntelImm i =- let h = showHex i "H"- (f:_) = h- in (if isDigit f then "" else "0") ++ h---- Show an address in hexadecimal.--showAddr i = - let w :: Word32- w = fromIntegral i- in "0x" ++ showHex w ""-showIntelAddr i = - let w :: Word32- w = fromIntegral i- h = showHex w "H"- (f:_) = h- in (if isDigit f then "" else "0") ++ h---- | Disassemble a block of memory. Starting at the location--- pointed to by the given pointer, the given number of bytes are--- disassembled.--disassembleBlock :: Ptr Word8 -> Int -> IO (Either ParseError [Instruction])-disassembleBlock ptr len = do- l <- toList ptr len 0 []- parseInstructions - defaultState{startAddr = fromIntegral (minusPtr ptr nullPtr)} (reverse l)- where - toList :: (Ptr Word8) -> Int -> Int -> [Word8] -> IO [Word8]- toList ptr len idx acc | idx < len =- do p <- peekByteOff ptr idx- toList ptr len (idx + 1) (p : acc)--- return (p : r)- toList ptr len idx acc | idx >= len = return acc---- | Disassemble the contents of the given array.--disassembleArray :: (Monad m, IArray a Word8, Ix i) =>- a i Word8 -> m (Either ParseError [Instruction])-disassembleArray arr =- let l = elems arr- in parseInstructions defaultState l---- | Disassemble the contents of the given list.--disassembleList :: (Monad m) =>- [Word8] -> m (Either ParseError [Instruction])-disassembleList ls =- parseInstructions defaultState ls--disassembleFile filename = do- l <- readFile filename- parseInstructions defaultState (map (fromIntegral . ord) l)--instrToString insts style =- map showInstr insts- where- showInstr = case style of- IntelStyle -> showIntel- AttStyle -> showAtt---- | Test function for disassembling the contents of a binary file and--- displaying it in the provided style ("IntelStyle" or "AttStyle").--testFile :: FilePath -> ShowStyle -> IO ()-testFile fname style = do- l <- readFile fname- i <- parseInstructions defaultState (map (fromIntegral . ord) l)- case i of- Left err -> putStrLn (show err)- Right i' -> mapM_ (putStrLn . showInstr) i'- where- showInstr = case style of- IntelStyle -> showIntel- AttStyle -> showAtt---- This is the state maintained by the disassembler.--data PState = PState { defaultBitMode :: OperandSize,- operandBitMode :: OperandSize,- addressBitMode :: OperandSize,- in64BitMode :: Bool,- prefixes :: [Word8],- startAddr :: Word32- }---- Default state to be used if no other is given to the disassembly--- routines.--defaultState = PState { defaultBitMode = BIT32,- operandBitMode = BIT32, - addressBitMode = BIT32, - in64BitMode = False,- prefixes = [],- startAddr = 0}--type Word8Parser a = GenParser Word8 PState a--parseInstructions st l =- return (runParser instructionSequence st "memory block" l)---- Parse a possibly empty sequence of instructions.--instructionSequence = many instruction---- Parse a single instruction. The result is either a valid instruction--- or an indicator that there starts no valid instruction at the current--- position.--instruction = do- startPos' <- getPosition- let startPos = sourceColumn startPos' - 1- input <- getInput- st <- getState- setState st{operandBitMode = defaultBitMode st,- addressBitMode = defaultBitMode st,- prefixes = []}- many parsePrefix- b <- anyWord8- case lookup b oneByteOpCodeMap of- Just p -> do i <- p b- endPos' <- getPosition- let endPos = sourceColumn endPos' - 1- case i of- Instr oc opsize ops -> do- return $ Instruction oc opsize ops- (fromIntegral (startAddr st) + startPos)- (take (endPos - startPos) input)- Bad b desc ->- return $ BadInstruction b desc - (fromIntegral (startAddr st) + startPos)- (take (endPos - startPos) input)- Nothing -> do Bad b desc <- parseInvalidOpcode b- endPos' <- getPosition- let endPos = sourceColumn endPos' - 1- return $ BadInstruction b desc - (fromIntegral (startAddr st) + startPos)- (take (endPos - startPos) input)--toggleBitMode BIT16 = BIT32-toggleBitMode BIT32 = BIT16--rex_B = 0x1-rex_X = 0x2-rex_R = 0x4-rex_W = 0x8---- Return True if the given REX prefix bit appears in the list of current--- instruction prefixes, False otherwise.--hasREX rex st =- let rexs = filter (\ b -> b >= 0x40 && b <= 0x4f) (prefixes st) in- case rexs of- (r : _) -> if r .&. rex == rex then True else False- _ -> False---- Return True if the given prefix appears in the list of current--- instruction prefixes, False otherwise.--hasPrefix b st = b `elem` prefixes st--addPrefix b = do- st <- getState- setState st{prefixes = b : prefixes st}---- Parse a single prefix byte and remember it in the parser state. If in--- 64-bit mode, accept REX prefixes.--parsePrefix = do- (word8 0xf0 >>= addPrefix) -- LOCK- <|>- (word8 0xf2 >>= addPrefix) -- REPNE/REPNZ- <|>- (word8 0xf3 >>= addPrefix) -- REP or REPE/REPZ- <|>- (word8 0x2e >>= addPrefix) -- CS segment override- <|>- (word8 0x36 >>= addPrefix) -- SS segment override- <|>- (word8 0x3e >>= addPrefix) -- DS segment override- <|>- (word8 0x26 >>= addPrefix) -- ES segment override- <|>- (word8 0x64 >>= addPrefix) -- FS segment override- <|>- (word8 0x65 >>= addPrefix) -- GS segment override- <|>- (word8 0x2e >>= addPrefix) -- branch not taken- <|>- (word8 0x3e >>= addPrefix) -- branch taken- <|>- do word8 0x66 -- operand-size override- st <- getState- setState st{operandBitMode = toggleBitMode (operandBitMode st)}- addPrefix 0x66- <|>- do word8 0x67 -- address-size override- st <- getState- setState st{addressBitMode = toggleBitMode (addressBitMode st)}- addPrefix 0x66- <|> do st <- getState- if in64BitMode st - then (word8 0x40 >>= addPrefix)- <|>- (word8 0x41 >>= addPrefix)- <|>- (word8 0x42 >>= addPrefix)- <|>- (word8 0x43 >>= addPrefix)- <|>- (word8 0x44 >>= addPrefix)- <|>- (word8 0x45 >>= addPrefix)- <|>- (word8 0x46 >>= addPrefix)- <|>- (word8 0x47 >>= addPrefix)- <|>- (word8 0x48 >>= addPrefix)- <|>- (word8 0x49 >>= addPrefix)- <|>- (word8 0x4a >>= addPrefix)- <|>- (word8 0x4b >>= addPrefix)- <|>- (word8 0x4c >>= addPrefix)- <|>- (word8 0x4d >>= addPrefix)- <|>- (word8 0x4e >>= addPrefix)- <|>- (word8 0x4f >>= addPrefix)- else pzero---- Accept the single unsigned byte B.--word8 b = do- tokenPrim showByte nextPos testByte- where- showByte by = show by- nextPos pos x xs = incSourceColumn pos 1- testByte by = if b == by then Just by else Nothing---- Accept and return a single unsigned byte.--anyWord8 :: Word8Parser Word8-anyWord8 = do- tokenPrim showByte nextPos testByte- where- showByte by = show by- nextPos pos x xs = incSourceColumn pos 1- testByte by = Just by---- Accept any 8-bit signed byte.--anyInt8 :: Word8Parser Int8-anyInt8 = do- b <- anyWord8- let i :: Int8- i = fromIntegral b- return i---- Accept any 16-bit unsigned word.--anyWord16 = do- b0 <- anyWord8- b1 <- anyWord8- let w0, w1 :: Word16- w0 = fromIntegral b0- w1 = fromIntegral b1- return $ w0 .|. (w1 `shiftL` 8)---- Accept any 16-bit signed integer.--anyInt16 = do- b0 <- anyWord16- let w0 :: Int16- w0 = fromIntegral b0- return $ w0---- Accept a 32-bit unsigned word.--anyWord32 = do- b0 <- anyWord16- b1 <- anyWord16- let w0, w1 :: Word32- w0 = fromIntegral b0- w1 = fromIntegral b1- return $ w0 .|. (w1 `shiftL` 16)---- Accept a 32-bit signed integer.--anyInt32 :: Word8Parser Int32-anyInt32 = do- b0 <- anyWord32- let w0 :: Int32- w0 = fromIntegral b0- return $ w0---- Accept a 64-bit unsigned word.--anyWord64 :: Word8Parser Word64-anyWord64 = do- b0 <- anyWord32- b1 <- anyWord32- let w0, w1 :: Word64- w0 = fromIntegral b0- w1 = fromIntegral b1- return $ w0 .|. (w1 `shiftL` 32)---- Accept a 64-bit signed integer.--anyInt64 :: Word8Parser Int64-anyInt64 = do- b0 <- anyWord64- let w0 :: Int64- w0 = fromIntegral b0- return $ w0---- Accept a 16-bit word for 16-bit operand-size, a 32-bit word for--- 32-bit operand-size, or a 64-bit word in 64-bit mode.--anyWordV :: Word8Parser Word64-anyWordV = do- st <- getState- if in64BitMode st- then do w <- anyWord64- return w- else case operandBitMode st of- BIT16 -> do w <- anyWord16- let w' :: Word64- w' = fromIntegral w- return w'- BIT32 -> do w <- anyWord32- let w' :: Word64- w' = fromIntegral w- return w'---- Accept a 16-bit word for 16-bit operand-size or a 32-bit word for--- 32-bit operand-size or 64-bit mode.--anyWordZ :: Word8Parser Word32-anyWordZ = do- st <- getState- case operandBitMode st of- BIT16 -> do - w <- anyWord16- let w' :: Word32- w' = fromIntegral w- return w'- BIT32 -> anyWord32---- Accept a 16-bit integer for 16-bit operand-size or a 32-bit word for--- 32-bit operand-size or 64-bit mode.--anyIntZ :: Word8Parser Int32-anyIntZ = do- st <- getState- case operandBitMode st of- BIT16 -> do - w <- anyInt16- let w' :: Int32- w' = fromIntegral w- return w'- BIT32 -> anyInt32---- Accept a 32-bit far address for 16-bit operand-size or a 48-bit far--- address for 32-bit operand-size.--anyWordP :: Word8Parser Word64-anyWordP = do- st <- getState- case operandBitMode st of- BIT16 -> do w <- anyWord32- let w' :: Word64- w' = fromIntegral w- return w'- _ -> do w1 <- anyWord32- w2 <- anyWord16- let w1', w2' :: Word64- w1' = fromIntegral w1- w2' = fromIntegral w2- return (w1' .|. (w2' `shiftL` 32))--oneByteOpCodeMap =- [(0x00, parseALU ADD),- (0x01, parseALU ADD),- (0x02, parseALU ADD),- (0x03, parseALU ADD),- (0x04, parseALU ADD),- (0x05, parseALU ADD),- (0x06, invalidIn64BitMode (parsePUSHSeg "es")),- (0x07, invalidIn64BitMode (parsePOPSeg "es")),- (0x08, parseALU OR),- (0x09, parseALU OR),- (0x0a, parseALU OR),- (0x0b, parseALU OR),- (0x0c, parseALU OR),- (0x0d, parseALU OR),- (0x0e, invalidIn64BitMode (parsePUSHSeg "cs")),- (0x0f, twoByteEscape),-- (0x10, parseALU ADC),- (0x11, parseALU ADC),- (0x12, parseALU ADC),- (0x13, parseALU ADC),- (0x14, parseALU ADC),- (0x15, parseALU ADC),- (0x16, invalidIn64BitMode (parsePUSHSeg "ss")),- (0x17, invalidIn64BitMode (parsePOPSeg "ss")),- (0x18, parseALU SBB),- (0x19, parseALU SBB),- (0x1a, parseALU SBB),- (0x1b, parseALU SBB),- (0x1c, parseALU SBB),- (0x1d, parseALU SBB),- (0x1e, invalidIn64BitMode (parsePUSHSeg "ds")),- (0x1f, invalidIn64BitMode (parsePOPSeg "ds")),-- (0x20, parseALU AND),- (0x21, parseALU AND),- (0x22, parseALU AND),- (0x23, parseALU AND),- (0x24, parseALU AND),- (0x25, parseALU AND),- (0x26, parseInvalidPrefix), -- ES segment override prefix- (0x27, invalidIn64BitMode (parseGeneric DAA OPNONE)),- (0x28, parseALU SUB),- (0x29, parseALU SUB),- (0x2a, parseALU SUB),- (0x2b, parseALU SUB),- (0x2c, parseALU SUB),- (0x2d, parseALU SUB),- (0x2e, parseInvalidPrefix), -- CS segment override prefix- (0x2f, invalidIn64BitMode (parseGeneric DAS OPNONE)),-- (0x30, parseALU XOR),- (0x31, parseALU XOR),- (0x32, parseALU XOR),- (0x33, parseALU XOR),- (0x34, parseALU XOR),- (0x35, parseALU XOR),- (0x36, parseInvalidPrefix), -- SS segment override prefix- (0x37, invalidIn64BitMode (parseGeneric AAA OPNONE)),- (0x38, parseALU CMP),- (0x39, parseALU CMP),- (0x3a, parseALU CMP),- (0x3b, parseALU CMP),- (0x3c, parseALU CMP),- (0x3d, parseALU CMP),- (0x3e, parseInvalidPrefix), -- DS segment override prefix- (0x3f, invalidIn64BitMode (parseGeneric AAS OPNONE)),-- (0x40, invalidIn64BitMode parseINC), -- REX Prefix in 64-bit mode- (0x41, invalidIn64BitMode parseINC), -- ...- (0x42, invalidIn64BitMode parseINC),- (0x43, invalidIn64BitMode parseINC),- (0x44, invalidIn64BitMode parseINC),- (0x45, invalidIn64BitMode parseINC),- (0x46, invalidIn64BitMode parseINC),- (0x47, invalidIn64BitMode parseINC),- (0x48, invalidIn64BitMode parseDEC),- (0x49, invalidIn64BitMode parseDEC),- (0x4a, invalidIn64BitMode parseDEC),- (0x4b, invalidIn64BitMode parseDEC),- (0x4c, invalidIn64BitMode parseDEC),- (0x4d, invalidIn64BitMode parseDEC),- (0x4e, invalidIn64BitMode parseDEC),- (0x4f, invalidIn64BitMode parseDEC),-- (0x50, parsePUSH),- (0x51, parsePUSH),- (0x52, parsePUSH),- (0x53, parsePUSH),- (0x54, parsePUSH),- (0x55, parsePUSH),- (0x56, parsePUSH),- (0x57, parsePUSH),- (0x58, parsePOP),- (0x59, parsePOP),- (0x5a, parsePOP),- (0x5b, parsePOP),- (0x5c, parsePOP),- (0x5d, parsePOP),- (0x5e, parsePOP),- (0x5f, parsePOP),-- (0x60, invalidIn64BitMode parsePUSHA),- (0x61, invalidIn64BitMode parsePOPA),- (0x62, invalidIn64BitMode parseBOUND),- (0x63, choose64BitMode parseARPL parseMOVSXD), -- MOVSXD in 64-bit mode- (0x64, parseInvalidPrefix), -- FS segment override prefix- (0x65, parseInvalidPrefix), -- GS segment override prefix- (0x66, parseInvalidPrefix), -- operand-size prefix- (0x67, parseInvalidPrefix), -- address-size prefix- (0x68, parsePUSHImm),- (0x69, parseIMUL),- (0x6a, parsePUSHImm),- (0x6b, parseIMUL),- (0x6c, parseINS),- (0x6d, parseINS),- (0x6e, parseOUTS),- (0x6f, parseOUTS),-- (0x70, parseJccShort),- (0x71, parseJccShort),- (0x72, parseJccShort),- (0x73, parseJccShort),- (0x74, parseJccShort),- (0x75, parseJccShort),- (0x76, parseJccShort),- (0x77, parseJccShort),- (0x78, parseJccShort),- (0x79, parseJccShort),- (0x7a, parseJccShort),- (0x7b, parseJccShort),- (0x7c, parseJccShort),- (0x7d, parseJccShort),- (0x7e, parseJccShort),- (0x7f, parseJccShort),-- (0x80, parseGrp1),- (0x81, parseGrp1),- (0x82, invalidIn64BitMode parseGrp1),- (0x83, parseGrp1),- (0x84, parseTEST),- (0x85, parseTEST),- (0x86, parseXCHG),- (0x87, parseXCHG),- (0x88, parseMOV),- (0x89, parseMOV),- (0x8a, parseMOV),- (0x8b, parseMOV),- (0x8c, parseMOV),- (0x8d, parseLEA),- (0x8e, parseMOV),- (0x8f, parseGrp1A),-- (0x90, parse0x90), -- NOP, PAUSE(F3), XCHG r8,rAX- (0x91, parseXCHGReg),- (0x92, parseXCHGReg),- (0x93, parseXCHGReg),- (0x94, parseXCHGReg),- (0x95, parseXCHGReg),- (0x96, parseXCHGReg),- (0x97, parseXCHGReg),- (0x98, parseCBW_CWDE_CDQE),- (0x99, parseCWD_CDQ_CQO),- (0x9a, invalidIn64BitMode parseCALLF),- (0x9b, parseGeneric WAIT OPNONE),- (0x9c, parsePUSHF),- (0x9d, parsePOPF),- (0x9e, parseGeneric SAHF OPNONE),- (0x9f, parseGeneric LAHF OPNONE),-- (0xa0, parseMOVImm),- (0xa1, parseMOVImm),- (0xa2, parseMOVImm),- (0xa3, parseMOVImm),- (0xa4, parseMOVS),- (0xa5, parseMOVS),- (0xa6, parseCMPS),- (0xa7, parseCMPS),- (0xa8, parseTESTImm),- (0xa9, parseTESTImm),- (0xaa, parseSTOS),- (0xab, parseSTOS),- (0xac, parseLODS),- (0xad, parseLODS),- (0xae, parseSCAS),- (0xaf, parseSCAS),-- (0xb0, parseMOVImmByteToByteReg),- (0xb1, parseMOVImmByteToByteReg),- (0xb2, parseMOVImmByteToByteReg),- (0xb3, parseMOVImmByteToByteReg),- (0xb4, parseMOVImmByteToByteReg),- (0xb5, parseMOVImmByteToByteReg),- (0xb6, parseMOVImmByteToByteReg),- (0xb7, parseMOVImmByteToByteReg),- (0xb8, parseMOVImmToReg),- (0xb9, parseMOVImmToReg),- (0xba, parseMOVImmToReg),- (0xbb, parseMOVImmToReg),- (0xbc, parseMOVImmToReg),- (0xbd, parseMOVImmToReg),- (0xbe, parseMOVImmToReg),- (0xbf, parseMOVImmToReg),-- (0xc0, parseGrp2),- (0xc1, parseGrp2),- (0xc2, parseRETN),- (0xc3, parseRETN),- (0xc4, invalidIn64BitMode (parseLoadSegmentRegister LES)),- (0xc5, invalidIn64BitMode (parseLoadSegmentRegister LDS)),- (0xc6, parseGrp11),- (0xc7, parseGrp11),- (0xc8, parseENTER),- (0xc9, parseGeneric LEAVE OPNONE),- (0xca, parseGenericIw RETF),- (0xcb, parseGeneric RETF OPNONE),- (0xcc, parseGeneric INT3 OPNONE),- (0xcd, parseGenericIb INT),- (0xce, parseGeneric INTO OPNONE),- (0xcf, parseGeneric IRET OPNONE),-- (0xd0, parseGrp2),- (0xd1, parseGrp2),- (0xd2, parseGrp2),- (0xd3, parseGrp2),- (0xd4, parseGenericIb AAM),- (0xd5, parseGenericIb AAD),- (0xd6, parseReserved), -- reserved- (0xd7, parseGeneric XLAT OPNONE),- (0xd8, parseESC),- (0xd9, parseESC),- (0xda, parseESC),- (0xdb, parseESC),- (0xdc, parseESC),- (0xdd, parseESC),- (0xde, parseESC),- (0xdf, parseESC),-- (0xe0, parseGenericJb LOOPNE),- (0xe1, parseGenericJb LOOPE),- (0xe2, parseGenericJb LOOP),- (0xe3, parseGenericJb JCXZ), -- depends on bit mode- (0xe4, parseINImm),- (0xe5, parseINImm),- (0xe6, parseOUTImm),- (0xe7, parseOUTImm),- (0xe8, parseGenericJz CALL),- (0xe9, parseGenericJz JMP),- (0xea, parseJMPF),- (0xeb, parseGenericJb JMP),- (0xec, parseIN),- (0xed, parseIN),- (0xee, parseOUT),- (0xef, parseOUT),-- (0xf0, parseInvalidPrefix), -- LOCK prefix- (0xf1, parseReserved), -- reserved- (0xf2, parseInvalidPrefix), -- REPNE prefix- (0xf3, parseInvalidPrefix), -- REP/REPQ prefix- (0xf4, parseGeneric HLT OPNONE),- (0xf5, parseGeneric CMC OPNONE),- (0xf6, parseGrp3),- (0xf7, parseGrp3),- (0xf8, parseGeneric CLC OPNONE),- (0xf9, parseGeneric STC OPNONE),- (0xfa, parseGeneric CLI OPNONE),- (0xfb, parseGeneric STI OPNONE),- (0xfc, parseGeneric CLD OPNONE),- (0xfd, parseGeneric STD OPNONE),- (0xfe, parseGrp4),- (0xff, parseGrp5)-- ]--parseInvalidPrefix b = do- return $ Bad b "invalid prefix"--parseInvalidOpcode b = do- return $ Bad b "invalid opcode"--parseReserved b = do- return $ Bad b "reserved opcode"--parseUndefined name b = do- return $ Bad b ("undefined opcode: " ++ show name)--parseUnimplemented b = do- return $ Bad b "not implemented yet"--invalidIn64BitMode p b = do- st <- getState- if in64BitMode st- then return $ Bad b "invalid in 64-bit mode"- else p b--onlyIn64BitMode p b = do- st <- getState- if in64BitMode st- then p b- else return $ Bad b "only in 64-bit mode"--choose64BitMode p32 p64 b = do- st <- getState- if in64BitMode st- then p64 b- else p32 b--chooseOperandSize p16 p32 b = do- st <- getState- case operandBitMode st of- BIT16 -> p16 b- BIT32 -> p32 b--chooseAddressSize p16 p32 b = do- st <- getState- case addressBitMode st of- BIT16 -> p16 b- BIT32 -> p32 b--parseModRM = do- b <- anyWord8- parseModRM' b-parseModRM' b = do- return (b `shiftR` 6, (b `shiftR` 3) .&. 7, (b .&. 7))--parseSIB = do- b <- anyWord8- parseSIB' b-parseSIB' b = do- return (b `shiftR` 6, (b `shiftR` 3) .&. 7, (b .&. 7))--scaleToFactor 0 = 1-scaleToFactor 1 = 2-scaleToFactor 2 = 4-scaleToFactor 3 = 8---parseAddress32 :: InstrOperandSize ->- Word8Parser (Operand, Operand, Word8, Word8, Word8)-parseAddress32 s = do- b <- anyWord8- parseAddress32' s b--parseAddress32' :: InstrOperandSize -> - Word8 ->- Word8Parser (Operand, Operand, Word8, Word8, Word8)-parseAddress32' opsize modrm = do- (mod, reg_opc, rm) <- parseModRM' modrm- st <- getState- let opregnames = if in64BitMode st && hasREX rex_W st- then regnames64- else case operandBitMode st of - BIT16 -> regnames16- BIT32 -> regnames32- let addregnames = if in64BitMode st && hasREX rex_R st- then regnames64- else case addressBitMode st of - BIT16 -> regnames16- BIT32 -> regnames32- case mod of- 0 -> case rm of- 4 -> do - (s, i, b) <- parseSIB- case (i, b) of- (4, 5) -> do- disp <- anyWord32- return (OpAddr (fromIntegral disp) opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- (_, 5) -> do- disp <- anyWord32- return (OpIndexDisp (addregnames !! fromIntegral i)- (scaleToFactor s)- (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- (4, _) -> return (OpInd (addregnames !! fromIntegral b) opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- (_ ,_) -> return (OpBaseIndex - (addregnames !! fromIntegral b)- (addregnames !! fromIntegral i)- (scaleToFactor (fromIntegral s))- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- 5 -> do - disp <- anyWord32- return (OpAddr disp opsize, - OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- _ -> return (OpInd (addregnames !! fromIntegral rm) opsize, - OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- 1 -> case rm of- 4 -> do - (s, i, b) <- parseSIB- disp <- anyInt8- case i of- 4 -> return (OpIndDisp- (addregnames !! fromIntegral b) - (fromIntegral disp) opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- _ -> return (OpBaseIndexDisp- (addregnames !! fromIntegral b)- (addregnames !! fromIntegral i)- (scaleToFactor (fromIntegral s))- (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- _ -> do disp <- anyInt8- return (OpIndDisp- (addregnames !! fromIntegral rm) - (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- 2 -> case rm of- 4 -> do - (s, i, b) <- parseSIB- disp <- anyInt32- case i of- 4 -> return (OpIndDisp- (addregnames !! fromIntegral b)- (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- _ -> return (OpBaseIndexDisp- (addregnames !! fromIntegral b)- (addregnames !! fromIntegral i)- (scaleToFactor (fromIntegral s))- (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- _ -> do - disp <- anyInt32- return (OpIndDisp- (addregnames !! fromIntegral rm)- (fromIntegral disp)- opsize,- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)- 3 -> return (OpReg (opregnames !! fromIntegral rm)- (fromIntegral rm),- OpReg (opregnames !! fromIntegral reg_opc)- (fromIntegral reg_opc),- mod, reg_opc, rm)--parseALU :: Opcode -> Word8 -> Word8Parser Instr-parseALU op b = do- opsize <- instrOperandSize- case b .&. 0x07 of- 0 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr op OP8 [op1,- (OpReg (regnames8 !! fromIntegral reg)) (fromIntegral reg)]- 1 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr op opsize [op1, op2]- 2 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr op OP8 - [(OpReg (regnames8 !! fromIntegral reg))- (fromIntegral reg), op1]- 3 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr op opsize [op2, op1]- 4 -> do b <- anyWord8- return $ Instr op OP8 [(OpReg "al" 0), (OpImm (fromIntegral b))]- 5 -> do b <- anyWordZ- rn <- registerName 0- return $ Instr op opsize [(OpReg rn 0), (OpImm b)]- _ -> return $ Bad b "no ALU opcode (internal error)"- --parsePUSHSeg :: String -> Word8 -> Word8Parser Instr-parsePUSHSeg r _ = do- return $ Instr PUSH OP16 [(OpReg r 0)] -- FIXME: register number--parsePOPSeg :: String -> Word8 -> Word8Parser Instr-parsePOPSeg r _ = do- return $ Instr POP OP16 [(OpReg r 0)] -- FIXME: register number--parseGenericGvEw name b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP16- case op1 of- OpReg _ num -> return $ Instr name OP16 [op2, - OpReg (regnames16 !! num) num]- _ -> return $ Instr name OP8 [op2, op1]--parseGenericGvEb name b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- case op1 of- OpReg _ num -> return $ Instr name OP8 [op2, - OpReg (regnames8 !! num) num]- _ -> return $ Instr name OP8 [op2, op1]--parseGenericGvEv name b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr name opsize [op2, op1]--parseGenericEvGv name b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr name opsize [op1, op2]--parseGenericEbGb name b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr name OP8 [op1, (OpReg (regnames8 !! fromIntegral reg)- (fromIntegral reg))]--parseGenericEv name b = do- opsize <- instrOperandSize- (op1, op2, mod, _, rm) <- parseAddress32 opsize- return $ Instr name opsize [op1]--twoByteOpCodeMap = - [(0x00, parseGrp6),- (0x01, parseGrp7),- (0x02, parseGenericGvEw LAR),- (0x03, parseGenericGvEw LSL),- (0x04, parseReserved),- (0x05, onlyIn64BitMode (parseGeneric SYSCALL OPNONE)),- (0x06, parseGeneric CLTS OPNONE),- (0x07, onlyIn64BitMode (parseGeneric SYSCALL OPNONE)),- (0x08, parseGeneric INVD OPNONE),- (0x09, parseGeneric WBINVD OPNONE),- (0x0a, parseReserved),- (0x0b, parseUndefined UD2),- (0x0c, parseReserved),- (0x0d, parseGenericEv NOP),- (0x0e, parseReserved),- (0x0f, parseReserved),-- (0x10, parseMOVUPS),- (0x11, parseMOVUPS),- (0x12, parseMOVLPS),- (0x13, parseMOVLPS),- (0x14, parseUNPCKLPS),- (0x15, parseUNPCKHPS),- (0x16, parseMOVHPS),- (0x17, parseMOVHPS),- (0x18, parseGrp16),- (0x19, parseReserved),- (0x1a, parseReserved),- (0x1b, parseReserved),- (0x1c, parseReserved),- (0x1d, parseReserved),- (0x1e, parseReserved),- (0x1f, parseGenericEv NOP),-- (0x20, parseMOVCtrlDebug),- (0x21, parseMOVCtrlDebug),- (0x22, parseMOVCtrlDebug),- (0x23, parseMOVCtrlDebug),- (0x24, parseReserved),- (0x25, parseReserved),- (0x26, parseReserved),- (0x27, parseReserved),- (0x28, parseMOVAPS),- (0x29, parseMOVAPS),- (0x2a, parseCVTI2PS),- (0x2b, parseMOVNTPS),- (0x2c, parseCVTTPS2PI),- (0x2d, parseCVTPS2PI),- (0x2e, parseUCOMISS),- (0x2f, parseCOMISS),-- (0x30, parseGeneric WRMSR OPNONE),- (0x31, parseGeneric RDTSC OPNONE),- (0x32, parseGeneric RDMSR OPNONE),- (0x33, parseGeneric RDPMC OPNONE),- (0x34, parseGeneric SYSENTER OPNONE),- (0x35, parseGeneric SYSEXIT OPNONE),- (0x36, parseReserved),- (0x37, parseReserved),- (0x38, parseReserved),- (0x39, parseReserved),- (0x3a, parseReserved),- (0x3b, parseReserved),- (0x3c, parseReserved),- (0x3d, parseReserved),- (0x3e, parseReserved),- (0x3f, parseReserved),-- (0x40, parseCMOVcc),- (0x41, parseCMOVcc),- (0x42, parseCMOVcc),- (0x43, parseCMOVcc),- (0x44, parseCMOVcc),- (0x45, parseCMOVcc),- (0x46, parseCMOVcc),- (0x47, parseCMOVcc),- (0x48, parseCMOVcc),- (0x49, parseCMOVcc),- (0x4a, parseCMOVcc),- (0x4b, parseCMOVcc),- (0x4c, parseCMOVcc),- (0x4d, parseCMOVcc),- (0x4e, parseCMOVcc),- (0x4f, parseCMOVcc),-- (0x50, parseMOVSKPS),- (0x51, parseSQRTPS),- (0x52, parseRSQRTPS),- (0x53, parseRCPPS),- (0x54, parseANDPS),- (0x55, parseANDNPS),- (0x56, parseORPS),- (0x57, parseXORPS),- (0x58, parseADDPS),- (0x59, parseMULPS),- (0x5a, parseCVTPS2PD),- (0x5b, parseCVTDQ2PS),- (0x5c, parseSUBPS),- (0x5d, parseMINPS),- (0x5e, parseDIVPS),- (0x5f, parseMAXPS),-- (0x60, parsePUNPCKLBW),- (0x61, parsePUNPCKLWD),- (0x62, parsePUNPCKLDQ),- (0x63, parsePACKSSWB),- (0x64, parsePCMPGTB),- (0x65, parsePCMPGTW),- (0x66, parsePCMPGTD),- (0x67, parsePACKUSWB),- (0x68, parsePUNPCKHBW),- (0x69, parsePUNPCKHWD),- (0x6a, parsePUNPCKHDQ),- (0x6b, parsePACKSSDW),- (0x6c, parsePUNPCKLQDQ),- (0x6d, parsePUNPCKHQDQ),- (0x6e, parseMOVD_Q),- (0x6f, parseMOVQ),-- (0x70, parsePSHUFW),- (0x71, parseGrp12),- (0x72, parseGrp13),- (0x73, parseGrp14),- (0x74, parsePCMPEQB),- (0x75, parsePCMPEQW),- (0x76, parsePCMPEQD),- (0x77, parseGeneric EMMS OPNONE),- (0x78, parseVMREAD),- (0x79, parseVMWRITE),- (0x7a, parseReserved),- (0x7b, parseReserved),- (0x7c, parseHADDPS),- (0x7d, parseHSUBPS),- (0x7e, parseMOVD_Q),- (0x7f, parseMOVQ),-- (0x80, parseJccLong),- (0x81, parseJccLong),- (0x82, parseJccLong),- (0x83, parseJccLong),- (0x84, parseJccLong),- (0x85, parseJccLong),- (0x86, parseJccLong),- (0x87, parseJccLong),- (0x88, parseJccLong),- (0x89, parseJccLong),- (0x8a, parseJccLong),- (0x8b, parseJccLong),- (0x8c, parseJccLong),- (0x8d, parseJccLong),- (0x8e, parseJccLong),- (0x8f, parseJccLong),-- (0x90, parseSETcc),- (0x91, parseSETcc),- (0x92, parseSETcc),- (0x93, parseSETcc),- (0x94, parseSETcc),- (0x95, parseSETcc),- (0x96, parseSETcc),- (0x97, parseSETcc),- (0x98, parseSETcc),- (0x99, parseSETcc),- (0x9a, parseSETcc),- (0x9b, parseSETcc),- (0x9c, parseSETcc),- (0x9d, parseSETcc),- (0x9e, parseSETcc),- (0x9f, parseSETcc),-- (0xa0, parsePUSHSeg "fs"),- (0xa1, parsePOPSeg "fs"),- (0xa2, parseGeneric CPUID OPNONE),- (0xa3, parseGenericEvGv BT),- (0xa4, parseSHLD),- (0xa5, parseSHLD),- (0xa6, parseReserved),- (0xa7, parseReserved),- (0xa8, parsePUSHSeg "gs"),- (0xa9, parsePOPSeg "gs"),- (0xaa, parseGeneric RSM OPNONE),- (0xab, parseGenericEvGv BTS),- (0xac, parseSHRD),- (0xad, parseSHRD),- (0xae, parseGrp15),- (0xaf, parseGenericGvEv IMUL),-- (0xb0, parseGenericEbGb CMPXCHG),- (0xb1, parseGenericEvGv CMPXCHG),- (0xb2, parseLoadSegmentRegister LSS),- (0xb3, parseGenericEvGv BTR),- (0xb4, parseLoadSegmentRegister LFS),- (0xb5, parseLoadSegmentRegister LGS),- (0xb6, parseGenericGvEb MOVZXB),- (0xb7, parseGenericGvEw MOVZXW),- (0xb8, parseReserved),- (0xb9, parseGrp10),- (0xba, parseGrp8),- (0xbb, parseGenericEvGv BTC),- (0xbc, parseGenericGvEv BSF),- (0xbd, parseGenericGvEv BSR),- (0xbe, parseGenericGvEb MOVSXB),- (0xbf, parseGenericGvEw MOVSXW),-- (0xc0, parseGenericEbGb XADD),- (0xc1, parseGenericEvGv XADD),- (0xc2, parseCMPPS),- (0xc3, parseMOVNTI),- (0xc4, parsePINSRW),- (0xc5, parsePEXTRW),- (0xc6, parseSHUFPS),- (0xc7, parseGrp9),- (0xc8, parseBSWAP),- (0xc9, parseBSWAP),- (0xca, parseBSWAP),- (0xcb, parseBSWAP),- (0xcc, parseBSWAP),- (0xcd, parseBSWAP),- (0xce, parseBSWAP),- (0xcf, parseBSWAP),-- (0xd0, parseADDSUBPS),- (0xd1, parsePSRLW),- (0xd2, parsePSRLD),- (0xd3, parsePSRLQ),- (0xd4, parsePADDQ),- (0xd5, parsePMULLW),- (0xd6, parseMOVQ),- (0xd7, parsePMOVMSKB),- (0xd8, parsePSUBUSB),- (0xd9, parsePSUBUSW),- (0xda, parsePMINUB),- (0xdb, parsePAND),- (0xdc, parsePADDUSB),- (0xdd, parsePADDUSW),- (0xde, parsePMAXUB),- (0xdf, parsePANDN),-- (0xe0, parsePAVGB),- (0xe1, parsePSRAW),- (0xe2, parsePSRAD),- (0xe3, parsePAVGW),- (0xe4, parsePMULHUW),- (0xe5, parsePMULHW),- (0xe6, parseCVTPD2DQ),- (0xe7, parseMOVNTQ),- (0xe8, parsePSUBSB),- (0xe9, parsePSUBSQ),- (0xea, parsePMINSW),- (0xeb, parsePOR),- (0xec, parsePADDSB),- (0xed, parsePADDSW),- (0xee, parsePMAXSW),- (0xef, parsePXOR),-- (0xf0, parseLDDQU),- (0xf1, parsePSLLW),- (0xf2, parsePSLLD),- (0xf3, parsePSLLQ),- (0xf4, parsePMULUDQ),- (0xf5, parsePMADDWD),- (0xf6, parsePSADBW),- (0xf7, parseMASKMOVQ),- (0xf8, parsePSUBB),- (0xf9, parsePSUBW),- (0xfa, parsePSUBD),- (0xfb, parsePSUBQ),- (0xfc, parsePADDB),- (0xfd, parsePADDW),- (0xfe, parsePADDD),- (0xff, parseReserved)- ]--twoByteEscape :: Word8 -> Word8Parser Instr-twoByteEscape b1 = do- b <- anyWord8- case lookup b twoByteOpCodeMap of- Just p -> p b- Nothing -> return $ Bad b "invalid two-byte opcode"--parseGeneric name opsize _ = do- return (Instr name opsize [])-parseGenericIb name b = do- b <- anyWord8- return $ Instr name OP8 [OpImm (fromIntegral b)]-parseGenericIw name _ = do- w <- anyWord16- pos <- getPosition- return $ Instr name OP16 [OpImm (fromIntegral w)]-parseGenericJb name _ = do- b <- anyInt8- pos <- getPosition- st <- getState- return $ Instr name OPNONE - [OpAddr (fromIntegral ((fromIntegral b + sourceColumn pos - 1)) +- (startAddr st)) OPNONE]-parseGenericJz name _ = do- b <- anyIntZ- pos <- getPosition- st <- getState- return $ Instr name OPNONE - [OpAddr (fromIntegral ((fromIntegral b + sourceColumn pos - 1)) +- (startAddr st)) OPNONE]--parseINC b = do- opsize <- instrOperandSize- let reg = b .&. 0x0f- rn <- registerName (fromIntegral reg)- return $ Instr INC opsize [OpReg rn (fromIntegral reg)]--parseDEC b = do- opsize <- instrOperandSize- let reg = (b .&. 0x0f) - 8- rn <- registerName (fromIntegral reg)- return $ Instr DEC opsize [OpReg rn (fromIntegral reg)]--parsePUSH b = - let reg = b .&. 0x0f in do- st <- getState- rn <- registerName (fromIntegral reg)- opsize <- instrOperandSize- if hasREX rex_R st- then return $ Instr PUSH opsize [OpReg ("r" ++ show (reg + 8))- (fromIntegral reg)]- else return $ Instr PUSH opsize [OpReg rn- (fromIntegral reg)]--parsePOP b = - let reg = (b .&. 0x0f) - 8 in do- st <- getState- rn <- registerName (fromIntegral reg)- opsize <- instrOperandSize- if hasREX rex_R st- then return $ Instr POP opsize [OpReg ("r" ++ show (reg + 8))- (fromIntegral reg)]- else return $ Instr POP opsize [OpReg rn (fromIntegral reg)]--parsePUSHA = do- chooseOperandSize- (\ _ -> return $ Instr PUSHA OPNONE [])- (\ _ -> return $ Instr PUSHAD OPNONE [])-parsePOPA = do- chooseOperandSize- (\ _ -> return $ Instr POPA OPNONE [])- (\ _ -> return $ Instr POPAD OPNONE [])--parseBOUND b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- return $ Instr BOUND OPNONE [op2, op1]- -parseARPL b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP16- let rn = regnames16 !! fromIntegral reg- return $ Instr ARPL OPNONE [op1, (OpReg rn (fromIntegral reg))]- -parseMOVSXD b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- return $ Instr MOVSXD OPNONE [op2, op1]--parsePUSHImm 0x68 = do- w <- anyWordZ- opsize <- instrOperandSize- return $ Instr PUSH opsize [OpImm w]-parsePUSHImm 0x6a = do- w <- anyWord8- opsize <- instrOperandSize- return $ Instr PUSH opsize [OpImm (fromIntegral w)]--parseIMUL 0x69 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- imm <- anyWordZ- return $ Instr IMUL opsize [op2, op1, OpImm imm]-parseIMUL 0x6b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- imm <- anyWord8- return $ Instr IMUL opsize [op2, op1, OpImm (fromIntegral imm)]--parseINS 0x6c = return $ Instr INS OP8 []-parseINS b@0x6d = chooseOperandSize- (\ _ -> return $ Instr INS OP16 [])- (\ _ -> return $ Instr INS OP32 []) b--parseOUTS 0x6e = return $ Instr OUTS OP8 []-parseOUTS b@0x6f = chooseOperandSize- (\ _ -> return $ Instr OUTS OP16 [])- (\ _ -> return $ Instr OUTS OP32 []) b--parseJccShort b = do- disp <- anyInt8- pos <- getPosition- st <- getState- return $ Instr (jccname (b .&. 0xf)) OPNONE- [OpAddr (fromIntegral (fromIntegral disp + sourceColumn pos - 1) +- (startAddr st)) OPNONE]--parseTEST 0x84 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr TEST OP8 [op1, OpReg (regnames8 !! fromIntegral reg)- (fromIntegral reg)]-parseTEST 0x85 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr TEST opsize [op1, op2]--parseXCHG 0x86 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr XCHG OP8 [op1, OpReg (regnames8 !! fromIntegral reg)- (fromIntegral reg)]-parseXCHG 0x87 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr XCHG opsize[op1, op2]--parseMOV 0x88 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr MOV OP8 [op1, OpReg (regnames8 !! fromIntegral reg)- (fromIntegral reg)]-parseMOV 0x89 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr MOV opsize [op1, op2]-parseMOV 0x8a = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr MOV OP8 [OpReg (regnames8 !! fromIntegral reg) - (fromIntegral reg), op1]-parseMOV 0x8b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr MOV opsize [op2, op1]-parseMOV 0x8c = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP16- let rn = segregnames !! (fromIntegral reg)- return $ Instr MOV OP16 [op1, OpReg rn (fromIntegral reg)]-parseMOV 0x8e = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP16- let rn = segregnames !! (fromIntegral reg)- return $ Instr MOV OP16 [OpReg rn (fromIntegral reg), op1]--parseLEA b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- return $ Instr LEA OPNONE [op2, op1]---parse0x90 b = do- st <- getState- if hasPrefix 0xf3 st- then return $ Instr PAUSE OPNONE []- else do st <- getState- if in64BitMode st- then parseXCHGReg b- else return $ Instr NOP OPNONE []---- FIXME: Register name handling not quite right--parseXCHGReg :: Word8 -> Word8Parser Instr-parseXCHGReg b = - let reg = b .&. 0x0f in do- st <- getState- if hasREX rex_R st- then return $ Instr XCHG OP64 [OpReg "rax" 0, - OpReg ("r" ++ show (reg + 8))- (fromIntegral reg)]- else do rn <- registerName (fromIntegral reg)- return $ Instr XCHG OP64 [OpReg "rax" 0,- OpReg rn (fromIntegral reg)]--parseCBW_CWDE_CDQE b = do- st <- getState- if in64BitMode st- then if hasREX rex_W st- then return $ Instr CDQE OPNONE []- else return $ Instr CWDE OPNONE []- else chooseOperandSize- (\ _ -> return $ Instr CBW OPNONE [])- (\ _ -> return $ Instr CWDE OPNONE []) b--parseCWD_CDQ_CQO b = do- st <- getState- if in64BitMode st- then if hasREX rex_W st- then return $ Instr CDQE OPNONE []- else return $ Instr CDQ OPNONE []- else chooseOperandSize- (\ _ -> return $ Instr CWD OPNONE [])- (\ _ -> return $ Instr CDQ OPNONE []) b--parseCALLF b = do- w <- anyWord32- s <- anyWord16- return $ Instr CALLF OPNONE [OpImm (fromIntegral w),- OpImm (fromIntegral s)]---- FIXME: Check default/operand sizes.--parsePUSHF b = do- st <- getState- if in64BitMode st- then chooseOperandSize- (\ _ -> return $ Instr PUSHF OPNONE [])- (\ _ -> return $ Instr PUSHFQ OPNONE []) b- else chooseOperandSize- (\ _ -> return $ Instr PUSHF OPNONE [])- (\ _ -> return $ Instr PUSHFD OPNONE []) b--parsePOPF b = do- st <- getState- if in64BitMode st- then chooseOperandSize- (\ _ -> return $ Instr POPF OPNONE [])- (\ _ -> return $ Instr POPFQ OPNONE []) b- else chooseOperandSize- (\ _ -> return $ Instr POPF OPNONE [])- (\ _ -> return $ Instr POPFD OPNONE []) b--parseJMPF b = do- w <- anyWord32- return $ Instr JMPF OPNONE [OpImm w]--parseMOVImm b@0xa0 = do- chooseAddressSize- (\ _ -> do w <- anyWord16- return $ Instr MOV OP8 [OpReg "al" 0, OpImm (fromIntegral w)])- (\ _ -> do w <- anyWord32- return $ Instr MOV OP8 [OpReg "al" 0, OpImm w]) b-parseMOVImm b@0xa1 = do- opsize <- instrOperandSize- reg <- registerName 0- chooseAddressSize- (\ _ -> do w <- anyWord16- return $ Instr MOV opsize [OpReg reg 0, OpImm (fromIntegral w)])- (\ _ -> do w <- anyWord32- return $ Instr MOV opsize [OpReg reg 0, OpImm w]) b-parseMOVImm b@0xa2 = do- chooseAddressSize- (\ _ -> do w <- anyWord16- return $ Instr MOV OP8 [OpImm (fromIntegral w), OpReg "al" 0])- (\ _ -> do w <- anyWord32- return $ Instr MOV OP8 [OpImm w, OpReg "al" 0]) b-parseMOVImm b@0xa3 = do- opsize <- instrOperandSize- reg <- registerName 0- chooseAddressSize- (\ _ -> do w <- anyWord16- return $ Instr MOV opsize [OpImm (fromIntegral w), OpReg reg 0])- (\ _ -> do w <- anyWord32- return $ Instr MOV opsize [OpImm w, OpReg reg 0]) b--parseMOVS 0xa4 = return $ Instr MOVS OP8 []-parseMOVS b@0xa5 = do- st <- getState- opsize <- instrOperandSize- return $ Instr MOVS opsize []--parseCMPS 0xa6 = return $ Instr CMPS OP8 []-parseCMPS 0xa7 = do- st <- getState- opsize <- instrOperandSize- return $ Instr CMPS opsize []--parseTESTImm 0xa8 = do- imm <- anyWord8- return $ Instr TEST OP8 [OpReg "al" 0, OpImm (fromIntegral imm)]-parseTESTImm 0xa9 = do- imm <- anyWordZ- rn <- registerName 0- opsize <- instrOperandSize- return $ Instr TEST opsize [OpReg rn 0, OpImm imm]- --parseSTOS 0xaa = return $ Instr STOS OP8 []-parseSTOS b@0xab = do- st <- getState- opsize <- instrOperandSize- if in64BitMode st- then if hasREX rex_W st- then return $ Instr STOS opsize []- else chooseOperandSize- (\ _ -> return $ Instr STOS opsize [])- (\ _ -> return $ Instr STOS opsize []) b- else chooseOperandSize- (\ _ -> return $ Instr STOS opsize [])- (\ _ -> return $ Instr STOS opsize []) b--parseLODS 0xac = return $ Instr LODS OP8 []-parseLODS b@0xad = do- st <- getState- opsize <- instrOperandSize- if in64BitMode st- then if hasREX rex_W st- then return $ Instr LODS opsize []- else chooseOperandSize- (\ _ -> return $ Instr LODS opsize [])- (\ _ -> return $ Instr LODS opsize []) b- else chooseOperandSize- (\ _ -> return $ Instr LODS opsize [])- (\ _ -> return $ Instr LODS opsize []) b--parseSCAS 0xae = return $ Instr SCAS OP8 []-parseSCAS b@0xaf = do- st <- getState- opsize <- instrOperandSize- if in64BitMode st- then if hasREX rex_W st- then return $ Instr SCAS opsize []- else chooseOperandSize- (\ _ -> return $ Instr SCAS opsize [])- (\ _ -> return $ Instr SCAS opsize []) b- else chooseOperandSize- (\ _ -> return $ Instr SCAS opsize [])- (\ _ -> return $ Instr SCAS opsize []) b--parseMOVImmByteToByteReg :: Word8 -> Word8Parser Instr-parseMOVImmByteToByteReg b = do- let reg = b .&. 0x0f- st <- getState- imm <- anyWord8- if hasREX rex_R st- then return $ Instr MOV OP8 [OpReg ("r" ++ show reg ++ "l")- (fromIntegral reg),- OpImm (fromIntegral imm)]- else return $ Instr MOV OP8 [OpReg (regnames8 !! (fromIntegral reg))- (fromIntegral reg), - OpImm (fromIntegral imm)]--parseMOVImmToReg :: Word8 -> Word8Parser Instr-parseMOVImmToReg b = do- let reg = (b .&. 0x0f - 8)- imm <- anyWordV- opsize <- instrOperandSize- rn <- registerName (fromIntegral reg)- return $ Instr MOV opsize [OpReg rn (fromIntegral reg), - OpImm (fromIntegral imm)]--parseRETN 0xc2 = do- w <- anyWord16- return $ Instr RET OPNONE [OpImm (fromIntegral w)]-parseRETN 0xc3 = return $ Instr RET OPNONE []--parseLoadSegmentRegister opcode b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- return $ Instr opcode OPNONE [op2, op1]--parseENTER b = do- w <- anyWord16- b <- anyWord8- return $ Instr ENTER OPNONE [OpImm (fromIntegral w), - OpImm (fromIntegral b)]---- Floating-point operations. These can probably shortened by doing some--- arithmetic/logical tricks on the opcodes, but since the instruction--- set is still quite irregular (even though much better than the integer--- ops), I haven't bothered yet.--parseESC 0xd8 = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1, op2, mod, reg, rm) <- parseAddress32' OPF32 modrm- return $ Instr (ops !! fromIntegral reg) OPF32 [op1]- else if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]- else return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8))]- where ops = [FADD, FMUL, FCOM, FCOMP, - FSUB, FSUBR, FDIV, FDIVR]- -parseESC b@0xd9 = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- let op1 = case op1' of - OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)- op -> op- return $ Instr (lowOps !! fromIntegral reg) - (opsizes !! fromIntegral reg) [op1]- else if (modrm < 0xd0)- then if (modrm .&. 0x0f) < 8- then return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]- else return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f)- - 8)]- else case modrm of- 0xd0 -> return $ Instr FNOP OPNONE []- 0xe0 -> return $ Instr FCHS OPNONE []- 0xe1 -> return $ Instr FABS OPNONE []- 0xe4 -> return $ Instr FTST OPNONE []- 0xe5 -> return $ Instr FXAM OPNONE []- 0xe8 -> return $ Instr FLD1 OPNONE []- 0xe9 -> return $ Instr FLDL2T OPNONE []- 0xea -> return $ Instr FLDL2E OPNONE []- 0xeb -> return $ Instr FLDPI OPNONE []- 0xec -> return $ Instr FLDLG2 OPNONE []- 0xed -> return $ Instr FLDLN2 OPNONE []- 0xee -> return $ Instr FLDZ OPNONE []- _ -> parseInvalidOpcode b- where lowOps = [FLD, InvalidOpcode, FST, FSTP, - FLDENV, FLDCW, FSTENV, FSTCW]- opsizes = [OPF32, OPNONE, OPF32, OPF32,- OPNONE, OPNONE, OPNONE, OPNONE]- ops = [FLD, FXCH]--parseESC 0xda = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- return $ Instr (ops !! fromIntegral reg) OPNONE [op1]- else if (modrm < 0xe0)- then return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]- else case modrm of- 0xe1 -> return $ Instr FUCOMPP OPNONE []- _ -> parseInvalidOpcode 0xda- where ops = [FIADD, FIMUL, FICOM, FICOMP, - FISUB, FISUBR, FIDIV, FIDIVR]- ops' = [FCMOVB, FCMOVE, FCMOVBE, FCMOVU]--parseESC 0xdb = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- let op1 = case op1' of - OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)- op -> op- return $ Instr (ops !! fromIntegral reg) - (opsizes !! fromIntegral reg) [op1]- else - case modrm of- 0xe2 -> return $ Instr FCLEX OPNONE []- 0xe3 -> return $ Instr FINIT OPNONE []- _ ->- if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]- else return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg 0, OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8))]- where ops = [FILD, FISTP, FIST, FISTP, - InvalidOpcode, FLD, InvalidOpcode, FSTP]- opsizes = [OP32, OP32, OP32, OP32,- OPNONE, OPF80, OPNONE, OPF80]- ops' = [FCMOVNB, FCMOVNE, FCMOVNBE, FCMOVNU,- InvalidOpcode, FUCOMI, FCOMI, InvalidOpcode]--parseESC 0xdc = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- return $ Instr (ops !! fromIntegral reg) OPNONE [op1]- else- if modrm >= 0xd0 && modrm < 0xe0- then parseInvalidOpcode 0xdc- else if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]- else return $ Instr - (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]- where ops = [FADD, FMUL, FCOM, FCOMP, - FSUB, FSUBR, FDIV, FDIVR]- -parseESC 0xdd = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- let op1 = case op1' of - OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)- op -> op- return $ Instr (ops !! fromIntegral reg) - (opsizes !! fromIntegral reg) [op1]- else- if (modrm >= 0xc8) && modrm <= 0xd0 || (modrm >= 0xf0 && modrm < 0xff)- then parseInvalidOpcode 0xdc- else if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]- else return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]- where ops = [FLD, FISTTP, FST, FSTP, - FRSTOR, InvalidOpcode, FSAVE, FSTSW]- opsizes = [OPF64, OP64, OPF64, OPF64,- OPNONE, OPNONE, OPNONE, OP16]- ops' = [FFREE, InvalidOpcode, FST, FSTP, - FUCOM, FUCOMP]- -parseESC 0xde = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- return $ Instr (ops !! fromIntegral reg) OPNONE [op1]- else- if modrm >= 0xd0 && modrm <= 0xe0- then case modrm of- 0xd9 -> return $ Instr FCOMPP OPNONE []- _ -> parseInvalidOpcode 0xde- else if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]- else return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]- where ops = [FIADD, FIMUL, FICOM, FICOMP, - FISUB, FISUBR, FIDIV, FIDIVR]- ops' = [FADDP, FMULP, InvalidOpcode, InvalidOpcode,- FSUBRP, FSUBP, FDIVRP, FDIVP]- - -parseESC 0xdf = do- modrm <- anyWord8- let modrm' :: Word8- modrm' = modrm - 0xc0- if modrm <= 0xbf- then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm- return $ Instr (ops !! fromIntegral reg) OPNONE [op1]- else- case modrm of- 0xe0 -> return $ Instr FSTSW OPNONE [OpReg "ax" 0]- _ -> - if (modrm >= 0xe8 && modrm <= 0xef) ||- (modrm >= 0xf0 && modrm <= 0xf7)- then- if (modrm .&. 0x0f) < 0x8- then return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]- else return $ Instr - (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE- [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]- else parseInvalidOpcode 0xdf- where ops = [FILD, FISTPP, FIST, FISTP, - FBLD, FILD, FBSTP, FISTP]- ops' = [InvalidOpcode, InvalidOpcode, InvalidOpcode, InvalidOpcode,- InvalidOpcode, FUCOMIP, FCOMIP, InvalidOpcode]--parseINImm 0xe4 = do- b <- anyWord8- return $ Instr IN OP8 [OpReg "al" 0, OpImm (fromIntegral b)]-parseINImm 0xe5 = do- b <- anyWord8- rn <- registerName 0- opsize <- instrOperandSize- return $ Instr IN opsize [OpReg rn 0, OpImm (fromIntegral b)]-parseOUTImm 0xe6 = do- b <- anyWord8- return $ Instr OUT OP8 [OpImm (fromIntegral b), OpReg "al" 0]-parseOUTImm 0xe7 = do- b <- anyWord8- rn <- registerName 0- opsize <- instrOperandSize- return $ Instr OUT opsize [OpImm (fromIntegral b), OpReg rn 0]--parseIN 0xec = do- return $ Instr IN OP8 [OpReg "al" 0, OpReg "dx" 2]-parseIN 0xed = do- rn <- registerName 0- opsize <- instrOperandSize- return $ Instr IN opsize [OpReg rn 0, OpReg "dx" 2]-parseOUT 0xee = do- return $ Instr OUT OP8 [OpReg "dx" 2, OpReg "al" 0]-parseOUT 0xef = do- rn <- registerName 0- opsize <- instrOperandSize- return $ Instr OUT opsize [OpReg "dx" 2, OpReg rn 0]---- Return the name of the register encoded with R. Take 64-bit mode and--- possible REX and operand-size prefixes into account.--registerName r = do- st <- getState- if in64BitMode st && hasREX rex_R st- then return $ "r" ++ show (r + 8)- else case operandBitMode st of- BIT16 -> return $ regnames16 !! r- BIT32 -> return $ regnames32 !! r--instrOperandSize = do- st <- getState- if in64BitMode st && hasREX rex_W st- then return $ OP64- else case operandBitMode st of- BIT16 -> return OP16- BIT32 -> return OP32--regnames8 = ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"]-regnames16 = ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di"]-regnames32 = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"]-regnames64 = ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"]-segregnames = ["es", "cs", "ss", "ds", "fs", "gs", "<invalid>", "<invalid>"]-mmxregs = ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"]-xmmregs = ["xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"]--jccname 0 = JO-jccname 1 = JNO-jccname 2 = JB-jccname 3 = JNB-jccname 4 = JE-jccname 5 = JNE-jccname 6 = JBE-jccname 7 = JA-jccname 8 = JS-jccname 9 = JNS-jccname 10 = JP-jccname 11 = JNP-jccname 12 = JL-jccname 13 = JGE-jccname 14 = JLE-jccname 15 = JG--setccname 0 = SETO-setccname 1 = SETNO-setccname 2 = SETB-setccname 3 = SETNB-setccname 4 = SETE-setccname 5 = SETNE-setccname 6 = SETBE-setccname 7 = SETA-setccname 8 = SETS-setccname 9 = SETNS-setccname 10 = SETP-setccname 11 = SETNP-setccname 12 = SETL-setccname 13 = SETGE-setccname 14 = SETLE-setccname 15 = SETG--cmovccname 0 = CMOVO-cmovccname 1 = CMOVNO-cmovccname 2 = CMOVB-cmovccname 3 = CMOVNB-cmovccname 4 = CMOVE-cmovccname 5 = CMOVNE-cmovccname 6 = CMOVBE-cmovccname 7 = CMOVA-cmovccname 8 = CMOVS-cmovccname 9 = CMOVNS-cmovccname 10 = CMOVP-cmovccname 11 = CMOVNP-cmovccname 12 = CMOVL-cmovccname 13 = CMOVGE-cmovccname 14 = CMOVLE-cmovccname 15 = CMOVG--parseGrp1 0x80 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- immb <- anyWord8- return $ Instr (aluOps !! fromIntegral reg) OP8 - [op1, OpImm (fromIntegral immb)]-parseGrp1 0x81 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- immb <- anyWordZ- return $ Instr (aluOps !! fromIntegral reg) opsize - [op1, OpImm (fromIntegral immb)]-parseGrp1 0x82 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- immb <- anyWord8- return $ Instr (aluOps !! fromIntegral reg) OP8 - [op1, OpImm (fromIntegral immb)]-parseGrp1 0x83 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- immb <- anyWord8- return $ Instr (aluOps !! fromIntegral reg) opsize- [op1, OpImm (fromIntegral immb)]-aluOps = [ADD, OR, ADC, SBB, AND, SUB, XOR, CMP]---parseGrp1A b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- case reg of- 0 -> return $ Instr POP opsize [op1]- _ -> parseInvalidOpcode b--parseGrp2 0xc0 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- immb <- anyWord8- return $ Instr (shiftOps !! fromIntegral reg) OP8 - [op1, OpImm (fromIntegral immb)]-parseGrp2 0xc1 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- imm <- anyWord8- return $ Instr (shiftOps !! fromIntegral reg) opsize- [op1, OpImm (fromIntegral imm)]-parseGrp2 0xd0 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr (shiftOps !! fromIntegral reg) OP8 [op1, OpImm 1]-parseGrp2 0xd1 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr (shiftOps !! fromIntegral reg) opsize [op1, OpImm 1]-parseGrp2 0xd2 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- return $ Instr (shiftOps !! fromIntegral reg) OP8 [op1, OpReg "cl" 1]-parseGrp2 0xd3 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr (shiftOps !! fromIntegral reg) opsize [op1, OpReg "cl" 1]-shiftOps = [ROL, ROR, RCL, RCR, SHL, SHR, InvalidOpcode, SAR]--parseGrp3 0xf6 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- case reg of- 0 -> do imm <- anyWord8- return $ Instr TEST OP8 [op1, OpImm (fromIntegral imm)]- 1 -> parseInvalidOpcode 0xf6- 2 -> return $ Instr NOT OP8 [op1]- 3 -> return $ Instr NEG OP8 [op1]- 4 -> return $ Instr MUL OP8 [OpReg "al" 0, op1]- 5 -> return $ Instr IMUL OP8 [OpReg "al" 0, op1]- 6 -> return $ Instr DIV OP8 [OpReg "al" 0, op1]- 7 -> return $ Instr IDIV OP8 [OpReg "al" 0, op1]-parseGrp3 0xf7 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- rn <- registerName 0- case reg of- 0 -> do imm <- anyWordZ- return $ Instr TEST opsize [op1, OpImm (fromIntegral imm)]- 1 -> parseInvalidOpcode 0xf6- 2 -> return $ Instr NOT opsize [op1]- 3 -> return $ Instr NEG opsize [op1]- 4 -> return $ Instr MUL opsize [OpReg rn 0, op1]- 5 -> return $ Instr IMUL opsize [OpReg rn 0, op1]- 6 -> return $ Instr DIV opsize [OpReg rn 0, op1]- 7 -> return $ Instr IDIV opsize [OpReg rn 0, op1]--parseGrp4 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- case reg of- 0 -> return $ Instr INC OP8 [op1]- 1 -> return $ Instr DEC OP8 [op1]- _ -> parseInvalidOpcode b--parseGrp5 b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- case reg of- 0 -> return $ Instr INC opsize [op1]- 1 -> return $ Instr DEC opsize [op1]- 2 -> return $ Instr CALL OPNONE [op1]- 3 -> do w <- anyWord16- return $ Instr CALLF OPNONE [OpAddr (fromIntegral w) OPNONE, op1]- 4 -> return $ Instr JMPN OPNONE [op1]- 5 -> do w <- anyWord16- return $ Instr JMPF OPNONE [OpAddr (fromIntegral w) OPNONE, op1]- 6 -> return $ Instr PUSH opsize [op1]- _ -> parseInvalidOpcode b--parseGrp6 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- case reg of- 0 -> return $ Instr SLDT OPNONE [op1]- 1 -> return $ Instr STR OPNONE [op1]- 2 -> return $ Instr LLDT OPNONE [op1]- 3 -> return $ Instr LTR OPNONE [op1]- 4 -> return $ Instr VERR OPNONE [op1]- 5 -> return $ Instr VERW OPNONE [op1]- _ -> parseInvalidOpcode b--parseGrp7 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- case mod of- 3 -> case reg of- 0 -> case rm of- 1 -> return $ Instr VMCALL OPNONE []- 2 -> return $ Instr VMLAUNCH OPNONE []- 3 -> return $ Instr VMRESUME OPNONE []- 4 -> return $ Instr VMXOFF OPNONE []- _ -> parseInvalidOpcode b- 1 -> case rm of- 0 -> return $ Instr MONITOR OPNONE []- 1 -> return $ Instr MWAIT OPNONE []- _ -> parseInvalidOpcode b- 4 -> return $ Instr SMSW OPNONE [op1]- 6 -> return $ Instr LMSW OPNONE [op1]- 7 -> case rm of- 0 -> onlyIn64BitMode- (\b -> return $ Instr SWAPGS OPNONE []) b- _ -> parseInvalidOpcode b- _ -> parseInvalidOpcode b- _ -> case reg of- 0 -> return $ Instr SGDT OPNONE [op1]- 1 -> return $ Instr SIDT OPNONE [op1]- 2 -> return $ Instr LGDT OPNONE [op1]- 3 -> return $ Instr LIDT OPNONE [op1]- 4 -> return $ Instr SMSW OPNONE [op1]- 5 -> parseInvalidOpcode b- 6 -> return $ Instr LMSW OPNONE [op1]- 7 -> return $ Instr INVLPG OPNONE [op1]--parseGrp8 b = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- imm <- anyWord8- case reg of- 4 -> return $ Instr BT opsize [op1, OpImm (fromIntegral imm)]- 5 -> return $ Instr BTS opsize [op1, OpImm (fromIntegral imm)]- 6 -> return $ Instr BTR opsize [op1, OpImm (fromIntegral imm)]- 7 -> return $ Instr BTC opsize [op1, OpImm (fromIntegral imm)]- _ -> parseInvalidOpcode b--parseGrp9 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- st <- getState- case mod of- 3 -> parseInvalidOpcode b- _ -> case reg of- 1 -> if hasREX rex_W st- then return $ Instr CMPXCHG16B OPNONE [op1]- else return $ Instr CMPXCHG8B OPNONE [op1]- 6 -> if hasPrefix 0x66 st- then return $ Instr VMCLEAR OPNONE [op1]- else if hasPrefix 0xf3 st- then return $ Instr VMXON OPNONE [op1]- else return $ Instr VMPTRLD OPNONE [op1]- 7 -> return $ Instr VMPTRST OPNONE [op1]- _ -> parseInvalidOpcode b--parseGrp10 = parseInvalidOpcode--parseGrp11 0xc6 = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- imm <- anyWord8- return $ Instr MOV OP8 [op1, OpImm (fromIntegral imm)]-parseGrp11 0xc7 = do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- imm <- anyWordZ- return $ Instr MOV opsize [op1, OpImm (fromIntegral imm)]--mmxInstr op1 mod reg rm name = do- st <- getState- imm <- anyWord8- if hasPrefix 0x66 st- then return $ Instr name OP128- [OpReg (xmmregs !! fromIntegral rm) (fromIntegral rm),- OpImm (fromIntegral imm)]- else return $ Instr name OP64- [OpReg (mmxregs !! fromIntegral rm) (fromIntegral rm),- OpImm (fromIntegral imm)]- -parseGrp12 b = do- st <- getState- let opsize = if hasPrefix 0x66 st then OP128 else OP64- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- case mod of- 3 -> case reg of- 2 -> mmxInstr op1 mod reg rm PSRLW- 4 -> mmxInstr op1 mod reg rm PSRAW- 6 -> mmxInstr op1 mod reg rm PSLLW- _ -> parseInvalidOpcode b- _ -> parseInvalidOpcode b-parseGrp13 b = do- st <- getState- let opsize = if hasPrefix 0x66 st then OP128 else OP64- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- case mod of- 3 -> case reg of- 2 -> mmxInstr op1 mod reg rm PSRLD- 4 -> mmxInstr op1 mod reg rm PSRAD- 6 -> mmxInstr op1 mod reg rm PSLLD- _ -> parseInvalidOpcode b- _ -> parseInvalidOpcode b-parseGrp14 b = do- st <- getState- let opsize = if hasPrefix 0x66 st then OP128 else OP64- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- st <- getState- case mod of- 3 -> case reg of- 2 -> mmxInstr op1 mod reg rm PSRLQ- 3 -> if hasPrefix 0x66 st- then mmxInstr op1 mod reg rm PSRLDQ- else parseInvalidOpcode b- 6 -> mmxInstr op1 mod reg rm PSLLQ- 7 -> if hasPrefix 0x66 st- then mmxInstr op1 mod reg rm PSLLDQ- else parseInvalidOpcode b- _ -> parseInvalidOpcode b- _ -> parseInvalidOpcode b--parseGrp15 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- case mod of- 3 -> case reg of- 5 -> return $ Instr LFENCE OPNONE []- 6 -> return $ Instr MFENCE OPNONE []- 7 -> return $ Instr SFENCE OPNONE []- _ -> parseInvalidOpcode b- _ -> case reg of- 0 -> return $ Instr FXSAVE OPNONE [op1]- 1 -> return $ Instr FXRSTOR OPNONE [op1]- 2 -> return $ Instr LDMXCSR OPNONE [op1]- 3 -> return $ Instr STMXCSR OPNONE [op1]- 7 -> return $ Instr CLFLUSH OPNONE [op1]- _ -> parseInvalidOpcode b-parseGrp16 b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE- case mod of- 3 -> parseInvalidOpcode b- _ -> case reg of- 0 -> return $ Instr PREFETCHNTA OPNONE [op1]- 1 -> return $ Instr PREFETCHT0 OPNONE [op1]- 2 -> return $ Instr PREFETCHT1 OPNONE [op1]- 3 -> return $ Instr PREFETCHT2 OPNONE [op1]- _ -> parseInvalidOpcode b--parseXmmVW p p0xf3 p0x66 p0xf2 b =- do (op1, op2, mod, reg, rm) <- parseAddress32 OP128- st <- getState- let v = OpReg (xmmregs !! (fromIntegral reg)) (fromIntegral reg)- let w = case op1 of- OpReg _ num -> OpReg (xmmregs !! num) num- op -> op- if hasPrefix 0xf3 st- then return $ Instr p0xf3 OP128 [v, w]- else if hasPrefix 0x66 st- then return $ Instr p0x66 OP128 [v, w]- else if hasPrefix 0xf2 st- then return $ Instr p0xf2 OP128 [v, w]- else return $ Instr p OP128 [v, w]-parseXmmWV p p0xf3 p0x66 p0xf2 b =- do (op1, op2, mod, reg, rm) <- parseAddress32 OP128- st <- getState- let w = OpReg (xmmregs !! (fromIntegral reg)) (fromIntegral reg)- let v = case op1 of- OpReg _ num -> OpReg (xmmregs !! num) num- op -> op- if hasPrefix 0xf3 st- then return $ Instr p0xf3 OP128 [v, w]- else if hasPrefix 0x66 st- then return $ Instr p0x66 OP128 [v, w]- else if hasPrefix 0xf2 st- then return $ Instr p0xf2 OP128 [v, w]- else return $ Instr p OP128 [v, w]--parseXmmGU p p0xf3 p0x66 p0xf2 b =- do (mod, reg, rm) <- parseModRM- st <- getState- let g = OpReg (regnames32 !! (fromIntegral reg)) (fromIntegral reg)- let u = OpReg (xmmregs !! (fromIntegral rm)) (fromIntegral rm)- if hasPrefix 0xf3 st- then return $ Instr p0xf3 OP32 [g, u]- else if hasPrefix 0x66 st- then return $ Instr p0x66 OP32 [g, u]- else if hasPrefix 0xf2 st- then return $ Instr p0xf2 OP32 [g, u]- else return $ Instr p OP32 [g, u]--parseMOVUPS b@0x10 = parseXmmVW MOVUPS MOVSS MOVUPD MOVSD b-parseMOVUPS b@0x11 = parseXmmWV MOVUPS MOVSS MOVUPD MOVSD b-parseMOVLPS b@0x12 = parseXmmWV MOVLPS MOVSLDUP MOVLPD MOVDDUP b-parseMOVLPS b@0x13 = parseXmmVW MOVLPS InvalidOpcode MOVLPD InvalidOpcode b-parseUNPCKLPS b@0x14 =- parseXmmVW UNPCKLPS InvalidOpcode UNPCKLPD InvalidOpcode b-parseUNPCKHPS b@0x15 = - parseXmmVW UNPCKHPS InvalidOpcode UNPCKHPD InvalidOpcode b-parseMOVHPS b@0x16 = parseXmmVW MOVHPS MOVLSDUP MOVHPD MOVLHPS b-parseMOVHPS b@0x17 = parseXmmVW MOVHPS InvalidOpcode MOVHPD InvalidOpcode b--parseMOVCtrlDebug 0x20 = - do (mod, reg, rm) <- parseModRM- return $ Instr MOV OPNONE [OpReg (regnames32 !! fromIntegral rm)- (fromIntegral rm),- OpReg ("cr" ++ show reg) (fromIntegral reg)]-parseMOVCtrlDebug 0x21 = - do (mod, reg, rm) <- parseModRM- return $ Instr MOV OPNONE [OpReg (regnames32 !! fromIntegral rm)- (fromIntegral rm),- OpReg ("db" ++ show reg) (fromIntegral reg)]-parseMOVCtrlDebug 0x22 = - do (mod, reg, rm) <- parseModRM- return $ Instr MOV OPNONE [OpReg ("cr" ++ show reg) (fromIntegral reg),- OpReg (regnames32 !! fromIntegral rm)- (fromIntegral rm)]-parseMOVCtrlDebug 0x23 = - do (mod, reg, rm) <- parseModRM- return $ Instr MOV OPNONE [OpReg ("db" ++ show reg) (fromIntegral reg),- OpReg (regnames32 !! fromIntegral rm)- (fromIntegral rm)]- --parseMOVAPS b@0x28 = parseXmmVW MOVAPS InvalidOpcode MOVAPD InvalidOpcode b-parseMOVAPS b@0x29 = parseXmmWV MOVAPS InvalidOpcode MOVAPD InvalidOpcode b-parseCVTI2PS = parseUnimplemented-parseMOVNTPS = parseXmmWV MOVNTPS InvalidOpcode MOVNTPD InvalidOpcode-parseCVTPS2PI = parseUnimplemented-parseCVTTPS2PI = parseUnimplemented-parseUCOMISS = parseXmmVW UCOMISS InvalidOpcode UCOMISD InvalidOpcode-parseCOMISS = parseXmmVW COMISS InvalidOpcode COMISD InvalidOpcode--parseCMOVcc b= do- opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- return $ Instr (cmovccname (b .&. 0xf)) OPNONE [op2, op1]- -parseMOVSKPS = parseXmmGU MOVMSKPS InvalidOpcode MOVMSKPD InvalidOpcode--parseSQRTPS = parseXmmVW SQRTPS SQRTSS SQRTPD SQRTSD-parseRSQRTPS = parseXmmVW RSQRTPS RSQRTSS InvalidOpcode InvalidOpcode-parseRCPPS = parseXmmVW RCPPS RCPSS InvalidOpcode InvalidOpcode-parseCVTPS2PD = parseUnimplemented-parseANDNPS = parseXmmVW ANDNPS InvalidOpcode ANDNPD InvalidOpcode-parseANDPS = parseXmmVW ANDPS InvalidOpcode ANDPD InvalidOpcode-parseORPS = parseXmmVW ORPS InvalidOpcode ORPD InvalidOpcode-parseXORPS = parseXmmVW XORPS InvalidOpcode XORPD InvalidOpcode-parseADDPS = parseXmmVW ADDPS ADDSS ADDPD ADDSD-parseMULPS = parseXmmVW MULPS MULSS MULPD MULSD-parseCVTDQ2PS = parseUnimplemented-parsePUNPCKLWD = parseUnimplemented-parsePACKSSWB = parseUnimplemented-parsePUNPCKHWD = parseUnimplemented-parseSUBPS = parseXmmVW SUBPS SUBSS SUBPD SUBSD-parseMINPS = parseXmmVW MINPS MINSS MINPD MINSD-parseDIVPS = parseXmmVW DIVPS DIVSS DIVPD DIVSD-parseMAXPS = parseXmmVW MAXPS MAXSS MAXPD MAXSD-parsePUNPCKLBW = parseUnimplemented-parsePUNPCKLDQ = parseUnimplemented-parsePACKUSWB = parseUnimplemented-parsePCMPGTB = parseUnimplemented-parsePCMPGTW = parseUnimplemented-parsePCMPGTD = parseUnimplemented-parsePUNPCKHBW = parseUnimplemented-parsePUNPCKHDQ = parseUnimplemented-parsePACKSSDW = parseUnimplemented-parsePUNPCKLQDQ = parseUnimplemented-parsePUNPCKHQDQ = parseUnimplemented-parsePSHUFW = parseUnimplemented-parsePCMPEQB = parseUnimplemented-parsePCMPEQW = parseUnimplemented-parsePCMPEQD = parseUnimplemented--parseVMREAD b = - do st <- getState- if in64BitMode st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- return $ Instr VMREAD OP64 [op1, op2]- else do (op1, op2, mod, reg, rm) <- parseAddress32 OP32- return $ Instr VMREAD OP32 [op1, op2]-parseVMWRITE b = - do st <- getState- if in64BitMode st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- return $ Instr VMWRITE OP64 [op1, op2]- else do (op1, op2, mod, reg, rm) <- parseAddress32 OP32- return $ Instr VMWRITE OP32 [op1, op2]--parseHADDPS = parseXmmVW InvalidOpcode InvalidOpcode HADDPD HADDPS-parseHSUBPS = parseXmmVW InvalidOpcode InvalidOpcode HSUBPS HSUBPD--parseMOVD_Q = parseUnimplemented--parseJccLong b = do- disp <- anyIntZ- let disp' :: Int- disp' = fromIntegral disp- pos <- getPosition- st <- getState- return $ Instr (jccname (b .&. 0xf)) OPNONE- [OpAddr (fromIntegral (disp' + sourceColumn pos - 1) +- (startAddr st)) OPNONE]--parseSETcc b = do- (op1, op2, mod, reg, rm) <- parseAddress32 OP8- case op1 of- OpReg name num -> return $ Instr (setccname (b .&. 0xf)) OPNONE - [OpReg (regnames8 !! fromIntegral num) num]- _ -> return $ Instr (setccname (b .&. 0xf)) OPNONE [op1]--parseSHLD 0xa4 = - do opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- b <- anyWord8- opsize <- instrOperandSize- return $ Instr SHLD opsize [op1, op2, OpImm (fromIntegral b)]-parseSHLD 0xa5 = - do opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- opsize <- instrOperandSize- return $ Instr SHLD opsize [op1, op2, OpReg "cl" 1]-parseSHRD 0xac = - do opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- b <- anyWord8- opsize <- instrOperandSize- return $ Instr SHRD opsize [op1, op2, OpImm (fromIntegral b)]-parseSHRD 0xad = - do opsize <- instrOperandSize- (op1, op2, mod, reg, rm) <- parseAddress32 opsize- opsize <- instrOperandSize- return $ Instr SHRD opsize [op1, op2, OpReg "cl" 1]--parseCMPPS = parseUnimplemented-parseMOVNTI = parseUnimplemented-parsePINSRW = parseUnimplemented-parsePEXTRW = parseUnimplemented-parseSHUFPS = parseUnimplemented--parseBSWAP b = - do let reg = (b .&. 0xf) - 8- r <- registerName (fromIntegral reg)- opsize <- instrOperandSize- return $ Instr BSWAP opsize [OpReg r (fromIntegral reg)]--parseADDSUBPS = parseXmmVW InvalidOpcode InvalidOpcode ADDSUBPD ADDUBPS--parseMmxXmmPQVW opcode b =- do st <- getState- if hasPrefix 0x66 st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128- let v = OpReg (xmmregs !! (fromIntegral reg)) - (fromIntegral reg)- let w = case op1 of- OpReg _ num -> OpReg (xmmregs !! num) num- op -> op- return $ Instr opcode OP128 [v, w]- else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- let p = OpReg (mmxregs !! (fromIntegral reg)) - (fromIntegral reg)- let q = case op1 of- OpReg _ num -> OpReg (mmxregs !! num) num- op -> op- return $ Instr opcode OP128 [p, q]--parseMmxXmmMPMV opcode1 opcode2 b =- do st <- getState- if hasPrefix 0x66 st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128- let v = OpReg (xmmregs !! (fromIntegral reg)) - (fromIntegral reg)- return $ Instr opcode2 OP128 [op1, v]- else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- let p = OpReg (mmxregs !! (fromIntegral reg)) - (fromIntegral reg)- return $ Instr opcode1 OP128 [op1, p]--parseMmxXmmPNVU opcode b =- do st <- getState- if hasPrefix 0x66 st- then do (mod, reg, rm) <- parseModRM- let v = OpReg (xmmregs !! (fromIntegral reg)) - (fromIntegral reg)- let u = OpReg (xmmregs !! (fromIntegral rm))- (fromIntegral reg)- return $ Instr opcode OP128 [v, u]- else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- let p = OpReg (mmxregs !! (fromIntegral reg)) - (fromIntegral reg)- let n = OpReg (mmxregs !! (fromIntegral rm))- (fromIntegral reg)- return $ Instr opcode OP128 [p, n]--parsePSRLW = parseMmxXmmPQVW PSRLW-parsePSRLD = parseMmxXmmPQVW PSRLD-parsePSRLQ = parseMmxXmmPQVW PSRLQ-parsePADDQ = parseMmxXmmPQVW PADDQ-parsePMULLW = parseMmxXmmPQVW PMULLW-parseMOVQ b@0x6f = parseUnimplemented b-parseMOVQ b@0x7f = parseUnimplemented b-parseMOVQ b@0xd6 = - do st <- getState- if hasPrefix 0x66 st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64- return $ Instr MOVQ OP64 [op1, op2]- else if hasPrefix 0xf3 st- then do (mod, reg, rm) <- parseModRM- return $ Instr MOVQ OPNONE - [OpReg (xmmregs !! (fromIntegral reg))- (fromIntegral reg),- OpReg (mmxregs !! (fromIntegral rm))- (fromIntegral rm)]- else- if hasPrefix 0xf2 st- then do (mod, reg, rm) <- parseModRM- return $ Instr MOVQ OPNONE- [OpReg (mmxregs !! (fromIntegral reg))- (fromIntegral reg),- OpReg (xmmregs !! (fromIntegral rm))- (fromIntegral rm)]- else parseInvalidOpcode b- -parsePMOVMSKB b = - do st <- getState- (mod, reg, rm) <- parseModRM- if hasPrefix 0x66 st- then do return $ Instr PMOVMSKB OPNONE - [OpReg (regnames32 !! (fromIntegral reg))- (fromIntegral reg),- OpReg (xmmregs !! (fromIntegral rm))- (fromIntegral rm)]- else do return $ Instr PMOVMSKB OPNONE - [OpReg (regnames32 !! (fromIntegral reg))- (fromIntegral reg),- OpReg (mmxregs !! (fromIntegral rm))- (fromIntegral rm)]-parsePSUBUSB = parseMmxXmmPQVW PSUBUSB-parsePSUBUSW = parseMmxXmmPQVW PSUBUSW-parsePMINUB = parseMmxXmmPQVW PMINUB-parsePAND = parseMmxXmmPQVW PAND-parsePADDUSB = parseMmxXmmPQVW PADDUSB-parsePADDUSW = parseMmxXmmPQVW PADDUSW-parsePMAXUB = parseMmxXmmPQVW PMAXUB-parsePANDN = parseMmxXmmPQVW PANDN-parsePAVGB = parseMmxXmmPQVW PAVGB-parsePSRAW = parseMmxXmmPQVW PSRAW-parsePSRAD = parseMmxXmmPQVW PSRAD-parsePAVGW = parseMmxXmmPQVW PAVGW-parseCVTPD2DQ = parseUnimplemented-parsePMULHUW = parseMmxXmmPQVW PMULHUW-parsePMULHW = parseMmxXmmPQVW PMULHW-parseMOVNTQ = parseMmxXmmMPMV MOVNTQ MOVNTDQ-parsePSUBSB = parseMmxXmmPQVW PSUBSB-parsePSUBSQ = parseMmxXmmPQVW PSUBSQ-parsePMINSW = parseMmxXmmPQVW PMINSW-parsePOR = parseMmxXmmPQVW POR-parsePADDSB = parseMmxXmmPQVW PADDSB-parsePADDSW = parseMmxXmmPQVW PADDSW-parsePMAXSW = parseMmxXmmPQVW PMAXSW-parsePXOR = parseMmxXmmPQVW PXOR-parseLDDQU b = - do st <- getState- if hasPrefix 0xf2 st- then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128- let v = OpReg (xmmregs !! (fromIntegral reg))- (fromIntegral reg)- return $ Instr LDDQU OP128 [v, op1]- else parseInvalidOpcode b-parsePSLLW = parseMmxXmmPQVW PSLLW-parsePSLLD = parseMmxXmmPQVW PSLLD-parsePSLLQ = parseMmxXmmPQVW PSLLQ-parsePMULUDQ = parseMmxXmmPQVW PMULUDQ-parsePMADDWD = parseMmxXmmPQVW PMADDWD-parsePSADBW = parseMmxXmmPQVW PSADBW-parseMASKMOVQ = parseMmxXmmPNVU MASKMOVQ-parsePSUBB = parseMmxXmmPQVW PSUBB-parsePSUBW = parseMmxXmmPQVW PSUBW-parsePSUBD = parseMmxXmmPQVW PSUBD-parsePSUBQ = parseMmxXmmPQVW PSUBQ-parsePADDB = parseMmxXmmPQVW PADDB-parsePADDW = parseMmxXmmPQVW PADDW-parsePADDD = parseMmxXmmPQVW PADDD+-- This is a module for compatibility with earlier Harpy releases. It+-- re-exports the disassembler from the disassembler package.+--------------------------------------------------------------------------++module Harpy.X86Disassembler(+ -- * Types+ Opcode,+ Operand(..),+ InstrOperandSize(..),+ Instruction(..),+ ShowStyle(..),+ -- * Functions+ disassembleBlock,+ disassembleList,+ disassembleArray,+ showIntel,+ showAtt+ ) where++import Text.Disassembler.X86Disassembler
NEWS view
@@ -1,6 +1,29 @@ -*-outline-*- * Harpy NEWS +** New in version 0.4.2++*** package structure++- The disassembler is now in a separate package, and is re-exported for+ compatibility by Harpy. This allows us to give the more liberal BSD licence+ to the disassembler.++*** New instructions++- The "mov", "jcc" (jump on condition code), and "cmp" instructions support+ "Ptr a" as operand++- Henning Thielemann provided some further floating point and SSE+ instructions.++- The loop instruction supports labels now.++*** Enhancements++- The disassembly of Harpy's internal code buffers includes all labels+ now, even when multiple labels are defined for the same location.+ ** New in version 0.4.1 *** New Instances
harpy.cabal view
@@ -1,12 +1,12 @@ Cabal-version: >=1.2 Build-type: Simple Name: harpy-Version: 0.4.1+Version: 0.4.2 License: GPL License-file: COPYING Author: Dirk Kleeblatt <klee@cs.tu-berlin.de>- Martin Grabmueller <magr@cs.tu-berlin.de>-Maintainer: klee@cs.tu-berlin.de, magr@cs.tu-berlin.de+ Martin Grabmueller <martin.grabmueller@eleven.de>+Maintainer: klee@cs.tu-berlin.de, martin.grabmueller@eleven.de Homepage: http://uebb.cs.tu-berlin.de/harpy/ Category: Code Generation Synopsis: Runtime code generation for x86 machine code@@ -20,7 +20,9 @@ * An x86 disassembler which knows most of the opcodes available on modern x86 processors and can display its output both in the style used in Intel documents an in AT&T style, like the GNU tools. The- disassmbler can be found in module "Harpy.X86Disassembler".+ disassembler can be found in module "Harpy.X86Disassembler". The+ disassembler is re-exported from the disassembler package for+ compatibility with earlier Harpy releases. . * Some abstractions over the abovementioned code generation modules, such as automatic label management and code generation@@ -45,9 +47,10 @@ Library if flag(small_base)- Build-depends: base >= 3,parsec,mtl,template-haskell,pretty,containers,array+ Build-depends: base >= 3 && < 4,parsec,mtl,template-haskell,pretty,containers,array else Build-Depends: base < 3,parsec,mtl,template-haskell+ Build-depends: disassembler >= 0.1.0 Exposed-Modules: Harpy, Harpy.X86CodeGen,