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 */