2 * $FreeBSD: src/usr.bin/doscmd/i386-pinsn.c,v 1.1.6.1 2002/04/25 11:04:51 tg Exp $
3 * $DragonFly: src/usr.bin/doscmd/i386-pinsn.c,v 1.4 2008/10/16 01:52:32 swildner Exp $
7 /* Print i386 instructions for GDB, the GNU debugger.
8 Copyright (C) 1988, 1989 Free Software Foundation, Inc.
10 This file is part of GDB.
12 GDB is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 1, or (at your option)
17 GDB is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GDB; see the file COPYING. If not, write to
24 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
27 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
32 * The main tables describing the instructions is essentially a copy
33 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
34 * Programmers Manual. Usually, there is a capital letter, followed
35 * by a small letter. The capital letter tell the addressing mode,
36 * and the small letter tells about the operand size. Refer to
37 * the Intel manual for details.
45 static void OP_E(int), OP_indirE(int), OP_G(int);
46 static void OP_I(int), OP_sI(int), OP_REG(int), OP_J(int), OP_SEG(int);
47 static void OP_DIR(int), OP_OFF(int), OP_DSSI(int), OP_ESDI(int);
48 static void OP_C(int), OP_D(int), OP_T(int), OP_rm(int);
49 static void OP_ST(int), OP_STi(int);
50 static void append_pc(unsigned long);
51 static void append_prefix(void);
52 static void dofloat(void);
53 static int get16(void);
54 static int get32(void);
55 static void oappend(const char *);
56 static void putop(const char *);
58 #define Eb OP_E, b_mode
59 #define indirEb OP_indirE, b_mode
60 #define Gb OP_G, b_mode
61 #define Ev OP_E, v_mode
62 #define indirEv OP_indirE, v_mode
63 #define Ew OP_E, w_mode
64 #define Ma OP_E, v_mode
66 #define Mp OP_E, 0 /* ? */
67 #define Gv OP_G, v_mode
68 #define Gw OP_G, w_mode
69 #define Rw OP_rm, w_mode
70 #define Rd OP_rm, d_mode
71 #define Ib OP_I, b_mode
72 #define sIb OP_sI, b_mode /* sign extended byte */
73 #define Iv OP_I, v_mode
74 #define Iw OP_I, w_mode
75 #define Jb OP_J, b_mode
76 #define Jv OP_J, v_mode
77 #define Cd OP_C, d_mode
78 #define Dd OP_D, d_mode
79 #define Td OP_T, d_mode
81 #define eAX OP_REG, eAX_reg
82 #define eBX OP_REG, eBX_reg
83 #define eCX OP_REG, eCX_reg
84 #define eDX OP_REG, eDX_reg
85 #define eSP OP_REG, eSP_reg
86 #define eBP OP_REG, eBP_reg
87 #define eSI OP_REG, eSI_reg
88 #define eDI OP_REG, eDI_reg
89 #define AL OP_REG, al_reg
90 #define CL OP_REG, cl_reg
91 #define DL OP_REG, dl_reg
92 #define BL OP_REG, bl_reg
93 #define AH OP_REG, ah_reg
94 #define CH OP_REG, ch_reg
95 #define DH OP_REG, dh_reg
96 #define BH OP_REG, bh_reg
97 #define AX OP_REG, ax_reg
98 #define DX OP_REG, dx_reg
99 #define indirDX OP_REG, indir_dx_reg
101 #define Sw OP_SEG, w_mode
102 #define Ap OP_DIR, lptr
103 #define Av OP_DIR, v_mode
104 #define Ob OP_OFF, b_mode
105 #define Ov OP_OFF, v_mode
106 #define Xb OP_DSSI, b_mode
107 #define Xv OP_DSSI, v_mode
108 #define Yb OP_ESDI, b_mode
109 #define Yv OP_ESDI, v_mode
111 #define es OP_REG, es_reg
112 #define ss OP_REG, ss_reg
113 #define cs OP_REG, cs_reg
114 #define ds OP_REG, ds_reg
115 #define fs OP_REG, fs_reg
116 #define gs OP_REG, gs_reg
158 #define indir_dx_reg 150
160 #define NOFUNC NULL, 0
162 #define GRP1b NULL, NULL, 0, NOFUNC, NOFUNC
163 #define GRP1S NULL, NULL, 1, NOFUNC, NOFUNC
164 #define GRP1Ss NULL, NULL, 2, NOFUNC, NOFUNC
165 #define GRP2b NULL, NULL, 3, NOFUNC, NOFUNC
166 #define GRP2S NULL, NULL, 4, NOFUNC, NOFUNC
167 #define GRP2b_one NULL, NULL, 5, NOFUNC, NOFUNC
168 #define GRP2S_one NULL, NULL, 6, NOFUNC, NOFUNC
169 #define GRP2b_cl NULL, NULL, 7, NOFUNC, NOFUNC
170 #define GRP2S_cl NULL, NULL, 8, NOFUNC, NOFUNC
171 #define GRP3b NULL, NULL, 9, NOFUNC, NOFUNC
172 #define GRP3S NULL, NULL, 10, NOFUNC, NOFUNC
173 #define GRP4 NULL, NULL, 11, NOFUNC, NOFUNC
174 #define GRP5 NULL, NULL, 12, NOFUNC, NOFUNC
175 #define GRP6 NULL, NULL, 13, NOFUNC, NOFUNC
176 #define GRP7 NULL, NULL, 14, NOFUNC, NOFUNC
177 #define GRP8 NULL, NULL, 15, NOFUNC, NOFUNC
180 #define FLOAT NULL, NULL, FLOATCODE, NOFUNC, NOFUNC
192 struct dis386 dis386[] = {
194 { "addb", Eb, Gb, NOFUNC },
195 { "addS", Ev, Gv, NOFUNC },
196 { "addb", Gb, Eb, NOFUNC },
197 { "addS", Gv, Ev, NOFUNC },
198 { "addb", AL, Ib, NOFUNC },
199 { "addS", eAX, Iv, NOFUNC },
200 { "pushl", es, NOFUNC, NOFUNC },
201 { "popl", es, NOFUNC, NOFUNC },
203 { "orb", Eb, Gb, NOFUNC },
204 { "orS", Ev, Gv, NOFUNC },
205 { "orb", Gb, Eb, NOFUNC },
206 { "orS", Gv, Ev, NOFUNC },
207 { "orb", AL, Ib, NOFUNC },
208 { "orS", eAX, Iv, NOFUNC },
209 { "pushl", cs, NOFUNC, NOFUNC },
210 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* extended opcode escape */
212 { "adcb", Eb, Gb, NOFUNC },
213 { "adcS", Ev, Gv, NOFUNC },
214 { "adcb", Gb, Eb, NOFUNC },
215 { "adcS", Gv, Ev, NOFUNC },
216 { "adcb", AL, Ib, NOFUNC },
217 { "adcS", eAX, Iv, NOFUNC },
218 { "pushl", ss, NOFUNC, NOFUNC },
219 { "popl", ss, NOFUNC, NOFUNC },
221 { "sbbb", Eb, Gb, NOFUNC },
222 { "sbbS", Ev, Gv, NOFUNC },
223 { "sbbb", Gb, Eb, NOFUNC },
224 { "sbbS", Gv, Ev, NOFUNC },
225 { "sbbb", AL, Ib, NOFUNC },
226 { "sbbS", eAX, Iv, NOFUNC },
227 { "pushl", ds, NOFUNC, NOFUNC },
228 { "popl", ds, NOFUNC, NOFUNC },
230 { "andb", Eb, Gb, NOFUNC },
231 { "andS", Ev, Gv, NOFUNC },
232 { "andb", Gb, Eb, NOFUNC },
233 { "andS", Gv, Ev, NOFUNC },
234 { "andb", AL, Ib, NOFUNC },
235 { "andS", eAX, Iv, NOFUNC },
236 { "(bad)", NOFUNC, NOFUNC, NOFUNC}, /* SEG ES prefix */
237 { "daa", NOFUNC, NOFUNC, NOFUNC },
239 { "subb", Eb, Gb, NOFUNC },
240 { "subS", Ev, Gv, NOFUNC },
241 { "subb", Gb, Eb, NOFUNC },
242 { "subS", Gv, Ev, NOFUNC },
243 { "subb", AL, Ib, NOFUNC },
244 { "subS", eAX, Iv, NOFUNC },
245 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG CS prefix */
246 { "das", NOFUNC, NOFUNC, NOFUNC },
248 { "xorb", Eb, Gb, NOFUNC },
249 { "xorS", Ev, Gv, NOFUNC },
250 { "xorb", Gb, Eb, NOFUNC },
251 { "xorS", Gv, Ev, NOFUNC },
252 { "xorb", AL, Ib, NOFUNC },
253 { "xorS", eAX, Iv, NOFUNC },
254 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG SS prefix */
255 { "aaa", NOFUNC, NOFUNC, NOFUNC },
257 { "cmpb", Eb, Gb, NOFUNC },
258 { "cmpS", Ev, Gv, NOFUNC },
259 { "cmpb", Gb, Eb, NOFUNC },
260 { "cmpS", Gv, Ev, NOFUNC },
261 { "cmpb", AL, Ib, NOFUNC },
262 { "cmpS", eAX, Iv, NOFUNC },
263 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* SEG DS prefix */
264 { "aas", NOFUNC, NOFUNC, NOFUNC },
266 { "incS", eAX, NOFUNC, NOFUNC },
267 { "incS", eCX, NOFUNC, NOFUNC },
268 { "incS", eDX, NOFUNC, NOFUNC },
269 { "incS", eBX, NOFUNC, NOFUNC },
270 { "incS", eSP, NOFUNC, NOFUNC },
271 { "incS", eBP, NOFUNC, NOFUNC },
272 { "incS", eSI, NOFUNC, NOFUNC },
273 { "incS", eDI, NOFUNC, NOFUNC },
275 { "decS", eAX, NOFUNC, NOFUNC },
276 { "decS", eCX, NOFUNC, NOFUNC },
277 { "decS", eDX, NOFUNC, NOFUNC },
278 { "decS", eBX, NOFUNC, NOFUNC },
279 { "decS", eSP, NOFUNC, NOFUNC },
280 { "decS", eBP, NOFUNC, NOFUNC },
281 { "decS", eSI, NOFUNC, NOFUNC },
282 { "decS", eDI, NOFUNC, NOFUNC },
284 { "pushS", eAX, NOFUNC, NOFUNC },
285 { "pushS", eCX, NOFUNC, NOFUNC },
286 { "pushS", eDX, NOFUNC, NOFUNC },
287 { "pushS", eBX, NOFUNC, NOFUNC },
288 { "pushS", eSP, NOFUNC, NOFUNC },
289 { "pushS", eBP, NOFUNC, NOFUNC },
290 { "pushS", eSI, NOFUNC, NOFUNC },
291 { "pushS", eDI, NOFUNC, NOFUNC },
293 { "popS", eAX, NOFUNC, NOFUNC },
294 { "popS", eCX, NOFUNC, NOFUNC },
295 { "popS", eDX, NOFUNC, NOFUNC },
296 { "popS", eBX, NOFUNC, NOFUNC },
297 { "popS", eSP, NOFUNC, NOFUNC },
298 { "popS", eBP, NOFUNC, NOFUNC },
299 { "popS", eSI, NOFUNC, NOFUNC },
300 { "popS", eDI, NOFUNC, NOFUNC },
302 { "pusha", NOFUNC, NOFUNC, NOFUNC },
303 { "popa", NOFUNC, NOFUNC, NOFUNC },
304 { "boundS", Gv, Ma, NOFUNC },
305 { "arpl", Ew, Gw, NOFUNC },
306 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* seg fs */
307 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* seg gs */
308 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* op size prefix */
309 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* adr size prefix */
311 { "pushS", Iv, NOFUNC, NOFUNC }, /* 386 book wrong */
312 { "imulS", Gv, Ev, Iv },
313 { "pushl", sIb, NOFUNC, NOFUNC }, /* push of byte really pushes 4 bytes */
314 { "imulS", Gv, Ev, Ib },
315 { "insb", Yb, indirDX, NOFUNC },
316 { "insS", Yv, indirDX, NOFUNC },
317 { "outsb", indirDX, Xb, NOFUNC },
318 { "outsS", indirDX, Xv, NOFUNC },
320 { "jo", Jb, NOFUNC, NOFUNC },
321 { "jno", Jb, NOFUNC, NOFUNC },
322 { "jb", Jb, NOFUNC, NOFUNC },
323 { "jae", Jb, NOFUNC, NOFUNC },
324 { "je", Jb, NOFUNC, NOFUNC },
325 { "jne", Jb, NOFUNC, NOFUNC },
326 { "jbe", Jb, NOFUNC, NOFUNC },
327 { "ja", Jb, NOFUNC, NOFUNC },
329 { "js", Jb, NOFUNC, NOFUNC },
330 { "jns", Jb, NOFUNC, NOFUNC },
331 { "jp", Jb, NOFUNC, NOFUNC },
332 { "jnp", Jb, NOFUNC, NOFUNC },
333 { "jl", Jb, NOFUNC, NOFUNC },
334 { "jnl", Jb, NOFUNC, NOFUNC },
335 { "jle", Jb, NOFUNC, NOFUNC },
336 { "jg", Jb, NOFUNC, NOFUNC },
340 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
342 { "testb", Eb, Gb, NOFUNC },
343 { "testS", Ev, Gv, NOFUNC },
344 { "xchgb", Eb, Gb, NOFUNC },
345 { "xchgS", Ev, Gv, NOFUNC },
347 { "movb", Eb, Gb, NOFUNC },
348 { "movS", Ev, Gv, NOFUNC },
349 { "movb", Gb, Eb, NOFUNC },
350 { "movS", Gv, Ev, NOFUNC },
351 { "movw", Ew, Sw, NOFUNC },
352 { "leaS", Gv, M, NOFUNC },
353 { "movw", Sw, Ew, NOFUNC },
354 { "popS", Ev, NOFUNC, NOFUNC },
356 { "nop", NOFUNC, NOFUNC, NOFUNC },
357 { "xchgS", eCX, eAX, NOFUNC },
358 { "xchgS", eDX, eAX, NOFUNC },
359 { "xchgS", eBX, eAX, NOFUNC },
360 { "xchgS", eSP, eAX, NOFUNC },
361 { "xchgS", eBP, eAX, NOFUNC },
362 { "xchgS", eSI, eAX, NOFUNC },
363 { "xchgS", eDI, eAX, NOFUNC },
365 { "cwtl", NOFUNC, NOFUNC, NOFUNC },
366 { "cltd", NOFUNC, NOFUNC, NOFUNC },
367 { "lcall", Ap, NOFUNC, NOFUNC },
368 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* fwait */
369 { "pushf", NOFUNC, NOFUNC, NOFUNC },
370 { "popf", NOFUNC, NOFUNC, NOFUNC },
371 { "sahf", NOFUNC, NOFUNC, NOFUNC },
372 { "lahf", NOFUNC, NOFUNC, NOFUNC },
374 { "movb", AL, Ob, NOFUNC },
375 { "movS", eAX, Ov, NOFUNC },
376 { "movb", Ob, AL, NOFUNC },
377 { "movS", Ov, eAX, NOFUNC },
378 { "movsb", Yb, Xb, NOFUNC },
379 { "movsS", Yv, Xv, NOFUNC },
380 { "cmpsb", Xb, Yb, NOFUNC },
381 { "cmpsS", Xv, Yv, NOFUNC },
383 { "testb", AL, Ib, NOFUNC },
384 { "testS", eAX, Iv, NOFUNC },
385 { "stosb", Yb, AL, NOFUNC },
386 { "stosS", Yv, eAX, NOFUNC },
387 { "lodsb", AL, Xb, NOFUNC },
388 { "lodsS", eAX, Xv, NOFUNC },
389 { "scasb", AL, Yb, NOFUNC },
390 { "scasS", eAX, Yv, NOFUNC },
392 { "movb", AL, Ib, NOFUNC },
393 { "movb", CL, Ib, NOFUNC },
394 { "movb", DL, Ib, NOFUNC },
395 { "movb", BL, Ib, NOFUNC },
396 { "movb", AH, Ib, NOFUNC },
397 { "movb", CH, Ib, NOFUNC },
398 { "movb", DH, Ib, NOFUNC },
399 { "movb", BH, Ib, NOFUNC },
401 { "movS", eAX, Iv, NOFUNC },
402 { "movS", eCX, Iv, NOFUNC },
403 { "movS", eDX, Iv, NOFUNC },
404 { "movS", eBX, Iv, NOFUNC },
405 { "movS", eSP, Iv, NOFUNC },
406 { "movS", eBP, Iv, NOFUNC },
407 { "movS", eSI, Iv, NOFUNC },
408 { "movS", eDI, Iv, NOFUNC },
412 { "ret", Iw, NOFUNC, NOFUNC },
413 { "ret", NOFUNC, NOFUNC, NOFUNC },
414 { "lesS", Gv, Mp, NOFUNC },
415 { "ldsS", Gv, Mp, NOFUNC },
416 { "movb", Eb, Ib, NOFUNC },
417 { "movS", Ev, Iv, NOFUNC },
419 { "enter", Iw, Ib, NOFUNC },
420 { "leave", NOFUNC, NOFUNC, NOFUNC },
421 { "lret", Iw, NOFUNC, NOFUNC },
422 { "lret", NOFUNC, NOFUNC, NOFUNC },
423 { "int3", NOFUNC, NOFUNC, NOFUNC },
424 { "int", Ib, NOFUNC, NOFUNC },
425 { "into", NOFUNC, NOFUNC, NOFUNC },
426 { "iret", NOFUNC, NOFUNC, NOFUNC },
432 { "aam", Ib, NOFUNC, NOFUNC },
433 { "aad", Ib, NOFUNC, NOFUNC },
434 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
435 { "xlat", NOFUNC, NOFUNC, NOFUNC },
446 { "loopne", Jb, NOFUNC, NOFUNC },
447 { "loope", Jb, NOFUNC, NOFUNC },
448 { "loop", Jb, NOFUNC, NOFUNC },
449 { "jCcxz", Jb, NOFUNC, NOFUNC },
450 { "inb", AL, Ib, NOFUNC },
451 { "inS", eAX, Ib, NOFUNC },
452 { "outb", Ib, AL, NOFUNC },
453 { "outS", Ib, eAX, NOFUNC },
455 { "call", Av, NOFUNC, NOFUNC },
456 { "jmp", Jv, NOFUNC, NOFUNC },
457 { "ljmp", Ap, NOFUNC, NOFUNC },
458 { "jmp", Jb, NOFUNC, NOFUNC },
459 { "inb", AL, indirDX, NOFUNC },
460 { "inS", eAX, indirDX, NOFUNC },
461 { "outb", indirDX, AL, NOFUNC },
462 { "outS", indirDX, eAX, NOFUNC },
464 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* lock prefix */
465 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
466 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* repne */
467 { "(bad)", NOFUNC, NOFUNC, NOFUNC }, /* repz */
468 { "hlt", NOFUNC, NOFUNC, NOFUNC },
469 { "cmc", NOFUNC, NOFUNC, NOFUNC },
473 { "clc", NOFUNC, NOFUNC, NOFUNC },
474 { "stc", NOFUNC, NOFUNC, NOFUNC },
475 { "cli", NOFUNC, NOFUNC, NOFUNC },
476 { "sti", NOFUNC, NOFUNC, NOFUNC },
477 { "cld", NOFUNC, NOFUNC, NOFUNC },
478 { "std", NOFUNC, NOFUNC, NOFUNC },
483 struct dis386 dis386_twobyte[] = {
487 { "larS", Gv, Ew, NOFUNC },
488 { "lslS", Gv, Ew, NOFUNC },
489 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
490 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
491 { "clts", NOFUNC, NOFUNC, NOFUNC },
492 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
494 { "invd", NOFUNC, NOFUNC, NOFUNC },
495 { "wbinvd", 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 },
501 { "(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 },
510 { "(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 },
519 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
521 /* these are all backward in appendix A of the intel book */
522 { "movl", Rd, Cd, NOFUNC },
523 { "movl", Rd, Dd, NOFUNC },
524 { "movl", Cd, Rd, NOFUNC },
525 { "movl", Dd, Rd, NOFUNC },
526 { "movl", Rd, Td, NOFUNC },
527 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
528 { "movl", Td, Rd, NOFUNC },
529 { "(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 },
538 { "(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 },
547 { "(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 },
556 { "(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 },
565 { "(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 },
574 { "(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 },
583 { "(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 },
592 { "(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 },
601 { "(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 },
610 { "(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 },
619 { "(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 },
628 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
630 { "jo", Jv, NOFUNC, NOFUNC },
631 { "jno", Jv, NOFUNC, NOFUNC },
632 { "jb", Jv, NOFUNC, NOFUNC },
633 { "jae", Jv, NOFUNC, NOFUNC },
634 { "je", Jv, NOFUNC, NOFUNC },
635 { "jne", Jv, NOFUNC, NOFUNC },
636 { "jbe", Jv, NOFUNC, NOFUNC },
637 { "ja", Jv, NOFUNC, NOFUNC },
639 { "js", Jv, NOFUNC, NOFUNC },
640 { "jns", Jv, NOFUNC, NOFUNC },
641 { "jp", Jv, NOFUNC, NOFUNC },
642 { "jnp", Jv, NOFUNC, NOFUNC },
643 { "jl", Jv, NOFUNC, NOFUNC },
644 { "jge", Jv, NOFUNC, NOFUNC },
645 { "jle", Jv, NOFUNC, NOFUNC },
646 { "jg", Jv, NOFUNC, NOFUNC },
648 { "seto", Eb, NOFUNC, NOFUNC },
649 { "setno", Eb, NOFUNC, NOFUNC },
650 { "setb", Eb, NOFUNC, NOFUNC },
651 { "setae", Eb, NOFUNC, NOFUNC },
652 { "sete", Eb, NOFUNC, NOFUNC },
653 { "setne", Eb, NOFUNC, NOFUNC },
654 { "setbe", Eb, NOFUNC, NOFUNC },
655 { "seta", Eb, NOFUNC, NOFUNC },
657 { "sets", Eb, NOFUNC, NOFUNC },
658 { "setns", Eb, NOFUNC, NOFUNC },
659 { "setp", Eb, NOFUNC, NOFUNC },
660 { "setnp", Eb, NOFUNC, NOFUNC },
661 { "setl", Eb, NOFUNC, NOFUNC },
662 { "setge", Eb, NOFUNC, NOFUNC },
663 { "setle", Eb, NOFUNC, NOFUNC },
664 { "setg", Eb, NOFUNC, NOFUNC },
666 { "pushl", fs, NOFUNC, NOFUNC },
667 { "popl", fs, NOFUNC, NOFUNC },
668 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
669 { "btS", Ev, Gv, NOFUNC },
670 { "shldS", Ev, Gv, Ib },
671 { "shldS", Ev, Gv, CL },
672 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
673 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
675 { "pushl", gs, NOFUNC, NOFUNC },
676 { "popl", gs, NOFUNC, NOFUNC },
677 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
678 { "btsS", Ev, Gv, NOFUNC },
679 { "shrdS", Ev, Gv, Ib },
680 { "shrdS", Ev, Gv, CL },
681 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
682 { "imulS", Gv, Ev, NOFUNC },
684 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
685 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
686 { "lssS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
687 { "btrS", Ev, Gv, NOFUNC },
688 { "lfsS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
689 { "lgsS", Gv, Mp, NOFUNC }, /* 386 lists only Mp */
690 { "movzbS", Gv, Eb, NOFUNC },
691 { "movzwS", Gv, Ew, NOFUNC },
693 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
694 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
696 { "btcS", Ev, Gv, NOFUNC },
697 { "bsfS", Gv, Ev, NOFUNC },
698 { "bsrS", Gv, Ev, NOFUNC },
699 { "movsbS", Gv, Eb, NOFUNC },
700 { "movswS", Gv, Ew, 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 },
709 { "(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 },
718 { "(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 },
727 { "(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 },
736 { "(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 },
745 { "(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 },
754 { "(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 },
763 { "(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 },
772 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
775 static char obuf[100];
777 static char scratchbuf[100];
778 static unsigned char *start_codep;
779 static unsigned char *codep;
784 static const char *names32[]={
785 "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
787 static const char *names16[] = {
788 "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
790 static const char *names8[] = {
791 "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
793 static const char *names_seg[] = {
794 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
796 static const char *names16_pairs[] = {
797 "%bx+%si","%bx+%di","%bp+%si","%bp+%di","%si","%di","%bp","%bx",
800 struct dis386 grps[][8] = {
803 { "addb", Eb, Ib, NOFUNC },
804 { "orb", Eb, Ib, NOFUNC },
805 { "adcb", Eb, Ib, NOFUNC },
806 { "sbbb", Eb, Ib, NOFUNC },
807 { "andb", Eb, Ib, NOFUNC },
808 { "subb", Eb, Ib, NOFUNC },
809 { "xorb", Eb, Ib, NOFUNC },
810 { "cmpb", Eb, Ib, NOFUNC }
814 { "addS", Ev, Iv, NOFUNC },
815 { "orS", Ev, Iv, NOFUNC },
816 { "adcS", Ev, Iv, NOFUNC },
817 { "sbbS", Ev, Iv, NOFUNC },
818 { "andS", Ev, Iv, NOFUNC },
819 { "subS", Ev, Iv, NOFUNC },
820 { "xorS", Ev, Iv, NOFUNC },
821 { "cmpS", Ev, Iv, NOFUNC }
825 { "addS", Ev, sIb, NOFUNC },
826 { "orS", Ev, sIb, NOFUNC },
827 { "adcS", Ev, sIb, NOFUNC },
828 { "sbbS", Ev, sIb, NOFUNC },
829 { "andS", Ev, sIb, NOFUNC },
830 { "subS", Ev, sIb, NOFUNC },
831 { "xorS", Ev, sIb, NOFUNC },
832 { "cmpS", Ev, sIb, NOFUNC }
836 { "rolb", Eb, Ib, NOFUNC },
837 { "rorb", Eb, Ib, NOFUNC },
838 { "rclb", Eb, Ib, NOFUNC },
839 { "rcrb", Eb, Ib, NOFUNC },
840 { "shlb", Eb, Ib, NOFUNC },
841 { "shrb", Eb, Ib, NOFUNC },
842 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
843 { "sarb", Eb, Ib, NOFUNC },
847 { "rolS", Ev, Ib, NOFUNC },
848 { "rorS", Ev, Ib, NOFUNC },
849 { "rclS", Ev, Ib, NOFUNC },
850 { "rcrS", Ev, Ib, NOFUNC },
851 { "shlS", Ev, Ib, NOFUNC },
852 { "shrS", Ev, Ib, NOFUNC },
853 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
854 { "sarS", Ev, Ib, NOFUNC },
858 { "rolb", Eb, NOFUNC, NOFUNC },
859 { "rorb", Eb, NOFUNC, NOFUNC },
860 { "rclb", Eb, NOFUNC, NOFUNC },
861 { "rcrb", Eb, NOFUNC, NOFUNC },
862 { "shlb", Eb, NOFUNC, NOFUNC },
863 { "shrb", Eb, NOFUNC, NOFUNC },
864 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
865 { "sarb", Eb, NOFUNC, NOFUNC },
869 { "rolS", Ev, NOFUNC, NOFUNC },
870 { "rorS", Ev, NOFUNC, NOFUNC },
871 { "rclS", Ev, NOFUNC, NOFUNC },
872 { "rcrS", Ev, NOFUNC, NOFUNC },
873 { "shlS", Ev, NOFUNC, NOFUNC },
874 { "shrS", Ev, NOFUNC, NOFUNC },
875 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
876 { "sarS", Ev, NOFUNC, NOFUNC },
880 { "rolb", Eb, CL, NOFUNC },
881 { "rorb", Eb, CL, NOFUNC },
882 { "rclb", Eb, CL, NOFUNC },
883 { "rcrb", Eb, CL, NOFUNC },
884 { "shlb", Eb, CL, NOFUNC },
885 { "shrb", Eb, CL, NOFUNC },
886 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
887 { "sarb", Eb, CL, NOFUNC },
891 { "rolS", Ev, CL, NOFUNC },
892 { "rorS", Ev, CL, NOFUNC },
893 { "rclS", Ev, CL, NOFUNC },
894 { "rcrS", Ev, CL, NOFUNC },
895 { "shlS", Ev, CL, NOFUNC },
896 { "shrS", Ev, CL, NOFUNC },
897 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
898 { "sarS", Ev, CL, NOFUNC }
902 { "testb", Eb, Ib, NOFUNC },
903 { "(bad)", Eb, NOFUNC, NOFUNC },
904 { "notb", Eb, NOFUNC, NOFUNC },
905 { "negb", Eb, NOFUNC, NOFUNC },
906 { "mulb", AL, Eb, NOFUNC },
907 { "imulb", AL, Eb, NOFUNC },
908 { "divb", AL, Eb, NOFUNC },
909 { "idivb", AL, Eb, NOFUNC }
913 { "testS", Ev, Iv, NOFUNC },
914 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
915 { "notS", Ev, NOFUNC, NOFUNC },
916 { "negS", Ev, NOFUNC, NOFUNC },
917 { "mulS", eAX, Ev, NOFUNC },
918 { "imulS", eAX, Ev, NOFUNC },
919 { "divS", eAX, Ev, NOFUNC },
920 { "idivS", eAX, Ev, NOFUNC },
924 { "incb", Eb, NOFUNC, NOFUNC },
925 { "decb", Eb, 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 },
931 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
935 { "incS", Ev, NOFUNC, NOFUNC },
936 { "decS", Ev, NOFUNC, NOFUNC },
937 { "call", indirEv, NOFUNC, NOFUNC },
938 { "lcall", indirEv, NOFUNC, NOFUNC },
939 { "jmp", indirEv, NOFUNC, NOFUNC },
940 { "ljmp", indirEv, NOFUNC, NOFUNC },
941 { "pushS", Ev, NOFUNC, NOFUNC },
942 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
946 { "sldt", Ew, NOFUNC, NOFUNC },
947 { "str", Ew, NOFUNC, NOFUNC },
948 { "lldt", Ew, NOFUNC, NOFUNC },
949 { "ltr", Ew, NOFUNC, NOFUNC },
950 { "verr", Ew, NOFUNC, NOFUNC },
951 { "verw", Ew, NOFUNC, NOFUNC },
952 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
953 { "(bad)", NOFUNC, NOFUNC, NOFUNC }
957 { "sgdt", Ew, NOFUNC, NOFUNC },
958 { "sidt", Ew, NOFUNC, NOFUNC },
959 { "lgdt", Ew, NOFUNC, NOFUNC },
960 { "lidt", Ew, NOFUNC, NOFUNC },
961 { "smsw", Ew, NOFUNC, NOFUNC },
962 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
963 { "lmsw", Ew, NOFUNC, NOFUNC },
964 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
968 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
969 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
970 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
971 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
972 { "btS", Ev, Ib, NOFUNC },
973 { "btsS", Ev, Ib, NOFUNC },
974 { "btrS", Ev, Ib, NOFUNC },
975 { "btcS", Ev, Ib, NOFUNC },
979 #define PREFIX_REPZ 0x01
980 #define PREFIX_REPNZ 0x02
981 #define PREFIX_LOCK 0x04
982 #define PREFIX_CS 0x08
983 #define PREFIX_SS 0x10
984 #define PREFIX_DS 0x20
985 #define PREFIX_ES 0x40
986 #define PREFIX_FS 0x80
987 #define PREFIX_GS 0x100
988 #define PREFIX_DATA 0x200
989 #define PREFIX_ADR 0x400
990 #define PREFIX_FWAIT 0x800
1003 prefixes |= PREFIX_REPZ;
1006 prefixes |= PREFIX_REPNZ;
1009 prefixes |= PREFIX_LOCK;
1012 prefixes |= PREFIX_CS;
1015 prefixes |= PREFIX_SS;
1018 prefixes |= PREFIX_DS;
1021 prefixes |= PREFIX_ES;
1024 prefixes |= PREFIX_FS;
1027 prefixes |= PREFIX_GS;
1030 prefixes |= PREFIX_DATA;
1033 prefixes |= PREFIX_ADR;
1036 prefixes |= PREFIX_FWAIT;
1048 static char op1out[100], op2out[100], op3out[100];
1049 static unsigned long start_pc;
1052 * disassemble the first instruction in 'inbuf'. You have to make
1053 * sure all of the bytes of the instruction are filled in.
1054 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1055 * (see topic "Redundant prefixes" in the "Differences from 8086"
1056 * section of the "Virtual 8086 Mode" chapter.)
1057 * 'pc' should be the address of this instruction, it will
1058 * be used to print the target address if this is a relative jump or call
1059 * 'outbuf' gets filled in with the disassembled instruction. it should
1060 * be long enough to hold the longest disassembled instruction.
1061 * 100 bytes is certainly enough, unless symbol printing is added later
1062 * The function returns the length of this instruction in bytes.
1065 i386dis (unsigned short ucs, unsigned short uip, unsigned char *inbuf,
1066 char *outbuf, int mode)
1070 int enter_instruction;
1071 char *first, *second, *third;
1079 start_pc = ucs << 16 | uip;
1080 start_codep = inbuf;
1086 enter_instruction = 1;
1088 enter_instruction = 0;
1092 if (prefixes & PREFIX_REPZ)
1094 if (prefixes & PREFIX_REPNZ)
1096 if (prefixes & PREFIX_LOCK)
1099 if ((prefixes & PREFIX_FWAIT)
1100 && ((*codep < 0xd8) || (*codep > 0xdf)))
1102 /* fwait not followed by floating point instruction */
1104 strcpy (outbuf, obuf);
1108 /* these would be initialized to 0 if disassembling for 8086 or 286 */
1117 if (prefixes & PREFIX_DATA)
1120 if (prefixes & PREFIX_ADR)
1123 oappend ("addr16 ");
1127 dp = &dis386_twobyte[*++codep];
1129 dp = &dis386[*codep];
1131 mod = (*codep >> 6) & 3;
1132 reg = (*codep >> 3) & 7;
1135 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1141 if (dp->name == NULL)
1142 dp = &grps[dp->bytemode1][reg];
1148 (*dp->op1)(dp->bytemode1);
1152 (*dp->op2)(dp->bytemode2);
1156 (*dp->op3)(dp->bytemode3);
1159 obufp = obuf + strlen (obuf);
1160 for (i = strlen (obuf); i < 6; i++)
1164 /* enter instruction is printed with operands in the
1165 * same order as the intel book; everything else
1166 * is printed in reverse order
1168 if (enter_instruction)
1199 strcpy (outbuf, obuf);
1200 return (codep - inbuf);
1203 const char *float_mem[] = {
1279 #define STi OP_STi, 0
1281 #define FGRPd9_2 NULL, NULL, 0, NOFUNC, NOFUNC
1282 #define FGRPd9_4 NULL, NULL, 1, NOFUNC, NOFUNC
1283 #define FGRPd9_5 NULL, NULL, 2, NOFUNC, NOFUNC
1284 #define FGRPd9_6 NULL, NULL, 3, NOFUNC, NOFUNC
1285 #define FGRPd9_7 NULL, NULL, 4, NOFUNC, NOFUNC
1286 #define FGRPda_5 NULL, NULL, 5, NOFUNC, NOFUNC
1287 #define FGRPdb_4 NULL, NULL, 6, NOFUNC, NOFUNC
1288 #define FGRPde_3 NULL, NULL, 7, NOFUNC, NOFUNC
1289 #define FGRPdf_4 NULL, NULL, 8, NOFUNC, NOFUNC
1291 struct dis386 float_reg[][8] = {
1294 { "fadd", ST, STi, NOFUNC },
1295 { "fmul", ST, STi, NOFUNC },
1296 { "fcom", STi, NOFUNC, NOFUNC },
1297 { "fcomp", STi, NOFUNC, NOFUNC },
1298 { "fsub", ST, STi, NOFUNC },
1299 { "fsubr", ST, STi, NOFUNC },
1300 { "fdiv", ST, STi, NOFUNC },
1301 { "fdivr", ST, STi, NOFUNC },
1305 { "fld", STi, NOFUNC, NOFUNC },
1306 { "fxch", STi, NOFUNC, NOFUNC },
1308 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1316 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1317 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1318 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1319 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1320 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1322 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1323 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1327 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1328 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1329 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1330 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1332 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1333 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1334 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1338 { "fadd", STi, ST, NOFUNC },
1339 { "fmul", STi, ST, NOFUNC },
1340 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1341 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1342 { "fsub", STi, ST, NOFUNC },
1343 { "fsubr", STi, ST, NOFUNC },
1344 { "fdiv", STi, ST, NOFUNC },
1345 { "fdivr", STi, ST, NOFUNC },
1349 { "ffree", STi, NOFUNC, NOFUNC },
1350 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1351 { "fst", STi, NOFUNC, NOFUNC },
1352 { "fstp", STi, NOFUNC, NOFUNC },
1353 { "fucom", STi, NOFUNC, NOFUNC },
1354 { "fucomp", STi, NOFUNC, NOFUNC },
1355 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1356 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1360 { "faddp", STi, ST, NOFUNC },
1361 { "fmulp", STi, ST, NOFUNC },
1362 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1364 { "fsubp", STi, ST, NOFUNC },
1365 { "fsubrp", STi, ST, NOFUNC },
1366 { "fdivp", STi, ST, NOFUNC },
1367 { "fdivrp", STi, ST, NOFUNC },
1371 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1372 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1373 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1374 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1376 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1377 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1378 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1383 const char *fgrps[][8] = {
1386 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1391 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1396 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1401 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1406 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1411 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1416 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1417 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1422 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1427 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1436 unsigned char floatop;
1438 floatop = codep[-1];
1442 putop (float_mem[(floatop - 0xd8) * 8 + reg]);
1449 dp = &float_reg[floatop - 0xd8][reg];
1450 if (dp->name == NULL)
1452 putop (fgrps[dp->bytemode1][rm]);
1453 /* instruction fnstsw is only one with strange arg */
1454 if (floatop == 0xdf && *codep == 0xe0)
1455 strcpy (op1out, "%eax");
1462 (*dp->op1)(dp->bytemode1);
1465 (*dp->op2)(dp->bytemode2);
1470 OP_ST(int dummy __unused)
1476 OP_STi(int dummy __unused)
1478 sprintf (scratchbuf, "%%st(%d)", rm);
1479 oappend (scratchbuf);
1483 /* capital letters in template are macros */
1485 putop(const char *template)
1489 for (p = template; *p; p++)
1496 case 'C': /* For jcxz/jecxz */
1501 if ((prefixes & PREFIX_FWAIT) == 0)
1505 /* operand size flag */
1517 oappend(const char *s)
1520 obufp += strlen (s);
1527 if (prefixes & PREFIX_CS)
1529 if (prefixes & PREFIX_DS)
1531 if (prefixes & PREFIX_SS)
1533 if (prefixes & PREFIX_ES)
1535 if (prefixes & PREFIX_FS)
1537 if (prefixes & PREFIX_GS)
1542 OP_indirE(int bytemode)
1558 /* skip mod/rm byte */
1568 oappend (names8[rm]);
1571 oappend (names16[rm]);
1575 oappend (names32[rm]);
1577 oappend (names16[rm]);
1580 oappend ("<bad dis table>");
1588 if (aflag && rm == 4) {
1591 scale = (*codep >> 6) & 3;
1592 idx = (*codep >> 3) & 7;
1602 /* implies havesib and havebase */
1627 disp = *(char *)codep++;
1628 if (!aflag || rm != 4) {
1638 if (!aflag || rm != 4) {
1645 if (mod != 0 || ((aflag && rm == 5) || (havesib && base == 5))
1646 || (!aflag && rm == 6)) {
1647 sprintf (scratchbuf, "0x%x", disp);
1648 oappend (scratchbuf);
1651 if (havebase || havesib) {
1654 oappend (aflag ? names32[base] : names16_pairs[base]);
1657 sprintf (scratchbuf, ",%s", names32[idx]);
1658 oappend (scratchbuf);
1660 sprintf (scratchbuf, ",%d", 1 << scale);
1661 oappend (scratchbuf);
1673 oappend (names8[reg]);
1676 oappend (names16[reg]);
1679 oappend (names32[reg]);
1683 oappend (names32[reg]);
1685 oappend (names16[reg]);
1688 oappend ("<internal disassembler error>");
1698 x = *codep++ & 0xff;
1699 x |= (*codep++ & 0xff) << 8;
1700 x |= (*codep++ & 0xff) << 16;
1701 x |= (*codep++ & 0xff) << 24;
1710 x = *codep++ & 0xff;
1711 x |= (*codep++ & 0xff) << 8;
1722 case indir_dx_reg: s = "(%dx)"; break;
1723 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
1724 case sp_reg: case bp_reg: case si_reg: case di_reg:
1725 s = names16[code - ax_reg];
1727 case es_reg: case ss_reg: case cs_reg:
1728 case ds_reg: case fs_reg: case gs_reg:
1729 s = names_seg[code - es_reg];
1731 case al_reg: case ah_reg: case cl_reg: case ch_reg:
1732 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
1733 s = names8[code - al_reg];
1735 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
1736 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
1738 s = names32[code - eAX_reg];
1740 s = names16[code - eAX_reg];
1743 s = "<internal disassembler error>";
1757 op = *codep++ & 0xff;
1769 oappend ("<internal disassembler error>");
1772 sprintf (scratchbuf, "$0x%x", op);
1773 oappend (scratchbuf);
1784 op = *(char *)codep++;
1790 op = (short)get16();
1793 op = (short)get16 ();
1796 oappend ("<internal disassembler error>");
1799 sprintf (scratchbuf, "$0x%x", op);
1800 oappend (scratchbuf);
1811 disp = *(char *)codep++;
1812 append_pc(start_pc + codep - start_codep + disp);
1817 append_pc(start_pc + codep - start_codep + disp);
1819 disp = (short)get16 ();
1820 disp = (((start_pc + codep - start_codep) & 0xffff) + disp) & 0xffff;
1821 append_pc((start_pc & 0xffff0000) | disp);
1825 oappend ("<internal disassembelr error>");
1829 oappend (scratchbuf);
1833 append_pc(unsigned long pc)
1835 sprintf(scratchbuf, "%04lx:%04lx", pc >> 16, pc & 0xffff);
1839 OP_SEG(int dummy __unused)
1841 static const char *sreg[] = {
1842 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
1845 oappend (sreg[reg]);
1866 sprintf (scratchbuf, "%04x:%04x", seg, offset);
1867 oappend (scratchbuf);
1873 offset = (short)get16 ();
1875 append_pc(start_pc + codep - start_codep + offset);
1876 oappend (scratchbuf);
1879 oappend ("<internal disassembler error>");
1885 OP_OFF(int dummy __unused)
1894 sprintf (scratchbuf, "0x%x", off);
1895 oappend (scratchbuf);
1899 OP_ESDI(int dummy __unused)
1902 oappend (aflag ? "%edi" : "%di");
1907 OP_DSSI(int dummy __unused)
1910 oappend (aflag ? "%esi" : "%si");
1915 OP_C(int dummy __unused)
1917 codep++; /* skip mod/rm */
1918 sprintf (scratchbuf, "%%cr%d", reg);
1919 oappend (scratchbuf);
1923 OP_D(int dummy __unused)
1925 codep++; /* skip mod/rm */
1926 sprintf (scratchbuf, "%%db%d", reg);
1927 oappend (scratchbuf);
1931 OP_T(int dummy __unused)
1933 codep++; /* skip mod/rm */
1934 sprintf (scratchbuf, "%%tr%d", reg);
1935 oappend (scratchbuf);
1944 oappend (names32[rm]);
1947 oappend (names16[rm]);
1954 i386dis (int pc, unsigned char *inbuf, char outbuf, int mode)
1956 strcpy (outbuf, "(no disassembler)");
1960 #endif /* DISASSEMBLER */