2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
42 // $Id: arch-x86.C,v 1.17 2002/06/17 17:04:04 gaburici Exp $
43 // x86 instruction decoder
47 #include "common/h/Types.h"
49 #include "arch-ia32.h"
51 // opcode descriptors (from the Pentium manual)
53 Grp1=0, Grp2, Grp3a, Grp3b, Grp4, Grp5, Grp6, Grp7, Grp8, Grp9,
54 oneB, twoB, coprocEsc,
55 PREFIX_SEG_OVR, PREFIX_OPR_SZ, PREFIX_ADDR_SZ, PREFIX_INSTR,
59 // operand descriptor (from the Pentium manual)
63 CS, DS, ES, FS, GS, SS,
64 AL, AH, BL, BH, CL, CH, DL, DH,
65 AX, BX, CX, DX, SI, DI, BP, SP,
66 eAX, eBX, eCX, eDX, eSI, eDI, eBP, eSP,
67 rEAX, rEBX, rECX, rEDX, rESI, rEDI, rEBP, rESP,
85 // an entry of the opcode tables map
87 char *name; // name of the instruction (for debbuging only)
88 unsigned escape_code; // which opcode tables to look at (eg. oneB, twoB, etc)
89 bool hasModRM; // true if the instruction has a MOD/RM byte
90 unsigned operands[3]; // operand descriptos
91 unsigned insnType; // the type of the instruction (e.g. (IS_CALL | REL_W))
95 /* groupMap: opcodes determined by bits 5,4,3 of the MOD/RM byte.
96 For some instructions in this table, the operands are defined in the
97 one or two byte opcode map, for others the operands are defined here.
98 Get operands from one or two byte map: Grp1, Grp2, Grp8
99 Get operands from ModRM map: Grp3a, Grp3b, Grp4, Grp5, Grp6, Grp7, Grp 9
102 static x86_insn groupMap[10][8] = {
103 { /* group 1 - only opcode is defined here,
104 operands are defined in the one or two byte maps below */
105 { "add", 0, true, { 0, 0, 0 }, 0 },
106 { "or", 0, true, { 0, 0, 0 }, 0 },
107 { "adc", 0, true, { 0, 0, 0 }, 0 },
108 { "sbb", 0, true, { 0, 0, 0 }, 0 },
109 { "and", 0, true, { 0, 0, 0 }, 0 },
110 { "sub", 0, true, { 0, 0, 0 }, 0 },
111 { "xor", 0, true, { 0, 0, 0 }, 0 },
112 { "cmp", 0, true, { 0, 0, 0 }, 0 }
115 { /* group 2 - only opcode is defined here,
116 operands are defined in the one or two byte maps below */
117 { "rol", 0, true, { 0, 0, 0 }, 0 },
118 { "ror", 0, true, { 0, 0, 0 }, 0 },
119 { "rcl", 0, true, { 0, 0, 0 }, 0 },
120 { "rcr", 0, true, { 0, 0, 0 }, 0 },
121 { "shl sal", 0, true, { 0, 0, 0 }, 0 },
122 { "shr", 0, true, { 0, 0, 0 }, 0 },
123 { 0, Ill, 0, { 0, 0, 0 }, 0 },
124 { "sar", 0, true, { 0, 0, 0 }, 0 }
127 { /* group 3a - operands are defined here */
128 { "test", 0, true, { Eb, Ib, 0 }, 0 },
129 { 0, Ill, 0, { 0, 0, 0 }, 0 },
130 { "not", 0, true, { Eb, 0, 0 }, 0 },
131 { "neg", 0, true, { Eb, 0, 0 }, 0 },
132 { "mul", 0, true, { AL, Eb, 0 }, 0 },
133 { "imul", 0, true, { AL, Eb, 0 }, 0 },
134 { "div", 0, true, { AL, Eb, 0 }, 0 },
135 { "idiv", 0, true, { AL, Eb, 0 }, 0 }
138 { /* group 3b - operands are defined here */
139 { "test", 0, true, { Ev, Iv, 0 }, 0 },
140 { 0, Ill, 0, { 0, 0, 0 }, 0 },
141 { "not", 0, true, { Ev, 0, 0 }, 0 },
142 { "neg", 0, true, { Ev, 0, 0 }, 0 },
143 { "mul", 0, true, { eAX, Ev, 0 }, 0 },
144 { "imul", 0, true, { eAX, Ev, 0 }, 0 },
145 { "div", 0, true, { eAX, Ev, 0 }, 0 },
146 { "idiv", 0, true, { eAX, Ev, 0 }, 0 }
149 { /* group 4 - operands are defined here */
150 { "inc", 0, true, { Eb, 0, 0 }, 0 },
151 { "dec", 0, true, { Eb, 0, 0 }, 0 },
152 { 0, Ill, 0, { 0, 0, 0 }, 0 },
153 { 0, Ill, 0, { 0, 0, 0 }, 0 },
154 { 0, Ill, 0, { 0, 0, 0 }, 0 },
155 { 0, Ill, 0, { 0, 0, 0 }, 0 },
156 { 0, Ill, 0, { 0, 0, 0 }, 0 },
157 { 0, Ill, 0, { 0, 0, 0 }, 0 },
160 { /* group 5 - operands are defined here */
161 { "inc", 0, true, { Ev, 0, 0 }, 0 },
162 { "dec", 0, true, { Ev, 0, 0 }, 0 },
163 { "call", 0, true, { Ev, 0, 0 }, (IS_CALL | INDIR) },
164 { "call", 0, true, { Ep, 0, 0 }, (IS_CALL | INDIR) },
165 { "jmp", 0, true, { Ev, 0, 0 } , (IS_JUMP | INDIR) },
166 { "jmp", 0, true, { Ep, 0, 0 }, (IS_JUMP | INDIR) },
167 { "push", 0, true, { Ev, 0, 0, }, 0 },
168 { 0, Ill, 0, { 0, 0, 0 }, 0 },
171 { /* group 6 - operands are defined here */
172 { "sldt", 0, true, { Ew, 0, 0 }, 0 },
173 { "str", 0, true, { Ew, 0, 0 }, 0 },
174 { "lldt", 0, true, { Ew, 0, 0 }, 0 },
175 { "ltr", 0, true, { Ew, 0, 0 }, 0 },
176 { "verr", 0, true, { Ew, 0, 0 }, 0 },
177 { "verw", 0, true, { Ew, 0, 0 }, 0 },
178 { 0, Ill, 0, { 0, 0, 0 }, 0 },
179 { 0, Ill, 0, { 0, 0, 0 }, 0 },
182 { /* group 7 - operands are defined here */
183 { "sgdt", 0, true, { Ms, 0, 0 }, 0 },
184 { "sidt", 0, true, { Ms, 0, 0 }, 0 },
185 { "lgdt", 0, true, { Ms, 0, 0 }, 0 },
186 { "lidt", 0, true, { Ms, 0, 0 }, 0 },
187 { "smsw", 0, true, { Ew, 0, 0 }, 0 },
188 { 0, Ill, 0, { 0, 0, 0 }, 0 },
189 { "lmsw", 0, true, { Ew, 0, 0 }, 0 },
190 { "invlpg", 0, true, { 0, 0, 0 }, 0 },
193 { /* group 8 - only opcode is defined here,
194 operands are defined in the one or two byte maps below */
195 { 0, Ill, 0, { 0, 0, 0 }, 0 },
196 { 0, Ill, 0, { 0, 0, 0 }, 0 },
197 { 0, Ill, 0, { 0, 0, 0 }, 0 },
198 { 0, Ill, 0, { 0, 0, 0 }, 0 },
199 { "bt", 0, true, { 0, 0, 0 }, 0 },
200 { "bts", 0, true, { 0, 0, 0 }, 0 },
201 { "btr", 0, true, { 0, 0, 0 }, 0 },
202 { "btc", 0, true, { 0, 0, 0 }, 0 },
205 { /* group 9 - operands are defined here */
206 { 0, Ill, 0, { 0, 0, 0 }, 0 },
207 { "cmpxch8b", 0, true, { Mq, 0, 0 }, 0 },
208 { 0, Ill, 0, { 0, 0, 0 }, 0 },
209 { 0, Ill, 0, { 0, 0, 0 }, 0 },
210 { 0, Ill, 0, { 0, 0, 0 }, 0 },
211 { 0, Ill, 0, { 0, 0, 0 }, 0 },
212 { 0, Ill, 0, { 0, 0, 0 }, 0 },
213 { 0, Ill, 0, { 0, 0, 0 }, 0 }
217 // twoByteMap: two byte opcode instructions (first byte is 0x0F)
218 static x86_insn twoByteMap[256] = {
220 { 0, Grp6, true, { 0, 0, 0 }, 0 },
221 { 0, 0, false, { 0, 0, 0 }, 0 },
222 { "lar", twoB, true, { Gv, Ew, 0 }, 0 },
223 { "lsl", twoB, true, { Gv, Ew, 0 }, 0 },
226 { "clts", twoB, false, { 0, 0, 0 }, 0 },
229 { "invd", twoB, false, { 0, 0, 0 }, 0 },
230 { "wbinvd", twoB, false, { 0, 0, 0 }, 0 },
238 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
239 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
241 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
242 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
244 { "mov", twoB, true, { Rd, Cd, 0 }, 0 },
245 { "mov", twoB, true, { Rd, Dd, 0 }, 0 },
246 { "mov", twoB, true, { Cd, Rd, 0 }, 0 },
247 { "mov", twoB, true, { Dd, Rd, 0 }, 0 },
248 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
250 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
251 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
253 { "wrmsr", twoB, false, { 0, 0, 0 }, 0 },
254 { "rdtsc", twoB, false, { 0, 0, 0 }, 0 },
255 { "rdmsr", twoB, false, { 0, 0, 0 }, 0 },
257 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
259 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
260 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
262 { "cmovo", twoB, true, { Gv, Ev, 0 }, 0 },
263 { "cmovno", twoB, true, { Gv, Ev, 0 }, 0 },
264 { "cmovnae", twoB, true, { Gv, Ev, 0 }, 0 },
265 { "cmovnb", twoB, true, { Gv, Ev, 0 }, 0 },
266 { "cmove", twoB, true, { Gv, Ev, 0 }, 0 },
267 { "cmovne", twoB, true, { Gv, Ev, 0 }, 0 },
268 { "cmovbe", twoB, true, { Gv, Ev, 0 }, 0 },
269 { "cmovnbe", twoB, true, { Gv, Ev, 0 }, 0 },
271 { "cmovs", twoB, true, { Gv, Ev, 0 }, 0 },
272 { "cmovns", twoB, true, { Gv, Ev, 0 }, 0 },
273 { "cmovpe", twoB, true, { Gv, Ev, 0 }, 0 },
274 { "cmovpo", twoB, true, { Gv, Ev, 0 }, 0 },
275 { "cmovnge", twoB, true, { Gv, Ev, 0 }, 0 },
276 { "cmovnl", twoB, true, { Gv, Ev, 0 }, 0 },
277 { "cmovng", twoB, true, { Gv, Ev, 0 }, 0 },
278 { "cmovnl", twoB, true, { Gv, Ev, 0 }, 0 },
280 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
281 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
283 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
284 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
286 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
287 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
289 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
290 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
292 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
293 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
295 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
296 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
298 { "jo", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
299 { "jno", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
300 { "jb", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
301 { "jnb", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
302 { "jz", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
303 { "jnz", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
304 { "jbe", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
305 { "jnbe", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
307 { "js", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
308 { "jns", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
309 { "jp", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
310 { "jnp", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
311 { "jl", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
312 { "jnl", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
313 { "jle", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
314 { "jnle", twoB, false, { Jv, 0, 0 }, (IS_JCC | REL_X) },
316 { "seto", twoB, true, { Eb, 0, 0 }, 0 },
317 { "setno", twoB, true, { Eb, 0, 0 }, 0 },
318 { "setb", twoB, true, { Eb, 0, 0 }, 0 },
319 { "setnb", twoB, true, { Eb, 0, 0 }, 0 },
320 { "setz", twoB, true, { Eb, 0, 0 }, 0 },
321 { "setnz", twoB, true, { Eb, 0, 0 }, 0 },
322 { "setbe", twoB, true, { Eb, 0, 0 }, 0 },
323 { "setnbe", twoB, true, { Eb, 0, 0 }, 0 },
325 { "sets", twoB, true, { Eb, 0, 0 }, 0 },
326 { "setns", twoB, true, { Eb, 0, 0 }, 0 },
327 { "setp", twoB, true, { Eb, 0, 0 }, 0 },
328 { "setnp", twoB, true, { Eb, 0, 0 }, 0 },
329 { "setl", twoB, true, { Eb, 0, 0 }, 0 },
330 { "setnl", twoB, true, { Eb, 0, 0 }, 0 },
331 { "setle", twoB, true, { Eb, 0, 0 }, 0 },
332 { "setnle", twoB, true, { Eb, 0, 0 }, 0 },
334 { "push", twoB, false, { FS, 0, 0 }, 0 },
335 { "pop", twoB, false, { FS, 0, 0 }, 0 },
336 { "cpuid", twoB, false, { 0, 0, 0 }, 0 },
337 { "bt", twoB, true, { Ev, Gv, 0 }, 0 },
338 { "shld", twoB, true, { Ev, Gv, Ib }, 0 },
339 { "shld", twoB, true, { Ev, Gv, CL }, 0 },
343 { "push", twoB, false, { GS, 0, 0 }, 0 },
344 { "pop", twoB, false, { GS, 0, 0 }, 0 },
345 { "rsm", twoB, false, { 0, 0, 0 }, 0 },
346 { "bts", twoB, true, { Ev, Gv, 0 }, 0 },
347 { "shrd", twoB, true, { Ev, Gv, Ib }, 0 },
348 { "shrd", twoB, true, { Ev, Gv, CL }, 0 },
350 { "imul", twoB, true, { Gv, Ev, 0 }, 0 },
352 { "cmpxch", twoB, true, { Eb, Gb, 0 }, 0 },
353 { "cmpxch", twoB, true, { Ev, Gv, 0 }, 0 },
354 { "lss", twoB, true, { Mp, 0, 0 }, 0 },
355 { "btr", twoB, true, { Ev, Gv, 0 }, 0 },
356 { "lfs", twoB, true, { Mp, 0, 0 }, 0 },
357 { "lgs", twoB, true, { Mp, 0, 0 }, 0 },
358 { "movzx", twoB, true, { Gv, Eb, 0 }, 0 },
359 { "movzx", twoB, true, { Gv, Ew, 0 }, 0 },
363 { 0, Grp8, true, { Ev, Ib, 0 }, 0 },
364 { "btc", twoB, true, { Ev, Gv, 0 }, 0 },
365 { "bsf", twoB, true, { Gv, Ev, 0 }, 0 },
366 { "bsr", twoB, true, { Gv, Ev, 0 }, 0 },
367 { "movsx", twoB, true, { Gv, Eb, 0 }, 0 },
368 { "movsx", twoB, true, { Gv, Ew, 0 }, 0 },
370 { "xadd", twoB, true, { Eb, Gb, 0 }, 0 },
371 { "xadd", twoB, true, { Ev, Gv, 0 }, 0 },
377 { 0, Grp9, true, { 0, 0, 0 }, 0 },
379 { "bswap", twoB, false, { rEAX, 0, 0 }, 0 },
380 { "bswap", twoB, false, { rECX, 0, 0 }, 0 },
381 { "bswap", twoB, false, { rEDX, 0, 0 }, 0 },
382 { "bswap", twoB, false, { rEBX, 0, 0 }, 0 },
383 { "bswap", twoB, false, { rESP, 0, 0 }, 0 },
384 { "bswap", twoB, false, { rEBP, 0, 0 }, 0 },
385 { "bswap", twoB, false, { rESI, 0, 0 }, 0 },
386 { "bswap", twoB, false, { rEDI, 0, 0 }, 0 },
388 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
389 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
391 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
392 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
394 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
395 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
397 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
398 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
400 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
401 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
403 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
404 {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0}, {0,Ill,0,{0,0,0},0},
408 // oneByteMap: one byte opcode map
409 static x86_insn oneByteMap[256] = {
411 { "add", oneB, true, { Eb, Gb, 0 }, 0 },
412 { "add", oneB, true, { Ev, Gv, 0 }, 0 },
413 { "add", oneB, true, { Gb, Eb, 0 }, 0 },
414 { "add", oneB, true, { Gv, Ev, 0 }, 0 },
415 { "add", oneB, false, { AL, Ib, 0 }, 0 },
416 { "add", oneB, false, { eAX, Iv, 0 }, 0 },
417 { "push", oneB, false, { ES, 0, 0 }, 0 },
418 { "pop", oneB, false, { ES, 0, 0 }, 0 },
420 { "or", oneB, true, { Eb, Gb, 0 }, 0 },
421 { "or", oneB, true, { Ev, Gv, 0 }, 0 },
422 { "or", oneB, true, { Gb, Eb, 0 }, 0 },
423 { "or", oneB, true, { Gv, Ev, 0 }, 0 },
424 { "or", oneB, false, { AL, Ib, 0 }, 0 },
425 { "or", oneB, false, { eAX, Iv, 0 }, 0 },
426 { "push", oneB, false, { ES, 0, 0 }, 0 },
427 { 0 , twoB, false, { 0, 0, 0 }, 0 },
429 { "adc", oneB, true, { Eb, Gb, 0 }, 0 },
430 { "adc", oneB, true, { Ev, Gv, 0 }, 0 },
431 { "adc", oneB, true, { Gb, Eb, 0 }, 0 },
432 { "adc", oneB, true, { Gv, Ev, 0 }, 0 },
433 { "adc", oneB, false, { AL, Ib, 0 }, 0 },
434 { "adc", oneB, false, { eAX, Iv, 0 }, 0 },
435 { "push", oneB, false, { SS, 0, 0 }, 0 },
436 { "pop", oneB, false, { SS, 0, 0 }, 0 },
438 { "sbb", oneB, true, { Eb, Gb, 0 }, 0 },
439 { "sbb", oneB, true, { Ev, Gv, 0 }, 0 },
440 { "sbb", oneB, true, { Gb, Eb, 0 }, 0 },
441 { "sbb", oneB, true, { Gv, Ev, 0 }, 0 },
442 { "sbb", oneB, false, { AL, Ib, 0 }, 0 },
443 { "sbb", oneB, false, { eAX, Iv, 0 }, 0 },
444 { "push", oneB, false, { DS, 0, 0 }, 0 },
445 { "pop" , oneB, false, { DS, 0, 0 }, 0 },
447 { "and", oneB, true, { Eb, Gb, 0 }, 0 },
448 { "and", oneB, true, { Ev, Gv, 0 }, 0 },
449 { "and", oneB, true, { Gb, Eb, 0 }, 0 },
450 { "and", oneB, true, { Gv, Ev, 0 }, 0 },
451 { "and", oneB, false, { AL, Ib, 0 }, 0 },
452 { "and", oneB, false, { eAX, Iv, 0 }, 0 },
453 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
454 { "daa", oneB, false, { 0, 0, 0 }, 0 },
456 { "sub", oneB, true, { Eb, Gb, 0 }, 0 },
457 { "sub", oneB, true, { Ev, Gv, 0 }, 0 },
458 { "sub", oneB, true, { Gb, Eb, 0 }, 0 },
459 { "sub", oneB, true, { Gv, Ev, 0 }, 0 },
460 { "sub", oneB, false, { AL, Ib, 0 }, 0 },
461 { "sub", oneB, false, { eAX, Iv, 0 }, 0 },
462 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
463 { "das" , oneB, false, { 0, 0, 0 }, 0 },
465 { "xor", oneB, true, { Eb, Gb, 0 }, 0 },
466 { "xor", oneB, true, { Ev, Gv, 0 }, 0 },
467 { "xor", oneB, true, { Gb, Eb, 0 }, 0 },
468 { "xor", oneB, true, { Gv, Ev, 0 }, 0 },
469 { "xor", oneB, false, { AL, Ib, 0 }, 0 },
470 { "xor", oneB, false, { eAX, Iv, 0 }, 0 },
471 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
472 { "aaa", oneB, false, { 0, 0, 0 }, 0 },
474 { "cmp", oneB, true, { Eb, Gb, 0 }, 0 },
475 { "cmp", oneB, true, { Ev, Gv, 0 }, 0 },
476 { "cmp", oneB, true, { Gb, Eb, 0 }, 0 },
477 { "cmp", oneB, true, { Gv, Ev, 0 }, 0 },
478 { "cmp", oneB, false, { AL, Ib, 0 }, 0 },
479 { "cmp", oneB, false, { eAX, Iv, 0 }, 0 },
480 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
481 { "aas" , oneB, false, { 0, 0, 0 }, 0 },
483 { "inc", oneB, false, { eAX, 0, 0 }, 0 },
484 { "inc", oneB, false, { eCX, 0, 0 }, 0 },
485 { "inc", oneB, false, { eDX, 0, 0 }, 0 },
486 { "inc", oneB, false, { eBX, 0, 0 }, 0 },
487 { "inc", oneB, false, { eSP, 0, 0 }, 0 },
488 { "inc", oneB, false, { eBP, 0, 0 }, 0 },
489 { "inc", oneB, false, { eSI, 0, 0 }, 0 },
490 { "inc", oneB, false, { eDI, 0, 0 }, 0 },
492 { "dec", oneB, false, { eAX, 0, 0 }, 0 },
493 { "dec", oneB, false, { eCX, 0, 0 }, 0 },
494 { "dec", oneB, false, { eDX, 0, 0 }, 0 },
495 { "dec", oneB, false, { eBX, 0, 0 }, 0 },
496 { "dec", oneB, false, { eSP, 0, 0 }, 0 },
497 { "dec", oneB, false, { eBP, 0, 0 }, 0 },
498 { "dec", oneB, false, { eSI, 0, 0 }, 0 },
499 { "dec", oneB, false, { eDI, 0, 0 }, 0 },
501 { "push", oneB, false, { eAX, 0, 0 }, 0 },
502 { "push", oneB, false, { eCX, 0, 0 }, 0 },
503 { "push", oneB, false, { eDX, 0, 0 }, 0 },
504 { "push", oneB, false, { eBX, 0, 0 }, 0 },
505 { "push", oneB, false, { eSP, 0, 0 }, 0 },
506 { "push", oneB, false, { eBP, 0, 0 }, 0 },
507 { "push", oneB, false, { eSI, 0, 0 }, 0 },
508 { "push", oneB, false, { eDI, 0, 0 }, 0 },
510 { "pop", oneB, false, { eAX, 0, 0 }, 0 },
511 { "pop", oneB, false, { eCX, 0, 0 }, 0 },
512 { "pop", oneB, false, { eDX, 0, 0 }, 0 },
513 { "pop", oneB, false, { eBX, 0, 0 }, 0 },
514 { "pop", oneB, false, { eSP, 0, 0 }, 0 },
515 { "pop", oneB, false, { eBP, 0, 0 }, 0 },
516 { "pop", oneB, false, { eSI, 0, 0 }, 0 },
517 { "pop", oneB, false, { eDI, 0, 0 }, 0 },
519 { "pusha(d)", oneB, false, { 0, 0, 0 }, 0 },
520 { "popa(d)", oneB, false, { 0, 0, 0 }, 0 },
521 { "bound", oneB, true, { Gv, Ma, 0 }, 0 },
522 { "arpl", oneB, true, { Ew, Gw, 0 }, 0 },
523 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
524 { 0, PREFIX_SEG_OVR, false, { 0, 0, 0 }, 0 },
525 { 0, PREFIX_OPR_SZ, false, { 0, 0, 0 }, 0 }, /* operand size prefix */
526 { 0, PREFIX_ADDR_SZ, false, { 0, 0, 0 }, 0 }, /* address size prefix */
528 { "push", oneB, false, { Iv, 0, 0 }, 0 },
529 { "imul", oneB, true, { Gv, Ev, Iv }, 0 },
530 { "push", oneB, false, { Ib, 0, 0 }, 0 },
531 { "imul", oneB, true, { Gv, Ev, Ib }, 0 },
532 { "insb", oneB, false, { Yb, DX, 0 }, 0 },
533 { "insw/d", oneB, false, { Yv, DX, 0 }, 0 },
534 { "outsb", oneB, false, { DX, Xb, 0 }, 0 },
535 { "outsw/d", oneB, false, { DX, Xv, 0 }, 0 },
537 { "jo", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
538 { "jno", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
539 { "jb/jnaej/j", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
540 { "jnb/jae/j", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
541 { "jz", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
542 { "jnz", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
543 { "jbe", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
544 { "jnbe", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
546 { "js", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
547 { "jns", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
548 { "jp", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
549 { "jnp", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
550 { "jl", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
551 { "jnl", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
552 { "jle", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
553 { "jnle", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
555 { 0, Grp1, true, { Eb, Ib, 0 }, 0 },
556 { 0, Grp1, true, { Ev, Iv, 0 }, 0 },
557 { 0, Ill, 0, { 0, 0, 0 }, 0 },
558 { 0, Grp1, true, { Ev, Ib, 0 }, 0 },
559 { "test", oneB, true, { Eb, Gb, 0 }, 0 },
560 { "test", oneB, true, { Ev, Gv, 0 }, 0 },
561 { "xchg", oneB, true, { Eb, Gb, 0 }, 0 },
562 { "xchg", oneB, true, { Ev, Gv, 0 }, 0 },
564 { "mov", oneB, true, { Eb, Gb, 0 }, 0 },
565 { "mov", oneB, true, { Ev, Gv, 0 }, 0 },
566 { "mov", oneB, true, { Gb, Eb, 0 }, 0 },
567 { "mov", oneB, true, { Gv, Ev, 0 }, 0 },
568 { "mov", oneB, true, { Ew, Sw, 0 }, 0 },
569 { "lea", oneB, true, { Gv, M, 0 }, 0 },
570 { "mov", oneB, true, { Sw, Ew, 0 }, 0 },
571 { "pop", oneB, true, { Ev, 0, 0, }, 0 },
573 { "nop", oneB, false, { 0, 0, 0 }, 0 },
574 { "xchg", oneB, false, { eCX, 0, 0 }, 0 },
575 { "xchg", oneB, false, { eDX, 0, 0 }, 0 },
576 { "xchg", oneB, false, { eBX, 0, 0 }, 0 },
577 { "xchg", oneB, false, { eSP, 0, 0 }, 0 },
578 { "xchg", oneB, false, { eBP, 0, 0 }, 0 },
579 { "xchg", oneB, false, { eSI, 0, 0 }, 0 },
580 { "xchg", oneB, false, { eDI, 0, 0 }, 0 },
582 { "cbw", oneB, false, { 0, 0, 0 }, 0 },
583 { "cwd/cdq", oneB, false, { 0, 0, 0 }, 0 },
584 { "call", oneB, false, { Ap, 0, 0}, IS_CALL | PTR_WX },
585 { "wait", oneB, false, { 0, 0, 0 }, 0 },
586 { "pushf", oneB, false, { Fv, 0, 0 }, 0 },
587 { "pop", oneB, false, { Fv, 0, 0 }, 0 },
588 { "sahf", oneB, false, { 0, 0, 0 }, 0 },
589 { "lahf", oneB, false, { 0, 0, 0 }, 0 },
591 { "mov", oneB, false, { AL, Ob, 0 }, 0 },
592 { "mov", oneB, false, { eAX, Ov, 0 }, 0 },
593 { "mov", oneB, false, { Ob, AL, 0 }, 0 },
594 { "mov", oneB, false, { Ov, eAX, 0 }, 0 },
595 { "movsb", oneB, false, { Xb, Yb, 0 }, 0 },
596 { "movsw", oneB, false, { Xv, Yv, 0 }, 0 },
597 { "cmpsb", oneB, false, { Xb, Yb, 0 }, 0 },
598 { "cmpsw", oneB, false, { Xv, Yv, 0 }, 0 },
600 { "test", oneB, false, { AL, Ib, 0 }, 0 },
601 { "test", oneB, false, { eAX, Iv, 0 }, 0 },
602 { "stopsb", oneB, false, { Yb, AL, 0 }, 0 },
603 { "stopsw/d", oneB, false, { Yv, eAX, 0 }, 0 },
604 { "lodsb", oneB, false, { AL, Xb, 0 }, 0 },
605 { "lodsw", oneB, false, { eAX, Xv, 0 }, 0 },
606 { "scasb", oneB, false, { AL, Yb, 0 }, 0 },
607 { "scasw/d", oneB, false, { eAX, Yv, 0 }, 0 },
609 { "mov", oneB, false, { AL, Ib, 0 }, 0 },
610 { "mov", oneB, false, { CL, Ib, 0 }, 0 },
611 { "mov", oneB, false, { DL, Ib, 0 }, 0 },
612 { "mov", oneB, false, { BL, Ib, 0 }, 0 },
613 { "mov", oneB, false, { AH, Ib, 0 }, 0 },
614 { "mov", oneB, false, { CH, Ib, 0 }, 0 },
615 { "mov", oneB, false, { DH, Ib, 0 }, 0 },
616 { "mov", oneB, false, { BH, Ib, 0 }, 0 },
618 { "mov", oneB, false, { eAX, Iv, 0 }, 0 },
619 { "mov", oneB, false, { eCX, Iv, 0 }, 0 },
620 { "mov", oneB, false, { eDX, Iv, 0 }, 0 },
621 { "mov", oneB, false, { eBX, Iv, 0 }, 0 },
622 { "mov", oneB, false, { eSP, Iv, 0 }, 0 },
623 { "mov", oneB, false, { eBP, Iv, 0 }, 0 },
624 { "mov", oneB, false, { eSI, Iv, 0 }, 0 },
625 { "mov", oneB, false, { eDI, Iv, 0 }, 0 },
627 { 0, Grp2, true, { Eb, Ib, 0 }, 0 },
628 { 0, Grp2, true, { Ev, Ib, 0 }, 0 },
629 { "ret near", oneB, false, { Iw, 0, 0 }, (IS_RET) },
630 { "ret near", oneB, false, { 0, 0, 0 }, (IS_RET) },
631 { "les", oneB, true, { Gv, Mp, 0 }, 0 },
632 { "lds", oneB, true, { Gv, Mp, 0 }, 0 },
633 { "mov", oneB, true, { Eb, Ib, 0 }, 0 },
634 { "mov", oneB, true, { Ev, Iv, 0 }, 0 },
636 { "enter", oneB, false, { Iw, Ib, 0 }, 0 },
637 { "leave", oneB, false, { 0, 0, 0 }, 0 },
638 { "ret far", oneB, false, { Iw, 0, 0 }, (IS_RETF) },
639 { "ret far", oneB, false, { 0, 0, 0 }, (IS_RETF) },
640 { "int 3", oneB, false, { 0, 0, 0 }, 0 },
641 { "int", oneB, false, { Ib, 0, 0 }, 0 },
642 { "into", oneB, false, { 0, 0, 0 }, 0 },
643 { "iret", oneB, false, { 0, 0, 0 }, (IS_RET) },
645 { 0, Grp2, true, { Eb, const1, 0 }, 0 },
646 { 0, Grp2, true, { Ev, const1, 0 }, 0 },
647 { 0, Grp2, true, { Eb, CL, 0 }, 0 },
648 { 0, Grp2, true, { Ev, CL, 0 }, 0 },
649 { "aam", oneB, false, { 0, 0, 0 }, 0 },
650 { "aad", oneB, false, { 0, 0, 0 }, 0 },
651 { 0, Ill, 0, { 0, 0, 0 }, 0 },
652 { "xlat", oneB, false, { 0, 0, 0 }, 0 },
654 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
655 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
656 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
657 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
658 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
659 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
660 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
661 { 0, coprocEsc, true, { 0, 0, 0 }, 0 },
663 { "loopn", oneB, false, { Jb, 0, 0 }, 0 },
664 { "loope", oneB, false, { Jb, 0, 0 }, 0 },
665 { "loop", oneB, false, { Jb, 0, 0 }, 0 },
666 { "jcxz/jec", oneB, false, { Jb, 0, 0 }, (IS_JCC | REL_B) },
667 { "in", oneB, false, { AL, Ib, 0 }, 0 },
668 { "in", oneB, false, { eAX, Ib, 0 }, 0 },
669 { "out", oneB, false, { Ib, AL, 0 }, 0 },
670 { "out", oneB, false, { Ib, eAX, 0 }, 0 },
672 { "call", oneB, false, { Jv, 0, 0 }, (IS_CALL | REL_X) },
673 { "jmp", oneB, false, { Jv, 0, 0 }, (IS_JUMP | REL_X) },
674 { "jmp", oneB, false, { Ap, 0, 0 }, (IS_JUMP | PTR_WX) },
675 { "jmp", oneB, false, { Jb, 0, 0 }, (IS_JUMP | REL_B) },
676 { "in", oneB, false, { AL, DX, 0 }, 0 },
677 { "in", oneB, false, { eAX, DX, 0 }, 0 },
678 { "out", oneB, false, { DX, AL, 0 }, 0 },
679 { "out", oneB, false, { DX, eAX, 0 }, 0 },
681 { 0, PREFIX_INSTR, false, { 0, 0, 0 }, 0 },
682 { 0, 0, false, { 0, 0, 0 }, 0 },
683 { 0, PREFIX_INSTR, false, { 0, 0, 0 }, 0 },
684 { 0, PREFIX_INSTR, false, { 0, 0, 0 }, 0 },
685 { "hlt", oneB, false, { 0, 0, 0 }, 0 },
686 { "cmc", oneB, false, { 0, 0, 0 }, 0 },
687 { 0, Grp3a, true, { Eb, 0, 0 }, 0 },
688 { 0, Grp3b, true, { Ev, 0, 0 }, 0 },
690 { "clc", oneB, false, { 0, 0, 0 }, 0 },
691 { "stc", oneB, false, { 0, 0, 0 }, 0 },
692 { "cli", oneB, false, { 0, 0, 0 }, 0 },
693 { "sti", oneB, false, { 0, 0, 0 }, 0 },
694 { "cld", oneB, false, { 0, 0, 0 }, 0 },
695 { "std", oneB, false, { 0, 0, 0 }, 0 },
696 { 0, Grp4, true, { 0, 0, 0 }, 0 },
697 { 0, Grp5, true, { 0, 0, 0 }, 0 }
701 /* decodes an operand especified in the ModRM byte. Return the size in bytes of the
702 operand field, not counting the ModRM byte.
704 static unsigned doModRMOperand(const unsigned addrSzAttr, // the address size attr.
705 const unsigned Mod, // mod field
706 const unsigned RM, // RM field
707 const unsigned SIB) // SIB byte
709 if (addrSzAttr == 1) { // 16-bit addressing - use table 25-2 in the Pentium manual
710 if ((Mod == 0 && RM == 6) || (Mod == 2)) {
720 else { // 32-bit addressing - use table 25-3 in the Pentium manual
721 if ((Mod == 0 && RM == 5) || (Mod == 2)) {
728 // check SIB: there is a 32 bit displacement if Mod = 0 and
729 // the base field of SIB is 5
730 if (Mod == 0 && RM == 4 && ((SIB & 0x7) == 5))
741 decodes an operand of an instruction.
742 Return the size in bytes of the operand fields. If the operand is encoded in the
743 opcode or in the ModR/M byte, the size returned is zero.
745 static unsigned doOperand(const unsigned operandType, // type descriptor of operand
746 const unsigned operandSzAttr, // operand sz. attribute
747 const unsigned addrSzAttr, // address sz. attribute
748 const unsigned Mod, // MOD field
749 const unsigned RM, // RM field
750 const unsigned SIB) // SIB byte
752 switch (operandType) {
754 /* direct address of operand encoded in instruction as a segment number (word)
755 and an offset (word or dword)
757 return (wordSzB + (addrSzAttr * wordSzB));
762 // ModRM byte selects operand
770 /* the operand is either a register or a memory operand.
771 The operand size doesn't matter here as the instruction does not have the
772 operand itself, but only its address.
773 Only the address size is used here.
775 return doModRMOperand(addrSzAttr, Mod, RM, SIB);
779 // operand is flag register
786 // operand encoded in modR/M byte
790 case Ib: /* immediate byte */
793 case Iv: /* immediate word or dword */
794 return (wordSzB * operandSzAttr);
796 case Iw: /* immediate word */
800 case Jb: /* byte relative offset in instruction */
803 case Jv: /* word or dword relative offset in instruction */
804 return (wordSzB * operandSzAttr);
812 /* Like E but the operand can be only a memory operand.
813 The operand size doesn't matter here as the instruction does not have the
814 operand itself, but only its address.
815 Only the address size is used here.
817 return doModRMOperand(addrSzAttr, Mod, RM, SIB);
822 /* offset of operand encoded as word or dword */
823 return (wordSzB * addrSzAttr);
831 // operand defined in reg field of ModR/M byte
850 if (operandType >= CS && operandType <= rESP)
853 // should not be reached
858 /* decodes the operands, return the total size in bytes of the operands */
859 static unsigned doOperands(unsigned operands[3],
860 const unsigned operandSzAttr, const unsigned addrSzAttr,
861 const unsigned Mod, const unsigned RM, const unsigned SIB)
865 size += doOperand(operands[0], operandSzAttr, addrSzAttr, Mod, RM, SIB);
868 size += doOperand(operands[1], operandSzAttr, addrSzAttr, Mod, RM, SIB);
871 size += doOperand(operands[2], operandSzAttr, addrSzAttr, Mod, RM, SIB);
877 unsigned get_instruction2(const unsigned char* addr, unsigned &insnType)
879 bool instrPrefix = false;
880 bool addrSzPrefix = false;
881 bool oprSzPrefix = false;
882 bool segOvrPrefix = false;
884 unsigned operandSzAttr = 2;
885 unsigned addrSzAttr = 2;
887 const unsigned char *nextb = addr;
891 unsigned ModRMbyte = 0;
902 desc = &oneByteMap[*nextb++];
903 code = desc->escape_code;
904 if (code == PREFIX_INSTR)
906 else if (code == PREFIX_ADDR_SZ)
908 else if (code == PREFIX_OPR_SZ)
910 else if (code == PREFIX_SEG_OVR)
922 /* if it is a two byte opcode instruction, fetch the next opcode byte
923 and decode using twoByteMap */
925 desc = &twoByteMap[*nextb++];
926 code = desc->escape_code;
929 // check if the instruction has Mod/RM and SIB bytes
930 if (desc->hasModRM) {
931 ModRMbyte = *nextb++;
932 Mod = ModRMbyte >> 6;
933 RM = ModRMbyte & 0x07;
934 Reg = (ModRMbyte >> 3) & 0x07;
935 hasSIB = (Mod != 3) && (RM == 4);
941 /* now decode the instruction */
945 insnType = desc->insnType;
946 if (insnType & REL_X) {
947 // set the correct size for the operand
948 if (operandSzAttr == 1)
953 //assert(desc->name);
954 //printf("%s ", desc->name);
955 nextb += doOperands(desc->operands, operandSzAttr, addrSzAttr, Mod, RM, SIB);
961 // operands defined in oneByteMap
962 insnType = desc->insnType;
963 descAux = &groupMap[code][Reg];
964 //assert(descAux->name);
965 //printf("%s ", descAux->name);
966 nextb += doOperands(desc->operands, operandSzAttr, addrSzAttr, Mod, RM, SIB);
976 // operands defined in groupMap
977 descAux = &groupMap[code][Reg];
978 insnType = descAux->insnType;
979 //assert(descAux->name);
980 //printf("%s ", descAux->name);
981 nextb += doOperands(descAux->operands, operandSzAttr, addrSzAttr, Mod, RM, SIB);
986 //fprintf(stderr,"FP instruction %x\n", nextb);
987 if (ModRMbyte <= 0xBF) {
988 nextb += doModRMOperand(addrSzAttr, Mod, RM, SIB);
997 // should not be reached
1002 // set the correct size for the operand in insnType
1003 if (insnType & REL_X) {
1004 if (operandSzAttr == 1)
1009 else if (insnType & PTR_WX) {
1010 if (operandSzAttr == 1)
1016 // set the prefix flags in insnType
1018 insnType |= PREFIX_INST;
1020 insnType |= PREFIX_ADDR;
1022 insnType |= PREFIX_OPR;
1024 insnType |= PREFIX_SEG;
1026 return (nextb - addr);
1029 /* decode instruction at address addr, return size of instruction */
1030 unsigned get_instruction(const unsigned char* addr, unsigned &insnType)
1036 #if defined(i386_unknown_nt4_0) && _MSC_VER < 1300
1037 ia32_decode(0, addr, i);
1039 ia32_decode<0>(addr, i);
1042 insnType1 = ia32_emulate_old_type(i);
1048 r2 = get_instruction2(addr, insnType2);
1050 fprintf(stderr, "[L] %d!=%d @ %p:", r1, r2, addr);
1051 for(int i=0; i<10; ++i)
1052 fprintf(stderr, " %x", addr[i]);
1053 fprintf(stderr, "\n");
1055 if(insnType1 != insnType2) {
1056 fprintf(stderr, "[T] %x!=%x @ %p:", insnType1, insnType2, addr);
1057 for(int i=0; i<10; ++i)
1058 fprintf(stderr, " %x", addr[i]);
1059 fprintf(stderr, "\n");
1063 insnType = insnType1;
1068 /* CODE ADDED FOR FUNCTION RELOCATION */
1070 /*************************************************************************/
1071 /*************************************************************************/
1073 // find the target of a jump or call
1075 Address get_target(const unsigned char *instr, unsigned type, unsigned size,
1077 int disp = displacement(instr, type);
1078 return (Address)(addr + size + disp);
1082 // get the displacement of a jump or call
1084 int displacement(const unsigned char *instr, unsigned type) {
1088 if (type & IS_JUMP) {
1090 disp = *(const char *)(instr+1);
1091 } else if (type & REL_W) {
1092 disp = *(const short *)(instr+2); // skip prefix and opcode
1093 } else if (type & REL_D) {
1094 disp = *(const int *)(instr+1);
1096 } else if (type & IS_JCC) {
1098 disp = *(const char *)(instr+1);
1099 } else if (type & REL_W) {
1100 disp = *(const short *)(instr+3); // skip prefix and two byte opcode
1101 } else if (type & REL_D) {
1102 disp = *(const int *)(instr+2); // skip two byte opcode
1104 } else if (type & IS_CALL) {
1106 disp = *(const short *)(instr+2); // skip prefix and opcode
1107 } else if (type & REL_D) {
1108 disp = *(const int *)(instr+1);
1116 // get the displacement of a relative jump or call
1118 int get_disp(instruction *insn) {
1119 return displacement(insn->ptr(), insn->type());
1123 // if setDisp is true set the target of a relative jump or call insn
1124 // otherwise, return the number of bytes needed to expand the present
1125 // instruction so that its target is in the range of its displacement.
1126 // In cases where we have a short near jump out of the function, we always
1127 // want to expand it to a 4 byte jump
1129 int set_disp(bool setDisp, instruction *insn, int newOffset, bool outOfFunc) {
1131 unsigned char *instr = (const_cast<unsigned char *> (insn->ptr()));
1132 unsigned type = insn->type();
1134 if (!((type & IS_JUMP) || (type & IS_JCC) || (type & IS_CALL))) return 0;
1136 if (type & IS_CALL) {
1139 return 2; // go from 3 to 5 bytes;
1143 *((short *) instr) = (short) newOffset;
1151 *((int *) instr) = (int) newOffset;
1159 // assert((type & IS_JUMP) || (type & IS_JCC));
1162 if (*instr == JCXZ) {
1163 if (newOffset > 127 || newOffset < -128 || outOfFunc) {
1164 return 7; // go from 2 to 9 bytes
1168 *((char *) instr) = (char) newOffset;
1173 if (type & IS_JCC) {
1174 if (newOffset > 127 || newOffset < -128 || outOfFunc) {
1175 return 4; // go from 2 to 6 bytes
1179 *((char *) instr) = (char) newOffset;
1184 if (type & IS_JUMP) {
1185 if (newOffset > 127 || newOffset < -128 || outOfFunc) {
1186 return 3; // go from 2 to 5 bytes
1190 *((char *) instr) = (char) newOffset;
1199 if (newOffset > 32767 || newOffset < -32768 || outOfFunc) {
1200 return 1; // drop the PREFIX_OPR, add 2 bytes for disp
1203 if (type & PREFIX_OPR)
1205 if (type & PREFIX_SEG)
1208 *((short *) instr) = (short) newOffset;
1214 if (type & PREFIX_SEG)
1219 *((int *) instr) = (int) newOffset;
1227 int addressOfMachineInsn(instruction *insn) {
1228 return (int)insn->ptr();
1231 int sizeOfMachineInsn(instruction *insn) {
1232 return insn->size();
1235 /*********************************************************************/
1236 /*********************************************************************/
1240 //This function decodes the addressing modes used for call instructions
1241 //For documentation on these mode, and how to decode them, see tables
1242 //2-2 and 2-3 from the intel software developers manual.
1243 int get_instruction_operand(const unsigned char *ptr, Register& base_reg,
1244 Register& index_reg, int& displacement,
1245 unsigned& scale, unsigned &Mod){
1251 unsigned SIBbyte = 0;
1253 //Initialize default values to an appropriately devilish number
1261 desc = &oneByteMap[*ptr++];
1262 code = desc->escape_code;
1263 if (code == PREFIX_INSTR
1264 || code == PREFIX_ADDR_SZ
1265 || code == PREFIX_OPR_SZ
1266 || code == PREFIX_SEG_OVR){
1268 //We do not have support for handling the prefixes of x86 instructions
1277 //We should never get here, there should never be a non group5
1278 //indirect call instruction
1282 //If the instruction has a mod/rm byte
1283 if (desc->hasModRM) {
1285 Mod = ModRMbyte >> 6;
1286 RM = ModRMbyte & 0x07;
1287 REG = (ModRMbyte >> 3) & 0x07;
1288 hasSIB = (Mod != 3) && (RM == 4);
1294 if (Mod == 3){ //Standard call where address is in register
1295 base_reg = (Register) RM;
1296 return REGISTER_DIRECT;
1299 displacement = *( ( const unsigned int * ) ptr );
1302 decode_SIB(SIBbyte, scale, index_reg, base_reg);
1306 base_reg = (Register) RM;
1307 return REGISTER_INDIRECT_DISPLACED;
1310 else if(Mod == 1){//call with 8-bit signed displacement
1311 displacement = *( const char * )ptr;
1314 decode_SIB(SIBbyte, scale, index_reg, base_reg);
1318 base_reg = (Register) RM;
1319 return REGISTER_INDIRECT_DISPLACED;
1324 decode_SIB(SIBbyte, scale, index_reg, base_reg);
1326 displacement = *( ( const unsigned int * )ptr );
1333 else if(RM == 5){ //The disp32 field from Table 2-2 of IA guide
1334 displacement = *( ( const unsigned int * ) ptr );
1339 base_reg = (Register) RM;
1340 return REGISTER_INDIRECT;
1345 //The call instruction is a far call, for which there
1346 //is no monitoring code
1356 //Determine appropriate scale, index, and base given SIB byte.
1357 void decode_SIB(unsigned sib, unsigned& scale, Register& index_reg, Register& base_reg){
1370 index_reg = (sib >> 3) & 0x07;
1371 base_reg = sib & 0x07;
1374 const unsigned char*
1375 skip_headers(const unsigned char* addr, bool& isWordAddr,bool& isWordOp)
1380 ia32_prefixes prefs;
1382 ia32_decode_prefixes(addr, prefs);
1383 if(prefs.getPrefix(2) == PREFIX_SZOPER)
1385 if(prefs.getPrefix(3) == PREFIX_SZADDR)
1387 return addr+prefs.getCount();
1390 bool insn_hasSIB(unsigned ModRMbyte,unsigned& Mod,unsigned& Reg,unsigned& RM){
1391 Mod = (ModRMbyte >> 6) & 0x03;
1392 Reg = (ModRMbyte >> 3) & 0x07;
1393 RM = ModRMbyte & 0x07;
1394 return ((Mod != 3) && ((RM == 4) || (RM == 5)));