metasm 1.0.0

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