1 --------------------------------------------------------------------------
3 -- Module : Text.Disassembler.X86Disassembler
4 -- Copyright : (c) Martin Grabmueller and Dirk Kleeblatt
7 -- Maintainer : martin@grabmueller.de,klee@cs.tu-berlin.de
8 -- Stability : provisional
9 -- Portability : portable
11 -- Disassembler for x86 machine code.
13 -- This is a disassembler for object code for the x86 architecture.
14 -- It provides functions for disassembling byte arrays, byte lists and
15 -- memory blocks containing raw binary code.
19 -- - Disassembles memory blocks, lists or arrays of bytes into lists of
22 -- - Abstract instructions provide as much information as possible about
23 -- opcodes, addressing modes or operand sizes, allowing for detailed
26 -- - Provides functions for displaying instructions in Intel or AT&T
27 -- style (like the GNU tools)
29 -- Differences to GNU tools, like gdb or objdump:
31 -- - Displacements are shown in decimal, with sign if negative.
35 -- - LOCK and repeat prefixes are recognized, but not contained in the
36 -- opcodes of instructions.
38 -- - Support for 16-bit addressing modes. Could be added when needed.
40 -- - Complete disassembly of all 64-bit instructions. I have tried to
41 -- disassemble them properly but have been limited to the information
42 -- in the docs, because I have no 64-bit machine to test on. This will
43 -- probably change when I get GNU as to produce 64-bit object files.
45 -- - Not all MMX and SSE/SSE2/SSE3 instructions are decoded yet. This is
46 -- just a matter of missing time.
48 -- - segment override prefixes are decoded, but not appended to memory
51 -- On the implementation:
53 -- This disassembler uses the Parsec parser combinators, working on byte
54 -- lists. This proved to be very convenient, as the combinators keep
55 -- track of the current position, etc.
56 --------------------------------------------------------------------------
58 module Text.Disassembler.X86Disassembler(
71 disassembleBlockWithConfig,
72 disassembleListWithConfig,
73 disassembleArrayWithConfig,
74 disassembleFileWithConfig,
80 import Text.ParserCombinators.Parsec
81 import Control.Monad.State
85 import Data.Array.IArray
89 -- | All opcodes are represented by this enumeration type.
91 data Opcode = InvalidOpcode
502 -- Display an opcode in lower case.
504 showOp :: Opcode -> String
505 showOp = (map toLower) . show
507 -- | All operands are in one of the following locations:
509 -- - Constants in the instruction stream
511 -- - Memory locations
515 -- Memory locations are referred to by on of several addressing modes:
517 -- - Absolute (address in instruction stream)
519 -- - Register-indirect (address in register)
521 -- - Register-indirect with displacement
523 -- - Base-Index with scale
525 -- - Base-Index with scale and displacement
527 -- Displacements can be encoded as 8 or 32-bit immediates in the
528 -- instruction stream, but are encoded as Int in instructions for
531 data Operand = OpImm Word32 -- ^ Immediate value
532 | OpAddr Word32 InstrOperandSize -- ^ Absolute address
533 | OpReg String Int -- ^ Register
534 | OpFPReg Int -- ^ Floating-point register
535 | OpInd String InstrOperandSize -- ^Register-indirect
536 | OpIndDisp String Int InstrOperandSize
537 -- ^ Register-indirect with displacement
538 | OpBaseIndex String String Int InstrOperandSize
539 -- ^ Base plus scaled index
540 | OpIndexDisp String Int Int InstrOperandSize
541 -- ^ Scaled index with displacement
542 | OpBaseIndexDisp String String Int Int InstrOperandSize
543 -- ^ Base plus scaled index with displacement
546 -- Show an operand in AT&T style.
548 showAttOps (OpImm w) = showImm w
549 showAttOps (OpAddr w _) = showAddr w
550 showAttOps (OpReg s num) = "%" ++ s
551 showAttOps (OpFPReg 0) = "%st"
552 showAttOps (OpFPReg i) = "%st(" ++ show i ++ ")"
553 showAttOps (OpInd s _) = "(%" ++ s ++ ")"
554 showAttOps (OpIndDisp s disp _) = show disp ++ "(%" ++ s ++ ")"
555 showAttOps (OpBaseIndex b i s _) = "(%" ++ b ++ ",%" ++ i ++ "," ++ show s ++ ")"
556 showAttOps (OpIndexDisp i s disp _) = show disp ++ "(%" ++ i ++ "," ++
558 showAttOps (OpBaseIndexDisp b i s disp _) = show disp ++ "(%" ++ b ++ ",%" ++
559 i ++ "," ++ show s ++ ")"
561 -- Show an operand in Intel style.
563 showIntelOps opsize (OpImm w) = showIntelImm w
564 showIntelOps opsize (OpAddr w sz) = opInd sz ++ "[" ++ showIntelAddr w ++ "]"
565 showIntelOps opsize (OpReg s num) = s
566 showIntelOps opsize (OpFPReg 0) = "st"
567 showIntelOps opsize (OpFPReg i) = "st(" ++ show i ++ ")"
568 showIntelOps opsize (OpInd s sz) = opInd sz ++ "[" ++ s ++ "]"
569 showIntelOps opsize (OpIndDisp s disp sz) =
570 opInd sz ++ "[" ++ s ++
571 (if disp < 0 then "" else "+") ++ show disp ++ "]"
572 showIntelOps opsize (OpBaseIndex b i s sz) =
573 opInd sz ++ "[" ++ b ++ "+" ++ i ++ "*" ++ show s ++ "]"
574 showIntelOps opsize (OpIndexDisp i s disp sz) =
575 opInd sz ++ "[" ++ i ++ "*" ++ show s ++
576 (if disp < 0 then "" else "+") ++ show disp ++ "]"
577 showIntelOps opsize (OpBaseIndexDisp b i s disp sz) =
578 opInd sz ++ "[" ++ b ++ "+" ++ i ++ "*" ++ show s ++
579 (if disp < 0 then "" else "+") ++
582 opInd OP8 = "byte ptr "
583 opInd OP16 = "word ptr "
584 opInd OP32 = "dword ptr "
585 opInd OPF32 = "dword ptr "
586 opInd OP64 = "qword ptr "
587 opInd OPF64 = "qword ptr "
588 opInd OPF80 = "tbyte ptr "
589 opInd OP128 = "dqword ptr "
591 -- | Encodes the default and currently active operand or address size. Can
592 -- be changed with the operand- or address-size prefixes 0x66 and 0x67.
594 data OperandSize = BIT16 | BIT32
596 -- | Some opcodes can operate on data of several widths. This information
597 -- is encoded in instructions using the following enumeration type..
599 data InstrOperandSize = OPNONE -- ^ No operand size specified
600 | OP8 -- ^ 8-bit integer operand
601 | OP16 -- ^ 16-bit integer operand
602 | OP32 -- ^ 32-bit integer operand
603 | OP64 -- ^ 64-bit integer operand
604 | OP128 -- ^ 128-bit integer operand
605 | OPF32 -- ^ 32-bit floating point operand
606 | OPF64 -- ^ 64-bit floating point operand
607 | OPF80 -- ^ 80-bit floating point operand
611 -- | The disassembly routines return lists of the following datatype. It
612 -- encodes both invalid byte sequences (with a useful error message, if
613 -- possible), or a valid instruction. Both variants contain the list of
614 -- opcode bytes from which the instruction was decoded and the address of
618 BadInstruction Word8 String Int [Word8] -- ^ Invalid instruction
619 | PseudoInstruction Int String -- ^ Pseudo instruction, e.g. label
620 | Instruction { opcode :: Opcode, -- ^ Opcode of the instruction
621 opsize :: InstrOperandSize, -- ^ Operand size, if any
622 operands :: [Operand], -- ^ Instruction operands
623 address :: Int, -- ^ Start address of instruction
624 bytes ::[Word8] -- ^ Instruction bytes
625 } -- ^ Valid instruction
628 instance Show Instruction where
631 data Instr = Bad Word8 String
632 | Instr Opcode InstrOperandSize [Operand]
634 -- Show an integer as an 8-digit hexadecimal number with leading zeroes.
636 hex32 :: Int -> String
641 in take (8 - length s) (repeat '0') ++ s
643 -- Show a byte as an 2-digit hexadecimal number with leading zeroes.
645 hex8 :: Word8 -> String
648 in take (2 - length s) ['0','0'] ++ s
651 -- | Instructions can be displayed either in Intel or AT&T style (like in
656 -- - Destination operand comes first, source second.
658 -- - No register or immediate prefixes.
660 -- - Memory operands are annotated with operand size.
662 -- - Hexadecimal numbers are suffixed with @H@ and prefixed with @0@ if
667 -- - Source operand comes first, destination second.
669 -- - Register names are prefixes with @%@.
671 -- - Immediates are prefixed with @$@.
673 -- - Hexadecimal numbers are prefixes with @0x@
675 -- - Opcodes are suffixed with operand size, when ambiguous otherwise.
676 data ShowStyle = IntelStyle -- ^ Show in Intel style
677 | AttStyle -- ^ Show in AT&T style
679 -- | Show an instruction in Intel style.
681 showIntel :: Instruction -> [Char]
682 showIntel (BadInstruction b desc pos bytes) =
683 showPosBytes pos bytes ++
684 "(" ++ desc ++ ", byte=" ++ show b ++ ")"
685 showIntel (PseudoInstruction pos s) =
686 hex32 pos ++ " " ++ s
687 showIntel (Instruction op opsize [] pos bytes) =
688 showPosBytes pos bytes ++
690 showIntel (Instruction op opsize ops pos bytes) =
691 showPosBytes pos bytes ++
692 enlarge (showOp op) 6 ++ " " ++
693 concat (intersperse "," (map (showIntelOps opsize) ops))
695 -- | Show an instruction in AT&T style.
697 showAtt :: Instruction -> [Char]
698 showAtt (BadInstruction b desc pos bytes) =
699 showPosBytes pos bytes ++
700 "(" ++ desc ++ ", byte=" ++ show b ++ ")"
701 showAtt (PseudoInstruction pos s) =
702 hex32 pos ++ " " ++ s
703 showAtt (Instruction op opsize [] pos bytes) =
704 showPosBytes pos bytes ++
705 showOp op ++ showInstrSuffix [] opsize
706 showAtt (Instruction op opsize ops pos bytes) =
707 showPosBytes pos bytes ++
708 enlarge (showOp op ++ showInstrSuffix ops opsize) 6 ++ " " ++
709 concat (intersperse "," (map showAttOps (reverse ops)))
711 showPosBytes pos bytes =
713 enlarge (concat (intersperse " " (map hex8 bytes))) 30
715 enlarge s i = s ++ take (i - length s) (repeat ' ')
717 opSizeSuffix OPNONE = ""
718 opSizeSuffix OP8 = "b"
719 opSizeSuffix OP16 = "w"
720 opSizeSuffix OP32 = "l"
721 opSizeSuffix OP64 = "q"
722 opSizeSuffix OP128 = "dq"
723 opSizeSuffix OPF32 = "s"
724 opSizeSuffix OPF64 = "l"
725 opSizeSuffix OPF80 = "t"
727 showInstrSuffix [] sz = opSizeSuffix sz
728 showInstrSuffix ((OpImm _) : os) s = showInstrSuffix os s
729 --showInstrSuffix ((OpReg _ _) : []) s = ""
730 showInstrSuffix ((OpReg _ _) : os) s = showInstrSuffix os OPNONE
731 showInstrSuffix ((OpFPReg _) : os) s = showInstrSuffix os s
732 showInstrSuffix ((OpAddr _ OPNONE) : os) s = showInstrSuffix os s
733 showInstrSuffix ((OpAddr _ sz) : os) s = opSizeSuffix sz
734 showInstrSuffix ((OpInd _ OPNONE) : os) s = showInstrSuffix os s
735 showInstrSuffix ((OpInd _ sz) : os) s = opSizeSuffix sz
736 showInstrSuffix ((OpIndDisp _ _ OPNONE) : os) s = showInstrSuffix os s
737 showInstrSuffix ((OpIndDisp _ _ sz) : os) s = opSizeSuffix sz
738 showInstrSuffix ((OpBaseIndex _ _ _ OPNONE) : os) s = showInstrSuffix os s
739 showInstrSuffix ((OpBaseIndex _ _ _ sz) : os) s = opSizeSuffix sz
740 showInstrSuffix ((OpIndexDisp _ _ _ OPNONE) : os) s = showInstrSuffix os s
741 showInstrSuffix ((OpIndexDisp _ _ _ sz) : os) s = opSizeSuffix sz
742 showInstrSuffix ((OpBaseIndexDisp _ _ _ _ OPNONE) : os) s = showInstrSuffix os s
743 showInstrSuffix ((OpBaseIndexDisp _ _ _ _ sz) : os) s = opSizeSuffix sz
745 -- showInstrOperandSize ops OPNONE | noRegop ops = ""
746 -- showInstrOperandSize ops OP8 | noRegop ops = "b"
747 -- showInstrOperandSize ops OP16 | noRegop ops = "w"
748 -- showInstrOperandSize ops OP32 | noRegop ops = "l"
749 -- showInstrOperandSize ops OPF32 | noRegop ops = "s"
750 -- showInstrOperandSize ops OP64 | noRegop ops = "q"
751 -- showInstrOperandSize ops OPF64 | noRegop ops = "l"
752 -- showInstrOperandSize ops OPF80 | noRegop ops = "e"
753 -- showInstrOperandSize ops OP128 | noRegop ops = ""
754 -- showInstrOperandSize _ _ = ""
756 -- noRegop ops = null (filter isRegop ops)
757 -- isRegop (OpReg _ _) = True
760 -- Show an immediate value in hexadecimal.
762 showImm :: Word32 -> String
764 "$0x" ++ showHex i ""
766 showIntelImm :: Word32 -> String
768 let h = showHex i "H"
770 in (if isDigit f then "" else "0") ++ h
772 -- Show an address in hexadecimal.
777 in "0x" ++ showHex w ""
783 in (if isDigit f then "" else "0") ++ h
785 -- | Disassemble a block of memory. Starting at the location
786 -- pointed to by the given pointer, the given number of bytes are
789 disassembleBlock :: Ptr Word8 -> Int -> IO (Either ParseError [Instruction])
790 disassembleBlock ptr len =
791 disassembleBlockWithConfig defaultConfig{confStartAddr = fromIntegral (minusPtr ptr nullPtr)}
794 disassembleBlockWithConfig :: Config -> Ptr Word8 -> Int -> IO (Either ParseError [Instruction])
795 disassembleBlockWithConfig config ptr len = do
796 l <- toList ptr len 0 []
797 parseInstructions (configToState config) (reverse l)
799 toList :: (Ptr Word8) -> Int -> Int -> [Word8] -> IO [Word8]
800 toList ptr len idx acc | idx < len =
801 do p <- peekByteOff ptr idx
802 toList ptr len (idx + 1) (p : acc)
804 toList ptr len idx acc | idx >= len = return acc
806 -- | Disassemble the contents of the given array.
808 disassembleArray :: (Monad m, IArray a Word8, Ix i) =>
809 a i Word8 -> m (Either ParseError [Instruction])
810 disassembleArray arr = disassembleArrayWithConfig defaultConfig arr
812 disassembleArrayWithConfig :: (Monad m, IArray a Word8, Ix i) => Config ->
813 a i Word8 -> m (Either ParseError [Instruction])
814 disassembleArrayWithConfig config arr =
816 in parseInstructions (configToState config) l
818 -- | Disassemble the contents of the given list.
820 disassembleList :: (Monad m) =>
821 [Word8] -> m (Either ParseError [Instruction])
822 disassembleList ls = disassembleListWithConfig defaultConfig ls
824 disassembleListWithConfig :: (Monad m) => Config ->
825 [Word8] -> m (Either ParseError [Instruction])
826 disassembleListWithConfig config ls =
827 parseInstructions (configToState config) ls
829 disassembleFile filename = disassembleFileWithConfig defaultConfig filename
831 disassembleFileWithConfig config filename = do
832 l <- readFile filename
833 parseInstructions (configToState config) (map (fromIntegral . ord) l)
835 instrToString insts style =
838 showInstr = case style of
839 IntelStyle -> showIntel
842 -- | Test function for disassembling the contents of a binary file and
843 -- displaying it in the provided style ("IntelStyle" or "AttStyle").
845 testFile :: FilePath -> ShowStyle -> IO ()
846 testFile fname style = do
848 i <- parseInstructions defaultState (map (fromIntegral . ord) l)
850 Left err -> putStrLn (show err)
851 Right i' -> mapM_ (putStrLn . showInstr) i'
853 showInstr = case style of
854 IntelStyle -> showIntel
857 -- This is the state maintained by the disassembler.
859 data PState = PState { defaultBitMode :: OperandSize,
860 operandBitMode :: OperandSize,
861 addressBitMode :: OperandSize,
867 data Config = Config {confDefaultBitMode :: OperandSize,
868 confOperandBitMode :: OperandSize,
869 confAddressBitMode :: OperandSize,
870 confIn64BitMode :: Bool,
871 confStartAddr :: Word32}
873 defaultConfig = Config{ confDefaultBitMode = BIT32,
874 confOperandBitMode = BIT32,
875 confAddressBitMode = BIT32,
876 confIn64BitMode = False,
879 configToState (Config defBitMode opMode addrMode in64 confStartAddr) =
880 defaultState{defaultBitMode = defBitMode,
881 operandBitMode = opMode,
882 addressBitMode = addrMode,
884 startAddr = confStartAddr}
886 -- Default state to be used if no other is given to the disassembly
889 defaultState = PState { defaultBitMode = BIT32,
890 operandBitMode = BIT32,
891 addressBitMode = BIT32,
896 type Word8Parser a = GenParser Word8 PState a
898 parseInstructions st l =
899 return (runParser instructionSequence st "memory block" l)
901 -- Parse a possibly empty sequence of instructions.
903 instructionSequence = many instruction
905 -- Parse a single instruction. The result is either a valid instruction
906 -- or an indicator that there starts no valid instruction at the current
910 startPos' <- getPosition
911 let startPos = sourceColumn startPos' - 1
914 setState st{operandBitMode = defaultBitMode st,
915 addressBitMode = defaultBitMode st,
919 case lookup b oneByteOpCodeMap of
920 Just p -> do i <- p b
921 endPos' <- getPosition
922 let endPos = sourceColumn endPos' - 1
924 Instr oc opsize ops -> do
925 return $ Instruction oc opsize ops
926 (fromIntegral (startAddr st) + startPos)
927 (take (endPos - startPos) input)
929 return $ BadInstruction b desc
930 (fromIntegral (startAddr st) + startPos)
931 (take (endPos - startPos) input)
932 Nothing -> do Bad b desc <- parseInvalidOpcode b
933 endPos' <- getPosition
934 let endPos = sourceColumn endPos' - 1
935 return $ BadInstruction b desc
936 (fromIntegral (startAddr st) + startPos)
937 (take (endPos - startPos) input)
939 toggleBitMode BIT16 = BIT32
940 toggleBitMode BIT32 = BIT16
947 -- Return True if the given REX prefix bit appears in the list of current
948 -- instruction prefixes, False otherwise.
951 let rexs = filter (\ b -> b >= 0x40 && b <= 0x4f) (prefixes st) in
953 (r : _) -> if r .&. rex == rex then True else False
956 -- Return True if the given prefix appears in the list of current
957 -- instruction prefixes, False otherwise.
959 hasPrefix b st = b `elem` prefixes st
963 setState st{prefixes = b : prefixes st}
965 -- Parse a single prefix byte and remember it in the parser state. If in
966 -- 64-bit mode, accept REX prefixes.
969 (word8 0xf0 >>= addPrefix) -- LOCK
971 (word8 0xf2 >>= addPrefix) -- REPNE/REPNZ
973 (word8 0xf3 >>= addPrefix) -- REP or REPE/REPZ
975 (word8 0x2e >>= addPrefix) -- CS segment override
977 (word8 0x36 >>= addPrefix) -- SS segment override
979 (word8 0x3e >>= addPrefix) -- DS segment override
981 (word8 0x26 >>= addPrefix) -- ES segment override
983 (word8 0x64 >>= addPrefix) -- FS segment override
985 (word8 0x65 >>= addPrefix) -- GS segment override
987 (word8 0x2e >>= addPrefix) -- branch not taken
989 (word8 0x3e >>= addPrefix) -- branch taken
991 do word8 0x66 -- operand-size override
993 setState st{operandBitMode = toggleBitMode (operandBitMode st)}
996 do word8 0x67 -- address-size override
998 setState st{addressBitMode = toggleBitMode (addressBitMode st)}
1000 <|> do st <- getState
1002 then (word8 0x40 >>= addPrefix)
1004 (word8 0x41 >>= addPrefix)
1006 (word8 0x42 >>= addPrefix)
1008 (word8 0x43 >>= addPrefix)
1010 (word8 0x44 >>= addPrefix)
1012 (word8 0x45 >>= addPrefix)
1014 (word8 0x46 >>= addPrefix)
1016 (word8 0x47 >>= addPrefix)
1018 (word8 0x48 >>= addPrefix)
1020 (word8 0x49 >>= addPrefix)
1022 (word8 0x4a >>= addPrefix)
1024 (word8 0x4b >>= addPrefix)
1026 (word8 0x4c >>= addPrefix)
1028 (word8 0x4d >>= addPrefix)
1030 (word8 0x4e >>= addPrefix)
1032 (word8 0x4f >>= addPrefix)
1035 -- Accept the single unsigned byte B.
1038 tokenPrim showByte nextPos testByte
1040 showByte by = show by
1041 nextPos pos x xs = incSourceColumn pos 1
1042 testByte by = if b == by then Just by else Nothing
1044 -- Accept and return a single unsigned byte.
1046 anyWord8 :: Word8Parser Word8
1048 tokenPrim showByte nextPos testByte
1050 showByte by = show by
1051 nextPos pos x xs = incSourceColumn pos 1
1052 testByte by = Just by
1054 -- Accept any 8-bit signed byte.
1056 anyInt8 :: Word8Parser Int8
1063 -- Accept any 16-bit unsigned word.
1068 let w0, w1 :: Word16
1069 w0 = fromIntegral b0
1070 w1 = fromIntegral b1
1071 return $ w0 .|. (w1 `shiftL` 8)
1073 -- Accept any 16-bit signed integer.
1078 w0 = fromIntegral b0
1081 -- Accept a 32-bit unsigned word.
1086 let w0, w1 :: Word32
1087 w0 = fromIntegral b0
1088 w1 = fromIntegral b1
1089 return $ w0 .|. (w1 `shiftL` 16)
1091 -- Accept a 32-bit signed integer.
1093 anyInt32 :: Word8Parser Int32
1097 w0 = fromIntegral b0
1100 -- Accept a 64-bit unsigned word.
1102 anyWord64 :: Word8Parser Word64
1106 let w0, w1 :: Word64
1107 w0 = fromIntegral b0
1108 w1 = fromIntegral b1
1109 return $ w0 .|. (w1 `shiftL` 32)
1111 -- Accept a 64-bit signed integer.
1113 anyInt64 :: Word8Parser Int64
1117 w0 = fromIntegral b0
1120 -- Accept a 16-bit word for 16-bit operand-size, a 32-bit word for
1121 -- 32-bit operand-size, or a 64-bit word in 64-bit mode.
1123 anyWordV :: Word8Parser Word64
1127 then do w <- anyWord64
1129 else case operandBitMode st of
1130 BIT16 -> do w <- anyWord16
1134 BIT32 -> do w <- anyWord32
1139 -- Accept a 16-bit word for 16-bit operand-size or a 32-bit word for
1140 -- 32-bit operand-size or 64-bit mode.
1142 anyWordZ :: Word8Parser Word32
1145 case operandBitMode st of
1153 -- Accept a 16-bit integer for 16-bit operand-size or a 32-bit word for
1154 -- 32-bit operand-size or 64-bit mode.
1156 anyIntZ :: Word8Parser Int32
1159 case operandBitMode st of
1167 -- Accept a 32-bit far address for 16-bit operand-size or a 48-bit far
1168 -- address for 32-bit operand-size.
1170 anyWordP :: Word8Parser Word64
1173 case operandBitMode st of
1174 BIT16 -> do w <- anyWord32
1178 _ -> do w1 <- anyWord32
1180 let w1', w2' :: Word64
1181 w1' = fromIntegral w1
1182 w2' = fromIntegral w2
1183 return (w1' .|. (w2' `shiftL` 32))
1186 [(0x00, parseALU ADD),
1187 (0x01, parseALU ADD),
1188 (0x02, parseALU ADD),
1189 (0x03, parseALU ADD),
1190 (0x04, parseALU ADD),
1191 (0x05, parseALU ADD),
1192 (0x06, invalidIn64BitMode (parsePUSHSeg "es")),
1193 (0x07, invalidIn64BitMode (parsePOPSeg "es")),
1194 (0x08, parseALU OR),
1195 (0x09, parseALU OR),
1196 (0x0a, parseALU OR),
1197 (0x0b, parseALU OR),
1198 (0x0c, parseALU OR),
1199 (0x0d, parseALU OR),
1200 (0x0e, invalidIn64BitMode (parsePUSHSeg "cs")),
1201 (0x0f, twoByteEscape),
1203 (0x10, parseALU ADC),
1204 (0x11, parseALU ADC),
1205 (0x12, parseALU ADC),
1206 (0x13, parseALU ADC),
1207 (0x14, parseALU ADC),
1208 (0x15, parseALU ADC),
1209 (0x16, invalidIn64BitMode (parsePUSHSeg "ss")),
1210 (0x17, invalidIn64BitMode (parsePOPSeg "ss")),
1211 (0x18, parseALU SBB),
1212 (0x19, parseALU SBB),
1213 (0x1a, parseALU SBB),
1214 (0x1b, parseALU SBB),
1215 (0x1c, parseALU SBB),
1216 (0x1d, parseALU SBB),
1217 (0x1e, invalidIn64BitMode (parsePUSHSeg "ds")),
1218 (0x1f, invalidIn64BitMode (parsePOPSeg "ds")),
1220 (0x20, parseALU AND),
1221 (0x21, parseALU AND),
1222 (0x22, parseALU AND),
1223 (0x23, parseALU AND),
1224 (0x24, parseALU AND),
1225 (0x25, parseALU AND),
1226 (0x26, parseInvalidPrefix), -- ES segment override prefix
1227 (0x27, invalidIn64BitMode (parseGeneric DAA OPNONE)),
1228 (0x28, parseALU SUB),
1229 (0x29, parseALU SUB),
1230 (0x2a, parseALU SUB),
1231 (0x2b, parseALU SUB),
1232 (0x2c, parseALU SUB),
1233 (0x2d, parseALU SUB),
1234 (0x2e, parseInvalidPrefix), -- CS segment override prefix
1235 (0x2f, invalidIn64BitMode (parseGeneric DAS OPNONE)),
1237 (0x30, parseALU XOR),
1238 (0x31, parseALU XOR),
1239 (0x32, parseALU XOR),
1240 (0x33, parseALU XOR),
1241 (0x34, parseALU XOR),
1242 (0x35, parseALU XOR),
1243 (0x36, parseInvalidPrefix), -- SS segment override prefix
1244 (0x37, invalidIn64BitMode (parseGeneric AAA OPNONE)),
1245 (0x38, parseALU CMP),
1246 (0x39, parseALU CMP),
1247 (0x3a, parseALU CMP),
1248 (0x3b, parseALU CMP),
1249 (0x3c, parseALU CMP),
1250 (0x3d, parseALU CMP),
1251 (0x3e, parseInvalidPrefix), -- DS segment override prefix
1252 (0x3f, invalidIn64BitMode (parseGeneric AAS OPNONE)),
1254 (0x40, invalidIn64BitMode parseINC), -- REX Prefix in 64-bit mode
1255 (0x41, invalidIn64BitMode parseINC), -- ...
1256 (0x42, invalidIn64BitMode parseINC),
1257 (0x43, invalidIn64BitMode parseINC),
1258 (0x44, invalidIn64BitMode parseINC),
1259 (0x45, invalidIn64BitMode parseINC),
1260 (0x46, invalidIn64BitMode parseINC),
1261 (0x47, invalidIn64BitMode parseINC),
1262 (0x48, invalidIn64BitMode parseDEC),
1263 (0x49, invalidIn64BitMode parseDEC),
1264 (0x4a, invalidIn64BitMode parseDEC),
1265 (0x4b, invalidIn64BitMode parseDEC),
1266 (0x4c, invalidIn64BitMode parseDEC),
1267 (0x4d, invalidIn64BitMode parseDEC),
1268 (0x4e, invalidIn64BitMode parseDEC),
1269 (0x4f, invalidIn64BitMode parseDEC),
1288 (0x60, invalidIn64BitMode parsePUSHA),
1289 (0x61, invalidIn64BitMode parsePOPA),
1290 (0x62, invalidIn64BitMode parseBOUND),
1291 (0x63, choose64BitMode parseARPL parseMOVSXD), -- MOVSXD in 64-bit mode
1292 (0x64, parseInvalidPrefix), -- FS segment override prefix
1293 (0x65, parseInvalidPrefix), -- GS segment override prefix
1294 (0x66, parseInvalidPrefix), -- operand-size prefix
1295 (0x67, parseInvalidPrefix), -- address-size prefix
1296 (0x68, parsePUSHImm),
1298 (0x6a, parsePUSHImm),
1305 (0x70, parseJccShort),
1306 (0x71, parseJccShort),
1307 (0x72, parseJccShort),
1308 (0x73, parseJccShort),
1309 (0x74, parseJccShort),
1310 (0x75, parseJccShort),
1311 (0x76, parseJccShort),
1312 (0x77, parseJccShort),
1313 (0x78, parseJccShort),
1314 (0x79, parseJccShort),
1315 (0x7a, parseJccShort),
1316 (0x7b, parseJccShort),
1317 (0x7c, parseJccShort),
1318 (0x7d, parseJccShort),
1319 (0x7e, parseJccShort),
1320 (0x7f, parseJccShort),
1324 (0x82, invalidIn64BitMode parseGrp1),
1339 (0x90, parse0x90), -- NOP, PAUSE(F3), XCHG r8,rAX
1340 (0x91, parseXCHGReg),
1341 (0x92, parseXCHGReg),
1342 (0x93, parseXCHGReg),
1343 (0x94, parseXCHGReg),
1344 (0x95, parseXCHGReg),
1345 (0x96, parseXCHGReg),
1346 (0x97, parseXCHGReg),
1347 (0x98, parseCBW_CWDE_CDQE),
1348 (0x99, parseCWD_CDQ_CQO),
1349 (0x9a, invalidIn64BitMode parseCALLF),
1350 (0x9b, parseGeneric WAIT OPNONE),
1353 (0x9e, parseGeneric SAHF OPNONE),
1354 (0x9f, parseGeneric LAHF OPNONE),
1356 (0xa0, parseMOVImm),
1357 (0xa1, parseMOVImm),
1358 (0xa2, parseMOVImm),
1359 (0xa3, parseMOVImm),
1364 (0xa8, parseTESTImm),
1365 (0xa9, parseTESTImm),
1373 (0xb0, parseMOVImmByteToByteReg),
1374 (0xb1, parseMOVImmByteToByteReg),
1375 (0xb2, parseMOVImmByteToByteReg),
1376 (0xb3, parseMOVImmByteToByteReg),
1377 (0xb4, parseMOVImmByteToByteReg),
1378 (0xb5, parseMOVImmByteToByteReg),
1379 (0xb6, parseMOVImmByteToByteReg),
1380 (0xb7, parseMOVImmByteToByteReg),
1381 (0xb8, parseMOVImmToReg),
1382 (0xb9, parseMOVImmToReg),
1383 (0xba, parseMOVImmToReg),
1384 (0xbb, parseMOVImmToReg),
1385 (0xbc, parseMOVImmToReg),
1386 (0xbd, parseMOVImmToReg),
1387 (0xbe, parseMOVImmToReg),
1388 (0xbf, parseMOVImmToReg),
1394 (0xc4, invalidIn64BitMode (parseLoadSegmentRegister LES)),
1395 (0xc5, invalidIn64BitMode (parseLoadSegmentRegister LDS)),
1399 (0xc9, parseGeneric LEAVE OPNONE),
1400 (0xca, parseGenericIw RETF),
1401 (0xcb, parseGeneric RETF OPNONE),
1402 (0xcc, parseGeneric INT3 OPNONE),
1403 (0xcd, parseGenericIb INT),
1404 (0xce, parseGeneric INTO OPNONE),
1405 (0xcf, parseGeneric IRET OPNONE),
1411 (0xd4, parseGenericIb AAM),
1412 (0xd5, parseGenericIb AAD),
1413 (0xd6, parseReserved), -- reserved
1414 (0xd7, parseGeneric XLAT OPNONE),
1424 (0xe0, parseGenericJb LOOPNE),
1425 (0xe1, parseGenericJb LOOPE),
1426 (0xe2, parseGenericJb LOOP),
1427 (0xe3, parseGenericJb JCXZ), -- depends on bit mode
1430 (0xe6, parseOUTImm),
1431 (0xe7, parseOUTImm),
1432 (0xe8, parseGenericJz CALL),
1433 (0xe9, parseGenericJz JMP),
1435 (0xeb, parseGenericJb JMP),
1441 (0xf0, parseInvalidPrefix), -- LOCK prefix
1442 (0xf1, parseReserved), -- reserved
1443 (0xf2, parseInvalidPrefix), -- REPNE prefix
1444 (0xf3, parseInvalidPrefix), -- REP/REPQ prefix
1445 (0xf4, parseGeneric HLT OPNONE),
1446 (0xf5, parseGeneric CMC OPNONE),
1449 (0xf8, parseGeneric CLC OPNONE),
1450 (0xf9, parseGeneric STC OPNONE),
1451 (0xfa, parseGeneric CLI OPNONE),
1452 (0xfb, parseGeneric STI OPNONE),
1453 (0xfc, parseGeneric CLD OPNONE),
1454 (0xfd, parseGeneric STD OPNONE),
1460 parseInvalidPrefix b = do
1461 return $ Bad b "invalid prefix"
1463 parseInvalidOpcode b = do
1464 return $ Bad b "invalid opcode"
1466 parseReserved b = do
1467 return $ Bad b "reserved opcode"
1469 parseUndefined name b = do
1470 return $ Bad b ("undefined opcode: " ++ show name)
1472 parseUnimplemented b = do
1473 return $ Bad b "not implemented yet"
1475 invalidIn64BitMode p b = do
1478 then return $ Bad b "invalid in 64-bit mode"
1481 onlyIn64BitMode p b = do
1485 else return $ Bad b "only in 64-bit mode"
1487 choose64BitMode p32 p64 b = do
1493 chooseOperandSize p16 p32 b = do
1495 case operandBitMode st of
1499 chooseAddressSize p16 p32 b = do
1501 case addressBitMode st of
1509 return (b `shiftR` 6, (b `shiftR` 3) .&. 7, (b .&. 7))
1515 return (b `shiftR` 6, (b `shiftR` 3) .&. 7, (b .&. 7))
1523 parseAddress32 :: InstrOperandSize ->
1524 Word8Parser (Operand, Operand, Word8, Word8, Word8)
1525 parseAddress32 s = do
1529 parseAddress32' :: InstrOperandSize ->
1531 Word8Parser (Operand, Operand, Word8, Word8, Word8)
1532 parseAddress32' opsize modrm = do
1533 (mod, reg_opc, rm) <- parseModRM' modrm
1535 let opregnames = if in64BitMode st && hasREX rex_W st
1537 else case operandBitMode st of
1540 let addregnames = if in64BitMode st && hasREX rex_R st
1542 else case addressBitMode st of
1548 (s, i, b) <- parseSIB
1552 return (OpAddr (fromIntegral disp) opsize,
1553 OpReg (opregnames !! fromIntegral reg_opc)
1554 (fromIntegral reg_opc),
1558 return (OpIndexDisp (addregnames !! fromIntegral i)
1562 OpReg (opregnames !! fromIntegral reg_opc)
1563 (fromIntegral reg_opc),
1565 (4, _) -> return (OpInd (addregnames !! fromIntegral b) opsize,
1566 OpReg (opregnames !! fromIntegral reg_opc)
1567 (fromIntegral reg_opc),
1569 (_ ,_) -> return (OpBaseIndex
1570 (addregnames !! fromIntegral b)
1571 (addregnames !! fromIntegral i)
1572 (scaleToFactor (fromIntegral s))
1574 OpReg (opregnames !! fromIntegral reg_opc)
1575 (fromIntegral reg_opc),
1579 return (OpAddr disp opsize,
1580 OpReg (opregnames !! fromIntegral reg_opc)
1581 (fromIntegral reg_opc),
1583 _ -> return (OpInd (addregnames !! fromIntegral rm) opsize,
1584 OpReg (opregnames !! fromIntegral reg_opc)
1585 (fromIntegral reg_opc),
1589 (s, i, b) <- parseSIB
1592 4 -> return (OpIndDisp
1593 (addregnames !! fromIntegral b)
1594 (fromIntegral disp) opsize,
1595 OpReg (opregnames !! fromIntegral reg_opc)
1596 (fromIntegral reg_opc),
1598 _ -> return (OpBaseIndexDisp
1599 (addregnames !! fromIntegral b)
1600 (addregnames !! fromIntegral i)
1601 (scaleToFactor (fromIntegral s))
1604 OpReg (opregnames !! fromIntegral reg_opc)
1605 (fromIntegral reg_opc),
1607 _ -> do disp <- anyInt8
1609 (addregnames !! fromIntegral rm)
1612 OpReg (opregnames !! fromIntegral reg_opc)
1613 (fromIntegral reg_opc),
1617 (s, i, b) <- parseSIB
1620 4 -> return (OpIndDisp
1621 (addregnames !! fromIntegral b)
1624 OpReg (opregnames !! fromIntegral reg_opc)
1625 (fromIntegral reg_opc),
1627 _ -> return (OpBaseIndexDisp
1628 (addregnames !! fromIntegral b)
1629 (addregnames !! fromIntegral i)
1630 (scaleToFactor (fromIntegral s))
1633 OpReg (opregnames !! fromIntegral reg_opc)
1634 (fromIntegral reg_opc),
1639 (addregnames !! fromIntegral rm)
1642 OpReg (opregnames !! fromIntegral reg_opc)
1643 (fromIntegral reg_opc),
1645 3 -> return (OpReg (opregnames !! fromIntegral rm)
1647 OpReg (opregnames !! fromIntegral reg_opc)
1648 (fromIntegral reg_opc),
1651 parseALU :: Opcode -> Word8 -> Word8Parser Instr
1653 opsize <- instrOperandSize
1655 0 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1656 return $ Instr op OP8 [op1,
1657 (OpReg (regnames8 !! fromIntegral reg)) (fromIntegral reg)]
1658 1 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1659 return $ Instr op opsize [op1, op2]
1660 2 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1661 return $ Instr op OP8
1662 [(OpReg (regnames8 !! fromIntegral reg))
1663 (fromIntegral reg), op1]
1664 3 -> do (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1665 return $ Instr op opsize [op2, op1]
1666 4 -> do b <- anyWord8
1667 return $ Instr op OP8 [(OpReg "al" 0), (OpImm (fromIntegral b))]
1668 5 -> do b <- anyWordZ
1669 rn <- registerName 0
1670 return $ Instr op opsize [(OpReg rn 0), (OpImm b)]
1671 _ -> return $ Bad b "no ALU opcode (internal error)"
1674 parsePUSHSeg :: String -> Word8 -> Word8Parser Instr
1675 parsePUSHSeg r _ = do
1676 return $ Instr PUSH OP16 [(OpReg r 0)] -- FIXME: register number
1678 parsePOPSeg :: String -> Word8 -> Word8Parser Instr
1679 parsePOPSeg r _ = do
1680 return $ Instr POP OP16 [(OpReg r 0)] -- FIXME: register number
1682 parseGenericGvEw name b = do
1683 (op1, op2, mod, reg, rm) <- parseAddress32 OP16
1685 OpReg _ num -> return $ Instr name OP16 [op2,
1686 OpReg (regnames16 !! num) num]
1687 _ -> return $ Instr name OP8 [op2, op1]
1689 parseGenericGvEb name b = do
1690 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
1692 OpReg _ num -> return $ Instr name OP8 [op2,
1693 OpReg (regnames8 !! num) num]
1694 _ -> return $ Instr name OP8 [op2, op1]
1696 parseGenericGvEv name b = do
1697 opsize <- instrOperandSize
1698 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1699 return $ Instr name opsize [op2, op1]
1701 parseGenericEvGv name b = do
1702 opsize <- instrOperandSize
1703 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
1704 return $ Instr name opsize [op1, op2]
1706 parseGenericEbGb name b = do
1707 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
1708 return $ Instr name OP8 [op1, (OpReg (regnames8 !! fromIntegral reg)
1709 (fromIntegral reg))]
1711 parseGenericEv name b = do
1712 opsize <- instrOperandSize
1713 (op1, op2, mod, _, rm) <- parseAddress32 opsize
1714 return $ Instr name opsize [op1]
1719 (0x02, parseGenericGvEw LAR),
1720 (0x03, parseGenericGvEw LSL),
1721 (0x04, parseReserved),
1722 (0x05, onlyIn64BitMode (parseGeneric SYSCALL OPNONE)),
1723 (0x06, parseGeneric CLTS OPNONE),
1724 (0x07, onlyIn64BitMode (parseGeneric SYSCALL OPNONE)),
1725 (0x08, parseGeneric INVD OPNONE),
1726 (0x09, parseGeneric WBINVD OPNONE),
1727 (0x0a, parseReserved),
1728 (0x0b, parseUndefined UD2),
1729 (0x0c, parseReserved),
1730 (0x0d, parseGenericEv NOP),
1731 (0x0e, parseReserved),
1732 (0x0f, parseReserved),
1734 (0x10, parseMOVUPS),
1735 (0x11, parseMOVUPS),
1736 (0x12, parseMOVLPS),
1737 (0x13, parseMOVLPS),
1738 (0x14, parseUNPCKLPS),
1739 (0x15, parseUNPCKHPS),
1740 (0x16, parseMOVHPS),
1741 (0x17, parseMOVHPS),
1743 (0x19, parseReserved),
1744 (0x1a, parseReserved),
1745 (0x1b, parseReserved),
1746 (0x1c, parseReserved),
1747 (0x1d, parseReserved),
1748 (0x1e, parseReserved),
1749 (0x1f, parseGenericEv NOP),
1751 (0x20, parseMOVCtrlDebug),
1752 (0x21, parseMOVCtrlDebug),
1753 (0x22, parseMOVCtrlDebug),
1754 (0x23, parseMOVCtrlDebug),
1755 (0x24, parseReserved),
1756 (0x25, parseReserved),
1757 (0x26, parseReserved),
1758 (0x27, parseReserved),
1759 (0x28, parseMOVAPS),
1760 (0x29, parseMOVAPS),
1761 (0x2a, parseCVTI2PS),
1762 (0x2b, parseMOVNTPS),
1763 (0x2c, parseCVTTPS2PI),
1764 (0x2d, parseCVTPS2PI),
1765 (0x2e, parseUCOMISS),
1766 (0x2f, parseCOMISS),
1768 (0x30, parseGeneric WRMSR OPNONE),
1769 (0x31, parseGeneric RDTSC OPNONE),
1770 (0x32, parseGeneric RDMSR OPNONE),
1771 (0x33, parseGeneric RDPMC OPNONE),
1772 (0x34, parseGeneric SYSENTER OPNONE),
1773 (0x35, parseGeneric SYSEXIT OPNONE),
1774 (0x36, parseReserved),
1775 (0x37, parseReserved),
1776 (0x38, parseReserved),
1777 (0x39, parseReserved),
1778 (0x3a, parseReserved),
1779 (0x3b, parseReserved),
1780 (0x3c, parseReserved),
1781 (0x3d, parseReserved),
1782 (0x3e, parseReserved),
1783 (0x3f, parseReserved),
1785 (0x40, parseCMOVcc),
1786 (0x41, parseCMOVcc),
1787 (0x42, parseCMOVcc),
1788 (0x43, parseCMOVcc),
1789 (0x44, parseCMOVcc),
1790 (0x45, parseCMOVcc),
1791 (0x46, parseCMOVcc),
1792 (0x47, parseCMOVcc),
1793 (0x48, parseCMOVcc),
1794 (0x49, parseCMOVcc),
1795 (0x4a, parseCMOVcc),
1796 (0x4b, parseCMOVcc),
1797 (0x4c, parseCMOVcc),
1798 (0x4d, parseCMOVcc),
1799 (0x4e, parseCMOVcc),
1800 (0x4f, parseCMOVcc),
1802 (0x50, parseMOVSKPS),
1803 (0x51, parseSQRTPS),
1804 (0x52, parseRSQRTPS),
1807 (0x55, parseANDNPS),
1812 (0x5a, parseCVTPS2PD),
1813 (0x5b, parseCVTDQ2PS),
1819 (0x60, parsePUNPCKLBW),
1820 (0x61, parsePUNPCKLWD),
1821 (0x62, parsePUNPCKLDQ),
1822 (0x63, parsePACKSSWB),
1823 (0x64, parsePCMPGTB),
1824 (0x65, parsePCMPGTW),
1825 (0x66, parsePCMPGTD),
1826 (0x67, parsePACKUSWB),
1827 (0x68, parsePUNPCKHBW),
1828 (0x69, parsePUNPCKHWD),
1829 (0x6a, parsePUNPCKHDQ),
1830 (0x6b, parsePACKSSDW),
1831 (0x6c, parsePUNPCKLQDQ),
1832 (0x6d, parsePUNPCKHQDQ),
1833 (0x6e, parseMOVD_Q),
1836 (0x70, parsePSHUFW),
1840 (0x74, parsePCMPEQB),
1841 (0x75, parsePCMPEQW),
1842 (0x76, parsePCMPEQD),
1843 (0x77, parseGeneric EMMS OPNONE),
1844 (0x78, parseVMREAD),
1845 (0x79, parseVMWRITE),
1846 (0x7a, parseReserved),
1847 (0x7b, parseReserved),
1848 (0x7c, parseHADDPS),
1849 (0x7d, parseHSUBPS),
1850 (0x7e, parseMOVD_Q),
1853 (0x80, parseJccLong),
1854 (0x81, parseJccLong),
1855 (0x82, parseJccLong),
1856 (0x83, parseJccLong),
1857 (0x84, parseJccLong),
1858 (0x85, parseJccLong),
1859 (0x86, parseJccLong),
1860 (0x87, parseJccLong),
1861 (0x88, parseJccLong),
1862 (0x89, parseJccLong),
1863 (0x8a, parseJccLong),
1864 (0x8b, parseJccLong),
1865 (0x8c, parseJccLong),
1866 (0x8d, parseJccLong),
1867 (0x8e, parseJccLong),
1868 (0x8f, parseJccLong),
1887 (0xa0, parsePUSHSeg "fs"),
1888 (0xa1, parsePOPSeg "fs"),
1889 (0xa2, parseGeneric CPUID OPNONE),
1890 (0xa3, parseGenericEvGv BT),
1893 (0xa6, parseReserved),
1894 (0xa7, parseReserved),
1895 (0xa8, parsePUSHSeg "gs"),
1896 (0xa9, parsePOPSeg "gs"),
1897 (0xaa, parseGeneric RSM OPNONE),
1898 (0xab, parseGenericEvGv BTS),
1902 (0xaf, parseGenericGvEv IMUL),
1904 (0xb0, parseGenericEbGb CMPXCHG),
1905 (0xb1, parseGenericEvGv CMPXCHG),
1906 (0xb2, parseLoadSegmentRegister LSS),
1907 (0xb3, parseGenericEvGv BTR),
1908 (0xb4, parseLoadSegmentRegister LFS),
1909 (0xb5, parseLoadSegmentRegister LGS),
1910 (0xb6, parseGenericGvEb MOVZXB),
1911 (0xb7, parseGenericGvEw MOVZXW),
1912 (0xb8, parseReserved),
1915 (0xbb, parseGenericEvGv BTC),
1916 (0xbc, parseGenericGvEv BSF),
1917 (0xbd, parseGenericGvEv BSR),
1918 (0xbe, parseGenericGvEb MOVSXB),
1919 (0xbf, parseGenericGvEw MOVSXW),
1921 (0xc0, parseGenericEbGb XADD),
1922 (0xc1, parseGenericEvGv XADD),
1924 (0xc3, parseMOVNTI),
1925 (0xc4, parsePINSRW),
1926 (0xc5, parsePEXTRW),
1927 (0xc6, parseSHUFPS),
1938 (0xd0, parseADDSUBPS),
1943 (0xd5, parsePMULLW),
1945 (0xd7, parsePMOVMSKB),
1946 (0xd8, parsePSUBUSB),
1947 (0xd9, parsePSUBUSW),
1948 (0xda, parsePMINUB),
1950 (0xdc, parsePADDUSB),
1951 (0xdd, parsePADDUSW),
1952 (0xde, parsePMAXUB),
1959 (0xe4, parsePMULHUW),
1960 (0xe5, parsePMULHW),
1961 (0xe6, parseCVTPD2DQ),
1962 (0xe7, parseMOVNTQ),
1963 (0xe8, parsePSUBSB),
1964 (0xe9, parsePSUBSQ),
1965 (0xea, parsePMINSW),
1967 (0xec, parsePADDSB),
1968 (0xed, parsePADDSW),
1969 (0xee, parsePMAXSW),
1976 (0xf4, parsePMULUDQ),
1977 (0xf5, parsePMADDWD),
1978 (0xf6, parsePSADBW),
1979 (0xf7, parseMASKMOVQ),
1987 (0xff, parseReserved)
1990 twoByteEscape :: Word8 -> Word8Parser Instr
1991 twoByteEscape b1 = do
1993 case lookup b twoByteOpCodeMap of
1995 Nothing -> return $ Bad b "invalid two-byte opcode"
1997 parseGeneric name opsize _ = do
1998 return (Instr name opsize [])
1999 parseGenericIb name b = do
2001 return $ Instr name OP8 [OpImm (fromIntegral b)]
2002 parseGenericIw name _ = do
2005 return $ Instr name OP16 [OpImm (fromIntegral w)]
2006 parseGenericJb name _ = do
2010 return $ Instr name OPNONE
2011 [OpAddr (fromIntegral ((fromIntegral b + sourceColumn pos - 1)) +
2012 (startAddr st)) OPNONE]
2013 parseGenericJz name _ = do
2017 return $ Instr name OPNONE
2018 [OpAddr (fromIntegral ((fromIntegral b + sourceColumn pos - 1)) +
2019 (startAddr st)) OPNONE]
2022 opsize <- instrOperandSize
2023 let reg = b .&. 0x0f
2024 rn <- registerName (fromIntegral reg)
2025 return $ Instr INC opsize [OpReg rn (fromIntegral reg)]
2028 opsize <- instrOperandSize
2029 let reg = (b .&. 0x0f) - 8
2030 rn <- registerName (fromIntegral reg)
2031 return $ Instr DEC opsize [OpReg rn (fromIntegral reg)]
2034 let reg = b .&. 0x0f in do
2036 rn <- registerName (fromIntegral reg)
2037 opsize <- instrOperandSize
2039 then return $ Instr PUSH opsize [OpReg ("r" ++ show (reg + 8))
2041 else return $ Instr PUSH opsize [OpReg rn
2045 let reg = (b .&. 0x0f) - 8 in do
2047 rn <- registerName (fromIntegral reg)
2048 opsize <- instrOperandSize
2050 then return $ Instr POP opsize [OpReg ("r" ++ show (reg + 8))
2052 else return $ Instr POP opsize [OpReg rn (fromIntegral reg)]
2056 (\ _ -> return $ Instr PUSHA OPNONE [])
2057 (\ _ -> return $ Instr PUSHAD OPNONE [])
2060 (\ _ -> return $ Instr POPA OPNONE [])
2061 (\ _ -> return $ Instr POPAD OPNONE [])
2064 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2065 return $ Instr BOUND OPNONE [op2, op1]
2068 (op1, op2, mod, reg, rm) <- parseAddress32 OP16
2069 let rn = regnames16 !! fromIntegral reg
2070 return $ Instr ARPL OPNONE [op1, (OpReg rn (fromIntegral reg))]
2073 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2074 return $ Instr MOVSXD OPNONE [op2, op1]
2076 parsePUSHImm 0x68 = do
2078 opsize <- instrOperandSize
2079 return $ Instr PUSH opsize [OpImm w]
2080 parsePUSHImm 0x6a = do
2082 opsize <- instrOperandSize
2083 return $ Instr PUSH opsize [OpImm (fromIntegral w)]
2086 opsize <- instrOperandSize
2087 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2089 return $ Instr IMUL opsize [op2, op1, OpImm imm]
2091 opsize <- instrOperandSize
2092 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2094 return $ Instr IMUL opsize [op2, op1, OpImm (fromIntegral imm)]
2096 parseINS 0x6c = return $ Instr INS OP8 []
2097 parseINS b@0x6d = chooseOperandSize
2098 (\ _ -> return $ Instr INS OP16 [])
2099 (\ _ -> return $ Instr INS OP32 []) b
2101 parseOUTS 0x6e = return $ Instr OUTS OP8 []
2102 parseOUTS b@0x6f = chooseOperandSize
2103 (\ _ -> return $ Instr OUTS OP16 [])
2104 (\ _ -> return $ Instr OUTS OP32 []) b
2106 parseJccShort b = do
2110 return $ Instr (jccname (b .&. 0xf)) OPNONE
2111 [OpAddr (fromIntegral (fromIntegral disp + sourceColumn pos - 1) +
2112 (startAddr st)) OPNONE]
2115 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2116 return $ Instr TEST OP8 [op1, OpReg (regnames8 !! fromIntegral reg)
2119 opsize <- instrOperandSize
2120 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2121 return $ Instr TEST opsize [op1, op2]
2124 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2125 return $ Instr XCHG OP8 [op1, OpReg (regnames8 !! fromIntegral reg)
2128 opsize <- instrOperandSize
2129 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2130 return $ Instr XCHG opsize[op1, op2]
2133 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2134 return $ Instr MOV OP8 [op1, OpReg (regnames8 !! fromIntegral reg)
2137 opsize <- instrOperandSize
2138 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2139 return $ Instr MOV opsize [op1, op2]
2141 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2142 return $ Instr MOV OP8 [OpReg (regnames8 !! fromIntegral reg)
2143 (fromIntegral reg), op1]
2145 opsize <- instrOperandSize
2146 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2147 return $ Instr MOV opsize [op2, op1]
2149 (op1, op2, mod, reg, rm) <- parseAddress32 OP16
2150 let rn = segregnames !! (fromIntegral reg)
2151 return $ Instr MOV OP16 [op1, OpReg rn (fromIntegral reg)]
2153 (op1, op2, mod, reg, rm) <- parseAddress32 OP16
2154 let rn = segregnames !! (fromIntegral reg)
2155 return $ Instr MOV OP16 [OpReg rn (fromIntegral reg), op1]
2158 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2159 return $ Instr LEA OPNONE [op2, op1]
2164 if hasPrefix 0xf3 st
2165 then return $ Instr PAUSE OPNONE []
2166 else do st <- getState
2169 else return $ Instr NOP OPNONE []
2171 -- FIXME: Register name handling not quite right
2173 parseXCHGReg :: Word8 -> Word8Parser Instr
2175 let reg = b .&. 0x0f in do
2178 then return $ Instr XCHG OP64 [OpReg "rax" 0,
2179 OpReg ("r" ++ show (reg + 8))
2181 else do rn <- registerName (fromIntegral reg)
2182 return $ Instr XCHG OP64 [OpReg "rax" 0,
2183 OpReg rn (fromIntegral reg)]
2185 parseCBW_CWDE_CDQE b = do
2188 then if hasREX rex_W st
2189 then return $ Instr CDQE OPNONE []
2190 else return $ Instr CWDE OPNONE []
2191 else chooseOperandSize
2192 (\ _ -> return $ Instr CBW OPNONE [])
2193 (\ _ -> return $ Instr CWDE OPNONE []) b
2195 parseCWD_CDQ_CQO b = do
2198 then if hasREX rex_W st
2199 then return $ Instr CDQE OPNONE []
2200 else return $ Instr CDQ OPNONE []
2201 else chooseOperandSize
2202 (\ _ -> return $ Instr CWD OPNONE [])
2203 (\ _ -> return $ Instr CDQ OPNONE []) b
2208 return $ Instr CALLF OPNONE [OpImm (fromIntegral w),
2209 OpImm (fromIntegral s)]
2211 -- FIXME: Check default/operand sizes.
2216 then chooseOperandSize
2217 (\ _ -> return $ Instr PUSHF OPNONE [])
2218 (\ _ -> return $ Instr PUSHFQ OPNONE []) b
2219 else chooseOperandSize
2220 (\ _ -> return $ Instr PUSHF OPNONE [])
2221 (\ _ -> return $ Instr PUSHFD OPNONE []) b
2226 then chooseOperandSize
2227 (\ _ -> return $ Instr POPF OPNONE [])
2228 (\ _ -> return $ Instr POPFQ OPNONE []) b
2229 else chooseOperandSize
2230 (\ _ -> return $ Instr POPF OPNONE [])
2231 (\ _ -> return $ Instr POPFD OPNONE []) b
2235 return $ Instr JMPF OPNONE [OpImm w]
2237 parseMOVImm b@0xa0 = do
2239 (\ _ -> do w <- anyWord16
2240 return $ Instr MOV OP8 [OpReg "al" 0, OpImm (fromIntegral w)])
2241 (\ _ -> do w <- anyWord32
2242 return $ Instr MOV OP8 [OpReg "al" 0, OpImm w]) b
2243 parseMOVImm b@0xa1 = do
2244 opsize <- instrOperandSize
2245 reg <- registerName 0
2247 (\ _ -> do w <- anyWord16
2248 return $ Instr MOV opsize [OpReg reg 0, OpImm (fromIntegral w)])
2249 (\ _ -> do w <- anyWord32
2250 return $ Instr MOV opsize [OpReg reg 0, OpImm w]) b
2251 parseMOVImm b@0xa2 = do
2253 (\ _ -> do w <- anyWord16
2254 return $ Instr MOV OP8 [OpImm (fromIntegral w), OpReg "al" 0])
2255 (\ _ -> do w <- anyWord32
2256 return $ Instr MOV OP8 [OpImm w, OpReg "al" 0]) b
2257 parseMOVImm b@0xa3 = do
2258 opsize <- instrOperandSize
2259 reg <- registerName 0
2261 (\ _ -> do w <- anyWord16
2262 return $ Instr MOV opsize [OpImm (fromIntegral w), OpReg reg 0])
2263 (\ _ -> do w <- anyWord32
2264 return $ Instr MOV opsize [OpImm w, OpReg reg 0]) b
2266 parseMOVS 0xa4 = return $ Instr MOVS OP8 []
2267 parseMOVS b@0xa5 = do
2269 opsize <- instrOperandSize
2270 return $ Instr MOVS opsize []
2272 parseCMPS 0xa6 = return $ Instr CMPS OP8 []
2275 opsize <- instrOperandSize
2276 return $ Instr CMPS opsize []
2278 parseTESTImm 0xa8 = do
2280 return $ Instr TEST OP8 [OpReg "al" 0, OpImm (fromIntegral imm)]
2281 parseTESTImm 0xa9 = do
2283 rn <- registerName 0
2284 opsize <- instrOperandSize
2285 return $ Instr TEST opsize [OpReg rn 0, OpImm imm]
2288 parseSTOS 0xaa = return $ Instr STOS OP8 []
2289 parseSTOS b@0xab = do
2291 opsize <- instrOperandSize
2293 then if hasREX rex_W st
2294 then return $ Instr STOS opsize []
2295 else chooseOperandSize
2296 (\ _ -> return $ Instr STOS opsize [])
2297 (\ _ -> return $ Instr STOS opsize []) b
2298 else chooseOperandSize
2299 (\ _ -> return $ Instr STOS opsize [])
2300 (\ _ -> return $ Instr STOS opsize []) b
2302 parseLODS 0xac = return $ Instr LODS OP8 []
2303 parseLODS b@0xad = do
2305 opsize <- instrOperandSize
2307 then if hasREX rex_W st
2308 then return $ Instr LODS opsize []
2309 else chooseOperandSize
2310 (\ _ -> return $ Instr LODS opsize [])
2311 (\ _ -> return $ Instr LODS opsize []) b
2312 else chooseOperandSize
2313 (\ _ -> return $ Instr LODS opsize [])
2314 (\ _ -> return $ Instr LODS opsize []) b
2316 parseSCAS 0xae = return $ Instr SCAS OP8 []
2317 parseSCAS b@0xaf = do
2319 opsize <- instrOperandSize
2321 then if hasREX rex_W st
2322 then return $ Instr SCAS opsize []
2323 else chooseOperandSize
2324 (\ _ -> return $ Instr SCAS opsize [])
2325 (\ _ -> return $ Instr SCAS opsize []) b
2326 else chooseOperandSize
2327 (\ _ -> return $ Instr SCAS opsize [])
2328 (\ _ -> return $ Instr SCAS opsize []) b
2330 parseMOVImmByteToByteReg :: Word8 -> Word8Parser Instr
2331 parseMOVImmByteToByteReg b = do
2332 let reg = b .&. 0x0f
2336 then return $ Instr MOV OP8 [OpReg ("r" ++ show reg ++ "l")
2338 OpImm (fromIntegral imm)]
2339 else return $ Instr MOV OP8 [OpReg (regnames8 !! (fromIntegral reg))
2341 OpImm (fromIntegral imm)]
2343 parseMOVImmToReg :: Word8 -> Word8Parser Instr
2344 parseMOVImmToReg b = do
2345 let reg = (b .&. 0x0f - 8)
2347 opsize <- instrOperandSize
2348 rn <- registerName (fromIntegral reg)
2349 return $ Instr MOV opsize [OpReg rn (fromIntegral reg),
2350 OpImm (fromIntegral imm)]
2354 return $ Instr RET OPNONE [OpImm (fromIntegral w)]
2355 parseRETN 0xc3 = return $ Instr RET OPNONE []
2357 parseLoadSegmentRegister opcode b = do
2358 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2359 return $ Instr opcode OPNONE [op2, op1]
2364 return $ Instr ENTER OPNONE [OpImm (fromIntegral w),
2365 OpImm (fromIntegral b)]
2367 -- Floating-point operations. These can probably shortened by doing some
2368 -- arithmetic/logical tricks on the opcodes, but since the instruction
2369 -- set is still quite irregular (even though much better than the integer
2370 -- ops), I haven't bothered yet.
2375 modrm' = modrm - 0xc0
2377 then do (op1, op2, mod, reg, rm) <- parseAddress32' OPF32 modrm
2378 return $ Instr (ops !! fromIntegral reg) OPF32 [op1]
2379 else if (modrm .&. 0x0f) < 0x8
2381 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2382 [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]
2384 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2385 [OpFPReg 0, OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8))]
2386 where ops = [FADD, FMUL, FCOM, FCOMP,
2387 FSUB, FSUBR, FDIV, FDIVR]
2389 parseESC b@0xd9 = do
2392 modrm' = modrm - 0xc0
2394 then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2395 let op1 = case op1' of
2396 OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)
2398 return $ Instr (lowOps !! fromIntegral reg)
2399 (opsizes !! fromIntegral reg) [op1]
2400 else if (modrm < 0xd0)
2401 then if (modrm .&. 0x0f) < 8
2403 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2404 [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]
2406 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2407 [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f)
2410 0xd0 -> return $ Instr FNOP OPNONE []
2411 0xe0 -> return $ Instr FCHS OPNONE []
2412 0xe1 -> return $ Instr FABS OPNONE []
2413 0xe4 -> return $ Instr FTST OPNONE []
2414 0xe5 -> return $ Instr FXAM OPNONE []
2415 0xe8 -> return $ Instr FLD1 OPNONE []
2416 0xe9 -> return $ Instr FLDL2T OPNONE []
2417 0xea -> return $ Instr FLDL2E OPNONE []
2418 0xeb -> return $ Instr FLDPI OPNONE []
2419 0xec -> return $ Instr FLDLG2 OPNONE []
2420 0xed -> return $ Instr FLDLN2 OPNONE []
2421 0xee -> return $ Instr FLDZ OPNONE []
2422 _ -> parseInvalidOpcode b
2423 where lowOps = [FLD, InvalidOpcode, FST, FSTP,
2424 FLDENV, FLDCW, FSTENV, FSTCW]
2425 opsizes = [OPF32, OPNONE, OPF32, OPF32,
2426 OPNONE, OPNONE, OPNONE, OPNONE]
2432 modrm' = modrm - 0xc0
2434 then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2435 return $ Instr (ops !! fromIntegral reg) OPNONE [op1]
2436 else if (modrm < 0xe0)
2438 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2439 [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]
2441 0xe1 -> return $ Instr FUCOMPP OPNONE []
2442 _ -> parseInvalidOpcode 0xda
2443 where ops = [FIADD, FIMUL, FICOM, FICOMP,
2444 FISUB, FISUBR, FIDIV, FIDIVR]
2445 ops' = [FCMOVB, FCMOVE, FCMOVBE, FCMOVU]
2450 modrm' = modrm - 0xc0
2452 then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2453 let op1 = case op1' of
2454 OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)
2456 return $ Instr (ops !! fromIntegral reg)
2457 (opsizes !! fromIntegral reg) [op1]
2460 0xe2 -> return $ Instr FCLEX OPNONE []
2461 0xe3 -> return $ Instr FINIT OPNONE []
2463 if (modrm .&. 0x0f) < 0x8
2465 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2466 [OpFPReg 0, OpFPReg (fromIntegral (modrm .&. 0x0f))]
2468 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2469 [OpFPReg 0, OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8))]
2470 where ops = [FILD, FISTP, FIST, FISTP,
2471 InvalidOpcode, FLD, InvalidOpcode, FSTP]
2472 opsizes = [OP32, OP32, OP32, OP32,
2473 OPNONE, OPF80, OPNONE, OPF80]
2474 ops' = [FCMOVNB, FCMOVNE, FCMOVNBE, FCMOVNU,
2475 InvalidOpcode, FUCOMI, FCOMI, InvalidOpcode]
2480 modrm' = modrm - 0xc0
2482 then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2483 return $ Instr (ops !! fromIntegral reg) OPNONE [op1]
2485 if modrm >= 0xd0 && modrm < 0xe0
2486 then parseInvalidOpcode 0xdc
2487 else if (modrm .&. 0x0f) < 0x8
2489 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2490 [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]
2492 (ops !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2493 [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]
2494 where ops = [FADD, FMUL, FCOM, FCOMP,
2495 FSUB, FSUBR, FDIV, FDIVR]
2500 modrm' = modrm - 0xc0
2502 then do (op1', op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2503 let op1 = case op1' of
2504 OpAddr a _ -> OpAddr a (opsizes !! fromIntegral reg)
2506 return $ Instr (ops !! fromIntegral reg)
2507 (opsizes !! fromIntegral reg) [op1]
2509 if (modrm >= 0xc8) && modrm <= 0xd0 || (modrm >= 0xf0 && modrm < 0xff)
2510 then parseInvalidOpcode 0xdc
2511 else if (modrm .&. 0x0f) < 0x8
2513 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2514 [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]
2516 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2517 [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]
2518 where ops = [FLD, FISTTP, FST, FSTP,
2519 FRSTOR, InvalidOpcode, FSAVE, FSTSW]
2520 opsizes = [OPF64, OP64, OPF64, OPF64,
2521 OPNONE, OPNONE, OPNONE, OP16]
2522 ops' = [FFREE, InvalidOpcode, FST, FSTP,
2528 modrm' = modrm - 0xc0
2530 then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2531 return $ Instr (ops !! fromIntegral reg) OPNONE [op1]
2533 if modrm >= 0xd0 && modrm <= 0xe0
2535 0xd9 -> return $ Instr FCOMPP OPNONE []
2536 _ -> parseInvalidOpcode 0xde
2537 else if (modrm .&. 0x0f) < 0x8
2539 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2540 [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]
2542 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2543 [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]
2544 where ops = [FIADD, FIMUL, FICOM, FICOMP,
2545 FISUB, FISUBR, FIDIV, FIDIVR]
2546 ops' = [FADDP, FMULP, InvalidOpcode, InvalidOpcode,
2547 FSUBRP, FSUBP, FDIVRP, FDIVP]
2553 modrm' = modrm - 0xc0
2555 then do (op1, op2, mod, reg, rm) <- parseAddress32' OPNONE modrm
2556 return $ Instr (ops !! fromIntegral reg) OPNONE [op1]
2559 0xe0 -> return $ Instr FSTSW OPNONE [OpReg "ax" 0]
2561 if (modrm >= 0xe8 && modrm <= 0xef) ||
2562 (modrm >= 0xf0 && modrm <= 0xf7)
2564 if (modrm .&. 0x0f) < 0x8
2566 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2567 [OpFPReg (fromIntegral (modrm .&. 0x0f)), OpFPReg 0]
2569 (ops' !! fromIntegral ((modrm' `shiftR` 3))) OPNONE
2570 [OpFPReg (fromIntegral ((modrm .&. 0x0f) - 8)), OpFPReg 0]
2571 else parseInvalidOpcode 0xdf
2572 where ops = [FILD, FISTPP, FIST, FISTP,
2573 FBLD, FILD, FBSTP, FISTP]
2574 ops' = [InvalidOpcode, InvalidOpcode, InvalidOpcode, InvalidOpcode,
2575 InvalidOpcode, FUCOMIP, FCOMIP, InvalidOpcode]
2577 parseINImm 0xe4 = do
2579 return $ Instr IN OP8 [OpReg "al" 0, OpImm (fromIntegral b)]
2580 parseINImm 0xe5 = do
2582 rn <- registerName 0
2583 opsize <- instrOperandSize
2584 return $ Instr IN opsize [OpReg rn 0, OpImm (fromIntegral b)]
2585 parseOUTImm 0xe6 = do
2587 return $ Instr OUT OP8 [OpImm (fromIntegral b), OpReg "al" 0]
2588 parseOUTImm 0xe7 = do
2590 rn <- registerName 0
2591 opsize <- instrOperandSize
2592 return $ Instr OUT opsize [OpImm (fromIntegral b), OpReg rn 0]
2595 return $ Instr IN OP8 [OpReg "al" 0, OpReg "dx" 2]
2597 rn <- registerName 0
2598 opsize <- instrOperandSize
2599 return $ Instr IN opsize [OpReg rn 0, OpReg "dx" 2]
2601 return $ Instr OUT OP8 [OpReg "dx" 2, OpReg "al" 0]
2603 rn <- registerName 0
2604 opsize <- instrOperandSize
2605 return $ Instr OUT opsize [OpReg "dx" 2, OpReg rn 0]
2607 -- Return the name of the register encoded with R. Take 64-bit mode and
2608 -- possible REX and operand-size prefixes into account.
2612 if in64BitMode st && hasREX rex_R st
2613 then return $ "r" ++ show (r + 8)
2614 else case operandBitMode st of
2615 BIT16 -> return $ regnames16 !! r
2616 BIT32 -> return $ regnames32 !! r
2618 instrOperandSize = do
2620 if in64BitMode st && hasREX rex_W st
2622 else case operandBitMode st of
2623 BIT16 -> return OP16
2624 BIT32 -> return OP32
2626 regnames8 = ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"]
2627 regnames16 = ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di"]
2628 regnames32 = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"]
2629 regnames64 = ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"]
2630 segregnames = ["es", "cs", "ss", "ds", "fs", "gs", "<invalid>", "<invalid>"]
2631 mmxregs = ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"]
2632 xmmregs = ["xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"]
2662 setccname 11 = SETNP
2664 setccname 13 = SETGE
2665 setccname 14 = SETLE
2668 cmovccname 0 = CMOVO
2669 cmovccname 1 = CMOVNO
2670 cmovccname 2 = CMOVB
2671 cmovccname 3 = CMOVNB
2672 cmovccname 4 = CMOVE
2673 cmovccname 5 = CMOVNE
2674 cmovccname 6 = CMOVBE
2675 cmovccname 7 = CMOVA
2676 cmovccname 8 = CMOVS
2677 cmovccname 9 = CMOVNS
2678 cmovccname 10 = CMOVP
2679 cmovccname 11 = CMOVNP
2680 cmovccname 12 = CMOVL
2681 cmovccname 13 = CMOVGE
2682 cmovccname 14 = CMOVLE
2683 cmovccname 15 = CMOVG
2686 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2688 return $ Instr (aluOps !! fromIntegral reg) OP8
2689 [op1, OpImm (fromIntegral immb)]
2691 opsize <- instrOperandSize
2692 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2694 return $ Instr (aluOps !! fromIntegral reg) opsize
2695 [op1, OpImm (fromIntegral immb)]
2697 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2699 return $ Instr (aluOps !! fromIntegral reg) OP8
2700 [op1, OpImm (fromIntegral immb)]
2702 opsize <- instrOperandSize
2703 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2705 return $ Instr (aluOps !! fromIntegral reg) opsize
2706 [op1, OpImm (fromIntegral immb)]
2707 aluOps = [ADD, OR, ADC, SBB, AND, SUB, XOR, CMP]
2711 opsize <- instrOperandSize
2712 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2714 0 -> return $ Instr POP opsize [op1]
2715 _ -> parseInvalidOpcode b
2718 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2720 return $ Instr (shiftOps !! fromIntegral reg) OP8
2721 [op1, OpImm (fromIntegral immb)]
2723 opsize <- instrOperandSize
2724 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2726 return $ Instr (shiftOps !! fromIntegral reg) opsize
2727 [op1, OpImm (fromIntegral imm)]
2729 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2730 return $ Instr (shiftOps !! fromIntegral reg) OP8 [op1, OpImm 1]
2732 opsize <- instrOperandSize
2733 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2734 return $ Instr (shiftOps !! fromIntegral reg) opsize [op1, OpImm 1]
2736 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2737 return $ Instr (shiftOps !! fromIntegral reg) OP8 [op1, OpReg "cl" 1]
2739 opsize <- instrOperandSize
2740 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2741 return $ Instr (shiftOps !! fromIntegral reg) opsize [op1, OpReg "cl" 1]
2742 shiftOps = [ROL, ROR, RCL, RCR, SHL, SHR, InvalidOpcode, SAR]
2745 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2747 0 -> do imm <- anyWord8
2748 return $ Instr TEST OP8 [op1, OpImm (fromIntegral imm)]
2749 1 -> parseInvalidOpcode 0xf6
2750 2 -> return $ Instr NOT OP8 [op1]
2751 3 -> return $ Instr NEG OP8 [op1]
2752 4 -> return $ Instr MUL OP8 [OpReg "al" 0, op1]
2753 5 -> return $ Instr IMUL OP8 [OpReg "al" 0, op1]
2754 6 -> return $ Instr DIV OP8 [OpReg "al" 0, op1]
2755 7 -> return $ Instr IDIV OP8 [OpReg "al" 0, op1]
2757 opsize <- instrOperandSize
2758 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2759 rn <- registerName 0
2761 0 -> do imm <- anyWordZ
2762 return $ Instr TEST opsize [op1, OpImm (fromIntegral imm)]
2763 1 -> parseInvalidOpcode 0xf6
2764 2 -> return $ Instr NOT opsize [op1]
2765 3 -> return $ Instr NEG opsize [op1]
2766 4 -> return $ Instr MUL opsize [OpReg rn 0, op1]
2767 5 -> return $ Instr IMUL opsize [OpReg rn 0, op1]
2768 6 -> return $ Instr DIV opsize [OpReg rn 0, op1]
2769 7 -> return $ Instr IDIV opsize [OpReg rn 0, op1]
2772 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2774 0 -> return $ Instr INC OP8 [op1]
2775 1 -> return $ Instr DEC OP8 [op1]
2776 _ -> parseInvalidOpcode b
2779 opsize <- instrOperandSize
2780 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2782 0 -> return $ Instr INC opsize [op1]
2783 1 -> return $ Instr DEC opsize [op1]
2784 2 -> return $ Instr CALL OPNONE [op1]
2785 3 -> do w <- anyWord16
2786 return $ Instr CALLF OPNONE [OpAddr (fromIntegral w) OPNONE, op1]
2787 4 -> return $ Instr JMPN OPNONE [op1]
2788 5 -> do w <- anyWord16
2789 return $ Instr JMPF OPNONE [OpAddr (fromIntegral w) OPNONE, op1]
2790 6 -> return $ Instr PUSH opsize [op1]
2791 _ -> parseInvalidOpcode b
2794 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2796 0 -> return $ Instr SLDT OPNONE [op1]
2797 1 -> return $ Instr STR OPNONE [op1]
2798 2 -> return $ Instr LLDT OPNONE [op1]
2799 3 -> return $ Instr LTR OPNONE [op1]
2800 4 -> return $ Instr VERR OPNONE [op1]
2801 5 -> return $ Instr VERW OPNONE [op1]
2802 _ -> parseInvalidOpcode b
2805 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2809 1 -> return $ Instr VMCALL OPNONE []
2810 2 -> return $ Instr VMLAUNCH OPNONE []
2811 3 -> return $ Instr VMRESUME OPNONE []
2812 4 -> return $ Instr VMXOFF OPNONE []
2813 _ -> parseInvalidOpcode b
2815 0 -> return $ Instr MONITOR OPNONE []
2816 1 -> return $ Instr MWAIT OPNONE []
2817 _ -> parseInvalidOpcode b
2818 4 -> return $ Instr SMSW OPNONE [op1]
2819 6 -> return $ Instr LMSW OPNONE [op1]
2821 0 -> onlyIn64BitMode
2822 (\b -> return $ Instr SWAPGS OPNONE []) b
2823 _ -> parseInvalidOpcode b
2824 _ -> parseInvalidOpcode b
2826 0 -> return $ Instr SGDT OPNONE [op1]
2827 1 -> return $ Instr SIDT OPNONE [op1]
2828 2 -> return $ Instr LGDT OPNONE [op1]
2829 3 -> return $ Instr LIDT OPNONE [op1]
2830 4 -> return $ Instr SMSW OPNONE [op1]
2831 5 -> parseInvalidOpcode b
2832 6 -> return $ Instr LMSW OPNONE [op1]
2833 7 -> return $ Instr INVLPG OPNONE [op1]
2836 opsize <- instrOperandSize
2837 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2840 4 -> return $ Instr BT opsize [op1, OpImm (fromIntegral imm)]
2841 5 -> return $ Instr BTS opsize [op1, OpImm (fromIntegral imm)]
2842 6 -> return $ Instr BTR opsize [op1, OpImm (fromIntegral imm)]
2843 7 -> return $ Instr BTC opsize [op1, OpImm (fromIntegral imm)]
2844 _ -> parseInvalidOpcode b
2847 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2850 3 -> parseInvalidOpcode b
2852 1 -> if hasREX rex_W st
2853 then return $ Instr CMPXCHG16B OPNONE [op1]
2854 else return $ Instr CMPXCHG8B OPNONE [op1]
2855 6 -> if hasPrefix 0x66 st
2856 then return $ Instr VMCLEAR OPNONE [op1]
2857 else if hasPrefix 0xf3 st
2858 then return $ Instr VMXON OPNONE [op1]
2859 else return $ Instr VMPTRLD OPNONE [op1]
2860 7 -> return $ Instr VMPTRST OPNONE [op1]
2861 _ -> parseInvalidOpcode b
2863 parseGrp10 = parseInvalidOpcode
2865 parseGrp11 0xc6 = do
2866 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
2868 return $ Instr MOV OP8 [op1, OpImm (fromIntegral imm)]
2869 parseGrp11 0xc7 = do
2870 opsize <- instrOperandSize
2871 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2873 return $ Instr MOV opsize [op1, OpImm (fromIntegral imm)]
2875 mmxInstr op1 mod reg rm name = do
2878 if hasPrefix 0x66 st
2879 then return $ Instr name OP128
2880 [OpReg (xmmregs !! fromIntegral rm) (fromIntegral rm),
2881 OpImm (fromIntegral imm)]
2882 else return $ Instr name OP64
2883 [OpReg (mmxregs !! fromIntegral rm) (fromIntegral rm),
2884 OpImm (fromIntegral imm)]
2888 let opsize = if hasPrefix 0x66 st then OP128 else OP64
2889 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2892 2 -> mmxInstr op1 mod reg rm PSRLW
2893 4 -> mmxInstr op1 mod reg rm PSRAW
2894 6 -> mmxInstr op1 mod reg rm PSLLW
2895 _ -> parseInvalidOpcode b
2896 _ -> parseInvalidOpcode b
2899 let opsize = if hasPrefix 0x66 st then OP128 else OP64
2900 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2903 2 -> mmxInstr op1 mod reg rm PSRLD
2904 4 -> mmxInstr op1 mod reg rm PSRAD
2905 6 -> mmxInstr op1 mod reg rm PSLLD
2906 _ -> parseInvalidOpcode b
2907 _ -> parseInvalidOpcode b
2910 let opsize = if hasPrefix 0x66 st then OP128 else OP64
2911 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
2915 2 -> mmxInstr op1 mod reg rm PSRLQ
2916 3 -> if hasPrefix 0x66 st
2917 then mmxInstr op1 mod reg rm PSRLDQ
2918 else parseInvalidOpcode b
2919 6 -> mmxInstr op1 mod reg rm PSLLQ
2920 7 -> if hasPrefix 0x66 st
2921 then mmxInstr op1 mod reg rm PSLLDQ
2922 else parseInvalidOpcode b
2923 _ -> parseInvalidOpcode b
2924 _ -> parseInvalidOpcode b
2927 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2930 5 -> return $ Instr LFENCE OPNONE []
2931 6 -> return $ Instr MFENCE OPNONE []
2932 7 -> return $ Instr SFENCE OPNONE []
2933 _ -> parseInvalidOpcode b
2935 0 -> return $ Instr FXSAVE OPNONE [op1]
2936 1 -> return $ Instr FXRSTOR OPNONE [op1]
2937 2 -> return $ Instr LDMXCSR OPNONE [op1]
2938 3 -> return $ Instr STMXCSR OPNONE [op1]
2939 7 -> return $ Instr CLFLUSH OPNONE [op1]
2940 _ -> parseInvalidOpcode b
2942 (op1, op2, mod, reg, rm) <- parseAddress32 OPNONE
2944 3 -> parseInvalidOpcode b
2946 0 -> return $ Instr PREFETCHNTA OPNONE [op1]
2947 1 -> return $ Instr PREFETCHT0 OPNONE [op1]
2948 2 -> return $ Instr PREFETCHT1 OPNONE [op1]
2949 3 -> return $ Instr PREFETCHT2 OPNONE [op1]
2950 _ -> parseInvalidOpcode b
2952 parseXmmVW p p0xf3 p0x66 p0xf2 b =
2953 do (op1, op2, mod, reg, rm) <- parseAddress32 OP128
2955 let v = OpReg (xmmregs !! (fromIntegral reg)) (fromIntegral reg)
2957 OpReg _ num -> OpReg (xmmregs !! num) num
2959 if hasPrefix 0xf3 st
2960 then return $ Instr p0xf3 OP128 [v, w]
2961 else if hasPrefix 0x66 st
2962 then return $ Instr p0x66 OP128 [v, w]
2963 else if hasPrefix 0xf2 st
2964 then return $ Instr p0xf2 OP128 [v, w]
2965 else return $ Instr p OP128 [v, w]
2966 parseXmmWV p p0xf3 p0x66 p0xf2 b =
2967 do (op1, op2, mod, reg, rm) <- parseAddress32 OP128
2969 let w = OpReg (xmmregs !! (fromIntegral reg)) (fromIntegral reg)
2971 OpReg _ num -> OpReg (xmmregs !! num) num
2973 if hasPrefix 0xf3 st
2974 then return $ Instr p0xf3 OP128 [v, w]
2975 else if hasPrefix 0x66 st
2976 then return $ Instr p0x66 OP128 [v, w]
2977 else if hasPrefix 0xf2 st
2978 then return $ Instr p0xf2 OP128 [v, w]
2979 else return $ Instr p OP128 [v, w]
2981 parseXmmGU p p0xf3 p0x66 p0xf2 b =
2982 do (mod, reg, rm) <- parseModRM
2984 let g = OpReg (regnames32 !! (fromIntegral reg)) (fromIntegral reg)
2985 let u = OpReg (xmmregs !! (fromIntegral rm)) (fromIntegral rm)
2986 if hasPrefix 0xf3 st
2987 then return $ Instr p0xf3 OP32 [g, u]
2988 else if hasPrefix 0x66 st
2989 then return $ Instr p0x66 OP32 [g, u]
2990 else if hasPrefix 0xf2 st
2991 then return $ Instr p0xf2 OP32 [g, u]
2992 else return $ Instr p OP32 [g, u]
2994 parseMOVUPS b@0x10 = parseXmmVW MOVUPS MOVSS MOVUPD MOVSD b
2995 parseMOVUPS b@0x11 = parseXmmWV MOVUPS MOVSS MOVUPD MOVSD b
2996 parseMOVLPS b@0x12 = parseXmmWV MOVLPS MOVSLDUP MOVLPD MOVDDUP b
2997 parseMOVLPS b@0x13 = parseXmmVW MOVLPS InvalidOpcode MOVLPD InvalidOpcode b
2998 parseUNPCKLPS b@0x14 =
2999 parseXmmVW UNPCKLPS InvalidOpcode UNPCKLPD InvalidOpcode b
3000 parseUNPCKHPS b@0x15 =
3001 parseXmmVW UNPCKHPS InvalidOpcode UNPCKHPD InvalidOpcode b
3002 parseMOVHPS b@0x16 = parseXmmVW MOVHPS MOVLSDUP MOVHPD MOVLHPS b
3003 parseMOVHPS b@0x17 = parseXmmVW MOVHPS InvalidOpcode MOVHPD InvalidOpcode b
3005 parseMOVCtrlDebug 0x20 =
3006 do (mod, reg, rm) <- parseModRM
3007 return $ Instr MOV OPNONE [OpReg (regnames32 !! fromIntegral rm)
3009 OpReg ("cr" ++ show reg) (fromIntegral reg)]
3010 parseMOVCtrlDebug 0x21 =
3011 do (mod, reg, rm) <- parseModRM
3012 return $ Instr MOV OPNONE [OpReg (regnames32 !! fromIntegral rm)
3014 OpReg ("db" ++ show reg) (fromIntegral reg)]
3015 parseMOVCtrlDebug 0x22 =
3016 do (mod, reg, rm) <- parseModRM
3017 return $ Instr MOV OPNONE [OpReg ("cr" ++ show reg) (fromIntegral reg),
3018 OpReg (regnames32 !! fromIntegral rm)
3020 parseMOVCtrlDebug 0x23 =
3021 do (mod, reg, rm) <- parseModRM
3022 return $ Instr MOV OPNONE [OpReg ("db" ++ show reg) (fromIntegral reg),
3023 OpReg (regnames32 !! fromIntegral rm)
3027 parseMOVAPS b@0x28 = parseXmmVW MOVAPS InvalidOpcode MOVAPD InvalidOpcode b
3028 parseMOVAPS b@0x29 = parseXmmWV MOVAPS InvalidOpcode MOVAPD InvalidOpcode b
3029 parseCVTI2PS = parseUnimplemented
3030 parseMOVNTPS = parseXmmWV MOVNTPS InvalidOpcode MOVNTPD InvalidOpcode
3031 parseCVTPS2PI = parseUnimplemented
3032 parseCVTTPS2PI = parseUnimplemented
3033 parseUCOMISS = parseXmmVW UCOMISS InvalidOpcode UCOMISD InvalidOpcode
3034 parseCOMISS = parseXmmVW COMISS InvalidOpcode COMISD InvalidOpcode
3037 opsize <- instrOperandSize
3038 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
3039 return $ Instr (cmovccname (b .&. 0xf)) OPNONE [op2, op1]
3041 parseMOVSKPS = parseXmmGU MOVMSKPS InvalidOpcode MOVMSKPD InvalidOpcode
3043 parseSQRTPS = parseXmmVW SQRTPS SQRTSS SQRTPD SQRTSD
3044 parseRSQRTPS = parseXmmVW RSQRTPS RSQRTSS InvalidOpcode InvalidOpcode
3045 parseRCPPS = parseXmmVW RCPPS RCPSS InvalidOpcode InvalidOpcode
3046 parseCVTPS2PD = parseUnimplemented
3047 parseANDNPS = parseXmmVW ANDNPS InvalidOpcode ANDNPD InvalidOpcode
3048 parseANDPS = parseXmmVW ANDPS InvalidOpcode ANDPD InvalidOpcode
3049 parseORPS = parseXmmVW ORPS InvalidOpcode ORPD InvalidOpcode
3050 parseXORPS = parseXmmVW XORPS InvalidOpcode XORPD InvalidOpcode
3051 parseADDPS = parseXmmVW ADDPS ADDSS ADDPD ADDSD
3052 parseMULPS = parseXmmVW MULPS MULSS MULPD MULSD
3053 parseCVTDQ2PS = parseUnimplemented
3054 parsePUNPCKLWD = parseUnimplemented
3055 parsePACKSSWB = parseUnimplemented
3056 parsePUNPCKHWD = parseUnimplemented
3057 parseSUBPS = parseXmmVW SUBPS SUBSS SUBPD SUBSD
3058 parseMINPS = parseXmmVW MINPS MINSS MINPD MINSD
3059 parseDIVPS = parseXmmVW DIVPS DIVSS DIVPD DIVSD
3060 parseMAXPS = parseXmmVW MAXPS MAXSS MAXPD MAXSD
3061 parsePUNPCKLBW = parseUnimplemented
3062 parsePUNPCKLDQ = parseUnimplemented
3063 parsePACKUSWB = parseUnimplemented
3064 parsePCMPGTB = parseUnimplemented
3065 parsePCMPGTW = parseUnimplemented
3066 parsePCMPGTD = parseUnimplemented
3067 parsePUNPCKHBW = parseUnimplemented
3068 parsePUNPCKHDQ = parseUnimplemented
3069 parsePACKSSDW = parseUnimplemented
3070 parsePUNPCKLQDQ = parseUnimplemented
3071 parsePUNPCKHQDQ = parseUnimplemented
3072 parsePSHUFW = parseUnimplemented
3073 parsePCMPEQB = parseUnimplemented
3074 parsePCMPEQW = parseUnimplemented
3075 parsePCMPEQD = parseUnimplemented
3080 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3081 return $ Instr VMREAD OP64 [op1, op2]
3082 else do (op1, op2, mod, reg, rm) <- parseAddress32 OP32
3083 return $ Instr VMREAD OP32 [op1, op2]
3087 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3088 return $ Instr VMWRITE OP64 [op1, op2]
3089 else do (op1, op2, mod, reg, rm) <- parseAddress32 OP32
3090 return $ Instr VMWRITE OP32 [op1, op2]
3092 parseHADDPS = parseXmmVW InvalidOpcode InvalidOpcode HADDPD HADDPS
3093 parseHSUBPS = parseXmmVW InvalidOpcode InvalidOpcode HSUBPS HSUBPD
3095 parseMOVD_Q = parseUnimplemented
3100 disp' = fromIntegral disp
3103 return $ Instr (jccname (b .&. 0xf)) OPNONE
3104 [OpAddr (fromIntegral (disp' + sourceColumn pos - 1) +
3105 (startAddr st)) OPNONE]
3108 (op1, op2, mod, reg, rm) <- parseAddress32 OP8
3110 OpReg name num -> return $ Instr (setccname (b .&. 0xf)) OPNONE
3111 [OpReg (regnames8 !! fromIntegral num) num]
3112 _ -> return $ Instr (setccname (b .&. 0xf)) OPNONE [op1]
3115 do opsize <- instrOperandSize
3116 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
3118 opsize <- instrOperandSize
3119 return $ Instr SHLD opsize [op1, op2, OpImm (fromIntegral b)]
3121 do opsize <- instrOperandSize
3122 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
3123 opsize <- instrOperandSize
3124 return $ Instr SHLD opsize [op1, op2, OpReg "cl" 1]
3126 do opsize <- instrOperandSize
3127 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
3129 opsize <- instrOperandSize
3130 return $ Instr SHRD opsize [op1, op2, OpImm (fromIntegral b)]
3132 do opsize <- instrOperandSize
3133 (op1, op2, mod, reg, rm) <- parseAddress32 opsize
3134 opsize <- instrOperandSize
3135 return $ Instr SHRD opsize [op1, op2, OpReg "cl" 1]
3137 parseCMPPS = parseUnimplemented
3138 parseMOVNTI = parseUnimplemented
3139 parsePINSRW = parseUnimplemented
3140 parsePEXTRW = parseUnimplemented
3141 parseSHUFPS = parseUnimplemented
3144 do let reg = (b .&. 0xf) - 8
3145 r <- registerName (fromIntegral reg)
3146 opsize <- instrOperandSize
3147 return $ Instr BSWAP opsize [OpReg r (fromIntegral reg)]
3149 parseADDSUBPS = parseXmmVW InvalidOpcode InvalidOpcode ADDSUBPD ADDUBPS
3151 parseMmxXmmPQVW opcode b =
3153 if hasPrefix 0x66 st
3154 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128
3155 let v = OpReg (xmmregs !! (fromIntegral reg))
3158 OpReg _ num -> OpReg (xmmregs !! num) num
3160 return $ Instr opcode OP128 [v, w]
3161 else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3162 let p = OpReg (mmxregs !! (fromIntegral reg))
3165 OpReg _ num -> OpReg (mmxregs !! num) num
3167 return $ Instr opcode OP128 [p, q]
3169 parseMmxXmmMPMV opcode1 opcode2 b =
3171 if hasPrefix 0x66 st
3172 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128
3173 let v = OpReg (xmmregs !! (fromIntegral reg))
3175 return $ Instr opcode2 OP128 [op1, v]
3176 else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3177 let p = OpReg (mmxregs !! (fromIntegral reg))
3179 return $ Instr opcode1 OP128 [op1, p]
3181 parseMmxXmmPNVU opcode b =
3183 if hasPrefix 0x66 st
3184 then do (mod, reg, rm) <- parseModRM
3185 let v = OpReg (xmmregs !! (fromIntegral reg))
3187 let u = OpReg (xmmregs !! (fromIntegral rm))
3189 return $ Instr opcode OP128 [v, u]
3190 else do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3191 let p = OpReg (mmxregs !! (fromIntegral reg))
3193 let n = OpReg (mmxregs !! (fromIntegral rm))
3195 return $ Instr opcode OP128 [p, n]
3197 parsePSRLW = parseMmxXmmPQVW PSRLW
3198 parsePSRLD = parseMmxXmmPQVW PSRLD
3199 parsePSRLQ = parseMmxXmmPQVW PSRLQ
3200 parsePADDQ = parseMmxXmmPQVW PADDQ
3201 parsePMULLW = parseMmxXmmPQVW PMULLW
3202 parseMOVQ b@0x6f = parseUnimplemented b
3203 parseMOVQ b@0x7f = parseUnimplemented b
3206 if hasPrefix 0x66 st
3207 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP64
3208 return $ Instr MOVQ OP64 [op1, op2]
3209 else if hasPrefix 0xf3 st
3210 then do (mod, reg, rm) <- parseModRM
3211 return $ Instr MOVQ OPNONE
3212 [OpReg (xmmregs !! (fromIntegral reg))
3214 OpReg (mmxregs !! (fromIntegral rm))
3217 if hasPrefix 0xf2 st
3218 then do (mod, reg, rm) <- parseModRM
3219 return $ Instr MOVQ OPNONE
3220 [OpReg (mmxregs !! (fromIntegral reg))
3222 OpReg (xmmregs !! (fromIntegral rm))
3224 else parseInvalidOpcode b
3228 (mod, reg, rm) <- parseModRM
3229 if hasPrefix 0x66 st
3230 then do return $ Instr PMOVMSKB OPNONE
3231 [OpReg (regnames32 !! (fromIntegral reg))
3233 OpReg (xmmregs !! (fromIntegral rm))
3235 else do return $ Instr PMOVMSKB OPNONE
3236 [OpReg (regnames32 !! (fromIntegral reg))
3238 OpReg (mmxregs !! (fromIntegral rm))
3240 parsePSUBUSB = parseMmxXmmPQVW PSUBUSB
3241 parsePSUBUSW = parseMmxXmmPQVW PSUBUSW
3242 parsePMINUB = parseMmxXmmPQVW PMINUB
3243 parsePAND = parseMmxXmmPQVW PAND
3244 parsePADDUSB = parseMmxXmmPQVW PADDUSB
3245 parsePADDUSW = parseMmxXmmPQVW PADDUSW
3246 parsePMAXUB = parseMmxXmmPQVW PMAXUB
3247 parsePANDN = parseMmxXmmPQVW PANDN
3248 parsePAVGB = parseMmxXmmPQVW PAVGB
3249 parsePSRAW = parseMmxXmmPQVW PSRAW
3250 parsePSRAD = parseMmxXmmPQVW PSRAD
3251 parsePAVGW = parseMmxXmmPQVW PAVGW
3252 parseCVTPD2DQ = parseUnimplemented
3253 parsePMULHUW = parseMmxXmmPQVW PMULHUW
3254 parsePMULHW = parseMmxXmmPQVW PMULHW
3255 parseMOVNTQ = parseMmxXmmMPMV MOVNTQ MOVNTDQ
3256 parsePSUBSB = parseMmxXmmPQVW PSUBSB
3257 parsePSUBSQ = parseMmxXmmPQVW PSUBSQ
3258 parsePMINSW = parseMmxXmmPQVW PMINSW
3259 parsePOR = parseMmxXmmPQVW POR
3260 parsePADDSB = parseMmxXmmPQVW PADDSB
3261 parsePADDSW = parseMmxXmmPQVW PADDSW
3262 parsePMAXSW = parseMmxXmmPQVW PMAXSW
3263 parsePXOR = parseMmxXmmPQVW PXOR
3266 if hasPrefix 0xf2 st
3267 then do (op1, op2, mod, reg, rm) <- parseAddress32 OP128
3268 let v = OpReg (xmmregs !! (fromIntegral reg))
3270 return $ Instr LDDQU OP128 [v, op1]
3271 else parseInvalidOpcode b
3272 parsePSLLW = parseMmxXmmPQVW PSLLW
3273 parsePSLLD = parseMmxXmmPQVW PSLLD
3274 parsePSLLQ = parseMmxXmmPQVW PSLLQ
3275 parsePMULUDQ = parseMmxXmmPQVW PMULUDQ
3276 parsePMADDWD = parseMmxXmmPQVW PMADDWD
3277 parsePSADBW = parseMmxXmmPQVW PSADBW
3278 parseMASKMOVQ = parseMmxXmmPNVU MASKMOVQ
3279 parsePSUBB = parseMmxXmmPQVW PSUBB
3280 parsePSUBW = parseMmxXmmPQVW PSUBW
3281 parsePSUBD = parseMmxXmmPQVW PSUBD
3282 parsePSUBQ = parseMmxXmmPQVW PSUBQ
3283 parsePADDB = parseMmxXmmPQVW PADDB
3284 parsePADDW = parseMmxXmmPQVW PADDW
3285 parsePADDD = parseMmxXmmPQVW PADDD