metasm 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
@@ -4,7 +4,7 @@
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
5
5
|
|
6
6
|
|
7
|
-
require 'metasm/ia32/main'
|
7
|
+
require 'metasm/cpu/ia32/main'
|
8
8
|
|
9
9
|
module Metasm
|
10
10
|
class Ia32
|
@@ -52,7 +52,7 @@ class Ia32
|
|
52
52
|
# returns { blockaddr => [list of vars that are needed by a following block] }
|
53
53
|
def decompile_func_finddeps(dcmp, blocks, func)
|
54
54
|
deps_r = {} ; deps_w = {} ; deps_to = {}
|
55
|
-
deps_subfunc = {}
|
55
|
+
deps_subfunc = {} # things read/written by subfuncs
|
56
56
|
|
57
57
|
# find read/writes by each block
|
58
58
|
blocks.each { |b, to|
|
@@ -70,7 +70,7 @@ class Ia32
|
|
70
70
|
end
|
71
71
|
}
|
72
72
|
a << :eax if di.opcode.name == 'ret' and (not func.type.kind_of? C::BaseType or func.type.type.name != :void) # standard ABI
|
73
|
-
|
73
|
+
|
74
74
|
deps_r[b] |= a.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown] - deps_w[b]
|
75
75
|
deps_w[b] |= w.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown]
|
76
76
|
}
|
@@ -121,7 +121,7 @@ class Ia32
|
|
121
121
|
end
|
122
122
|
}
|
123
123
|
a << :eax if di.opcode.name == 'ret' and (not func.type.kind_of? C::BaseType or func.type.type.name != :void) # standard ABI
|
124
|
-
|
124
|
+
|
125
125
|
next true if (a.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown] - bw).include? r
|
126
126
|
bw |= w.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown]
|
127
127
|
false
|
@@ -369,7 +369,7 @@ class Ia32
|
|
369
369
|
# to.delete addr
|
370
370
|
# next if not l = dcmp.dasm.get_label_at(addr)
|
371
371
|
# sw.body.statements << C::Goto.new(l)
|
372
|
-
|
372
|
+
# }
|
373
373
|
# stmts << sw
|
374
374
|
a = di.instruction.args.first
|
375
375
|
if a.kind_of? Expression
|
@@ -512,9 +512,9 @@ class Ia32
|
|
512
512
|
dcmp.dasm.decoded[b_].block.list.each { |di|
|
513
513
|
di.backtrace_binding = nil
|
514
514
|
}
|
515
|
-
|
515
|
+
}
|
516
516
|
end
|
517
|
-
|
517
|
+
|
518
518
|
def decompile_check_abi(dcmp, entry, func)
|
519
519
|
a = func.type.args || []
|
520
520
|
a.delete_if { |arg| arg.has_attribute_var('register') and arg.has_attribute('unused') }
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
5
5
|
|
6
6
|
|
7
|
-
require 'metasm/ia32/opcodes'
|
7
|
+
require 'metasm/cpu/ia32/opcodes'
|
8
8
|
require 'metasm/encode'
|
9
9
|
|
10
10
|
module Metasm
|
@@ -195,27 +195,28 @@ class Ia32
|
|
195
195
|
case k
|
196
196
|
when :jmp; {:jmp => 0x3e, :nojmp => 0x2e}[v]
|
197
197
|
when :lock; 0xf0
|
198
|
-
when :rep; {'repnz' => 0xf2, 'repz' => 0xf3, 'rep' => 0xf2}[v]
|
198
|
+
when :rep; {'repnz' => 0xf2, 'repz' => 0xf3, 'rep' => 0xf2}[v]
|
199
|
+
when :jmphint; {'hintjmp' => 0x3e, 'hintnojmp' => 0x2e}[v]
|
200
|
+
when :seg; [0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65][v.val]
|
199
201
|
end
|
200
202
|
}.compact.pack 'C*'
|
201
|
-
pfx << op.props[:needpfx] if op.props[:needpfx]
|
202
203
|
|
203
204
|
if op.name == 'movsx' or op.name == 'movzx'
|
204
205
|
pfx << 0x66 if size == 48-i.args[0].sz
|
206
|
+
elsif op.name == 'crc32'
|
207
|
+
pfx << 0x66 if size == 48-i.args[1].sz
|
205
208
|
else
|
206
209
|
opsz = op.props[:argsz]
|
207
210
|
oi.each { |oa, ia|
|
208
211
|
case oa
|
209
|
-
when :reg, :reg_eax, :modrm, :
|
212
|
+
when :reg, :reg_eax, :modrm, :mrm_imm
|
210
213
|
raise EncodeError, "Incompatible arg size in #{i}" if ia.sz and opsz and opsz != ia.sz
|
211
214
|
opsz = ia.sz
|
212
215
|
end
|
213
216
|
}
|
214
|
-
pfx << 0x66 if (
|
215
|
-
|
216
|
-
|
217
|
-
opsz = op.props[:opsz]
|
218
|
-
end
|
217
|
+
pfx << 0x66 if (op.props[:opsz] and size == 48 - op.props[:opsz]) or
|
218
|
+
(not op.props[:argsz] and opsz and size == 48 - opsz)
|
219
|
+
opsz ||= op.props[:opsz]
|
219
220
|
end
|
220
221
|
opsz ||= size
|
221
222
|
|
@@ -226,7 +227,7 @@ class Ia32
|
|
226
227
|
adsz ||= size
|
227
228
|
# addrsize override / segment override
|
228
229
|
if mrm = i.args.grep(ModRM).first
|
229
|
-
if not op.props[:adsz] and ((mrm.b and mrm.b.sz
|
230
|
+
if not op.props[:adsz] and ((mrm.b and mrm.b.sz == 48 - adsz) or (mrm.i and mrm.i.sz == 48 - adsz))
|
230
231
|
pfx << 0x67
|
231
232
|
adsz = 48 - adsz
|
232
233
|
end
|
@@ -240,10 +241,12 @@ class Ia32
|
|
240
241
|
postponed = []
|
241
242
|
oi.each { |oa, ia|
|
242
243
|
case oa
|
243
|
-
when :reg, :seg3, :seg3A, :seg2, :seg2A, :eeec, :eeed, :eeet, :regfp, :regmmx, :regxmm
|
244
|
+
when :reg, :seg3, :seg3A, :seg2, :seg2A, :eeec, :eeed, :eeet, :regfp, :regmmx, :regxmm, :regymm
|
244
245
|
# field arg
|
245
246
|
set_field[oa, ia.val]
|
246
247
|
pfx << 0x66 if oa == :regmmx and op.props[:xmmx] and ia.sz == 128
|
248
|
+
when :vexvreg, :vexvxmm, :vexvymm
|
249
|
+
set_field[:vex_vvvv, ia.val ^ 0xf]
|
247
250
|
when :imm_val1, :imm_val3, :reg_cl, :reg_eax, :reg_dx, :regfp0
|
248
251
|
# implicit
|
249
252
|
else
|
@@ -251,7 +254,7 @@ class Ia32
|
|
251
254
|
end
|
252
255
|
}
|
253
256
|
|
254
|
-
if !(op.args & [:modrm, :
|
257
|
+
if !(op.args & [:modrm, :modrmmmx, :modrmxmm, :modrmymm]).empty?
|
255
258
|
# reg field of modrm
|
256
259
|
regval = (base[-1] >> 3) & 7
|
257
260
|
base.pop
|
@@ -265,6 +268,8 @@ class Ia32
|
|
265
268
|
postponed.first[1] = Expression[target, :-, postlabel]
|
266
269
|
end
|
267
270
|
|
271
|
+
pfx << op.props[:needpfx] if op.props[:needpfx]
|
272
|
+
|
268
273
|
#
|
269
274
|
# append other arguments
|
270
275
|
#
|
@@ -273,7 +278,7 @@ class Ia32
|
|
273
278
|
postponed.each { |oa, ia|
|
274
279
|
case oa
|
275
280
|
when :farptr; ed = ia.encode(@endianness, "a#{opsz}".to_sym)
|
276
|
-
when :modrm, :
|
281
|
+
when :modrm, :modrmmmx, :modrmxmm, :modrmymm
|
277
282
|
if ia.kind_of? ModRM
|
278
283
|
ed = ia.encode(regval, @endianness)
|
279
284
|
if ed.kind_of?(::Array)
|
@@ -295,6 +300,7 @@ class Ia32
|
|
295
300
|
when :mrm_imm; ed = ia.imm.encode("a#{adsz}".to_sym, @endianness)
|
296
301
|
when :i8, :u8, :u16; ed = ia.encode(oa, @endianness)
|
297
302
|
when :i; ed = ia.encode("a#{opsz}".to_sym, @endianness)
|
303
|
+
when :i4xmm, :i4ymm; ed = ia.val << 4 # u8
|
298
304
|
else raise SyntaxError, "Internal error: want to encode field #{oa.inspect} as arg in #{i}"
|
299
305
|
end
|
300
306
|
|
@@ -34,6 +34,10 @@ class Ia32 < CPU
|
|
34
34
|
@val = v
|
35
35
|
end
|
36
36
|
|
37
|
+
def ==(o)
|
38
|
+
self.class == o.class and val == o.val
|
39
|
+
end
|
40
|
+
|
37
41
|
def self.from_str(s) new(@s_to_i[s]) end
|
38
42
|
}
|
39
43
|
end
|
@@ -53,13 +57,16 @@ class Ia32 < CPU
|
|
53
57
|
@sz = sz
|
54
58
|
end
|
55
59
|
|
60
|
+
def ==(o)
|
61
|
+
self.class == o.class and val == o.val and sz == o.sz
|
62
|
+
end
|
63
|
+
|
56
64
|
def self.from_str(s)
|
57
65
|
raise "Bad #{name} #{s.inspect}" if not x = @s_to_i[s]
|
58
66
|
new(*x)
|
59
67
|
end
|
60
68
|
}
|
61
69
|
end
|
62
|
-
|
63
70
|
end
|
64
71
|
|
65
72
|
|
@@ -88,10 +95,11 @@ class Ia32 < CPU
|
|
88
95
|
simple_map((0..7).map { |i| [i, "ST(#{i})"] } << [nil, 'ST'])
|
89
96
|
end
|
90
97
|
|
91
|
-
#
|
98
|
+
# Single Instr Multiple Data register (mm0..mm7, xmm0..xmm7, ymm0..ymm7)
|
92
99
|
class SimdReg < Argument
|
93
100
|
double_map 64 => (0..7).map { |n| "mm#{n}" },
|
94
|
-
128 => (0..7).map { |n| "xmm#{n}" }
|
101
|
+
128 => (0..7).map { |n| "xmm#{n}" },
|
102
|
+
256 => (0..7).map { |n| "ymm#{n}" }
|
95
103
|
def symbolic(di=nil) ; to_s.to_sym end
|
96
104
|
end
|
97
105
|
|
@@ -133,12 +141,16 @@ class Ia32 < CPU
|
|
133
141
|
def initialize(seg, addr)
|
134
142
|
@seg, @addr = seg, addr
|
135
143
|
end
|
144
|
+
|
145
|
+
def ==(o)
|
146
|
+
self.class == o.class and seg == o.seg and addr == o.addr
|
147
|
+
end
|
136
148
|
end
|
137
149
|
|
138
150
|
# ModRM represents indirections in x86 (eg dword ptr [eax+4*ebx+12h])
|
139
151
|
class ModRM < Argument
|
140
152
|
# valid combinaisons for a modrm
|
141
|
-
# ints are reg indexes, symbols are immediates, except :sib
|
153
|
+
# ints are reg indexes, symbols are immediates, except :sib
|
142
154
|
Sum = {
|
143
155
|
16 => {
|
144
156
|
0 => [ [3, 6], [3, 7], [5, 6], [5, 7], [6], [7], [:i16], [3] ],
|
@@ -180,6 +192,10 @@ class Ia32 < CPU
|
|
180
192
|
p = Expression["segment_base_#@seg", :+, p] if seg and seg.val != ((b && (@b.val == 4 || @b.val == 5)) ? 2 : 3)
|
181
193
|
Indirection[p.reduce, @sz/8, (di.address if di)]
|
182
194
|
end
|
195
|
+
|
196
|
+
def ==(o)
|
197
|
+
self.class == o.class and s == o.s and i == o.i and b == o.b and imm == o.imm and seg == o.seg and adsz == o.adsz and sz == o.sz
|
198
|
+
end
|
183
199
|
end
|
184
200
|
|
185
201
|
|
@@ -222,17 +238,44 @@ class Ia32 < CPU
|
|
222
238
|
pp.define_weak('__i386__')
|
223
239
|
end
|
224
240
|
|
225
|
-
# returns a Reg object if the arg is a valid register (eg 'ax' => Reg.new(0, 16))
|
241
|
+
# returns a Reg/SimdReg object if the arg is a valid register (eg 'ax' => Reg.new(0, 16))
|
226
242
|
# returns nil if str is invalid
|
227
243
|
def str_to_reg(str)
|
228
|
-
Reg.
|
244
|
+
Reg.s_to_i.has_key?(str) ? Reg.from_str(str) : SimdReg.s_to_i.has_key?(str) ? SimdReg.from_str(str) : nil
|
245
|
+
end
|
246
|
+
|
247
|
+
# returns the list of Regs in the instruction arguments
|
248
|
+
# may be converted into symbols through Reg#symbolic
|
249
|
+
def instr_args_regs(i)
|
250
|
+
i = i.instruction if i.kind_of?(DecodedInstruction)
|
251
|
+
i.args.grep(Reg)
|
252
|
+
end
|
253
|
+
|
254
|
+
# returns the list of ModRMs in the instruction arguments
|
255
|
+
# may be converted into Indirection through ModRM#symbolic
|
256
|
+
def instr_args_memoryptr(i)
|
257
|
+
i = i.instruction if i.kind_of?(DecodedInstruction)
|
258
|
+
i.args.grep(ModRM)
|
259
|
+
end
|
260
|
+
|
261
|
+
# return the 'base' of the ModRM (Reg/nil)
|
262
|
+
def instr_args_memoryptr_getbase(mrm)
|
263
|
+
mrm.b || (mrm.i if mrm.s == 1)
|
264
|
+
end
|
265
|
+
|
266
|
+
# return the offset of the ModRM (Expression/nil)
|
267
|
+
def instr_args_memoryptr_getoffset(mrm)
|
268
|
+
mrm.imm
|
269
|
+
end
|
270
|
+
|
271
|
+
# define ModRM offset (eg to changing imm into an ExpressionString)
|
272
|
+
def instr_args_memoryptr_setoffset(mrm, imm)
|
273
|
+
mrm.imm = (imm ? Expression[imm] : imm)
|
229
274
|
end
|
230
275
|
|
231
276
|
def shortname
|
232
277
|
"ia32#{'_16' if @size == 16}#{'_be' if @endianness == :big}"
|
233
278
|
end
|
234
279
|
end
|
235
|
-
|
236
280
|
X86 = Ia32
|
237
|
-
|
238
281
|
end
|
@@ -0,0 +1,1424 @@
|
|
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/cpu/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, :eeet => 7, :seg2 => 3, :seg3 => 7,
|
15
|
+
:regfp => 7, :regmmx => 7, :regxmm => 7, :regymm => 7,
|
16
|
+
:vex_r => 1, :vex_b => 1, :vex_x => 1, :vex_w => 1,
|
17
|
+
:vex_vvvv => 0xF
|
18
|
+
@fields_mask[:seg2A] = @fields_mask[:seg2]
|
19
|
+
@fields_mask[:seg3A] = @fields_mask[:seg3]
|
20
|
+
|
21
|
+
[:i, :i8, :u8, :u16, :reg, :seg2, :seg2A,
|
22
|
+
:seg3, :seg3A, :eeec, :eeed, :eeet, :modrm, :mrm_imm,
|
23
|
+
:farptr, :imm_val1, :imm_val3, :reg_cl, :reg_eax,
|
24
|
+
:reg_dx, :regfp, :regfp0, :modrmmmx, :regmmx,
|
25
|
+
:modrmxmm, :regxmm, :modrmymm, :regymm,
|
26
|
+
:vexvxmm, :vexvymm, :vexvreg, :i4xmm, :i4ymm
|
27
|
+
].each { |a| @valid_args[a] = true }
|
28
|
+
|
29
|
+
[:strop, :stropz, :opsz, :adsz, :argsz, :setip,
|
30
|
+
:stopexec, :saveip, :unsigned_imm, :random, :needpfx,
|
31
|
+
:xmmx, :modrmR, :modrmA, :mrmvex
|
32
|
+
].each { |a| @valid_props[a] = true }
|
33
|
+
end
|
34
|
+
|
35
|
+
# only most common instructions from the 386 instruction set
|
36
|
+
# inexhaustive list :
|
37
|
+
# no aaa, arpl, mov crX, call/jmp/ret far, in/out, bts, xchg...
|
38
|
+
def init_386_common_only
|
39
|
+
init_cpu_constants
|
40
|
+
|
41
|
+
addop_macro1 'adc', 2
|
42
|
+
addop_macro1 'add', 0
|
43
|
+
addop_macro1 'and', 4, :unsigned_imm
|
44
|
+
addop 'bswap', [0x0F, 0xC8], :reg
|
45
|
+
addop 'call', [0xE8], nil, :stopexec, :setip, :i, :saveip
|
46
|
+
addop 'call', [0xFF], 2, :stopexec, :setip, :saveip
|
47
|
+
addop('cbw', [0x98]) { |o| o.props[:opsz] = 16 }
|
48
|
+
addop('cwde', [0x98]) { |o| o.props[:opsz] = 32 }
|
49
|
+
addop('cwd', [0x99]) { |o| o.props[:opsz] = 16 }
|
50
|
+
addop('cdq', [0x99]) { |o| o.props[:opsz] = 32 }
|
51
|
+
addop_macro1 'cmp', 7
|
52
|
+
addop_macrostr 'cmps', [0xA6], :stropz
|
53
|
+
addop 'dec', [0x48], :reg
|
54
|
+
addop 'dec', [0xFE], 1, {:w => [0, 0]}
|
55
|
+
addop 'div', [0xF6], 6, {:w => [0, 0]}
|
56
|
+
addop 'enter', [0xC8], nil, :u16, :u8
|
57
|
+
addop 'idiv', [0xF6], 7, {:w => [0, 0]}
|
58
|
+
addop 'imul', [0xF6], 5, {:w => [0, 0]} # implicit eax, but different semantic from imul eax, ebx (the implicit version updates edx:eax)
|
59
|
+
addop 'imul', [0x0F, 0xAF], :mrm
|
60
|
+
addop 'imul', [0x69], :mrm, {:s => [0, 1]}, :i
|
61
|
+
addop 'inc', [0x40], :reg
|
62
|
+
addop 'inc', [0xFE], 0, {:w => [0, 0]}
|
63
|
+
addop 'int', [0xCC], nil, :imm_val3, :stopexec
|
64
|
+
addop 'int', [0xCD], nil, :u8
|
65
|
+
addop_macrotttn 'j', [0x70], nil, :setip, :i8
|
66
|
+
addop_macrotttn('j', [0x70], nil, :setip, :i8) { |o| o.name << '.i8' }
|
67
|
+
addop_macrotttn 'j', [0x0F, 0x80], nil, :setip, :i
|
68
|
+
addop_macrotttn('j', [0x0F, 0x80], nil, :setip, :i) { |o| o.name << '.i' }
|
69
|
+
addop 'jmp', [0xE9], nil, {:s => [0, 1]}, :setip, :i, :stopexec
|
70
|
+
addop 'jmp', [0xFF], 4, :setip, :stopexec
|
71
|
+
addop 'lea', [0x8D], :mrmA
|
72
|
+
addop 'leave', [0xC9]
|
73
|
+
addop_macrostr 'lods', [0xAC], :strop
|
74
|
+
addop 'loop', [0xE2], nil, :setip, :i8
|
75
|
+
addop 'loopz', [0xE1], nil, :setip, :i8
|
76
|
+
addop 'loope', [0xE1], nil, :setip, :i8
|
77
|
+
addop 'loopnz',[0xE0], nil, :setip, :i8
|
78
|
+
addop 'loopne',[0xE0], nil, :setip, :i8
|
79
|
+
addop 'mov', [0xA0], nil, {:w => [0, 0], :d => [0, 1]}, :reg_eax, :mrm_imm
|
80
|
+
addop('mov', [0x88], :mrmw,{:d => [0, 1]}) { |o| o.args.reverse! }
|
81
|
+
addop 'mov', [0xB0], :reg, {:w => [0, 3]}, :i, :unsigned_imm
|
82
|
+
addop 'mov', [0xC6], 0, {:w => [0, 0]}, :i, :unsigned_imm
|
83
|
+
addop_macrostr 'movs', [0xA4], :strop
|
84
|
+
addop 'movsx', [0x0F, 0xBE], :mrmw
|
85
|
+
addop 'movzx', [0x0F, 0xB6], :mrmw
|
86
|
+
addop 'mul', [0xF6], 4, {:w => [0, 0]}
|
87
|
+
addop 'neg', [0xF6], 3, {:w => [0, 0]}
|
88
|
+
addop 'nop', [0x90]
|
89
|
+
addop 'not', [0xF6], 2, {:w => [0, 0]}
|
90
|
+
addop_macro1 'or', 1, :unsigned_imm
|
91
|
+
addop 'pop', [0x58], :reg
|
92
|
+
addop 'pop', [0x8F], 0
|
93
|
+
addop 'push', [0x50], :reg
|
94
|
+
addop 'push', [0xFF], 6
|
95
|
+
addop 'push', [0x68], nil, {:s => [0, 1]}, :i, :unsigned_imm
|
96
|
+
addop 'ret', [0xC3], nil, :stopexec, :setip
|
97
|
+
addop 'ret', [0xC2], nil, :stopexec, :u16, :setip
|
98
|
+
addop_macro3 'rol', 0
|
99
|
+
addop_macro3 'ror', 1
|
100
|
+
addop_macro3 'sar', 7
|
101
|
+
addop_macro1 'sbb', 3
|
102
|
+
addop_macrostr 'scas', [0xAE], :stropz
|
103
|
+
addop_macrotttn('set', [0x0F, 0x90], 0) { |o| o.props[:argsz] = 8 }
|
104
|
+
addop_macrotttn('set', [0x0F, 0x90], :mrm) { |o| o.props[:argsz] = 8 ; o.args.reverse! } # :reg field is unused
|
105
|
+
addop_macro3 'shl', 4
|
106
|
+
addop_macro3 'sal', 6
|
107
|
+
addop('shld', [0x0F, 0xA4], :mrm, :u8) { |o| o.args[0], o.args[1] = o.args[1], o.args[0] }
|
108
|
+
addop('shld', [0x0F, 0xA5], :mrm, :reg_cl) { |o| o.args[0], o.args[1] = o.args[1], o.args[0] }
|
109
|
+
addop_macro3 'shr', 5
|
110
|
+
addop('shrd', [0x0F, 0xAC], :mrm, :u8) { |o| o.args[0], o.args[1] = o.args[1], o.args[0] }
|
111
|
+
addop('shrd', [0x0F, 0xAD], :mrm, :reg_cl) { |o| o.args[0], o.args[1] = o.args[1], o.args[0] }
|
112
|
+
addop_macrostr 'stos', [0xAA], :strop
|
113
|
+
addop_macro1 'sub', 5
|
114
|
+
addop 'test', [0x84], :mrmw
|
115
|
+
addop 'test', [0xA8], nil, {:w => [0, 0]}, :reg_eax, :i, :unsigned_imm
|
116
|
+
addop 'test', [0xF6], 0, {:w => [0, 0]}, :i, :unsigned_imm
|
117
|
+
addop 'xchg', [0x90], :reg, :reg_eax
|
118
|
+
addop('xchg', [0x90], :reg, :reg_eax) { |o| o.args.reverse! } # xchg eax, ebx == xchg ebx, eax)
|
119
|
+
addop 'xchg', [0x86], :mrmw
|
120
|
+
addop('xchg', [0x86], :mrmw) { |o| o.args.reverse! }
|
121
|
+
addop_macro1 'xor', 6, :unsigned_imm
|
122
|
+
end
|
123
|
+
|
124
|
+
def init_386_only
|
125
|
+
init_cpu_constants
|
126
|
+
|
127
|
+
addop 'aaa', [0x37]
|
128
|
+
addop 'aad', [0xD5, 0x0A]
|
129
|
+
addop 'aam', [0xD4, 0x0A]
|
130
|
+
addop 'aas', [0x3F]
|
131
|
+
addop('arpl', [0x63], :mrm) { |o| o.props[:argsz] = 16 ; o.args.reverse! }
|
132
|
+
addop 'bound', [0x62], :mrmA
|
133
|
+
addop 'bsf', [0x0F, 0xBC], :mrm
|
134
|
+
addop 'bsr', [0x0F, 0xBD], :mrm
|
135
|
+
addop_macro2 'bt' , 0
|
136
|
+
addop_macro2 'btc', 3
|
137
|
+
addop_macro2 'btr', 2
|
138
|
+
addop_macro2 'bts', 1
|
139
|
+
addop 'call', [0x9A], nil, :stopexec, :setip, :farptr, :saveip
|
140
|
+
addop 'callf', [0x9A], nil, :stopexec, :setip, :farptr, :saveip
|
141
|
+
addop 'callf', [0xFF], 3, :stopexec, :setip, :saveip
|
142
|
+
addop 'clc', [0xF8]
|
143
|
+
addop 'cld', [0xFC]
|
144
|
+
addop 'cli', [0xFA]
|
145
|
+
addop 'clts', [0x0F, 0x06]
|
146
|
+
addop 'cmc', [0xF5]
|
147
|
+
addop('cmpxchg',[0x0F, 0xB0], :mrmw) { |o| o.args.reverse! }
|
148
|
+
addop 'cpuid', [0x0F, 0xA2]
|
149
|
+
addop 'daa', [0x27]
|
150
|
+
addop 'das', [0x2F]
|
151
|
+
addop 'hlt', [0xF4], nil, :stopexec
|
152
|
+
addop 'in', [0xE4], nil, {:w => [0, 0]}, :reg_eax, :u8
|
153
|
+
addop 'in', [0xE4], nil, {:w => [0, 0]}, :u8
|
154
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}, :reg_eax, :reg_dx
|
155
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}, :reg_eax
|
156
|
+
addop 'in', [0xEC], nil, {:w => [0, 0]}
|
157
|
+
addop_macrostr 'ins', [0x6C], :strop
|
158
|
+
addop 'into', [0xCE]
|
159
|
+
addop 'invd', [0x0F, 0x08]
|
160
|
+
addop 'invlpg', [0x0F, 0x01, 7<<3], :modrmA
|
161
|
+
addop('iretd', [0xCF], nil, :stopexec, :setip) { |o| o.props[:opsz] = 32 }
|
162
|
+
addop_macroret 'iret', [0xCF]
|
163
|
+
addop('jcxz', [0xE3], nil, :setip, :i8) { |o| o.props[:adsz] = 16 }
|
164
|
+
addop('jecxz', [0xE3], nil, :setip, :i8) { |o| o.props[:adsz] = 32 }
|
165
|
+
addop 'jmp', [0xEA], nil, :farptr, :setip, :stopexec
|
166
|
+
addop 'jmpf', [0xEA], nil, :farptr, :setip, :stopexec
|
167
|
+
addop 'jmpf', [0xFF], 5, :stopexec, :setip # reg ?
|
168
|
+
addop 'lahf', [0x9F]
|
169
|
+
addop 'lar', [0x0F, 0x02], :mrm
|
170
|
+
addop 'lds', [0xC5], :mrmA
|
171
|
+
addop 'les', [0xC4], :mrmA
|
172
|
+
addop 'lfs', [0x0F, 0xB4], :mrmA
|
173
|
+
addop 'lgs', [0x0F, 0xB5], :mrmA
|
174
|
+
addop 'lgdt', [0x0F, 0x01], 2, :modrmA
|
175
|
+
addop 'lidt', [0x0F, 0x01, 3<<3], :modrmA
|
176
|
+
addop 'lldt', [0x0F, 0x00], 2, :modrmA
|
177
|
+
addop 'lmsw', [0x0F, 0x01], 6
|
178
|
+
# prefix addop 'lock', [0xF0]
|
179
|
+
addop 'lsl', [0x0F, 0x03], :mrm
|
180
|
+
addop 'lss', [0x0F, 0xB2], :mrmA
|
181
|
+
addop 'ltr', [0x0F, 0x00], 3
|
182
|
+
addop 'mov', [0x0F, 0x20, 0xC0], :reg, {:d => [1, 1], :eeec => [2, 3]}, :eeec
|
183
|
+
addop 'mov', [0x0F, 0x21, 0xC0], :reg, {:d => [1, 1], :eeed => [2, 3]}, :eeed
|
184
|
+
addop 'mov', [0x0F, 0x24, 0xC0], :reg, {:d => [1, 1], :eeet => [2, 3]}, :eeet
|
185
|
+
addop 'mov', [0x8C], 0, {:d => [0, 1], :seg3 => [1, 3]}, :seg3
|
186
|
+
addop 'movbe', [0x0F, 0x38, 0xF0], :mrm, { :d => [2, 0] }
|
187
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :u8, :reg_eax
|
188
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :reg_eax, :u8
|
189
|
+
addop 'out', [0xE6], nil, {:w => [0, 0]}, :u8
|
190
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_dx, :reg_eax
|
191
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_eax, :reg_dx
|
192
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}, :reg_eax # implicit arguments
|
193
|
+
addop 'out', [0xEE], nil, {:w => [0, 0]}
|
194
|
+
addop_macrostr 'outs', [0x6E], :strop
|
195
|
+
addop 'pop', [0x07], nil, {:seg2A => [0, 3]}, :seg2A
|
196
|
+
addop 'pop', [0x0F, 0x81], nil, {:seg3A => [1, 3]}, :seg3A
|
197
|
+
addop('popa', [0x61]) { |o| o.props[:opsz] = 16 }
|
198
|
+
addop('popad', [0x61]) { |o| o.props[:opsz] = 32 }
|
199
|
+
addop('popf', [0x9D]) { |o| o.props[:opsz] = 16 }
|
200
|
+
addop('popfd', [0x9D]) { |o| o.props[:opsz] = 32 }
|
201
|
+
addop 'push', [0x06], nil, {:seg2 => [0, 3]}, :seg2
|
202
|
+
addop 'push', [0x0F, 0x80], nil, {:seg3A => [1, 3]}, :seg3A
|
203
|
+
addop('pusha', [0x60]) { |o| o.props[:opsz] = 16 }
|
204
|
+
addop('pushad',[0x60]) { |o| o.props[:opsz] = 32 }
|
205
|
+
addop('pushf', [0x9C]) { |o| o.props[:opsz] = 16 }
|
206
|
+
addop('pushfd',[0x9C]) { |o| o.props[:opsz] = 32 }
|
207
|
+
addop_macro3 'rcl', 2
|
208
|
+
addop_macro3 'rcr', 3
|
209
|
+
addop 'rdmsr', [0x0F, 0x32]
|
210
|
+
addop 'rdpmc', [0x0F, 0x33]
|
211
|
+
addop 'rdtsc', [0x0F, 0x31], nil, :random
|
212
|
+
addop_macroret 'retf', [0xCB]
|
213
|
+
addop_macroret 'retf', [0xCA], :u16
|
214
|
+
addop 'rsm', [0x0F, 0xAA], nil, :stopexec
|
215
|
+
addop 'sahf', [0x9E]
|
216
|
+
addop 'sgdt', [0x0F, 0x01, 0<<3], :modrmA
|
217
|
+
addop 'sidt', [0x0F, 0x01, 1<<3], :modrmA
|
218
|
+
addop 'sldt', [0x0F, 0x00], 0
|
219
|
+
addop 'smsw', [0x0F, 0x01], 4
|
220
|
+
addop 'stc', [0xF9]
|
221
|
+
addop 'std', [0xFD]
|
222
|
+
addop 'sti', [0xFB]
|
223
|
+
addop 'str', [0x0F, 0x00], 1
|
224
|
+
addop 'test', [0xF6], 1, {:w => [0, 0]}, :i, :unsigned_imm # undocumented alias to F6/0
|
225
|
+
addop 'ud2', [0x0F, 0x0B]
|
226
|
+
addop 'verr', [0x0F, 0x00], 4
|
227
|
+
addop 'verw', [0x0F, 0x00], 5
|
228
|
+
addop 'wait', [0x9B]
|
229
|
+
addop 'wbinvd',[0x0F, 0x09]
|
230
|
+
addop 'wrmsr', [0x0F, 0x30]
|
231
|
+
addop('xadd', [0x0F, 0xC0], :mrmw) { |o| o.args.reverse! }
|
232
|
+
addop 'xlat', [0xD7]
|
233
|
+
|
234
|
+
# pfx: addrsz = 0x67, lock = 0xF0, opsz = 0x66, repnz = 0xF2, rep/repz = 0xF3
|
235
|
+
# cs/nojmp = 0x2E, ds/jmp = 0x3E, es = 0x26, fs = 0x64, gs = 0x65, ss = 0x36
|
236
|
+
|
237
|
+
# undocumented opcodes
|
238
|
+
addop 'aam', [0xD4], nil, :u8
|
239
|
+
addop 'aad', [0xD5], nil, :u8
|
240
|
+
addop 'setalc',[0xD6]
|
241
|
+
addop 'salc', [0xD6]
|
242
|
+
addop 'icebp', [0xF1]
|
243
|
+
#addop 'loadall',[0x0F, 0x07] # conflict with syscall
|
244
|
+
addop 'ud0', [0x0F, 0xFF] # amd
|
245
|
+
addop 'ud2', [0x0F, 0xB9], :mrm
|
246
|
+
#addop 'umov', [0x0F, 0x10], :mrmw, {:d => [1, 1]} # conflicts with movups/movhlps
|
247
|
+
end
|
248
|
+
|
249
|
+
def init_387_only
|
250
|
+
init_cpu_constants
|
251
|
+
|
252
|
+
addop 'f2xm1', [0xD9, 0xF0]
|
253
|
+
addop 'fabs', [0xD9, 0xE1]
|
254
|
+
addop_macrofpu1 'fadd', 0
|
255
|
+
addop 'faddp', [0xDE, 0xC0], :regfp
|
256
|
+
addop 'faddp', [0xDE, 0xC1]
|
257
|
+
addop('fbld', [0xDF, 4<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 80 }
|
258
|
+
addop('fbstp', [0xDF, 6<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 80 }
|
259
|
+
addop 'fchs', [0xD9, 0xE0], nil, :regfp0
|
260
|
+
addop 'fnclex', [0xDB, 0xE2]
|
261
|
+
addop_macrofpu1 'fcom', 2
|
262
|
+
addop_macrofpu1 'fcomp', 3
|
263
|
+
addop 'fcompp',[0xDE, 0xD9]
|
264
|
+
addop 'fcomip',[0xDF, 0xF0], :regfp
|
265
|
+
addop 'fcos', [0xD9, 0xFF], nil, :regfp0
|
266
|
+
addop 'fdecstp', [0xD9, 0xF6]
|
267
|
+
addop_macrofpu1 'fdiv', 6
|
268
|
+
addop_macrofpu1 'fdivr', 7
|
269
|
+
addop 'fdivp', [0xDE, 0xF8], :regfp
|
270
|
+
addop 'fdivp', [0xDE, 0xF9]
|
271
|
+
addop 'fdivrp',[0xDE, 0xF0], :regfp
|
272
|
+
addop 'fdivrp',[0xDE, 0xF1]
|
273
|
+
addop 'ffree', [0xDD, 0xC0], nil, {:regfp => [1, 0]}, :regfp
|
274
|
+
addop_macrofpu2 'fiadd', 0
|
275
|
+
addop_macrofpu2 'fimul', 1
|
276
|
+
addop_macrofpu2 'ficom', 2
|
277
|
+
addop_macrofpu2 'ficomp',3
|
278
|
+
addop_macrofpu2 'fisub', 4
|
279
|
+
addop_macrofpu2 'fisubr',5
|
280
|
+
addop_macrofpu2 'fidiv', 6
|
281
|
+
addop_macrofpu2 'fidivr',7
|
282
|
+
addop 'fincstp', [0xD9, 0xF7]
|
283
|
+
addop 'fninit', [0xDB, 0xE3]
|
284
|
+
addop_macrofpu2 'fist', 2, 1
|
285
|
+
addop_macrofpu3 'fild', 0
|
286
|
+
addop_macrofpu3 'fistp',3
|
287
|
+
addop('fld', [0xD9, 0<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 32 }
|
288
|
+
addop('fld', [0xDD, 0<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 64 }
|
289
|
+
addop('fld', [0xDB, 5<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 80 }
|
290
|
+
addop 'fld', [0xD9, 0xC0], :regfp
|
291
|
+
|
292
|
+
addop('fldcw', [0xD9, 5<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
293
|
+
addop 'fldenv', [0xD9, 4<<3], :modrmA
|
294
|
+
addop 'fld1', [0xD9, 0xE8]
|
295
|
+
addop 'fldl2t', [0xD9, 0xE9]
|
296
|
+
addop 'fldl2e', [0xD9, 0xEA]
|
297
|
+
addop 'fldpi', [0xD9, 0xEB]
|
298
|
+
addop 'fldlg2', [0xD9, 0xEC]
|
299
|
+
addop 'fldln2', [0xD9, 0xED]
|
300
|
+
addop 'fldz', [0xD9, 0xEE]
|
301
|
+
addop_macrofpu1 'fmul', 1
|
302
|
+
addop 'fmulp', [0xDE, 0xC8], :regfp
|
303
|
+
addop 'fmulp', [0xDE, 0xC9]
|
304
|
+
addop 'fnop', [0xD9, 0xD0]
|
305
|
+
addop 'fpatan', [0xD9, 0xF3]
|
306
|
+
addop 'fprem', [0xD9, 0xF8]
|
307
|
+
addop 'fprem1', [0xD9, 0xF5]
|
308
|
+
addop 'fptan', [0xD9, 0xF2]
|
309
|
+
addop 'frndint',[0xD9, 0xFC]
|
310
|
+
addop 'frstor', [0xDD, 4<<3], :modrmA
|
311
|
+
addop 'fnsave', [0xDD, 6<<3], :modrmA
|
312
|
+
addop('fnstcw', [0xD9, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
313
|
+
addop 'fnstenv',[0xD9, 6<<3], :modrmA
|
314
|
+
addop 'fnstsw', [0xDF, 0xE0]
|
315
|
+
addop('fnstsw', [0xDD, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
316
|
+
addop 'fscale', [0xD9, 0xFD]
|
317
|
+
addop 'fsin', [0xD9, 0xFE]
|
318
|
+
addop 'fsincos',[0xD9, 0xFB]
|
319
|
+
addop 'fsqrt', [0xD9, 0xFA]
|
320
|
+
addop('fst', [0xD9, 2<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 32 }
|
321
|
+
addop('fst', [0xDD, 2<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 64 }
|
322
|
+
addop 'fst', [0xD9, 0xD0], :regfp
|
323
|
+
addop('fstp', [0xD9, 3<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 32 }
|
324
|
+
addop('fstp', [0xDD, 3<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 64 }
|
325
|
+
addop('fstp', [0xDB, 7<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 80 }
|
326
|
+
addop 'fstp', [0xDD, 0xD8], :regfp
|
327
|
+
addop_macrofpu1 'fsub', 4
|
328
|
+
addop 'fsubp', [0xDE, 0xE8], :regfp
|
329
|
+
addop 'fsubp', [0xDE, 0xE9]
|
330
|
+
addop_macrofpu1 'fsubp', 5
|
331
|
+
addop 'fsubrp', [0xDE, 0xE0], :regfp
|
332
|
+
addop 'fsubrp', [0xDE, 0xE1]
|
333
|
+
addop 'ftst', [0xD9, 0xE4]
|
334
|
+
addop 'fucom', [0xDD, 0xE0], :regfp
|
335
|
+
addop 'fucomp', [0xDD, 0xE8], :regfp
|
336
|
+
addop 'fucompp',[0xDA, 0xE9]
|
337
|
+
addop 'fucomi', [0xDB, 0xE8], :regfp
|
338
|
+
addop 'fxam', [0xD9, 0xE5]
|
339
|
+
addop 'fxch', [0xD9, 0xC8], :regfp
|
340
|
+
addop 'fxtract',[0xD9, 0xF4]
|
341
|
+
addop 'fyl2x', [0xD9, 0xF1]
|
342
|
+
addop 'fyl2xp1',[0xD9, 0xF9]
|
343
|
+
# fwait prefix
|
344
|
+
addop 'fclex', [0x9B, 0xDB, 0xE2]
|
345
|
+
addop 'finit', [0x9B, 0xDB, 0xE3]
|
346
|
+
addop 'fsave', [0x9B, 0xDD, 6<<3], :modrmA
|
347
|
+
addop('fstcw', [0x9B, 0xD9, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
348
|
+
addop 'fstenv', [0x9B, 0xD9, 6<<3], :modrmA
|
349
|
+
addop 'fstsw', [0x9B, 0xDF, 0xE0]
|
350
|
+
addop('fstsw', [0x9B, 0xDD, 7<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
351
|
+
addop 'fwait', [0x9B]
|
352
|
+
end
|
353
|
+
|
354
|
+
def init_486_only
|
355
|
+
init_cpu_constants
|
356
|
+
end
|
357
|
+
|
358
|
+
def init_pentium_only
|
359
|
+
init_cpu_constants
|
360
|
+
|
361
|
+
addop('cmpxchg8b', [0x0F, 0xC7], 1) { |o| o.props[:opsz] = 32 ; o.props[:argsz] = 64 }
|
362
|
+
# lock cmpxchg8b eax
|
363
|
+
#addop 'f00fbug', [0xF0, 0x0F, 0xC7, 0xC8]
|
364
|
+
|
365
|
+
# mmx
|
366
|
+
addop 'emms', [0x0F, 0x77]
|
367
|
+
addop('movd', [0x0F, 0x6E], :mrmmmx, {:d => [1, 4]}) { |o| o.args = [:modrm, :regmmx] ; o.props[:opsz] = o.props[:argsz] = 32 }
|
368
|
+
addop('movq', [0x0F, 0x6F], :mrmmmx, {:d => [1, 4]}) { |o| o.props[:argsz] = 64 }
|
369
|
+
addop 'packssdw', [0x0F, 0x6B], :mrmmmx
|
370
|
+
addop 'packsswb', [0x0F, 0x63], :mrmmmx
|
371
|
+
addop 'packuswb', [0x0F, 0x67], :mrmmmx
|
372
|
+
addop_macrogg 0..2, 'padd', [0x0F, 0xFC], :mrmmmx
|
373
|
+
addop_macrogg 0..1, 'padds', [0x0F, 0xEC], :mrmmmx
|
374
|
+
addop_macrogg 0..1, 'paddus',[0x0F, 0xDC], :mrmmmx
|
375
|
+
addop 'pand', [0x0F, 0xDB], :mrmmmx
|
376
|
+
addop 'pandn', [0x0F, 0xDF], :mrmmmx
|
377
|
+
addop_macrogg 0..2, 'pcmpeq',[0x0F, 0x74], :mrmmmx
|
378
|
+
addop_macrogg 0..2, 'pcmpgt',[0x0F, 0x64], :mrmmmx
|
379
|
+
addop 'pmaddwd', [0x0F, 0xF5], :mrmmmx
|
380
|
+
addop 'pmulhuw', [0x0F, 0xE4], :mrmmmx
|
381
|
+
addop 'pmulhw',[0x0F, 0xE5], :mrmmmx
|
382
|
+
addop 'pmullw',[0x0F, 0xD5], :mrmmmx
|
383
|
+
addop 'por', [0x0F, 0xEB], :mrmmmx
|
384
|
+
[[1..3, 'psll', 3], [1..2, 'psra', 2], [1..3, 'psrl', 1]].each { |ggrng, name, val|
|
385
|
+
addop_macrogg ggrng, name, [0x0F, 0xC0 | (val << 4)], :mrmmmx
|
386
|
+
addop_macrogg ggrng, name, [0x0F, 0x70, 0xC0 | (val << 4)], nil, {:regmmx => [2, 0]}, :regmmx, :u8
|
387
|
+
}
|
388
|
+
addop_macrogg 0..2, 'psub', [0x0F, 0xF8], :mrmmmx
|
389
|
+
addop_macrogg 0..1, 'psubs', [0x0F, 0xE8], :mrmmmx
|
390
|
+
addop_macrogg 0..1, 'psubus',[0x0F, 0xD8], :mrmmmx
|
391
|
+
addop_macrogg 1..3, 'punpckh', [0x0F, 0x68], :mrmmmx
|
392
|
+
addop_macrogg 1..3, 'punpckl', [0x0F, 0x60], :mrmmmx
|
393
|
+
addop 'pxor', [0x0F, 0xEF], :mrmmmx
|
394
|
+
end
|
395
|
+
|
396
|
+
def init_p6_only
|
397
|
+
addop_macrotttn 'cmov', [0x0F, 0x40], :mrm
|
398
|
+
|
399
|
+
%w{b e be u}.each_with_index { |tt, i|
|
400
|
+
addop 'fcmov' + tt, [0xDA, 0xC0 | (i << 3)], :regfp
|
401
|
+
addop 'fcmovn'+ tt, [0xDB, 0xC0 | (i << 3)], :regfp
|
402
|
+
}
|
403
|
+
addop 'fcomi', [0xDB, 0xF0], :regfp
|
404
|
+
addop('fxrstor', [0x0F, 0xAE, 1<<3], :modrmA) { |o| o.props[:argsz] = 512*8 }
|
405
|
+
addop('fxsave', [0x0F, 0xAE, 0<<3], :modrmA) { |o| o.props[:argsz] = 512*8 }
|
406
|
+
addop 'sysenter',[0x0F, 0x34]
|
407
|
+
addop 'sysexit', [0x0F, 0x35]
|
408
|
+
|
409
|
+
addop 'syscall', [0x0F, 0x05] # AMD
|
410
|
+
addop_macroret 'sysret', [0x0F, 0x07] # AMD
|
411
|
+
end
|
412
|
+
|
413
|
+
def init_3dnow_only
|
414
|
+
init_cpu_constants
|
415
|
+
|
416
|
+
[['pavgusb', 0xBF], ['pfadd', 0x9E], ['pfsub', 0x9A],
|
417
|
+
['pfsubr', 0xAA], ['pfacc', 0xAE], ['pfcmpge', 0x90],
|
418
|
+
['pfcmpgt', 0xA0], ['fpcmpeq', 0xB0], ['pfmin', 0x94],
|
419
|
+
['pfmax', 0xA4], ['pi2fd', 0x0D], ['pf2id', 0x1D],
|
420
|
+
['pfrcp', 0x96], ['pfrsqrt', 0x97], ['pfmul', 0xB4],
|
421
|
+
['pfrcpit1', 0xA6], ['pfrsqit1', 0xA7], ['pfrcpit2', 0xB6],
|
422
|
+
['pmulhrw', 0xB7]].each { |str, bin|
|
423
|
+
addop str, [0x0F, 0x0F, bin], :mrmmmx
|
424
|
+
}
|
425
|
+
# 3dnow prefix fallback
|
426
|
+
addop '3dnow', [0x0F, 0x0F], :mrmmmx, :u8
|
427
|
+
|
428
|
+
addop 'femms', [0x0F, 0x0E]
|
429
|
+
addop 'prefetch', [0x0F, 0x0D, 0<<3], :modrmA
|
430
|
+
addop 'prefetchw', [0x0F, 0x0D, 1<<3], :modrmA
|
431
|
+
end
|
432
|
+
|
433
|
+
def init_sse_only
|
434
|
+
init_cpu_constants
|
435
|
+
|
436
|
+
addop_macrossps 'addps', [0x0F, 0x58], :mrmxmm
|
437
|
+
addop 'andnps', [0x0F, 0x55], :mrmxmm
|
438
|
+
addop 'andps', [0x0F, 0x54], :mrmxmm
|
439
|
+
addop_macrossps 'cmpps', [0x0F, 0xC2], :mrmxmm, :u8
|
440
|
+
addop 'comiss', [0x0F, 0x2F], :mrmxmm
|
441
|
+
|
442
|
+
addop('cvtpi2ps', [0x0F, 0x2A], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrmmmx }
|
443
|
+
addop('cvtps2pi', [0x0F, 0x2D], :mrmmmx) { |o| o.args[o.args.index(:modrmmmx)] = :modrmxmm }
|
444
|
+
addop('cvtsi2ss', [0x0F, 0x2A], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrm ; o.props[:needpfx] = 0xF3 }
|
445
|
+
addop('cvtss2si', [0x0F, 0x2D], :mrm) { |o| o.args[o.args.index(:modrm)] = :modrmxmm ; o.props[:needpfx] = 0xF3 }
|
446
|
+
addop('cvttps2pi',[0x0F, 0x2C], :mrmmmx) { |o| o.args[o.args.index(:modrmmmx)] = :modrmxmm }
|
447
|
+
addop('cvttss2si',[0x0F, 0x2C], :mrm) { |o| o.args[o.args.index(:modrm)] = :modrmxmm ; o.props[:needpfx] = 0xF3 }
|
448
|
+
|
449
|
+
addop_macrossps 'divps', [0x0F, 0x5E], :mrmxmm
|
450
|
+
addop 'ldmxcsr', [0x0F, 0xAE, 2<<3], :modrmA
|
451
|
+
addop_macrossps 'maxps', [0x0F, 0x5F], :mrmxmm
|
452
|
+
addop_macrossps 'minps', [0x0F, 0x5D], :mrmxmm
|
453
|
+
addop 'movaps', [0x0F, 0x28], :mrmxmm, {:d => [1, 0]}
|
454
|
+
addop 'movhlps', [0x0F, 0x12], :mrmxmm, :modrmR
|
455
|
+
addop 'movlps', [0x0F, 0x12], :mrmxmm, {:d => [1, 0]}, :modrmA
|
456
|
+
addop 'movlhps', [0x0F, 0x16], :mrmxmm, :modrmR
|
457
|
+
addop 'movhps', [0x0F, 0x16], :mrmxmm, {:d => [1, 0]}, :modrmA
|
458
|
+
addop 'movmskps',[0x0F, 0x50, 0xC0], nil, {:reg => [2, 3], :regxmm => [2, 0]}, :regxmm, :reg
|
459
|
+
addop('movss', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0xF3 }
|
460
|
+
addop 'movups', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}
|
461
|
+
addop_macrossps 'mulps', [0x0F, 0x59], :mrmxmm
|
462
|
+
addop 'orps', [0x0F, 0x56], :mrmxmm
|
463
|
+
addop_macrossps 'rcpps', [0x0F, 0x53], :mrmxmm
|
464
|
+
addop_macrossps 'rsqrtps',[0x0F, 0x52], :mrmxmm
|
465
|
+
addop 'shufps', [0x0F, 0xC6], :mrmxmm, :u8
|
466
|
+
addop_macrossps 'sqrtps', [0x0F, 0x51], :mrmxmm
|
467
|
+
addop 'stmxcsr', [0x0F, 0xAE, 3<<3], :modrmA
|
468
|
+
addop_macrossps 'subps', [0x0F, 0x5C], :mrmxmm
|
469
|
+
addop 'ucomiss', [0x0F, 0x2E], :mrmxmm
|
470
|
+
addop 'unpckhps',[0x0F, 0x15], :mrmxmm
|
471
|
+
addop 'unpcklps',[0x0F, 0x14], :mrmxmm
|
472
|
+
addop 'xorps', [0x0F, 0x57], :mrmxmm
|
473
|
+
|
474
|
+
# integer instrs, mmx only
|
475
|
+
addop 'pavgb', [0x0F, 0xE0], :mrmmmx
|
476
|
+
addop 'pavgw', [0x0F, 0xE3], :mrmmmx
|
477
|
+
addop 'pextrw', [0x0F, 0xC5, 0xC0], nil, {:reg => [2, 3], :regmmx => [2, 0]}, :reg, :regmmx, :u8
|
478
|
+
addop 'pinsrw', [0x0F, 0xC4, 0x00], nil, {:modrm => [2, 0], :regmmx => [2, 3]}, :modrm, :regmmx, :u8
|
479
|
+
addop 'pmaxsw', [0x0F, 0xEE], :mrmmmx
|
480
|
+
addop 'pmaxub', [0x0F, 0xDE], :mrmmmx
|
481
|
+
addop 'pminsw', [0x0F, 0xEA], :mrmmmx
|
482
|
+
addop 'pminub', [0x0F, 0xDA], :mrmmmx
|
483
|
+
addop 'pmovmskb',[0x0F, 0xD7, 0xC0], nil, {:reg => [2, 3], :regmmx => [2, 0]}, :reg, :regmmx
|
484
|
+
addop 'psadbw', [0x0F, 0xF6], :mrmmmx
|
485
|
+
addop 'pshufw', [0x0F, 0x70], :mrmmmx, :u8
|
486
|
+
|
487
|
+
addop 'maskmovq',[0x0F, 0xF7], :mrmmmx, :modrmR
|
488
|
+
addop('movntq', [0x0F, 0xE7], :mrmmmx) { |o| o.args.reverse! }
|
489
|
+
addop('movntps', [0x0F, 0x2B], :mrmxmm) { |o| o.args.reverse! }
|
490
|
+
addop 'prefetcht0', [0x0F, 0x18, 1<<3], :modrmA
|
491
|
+
addop 'prefetcht1', [0x0F, 0x18, 2<<3], :modrmA
|
492
|
+
addop 'prefetcht2', [0x0F, 0x18, 3<<3], :modrmA
|
493
|
+
addop 'prefetchnta',[0x0F, 0x18, 0<<3], :modrmA
|
494
|
+
addop 'sfence', [0x0F, 0xAE, 0xF8]
|
495
|
+
|
496
|
+
# the whole row of prefetch is actually nops
|
497
|
+
addop 'nop', [0x0F, 0x1C], :mrmw, :d => [1, 1] # incl. official version = 0f1f mrm
|
498
|
+
addop 'nop_8', [0x0F, 0x18], :mrmw, :d => [1, 1]
|
499
|
+
addop 'nop_d', [0x0F, 0x0D], :mrm
|
500
|
+
addop 'nop', [0x0F, 0x1C], 0 # official asm syntax is 'nop [eax]'
|
501
|
+
end
|
502
|
+
|
503
|
+
def init_sse2_only
|
504
|
+
init_cpu_constants
|
505
|
+
|
506
|
+
@opcode_list.each { |o| o.props[:xmmx] = true if o.fields[:regmmx] and o.name !~ /^(?:mov(?:nt)?q|pshufw|cvt.*)$/ }
|
507
|
+
|
508
|
+
# mirror of the init_sse part
|
509
|
+
addop_macrosdpd 'addpd', [0x0F, 0x58], :mrmxmm
|
510
|
+
addop('andnpd', [0x0F, 0x55], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
511
|
+
addop('andpd', [0x0F, 0x54], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
512
|
+
addop_macrosdpd 'cmppd', [0x0F, 0xC2], :mrmxmm, :u8
|
513
|
+
addop('comisd', [0x0F, 0x2F], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
514
|
+
|
515
|
+
addop('cvtpi2pd', [0x0F, 0x2A], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrmmmx ; o.props[:needpfx] = 0x66 }
|
516
|
+
addop('cvtpd2pi', [0x0F, 0x2D], :mrmmmx) { |o| o.args[o.args.index(:modrmmmx)] = :modrmxmm ; o.props[:needpfx] = 0x66 }
|
517
|
+
addop('cvtsi2sd', [0x0F, 0x2A], :mrmxmm) { |o| o.args[o.args.index(:modrmxmm)] = :modrm ; o.props[:needpfx] = 0xF2 }
|
518
|
+
addop('cvtsd2si', [0x0F, 0x2D], :mrm ) { |o| o.args[o.args.index(:modrm )] = :modrmxmm ; o.props[:needpfx] = 0xF2 }
|
519
|
+
addop('cvttpd2pi',[0x0F, 0x2C], :mrmmmx) { |o| o.args[o.args.index(:modrmmmx)] = :modrmxmm ; o.props[:needpfx] = 0x66 }
|
520
|
+
addop('cvttsd2si',[0x0F, 0x2C], :mrm ) { |o| o.args[o.args.index(:modrm )] = :modrmxmm ; o.props[:needpfx] = 0xF2 }
|
521
|
+
|
522
|
+
addop('cvtpd2ps', [0x0F, 0x5A], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
523
|
+
addop('cvtps2pd', [0x0F, 0x5A], :mrmxmm)
|
524
|
+
addop('cvtsd2ss', [0x0F, 0x5A], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
525
|
+
addop('cvtss2sd', [0x0F, 0x5A], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
526
|
+
|
527
|
+
addop('cvtpd2dq', [0x0F, 0xE6], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
528
|
+
addop('cvttpd2dq',[0x0F, 0xE6], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
529
|
+
addop('cvtdq2pd', [0x0F, 0xE6], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
530
|
+
addop('cvtps2dq', [0x0F, 0x5B], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
531
|
+
addop('cvttps2dq',[0x0F, 0x5B], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
532
|
+
addop('cvtdq2ps', [0x0F, 0x5B], :mrmxmm)
|
533
|
+
|
534
|
+
addop_macrosdpd 'divpd', [0x0F, 0x5E], :mrmxmm
|
535
|
+
addop_macrosdpd 'maxpd', [0x0F, 0x5F], :mrmxmm
|
536
|
+
addop_macrosdpd 'minpd', [0x0F, 0x5D], :mrmxmm
|
537
|
+
addop('movapd', [0x0F, 0x28], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0x66 }
|
538
|
+
|
539
|
+
addop('movlpd', [0x0F, 0x12], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0x66 }
|
540
|
+
addop('movhpd', [0x0F, 0x16], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0x66 }
|
541
|
+
|
542
|
+
addop('movmskpd',[0x0F, 0x50, 0xC0], nil, {:reg => [2, 3], :regxmm => [2, 0]}, :regxmm, :reg) { |o| o.props[:needpfx] = 0x66 }
|
543
|
+
addop('movsd', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0xF2 }
|
544
|
+
addop('movupd', [0x0F, 0x10], :mrmxmm, {:d => [1, 0]}) { |o| o.props[:needpfx] = 0x66 }
|
545
|
+
addop_macrosdpd 'mulpd', [0x0F, 0x59], :mrmxmm
|
546
|
+
addop('orpd', [0x0F, 0x56], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
547
|
+
addop('shufpd', [0x0F, 0xC6], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
548
|
+
addop_macrosdpd 'sqrtpd', [0x0F, 0x51], :mrmxmm
|
549
|
+
addop_macrosdpd 'subpd', [0x0F, 0x5C], :mrmxmm
|
550
|
+
addop('ucomisd', [0x0F, 0x2E], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
551
|
+
addop('unpckhpd',[0x0F, 0x15], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
552
|
+
addop('unpcklpd',[0x0F, 0x14], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
553
|
+
addop('xorpd', [0x0F, 0x57], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
554
|
+
|
555
|
+
addop('movdqa', [0x0F, 0x6F], :mrmxmm, {:d => [1, 4]}) { |o| o.props[:needpfx] = 0x66 }
|
556
|
+
addop('movdqu', [0x0F, 0x6F], :mrmxmm, {:d => [1, 4]}) { |o| o.props[:needpfx] = 0xF3 }
|
557
|
+
addop('movq2dq', [0x0F, 0xD6], :mrmxmm, :modrmR) { |o| o.args[o.args.index(:modrmxmm)] = :modrmmmx ; o.props[:needpfx] = 0xF3 }
|
558
|
+
addop('movdq2q', [0x0F, 0xD6], :mrmmmx, :modrmR) { |o| o.args[o.args.index(:modrmmmx)] = :modrmxmm ; o.props[:needpfx] = 0xF2 }
|
559
|
+
addop('movq', [0x0F, 0x7E], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 ; o.props[:argsz] = 128 }
|
560
|
+
addop('movq', [0x0F, 0xD6], :mrmxmm) { |o| o.args.reverse! ; o.props[:needpfx] = 0x66 ; o.props[:argsz] = 128 }
|
561
|
+
|
562
|
+
addop 'paddq', [0x0F, 0xD4], :mrmmmx, :xmmx
|
563
|
+
addop 'pmuludq', [0x0F, 0xF4], :mrmmmx, :xmmx
|
564
|
+
addop('pshuflw', [0x0F, 0x70], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0xF2 }
|
565
|
+
addop('pshufhw', [0x0F, 0x70], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0xF3 }
|
566
|
+
addop('pshufd', [0x0F, 0x70], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
567
|
+
addop('pslldq', [0x0F, 0x73, 0xF8], nil, {:regxmm => [2, 0]}, :regxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
568
|
+
addop('psrldq', [0x0F, 0x73, 0xD8], nil, {:regxmm => [2, 0]}, :regxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
569
|
+
addop 'psubq', [0x0F, 0xFB], :mrmmmx, :xmmx
|
570
|
+
addop('punpckhqdq', [0x0F, 0x6D], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
571
|
+
addop('punpcklqdq', [0x0F, 0x6C], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
572
|
+
|
573
|
+
addop('clflush', [0x0F, 0xAE, 7<<3], :modrmA) { |o| o.props[:argsz] = 8 }
|
574
|
+
addop('maskmovdqu', [0x0F, 0xF7], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
575
|
+
addop('movntpd', [0x0F, 0x2B], :mrmxmm) { |o| o.args.reverse! ; o.props[:needpfx] = 0x66 }
|
576
|
+
addop('movntdq', [0x0F, 0xE7], :mrmxmm) { |o| o.args.reverse! ; o.props[:needpfx] = 0x66 }
|
577
|
+
addop('movnti', [0x0F, 0xC3], :mrm) { |o| o.args.reverse! }
|
578
|
+
addop('pause', [0x90]) { |o| o.props[:needpfx] = 0xF3 }
|
579
|
+
addop 'lfence', [0x0F, 0xAE, 0xE8]
|
580
|
+
addop 'mfence', [0x0F, 0xAE, 0xF0]
|
581
|
+
end
|
582
|
+
|
583
|
+
def init_sse3_only
|
584
|
+
init_cpu_constants
|
585
|
+
|
586
|
+
addop('addsubpd', [0x0F, 0xD0], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
587
|
+
addop('addsubps', [0x0F, 0xD0], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
588
|
+
addop('haddpd', [0x0F, 0x7C], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
589
|
+
addop('haddps', [0x0F, 0x7C], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
590
|
+
addop('hsubpd', [0x0F, 0x7D], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
591
|
+
addop('hsubps', [0x0F, 0x7D], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
592
|
+
|
593
|
+
addop 'monitor', [0x0F, 0x01, 0xC8]
|
594
|
+
addop 'mwait', [0x0F, 0x01, 0xC9]
|
595
|
+
|
596
|
+
addop('fisttp', [0xDF, 1<<3], :modrmA) { |o| o.props[:argsz] = 16 }
|
597
|
+
addop('fisttp', [0xDB, 1<<3], :modrmA) { |o| o.props[:argsz] = 32 }
|
598
|
+
addop('fisttp', [0xDD, 1<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
599
|
+
addop('lddqu', [0x0F, 0xF0], :mrmxmm, :modrmA) { |o| o.args[o.args.index(:modrmxmm)] = :modrm ; o.props[:needpfx] = 0xF2 }
|
600
|
+
addop('movddup', [0x0F, 0x12], :mrmxmm) { |o| o.props[:needpfx] = 0xF2 }
|
601
|
+
addop('movshdup', [0x0F, 0x16], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
602
|
+
addop('movsldup', [0x0F, 0x12], :mrmxmm) { |o| o.props[:needpfx] = 0xF3 }
|
603
|
+
end
|
604
|
+
|
605
|
+
def init_ssse3_only
|
606
|
+
init_cpu_constants
|
607
|
+
|
608
|
+
addop_macrogg 0..2, 'pabs', [0x0F, 0x38, 0x1C], :mrmmmx, :xmmx
|
609
|
+
addop 'palignr', [0x0F, 0x3A, 0x0F], :mrmmmx, :u8, :xmmx
|
610
|
+
addop 'phaddd', [0x0F, 0x38, 0x02], :mrmmmx, :xmmx
|
611
|
+
addop 'phaddsw', [0x0F, 0x38, 0x03], :mrmmmx, :xmmx
|
612
|
+
addop 'phaddw', [0x0F, 0x38, 0x01], :mrmmmx, :xmmx
|
613
|
+
addop 'phsubd', [0x0F, 0x38, 0x06], :mrmmmx, :xmmx
|
614
|
+
addop 'phsubsw', [0x0F, 0x38, 0x07], :mrmmmx, :xmmx
|
615
|
+
addop 'phsubw', [0x0F, 0x38, 0x05], :mrmmmx, :xmmx
|
616
|
+
addop 'pmaddubsw',[0x0F, 0x38, 0x04], :mrmmmx, :xmmx
|
617
|
+
addop 'pmulhrsw', [0x0F, 0x38, 0x0B], :mrmmmx, :xmmx
|
618
|
+
addop 'pshufb', [0x0F, 0x38, 0x00], :mrmmmx, :xmmx
|
619
|
+
addop_macrogg 0..2, 'psignb', [0x0F, 0x38, 0x80], :mrmmmx, :xmmx
|
620
|
+
end
|
621
|
+
|
622
|
+
def init_aesni_only
|
623
|
+
init_cpu_constants
|
624
|
+
|
625
|
+
addop('aesdec', [0x0F, 0x38, 0xDE], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
626
|
+
addop('aesdeclast',[0x0F, 0x38, 0xDF], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
627
|
+
addop('aesenc', [0x0F, 0x38, 0xDC], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
628
|
+
addop('aesenclast',[0x0F, 0x38, 0xDD], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
629
|
+
addop('aesimc', [0x0F, 0x38, 0xDB], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
630
|
+
addop('aeskeygenassist', [0x0F, 0x3A, 0xDF], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
631
|
+
|
632
|
+
addop('pclmulqdq', [0x0F, 0x3A, 0x44], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
633
|
+
end
|
634
|
+
|
635
|
+
def init_vmx_only
|
636
|
+
init_cpu_constants
|
637
|
+
|
638
|
+
addop 'vmcall', [0x0F, 0x01, 0xC1]
|
639
|
+
addop 'vmlaunch', [0x0F, 0x01, 0xC2]
|
640
|
+
addop 'vmresume', [0x0F, 0x01, 0xC3]
|
641
|
+
addop 'vmxoff', [0x0F, 0x01, 0xC4]
|
642
|
+
addop 'vmread', [0x0F, 0x78], :mrm
|
643
|
+
addop 'vmwrite', [0x0F, 0x79], :mrm
|
644
|
+
addop('vmclear', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0x66 }
|
645
|
+
addop('vmxon', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0xF3 }
|
646
|
+
addop('vmptrld', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
647
|
+
addop('vmptrrst', [0x0F, 0xC7, 7<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
648
|
+
addop('invept', [0x0F, 0x38, 0x80], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
649
|
+
addop('invvpid', [0x0F, 0x38, 0x81], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
650
|
+
|
651
|
+
addop 'getsec', [0x0F, 0x37]
|
652
|
+
|
653
|
+
addop 'xgetbv', [0x0F, 0x01, 0xD0]
|
654
|
+
addop 'xsetbv', [0x0F, 0x01, 0xD1]
|
655
|
+
addop 'rdtscp', [0x0F, 0x01, 0xF9]
|
656
|
+
addop 'xrstor', [0x0F, 0xAE, 5<<3], :modrmA
|
657
|
+
addop 'xsave', [0x0F, 0xAE, 4<<3], :modrmA
|
658
|
+
end
|
659
|
+
|
660
|
+
def init_sse41_only
|
661
|
+
init_cpu_constants
|
662
|
+
|
663
|
+
addop('blendpd', [0x0F, 0x3A, 0x0D], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
664
|
+
addop('blendps', [0x0F, 0x3A, 0x0C], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
665
|
+
addop('blendvpd', [0x0F, 0x38, 0x15], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
666
|
+
addop('blendvps', [0x0F, 0x38, 0x14], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
667
|
+
addop('dppd', [0x0F, 0x3A, 0x41], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
668
|
+
addop('dpps', [0x0F, 0x3A, 0x40], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
669
|
+
addop('extractps',[0x0F, 0x3A, 0x17], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
670
|
+
addop('insertps', [0x0F, 0x3A, 0x21], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
671
|
+
addop('movntdqa', [0x0F, 0x38, 0x2A], :mrmxmm, :modrmA) { |o| o.props[:needpfx] = 0x66 }
|
672
|
+
addop('mpsadbw', [0x0F, 0x3A, 0x42], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
673
|
+
addop('packusdw', [0x0F, 0x38, 0x2B], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
674
|
+
addop('pblendvb', [0x0F, 0x38, 0x10], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
675
|
+
addop('pblendw', [0x0F, 0x3A, 0x1E], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
676
|
+
addop('pcmpeqq', [0x0F, 0x38, 0x29], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
677
|
+
addop('pextrb', [0x0F, 0x3A, 0x14], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 8 }
|
678
|
+
addop('pextrw', [0x0F, 0x3A, 0x15], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 16 }
|
679
|
+
addop('pextrd', [0x0F, 0x3A, 0x16], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 32 }
|
680
|
+
addop('pinsrb', [0x0F, 0x3A, 0x20], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 8 }
|
681
|
+
addop('pinsrw', [0x0F, 0x3A, 0x21], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 16 }
|
682
|
+
addop('pinsrd', [0x0F, 0x3A, 0x22], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 32 }
|
683
|
+
addop('phminposuw', [0x0F, 0x38, 0x41], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
684
|
+
addop('pminsb', [0x0F, 0x38, 0x38], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
685
|
+
addop('pminsd', [0x0F, 0x38, 0x39], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
686
|
+
addop('pminuw', [0x0F, 0x38, 0x3A], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
687
|
+
addop('pminud', [0x0F, 0x38, 0x3B], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
688
|
+
addop('pmaxsb', [0x0F, 0x38, 0x3C], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
689
|
+
addop('pmaxsd', [0x0F, 0x38, 0x3D], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
690
|
+
addop('pmaxuw', [0x0F, 0x38, 0x3E], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
691
|
+
addop('pmaxud', [0x0F, 0x38, 0x3F], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
692
|
+
|
693
|
+
addop('pmovsxbw', [0x0F, 0x38, 0x20], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
694
|
+
addop('pmovsxbd', [0x0F, 0x38, 0x21], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
695
|
+
addop('pmovsxbq', [0x0F, 0x38, 0x22], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
696
|
+
addop('pmovsxwd', [0x0F, 0x38, 0x23], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
697
|
+
addop('pmovsxwq', [0x0F, 0x38, 0x24], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
698
|
+
addop('pmovsxdq', [0x0F, 0x38, 0x25], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
699
|
+
addop('pmovzxbw', [0x0F, 0x38, 0x30], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
700
|
+
addop('pmovzxbd', [0x0F, 0x38, 0x31], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
701
|
+
addop('pmovzxbq', [0x0F, 0x38, 0x32], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
702
|
+
addop('pmovzxwd', [0x0F, 0x38, 0x33], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
703
|
+
addop('pmovzxwq', [0x0F, 0x38, 0x34], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
704
|
+
addop('pmovzxdq', [0x0F, 0x38, 0x35], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
705
|
+
|
706
|
+
addop('pmuldq', [0x0F, 0x38, 0x28], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
707
|
+
addop('pmulld', [0x0F, 0x38, 0x40], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
708
|
+
addop('ptest', [0x0F, 0x38, 0x17], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
709
|
+
addop('roundps', [0x0F, 0x3A, 0x08], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
710
|
+
addop('roundpd', [0x0F, 0x3A, 0x09], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
711
|
+
addop('roundss', [0x0F, 0x3A, 0x0A], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
712
|
+
addop('roundsd', [0x0F, 0x3A, 0x0B], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
713
|
+
end
|
714
|
+
|
715
|
+
def init_sse42_only
|
716
|
+
init_cpu_constants
|
717
|
+
|
718
|
+
addop('crc32', [0x0F, 0x38, 0xF0], :mrmw) { |o| o.props[:needpfx] = 0xF2 }
|
719
|
+
addop('pcmpestrm', [0x0F, 0x3A, 0x60], :mrmxmm, :i8) { |o| o.props[:needpfx] = 0x66 }
|
720
|
+
addop('pcmpestri', [0x0F, 0x3A, 0x61], :mrmxmm, :i8) { |o| o.props[:needpfx] = 0x66 }
|
721
|
+
addop('pcmpistrm', [0x0F, 0x3A, 0x62], :mrmxmm, :i8) { |o| o.props[:needpfx] = 0x66 }
|
722
|
+
addop('pcmpistri', [0x0F, 0x3A, 0x63], :mrmxmm, :i8) { |o| o.props[:needpfx] = 0x66 }
|
723
|
+
addop('pcmpgtq', [0x0F, 0x38, 0x37], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
724
|
+
addop('popcnt', [0x0F, 0xB8], :mrm) { |o| o.props[:needpfx] = 0xF3 }
|
725
|
+
end
|
726
|
+
|
727
|
+
def init_avx_only
|
728
|
+
init_cpu_constants
|
729
|
+
|
730
|
+
add128 = {}
|
731
|
+
add256 = {}
|
732
|
+
%w[movss movsd movlhps movhpd movhlps
|
733
|
+
cvtsi2ss cvtsi2sd sqrtss sqrtsd rsqrtss rcpss
|
734
|
+
addss addsd mulss mulsd cvtss2sd cvtsd2ss subss subsd
|
735
|
+
minss minsd divss divsd maxss maxsd
|
736
|
+
punpcklb punpcklw punpckld packsswb pcmpgtb pcmpgtw pcmpgtd packuswb
|
737
|
+
punpckhb punpckhw punpckhd packssdw punpcklq punpckhq
|
738
|
+
pcmpeqb pcmpeqw pcmpeqd ldmxcsr stmxcsr
|
739
|
+
cmpss cmpsd paddq pmullw psubusb psubusw pminub
|
740
|
+
pand paddusb paddusw pmaxub pandn pavgb pavgw
|
741
|
+
pmulhuw pmulhw psubsb psubsw pminsw por paddsb paddsw pmaxsw pxor
|
742
|
+
pmuludq pmaddwd psadbw
|
743
|
+
psubb psubw psubd psubq paddb paddw paddd
|
744
|
+
phaddw phaddsw phaddd phsubw phsubsw phsubd
|
745
|
+
pmaddubsw palignr pshufb pmulhrsw psignb psignw psignd
|
746
|
+
dppd insertps mpsadbw packusdw pblendw pcmpeqq
|
747
|
+
pinsrb pinsrw pinsrd pinsrq
|
748
|
+
pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw
|
749
|
+
pmuldq pmulld roundsd roundss pcmpgtq
|
750
|
+
aesdec aesdeclast aesenc aesenclast
|
751
|
+
pclmulqdq punpcklbw punpcklwd punpckldq punpckhbw punpckhwd
|
752
|
+
punpckhdq punpcklqdq punpckhqdq].each { |n| add128[n] = true }
|
753
|
+
|
754
|
+
%w[movups movupd movddup movsldup
|
755
|
+
unpcklps unpcklpd unpckhps unpckhpd
|
756
|
+
movaps movshdup movapd movntps movntpd movmskps movmskpd
|
757
|
+
sqrtps sqrtpd rsqrtps rcpps andps andpd andnps andnpd
|
758
|
+
orps orpd xorps xorpd addps addpd mulps mulpd
|
759
|
+
cvtps2pd cvtpd2ps cvtdq2ps cvtps2dq cvttps2dq
|
760
|
+
subps subpd minps minpd divps divpd maxps maxpd
|
761
|
+
movdqa movdqu haddpd haddps hsubpd hsubps
|
762
|
+
cmpps cmppd shufps shufpd addsubpd addsubps
|
763
|
+
cvtpd2dq cvttpd2dq cvtdq2pd movntdq lddqu
|
764
|
+
blendps blendpd blendvps blendvpd dpps ptest
|
765
|
+
roundpd roundps].each { |n| add128[n] = add256[n] = true }
|
766
|
+
|
767
|
+
varg = Hash.new(1)
|
768
|
+
%w[pabsb pabsw pabsd pmovmskb pshufd pshufhw pshuflw movntdqa
|
769
|
+
pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq
|
770
|
+
pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq
|
771
|
+
aesimc aeskeygenassist lddqu maskmovdqu movapd movaps
|
772
|
+
pcmpestri pcmpestrm pcmpistri pcmpistrm phminposuw
|
773
|
+
cvtpd2dq cvttpd2dq cvtdq2pd cvtps2pd cvtpd2ps cvtdq2ps cvtps2dq
|
774
|
+
cvttps2dq movd movq movddup movdqa movdqu movmskps movmskpd
|
775
|
+
movntdq movntps movntpd movshdup movsldup movups movupd
|
776
|
+
pextrb pextrw pextrd pextrq ptest rcpps roundps roundpd
|
777
|
+
extractps sqrtps sqrtpd comiss comisd ucomiss ucomisd
|
778
|
+
cvttss2si cvttsd2si cvtss2si cvtsd2si
|
779
|
+
].each { |n| add128[n] = true ; varg[n] = nil }
|
780
|
+
|
781
|
+
cvtarg128 = { :regmmx => :regxmm, :modrmmmx => :modrmxmm }
|
782
|
+
cvtarg256 = { :regmmx => :regymm, :modrmmmx => :modrmymm,
|
783
|
+
:regxmm => :regymm, :modrmxmm => :modrmymm }
|
784
|
+
|
785
|
+
# autopromote old sseX opcodes
|
786
|
+
@opcode_list.each { |o|
|
787
|
+
next if o.bin[0] != 0x0F or not add128[o.name] # rep cmpsd / movsd
|
788
|
+
|
789
|
+
mm = (o.bin[1] == 0x38 ? 0x0F38 : o.bin[1] == 0x3A ? 0x0F3A : 0x0F)
|
790
|
+
pp = o.props[:needpfx]
|
791
|
+
pp = 0x66 if o.props[:xmmx]
|
792
|
+
fpxlen = (mm == 0x0F ? 1 : 2)
|
793
|
+
|
794
|
+
addop_vex('v' + o.name, [varg[o.name], 128, pp, mm], o.bin[fpxlen], nil, *o.args.map { |oa| cvtarg128[oa] || oa }) { |oo|
|
795
|
+
oo.bin += [o.bin[fpxlen+1]] if o.bin[fpxlen+1]
|
796
|
+
dbinlen = o.bin.length - oo.bin.length
|
797
|
+
o.fields.each { |k, v| oo.fields[cvtarg128[k] || k] = [v[0]-dbinlen, v[1]] }
|
798
|
+
o.props.each { |k, v| oo.props[k] = v if k != :xmmx and k != :needpfx }
|
799
|
+
}
|
800
|
+
|
801
|
+
next if not add256[o.name]
|
802
|
+
addop_vex('v' + o.name, [varg[o.name], 256, pp, mm], o.bin[fpxlen], nil, *o.args.map { |oa| cvtarg256[oa] || oa }) { |oo|
|
803
|
+
oo.bin += [o.bin[fpxlen+1]] if o.bin[fpxlen+1]
|
804
|
+
dbinlen = o.bin.length - oo.bin.length
|
805
|
+
o.fields.each { |k, v| oo.fields[cvtarg256[k] || k] = [v[0]-dbinlen, v[1]] }
|
806
|
+
o.props.each { |k, v| oo.props[k] = v if k != :xmmx and k != :needpfx }
|
807
|
+
}
|
808
|
+
}
|
809
|
+
|
810
|
+
# sse promotion, special cases
|
811
|
+
addop_vex 'vpblendvb', [1, 128, 0x66, 0x0F3A, 0], 0x4C, :mrmxmm, :i4xmm
|
812
|
+
addop_vex 'vpsllw', [1, 128, 0x66, 0x0F], 0xF1, :mrmxmm
|
813
|
+
addop_vex('vpsllw', [0, 128, 0x66, 0x0F], 0x71, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
814
|
+
addop_vex 'vpslld', [1, 128, 0x66, 0x0F], 0xF2, :mrmxmm
|
815
|
+
addop_vex('vpslld', [0, 128, 0x66, 0x0F], 0x72, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
816
|
+
addop_vex 'vpsllq', [1, 128, 0x66, 0x0F], 0xF3, :mrmxmm
|
817
|
+
addop_vex('vpsllq', [0, 128, 0x66, 0x0F], 0x73, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
818
|
+
addop_vex('vpslldq',[0, 128, 0x66, 0x0F], 0x73, 7, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
819
|
+
addop_vex 'vpsraw', [1, 128, 0x66, 0x0F], 0xE1, :mrmxmm
|
820
|
+
addop_vex('vpsraw', [0, 128, 0x66, 0x0F], 0x71, 4, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
821
|
+
addop_vex 'vpsrad', [1, 128, 0x66, 0x0F], 0xE2, :mrmxmm
|
822
|
+
addop_vex('vpsrad', [0, 128, 0x66, 0x0F], 0x72, 4, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
823
|
+
addop_vex 'vpsrlw', [1, 128, 0x66, 0x0F], 0xD1, :mrmxmm
|
824
|
+
addop_vex('vpsrlw', [0, 128, 0x66, 0x0F], 0x71, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
825
|
+
addop_vex 'vpsrld', [1, 128, 0x66, 0x0F], 0xD2, :mrmxmm
|
826
|
+
addop_vex('vpsrld', [0, 128, 0x66, 0x0F], 0x72, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
827
|
+
addop_vex 'vpsrlq', [1, 128, 0x66, 0x0F], 0xD3, :mrmxmm
|
828
|
+
addop_vex('vpsrlq', [0, 128, 0x66, 0x0F], 0x73, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
829
|
+
addop_vex('vpsrldq',[0, 128, 0x66, 0x0F], 0x73, 3, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmxmm }
|
830
|
+
|
831
|
+
# dst==mem => no vreg
|
832
|
+
addop_vex 'vmovhps', [1, 128, nil, 0x0F], 0x16, :mrmxmm, :modrmA
|
833
|
+
addop_vex('vmovhps', [nil, 128, nil, 0x0F], 0x17, :mrmxmm, :modrmA) { |o| o.args.reverse! }
|
834
|
+
addop_vex 'vmovlpd', [1, 128, 0x66, 0x0F], 0x12, :mrmxmm, :modrmA
|
835
|
+
addop_vex('vmovlpd', [nil, 128, 0x66, 0x0F], 0x13, :mrmxmm, :modrmA) { |o| o.args.reverse! }
|
836
|
+
addop_vex 'vmovlps', [1, 128, nil, 0x0F], 0x12, :mrmxmm, :modrmA
|
837
|
+
addop_vex('vmovlps', [nil, 128, nil, 0x0F], 0x13, :mrmxmm, :modrmA) { |o| o.args.reverse! }
|
838
|
+
|
839
|
+
addop_vex 'vbroadcastss', [nil, 128, 0x66, 0x0F38, 0], 0x18, :mrmxmm, :modrmA
|
840
|
+
addop_vex 'vbroadcastss', [nil, 256, 0x66, 0x0F38, 0], 0x18, :mrmymm, :modrmA
|
841
|
+
addop_vex 'vbroadcastsd', [nil, 256, 0x66, 0x0F38, 0], 0x19, :mrmymm, :modrmA
|
842
|
+
addop_vex 'vbroadcastf128', [nil, 256, 0x66, 0x0F38, 0], 0x1A, :mrmymm, :modrmA
|
843
|
+
|
844
|
+
# general-purpose register operations
|
845
|
+
addop_vex 'andn', [1, :vexvreg, 128, nil, 0x0F38], 0xF2, :mrm
|
846
|
+
addop_vex 'bextr', [2, :vexvreg, 128, nil, 0x0F38], 0xF7, :mrm
|
847
|
+
addop_vex 'blsi', [0, :vexvreg, 128, nil, 0x0F38], 0xF3, 3
|
848
|
+
addop_vex 'blsmsk', [0, :vexvreg, 128, nil, 0x0F38], 0xF3, 2
|
849
|
+
addop_vex 'blsr', [0, :vexvreg, 128, nil, 0x0F38], 0xF3, 1
|
850
|
+
addop_vex 'bzhi', [2, :vexvreg, 128, nil, 0x0F38], 0xF5, :mrm
|
851
|
+
addop('lzcnt', [0x0F, 0xBD], :mrm) { |o| o.props[:needpfx] = 0xF3 }
|
852
|
+
addop_vex 'mulx', [1, :vexvreg, 128, 0xF2, 0x0F38], 0xF6, :mrm
|
853
|
+
addop_vex 'pdep', [1, :vexvreg, 128, 0xF2, 0x0F38], 0xF5, :mrm
|
854
|
+
addop_vex 'pext', [1, :vexvreg, 128, 0xF3, 0x0F38], 0xF5, :mrm
|
855
|
+
addop_vex 'rorx', [nil, 128, 0xF2, 0x0F3A], 0xF0, :mrm, :u8
|
856
|
+
addop_vex 'sarx', [2, :vexvreg, 128, 0xF3, 0x0F38], 0xF7, :mrm
|
857
|
+
addop_vex 'shrx', [2, :vexvreg, 128, 0xF2, 0x0F38], 0xF7, :mrm
|
858
|
+
addop_vex 'shlx', [2, :vexvreg, 128, 0x66, 0x0F38], 0xF7, :mrm
|
859
|
+
addop('tzcnt', [0x0F, 0xBC], :mrm) { |o| o.props[:needpfx] = 0xF3 }
|
860
|
+
addop('invpcid', [0x0F, 0x38, 0x82], :mrm) { |o| o.props[:needpfx] = 0x66 }
|
861
|
+
addop 'rdrand', [0x0F, 0xC7], 6, :modrmR
|
862
|
+
addop 'rdseed', [0x0F, 0xC7], 7, :modrmR
|
863
|
+
addop('adcx', [0x0F, 0x38, 0xF6], :mrm) { |o| o.props[:needpfx] = 0x66 }
|
864
|
+
addop('adox', [0x0F, 0x38, 0xF6], :mrm) { |o| o.props[:needpfx] = 0xF3 }
|
865
|
+
|
866
|
+
# fp16
|
867
|
+
addop_vex 'vcvtph2ps', [nil, 128, 0x66, 0x0F38, 0], 0x13, :mrmxmm
|
868
|
+
addop_vex 'vcvtph2ps', [nil, 256, 0x66, 0x0F38, 0], 0x13, :mrmymm
|
869
|
+
addop_vex('vcvtps2ph', [nil, 128, 0x66, 0x0F3A, 0], 0x1D, :mrmxmm, :u8) { |o| o.args.reverse! }
|
870
|
+
addop_vex('vcvtps2ph', [nil, 256, 0x66, 0x0F3A, 0], 0x1D, :mrmymm, :u8) { |o| o.args.reverse! }
|
871
|
+
|
872
|
+
# TSE
|
873
|
+
addop 'xabort', [0xC6, 0xF8], nil, :i8 # may :stopexec
|
874
|
+
addop 'xbegin', [0xC7, 0xF8], nil, :i # may :setip: xabortreturns to $_(xbegin) + off
|
875
|
+
addop 'xend', [0x0F, 0x01, 0xD5]
|
876
|
+
addop 'xtest', [0x0F, 0x01, 0xD6]
|
877
|
+
|
878
|
+
# SMAP
|
879
|
+
addop 'clac', [0x0F, 0x01, 0xCA]
|
880
|
+
addop 'stac', [0x0F, 0x01, 0xCB]
|
881
|
+
end
|
882
|
+
|
883
|
+
def init_avx2_only
|
884
|
+
init_cpu_constants
|
885
|
+
|
886
|
+
add256 = {}
|
887
|
+
%w[packsswb pcmpgtb pcmpgtw pcmpgtd packuswb packssdw
|
888
|
+
pcmpeqb pcmpeqw pcmpeqd paddq pmullw psubusb psubusw
|
889
|
+
pminub pand paddusb paddusw pmaxub pandn pavgb pavgw
|
890
|
+
pmulhuw pmulhw psubsb psubsw pminsw por paddsb paddsw
|
891
|
+
pmaxsw pxor pmuludq pmaddwd psadbw
|
892
|
+
psubb psubw psubd psubq paddb paddw paddd
|
893
|
+
phaddw phaddsw phaddd phsubw phsubsw phsubd
|
894
|
+
pmaddubsw palignr pshufb pmulhrsw psignb psignw psignd
|
895
|
+
mpsadbw packusdw pblendw pcmpeqq
|
896
|
+
pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw
|
897
|
+
pmuldq pmulld pcmpgtq punpcklbw punpcklwd punpckldq
|
898
|
+
punpckhbw punpckhwd punpckhdq punpcklqdq punpckhqdq
|
899
|
+
].each { |n| add256[n] = true }
|
900
|
+
|
901
|
+
varg = Hash.new(1)
|
902
|
+
%w[pabsb pabsw pabsd pmovmskb pshufd pshufhw pshuflw movntdqa
|
903
|
+
pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq
|
904
|
+
pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq
|
905
|
+
maskmovdqu].each { |n| add256[n] = true ; varg[n] = nil }
|
906
|
+
|
907
|
+
cvtarg256 = { :regmmx => :regymm, :modrmmmx => :modrmymm,
|
908
|
+
:regxmm => :regymm, :modrmxmm => :modrmymm }
|
909
|
+
|
910
|
+
# autopromote old sseX opcodes
|
911
|
+
@opcode_list.each { |o|
|
912
|
+
next if o.bin[0] != 0x0F or not add256[o.name]
|
913
|
+
|
914
|
+
mm = (o.bin[1] == 0x38 ? 0x0F38 : o.bin[1] == 0x3A ? 0x0F3A : 0x0F)
|
915
|
+
pp = o.props[:needpfx]
|
916
|
+
pp = 0x66 if o.props[:xmmx]
|
917
|
+
fpxlen = (mm == 0x0F ? 1 : 2)
|
918
|
+
|
919
|
+
addop_vex('v' + o.name, [varg[o.name], 256, pp, mm], o.bin[fpxlen], nil, *o.args.map { |oa| cvtarg256[oa] || oa }) { |oo|
|
920
|
+
oo.bin += [o.bin[fpxlen+1]] if o.bin[fpxlen+1]
|
921
|
+
dbinlen = o.bin.length - oo.bin.length
|
922
|
+
o.fields.each { |k, v| oo.fields[cvtarg256[k] || k] = [v[0]-dbinlen, v[1]] }
|
923
|
+
o.props.each { |k, v| oo.props[k] = v if k != :xmmx and k != :needpfx }
|
924
|
+
}
|
925
|
+
}
|
926
|
+
|
927
|
+
# promote special cases
|
928
|
+
addop_vex 'vpblendvb', [1, 256, 0x66, 0x0F3A, 0], 0x4C, :mrmymm, :i4ymm
|
929
|
+
addop_vex 'vpsllw', [1, 256, 0x66, 0x0F], 0xF1, :mrmymm
|
930
|
+
addop_vex('vpsllw', [0, 256, 0x66, 0x0F], 0x71, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
931
|
+
addop_vex 'vpslld', [1, 256, 0x66, 0x0F], 0xF2, :mrmymm
|
932
|
+
addop_vex('vpslld', [0, 256, 0x66, 0x0F], 0x72, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
933
|
+
addop_vex 'vpsllq', [1, 256, 0x66, 0x0F], 0xF3, :mrmymm
|
934
|
+
addop_vex('vpsllq', [0, 256, 0x66, 0x0F], 0x73, 6, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
935
|
+
addop_vex('vpslldq',[0, 256, 0x66, 0x0F], 0x73, 7, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
936
|
+
addop_vex 'vpsraw', [1, 256, 0x66, 0x0F], 0xE1, :mrmymm
|
937
|
+
addop_vex('vpsraw', [0, 256, 0x66, 0x0F], 0x71, 4, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
938
|
+
addop_vex 'vpsrad', [1, 256, 0x66, 0x0F], 0xE2, :mrmymm
|
939
|
+
addop_vex('vpsrad', [0, 256, 0x66, 0x0F], 0x72, 4, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
940
|
+
addop_vex 'vpsrlw', [1, 256, 0x66, 0x0F], 0xD1, :mrmymm
|
941
|
+
addop_vex('vpsrlw', [0, 256, 0x66, 0x0F], 0x71, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
942
|
+
addop_vex 'vpsrld', [1, 256, 0x66, 0x0F], 0xD2, :mrmymm
|
943
|
+
addop_vex('vpsrld', [0, 256, 0x66, 0x0F], 0x72, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
944
|
+
addop_vex 'vpsrlq', [1, 256, 0x66, 0x0F], 0xD3, :mrmymm
|
945
|
+
addop_vex('vpsrlq', [0, 256, 0x66, 0x0F], 0x73, 2, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
946
|
+
addop_vex('vpsrldq',[0, 256, 0x66, 0x0F], 0x73, 3, :u8, :modrmR) { |o| o.args[o.args.index(:modrm)] = :modrmymm }
|
947
|
+
|
948
|
+
addop_vex 'vbroadcastss', [nil, 128, 0x66, 0x0F38, 0], 0x18, :mrmxmm, :modrmR
|
949
|
+
addop_vex 'vbroadcastss', [nil, 256, 0x66, 0x0F38, 0], 0x18, :mrmymm, :modrmR
|
950
|
+
addop_vex 'vbroadcastsd', [nil, 256, 0x66, 0x0F38, 0], 0x19, :mrmymm, :modrmR
|
951
|
+
addop_vex 'vbroadcasti128', [nil, 256, 0x66, 0x0F38, 0], 0x5A, :mrmymm, :modrmA
|
952
|
+
addop_vex 'vpblendd', [1, 128, 0x66, 0x0F3A, 0], 0x02, :mrmxmm, :u8
|
953
|
+
addop_vex 'vpblendd', [1, 256, 0x66, 0x0F3A, 0], 0x02, :mrmymm, :u8
|
954
|
+
addop_vex 'vpbroadcastb', [nil, 128, 0x66, 0x0F38, 0], 0x78, :mrmxmm
|
955
|
+
addop_vex 'vpbroadcastb', [nil, 256, 0x66, 0x0F38, 0], 0x78, :mrmymm
|
956
|
+
addop_vex 'vpbroadcastw', [nil, 128, 0x66, 0x0F38, 0], 0x79, :mrmxmm
|
957
|
+
addop_vex 'vpbroadcastw', [nil, 256, 0x66, 0x0F38, 0], 0x79, :mrmymm
|
958
|
+
addop_vex 'vpbroadcastd', [nil, 128, 0x66, 0x0F38, 0], 0x58, :mrmxmm
|
959
|
+
addop_vex 'vpbroadcastd', [nil, 256, 0x66, 0x0F38, 0], 0x58, :mrmymm
|
960
|
+
addop_vex 'vpbroadcastq', [nil, 128, 0x66, 0x0F38, 0], 0x59, :mrmxmm
|
961
|
+
addop_vex 'vpbroadcastq', [nil, 256, 0x66, 0x0F38, 0], 0x59, :mrmymm
|
962
|
+
addop_vex 'vpermd', [1, 256, 0x66, 0x0F38, 0], 0x36, :mrmymm
|
963
|
+
addop_vex 'vpermpd', [nil, 256, 0x66, 0x0F3A, 1], 0x01, :mrmymm, :u8
|
964
|
+
addop_vex 'vpermps', [1, 256, 0x66, 0x0F38, 0], 0x16, :mrmymm, :u8
|
965
|
+
addop_vex 'vpermq', [nil, 256, 0x66, 0x0F3A, 1], 0x00, :mrmymm, :u8
|
966
|
+
addop_vex 'vperm2i128', [1, 256, 0x66, 0x0F3A, 0], 0x46, :mrmymm, :u8
|
967
|
+
addop_vex 'vextracti128', [nil, 256, 0x66, 0x0F3A, 0], 0x39, :mrmymm, :u8
|
968
|
+
addop_vex 'vinserti128', [1, 256, 0x66, 0x0F3A, 0], 0x38, :mrmymm, :u8
|
969
|
+
addop_vex 'vpmaskmovd', [1, 128, 0x66, 0x0F38, 0], 0x8C, :mrmxmm, :modrmA
|
970
|
+
addop_vex 'vpmaskmovd', [1, 256, 0x66, 0x0F38, 0], 0x8C, :mrmymm, :modrmA
|
971
|
+
addop_vex 'vpmaskmovq', [1, 128, 0x66, 0x0F38, 1], 0x8C, :mrmxmm, :modrmA
|
972
|
+
addop_vex 'vpmaskmovq', [1, 256, 0x66, 0x0F38, 1], 0x8C, :mrmymm, :modrmA
|
973
|
+
addop_vex('vpmaskmovd', [1, 128, 0x66, 0x0F38, 0], 0x8E, :mrmxmm, :modrmA) { |o| o.args.reverse! }
|
974
|
+
addop_vex('vpmaskmovd', [1, 256, 0x66, 0x0F38, 0], 0x8E, :mrmymm, :modrmA) { |o| o.args.reverse! }
|
975
|
+
addop_vex('vpmaskmovq', [1, 128, 0x66, 0x0F38, 1], 0x8E, :mrmxmm, :modrmA) { |o| o.args.reverse! }
|
976
|
+
addop_vex('vpmaskmovq', [1, 256, 0x66, 0x0F38, 1], 0x8E, :mrmymm, :modrmA) { |o| o.args.reverse! }
|
977
|
+
addop_vex 'vpsllvd', [1, 128, 0x66, 0x0F38, 0], 0x47, :mrmxmm
|
978
|
+
addop_vex 'vpsllvq', [1, 128, 0x66, 0x0F38, 1], 0x47, :mrmxmm
|
979
|
+
addop_vex 'vpsllvd', [1, 256, 0x66, 0x0F38, 0], 0x47, :mrmymm
|
980
|
+
addop_vex 'vpsllvq', [1, 256, 0x66, 0x0F38, 1], 0x47, :mrmymm
|
981
|
+
addop_vex 'vpsravd', [1, 128, 0x66, 0x0F38, 0], 0x46, :mrmxmm
|
982
|
+
addop_vex 'vpsravd', [1, 256, 0x66, 0x0F38, 0], 0x46, :mrmymm
|
983
|
+
addop_vex 'vpsrlvd', [1, 128, 0x66, 0x0F38, 0], 0x45, :mrmxmm
|
984
|
+
addop_vex 'vpsrlvq', [1, 128, 0x66, 0x0F38, 1], 0x45, :mrmxmm
|
985
|
+
addop_vex 'vpsrlvd', [1, 256, 0x66, 0x0F38, 0], 0x45, :mrmymm
|
986
|
+
addop_vex 'vpsrlvq', [1, 256, 0x66, 0x0F38, 1], 0x45, :mrmymm
|
987
|
+
|
988
|
+
addop_vex('vpgatherdd', [2, 128, 0x66, 0x0F38, 0], 0x90, :mrmxmm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 128 }
|
989
|
+
addop_vex('vpgatherdd', [2, 256, 0x66, 0x0F38, 0], 0x90, :mrmymm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 256 }
|
990
|
+
addop_vex('vpgatherdq', [2, 128, 0x66, 0x0F38, 1], 0x90, :mrmxmm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 128 }
|
991
|
+
addop_vex('vpgatherdq', [2, 256, 0x66, 0x0F38, 1], 0x90, :mrmymm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 256 }
|
992
|
+
addop_vex('vpgatherqd', [2, 128, 0x66, 0x0F38, 0], 0x91, :mrmxmm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 128 }
|
993
|
+
addop_vex('vpgatherqd', [2, 256, 0x66, 0x0F38, 0], 0x91, :mrmymm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 256 }
|
994
|
+
addop_vex('vpgatherqq', [2, 128, 0x66, 0x0F38, 1], 0x91, :mrmxmm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 128 }
|
995
|
+
addop_vex('vpgatherqq', [2, 256, 0x66, 0x0F38, 1], 0x91, :mrmymm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 256 }
|
996
|
+
addop_vex('vgatherdps', [2, 128, 0x66, 0x0F38, 0], 0x92, :mrmxmm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 128 }
|
997
|
+
addop_vex('vgatherdps', [2, 256, 0x66, 0x0F38, 0], 0x92, :mrmymm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 256 }
|
998
|
+
addop_vex('vgatherdpd', [2, 128, 0x66, 0x0F38, 1], 0x92, :mrmxmm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 128 }
|
999
|
+
addop_vex('vgatherdpd', [2, 256, 0x66, 0x0F38, 1], 0x92, :mrmymm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 256 }
|
1000
|
+
addop_vex('vgatherqps', [2, 128, 0x66, 0x0F38, 0], 0x93, :mrmxmm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 128 }
|
1001
|
+
addop_vex('vgatherqps', [2, 256, 0x66, 0x0F38, 0], 0x93, :mrmymm) { |o| o.props[:argsz] = 32 ; o.props[:mrmvex] = 256 }
|
1002
|
+
addop_vex('vgatherqpd', [2, 128, 0x66, 0x0F38, 1], 0x93, :mrmxmm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 128 }
|
1003
|
+
addop_vex('vgatherqpd', [2, 256, 0x66, 0x0F38, 1], 0x93, :mrmymm) { |o| o.props[:argsz] = 64 ; o.props[:mrmvex] = 256 }
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
def init_fma_only
|
1007
|
+
init_cpu_constants
|
1008
|
+
|
1009
|
+
[['vfmaddsub', 'p', 0x86],
|
1010
|
+
['vfmsubadd', 'p', 0x87],
|
1011
|
+
['vfmadd', 'p', 0x88],
|
1012
|
+
['vfmadd', 's', 0x89],
|
1013
|
+
['vfmsub', 'p', 0x8A],
|
1014
|
+
['vfmsub', 's', 0x8B],
|
1015
|
+
['vfnmadd', 'p', 0x8C],
|
1016
|
+
['vfnmadd', 's', 0x8D],
|
1017
|
+
['vfnmsub', 'p', 0x8E],
|
1018
|
+
['vfnmsub', 's', 0x8F]].each { |n1, n2, bin|
|
1019
|
+
addop_vex n1 + '132' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x10, :mrmxmm
|
1020
|
+
addop_vex n1 + '132' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x10, :mrmymm
|
1021
|
+
addop_vex n1 + '132' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x10, :mrmxmm
|
1022
|
+
addop_vex n1 + '132' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x10, :mrmymm
|
1023
|
+
addop_vex n1 + '213' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x20, :mrmxmm
|
1024
|
+
addop_vex n1 + '213' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x20, :mrmymm
|
1025
|
+
addop_vex n1 + '213' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x20, :mrmxmm
|
1026
|
+
addop_vex n1 + '213' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x20, :mrmymm
|
1027
|
+
addop_vex n1 + '231' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x30, :mrmxmm
|
1028
|
+
addop_vex n1 + '231' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x30, :mrmymm
|
1029
|
+
addop_vex n1 + '231' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x30, :mrmxmm
|
1030
|
+
addop_vex n1 + '231' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x30, :mrmymm
|
1031
|
+
|
1032
|
+
# pseudo-opcodes aliases (swap arg0/arg1)
|
1033
|
+
addop_vex(n1 + '312' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x10, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1034
|
+
addop_vex(n1 + '312' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x10, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1035
|
+
addop_vex(n1 + '312' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x10, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1036
|
+
addop_vex(n1 + '312' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x10, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1037
|
+
addop_vex(n1 + '123' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x20, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1038
|
+
addop_vex(n1 + '123' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x20, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1039
|
+
addop_vex(n1 + '123' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x20, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1040
|
+
addop_vex(n1 + '123' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x20, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1041
|
+
addop_vex(n1 + '321' + n2 + 's', [1, 128, 0x66, 0x0F38, 0], bin | 0x30, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1042
|
+
addop_vex(n1 + '321' + n2 + 's', [1, 256, 0x66, 0x0F38, 0], bin | 0x30, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1043
|
+
addop_vex(n1 + '321' + n2 + 'd', [1, 128, 0x66, 0x0F38, 1], bin | 0x30, :mrmxmm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1044
|
+
addop_vex(n1 + '321' + n2 + 'd', [1, 256, 0x66, 0x0F38, 1], bin | 0x30, :mrmymm) { |o| o.args[0, 2] = o.args[0, 2].reverse }
|
1045
|
+
}
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
#
|
1049
|
+
# CPU family dependencies
|
1050
|
+
#
|
1051
|
+
|
1052
|
+
def init_386_common
|
1053
|
+
init_386_common_only
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
def init_386
|
1057
|
+
init_386_common
|
1058
|
+
init_386_only
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
def init_387
|
1062
|
+
init_387_only
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
def init_486
|
1066
|
+
init_386
|
1067
|
+
init_387
|
1068
|
+
init_486_only
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
def init_pentium
|
1072
|
+
init_486
|
1073
|
+
init_pentium_only
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def init_3dnow
|
1077
|
+
init_pentium
|
1078
|
+
init_3dnow_only
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
def init_p6
|
1082
|
+
init_pentium
|
1083
|
+
init_p6_only
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def init_sse
|
1087
|
+
init_p6
|
1088
|
+
init_sse_only
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def init_sse2
|
1092
|
+
init_sse
|
1093
|
+
init_sse2_only
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
def init_sse3
|
1097
|
+
init_sse2
|
1098
|
+
init_sse3_only
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def init_ssse3
|
1102
|
+
init_sse3
|
1103
|
+
init_ssse3_only
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def init_sse41
|
1107
|
+
init_ssse3
|
1108
|
+
init_sse41_only
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
def init_sse42
|
1112
|
+
init_sse41
|
1113
|
+
init_sse42_only
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
def init_avx
|
1117
|
+
init_sse42
|
1118
|
+
init_avx_only
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
def init_avx2
|
1122
|
+
init_avx
|
1123
|
+
init_fma_only
|
1124
|
+
init_avx2_only
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def init_all
|
1128
|
+
init_avx2
|
1129
|
+
init_3dnow_only
|
1130
|
+
init_vmx_only
|
1131
|
+
init_aesni_only
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
alias init_latest init_all
|
1135
|
+
|
1136
|
+
|
1137
|
+
#
|
1138
|
+
# addop_* macros
|
1139
|
+
#
|
1140
|
+
|
1141
|
+
def addop_macro1(name, num, *props)
|
1142
|
+
addop name, [(num << 3) | 4], nil, {:w => [0, 0]}, :reg_eax, :i, *props
|
1143
|
+
addop(name, [num << 3], :mrmw, {:d => [0, 1]}) { |o| o.args.reverse! }
|
1144
|
+
addop name, [0x80], num, {:w => [0, 0], :s => [0, 1]}, :i, *props
|
1145
|
+
end
|
1146
|
+
def addop_macro2(name, num)
|
1147
|
+
addop name, [0x0F, 0xBA], (4 | num), :u8
|
1148
|
+
addop(name, [0x0F, 0xA3 | (num << 3)], :mrm) { |op| op.args.reverse! }
|
1149
|
+
end
|
1150
|
+
def addop_macro3(name, num)
|
1151
|
+
addop name, [0xD0], num, {:w => [0, 0]}, :imm_val1
|
1152
|
+
addop name, [0xD2], num, {:w => [0, 0]}, :reg_cl
|
1153
|
+
addop name, [0xC0], num, {:w => [0, 0]}, :u8
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
def addop_macrotttn(name, bin, hint, *props, &blk)
|
1157
|
+
[%w{o}, %w{no}, %w{b nae c}, %w{nb ae nc},
|
1158
|
+
%w{z e}, %w{nz ne}, %w{be na}, %w{nbe a},
|
1159
|
+
%w{s}, %w{ns}, %w{p pe}, %w{np po},
|
1160
|
+
%w{l nge}, %w{nl ge}, %w{le ng}, %w{nle g}].each_with_index { |e, i|
|
1161
|
+
b = bin.dup
|
1162
|
+
if b[0] == 0x0F
|
1163
|
+
b[1] |= i
|
1164
|
+
else
|
1165
|
+
b[0] |= i
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
e.each { |k| addop(name + k, b.dup, hint, *props, &blk) }
|
1169
|
+
}
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
def addop_macrostr(name, bin, type)
|
1173
|
+
# addop(name, bin.dup, {:w => [0, 0]}) { |o| o.props[type] = true } # TODO allow segment override
|
1174
|
+
addop(name+'b', bin) { |o| o.props[:opsz] = 16 ; o.props[type] = true }
|
1175
|
+
addop(name+'b', bin) { |o| o.props[:opsz] = 32 ; o.props[type] = true }
|
1176
|
+
bin = bin.dup
|
1177
|
+
bin[0] |= 1
|
1178
|
+
addop(name+'w', bin) { |o| o.props[:opsz] = 16 ; o.props[type] = true }
|
1179
|
+
addop(name+'d', bin) { |o| o.props[:opsz] = 32 ; o.props[type] = true }
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
def addop_macrofpu1(name, n)
|
1183
|
+
addop(name, [0xD8, n<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 32 }
|
1184
|
+
addop(name, [0xDC, n<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 64 }
|
1185
|
+
addop(name, [0xD8, 0xC0|(n<<3)], :regfp, {:d => [0, 2]}) { |o| o.args.reverse! }
|
1186
|
+
end
|
1187
|
+
def addop_macrofpu2(name, n, n2=0)
|
1188
|
+
addop(name, [0xDE|n2, n<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 16 }
|
1189
|
+
addop(name, [0xDA|n2, n<<3], :modrmA, :regfp0) { |o| o.props[:argsz] = 32 }
|
1190
|
+
end
|
1191
|
+
def addop_macrofpu3(name, n)
|
1192
|
+
addop_macrofpu2 name, n, 1
|
1193
|
+
addop(name, [0xDF, 0x28|(n<<3)], :modrmA, :regfp0) { |o| o.props[:argsz] = 64 }
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
def addop_macrogg(ggrng, name, bin, *args, &blk)
|
1197
|
+
ggoff = 1
|
1198
|
+
ggoff = 2 if bin[1] == 0x38 or bin[1] == 0x3A
|
1199
|
+
ggrng.each { |gg|
|
1200
|
+
bindup = bin.dup
|
1201
|
+
bindup[ggoff] |= gg
|
1202
|
+
sfx = %w(b w d q)[gg]
|
1203
|
+
addop name+sfx, bindup, *args, &blk
|
1204
|
+
}
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
def addop_macrossps(name, bin, hint, *a)
|
1208
|
+
addop name, bin.dup, hint, *a
|
1209
|
+
addop(name.sub(/ps$/, 'ss'), bin.dup, hint, *a) { |o| o.props[:needpfx] = 0xF3 }
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
def addop_macrosdpd(name, bin, hint, *a)
|
1213
|
+
addop(name, bin.dup, hint, *a) { |o| o.props[:needpfx] = 0x66 }
|
1214
|
+
addop(name.sub(/pd$/, 'sd'), bin.dup, hint, *a) { |o| o.props[:needpfx] = 0xF2 }
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
# special ret (iret/retf), that still default to 32b mode in x64
|
1218
|
+
def addop_macroret(name, bin, *args)
|
1219
|
+
addop(name + '.i32', bin.dup, nil, :stopexec, :setip, *args) { |o| o.props[:opsz] = 32 }
|
1220
|
+
addop(name + '.i16', bin.dup, nil, :stopexec, :setip, *args) { |o| o.props[:opsz] = 16 } if name != 'sysret'
|
1221
|
+
addop(name, bin.dup, nil, :stopexec, :setip, *args) { |o| o.props[:opsz] = @size }
|
1222
|
+
end
|
1223
|
+
|
1224
|
+
# add an AVX instruction needing a VEX prefix (c4h/c5h)
|
1225
|
+
# the prefix is hardcoded
|
1226
|
+
def addop_vex(name, vexspec, bin, *args)
|
1227
|
+
argnr = vexspec.shift
|
1228
|
+
argt = vexspec.shift if argnr and vexspec.first.kind_of?(::Symbol)
|
1229
|
+
l = vexspec.shift
|
1230
|
+
pfx = vexspec.shift
|
1231
|
+
of = vexspec.shift
|
1232
|
+
w = vexspec.shift
|
1233
|
+
argt ||= (l == 128 ? :vexvxmm : :vexvymm)
|
1234
|
+
|
1235
|
+
lpp = ((l >> 8) << 2) | [nil, 0x66, 0xF3, 0xF2].index(pfx)
|
1236
|
+
mmmmm = [nil, 0x0F, 0x0F38, 0x0F3A].index(of)
|
1237
|
+
|
1238
|
+
c4bin = [0xC4, mmmmm, lpp, bin]
|
1239
|
+
c4bin[1] |= 1 << 7 if @size != 64
|
1240
|
+
c4bin[1] |= 1 << 6 if @size != 64
|
1241
|
+
c4bin[2] |= 1 << 7 if w == 1
|
1242
|
+
c4bin[2] |= 0xF << 3 if not argnr
|
1243
|
+
|
1244
|
+
addop(name, c4bin, *args) { |o|
|
1245
|
+
o.args.insert(argnr, argt) if argnr
|
1246
|
+
|
1247
|
+
o.fields[:vex_r] = [1, 7] if @size == 64
|
1248
|
+
o.fields[:vex_x] = [1, 6] if @size == 64
|
1249
|
+
o.fields[:vex_b] = [1, 5]
|
1250
|
+
o.fields[:vex_w] = [2, 7] if not w
|
1251
|
+
o.fields[:vex_vvvv] = [2, 3] if argnr
|
1252
|
+
|
1253
|
+
yield o if block_given?
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
return if w == 1 or mmmmm != 1
|
1257
|
+
|
1258
|
+
c5bin = [0xC5, lpp, bin]
|
1259
|
+
c5bin[1] |= 1 << 7 if @size != 64
|
1260
|
+
c5bin[1] |= 0xF << 3 if not argnr
|
1261
|
+
|
1262
|
+
addop(name, c5bin, *args) { |o|
|
1263
|
+
o.args.insert(argnr, argt) if argnr
|
1264
|
+
|
1265
|
+
o.fields[:vex_r] = [1, 7] if @size == 64
|
1266
|
+
o.fields[:vex_vvvv] = [1, 3] if argnr
|
1267
|
+
|
1268
|
+
yield o if block_given?
|
1269
|
+
}
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
# helper function: creates a new Opcode based on the arguments, eventually
|
1273
|
+
# yields it for further customisation, and append it to the instruction set
|
1274
|
+
# is responsible of the creation of disambiguating opcodes if necessary (:s flag hardcoding)
|
1275
|
+
def addop(name, bin, hint=nil, *argprops)
|
1276
|
+
fields = (argprops.first.kind_of?(Hash) ? argprops.shift : {})
|
1277
|
+
op = Opcode.new name, bin
|
1278
|
+
op.fields.replace fields
|
1279
|
+
|
1280
|
+
case hint
|
1281
|
+
when nil
|
1282
|
+
|
1283
|
+
when :mrm, :mrmw, :mrmA
|
1284
|
+
op.fields[:reg] = [bin.length, 3]
|
1285
|
+
op.fields[:modrm] = [bin.length, 0]
|
1286
|
+
op.fields[:w] = [bin.length - 1, 0] if hint == :mrmw
|
1287
|
+
argprops.unshift :reg, :modrm
|
1288
|
+
argprops << :modrmA if hint == :mrmA
|
1289
|
+
op.bin << 0
|
1290
|
+
when :reg
|
1291
|
+
op.fields[:reg] = [bin.length-1, 0]
|
1292
|
+
argprops.unshift :reg
|
1293
|
+
when :regfp
|
1294
|
+
op.fields[:regfp] = [bin.length-1, 0]
|
1295
|
+
argprops.unshift :regfp, :regfp0
|
1296
|
+
when :modrmA
|
1297
|
+
op.fields[:modrm] = [bin.length-1, 0]
|
1298
|
+
argprops << :modrm << :modrmA
|
1299
|
+
|
1300
|
+
when Integer # mod/m, reg == opcode extension = hint
|
1301
|
+
op.fields[:modrm] = [bin.length, 0]
|
1302
|
+
op.bin << (hint << 3)
|
1303
|
+
argprops.unshift :modrm
|
1304
|
+
|
1305
|
+
when :mrmmmx
|
1306
|
+
op.fields[:regmmx] = [bin.length, 3]
|
1307
|
+
op.fields[:modrm] = [bin.length, 0]
|
1308
|
+
bin << 0
|
1309
|
+
argprops.unshift :regmmx, :modrmmmx
|
1310
|
+
when :mrmxmm
|
1311
|
+
op.fields[:regxmm] = [bin.length, 3]
|
1312
|
+
op.fields[:modrm] = [bin.length, 0]
|
1313
|
+
bin << 0
|
1314
|
+
argprops.unshift :regxmm, :modrmxmm
|
1315
|
+
when :mrmymm
|
1316
|
+
op.fields[:regymm] = [bin.length, 3]
|
1317
|
+
op.fields[:modrm] = [bin.length, 0]
|
1318
|
+
bin << 0
|
1319
|
+
argprops.unshift :regymm, :modrmymm
|
1320
|
+
else
|
1321
|
+
raise SyntaxError, "invalid hint #{hint.inspect} for #{name}"
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
argprops.each { |a|
|
1325
|
+
op.props[a] = true if @valid_props[a]
|
1326
|
+
op.args << a if @valid_args[a]
|
1327
|
+
}
|
1328
|
+
|
1329
|
+
yield op if block_given?
|
1330
|
+
|
1331
|
+
if $DEBUG
|
1332
|
+
argprops -= @valid_props.keys + @valid_args.keys
|
1333
|
+
raise "Invalid opcode definition: #{name}: unknown #{argprops.inspect}" unless argprops.empty?
|
1334
|
+
|
1335
|
+
argprops = (op.props.keys - @valid_props.keys) + (op.args - @valid_args.keys) + (op.fields.keys - @fields_mask.keys)
|
1336
|
+
raise "Invalid opcode customisation: #{name}: #{argprops.inspect}" unless argprops.empty?
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
addop_post(op)
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
# this recursive method is in charge of Opcode duplication (eg to hardcode some flag)
|
1343
|
+
def addop_post(op)
|
1344
|
+
if df = op.fields.delete(:d)
|
1345
|
+
# hardcode the bit
|
1346
|
+
dop = op.dup
|
1347
|
+
addop_post dop
|
1348
|
+
|
1349
|
+
op.bin[df[0]] |= 1 << df[1]
|
1350
|
+
op.args.reverse!
|
1351
|
+
addop_post op
|
1352
|
+
|
1353
|
+
return
|
1354
|
+
elsif wf = op.fields.delete(:w)
|
1355
|
+
# hardcode the bit
|
1356
|
+
dop = op.dup
|
1357
|
+
dop.props[:argsz] = 8
|
1358
|
+
# 64-bit w=0 s=1 => UD
|
1359
|
+
dop.fields.delete(:s) if @size == 64
|
1360
|
+
addop_post dop
|
1361
|
+
|
1362
|
+
op.bin[wf[0]] |= 1 << wf[1]
|
1363
|
+
addop_post op
|
1364
|
+
|
1365
|
+
return
|
1366
|
+
elsif sf = op.fields.delete(:s)
|
1367
|
+
# add explicit choice versions, with lower precedence (so that disassembling will return the general version)
|
1368
|
+
# eg "jmp", "jmp.i8", "jmp.i"
|
1369
|
+
# also hardcode the bit
|
1370
|
+
op32 = op
|
1371
|
+
addop_post op32
|
1372
|
+
|
1373
|
+
op8 = op.dup
|
1374
|
+
op8.bin[sf[0]] |= 1 << sf[1]
|
1375
|
+
op8.args.map! { |arg| arg == :i ? :i8 : arg }
|
1376
|
+
addop_post op8
|
1377
|
+
|
1378
|
+
op32 = op32.dup
|
1379
|
+
op32.name << '.i'
|
1380
|
+
addop_post op32
|
1381
|
+
|
1382
|
+
op8 = op8.dup
|
1383
|
+
op8.name << '.i8'
|
1384
|
+
addop_post op8
|
1385
|
+
|
1386
|
+
return
|
1387
|
+
elsif op.args.first == :regfp0
|
1388
|
+
dop = op.dup
|
1389
|
+
dop.args.delete :regfp0
|
1390
|
+
addop_post dop
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
if op.props[:needpfx]
|
1394
|
+
@opcode_list.unshift op
|
1395
|
+
else
|
1396
|
+
@opcode_list << op
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
if (op.args == [:i] or op.args == [:farptr] or op.name == 'ret') and op.name !~ /\.i/
|
1400
|
+
# define opsz-override version for ambiguous opcodes
|
1401
|
+
op16 = op.dup
|
1402
|
+
op16.name << '.i16'
|
1403
|
+
op16.props[:opsz] = 16
|
1404
|
+
@opcode_list << op16
|
1405
|
+
op32 = op.dup
|
1406
|
+
op32.name << '.i32'
|
1407
|
+
op32.props[:opsz] = 32
|
1408
|
+
@opcode_list << op32
|
1409
|
+
elsif op.props[:strop] or op.props[:stropz] or op.args.include? :mrm_imm or
|
1410
|
+
op.args.include? :modrm or op.name =~ /loop|xlat/
|
1411
|
+
# define adsz-override version for ambiguous opcodes (TODO allow movsd edi / movsd di syntax)
|
1412
|
+
# XXX loop pfx 67 = eip+cx, 66 = ip+ecx
|
1413
|
+
op16 = op.dup
|
1414
|
+
op16.name << '.a16'
|
1415
|
+
op16.props[:adsz] = 16
|
1416
|
+
@opcode_list << op16
|
1417
|
+
op32 = op.dup
|
1418
|
+
op32.name << '.a32'
|
1419
|
+
op32.props[:adsz] = 32
|
1420
|
+
@opcode_list << op32
|
1421
|
+
end
|
1422
|
+
end
|
1423
|
+
end
|
1424
|
+
end
|