packages feed

disassembler (empty) → 0.1.0

raw patch · 4 files changed

+3345/−0 lines, 4 filesdep +arraydep +basedep +containerssetup-changed

Dependencies added: array, base, containers, mtl, parsec

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) Dirk Kleeblatt and Martin Grabmueller++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ Text/Disassembler/X86Disassembler.hs view
@@ -0,0 +1,3285 @@+--------------------------------------------------------------------------+-- |+-- Module      :  Text.Disassembler.X86Disassembler+-- Copyright   :  (c) Martin Grabmueller and Dirk Kleeblatt+-- License     :  BSD3+-- +-- Maintainer  :  martin.grabmueller@eleven.de,klee@cs.tu-berlin.de+-- Stability   :  provisional+-- Portability :  portable+--+-- 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 Text.Disassembler.X86Disassembler(+  -- * Types+  Opcode,+  Operand(..),+  InstrOperandSize(..),+  Instruction(..),+  ShowStyle(..),+  Config(..),+  -- * Functions+  disassembleBlock,+  disassembleList,+  disassembleArray,+  disassembleFile,+  disassembleBlockWithConfig,+  disassembleListWithConfig,+  disassembleArrayWithConfig,+  disassembleFileWithConfig,+  showIntel,+  showAtt,+  defaultConfig+  ) 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 = +    disassembleBlockWithConfig defaultConfig{confStartAddr = fromIntegral (minusPtr ptr nullPtr)} +                               ptr len++disassembleBlockWithConfig :: Config -> Ptr Word8 -> Int -> IO (Either ParseError [Instruction])+disassembleBlockWithConfig config ptr len = do+  l <- toList ptr len 0 []+  parseInstructions (configToState config) (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 = disassembleArrayWithConfig defaultConfig arr++disassembleArrayWithConfig :: (Monad m, IArray a Word8, Ix i) => Config ->+                             a i Word8 -> m (Either ParseError [Instruction])+disassembleArrayWithConfig config arr =+  let l = elems arr+  in parseInstructions (configToState config) l++-- | Disassemble the contents of the given list.++disassembleList :: (Monad m) =>+                   [Word8] -> m (Either ParseError [Instruction])+disassembleList ls = disassembleListWithConfig defaultConfig ls++disassembleListWithConfig :: (Monad m) => Config ->+                   [Word8] -> m (Either ParseError [Instruction])+disassembleListWithConfig config ls =+    parseInstructions (configToState config) ls++disassembleFile filename = disassembleFileWithConfig defaultConfig filename++disassembleFileWithConfig config filename = do+  l <- readFile filename+  parseInstructions (configToState config) (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+                      }++data Config = Config {confDefaultBitMode :: OperandSize,+                      confOperandBitMode :: OperandSize,+                      confAddressBitMode :: OperandSize,+                      confIn64BitMode        :: Bool,+                      confStartAddr          :: Word32}++defaultConfig = Config{ confDefaultBitMode = BIT32,+       	                confOperandBitMode = BIT32, +       	                confAddressBitMode = BIT32, +       	                confIn64BitMode = False,+       	                confStartAddr = 0}++configToState (Config defBitMode opMode addrMode in64 confStartAddr) =+    defaultState{defaultBitMode = defBitMode,+                 operandBitMode = opMode,+                 addressBitMode = addrMode,+                 in64BitMode = in64,+                 startAddr = confStartAddr}+           +-- 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
+ disassembler.cabal view
@@ -0,0 +1,27 @@+name:            disassembler+version:         0.1.0+license:         BSD3+license-file:    LICENSE+category:        Development, Disassembler+author:          Martin Grabmueller <martin.grabmueller@eleven.de>, Dirk Kleeblatt <klee@cs.tu-berlin.de>+maintainer:      Martin Grabmueller <martin.grabmueller@eleven.de>+stability:       experimental+tested-with:     GHC == 6.10.1+synopsis:        Disassembler for X86 & AMD64 machine code+description:     Disassembler for X86 & AMD64 machine code+cabal-version:   >= 1.2+build-type:      Simple++flag split-base++library+  if flag(split-base)+    -- bytestring was in base-2.0 and 2.1.1+    build-depends: base >= 2.0 && < 2.2+  else+    -- in base 1.0 and 3.0 bytestring is a separate package+    build-depends: base < 2.0 || >= 3, containers, array, mtl, parsec++  extensions: FlexibleContexts+  exposed-modules: Text.Disassembler.X86Disassembler+  ghc-options:     -O2