3 /* Print i386 instructions for GDB, the GNU debugger.
4 Copyright (C) 1988, 1989 Free Software Foundation, Inc.
6 This file is part of GDB.
8 GDB is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
13 GDB is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GDB; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
28 * The main tables describing the instructions is essentially a copy
29 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
30 * Programmers Manual. Usually, there is a capital letter, followed
31 * by a small letter. The capital letter tell the addressing mode,
32 * and the small letter tells about the operand size. Refer to
33 * the Intel manual for details.
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
44 static void OP_E(int), OP_indirE(int), OP_G(int);
45 static void OP_I(int), OP_sI(int), OP_REG(int), OP_J(int), OP_SEG(int);
46 static void OP_DIR(int), OP_OFF(int), OP_DSSI(int), OP_ESDI(int);
47 static void OP_C(int), OP_D(int), OP_T(int), OP_rm(int);
48 static void OP_ST(int), OP_STi(int);
49 static void append_pc(unsigned long);
50 static void append_prefix(void);
51 static void dofloat(void);
52 static int get16(void);
53 static int get32(void);
54 static void oappend(const char *);
55 static void putop(const char *);
57 #define Eb OP_E, b_mode
58 #define indirEb OP_indirE, b_mode
59 #define Gb OP_G, b_mode
60 #define Ev OP_E, v_mode
61 #define indirEv OP_indirE, v_mode
62 #define Ew OP_E, w_mode
63 #define Ma OP_E, v_mode
65 #define Mp OP_E, 0 /* ? */
66 #define Gv OP_G, v_mode
67 #define Gw OP_G, w_mode
68 #define Rw OP_rm, w_mode
69 #define Rd OP_rm, d_mode
70 #define Ib OP_I, b_mode
71 #define sIb OP_sI, b_mode /* sign extended byte */
72 #define Iv OP_I, v_mode
73 #define Iw OP_I, w_mode
74 #define Jb OP_J, b_mode
75 #define Jv OP_J, v_mode
76 #define Cd OP_C, d_mode
77 #define Dd OP_D, d_mode
78 #define Td OP_T, d_mode
80 #define eAX OP_REG, eAX_reg
81 #define eBX OP_REG, eBX_reg
82 #define eCX OP_REG, eCX_reg
83 #define eDX OP_REG, eDX_reg
84 #define eSP OP_REG, eSP_reg
85 #define eBP OP_REG, eBP_reg
86 #define eSI OP_REG, eSI_reg
87 #define eDI OP_REG, eDI_reg
88 #define AL OP_REG, al_reg
89 #define CL OP_REG, cl_reg
90 #define DL OP_REG, dl_reg
91 #define BL OP_REG, bl_reg
92 #define AH OP_REG, ah_reg
93 #define CH OP_REG, ch_reg
94 #define DH OP_REG, dh_reg
95 #define BH OP_REG, bh_reg
96 #define AX OP_REG, ax_reg
97 #define DX OP_REG, dx_reg
98 #define indirDX OP_REG, indir_dx_reg
100 #define Sw OP_SEG, w_mode
101 #define Ap OP_DIR, lptr
102 #define Av OP_DIR, v_mode
103 #define Ob OP_OFF, b_mode
104 #define Ov OP_OFF, v_mode
105 #define Xb OP_DSSI, b_mode
106 #define Xv OP_DSSI, v_mode
107 #define Yb OP_ESDI, b_mode
108 #define Yv OP_ESDI, v_mode
110 #define es OP_REG, es_reg
111 #define ss OP_REG, ss_reg
112 #define cs OP_REG, cs_reg
113 #define ds OP_REG, ds_reg
114 #define fs OP_REG, fs_reg
115 #define gs OP_REG, gs_reg
157 #define indir_dx_reg 150
159 #define NOFUNC NULL, 0
161 #define GRP1b NULL, NULL, 0, NOFUNC, NOFUNC
162 #define GRP1S NULL, NULL, 1, NOFUNC, NOFUNC
163 #define GRP1Ss NULL, NULL, 2, NOFUNC, NOFUNC
164 #define GRP2b NULL, NULL, 3, NOFUNC, NOFUNC
165 #define GRP2S NULL, NULL, 4, NOFUNC, NOFUNC
166 #define GRP2b_one NULL, NULL, 5, NOFUNC, NOFUNC
167 #define GRP2S_one NULL, NULL, 6, NOFUNC, NOFUNC
168 #define GRP2b_cl NULL, NULL, 7, NOFUNC, NOFUNC
169 #define GRP2S_cl NULL, NULL, 8, NOFUNC, NOFUNC
170 #define GRP3b NULL, NULL, 9, NOFUNC, NOFUNC
171 #define GRP3S NULL, NULL, 10, NOFUNC, NOFUNC
172 #define GRP4 NULL, NULL, 11, NOFUNC, NOFUNC
173 #define GRP5 NULL, NULL, 12, NOFUNC, NOFUNC
174 #define GRP6 NULL, NULL, 13, NOFUNC, NOFUNC
175 #define GRP7 NULL, NULL, 14, NOFUNC, NOFUNC
176 #define GRP8 NULL, NULL, 15, NOFUNC, NOFUNC
179 #define FLOAT NULL, NULL, FLOATCODE, NOFUNC, NOFUNC
191 struct dis386 dis386[] = {
193 { "addb", Eb, Gb, NOFUNC },
194 { "addS", Ev, Gv, NOFUNC },
195 { "addb", Gb, Eb, NOFUNC },
196 { "addS", Gv, Ev, NOFUNC },
197 { "addb", AL, Ib, NOFUNC },
198 { "addS", eAX, Iv, NOFUNC },
199 { "pushl", es, NOFUNC, NOFUNC },
200 { "popl", es, NOFUNC, NOFUNC },
202 { "orb", Eb, Gb, NOFUNC },
203 { "orS", Ev, Gv, NOFUNC },
204 { "orb", Gb, Eb, NOFUNC },
205 { "orS", Gv, Ev, NOFUNC },
206 { "orb", AL, Ib, NOFUNC },
207 { "orS", eAX, Iv, NOFUNC },
208 { "pushl", cs, NOFUNC, NOFUNC },
209 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* extended opcode escape */
211 { "adcb", Eb, Gb, NOFUNC },
212 { "adcS", Ev, Gv, NOFUNC },
213 { "adcb", Gb, Eb, NOFUNC },
214 { "adcS", Gv, Ev, NOFUNC },
215 { "adcb", AL, Ib, NOFUNC },
216 { "adcS", eAX, Iv, NOFUNC },
217 { "pushl", ss, NOFUNC, NOFUNC },
218 { "popl", ss, NOFUNC, NOFUNC },
220 { "sbbb", Eb, Gb, NOFUNC },
221 { "sbbS", Ev, Gv, NOFUNC },
222 { "sbbb", Gb, Eb, NOFUNC },
223 { "sbbS", Gv, Ev, NOFUNC },
224 { "sbbb", AL, Ib, NOFUNC },
225 { "sbbS", eAX, Iv, NOFUNC },
226 { "pushl", ds, NOFUNC, NOFUNC },
227 { "popl", ds, NOFUNC, NOFUNC },
229 { "andb", Eb, Gb, NOFUNC },
230 { "andS", Ev, Gv, NOFUNC },
231 { "andb", Gb, Eb, NOFUNC },
232 { "andS", Gv, Ev, NOFUNC },
233 { "andb", AL, Ib, NOFUNC },
234 { "andS", eAX, Iv, NOFUNC },
235 { "(bad)", NOFUNC, NOFUNC, NOFUNC}, /* SEG ES prefix */
236 { "daa", NOFUNC, NOFUNC, NOFUNC },
238 { "subb", Eb, Gb, NOFUNC },
239 { "subS", Ev, Gv, NOFUNC },
240 { "subb", Gb, Eb, NOFUNC },
241 { "subS", Gv, Ev, NOFUNC },
242 { "subb", AL, Ib, NOFUNC },
243 { "subS", eAX, Iv, NOFUNC },
244 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG CS prefix */
245 { "das", NOFUNC, NOFUNC, NOFUNC },
247 { "xorb", Eb, Gb, NOFUNC },
248 { "xorS", Ev, Gv, NOFUNC },
249 { "xorb", Gb, Eb, NOFUNC },
250 { "xorS", Gv, Ev, NOFUNC },
251 { "xorb", AL, Ib, NOFUNC },
252 { "xorS", eAX, Iv, NOFUNC },
253 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG SS prefix */
254 { "aaa", NOFUNC, NOFUNC, NOFUNC },
256 { "cmpb", Eb, Gb, NOFUNC },
257 { "cmpS", Ev, Gv, NOFUNC },
258 { "cmpb", Gb, Eb, NOFUNC },
259 { "cmpS", Gv, Ev, NOFUNC },
260 { "cmpb", AL, Ib, NOFUNC },
261 { "cmpS", eAX, Iv, NOFUNC },
262 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG DS prefix */
263 { "aas", NOFUNC, NOFUNC, NOFUNC },
265 { "incS", eAX, NOFUNC, NOFUNC },
266 { "incS", eCX, NOFUNC, NOFUNC },
267 { "incS", eDX, NOFUNC, NOFUNC },
268 { "incS", eBX, NOFUNC, NOFUNC },
269 { "incS", eSP, NOFUNC, NOFUNC },
270 { "incS", eBP, NOFUNC, NOFUNC },
271 { "incS", eSI, NOFUNC, NOFUNC },
272 { "incS", eDI, NOFUNC, NOFUNC },
274 { "decS", eAX, NOFUNC, NOFUNC },
275 { "decS", eCX, NOFUNC, NOFUNC },
276 { "decS", eDX, NOFUNC, NOFUNC },
277 { "decS", eBX, NOFUNC, NOFUNC },
278 { "decS", eSP, NOFUNC, NOFUNC },
279 { "decS", eBP, NOFUNC, NOFUNC },
280 { "decS", eSI, NOFUNC, NOFUNC },
281 { "decS", eDI, NOFUNC, NOFUNC },
283 { "pushS", eAX, NOFUNC, NOFUNC },
284 { "pushS", eCX, NOFUNC, NOFUNC },
285 { "pushS", eDX, NOFUNC, NOFUNC },
286 { "pushS", eBX, NOFUNC, NOFUNC },
287 { "pushS", eSP, NOFUNC, NOFUNC },
288 { "pushS", eBP, NOFUNC, NOFUNC },
289 { "pushS", eSI, NOFUNC, NOFUNC },
290 { "pushS", eDI, NOFUNC, NOFUNC },
292 { "popS", eAX, NOFUNC, NOFUNC },
293 { "popS", eCX, NOFUNC, NOFUNC },
294 { "popS", eDX, NOFUNC, NOFUNC },
295 { "popS", eBX, NOFUNC, NOFUNC },
296 { "popS", eSP, NOFUNC, NOFUNC },
297 { "popS", eBP, NOFUNC, NOFUNC },
298 { "popS", eSI, NOFUNC, NOFUNC },
299 { "popS", eDI, NOFUNC, NOFUNC },
301 { "pusha", NOFUNC, NOFUNC, NOFUNC },
302 { "popa", NOFUNC, NOFUNC, NOFUNC },
303 { "boundS", Gv, Ma, NOFUNC },
304 { "arpl", Ew, Gw, NOFUNC },
305 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* seg fs */
306 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* seg gs */
307 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* op size prefix */
308 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* adr size prefix */
310 { "pushS", Iv, NOFUNC, NOFUNC }, /* 386 book wrong */
311 { "imulS", Gv, Ev, Iv },
312 { "pushl", sIb, NOFUNC, NOFUNC }, /* push of byte really pushes 4 bytes */
313 { "imulS", Gv, Ev, Ib },
314 { "insb", Yb, indirDX, NOFUNC },
315 { "insS", Yv, indirDX, NOFUNC },
316 { "outsb", indirDX, Xb, NOFUNC },
317 { "outsS", indirDX, Xv, NOFUNC },
319 { "jo", Jb, NOFUNC, NOFUNC },
320 { "jno", Jb, NOFUNC, NOFUNC },
321 { "jb", Jb, NOFUNC, NOFUNC },
322 { "jae", Jb, NOFUNC, NOFUNC },
323 { "je", Jb, NOFUNC, NOFUNC },
324 { "jne", Jb, NOFUNC, NOFUNC },
325 { "jbe", Jb, NOFUNC, NOFUNC },
326 { "ja", Jb, NOFUNC, NOFUNC },
328 { "js", Jb, NOFUNC, NOFUNC },
329 { "jns", Jb, NOFUNC, NOFUNC },
330 { "jp", Jb, NOFUNC, NOFUNC },
331 { "jnp", Jb, NOFUNC, NOFUNC },
332 { "jl", Jb, NOFUNC, NOFUNC },
333 { "jnl", Jb, NOFUNC, NOFUNC },
334 { "jle", Jb, NOFUNC, NOFUNC },
335 { "jg", Jb, NOFUNC, NOFUNC },
339 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
341 { "testb", Eb, Gb, NOFUNC },
342 { "testS", Ev, Gv, NOFUNC },
343 { "xchgb", Eb, Gb, NOFUNC },
344 { "xchgS", Ev, Gv, NOFUNC },
346 { "movb", Eb, Gb, NOFUNC },
347 { "movS", Ev, Gv, NOFUNC },
348 { "movb", Gb, Eb, NOFUNC },
349 { "movS", Gv, Ev, NOFUNC },
350 { "movw", Ew, Sw, NOFUNC },
351 { "leaS", Gv, M, NOFUNC },
352 { "movw", Sw, Ew, NOFUNC },
353 { "popS", Ev, NOFUNC, NOFUNC },
355 { "nop", NOFUNC, NOFUNC, NOFUNC },
356 { "xchgS", eCX, eAX, NOFUNC },
357 { "xchgS", eDX, eAX, NOFUNC },
358 { "xchgS", eBX, eAX, NOFUNC },
359 { "xchgS", eSP, eAX, NOFUNC },
360 { "xchgS", eBP, eAX, NOFUNC },
361 { "xchgS", eSI, eAX, NOFUNC },
362 { "xchgS", eDI, eAX, NOFUNC },
364 { "cwtl", NOFUNC, NOFUNC, NOFUNC },
365 { "cltd", NOFUNC, NOFUNC, NOFUNC },
366 { "lcall", Ap, NOFUNC, NOFUNC },
367 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* fwait */
368 { "pushf", NOFUNC, NOFUNC, NOFUNC },
369 { "popf", NOFUNC, NOFUNC, NOFUNC },
370 { "sahf", NOFUNC, NOFUNC, NOFUNC },
371 { "lahf", NOFUNC, NOFUNC, NOFUNC },
373 { "movb", AL, Ob, NOFUNC },
374 { "movS", eAX, Ov, NOFUNC },
375 { "movb", Ob, AL, NOFUNC },
376 { "movS", Ov, eAX, NOFUNC },
377 { "movsb", Yb, Xb, NOFUNC },
378 { "movsS", Yv, Xv, NOFUNC },
379 { "cmpsb", Xb, Yb, NOFUNC },
380 { "cmpsS", Xv, Yv, NOFUNC },
382 { "testb", AL, Ib, NOFUNC },
383 { "testS", eAX, Iv, NOFUNC },
384 { "stosb", Yb, AL, NOFUNC },
385 { "stosS", Yv, eAX, NOFUNC },
386 { "lodsb", AL, Xb, NOFUNC },
387 { "lodsS", eAX, Xv, NOFUNC },
388 { "scasb", AL, Yb, NOFUNC },
389 { "scasS", eAX, Yv, NOFUNC },
391 { "movb", AL, Ib, NOFUNC },
392 { "movb", CL, Ib, NOFUNC },
393 { "movb", DL, Ib, NOFUNC },
394 { "movb", BL, Ib, NOFUNC },
395 { "movb", AH, Ib, NOFUNC },
396 { "movb", CH, Ib, NOFUNC },
397 { "movb", DH, Ib, NOFUNC },
398 { "movb", BH, Ib, NOFUNC },
400 { "movS", eAX, Iv, NOFUNC },
401 { "movS", eCX, Iv, NOFUNC },
402 { "movS", eDX, Iv, NOFUNC },
403 { "movS", eBX, Iv, NOFUNC },
404 { "movS", eSP, Iv, NOFUNC },
405 { "movS", eBP, Iv, NOFUNC },
406 { "movS", eSI, Iv, NOFUNC },
407 { "movS", eDI, Iv, NOFUNC },
411 { "ret", Iw, NOFUNC, NOFUNC },
412 { "ret", NOFUNC, NOFUNC, NOFUNC },
413 { "lesS", Gv, Mp, NOFUNC },
414 { "ldsS", Gv, Mp, NOFUNC },
415 { "movb", Eb, Ib, NOFUNC },
416 { "movS", Ev, Iv, NOFUNC },
418 { "enter", Iw, Ib, NOFUNC },
419 { "leave", NOFUNC, NOFUNC, NOFUNC },
420 { "lret", Iw, NOFUNC, NOFUNC },
421 { "lret", NOFUNC, NOFUNC, NOFUNC },
422 { "int3", NOFUNC, NOFUNC, NOFUNC },
423 { "int", Ib, NOFUNC, NOFUNC },
424 { "into", NOFUNC, NOFUNC, NOFUNC },
425 { "iret", NOFUNC, NOFUNC, NOFUNC },
431 { "aam", Ib, NOFUNC, NOFUNC },
432 { "aad", Ib, NOFUNC, NOFUNC },
433 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
434 { "xlat", NOFUNC, NOFUNC, NOFUNC },
445 { "loopne", Jb, NOFUNC, NOFUNC },
446 { "loope", Jb, NOFUNC, NOFUNC },
447 { "loop", Jb, NOFUNC, NOFUNC },
448 { "jCcxz", Jb, NOFUNC, NOFUNC },
449 { "inb", AL, Ib, NOFUNC },
450 { "inS", eAX, Ib, NOFUNC },
451 { "outb", Ib, AL, NOFUNC },
452 { "outS", Ib, eAX, NOFUNC },
454 { "call", Av, NOFUNC, NOFUNC },
455 { "jmp", Jv, NOFUNC, NOFUNC },
456 { "ljmp", Ap, NOFUNC, NOFUNC },
457 { "jmp", Jb, NOFUNC, NOFUNC },
458 { "inb", AL, indirDX, NOFUNC },
459 { "inS", eAX, indirDX, NOFUNC },
460 { "outb", indirDX, AL, NOFUNC },
461 { "outS", indirDX, eAX, NOFUNC },
463 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* lock prefix */
464 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
465 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* repne */
466 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* repz */
467 { "hlt", NOFUNC, NOFUNC, NOFUNC },
468 { "cmc", NOFUNC, NOFUNC, NOFUNC },
472 { "clc", NOFUNC, NOFUNC, NOFUNC },
473 { "stc", NOFUNC, NOFUNC, NOFUNC },
474 { "cli", NOFUNC, NOFUNC, NOFUNC },
475 { "sti", NOFUNC, NOFUNC, NOFUNC },
476 { "cld", NOFUNC, NOFUNC, NOFUNC },
477 { "std", NOFUNC, NOFUNC, NOFUNC },
482 struct dis386 dis386_twobyte[] = {
486 { "larS", Gv, Ew, NOFUNC },
487 { "lslS", Gv, Ew, NOFUNC },
488 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
489 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
490 { "clts", NOFUNC, NOFUNC, NOFUNC },
491 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
493 { "invd", NOFUNC, NOFUNC, NOFUNC },
494 { "wbinvd", NOFUNC, NOFUNC, NOFUNC },
495 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
496 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
497 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
498 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
499 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
500 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
502 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
503 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
504 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
505 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
506 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
507 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
508 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
509 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
511 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
512 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
513 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
514 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
515 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
516 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
517 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
518 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
520 /* these are all backward in appendix A of the intel book */
521 { "movl", Rd, Cd, NOFUNC },
522 { "movl", Rd, Dd, NOFUNC },
523 { "movl", Cd, Rd, NOFUNC },
524 { "movl", Dd, Rd, NOFUNC },
525 { "movl", Rd, Td, NOFUNC },
526 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
527 { "movl", Td, Rd, NOFUNC },
528 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
530 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
531 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
532 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
533 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
534 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
535 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
536 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
537 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
539 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
540 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
541 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
542 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
543 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
544 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
545 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
546 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
548 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
549 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
550 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
551 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
552 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
553 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
554 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
555 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
557 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
558 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
559 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
560 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
561 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
562 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
563 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
564 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
566 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
567 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
568 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
569 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
570 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
571 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
572 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
573 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
575 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
576 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
577 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
578 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
579 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
580 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
581 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
582 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
584 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
585 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
586 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
587 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
588 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
589 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
590 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
591 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
593 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
594 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
595 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
596 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
597 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
598 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
599 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
600 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
602 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
603 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
604 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
605 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
606 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
607 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
608 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
609 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
611 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
612 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
613 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
614 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
615 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
616 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
617 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
618 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
620 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
621 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
622 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
623 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
624 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
625 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
626 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
627 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
629 { "jo", Jv, NOFUNC, NOFUNC },
630 { "jno", Jv, NOFUNC, NOFUNC },
631 { "jb", Jv, NOFUNC, NOFUNC },
632 { "jae", Jv, NOFUNC, NOFUNC },
633 { "je", Jv, NOFUNC, NOFUNC },
634 { "jne", Jv, NOFUNC, NOFUNC },
635 { "jbe", Jv, NOFUNC, NOFUNC },
636 { "ja", Jv, NOFUNC, NOFUNC },
638 { "js", Jv, NOFUNC, NOFUNC },
639 { "jns", Jv, NOFUNC, NOFUNC },
640 { "jp", Jv, NOFUNC, NOFUNC },
641 { "jnp", Jv, NOFUNC, NOFUNC },
642 { "jl", Jv, NOFUNC, NOFUNC },
643 { "jge", Jv, NOFUNC, NOFUNC },
644 { "jle", Jv, NOFUNC, NOFUNC },
645 { "jg", Jv, NOFUNC, NOFUNC },
647 { "seto", Eb, NOFUNC, NOFUNC },
648 { "setno", Eb, NOFUNC, NOFUNC },
649 { "setb", Eb, NOFUNC, NOFUNC },
650 { "setae", Eb, NOFUNC, NOFUNC },
651 { "sete", Eb, NOFUNC, NOFUNC },
652 { "setne", Eb, NOFUNC, NOFUNC },
653 { "setbe", Eb, NOFUNC, NOFUNC },
654 { "seta", Eb, NOFUNC, NOFUNC },
656 { "sets", Eb, NOFUNC, NOFUNC },
657 { "setns", Eb, NOFUNC, NOFUNC },
658 { "setp", Eb, NOFUNC, NOFUNC },
659 { "setnp", Eb, NOFUNC, NOFUNC },
660 { "setl", Eb, NOFUNC, NOFUNC },
661 { "setge", Eb, NOFUNC, NOFUNC },
662 { "setle", Eb, NOFUNC, NOFUNC },
663 { "setg", Eb, NOFUNC, NOFUNC },
665 { "pushl", fs, NOFUNC, NOFUNC },
666 { "popl", fs, NOFUNC, NOFUNC },
667 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
668 { "btS", Ev, Gv, NOFUNC },
669 { "shldS", Ev, Gv, Ib },
670 { "shldS", Ev, Gv, CL },
671 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
672 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
674 { "pushl", gs, NOFUNC, NOFUNC },
675 { "popl", gs, NOFUNC, NOFUNC },
676 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
677 { "btsS", Ev, Gv, NOFUNC },
678 { "shrdS", Ev, Gv, Ib },
679 { "shrdS", Ev, Gv, CL },
680 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
681 { "imulS", Gv, Ev, NOFUNC },
683 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
684 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
685 { "lssS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
686 { "btrS", Ev, Gv, NOFUNC },
687 { "lfsS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
688 { "lgsS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
689 { "movzbS", Gv, Eb, NOFUNC },
690 { "movzwS", Gv, Ew, NOFUNC },
692 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
693 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
695 { "btcS", Ev, Gv, NOFUNC },
696 { "bsfS", Gv, Ev, NOFUNC },
697 { "bsrS", Gv, Ev, NOFUNC },
698 { "movsbS", Gv, Eb, NOFUNC },
699 { "movswS", Gv, Ew, NOFUNC },
701 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
702 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
703 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
704 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
705 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
706 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
707 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
708 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
710 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
711 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
712 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
713 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
714 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
715 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
716 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
717 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
719 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
720 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
721 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
722 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
723 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
724 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
725 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
726 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
728 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
729 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
730 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
731 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
732 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
733 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
734 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
735 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
737 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
738 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
739 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
740 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
741 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
742 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
743 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
744 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
746 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
747 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
748 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
749 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
750 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
751 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
752 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
753 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
755 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
756 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
757 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
758 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
759 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
760 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
761 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
762 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
764 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
765 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
766 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
767 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
768 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
769 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
770 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
771 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
774 static char obuf[100];
776 static char scratchbuf[100];
777 static unsigned char *start_codep;
778 static unsigned char *codep;
783 static const char *names32[]={
784 "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
786 static const char *names16[] = {
787 "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
789 static const char *names8[] = {
790 "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
792 static const char *names_seg[] = {
793 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
795 static const char *names16_pairs[] = {
796 "%bx+%si","%bx+%di","%bp+%si","%bp+%di","%si","%di","%bp","%bx",
799 struct dis386 grps[][8] = {
802 { "addb", Eb, Ib, NOFUNC },
803 { "orb", Eb, Ib, NOFUNC },
804 { "adcb", Eb, Ib, NOFUNC },
805 { "sbbb", Eb, Ib, NOFUNC },
806 { "andb", Eb, Ib, NOFUNC },
807 { "subb", Eb, Ib, NOFUNC },
808 { "xorb", Eb, Ib, NOFUNC },
809 { "cmpb", Eb, Ib, NOFUNC }
813 { "addS", Ev, Iv, NOFUNC },
814 { "orS", Ev, Iv, NOFUNC },
815 { "adcS", Ev, Iv, NOFUNC },
816 { "sbbS", Ev, Iv, NOFUNC },
817 { "andS", Ev, Iv, NOFUNC },
818 { "subS", Ev, Iv, NOFUNC },
819 { "xorS", Ev, Iv, NOFUNC },
820 { "cmpS", Ev, Iv, NOFUNC }
824 { "addS", Ev, sIb, NOFUNC },
825 { "orS", Ev, sIb, NOFUNC },
826 { "adcS", Ev, sIb, NOFUNC },
827 { "sbbS", Ev, sIb, NOFUNC },
828 { "andS", Ev, sIb, NOFUNC },
829 { "subS", Ev, sIb, NOFUNC },
830 { "xorS", Ev, sIb, NOFUNC },
831 { "cmpS", Ev, sIb, NOFUNC }
835 { "rolb", Eb, Ib, NOFUNC },
836 { "rorb", Eb, Ib, NOFUNC },
837 { "rclb", Eb, Ib, NOFUNC },
838 { "rcrb", Eb, Ib, NOFUNC },
839 { "shlb", Eb, Ib, NOFUNC },
840 { "shrb", Eb, Ib, NOFUNC },
841 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
842 { "sarb", Eb, Ib, NOFUNC },
846 { "rolS", Ev, Ib, NOFUNC },
847 { "rorS", Ev, Ib, NOFUNC },
848 { "rclS", Ev, Ib, NOFUNC },
849 { "rcrS", Ev, Ib, NOFUNC },
850 { "shlS", Ev, Ib, NOFUNC },
851 { "shrS", Ev, Ib, NOFUNC },
852 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
853 { "sarS", Ev, Ib, NOFUNC },
857 { "rolb", Eb, NOFUNC, NOFUNC },
858 { "rorb", Eb, NOFUNC, NOFUNC },
859 { "rclb", Eb, NOFUNC, NOFUNC },
860 { "rcrb", Eb, NOFUNC, NOFUNC },
861 { "shlb", Eb, NOFUNC, NOFUNC },
862 { "shrb", Eb, NOFUNC, NOFUNC },
863 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
864 { "sarb", Eb, NOFUNC, NOFUNC },
868 { "rolS", Ev, NOFUNC, NOFUNC },
869 { "rorS", Ev, NOFUNC, NOFUNC },
870 { "rclS", Ev, NOFUNC, NOFUNC },
871 { "rcrS", Ev, NOFUNC, NOFUNC },
872 { "shlS", Ev, NOFUNC, NOFUNC },
873 { "shrS", Ev, NOFUNC, NOFUNC },
874 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
875 { "sarS", Ev, NOFUNC, NOFUNC },
879 { "rolb", Eb, CL, NOFUNC },
880 { "rorb", Eb, CL, NOFUNC },
881 { "rclb", Eb, CL, NOFUNC },
882 { "rcrb", Eb, CL, NOFUNC },
883 { "shlb", Eb, CL, NOFUNC },
884 { "shrb", Eb, CL, NOFUNC },
885 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
886 { "sarb", Eb, CL, NOFUNC },
890 { "rolS", Ev, CL, NOFUNC },
891 { "rorS", Ev, CL, NOFUNC },
892 { "rclS", Ev, CL, NOFUNC },
893 { "rcrS", Ev, CL, NOFUNC },
894 { "shlS", Ev, CL, NOFUNC },
895 { "shrS", Ev, CL, NOFUNC },
896 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
897 { "sarS", Ev, CL, NOFUNC }
901 { "testb", Eb, Ib, NOFUNC },
902 { "(bad)", Eb, NOFUNC, NOFUNC },
903 { "notb", Eb, NOFUNC, NOFUNC },
904 { "negb", Eb, NOFUNC, NOFUNC },
905 { "mulb", AL, Eb, NOFUNC },
906 { "imulb", AL, Eb, NOFUNC },
907 { "divb", AL, Eb, NOFUNC },
908 { "idivb", AL, Eb, NOFUNC }
912 { "testS", Ev, Iv, NOFUNC },
913 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
914 { "notS", Ev, NOFUNC, NOFUNC },
915 { "negS", Ev, NOFUNC, NOFUNC },
916 { "mulS", eAX, Ev, NOFUNC },
917 { "imulS", eAX, Ev, NOFUNC },
918 { "divS", eAX, Ev, NOFUNC },
919 { "idivS", eAX, Ev, NOFUNC },
923 { "incb", Eb, NOFUNC, NOFUNC },
924 { "decb", Eb, NOFUNC, NOFUNC },
925 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
926 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
927 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
928 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
929 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
930 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
934 { "incS", Ev, NOFUNC, NOFUNC },
935 { "decS", Ev, NOFUNC, NOFUNC },
936 { "call", indirEv, NOFUNC, NOFUNC },
937 { "lcall", indirEv, NOFUNC, NOFUNC },
938 { "jmp", indirEv, NOFUNC, NOFUNC },
939 { "ljmp", indirEv, NOFUNC, NOFUNC },
940 { "pushS", Ev, NOFUNC, NOFUNC },
941 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
945 { "sldt", Ew, NOFUNC, NOFUNC },
946 { "str", Ew, NOFUNC, NOFUNC },
947 { "lldt", Ew, NOFUNC, NOFUNC },
948 { "ltr", Ew, NOFUNC, NOFUNC },
949 { "verr", Ew, NOFUNC, NOFUNC },
950 { "verw", Ew, NOFUNC, NOFUNC },
951 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
952 { "(bad)", NOFUNC, NOFUNC, NOFUNC }
956 { "sgdt", Ew, NOFUNC, NOFUNC },
957 { "sidt", Ew, NOFUNC, NOFUNC },
958 { "lgdt", Ew, NOFUNC, NOFUNC },
959 { "lidt", Ew, NOFUNC, NOFUNC },
960 { "smsw", Ew, NOFUNC, NOFUNC },
961 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
962 { "lmsw", Ew, NOFUNC, NOFUNC },
963 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
967 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
968 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
969 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
970 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
971 { "btS", Ev, Ib, NOFUNC },
972 { "btsS", Ev, Ib, NOFUNC },
973 { "btrS", Ev, Ib, NOFUNC },
974 { "btcS", Ev, Ib, NOFUNC },
978 #define PREFIX_REPZ 0x01
979 #define PREFIX_REPNZ 0x02
980 #define PREFIX_LOCK 0x04
981 #define PREFIX_CS 0x08
982 #define PREFIX_SS 0x10
983 #define PREFIX_DS 0x20
984 #define PREFIX_ES 0x40
985 #define PREFIX_FS 0x80
986 #define PREFIX_GS 0x100
987 #define PREFIX_DATA 0x200
988 #define PREFIX_ADR 0x400
989 #define PREFIX_FWAIT 0x800
1002 prefixes |= PREFIX_REPZ;
1005 prefixes |= PREFIX_REPNZ;
1008 prefixes |= PREFIX_LOCK;
1011 prefixes |= PREFIX_CS;
1014 prefixes |= PREFIX_SS;
1017 prefixes |= PREFIX_DS;
1020 prefixes |= PREFIX_ES;
1023 prefixes |= PREFIX_FS;
1026 prefixes |= PREFIX_GS;
1029 prefixes |= PREFIX_DATA;
1032 prefixes |= PREFIX_ADR;
1035 prefixes |= PREFIX_FWAIT;
1047 static char op1out[100], op2out[100], op3out[100];
1048 static unsigned long start_pc;
1051 * disassemble the first instruction in 'inbuf'. You have to make
1052 * sure all of the bytes of the instruction are filled in.
1053 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1054 * (see topic "Redundant prefixes" in the "Differences from 8086"
1055 * section of the "Virtual 8086 Mode" chapter.)
1056 * 'pc' should be the address of this instruction, it will
1057 * be used to print the target address if this is a relative jump or call
1058 * 'outbuf' gets filled in with the disassembled instruction. it should
1059 * be long enough to hold the longest disassembled instruction.
1060 * 100 bytes is certainly enough, unless symbol printing is added later
1061 * The function returns the length of this instruction in bytes.
1064 i386dis (unsigned short ucs, unsigned short uip, unsigned char *inbuf,
1065 char *outbuf, int mode)
1069 int enter_instruction;
1070 char *first, *second, *third;
1078 start_pc = ucs << 16 | uip;
1079 start_codep = inbuf;
1085 enter_instruction = 1;
1087 enter_instruction = 0;
1091 if (prefixes & PREFIX_REPZ)
1093 if (prefixes & PREFIX_REPNZ)
1095 if (prefixes & PREFIX_LOCK)
1098 if ((prefixes & PREFIX_FWAIT)
1099 && ((*codep < 0xd8) || (*codep > 0xdf)))
1101 /* fwait not followed by floating point instruction */
1103 strcpy (outbuf, obuf);
1107 /* these would be initialized to 0 if disassembling for 8086 or 286 */
1116 if (prefixes & PREFIX_DATA)
1119 if (prefixes & PREFIX_ADR)
1122 oappend ("addr16 ");
1126 dp = &dis386_twobyte[*++codep];
1128 dp = &dis386[*codep];
1130 mod = (*codep >> 6) & 3;
1131 reg = (*codep >> 3) & 7;
1134 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1140 if (dp->name == NULL)
1141 dp = &grps[dp->bytemode1][reg];
1147 (*dp->op1)(dp->bytemode1);
1151 (*dp->op2)(dp->bytemode2);
1155 (*dp->op3)(dp->bytemode3);
1158 obufp = obuf + strlen (obuf);
1159 for (i = strlen (obuf); i < 6; i++)
1163 /* enter instruction is printed with operands in the
1164 * same order as the intel book; everything else
1165 * is printed in reverse order
1167 if (enter_instruction)
1198 strcpy (outbuf, obuf);
1199 return (codep - inbuf);
1202 const char *float_mem[] = {
1278 #define STi OP_STi, 0
1280 #define FGRPd9_2 NULL, NULL, 0, NOFUNC, NOFUNC
1281 #define FGRPd9_4 NULL, NULL, 1, NOFUNC, NOFUNC
1282 #define FGRPd9_5 NULL, NULL, 2, NOFUNC, NOFUNC
1283 #define FGRPd9_6 NULL, NULL, 3, NOFUNC, NOFUNC
1284 #define FGRPd9_7 NULL, NULL, 4, NOFUNC, NOFUNC
1285 #define FGRPda_5 NULL, NULL, 5, NOFUNC, NOFUNC
1286 #define FGRPdb_4 NULL, NULL, 6, NOFUNC, NOFUNC
1287 #define FGRPde_3 NULL, NULL, 7, NOFUNC, NOFUNC
1288 #define FGRPdf_4 NULL, NULL, 8, NOFUNC, NOFUNC
1290 struct dis386 float_reg[][8] = {
1293 { "fadd", ST, STi, NOFUNC },
1294 { "fmul", ST, STi, NOFUNC },
1295 { "fcom", STi, NOFUNC, NOFUNC },
1296 { "fcomp", STi, NOFUNC, NOFUNC },
1297 { "fsub", ST, STi, NOFUNC },
1298 { "fsubr", ST, STi, NOFUNC },
1299 { "fdiv", ST, STi, NOFUNC },
1300 { "fdivr", ST, STi, NOFUNC },
1304 { "fld", STi, NOFUNC, NOFUNC },
1305 { "fxch", STi, NOFUNC, NOFUNC },
1307 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1315 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1316 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1317 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1318 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1319 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1321 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1322 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1326 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1327 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1328 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1329 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1331 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1332 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1333 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1337 { "fadd", STi, ST, NOFUNC },
1338 { "fmul", STi, ST, NOFUNC },
1339 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1340 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1341 { "fsub", STi, ST, NOFUNC },
1342 { "fsubr", STi, ST, NOFUNC },
1343 { "fdiv", STi, ST, NOFUNC },
1344 { "fdivr", STi, ST, NOFUNC },
1348 { "ffree", STi, NOFUNC, NOFUNC },
1349 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1350 { "fst", STi, NOFUNC, NOFUNC },
1351 { "fstp", STi, NOFUNC, NOFUNC },
1352 { "fucom", STi, NOFUNC, NOFUNC },
1353 { "fucomp", STi, NOFUNC, NOFUNC },
1354 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1355 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1359 { "faddp", STi, ST, NOFUNC },
1360 { "fmulp", STi, ST, NOFUNC },
1361 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1363 { "fsubp", STi, ST, NOFUNC },
1364 { "fsubrp", STi, ST, NOFUNC },
1365 { "fdivp", STi, ST, NOFUNC },
1366 { "fdivrp", STi, ST, NOFUNC },
1370 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1371 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1372 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1373 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1375 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1376 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1377 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1382 const char *fgrps[][8] = {
1385 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1390 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1395 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1400 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1405 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1410 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1415 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1416 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1421 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1426 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1435 unsigned char floatop;
1437 floatop = codep[-1];
1441 putop (float_mem[(floatop - 0xd8) * 8 + reg]);
1448 dp = &float_reg[floatop - 0xd8][reg];
1449 if (dp->name == NULL)
1451 putop (fgrps[dp->bytemode1][rm]);
1452 /* instruction fnstsw is only one with strange arg */
1453 if (floatop == 0xdf && *codep == 0xe0)
1454 strcpy (op1out, "%eax");
1461 (*dp->op1)(dp->bytemode1);
1464 (*dp->op2)(dp->bytemode2);
1469 OP_ST(int dummy __unused)
1475 OP_STi(int dummy __unused)
1477 sprintf (scratchbuf, "%%st(%d)", rm);
1478 oappend (scratchbuf);
1482 /* capital letters in template are macros */
1484 putop(const char *template)
1488 for (p = template; *p; p++)
1495 case 'C': /* For jcxz/jecxz */
1500 if ((prefixes & PREFIX_FWAIT) == 0)
1504 /* operand size flag */
1516 oappend(const char *s)
1519 obufp += strlen (s);
1526 if (prefixes & PREFIX_CS)
1528 if (prefixes & PREFIX_DS)
1530 if (prefixes & PREFIX_SS)
1532 if (prefixes & PREFIX_ES)
1534 if (prefixes & PREFIX_FS)
1536 if (prefixes & PREFIX_GS)
1541 OP_indirE(int bytemode)
1557 /* skip mod/rm byte */
1567 oappend (names8[rm]);
1570 oappend (names16[rm]);
1574 oappend (names32[rm]);
1576 oappend (names16[rm]);
1579 oappend ("<bad dis table>");
1587 if (aflag && rm == 4) {
1590 scale = (*codep >> 6) & 3;
1591 idx = (*codep >> 3) & 7;
1601 /* implies havesib and havebase */
1626 disp = *(char *)codep++;
1627 if (!aflag || rm != 4) {
1637 if (!aflag || rm != 4) {
1644 if (mod != 0 || ((aflag && rm == 5) || (havesib && base == 5))
1645 || (!aflag && rm == 6)) {
1646 sprintf (scratchbuf, "0x%x", disp);
1647 oappend (scratchbuf);
1650 if (havebase || havesib) {
1653 oappend (aflag ? names32[base] : names16_pairs[base]);
1656 sprintf (scratchbuf, ",%s", names32[idx]);
1657 oappend (scratchbuf);
1659 sprintf (scratchbuf, ",%d", 1 << scale);
1660 oappend (scratchbuf);
1672 oappend (names8[reg]);
1675 oappend (names16[reg]);
1678 oappend (names32[reg]);
1682 oappend (names32[reg]);
1684 oappend (names16[reg]);
1687 oappend ("<internal disassembler error>");
1697 x = *codep++ & 0xff;
1698 x |= (*codep++ & 0xff) << 8;
1699 x |= (*codep++ & 0xff) << 16;
1700 x |= (*codep++ & 0xff) << 24;
1709 x = *codep++ & 0xff;
1710 x |= (*codep++ & 0xff) << 8;
1721 case indir_dx_reg: s = "(%dx)"; break;
1722 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
1723 case sp_reg: case bp_reg: case si_reg: case di_reg:
1724 s = names16[code - ax_reg];
1726 case es_reg: case ss_reg: case cs_reg:
1727 case ds_reg: case fs_reg: case gs_reg:
1728 s = names_seg[code - es_reg];
1730 case al_reg: case ah_reg: case cl_reg: case ch_reg:
1731 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
1732 s = names8[code - al_reg];
1734 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
1735 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
1737 s = names32[code - eAX_reg];
1739 s = names16[code - eAX_reg];
1742 s = "<internal disassembler error>";
1756 op = *codep++ & 0xff;
1768 oappend ("<internal disassembler error>");
1771 sprintf (scratchbuf, "$0x%x", op);
1772 oappend (scratchbuf);
1783 op = *(char *)codep++;
1789 op = (short)get16();
1792 op = (short)get16 ();
1795 oappend ("<internal disassembler error>");
1798 sprintf (scratchbuf, "$0x%x", op);
1799 oappend (scratchbuf);
1810 disp = *(char *)codep++;
1811 append_pc(start_pc + codep - start_codep + disp);
1816 append_pc(start_pc + codep - start_codep + disp);
1818 disp = (short)get16 ();
1819 disp = (((start_pc + codep - start_codep) & 0xffff) + disp) & 0xffff;
1820 append_pc((start_pc & 0xffff0000) | disp);
1824 oappend ("<internal disassembelr error>");
1828 oappend (scratchbuf);
1832 append_pc(unsigned long pc)
1834 sprintf(scratchbuf, "%04lx:%04lx", pc >> 16, pc & 0xffff);
1838 OP_SEG(int dummy __unused)
1840 static const char *sreg[] = {
1841 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
1844 oappend (sreg[reg]);
1865 sprintf (scratchbuf, "%04x:%04x", seg, offset);
1866 oappend (scratchbuf);
1872 offset = (short)get16 ();
1874 append_pc(start_pc + codep - start_codep + offset);
1875 oappend (scratchbuf);
1878 oappend ("<internal disassembler error>");
1884 OP_OFF(int dummy __unused)
1893 sprintf (scratchbuf, "0x%x", off);
1894 oappend (scratchbuf);
1898 OP_ESDI(int dummy __unused)
1901 oappend (aflag ? "%edi" : "%di");
1906 OP_DSSI(int dummy __unused)
1909 oappend (aflag ? "%esi" : "%si");
1914 OP_C(int dummy __unused)
1916 codep++; /* skip mod/rm */
1917 sprintf (scratchbuf, "%%cr%d", reg);
1918 oappend (scratchbuf);
1922 OP_D(int dummy __unused)
1924 codep++; /* skip mod/rm */
1925 sprintf (scratchbuf, "%%db%d", reg);
1926 oappend (scratchbuf);
1930 OP_T(int dummy __unused)
1932 codep++; /* skip mod/rm */
1933 sprintf (scratchbuf, "%%tr%d", reg);
1934 oappend (scratchbuf);
1943 oappend (names32[rm]);
1946 oappend (names16[rm]);
1953 i386dis (pc, inbuf, outbuf, mode)
1955 unsigned char *inbuf;
1958 strcpy (outbuf, "(no disassembler)");
1962 #endif /* DISASSEMBLER */