metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- metadata +255 -0
@@ -0,0 +1,872 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'metasm/ia32/main'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class Ia32
|
11
|
+
def init_cpu_constants
|
12
|
+
@opcode_list ||= []
|
13
|
+
@fields_mask.update :w => 1, :s => 1, :d => 1, :modrm => 0xc7,
|
14
|
+
:reg => 7, :eeec => 7, :eeed => 7, :seg2 => 3, :seg3 => 7,
|
15
|
+
:regfp => 7, :regmmx => 7, :regxmm => 7
|
16
|
+
@fields_mask[:seg2A] = @fields_mask[:seg2]
|
17
|
+
@fields_mask[:seg3A] = @fields_mask[:seg3]
|
18
|
+
@fields_mask[:modrmA] = @fields_mask[:modrm]
|
19
|
+
|
20
|
+
@valid_args.concat [:i, :i8, :u8, :u16, :reg, :seg2, :seg2A,
|
21
|
+
:seg3, :seg3A, :eeec, :eeed, :modrm, :modrmA, :mrm_imm,
|
22
|
+
:farptr, :imm_val1, :imm_val3, :reg_cl, :reg_eax,
|
23
|
+
:reg_dx, :regfp, :regfp0, :modrmmmx, :regmmx,
|
24
|
+
:modrmxmm, :regxmm] - @valid_args
|
25
|
+
|
26
|
+
@valid_props.concat [:strop, :stropz, :opsz, :argsz, :setip,
|
27
|
+
:stopexec, :saveip, :unsigned_imm, :random, :needpfx,
|
28
|
+
:xmmx] - @valid_props
|
29
|
+
end
|
30
|
+
|
31
|
+
# only most common instructions from the 386 instruction set
|
32
|
+
# inexhaustive list :
|
33
|
+
# no aaa, arpl, mov crX, call/jmp/ret far, in/out, bts, xchg...
|
34
|
+
def init_386_common_only
|
35
|
+
init_cpu_constants
|
36
|
+
|
37
|
+
addop_macro1 'adc', 2
|
38
|
+
addop_macro1 'add', 0
|
39
|
+
addop_macro1 'and', 4, :u
|
40
|
+
addop 'bswap', [0x0F, 0xC8], :reg
|
41
|
+
addop 'call', [0xE8], nil, {}, :stopexec, :setip, :i, :saveip
|
42
|
+
addop 'call', [0xFF], 2, {}, :stopexec, :setip, :saveip
|
43
|
+
addop('cbw', [0x98]) { |o| o.props[:opsz] = 16 }
|
44
|
+
addop('cwde', [0x98]) { |o| o.props[:opsz] = 32 }
|
45
|
+
addop('cdqe', [0x98]) { |o| o.props[:opsz] = 64 }
|
46
|
+
addop('cwd', [0x99]) { |o| o.props[:opsz] = 16 }
|
47
|
+
addop('cdq', [0x99]) { |o| o.props[:opsz] = 32 }
|
48
|
+
addop('cqo', [0x99]) { |o| o.props[:opsz] = 64 }
|
49
|
+
addop_macro1 'cmp', 7
|
50
|
+
addop_macrostr 'cmps', [0xA6], :stropz
|
51
|
+
addop 'dec', [0x48], :reg
|
52
|
+
addop 'dec', [0xFE], 1, {:w => [0, 0]}
|
53
|
+
addop 'div', [0xF6], 6, {:w => [0, 0]}
|
54
|
+
addop 'enter', [0xC8], nil, {}, :u16, :u8
|
55
|
+
addop 'idiv', [0xF6], 7, {:w => [0, 0]}
|
56
|
+
addop 'imul', [0xF6], 5, {:w => [0, 0]}, :reg_eax
|
57
|
+
addop 'imul', [0x0F, 0xAF], :mrm
|
58
|
+
addop 'imul', [0x69], :mrm, {:s => [0, 1]}, :i
|
59
|
+
addop 'inc', [0x40], :reg
|
60
|
+
addop 'inc', [0xFE], 0, {:w => [0, 0]}
|
61
|
+
addop 'int', [0xCC], nil, {}, :imm_val3, :stopexec
|
62
|
+
addop 'int', [0xCD], nil, {}, :u8
|
63
|
+
addop_macrotttn 'j', [0x70], nil, {}, :setip, :i8
|
64
|
+
addop_macrotttn 'j', [0x0F, 0x80], nil, {}, :setip, :i
|
65
|
+
addop 'jmp', [0xE9], nil, {:s => [0, 1]}, :setip, :i, :stopexec
|
66
|
+
addop 'jmp', [0xFF], 4, {}, :setip, :stopexec
|
67
|
+
addop 'lea', [0x8D], :mrmA
|
68
|
+
addop 'leave', [0xC9]
|
69
|
+
addop_macrostr 'lods', [0xAC], :strop
|
70
|
+
addop 'loop', [0xE2], nil, {}, :setip, :i8
|
71
|
+
addop 'loopz', [0xE1], nil, {}, :setip, :i8
|
72
|
+
addop 'loope', [0xE1], nil, {}, :setip, :i8
|
73
|
+
addop 'loopnz',[0xE0], nil, {}, :setip, :i8
|
74
|
+
addop 'loopne',[0xE0], nil, {}, :setip, :i8
|
75
|
+
addop 'mov', [0xA0], nil, {:w => [0, 0], :d => [0, 1]}, :mrm_imm, :reg_eax
|
76
|
+
addop 'mov', [0x88], :mrmw,{:d => [0, 1]}
|
77
|
+
addop 'mov', [0xB0], :reg, {:w => [0, 3]}, :u
|
78
|
+
addop 'mov', [0xC6], 0, {:w => [0, 0]}, :u
|
79
|
+
addop_macrostr 'movs', [0xA4], :strop
|
80
|
+
addop 'movsx', [0x0F, 0xBE], :mrmw
|
81
|
+
addop 'movzx', [0x0F, 0xB6], :mrmw
|
82
|
+
addop 'mul', [0xF6], 4, {:w => [0, 0]}
|
83
|
+
addop 'neg', [0xF6], 3, {:w => [0, 0]}
|
84
|
+
addop 'nop', [0x90]
|
85
|
+
addop 'not', [0xF6], 2, {:w => [0, 0]}
|
86
|
+
addop_macro1 'or', 1, :u
|
87
|
+
addop 'pop', [0x58], :reg
|
88
|
+
addop 'pop', [0x8F], 0
|
89
|
+
addop 'push', [0x50], :reg
|
90
|
+
addop 'push', [0xFF], 6
|
91
|
+
addop 'push', [0x68], nil, {:s => [0, 1]}, :u
|
92
|
+
addop 'ret', [0xC3], nil, {}, :stopexec, :setip
|
93
|
+
addop 'ret', [0xC2], nil, {}, :stopexec, :u16, :setip
|
94
|
+
addop_macro3 'rol', 0
|
95
|
+
addop_macro3 'ror', 1
|
96
|
+
addop_macro3 'sar', 7
|
97
|
+
addop_macro1 'sbb', 3
|
98
|
+
addop_macrostr 'scas', [0xAE], :stropz
|
99
|
+
addop_macrotttn('set', [0x0F, 0x90], 0) { |o| o.props[:argsz] = 8 }
|
100
|
+
addop_macrotttn('set', [0x0F, 0x90], :mrm) { |o| o.props[:argsz] = 8 ; o.args.reverse! } # :reg field is unused
|
101
|
+
addop_macro3 'shl', 4
|
102
|
+
addop_macro3 'sal', 6
|
103
|
+
addop 'shld', [0x0F, 0xA4], :mrm, {}, :u8
|
104
|
+
addop 'shld', [0x0F, 0xA5], :mrm, {}, :reg_cl
|
105
|
+
addop_macro3 'shr', 5
|
106
|
+
addop 'shrd', [0x0F, 0xAC], :mrm, {}, :u8
|
107
|
+
addop 'shrd', [0x0F, 0xAD], :mrm, {}, :reg_cl
|
108
|
+
addop_macrostr 'stos', [0xAA], :strop
|
109
|
+
addop_macro1 'sub', 5
|
110
|
+
addop 'test', [0x84], :mrmw
|
111
|
+
addop 'test', [0xA8], nil, {:w => [0, 0]}, :reg_eax, :u
|
112
|
+
addop 'test', [0xF6], 0, {:w => [0, 0]}, :u
|
113
|
+
addop 'xchg', [0x90], :reg, {}, :reg_eax
|
114
|
+
addop('xchg', [0x90], :reg, {}, :reg_eax) { |o| o.args.reverse! } # xchg eax, ebx == xchg ebx, eax)
|
115
|
+
addop 'xchg', [0x86], :mrmw
|
116
|
+
addop('xchg', [0x86], :mrmw) { |o| o.args.reverse! }
|
117
|
+
addop_macro1 'xor', 6, :u
|
118
|
+
end
|
119
|
+
|
120
|
+
def init_386_only
|
121
|
+
init_cpu_constants
|
122
|
+
|
123
|
+
addop 'aaa', [0x37]
|
124
|
+
addop 'aad', [0xD5, 0x0A]
|
125
|
+
addop 'aam', [0xD4, 0x0A]
|
126
|
+
addop 'aas', [0x3F]
|
127
|
+
addop('arpl', [0x63], :mrm) { |o| o.props[:argsz] = 16 ; o.args.reverse! }
|
128
|
+
addop 'bound', [0x62], :mrmA
|
129
|
+
addop 'bsf', [0x0F, 0xBC], :mrm
|
130
|
+
addop 'bsr', [0x0F, 0xBD], :mrm
|
131
|
+
addop_macro2 'bt' , 0
|
132
|
+
addop_macro2 'btc', 3
|
133
|
+
addop_macro2 'btr', 2
|
134
|
+
addop_macro2 'bts', 1
|
135
|
+
addop 'call', [0x9A], nil, {}, :stopexec, :setip, :farptr, :saveip
|
136
|
+
addop 'callf', [0x9A], nil, {}, :stopexec, :setip, :farptr, :saveip
|
137
|
+
addop 'callf', [0xFF], 3, {}, :stopexec, :setip, :saveip
|
138
|
+
addop 'clc', [0xF8]
|
139
|
+
addop 'cld', [0xFC]
|
140
|
+
addop 'cli', [0xFA]
|
141
|
+
addop 'clts', [0x0F, 0x06]
|
142
|
+
addop 'cmc', [0xF5]
|
143
|
+
addop('cmpxchg',[0x0F, 0xB0], :mrmw) { |o| o.args.reverse! }
|
144
|
+
addop 'cpuid', [0x0F, 0xA2]
|
145
|
+
addop 'daa', [0x27]
|
146
|
+
addop 'das', [0x2F]
|
147
|
+
addop 'hlt', [0xF4], nil, {}, :stopexec
|
148
|
+
addop 'in', [0xE4], nil, {:w => [0, 0]}, :reg_eax, :u8
|
149
|
+
addop 'in', [0xE4], nil, {:w => [0, 0]}, :u8
|
150
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}, :reg_eax, :reg_dx
|
151
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}, :reg_eax
|
152
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}
|
153
|
+
addop_macrostr 'ins', [0x6C], :strop
|
154
|
+
addop 'into', [0xCE]
|
155
|
+
addop 'invd', [0x0F, 0x08]
|
156
|
+
addop 'invlpg',[0x0F, 0x01, 7<<3], :modrmA
|
157
|
+
addop 'iret', [0xCF], nil, {}, :stopexec, :setip
|
158
|
+
addop 'iretd', [0xCF], nil, {}, :stopexec, :setip
|
159
|
+
addop('jcxz', [0xE3], nil, {}, :setip, :i8) { |o| o.props[:opsz] = 16 }
|
160
|
+
addop('jecxz', [0xE3], nil, {}, :setip, :i8) { |o| o.props[:opsz] = 32 }
|
161
|
+
addop 'jmp', [0xEA], nil, {}, :farptr, :setip, :stopexec
|
162
|
+
addop 'jmpf', [0xEA], nil, {}, :farptr, :setip, :stopexec
|
163
|
+
addop 'jmpf', [0xFF], 5, {}, :stopexec, :setip # reg ?
|
164
|
+
addop 'lahf', [0x9F]
|
165
|
+
addop 'lar', [0x0F, 0x02], :mrm
|
166
|
+
addop 'lds', [0xC5], :mrmA
|
167
|
+
addop 'les', [0xC4], :mrmA
|
168
|
+
addop 'lfs', [0x0F, 0xB4], :mrmA
|
169
|
+
addop 'lgs', [0x0F, 0xB5], :mrmA
|
170
|
+
addop 'lgdt', [0x0F, 0x01], 2
|
171
|
+
addop 'lidt', [0x0F, 0x01, 3<<3], :modrmA
|
172
|
+
addop 'lldt', [0x0F, 0x00], 2
|
173
|
+
addop 'lmsw', [0x0F, 0x01], 6
|
174
|
+
# prefix addop 'lock', [0xF0]
|
175
|
+
addop 'lsl', [0x0F, 0x03], :mrm
|
176
|
+
addop 'lss', [0x0F, 0xB2], :mrmA
|
177
|
+
addop 'ltr', [0x0F, 0x00], 3
|
178
|
+
addop('mov', [0x0F, 0x20, 0xC0], :reg, {:d => [1, 1], :eeec => [2, 3]}, :eeec) { |op| op.args.reverse! }
|
179
|
+
addop('mov', [0x0F, 0x21, 0xC0], :reg, {:d => [1, 1], :eeed => [2, 3]}, :eeed) { |op| op.args.reverse! }
|
180
|
+
addop('mov', [0x8C], 0, {:d => [0, 1], :seg3 => [1, 3]}, :seg3) { |op| op.args.reverse! }
|
181
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :u8, :reg_eax
|
182
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :reg_eax, :u8
|
183
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :u8
|
184
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_dx, :reg_eax
|
185
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_eax, :reg_dx
|
186
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_eax # implicit arguments
|
187
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}
|
188
|
+
addop_macrostr 'outs', [0x6E], :strop
|
189
|
+
addop 'pop', [0x07], nil, {:seg2A => [0, 3]}, :seg2A
|
190
|
+
addop 'pop', [0x0F, 0x81], nil, {:seg3A => [1, 3]}, :seg3A
|
191
|
+
addop('popa', [0x61]) { |o| o.props[:opsz] = 16 }
|
192
|
+
addop('popad', [0x61]) { |o| o.props[:opsz] = 32 }
|
193
|
+
addop('popf', [0x9D]) { |o| o.props[:opsz] = 16 }
|
194
|
+
addop('popfd', [0x9D]) { |o| o.props[:opsz] = 32 }
|
195
|
+
addop 'push', [0x06], nil, {:seg2 => [0, 3]}, :seg2
|
196
|
+
addop 'push', [0x0F, 0x80], nil, {:seg3A => [1, 3]}, :seg3A
|
197
|
+
addop('pusha', [0x60]) { |o| o.props[:opsz] = 16 }
|
198
|
+
addop('pushad',[0x60]) { |o| o.props[:opsz] = 32 }
|
199
|
+
addop('pushf', [0x9C]) { |o| o.props[:opsz] = 16 }
|
200
|
+
addop('pushfd',[0x9C]) { |o| o.props[:opsz] = 32 }
|
201
|
+
addop_macro3 'rcl', 2
|
202
|
+
addop_macro3 'rcr', 3
|
203
|
+
addop 'rdmsr', [0x0F, 0x32]
|
204
|
+
addop 'rdpmc', [0x0F, 0x33]
|
205
|
+
addop 'rdtsc', [0x0F, 0x31], nil, {}, :random
|
206
|
+
addop 'retf', [0xCB], nil, {}, :stopexec, :setip
|
207
|
+
addop 'retf', [0xCA], nil, {}, :stopexec, :u16, :setip
|
208
|
+
addop 'rsm', [0x0F, 0xAA], nil, {}, :stopexec
|
209
|
+
addop 'sahf', [0x9E]
|
210
|
+
addop 'sgdt', [0x0F, 0x01, 0<<3], :modrmA
|
211
|
+
addop 'sidt', [0x0F, 0x01, 1<<3], :modrmA
|
212
|
+
addop 'sldt', [0x0F, 0x00], 0
|
213
|
+
addop 'smsw', [0x0F, 0x01], 4
|
214
|
+
addop 'stc', [0xF9]
|
215
|
+
addop 'std', [0xFD]
|
216
|
+
addop 'sti', [0xFB]
|
217
|
+
addop 'str', [0x0F, 0x00], 1
|
218
|
+
addop 'ud2', [0x0F, 0x0B]
|
219
|
+
addop 'verr', [0x0F, 0x00], 4
|
220
|
+
addop 'verw', [0x0F, 0x00], 5
|
221
|
+
addop 'wait', [0x9B]
|
222
|
+
addop 'wbinvd',[0x0F, 0x09]
|
223
|
+
addop 'wrmsr', [0x0F, 0x30]
|
224
|
+
addop('xadd', [0x0F, 0xC0], :mrmw) { |o| o.args.reverse! }
|
225
|
+
addop 'xlat', [0xD7]
|
226
|
+
|
227
|
+
# pfx: addrsz = 0x67, lock = 0xf0, opsz = 0x66, repnz = 0xf2, rep/repz = 0xf3
|
228
|
+
# cs/nojmp = 0x2E, ds/jmp = 0x3E, es = 0x26, fs = 0x64, gs = 0x65, ss = 0x36
|
229
|
+
# undocumented opcodes
|
230
|
+
# TODO put these in the right place (486/P6/...)
|
231
|
+
addop 'aam', [0xD4], nil, {}, :u8
|
232
|
+
addop 'aad', [0xD5], nil, {}, :u8
|
233
|
+
addop 'setalc', [0xD6]
|
234
|
+
addop 'salc', [0xD6]
|
235
|
+
addop 'icebp', [0xF1]
|
236
|
+
#addop 'loadall',[0x0F, 0x07] # conflict with syscall
|
237
|
+
addop 'ud2', [0x0F, 0xB9]
|
238
|
+
addop 'umov', [0x0F, 0x10], :mrmw,{:d => [1, 1]}
|
239
|
+
end
|
240
|
+
|
241
|
+
def init_387_only
|
242
|
+
init_cpu_constants
|
243
|
+
|
244
|
+
addop 'f2xm1', [0xD9, 0xF0]
|
245
|
+
addop 'fabs', [0xD9, 0xE1]
|
246
|
+
addop_macrofpu1 'fadd', 0
|
247
|
+
addop 'faddp', [0xDE, 0xC0], :regfp
|
248
|
+
addop 'faddp', [0xDE, 0xC1]
|
249
|
+
addop('fbld', [0xDF, 4<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 80 }
|
250
|
+
addop('fbstp', [0xDF, 6<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 80 }
|
251
|
+
addop 'fchs', [0xD9, 0xE0], nil, {}, :regfp0
|
252
|
+
addop 'fnclex', [0xDB, 0xE2]
|
253
|
+
addop_macrofpu1 'fcom', 2
|
254
|
+
addop_macrofpu1 'fcomp', 3
|
255
|
+
addop 'fcompp',[0xDE, 0xD9]
|
256
|
+
addop 'fcomip',[0xDF, 0xF0], :regfp
|
257
|
+
addop 'fcos', [0xD9, 0xFF], nil, {}, :regfp0
|
258
|
+
addop 'fdecstp', [0xD9, 0xF6]
|
259
|
+
addop_macrofpu1 'fdiv', 6
|
260
|
+
addop_macrofpu1 'fdivr', 7
|
261
|
+
addop 'fdivp', [0xDE, 0xF8], :regfp
|
262
|
+
addop 'fdivp', [0xDE, 0xF9]
|
263
|
+
addop 'fdivrp',[0xDE, 0xF0], :regfp
|
264
|
+
addop 'fdivrp',[0xDE, 0xF1]
|
265
|
+
addop 'ffree', [0xDD, 0xC0], nil, {:regfp => [1, 0]}, :regfp
|
266
|
+
addop_macrofpu2 'fiadd', 0
|
267
|
+
addop_macrofpu2 'fimul', 1
|
268
|
+
addop_macrofpu2 'ficom', 2
|
269
|
+
addop_macrofpu2 'ficomp',3
|
270
|
+
addop_macrofpu2 'fisub', 4
|
271
|
+
addop_macrofpu2 'fisubr',5
|
272
|
+
addop_macrofpu2 'fidiv', 6
|
273
|
+
addop_macrofpu2 'fidivr',7
|
274
|
+
addop 'fincstp', [0xD9, 0xF7]
|
275
|
+
addop 'fninit', [0xDB, 0xE3]
|
276
|
+
addop_macrofpu2 'fist', 2, 1
|
277
|
+
addop_macrofpu3 'fild', 0
|
278
|
+
addop_macrofpu3 'fistp',3
|
279
|
+
addop('fld', [0xD9, 0<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 32 }
|
280
|
+
addop('fld', [0xDD, 0<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 64 }
|
281
|
+
addop('fld', [0xDB, 5<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 80 }
|
282
|
+
addop 'fld', [0xD9, 0xC0], :regfp
|
283
|
+
|
284
|
+
addop('fldcw', [0xD9, 5<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
285
|
+
addop 'fldenv', [0xD9, 4<<3], :modrmA
|
286
|
+
addop 'fld1', [0xD9, 0xE8]
|
287
|
+
addop 'fldl2t', [0xD9, 0xE9]
|
288
|
+
addop 'fldl2e', [0xD9, 0xEA]
|
289
|
+
addop 'fldpi', [0xD9, 0xEB]
|
290
|
+
addop 'fldlg2', [0xD9, 0xEC]
|
291
|
+
addop 'fldln2', [0xD9, 0xED]
|
292
|
+
addop 'fldz', [0xD9, 0xEE]
|
293
|
+
addop_macrofpu1 'fmul', 1
|
294
|
+
addop 'fmulp', [0xDE, 0xC8], :regfp
|
295
|
+
addop 'fmulp', [0xDE, 0xC9]
|
296
|
+
addop 'fnop', [0xD9, 0xD0]
|
297
|
+
addop 'fpatan', [0xD9, 0xF3]
|
298
|
+
addop 'fprem', [0xD9, 0xF8]
|
299
|
+
addop 'fprem1', [0xD9, 0xF5]
|
300
|
+
addop 'fptan', [0xD9, 0xF2]
|
301
|
+
addop 'frndint',[0xD9, 0xFC]
|
302
|
+
addop 'frstor', [0xDD, 4<<3], :modrmA
|
303
|
+
addop 'fnsave', [0xDD, 6<<3], :modrmA
|
304
|
+
addop('fnstcw', [0xD9, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
305
|
+
addop 'fnstenv',[0xD9, 6<<3], :modrmA
|
306
|
+
addop 'fnstsw', [0xDF, 0xE0]
|
307
|
+
addop('fnstsw', [0xDD, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
308
|
+
addop 'fscale', [0xD9, 0xFD]
|
309
|
+
addop 'fsin', [0xD9, 0xFE]
|
310
|
+
addop 'fsincos',[0xD9, 0xFB]
|
311
|
+
addop 'fsqrt', [0xD9, 0xFA]
|
312
|
+
addop('fst', [0xD9, 2<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 32 }
|
313
|
+
addop('fst', [0xDD, 2<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 64 }
|
314
|
+
addop 'fst', [0xD9, 0xD0], :regfp
|
315
|
+
addop('fstp', [0xD9, 3<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 32 }
|
316
|
+
addop('fstp', [0xDD, 3<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 64 }
|
317
|
+
addop('fstp', [0xDB, 7<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 80 }
|
318
|
+
addop 'fstp', [0xDD, 0xD8], :regfp
|
319
|
+
addop_macrofpu1 'fsub', 4
|
320
|
+
addop 'fsubp', [0xDE, 0xE8], :regfp
|
321
|
+
addop 'fsubp', [0xDE, 0xE9]
|
322
|
+
addop_macrofpu1 'fsubp', 5
|
323
|
+
addop 'fsubrp', [0xDE, 0xE0], :regfp
|
324
|
+
addop 'fsubrp', [0xDE, 0xE1]
|
325
|
+
addop 'ftst', [0xD9, 0xE4]
|
326
|
+
addop 'fucom', [0xDD, 0xE0], :regfp
|
327
|
+
addop 'fucomp', [0xDD, 0xE8], :regfp
|
328
|
+
addop 'fucompp',[0xDA, 0xE9]
|
329
|
+
addop 'fucomi', [0xDB, 0xE8], :regfp
|
330
|
+
addop 'fxam', [0xD9, 0xE5]
|
331
|
+
addop 'fxch', [0xD9, 0xC8], :regfp
|
332
|
+
addop 'fxtract',[0xD9, 0xF4]
|
333
|
+
addop 'fyl2x', [0xD9, 0xF1]
|
334
|
+
addop 'fyl2xp1',[0xD9, 0xF9]
|
335
|
+
# fwait prefix
|
336
|
+
addop 'fclex', [0x9B, 0xDB, 0xE2]
|
337
|
+
addop 'finit', [0x9B, 0xDB, 0xE3]
|
338
|
+
addop 'fsave', [0x9B, 0xDD, 6<<3], :modrmA
|
339
|
+
addop('fstcw', [0x9B, 0xD9, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
340
|
+
addop 'fstenv', [0x9B, 0xD9, 6<<3], :modrmA
|
341
|
+
addop 'fstsw', [0x9B, 0xDF, 0xE0]
|
342
|
+
addop('fstsw', [0x9B, 0xDD, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
343
|
+
addop 'fwait', [0x9B]
|
344
|
+
end
|
345
|
+
|
346
|
+
def init_486_only
|
347
|
+
init_cpu_constants
|
348
|
+
# TODO add new segments (fs/gs) ?
|
349
|
+
end
|
350
|
+
|
351
|
+
def init_pentium_only
|
352
|
+
init_cpu_constants
|
353
|
+
|
354
|
+
addop 'cmpxchg8b', [0x0F, 0xC7], 1
|
355
|
+
# lock cmpxchg8b eax
|
356
|
+
#addop 'f00fbug', [0xF0, 0x0F, 0xC7, 0xC8]
|
357
|
+
|
358
|
+
# mmx
|
359
|
+
addop 'emms', [0x0F, 0x77]
|
360
|
+
addop('movd', [0x0F, 0x6E], :mrmmmx, {:d => [1, 4]}) { |o| o.args[o.args.index(:modrmmmx)] = :modrm ; o.args.reverse! }
|
361
|
+
addop('movq', [0x0F, 0x6F], :mrmmmx, {:d => [1, 4]}) { |o| o.args.reverse! }
|
362
|
+
addop 'packssdw', [0x0F, 0x6B], :mrmmmx
|
363
|
+
addop 'packsswb', [0x0F, 0x63], :mrmmmx
|
364
|
+
addop 'packuswb', [0x0F, 0x67], :mrmmmx
|
365
|
+
addop_macrogg 0..2, 'padd', [0x0F, 0xFC], :mrmmmx
|
366
|
+
addop_macrogg 0..1, 'padds', [0x0F, 0xEC], :mrmmmx
|
367
|
+
addop_macrogg 0..1, 'paddus',[0x0F, 0xDC], :mrmmmx
|
368
|
+
addop 'pand', [0x0F, 0xDB], :mrmmmx
|
369
|
+
addop 'pandn', [0x0F, 0xDF], :mrmmmx
|
370
|
+
addop_macrogg 0..2, 'pcmpeq',[0x0F, 0x74], :mrmmmx
|
371
|
+
addop_macrogg 0..2, 'pcmpgt',[0x0F, 0x64], :mrmmmx
|
372
|
+
addop 'pmaddwd', [0x0F, 0xF5], :mrmmmx
|
373
|
+
addop 'pmulhuw', [0x0F, 0xE4], :mrmmmx
|
374
|
+
addop 'pmulhw',[0x0F, 0xE5], :mrmmmx
|
375
|
+
addop 'pmullw',[0x0F, 0xD5], :mrmmmx
|
376
|
+
addop 'por', [0x0F, 0xEB], :mrmmmx
|
377
|
+
addop_macrommx 1..3, 'psll', 3
|
378
|
+
addop_macrommx 1..2, 'psra', 2
|
379
|
+
addop_macrommx 1..3, 'psrl', 1
|
380
|
+
addop_macrogg 0..2, 'psub', [0x0F, 0xF8], :mrmmmx
|
381
|
+
addop_macrogg 0..1, 'psubs', [0x0F, 0xE8], :mrmmmx
|
382
|
+
addop_macrogg 0..1, 'psubus',[0x0F, 0xD8], :mrmmmx
|
383
|
+
addop_macrogg 1..3, 'punchkh', [0x0F, 0x68], :mrmmmx
|
384
|
+
addop_macrogg 1..3, 'punpckl', [0x0F, 0x60], :mrmmmx
|
385
|
+
addop 'pxor', [0x0F, 0xEF], :mrmmmx
|
386
|
+
end
|
387
|
+
|
388
|
+
def init_p6_only
|
389
|
+
addop_macrotttn 'cmov', [0x0F, 0x40], :mrm
|
390
|
+
|
391
|
+
%w{b e be u}.each_with_index { |tt, i|
|
392
|
+
addop 'fcmov' + tt, [0xDA, 0xC0 | (i << 3)], :regfp
|
393
|
+
addop 'fcmovn'+ tt, [0xDB, 0xC0 | (i << 3)], :regfp
|
394
|
+
}
|
395
|
+
addop 'fcomi', [0xDB, 0xF0], :regfp
|
396
|
+
addop('fxrstor', [0x0F, 0xAE, 1<<3], :modrmA) { |o| o.props[:argsz] = 512*8 }
|
397
|
+
addop('fxsave', [0x0F, 0xAE, 0<<3], :modrmA) { |o| o.props[:argsz] = 512*8 }
|
398
|
+
addop 'sysenter',[0x0F, 0x34]
|
399
|
+
addop 'sysexit', [0x0F, 0x35]
|
400
|
+
|
401
|
+
addop 'syscall', [0x0F, 0x05] # AMD
|
402
|
+
addop 'sysret', [0x0F, 0x07] # AMD
|
403
|
+
end
|
404
|
+
|
405
|
+
def init_3dnow_only
|
406
|
+
init_cpu_constants
|
407
|
+
|
408
|
+
[['pavgusb', 0xBF], ['pfadd', 0x9E], ['pfsub', 0x9A],
|
409
|
+
['pfsubr', 0xAA], ['pfacc', 0xAE], ['pfcmpge', 0x90],
|
410
|
+
['pfcmpgt', 0xA0], ['fpcmpeq', 0xB0], ['pfmin', 0x94],
|
411
|
+
['pfmax', 0xA4], ['pi2fd', 0x0D], ['pf2id', 0x1D],
|
412
|
+
['pfrcp', 0x96], ['pfrsqrt', 0x97], ['pfmul', 0xB4],
|
413
|
+
['pfrcpit1', 0xA6], ['pfrsqit1', 0xA7], ['pfrcpit2', 0xB6],
|
414
|
+
['pmulhrw', 0xB7]].each { |str, bin|
|
415
|
+
addop str, [0x0F, 0x0F, bin], :mrmmmx
|
416
|
+
}
|
417
|
+
# 3dnow prefix fallback
|
418
|
+
addop '3dnow', [0x0F, 0x0F], :mrmmmx, {}, :u8
|
419
|
+
|
420
|
+
addop 'femms', [0x0F, 0x0E]
|
421
|
+
addop 'prefetch', [0x0F, 0x0D, 0<<3], :modrmA
|
422
|
+
addop 'prefetchw', [0x0F, 0x0D, 1<<3], :modrmA
|
423
|
+
end
|
424
|
+
|
425
|
+
def init_sse_only
|
426
|
+
init_cpu_constants
|
427
|
+
|
428
|
+
addop_macrossps 'addps', [0x0F, 0xA8], :mrmxmm
|
429
|
+
addop 'andnps', [0x0F, 0xAA], :mrmxmm
|
430
|
+
addop 'andps', [0x0F, 0xA4], :mrmxmm
|
431
|
+
addop_macrossps 'cmpps', [0x0F, 0xC2], :mrmxmm
|
432
|
+
addop 'comiss', [0x0F, 0x2F], :mrmxmm
|
433
|
+
|
434
|
+
[['pi2ps', 0x2A], ['ps2pi', 0x2D], ['tps2pi', 0x2C]].each { |str, bin|
|
435
|
+
addop('cvt' << str, [0x0F, bin], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrmmmx }
|
436
|
+
addop('cvt' << str.tr('p', 's'), [0x0F, bin], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrm ; o.props[:needpfx] = 0xF3 }
|
437
|
+
}
|
438
|
+
|
439
|
+
addop_macrossps 'divps', [0x0F, 0x5E], :mrmxmm
|
440
|
+
addop 'ldmxcsr', [0x0F, 0xAE, 2<<3], :modrmA
|
441
|
+
addop_macrossps 'maxps', [0x0F, 0x5F], :mrmxmm
|
442
|
+
addop_macrossps 'minps', [0x0F, 0x5D], :mrmxmm
|
443
|
+
addop('movaps', [0x0F, 0x28], :mrmxmm, {:d => [1, 0]}) { |o| o.args.reverse! }
|
444
|
+
addop('movd', [0x0F, 0x6E], :mrmxmm, {:d => [1, 4]}) { |o| o.args[o.args.index(:modrmxmm)] = :modrm ; o.args.reverse! ; o.props[:needpfx] = 0x66 }
|
445
|
+
addop('movdqa', [0x0F, 0x6F], :mrmxmm, {:d => [1, 4]}) { |o| o.args.reverse! ; o.props[:needpfx] = 0x66 }
|
446
|
+
|
447
|
+
# movhlps(reg, reg){nomem} == movlps(reg, mrm){no restriction}...
|
448
|
+
addop 'movhlps', [0x0F, 0x12], :mrmxmm, {:d => [1, 0]}
|
449
|
+
addop 'movlps', [0x0F, 0x12], :mrmxmm, {:d => [1, 0]}
|
450
|
+
addop 'movlhps', [0x0F, 0x16], :mrmxmm, {:d => [1, 0]}
|
451
|
+
addop 'movhps', [0x0F, 0x16], :mrmxmm, {:d => [1, 0]}
|
452
|
+
|
453
|
+
addop 'movmskps',[0x0F, 0x50, 0xC0], nil, {:reg => [2, 3], :regxmm => [2, 0]}, :regxmm, :reg
|
454
|
+
addop('movss', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0xF3 }
|
455
|
+
addop 'movups', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}
|
456
|
+
addop_macrossps 'mulps', [0x0F, 0x59], :mrmxmm
|
457
|
+
addop 'orps', [0x0F, 0x56], :mrmxmm
|
458
|
+
addop_macrossps 'rcpps', [0x0F, 0x53], :mrmxmm
|
459
|
+
addop_macrossps 'rsqrtps',[0x0F, 0x52], :mrmxmm
|
460
|
+
addop 'shufps', [0x0F, 0xC6], :mrmxmm, {}, :u8
|
461
|
+
addop_macrossps 'sqrtps', [0x0F, 0x51], :mrmxmm
|
462
|
+
addop 'stmxcsr', [0x0F, 0xAE, 3<<3], :modrmA
|
463
|
+
addop_macrossps 'subps', [0x0F, 0x5C], :mrmxmm
|
464
|
+
addop 'ucomiss', [0x0F, 0x2E], :mrmxmm
|
465
|
+
addop 'unpckhps',[0x0F, 0x15], :mrmxmm
|
466
|
+
addop 'unpcklps',[0x0F, 0x14], :mrmxmm
|
467
|
+
addop 'xorps', [0x0F, 0x57], :mrmxmm
|
468
|
+
|
469
|
+
# start of integer instruction (accept opsz override prefix to access xmm)
|
470
|
+
addop('pavgb', [0x0F, 0xE0], :mrmmmx) { |o| o.props[:xmmx] = true }
|
471
|
+
addop('pavgw', [0x0F, 0xE3], :mrmmmx) { |o| o.props[:xmmx] = true }
|
472
|
+
# TODO addop('pextrw', [0x0F, 0xC5], :mrmmmx) { |o| o.fields[:reg] = o.fields.delete(:regmmx) } { |o| o.props[:xmmx] = true ; o.args << :u8 }
|
473
|
+
# addop('pinsrw', [0x0F, 0xC4], :mrmmmx) { |o| o.fields[:reg] = o.fields.delete(:regmmx) } { |o| o.props[:xmmx] = true ; o.args << :u8 }
|
474
|
+
addop('pmaxsw', [0x0F, 0xEE], :mrmmmx) { |o| o.props[:xmmx] = true }
|
475
|
+
addop('pmaxub', [0x0F, 0xDE], :mrmmmx) { |o| o.props[:xmmx] = true }
|
476
|
+
addop('pminsw', [0x0F, 0xEA], :mrmmmx) { |o| o.props[:xmmx] = true }
|
477
|
+
addop('pminub', [0x0F, 0xDA], :mrmmmx) { |o| o.props[:xmmx] = true }
|
478
|
+
# addop('pmovmskb',[0x0F, 0xD4], :mrmmmx) { |o| o.fields[:reg] = o.fields.delete(:regmmx) } ) { |o| o.props[:xmmx] = true } # no mem ref in the mrm
|
479
|
+
addop('pmulhuw', [0x0F, 0xE4], :mrmmmx) { |o| o.props[:xmmx] = true }
|
480
|
+
addop('psadbw', [0x0F, 0xF6], :mrmmmx) { |o| o.props[:xmmx] = true }
|
481
|
+
addop('pshufw', [0x0F, 0x70], :mrmmmx) { |o| o.props[:xmmx] = true ; o.args << :u8 }
|
482
|
+
addop('maskmovq',[0x0F, 0xF7], :mrmmmx) { |o| o.props[:xmmx] = true } # nomem
|
483
|
+
addop('movntq', [0x0F, 0xE7], :mrmmmx) { |o| o.props[:xmmx] = true }
|
484
|
+
addop 'movntps', [0x0F, 0x2B], :mrmxmm
|
485
|
+
addop 'prefetcht0', [0x0F, 0x18, 1<<3], :modrmA
|
486
|
+
addop 'prefetcht1', [0x0F, 0x18, 2<<3], :modrmA
|
487
|
+
addop 'prefetcht2', [0x0F, 0x18, 3<<3], :modrmA
|
488
|
+
addop 'prefetchnta',[0x0F, 0x18, 0<<3], :modrmA
|
489
|
+
addop 'sfence', [0x0F, 0xAE, 0xF8]
|
490
|
+
end
|
491
|
+
|
492
|
+
# XXX must be done after init_sse (patches :regmmx opcodes)
|
493
|
+
# TODO complete the list
|
494
|
+
def init_sse2_only
|
495
|
+
init_cpu_constants
|
496
|
+
|
497
|
+
@opcode_list.each { |o| o.props[:xmmx] = true if o.args.include? :regmmx and o.args.include? :modrmmmx }
|
498
|
+
|
499
|
+
# TODO <..blabla...integer...blabla..>
|
500
|
+
|
501
|
+
# nomem
|
502
|
+
addop('clflush', [0x0F, 0xAE, 7<<3], :modrmA) { |o| o.props[:argsz] = 8 }
|
503
|
+
addop('maskmovdqu', [0x0F, 0xF7], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
504
|
+
addop('movntpd', [0x0F, 0x2B], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
505
|
+
addop('movntdq', [0x0F, 0xE7], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
506
|
+
addop 'movnti', [0x0F, 0xC3], :mrm
|
507
|
+
addop('pause', [0x90]) { |o| o.props[:needpfx] = 0xF3 }
|
508
|
+
addop 'lfence', [0x0F, 0xAE, 0xE8]
|
509
|
+
addop 'mfence', [0x0F, 0xAE, 0xF0]
|
510
|
+
end
|
511
|
+
|
512
|
+
def init_sse3_only
|
513
|
+
init_cpu_constants
|
514
|
+
|
515
|
+
addop('addsubpd', [0x0F, 0xD0], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
516
|
+
addop('addsubps', [0x0F, 0xD0], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
517
|
+
addop('haddpd', [0x0F, 0x7C], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
518
|
+
addop('haddps', [0x0F, 0x7C], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
519
|
+
addop('hsubpd', [0x0F, 0x7D], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
520
|
+
addop('hsubps', [0x0F, 0x7D], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
521
|
+
|
522
|
+
addop 'monitor', [0x0F, 0x01, 0xC8]
|
523
|
+
addop 'mwait', [0x0F, 0x01, 0xC9]
|
524
|
+
|
525
|
+
addop('fisttp', [0xDF, 1<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
526
|
+
addop('fisttp', [0xDB, 1<<3], :modrmA) { |o| o.props[:argsz] = 32 }
|
527
|
+
addop('fisttp', [0xDD, 1<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
528
|
+
addop('lddqu', [0x0F, 0xF0], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrmA ; o.props[:needpfx] = 0xF2 }
|
529
|
+
addop('movddup', [0x0F, 0x12], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
530
|
+
addop('movshdup', [0x0F, 0x16], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
531
|
+
addop('movsldup', [0x0F, 0x12], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
532
|
+
end
|
533
|
+
|
534
|
+
def init_vmx_only
|
535
|
+
init_cpu_constants
|
536
|
+
|
537
|
+
addop 'vmcall', [0x0F, 0x01, 0xC1]
|
538
|
+
addop 'vmlaunch', [0x0F, 0x01, 0xC2]
|
539
|
+
addop 'vmresume', [0x0F, 0x01, 0xC3]
|
540
|
+
addop 'vmxoff', [0x0F, 0x01, 0xC4]
|
541
|
+
addop 'vmread', [0x0F, 0x78], :mrm
|
542
|
+
addop 'vmwrite', [0x0F, 0x79], :mrm
|
543
|
+
addop('vmclear', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0x66 }
|
544
|
+
addop('vmxon', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0xF3 }
|
545
|
+
addop('vmptrld', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
546
|
+
addop('vmptrrst', [0x0F, 0xC7, 7<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
547
|
+
addop('invept', [0x0F, 0x38, 0x80], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
548
|
+
addop('invvpid', [0x0F, 0x38, 0x81], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
549
|
+
|
550
|
+
addop 'getsec', [0x0F, 0x37]
|
551
|
+
|
552
|
+
addop('movbe', [0x0F, 0x38, 0xF0], :mrm, { :d => [2, 0] }) { |o| o.args.reverse! }
|
553
|
+
addop 'xgetbv', [0x0F, 0x01, 0xD0]
|
554
|
+
addop 'xsetbv', [0x0F, 0x01, 0xD1]
|
555
|
+
addop 'rdtscp', [0x0F, 0x01, 0xF9]
|
556
|
+
addop 'xrstor', [0x0F, 0xAE, 5<<3], :modrmA
|
557
|
+
addop 'xsave', [0x0F, 0xAE, 4<<3], :modrmA
|
558
|
+
addop 'nop', [0x0F, 0x1F], 0 # which family does this belong to ?
|
559
|
+
end
|
560
|
+
|
561
|
+
def init_sse42_only
|
562
|
+
init_cpu_constants
|
563
|
+
|
564
|
+
addop('crc32', [0x0F, 0x38, 0xF0], :mrmw) { |o| o.props[:needpfx] = 0xF2 }
|
565
|
+
addop('pcmpestrm', [0x0F, 0x3A, 0x60], :mrmxmm, {}, :i8) { |o| o.props[:needpfx] = 0x66 }
|
566
|
+
addop('pcmpestri', [0x0F, 0x3A, 0x61], :mrmxmm, {}, :i8) { |o| o.props[:needpfx] = 0x66 }
|
567
|
+
addop('pcmpistrm', [0x0F, 0x3A, 0x62], :mrmxmm, {}, :i8) { |o| o.props[:needpfx] = 0x66 }
|
568
|
+
addop('pcmpistri', [0x0F, 0x3A, 0x63], :mrmxmm, {}, :i8) { |o| o.props[:needpfx] = 0x66 }
|
569
|
+
addop('pcmpgtq', [0x0F, 0x38, 0x37], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
570
|
+
addop('popcnt', [0x0F, 0xB8], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
571
|
+
end
|
572
|
+
|
573
|
+
|
574
|
+
#
|
575
|
+
# CPU family dependencies
|
576
|
+
#
|
577
|
+
|
578
|
+
def init_386_common
|
579
|
+
init_386_common_only
|
580
|
+
end
|
581
|
+
|
582
|
+
def init_386
|
583
|
+
init_386_common
|
584
|
+
init_386_only
|
585
|
+
end
|
586
|
+
|
587
|
+
def init_387
|
588
|
+
init_387_only
|
589
|
+
end
|
590
|
+
|
591
|
+
def init_486
|
592
|
+
init_386
|
593
|
+
init_387
|
594
|
+
init_486_only
|
595
|
+
end
|
596
|
+
|
597
|
+
def init_pentium
|
598
|
+
init_486
|
599
|
+
init_pentium_only
|
600
|
+
end
|
601
|
+
|
602
|
+
def init_3dnow
|
603
|
+
init_pentium
|
604
|
+
init_3dnow_only
|
605
|
+
end
|
606
|
+
|
607
|
+
def init_p6
|
608
|
+
init_pentium
|
609
|
+
init_p6_only
|
610
|
+
end
|
611
|
+
|
612
|
+
def init_sse
|
613
|
+
init_p6
|
614
|
+
init_sse_only
|
615
|
+
end
|
616
|
+
|
617
|
+
def init_sse2
|
618
|
+
init_sse
|
619
|
+
init_sse2_only
|
620
|
+
end
|
621
|
+
|
622
|
+
def init_sse3
|
623
|
+
init_sse2
|
624
|
+
init_sse3_only
|
625
|
+
end
|
626
|
+
|
627
|
+
def init_vmx
|
628
|
+
init_sse3
|
629
|
+
init_vmx_only
|
630
|
+
end
|
631
|
+
|
632
|
+
def init_all
|
633
|
+
init_vmx
|
634
|
+
init_sse42_only
|
635
|
+
init_3dnow_only
|
636
|
+
end
|
637
|
+
|
638
|
+
alias init_latest init_all
|
639
|
+
|
640
|
+
|
641
|
+
#
|
642
|
+
# addop_* macros
|
643
|
+
#
|
644
|
+
|
645
|
+
def addop_macro1(name, num, immtype=:i)
|
646
|
+
addop name, [(num << 3) | 4], nil, {:w => [0, 0]}, :reg_eax, immtype
|
647
|
+
addop name, [num << 3], :mrmw, {:d => [0, 1]}
|
648
|
+
addop name, [0x80], num, {:w => [0, 0], :s => [0, 1]}, immtype
|
649
|
+
end
|
650
|
+
def addop_macro2(name, num)
|
651
|
+
addop name, [0x0F, 0xBA], (4 | num), {}, :u8
|
652
|
+
addop(name, [0x0F, 0xA3 | (num << 3)], :mrm) { |op| op.args.reverse! }
|
653
|
+
end
|
654
|
+
def addop_macro3(name, num)
|
655
|
+
addop name, [0xD0], num, {:w => [0, 0]}, :imm_val1
|
656
|
+
addop name, [0xD2], num, {:w => [0, 0]}, :reg_cl
|
657
|
+
addop name, [0xC0], num, {:w => [0, 0]}, :u8
|
658
|
+
end
|
659
|
+
|
660
|
+
def addop_macrotttn(name, bin, hint, fields = {}, *props, &blk)
|
661
|
+
[%w{o}, %w{no}, %w{b nae c}, %w{nb ae nc},
|
662
|
+
%w{z e}, %w{nz ne}, %w{be na}, %w{nbe a},
|
663
|
+
%w{s}, %w{ns}, %w{p pe}, %w{np po},
|
664
|
+
%w{l nge}, %w{nl ge}, %w{le ng}, %w{nle g}].each_with_index { |e, i|
|
665
|
+
b = bin.dup
|
666
|
+
if b[0] == 0x0F
|
667
|
+
b[1] |= i
|
668
|
+
else
|
669
|
+
b[0] |= i
|
670
|
+
end
|
671
|
+
|
672
|
+
e.each { |k| addop(name + k, b.dup, hint, fields.dup, *props, &blk) }
|
673
|
+
}
|
674
|
+
end
|
675
|
+
|
676
|
+
def addop_macrostr(name, bin, type)
|
677
|
+
# addop(name, bin.dup, {:w => [0, 0]}) { |o| o.props[type] = true } # TODO allow segment override
|
678
|
+
addop(name+'b', bin) { |o| o.props[:opsz] = 16 ; o.props[type] = true }
|
679
|
+
addop(name+'b', bin) { |o| o.props[:opsz] = 32 ; o.props[type] = true }
|
680
|
+
bin = bin.dup
|
681
|
+
bin[0] |= 1
|
682
|
+
addop(name+'w', bin) { |o| o.props[:opsz] = 16 ; o.props[type] = true }
|
683
|
+
addop(name+'d', bin) { |o| o.props[:opsz] = 32 ; o.props[type] = true }
|
684
|
+
end
|
685
|
+
|
686
|
+
def addop_macrofpu1(name, n)
|
687
|
+
addop(name, [0xD8, n<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 32 }
|
688
|
+
addop(name, [0xDC, n<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 64 }
|
689
|
+
addop name, [0xD8, 0xC0|(n<<3)], :regfp, {:d => [0, 2]}
|
690
|
+
end
|
691
|
+
def addop_macrofpu2(name, n, n2=0)
|
692
|
+
addop(name, [0xDE|n2, n<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 16 }
|
693
|
+
addop(name, [0xDA|n2, n<<3], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 32 }
|
694
|
+
end
|
695
|
+
def addop_macrofpu3(name, n)
|
696
|
+
addop_macrofpu2 name, n, 1
|
697
|
+
addop(name, [0xDF, 0x28|(n<<3)], :modrmA, {}, :regfp0) { |o| o.props[:argsz] = 64 }
|
698
|
+
end
|
699
|
+
|
700
|
+
def addop_macrogg(ggrng, name, bin, *args, &blk)
|
701
|
+
ggrng.each { |gg|
|
702
|
+
bindup = bin.dup
|
703
|
+
bindup[1] |= gg
|
704
|
+
sfx = %w(b w d q)[gg]
|
705
|
+
addop name+sfx, bindup, *args, &blk
|
706
|
+
}
|
707
|
+
end
|
708
|
+
|
709
|
+
def addop_macrommx(ggrng, name, val)
|
710
|
+
addop_macrogg ggrng, name, [0x0F, 0xC0 | (val << 4)], :mrmmmx
|
711
|
+
addop_macrogg ggrng, name, [0x0F, 0x70, 0xC0 | (val << 4)], nil, {:regmmx => [2, 0]}, :u8
|
712
|
+
end
|
713
|
+
|
714
|
+
def addop_macrossps(name, bin, hint)
|
715
|
+
# don't allow fields argument, as this will be modified by addop (.dup it if needed)
|
716
|
+
addop name, bin, hint
|
717
|
+
addop(name.tr('p', 's'), bin, hint) { |o| o.props[:needpfx] = 0xF3 }
|
718
|
+
end
|
719
|
+
|
720
|
+
# helper function: creates a new Opcode based on the arguments, eventually
|
721
|
+
# yields it for further customisation, and append it to the instruction set
|
722
|
+
# is responsible of the creation of disambiguating opcodes if necessary (:s flag hardcoding)
|
723
|
+
def addop(name, bin, hint=nil, fields={}, *argprops)
|
724
|
+
op = Opcode.new name, bin
|
725
|
+
op.fields.replace fields
|
726
|
+
|
727
|
+
case hint
|
728
|
+
when nil
|
729
|
+
|
730
|
+
when :mrm, :mrmw, :mrmA
|
731
|
+
h = (hint == :mrmA ? :modrmA : :modrm)
|
732
|
+
op.fields[:reg] = [bin.length, 3]
|
733
|
+
op.fields[h] = [bin.length, 0]
|
734
|
+
op.fields[:w] = [bin.length - 1, 0] if hint == :mrmw
|
735
|
+
argprops.unshift :reg, h
|
736
|
+
op.bin << 0
|
737
|
+
when :reg
|
738
|
+
op.fields[:reg] = [bin.length-1, 0]
|
739
|
+
argprops.unshift :reg
|
740
|
+
when :regfp
|
741
|
+
op.fields[:regfp] = [bin.length-1, 0]
|
742
|
+
argprops.unshift :regfp, :regfp0
|
743
|
+
when :modrmA
|
744
|
+
op.fields[:modrmA] = [bin.length-1, 0]
|
745
|
+
argprops << :modrmA
|
746
|
+
|
747
|
+
when Integer # mod/m, reg == opcode extension = hint
|
748
|
+
op.fields[:modrm] = [bin.length, 0]
|
749
|
+
op.bin << (hint << 3)
|
750
|
+
argprops.unshift :modrm
|
751
|
+
|
752
|
+
when :mrmmmx
|
753
|
+
op.fields[:regmmx] = [bin.length, 3]
|
754
|
+
op.fields[:modrm] = [bin.length, 0]
|
755
|
+
bin << 0
|
756
|
+
argprops.unshift :regmmx, :modrmmmx
|
757
|
+
when :mrmxmm
|
758
|
+
op.fields[:regxmm] = [bin.length, 3]
|
759
|
+
op.fields[:modrm] = [bin.length, 0]
|
760
|
+
bin << 0
|
761
|
+
argprops.unshift :regxmm, :modrmxmm
|
762
|
+
else
|
763
|
+
raise SyntaxError, "invalid hint #{hint.inspect} for #{name}"
|
764
|
+
end
|
765
|
+
|
766
|
+
if argprops.index(:u)
|
767
|
+
argprops << :unsigned_imm
|
768
|
+
argprops[argprops.index(:u)] = :i
|
769
|
+
end
|
770
|
+
|
771
|
+
(argprops & @valid_props).each { |p| op.props[p] = true }
|
772
|
+
argprops -= @valid_props
|
773
|
+
|
774
|
+
op.args.concat(argprops & @valid_args)
|
775
|
+
argprops -= @valid_args
|
776
|
+
|
777
|
+
raise "Invalid opcode definition: #{name}: unknown #{argprops.inspect}" unless argprops.empty?
|
778
|
+
|
779
|
+
yield op if block_given?
|
780
|
+
|
781
|
+
argprops = (op.props.keys - @valid_props) + (op.args - @valid_args) + (op.fields.keys - @fields_mask.keys)
|
782
|
+
raise "Invalid opcode customisation: #{name}: #{argprops.inspect}" unless argprops.empty?
|
783
|
+
|
784
|
+
addop_post(op)
|
785
|
+
end
|
786
|
+
|
787
|
+
# this recursive method is in charge of Opcode duplication (eg to hardcode some flag)
|
788
|
+
def addop_post(op)
|
789
|
+
dupe = lambda { |o|
|
790
|
+
dop = Opcode.new o.name.dup
|
791
|
+
dop.bin, dop.fields, dop.props, dop.args = o.bin.dup, o.fields.dup, o.props.dup, o.args.dup
|
792
|
+
dop
|
793
|
+
}
|
794
|
+
if df = op.fields.delete(:d)
|
795
|
+
# hardcode the bit
|
796
|
+
dop = dupe[op]
|
797
|
+
dop.args.reverse!
|
798
|
+
addop_post dop
|
799
|
+
|
800
|
+
op.bin[df[0]] |= 1 << df[1]
|
801
|
+
addop_post op
|
802
|
+
|
803
|
+
return
|
804
|
+
elsif wf = op.fields.delete(:w)
|
805
|
+
# hardcode the bit
|
806
|
+
dop = dupe[op]
|
807
|
+
dop.props[:argsz] = 8
|
808
|
+
addop_post dop
|
809
|
+
|
810
|
+
op.bin[wf[0]] |= 1 << wf[1]
|
811
|
+
addop_post op
|
812
|
+
|
813
|
+
return
|
814
|
+
elsif sf = op.fields.delete(:s)
|
815
|
+
# add explicit choice versions, with lower precedence (so that disassembling will return the general version)
|
816
|
+
# eg "jmp", "jmp.i8", "jmp.i"
|
817
|
+
# also hardcode the bit
|
818
|
+
op32 = op
|
819
|
+
addop_post op32
|
820
|
+
|
821
|
+
op8 = dupe[op]
|
822
|
+
op8.bin[sf[0]] |= 1 << sf[1]
|
823
|
+
op8.args.map! { |arg| arg == :i ? :i8 : arg }
|
824
|
+
addop_post op8
|
825
|
+
|
826
|
+
op32 = dupe[op32]
|
827
|
+
op32.name << '.i'
|
828
|
+
addop_post op32
|
829
|
+
|
830
|
+
op8 = dupe[op8]
|
831
|
+
op8.name << '.i8'
|
832
|
+
addop_post op8
|
833
|
+
|
834
|
+
return
|
835
|
+
elsif op.args.first == :regfp0
|
836
|
+
dop = dupe[op]
|
837
|
+
dop.args.delete :regfp0
|
838
|
+
addop_post dop
|
839
|
+
end
|
840
|
+
|
841
|
+
if op.props[:needpfx] and @opcode_list.find { |oo| oo.name == op.name and not oo.props[:needpfx] }
|
842
|
+
@opcode_list.unshift op
|
843
|
+
else
|
844
|
+
@opcode_list << op
|
845
|
+
end
|
846
|
+
|
847
|
+
if op.args == [:i] or op.args == [:farptr] or op.name[0, 3] == 'ret'
|
848
|
+
# define opsz-override version for ambiguous opcodes
|
849
|
+
op16 = dupe[op]
|
850
|
+
op16.name << '.i16'
|
851
|
+
op16.props[:opsz] = 16
|
852
|
+
@opcode_list << op16
|
853
|
+
op32 = dupe[op]
|
854
|
+
op32.name << '.i32'
|
855
|
+
op32.props[:opsz] = 32
|
856
|
+
@opcode_list << op32
|
857
|
+
elsif op.props[:strop] or op.props[:stropz] or op.args.include? :mrm_imm or
|
858
|
+
op.args.include? :modrm or op.args.include? :modrmA or op.name =~ /loop|xlat/
|
859
|
+
# define adsz-override version for ambiguous opcodes (TODO allow movsd edi / movsd di syntax)
|
860
|
+
# XXX loop pfx 67 = eip+cx, 66 = ip+ecx
|
861
|
+
op16 = dupe[op]
|
862
|
+
op16.name << '.a16'
|
863
|
+
op16.props[:adsz] = 16
|
864
|
+
@opcode_list << op16
|
865
|
+
op32 = dupe[op]
|
866
|
+
op32.name << '.a32'
|
867
|
+
op32.props[:adsz] = 32
|
868
|
+
@opcode_list << op32
|
869
|
+
end
|
870
|
+
end
|
871
|
+
end
|
872
|
+
end
|