MFC: An off-by-one malloc size was corrupting the installer's memory,
[dragonfly.git] / usr.bin / doscmd / i386-pinsn.c
blob048b0a51844c224a98c2958b5fa8c01e3f271e1d
1 /*
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.3 2003/10/04 20:36:43 hmp Exp $
4 */
5 #ifdef DISASSEMBLER
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)
15 any later version.
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)
28 * July 1988
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.
40 #include <stdio.h>
41 #include <ctype.h>
43 #include "doscmd.h"
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
65 #define M OP_E, 0
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
118 #define b_mode 1
119 #define v_mode 2
120 #define w_mode 3
121 #define d_mode 4
123 #define es_reg 100
124 #define cs_reg 101
125 #define ss_reg 102
126 #define ds_reg 103
127 #define fs_reg 104
128 #define gs_reg 105
129 #define eAX_reg 107
130 #define eCX_reg 108
131 #define eDX_reg 109
132 #define eBX_reg 110
133 #define eSP_reg 111
134 #define eBP_reg 112
135 #define eSI_reg 113
136 #define eDI_reg 114
138 #define lptr 115
140 #define al_reg 116
141 #define cl_reg 117
142 #define dl_reg 118
143 #define bl_reg 119
144 #define ah_reg 120
145 #define ch_reg 121
146 #define dh_reg 122
147 #define bh_reg 123
149 #define ax_reg 124
150 #define cx_reg 125
151 #define dx_reg 126
152 #define bx_reg 127
153 #define sp_reg 128
154 #define bp_reg 129
155 #define si_reg 130
156 #define di_reg 131
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
179 #define FLOATCODE 50
180 #define FLOAT NULL, NULL, FLOATCODE, NOFUNC, NOFUNC
182 struct dis386 {
183 const char *name;
184 void (*op1)(int);
185 int bytemode1;
186 void (*op2)(int);
187 int bytemode2;
188 void (*op3)(int);
189 int bytemode3;
192 struct dis386 dis386[] = {
193 /* 00 */
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 },
202 /* 08 */
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 */
211 /* 10 */
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 },
220 /* 18 */
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 },
229 /* 20 */
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 },
238 /* 28 */
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 },
247 /* 30 */
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 },
256 /* 38 */
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 },
265 /* 40 */
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 },
274 /* 48 */
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 },
283 /* 50 */
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 },
292 /* 58 */
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 },
301 /* 60 */
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 */
310 /* 68 */
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 },
319 /* 70 */
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 },
328 /* 78 */
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 },
337 /* 80 */
338 { GRP1b },
339 { GRP1S },
340 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
341 { GRP1Ss },
342 { "testb", Eb, Gb, NOFUNC },
343 { "testS", Ev, Gv, NOFUNC },
344 { "xchgb", Eb, Gb, NOFUNC },
345 { "xchgS", Ev, Gv, NOFUNC },
346 /* 88 */
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 },
355 /* 90 */
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 },
364 /* 98 */
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 },
373 /* a0 */
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 },
382 /* a8 */
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 },
391 /* b0 */
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 },
400 /* b8 */
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 },
409 /* c0 */
410 { GRP2b },
411 { GRP2S },
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 },
418 /* c8 */
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 },
427 /* d0 */
428 { GRP2b_one },
429 { GRP2S_one },
430 { GRP2b_cl },
431 { GRP2S_cl },
432 { "aam", Ib, NOFUNC, NOFUNC },
433 { "aad", Ib, NOFUNC, NOFUNC },
434 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
435 { "xlat", NOFUNC, NOFUNC, NOFUNC },
436 /* d8 */
437 { FLOAT },
438 { FLOAT },
439 { FLOAT },
440 { FLOAT },
441 { FLOAT },
442 { FLOAT },
443 { FLOAT },
444 { FLOAT },
445 /* e0 */
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 },
454 /* e8 */
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 },
463 /* f0 */
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 },
470 { GRP3b },
471 { GRP3S },
472 /* f8 */
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 },
479 { GRP4 },
480 { GRP5 },
483 struct dis386 dis386_twobyte[] = {
484 /* 00 */
485 { GRP6 },
486 { GRP7 },
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 },
493 /* 08 */
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 },
502 /* 10 */
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 },
511 /* 18 */
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 },
520 /* 20 */
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 },
530 /* 28 */
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 },
539 /* 30 */
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 },
548 /* 38 */
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 },
557 /* 40 */
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 },
566 /* 48 */
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 },
575 /* 50 */
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 },
584 /* 58 */
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 },
593 /* 60 */
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 },
602 /* 68 */
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 },
611 /* 70 */
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 },
620 /* 78 */
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 },
629 /* 80 */
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 },
638 /* 88 */
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 },
647 /* 90 */
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 },
656 /* 98 */
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 },
665 /* a0 */
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 },
674 /* a8 */
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 },
683 /* b0 */
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 },
692 /* b8 */
693 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
694 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
695 { GRP8 },
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 },
701 /* c0 */
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 },
710 /* c8 */
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 },
719 /* d0 */
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 },
728 /* d8 */
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 },
737 /* e0 */
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 },
746 /* e8 */
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 },
755 /* f0 */
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 },
764 /* f8 */
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];
776 static char *obufp;
777 static char scratchbuf[100];
778 static unsigned char *start_codep;
779 static unsigned char *codep;
780 static int mod;
781 static int rm;
782 static int reg;
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] = {
801 /* GRP1b */
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 }
812 /* GRP1S */
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 }
823 /* GRP1Ss */
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 }
834 /* GRP2b */
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 },
845 /* GRP2S */
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 },
856 /* GRP2b_one */
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 },
867 /* GRP2S_one */
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 },
878 /* GRP2b_cl */
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 },
889 /* GRP2S_cl */
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 }
900 /* GRP3b */
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 }
911 /* GRP3S */
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 },
922 /* GRP4 */
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 },
933 /* GRP5 */
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 },
944 /* GRP6 */
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 }
955 /* GRP7 */
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 },
966 /* GRP8 */
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
992 static int prefixes;
994 static void
995 ckprefix(void)
997 prefixes = 0;
998 while (1)
1000 switch (*codep)
1002 case 0xf3:
1003 prefixes |= PREFIX_REPZ;
1004 break;
1005 case 0xf2:
1006 prefixes |= PREFIX_REPNZ;
1007 break;
1008 case 0xf0:
1009 prefixes |= PREFIX_LOCK;
1010 break;
1011 case 0x2e:
1012 prefixes |= PREFIX_CS;
1013 break;
1014 case 0x36:
1015 prefixes |= PREFIX_SS;
1016 break;
1017 case 0x3e:
1018 prefixes |= PREFIX_DS;
1019 break;
1020 case 0x26:
1021 prefixes |= PREFIX_ES;
1022 break;
1023 case 0x64:
1024 prefixes |= PREFIX_FS;
1025 break;
1026 case 0x65:
1027 prefixes |= PREFIX_GS;
1028 break;
1029 case 0x66:
1030 prefixes |= PREFIX_DATA;
1031 break;
1032 case 0x67:
1033 prefixes |= PREFIX_ADR;
1034 break;
1035 case 0x9b:
1036 prefixes |= PREFIX_FWAIT;
1037 break;
1038 default:
1039 return;
1041 codep++;
1045 static int dflag;
1046 static int aflag;
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)
1068 struct dis386 *dp;
1069 int i;
1070 int enter_instruction;
1071 char *first, *second, *third;
1072 int needcomma;
1074 obuf[0] = 0;
1075 op1out[0] = 0;
1076 op2out[0] = 0;
1077 op3out[0] = 0;
1079 start_pc = ucs << 16 | uip;
1080 start_codep = inbuf;
1081 codep = inbuf;
1083 ckprefix ();
1085 if (*codep == 0xc8)
1086 enter_instruction = 1;
1087 else
1088 enter_instruction = 0;
1090 obufp = obuf;
1092 if (prefixes & PREFIX_REPZ)
1093 oappend ("repz ");
1094 if (prefixes & PREFIX_REPNZ)
1095 oappend ("repnz ");
1096 if (prefixes & PREFIX_LOCK)
1097 oappend ("lock ");
1099 if ((prefixes & PREFIX_FWAIT)
1100 && ((*codep < 0xd8) || (*codep > 0xdf)))
1102 /* fwait not followed by floating point instruction */
1103 oappend ("fwait");
1104 strcpy (outbuf, obuf);
1105 return (1);
1108 /* these would be initialized to 0 if disassembling for 8086 or 286 */
1109 if (mode) {
1110 dflag = 1;
1111 aflag = 1;
1112 } else {
1113 dflag = 0;
1114 aflag = 0;
1117 if (prefixes & PREFIX_DATA)
1118 dflag ^= 1;
1120 if (prefixes & PREFIX_ADR)
1122 aflag ^= 1;
1123 oappend ("addr16 ");
1126 if (*codep == 0x0f)
1127 dp = &dis386_twobyte[*++codep];
1128 else
1129 dp = &dis386[*codep];
1130 codep++;
1131 mod = (*codep >> 6) & 3;
1132 reg = (*codep >> 3) & 7;
1133 rm = *codep & 7;
1135 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1137 dofloat ();
1139 else
1141 if (dp->name == NULL)
1142 dp = &grps[dp->bytemode1][reg];
1144 putop (dp->name);
1146 obufp = op1out;
1147 if (dp->op1)
1148 (*dp->op1)(dp->bytemode1);
1150 obufp = op2out;
1151 if (dp->op2)
1152 (*dp->op2)(dp->bytemode2);
1154 obufp = op3out;
1155 if (dp->op3)
1156 (*dp->op3)(dp->bytemode3);
1159 obufp = obuf + strlen (obuf);
1160 for (i = strlen (obuf); i < 6; i++)
1161 oappend (" ");
1162 oappend (" ");
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)
1170 first = op1out;
1171 second = op2out;
1172 third = op3out;
1174 else
1176 first = op3out;
1177 second = op2out;
1178 third = op1out;
1180 needcomma = 0;
1181 if (*first)
1183 oappend (first);
1184 needcomma = 1;
1186 if (*second)
1188 if (needcomma)
1189 oappend (",");
1190 oappend (second);
1191 needcomma = 1;
1193 if (*third)
1195 if (needcomma)
1196 oappend (",");
1197 oappend (third);
1199 strcpy (outbuf, obuf);
1200 return (codep - inbuf);
1203 const char *float_mem[] = {
1204 /* d8 */
1205 "fadds",
1206 "fmuls",
1207 "fcoms",
1208 "fcomps",
1209 "fsubs",
1210 "fsubrs",
1211 "fdivs",
1212 "fdivrs",
1213 /* d9 */
1214 "flds",
1215 "(bad)",
1216 "fsts",
1217 "fstps",
1218 "fldenv",
1219 "fldcw",
1220 "fNstenv",
1221 "fNstcw",
1222 /* da */
1223 "fiaddl",
1224 "fimull",
1225 "ficoml",
1226 "ficompl",
1227 "fisubl",
1228 "fisubrl",
1229 "fidivl",
1230 "fidivrl",
1231 /* db */
1232 "fildl",
1233 "(bad)",
1234 "fistl",
1235 "fistpl",
1236 "(bad)",
1237 "fldt",
1238 "(bad)",
1239 "fstpt",
1240 /* dc */
1241 "faddl",
1242 "fmull",
1243 "fcoml",
1244 "fcompl",
1245 "fsubl",
1246 "fsubrl",
1247 "fdivl",
1248 "fdivrl",
1249 /* dd */
1250 "fldl",
1251 "(bad)",
1252 "fstl",
1253 "fstpl",
1254 "frstor",
1255 "(bad)",
1256 "fNsave",
1257 "fNstsw",
1258 /* de */
1259 "fiadd",
1260 "fimul",
1261 "ficom",
1262 "ficomp",
1263 "fisub",
1264 "fisubr",
1265 "fidiv",
1266 "fidivr",
1267 /* df */
1268 "fild",
1269 "(bad)",
1270 "fist",
1271 "fistp",
1272 "fbld",
1273 "fildll",
1274 "fbstp",
1275 "fistpll",
1278 #define ST OP_ST, 0
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] = {
1292 /* d8 */
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 },
1303 /* d9 */
1305 { "fld", STi, NOFUNC, NOFUNC },
1306 { "fxch", STi, NOFUNC, NOFUNC },
1307 { FGRPd9_2 },
1308 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1309 { FGRPd9_4 },
1310 { FGRPd9_5 },
1311 { FGRPd9_6 },
1312 { FGRPd9_7 },
1314 /* da */
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 },
1321 { FGRPda_5 },
1322 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1323 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1325 /* db */
1327 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1328 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1329 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1330 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1331 { FGRPdb_4 },
1332 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1333 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1334 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1336 /* dc */
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 },
1347 /* dd */
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 },
1358 /* de */
1360 { "faddp", STi, ST, NOFUNC },
1361 { "fmulp", STi, ST, NOFUNC },
1362 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1363 { FGRPde_3 },
1364 { "fsubp", STi, ST, NOFUNC },
1365 { "fsubrp", STi, ST, NOFUNC },
1366 { "fdivp", STi, ST, NOFUNC },
1367 { "fdivrp", STi, ST, NOFUNC },
1369 /* df */
1371 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1372 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1373 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1374 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1375 { FGRPdf_4 },
1376 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1377 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1378 { "(bad)", NOFUNC, NOFUNC, NOFUNC },
1383 const char *fgrps[][8] = {
1384 /* d9_2 0 */
1386 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1389 /* d9_4 1 */
1391 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1394 /* d9_5 2 */
1396 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1399 /* d9_6 3 */
1401 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1404 /* d9_7 4 */
1406 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1409 /* da_5 5 */
1411 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1414 /* db_4 6 */
1416 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1417 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1420 /* de_3 7 */
1422 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1425 /* df_4 8 */
1427 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1432 static void
1433 dofloat (void)
1435 struct dis386 *dp;
1436 unsigned char floatop;
1438 floatop = codep[-1];
1440 if (mod != 3)
1442 putop (float_mem[(floatop - 0xd8) * 8 + reg]);
1443 obufp = op1out;
1444 OP_E (v_mode);
1445 return;
1447 codep++;
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");
1457 else
1459 putop (dp->name);
1460 obufp = op1out;
1461 if (dp->op1)
1462 (*dp->op1)(dp->bytemode1);
1463 obufp = op2out;
1464 if (dp->op2)
1465 (*dp->op2)(dp->bytemode2);
1469 static void
1470 OP_ST(int dummy __unused)
1472 oappend ("%st");
1475 static void
1476 OP_STi(int dummy __unused)
1478 sprintf (scratchbuf, "%%st(%d)", rm);
1479 oappend (scratchbuf);
1483 /* capital letters in template are macros */
1484 static void
1485 putop(const char *template)
1487 const char *p;
1489 for (p = template; *p; p++)
1491 switch (*p)
1493 default:
1494 *obufp++ = *p;
1495 break;
1496 case 'C': /* For jcxz/jecxz */
1497 if (aflag == 0)
1498 *obufp++ = 'e';
1499 break;
1500 case 'N':
1501 if ((prefixes & PREFIX_FWAIT) == 0)
1502 *obufp++ = 'n';
1503 break;
1504 case 'S':
1505 /* operand size flag */
1506 if (dflag)
1507 *obufp++ = 'l';
1508 else
1509 *obufp++ = 'w';
1510 break;
1513 *obufp = 0;
1516 static void
1517 oappend(const char *s)
1519 strcpy (obufp, s);
1520 obufp += strlen (s);
1521 *obufp = 0;
1524 static void
1525 append_prefix()
1527 if (prefixes & PREFIX_CS)
1528 oappend ("%cs:");
1529 if (prefixes & PREFIX_DS)
1530 oappend ("%ds:");
1531 if (prefixes & PREFIX_SS)
1532 oappend ("%ss:");
1533 if (prefixes & PREFIX_ES)
1534 oappend ("%es:");
1535 if (prefixes & PREFIX_FS)
1536 oappend ("%fs:");
1537 if (prefixes & PREFIX_GS)
1538 oappend ("%gs:");
1541 static void
1542 OP_indirE(int bytemode)
1544 oappend ("*");
1545 OP_E (bytemode);
1548 static void
1549 OP_E(int bytemode)
1551 int disp;
1552 int havesib;
1553 int base;
1554 int idx;
1555 int scale;
1556 int havebase;
1558 /* skip mod/rm byte */
1559 codep++;
1561 havesib = 0;
1562 havebase = 0;
1563 disp = 0;
1565 if (mod == 3) {
1566 switch (bytemode) {
1567 case b_mode:
1568 oappend (names8[rm]);
1569 break;
1570 case w_mode:
1571 oappend (names16[rm]);
1572 break;
1573 case v_mode:
1574 if (dflag)
1575 oappend (names32[rm]);
1576 else
1577 oappend (names16[rm]);
1578 break;
1579 default:
1580 oappend ("<bad dis table>");
1581 break;
1583 return;
1586 append_prefix ();
1588 if (aflag && rm == 4) {
1589 havesib = 1;
1590 havebase = 1;
1591 scale = (*codep >> 6) & 3;
1592 idx = (*codep >> 3) & 7;
1593 base = *codep & 7;
1594 codep++;
1597 switch (mod) {
1598 case 0:
1599 if (aflag) {
1600 switch (rm) {
1601 case 4:
1602 /* implies havesib and havebase */
1603 if (base == 5) {
1604 havebase = 0;
1605 disp = get32 ();
1607 break;
1608 case 5:
1609 disp = get32 ();
1610 break;
1611 default:
1612 havebase = 1;
1613 base = rm;
1614 break;
1616 } else {
1617 if (rm == 6) {
1618 havebase = 0;
1619 disp = get16 ();
1620 } else {
1621 havebase = 1;
1622 base = rm;
1625 break;
1626 case 1:
1627 disp = *(char *)codep++;
1628 if (!aflag || rm != 4) {
1629 havebase = 1;
1630 base = rm;
1632 break;
1633 case 2:
1634 if (aflag)
1635 disp = get32 ();
1636 else
1637 disp = get16 ();
1638 if (!aflag || rm != 4) {
1639 havebase = 1;
1640 base = rm;
1642 break;
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) {
1652 oappend ("(");
1653 if (havebase)
1654 oappend (aflag ? names32[base] : names16_pairs[base]);
1655 if (havesib) {
1656 if (idx != 4) {
1657 sprintf (scratchbuf, ",%s", names32[idx]);
1658 oappend (scratchbuf);
1660 sprintf (scratchbuf, ",%d", 1 << scale);
1661 oappend (scratchbuf);
1663 oappend (")");
1667 static void
1668 OP_G(int bytemode)
1670 switch (bytemode)
1672 case b_mode:
1673 oappend (names8[reg]);
1674 break;
1675 case w_mode:
1676 oappend (names16[reg]);
1677 break;
1678 case d_mode:
1679 oappend (names32[reg]);
1680 break;
1681 case v_mode:
1682 if (dflag)
1683 oappend (names32[reg]);
1684 else
1685 oappend (names16[reg]);
1686 break;
1687 default:
1688 oappend ("<internal disassembler error>");
1689 break;
1693 static int
1694 get32(void)
1696 int x = 0;
1698 x = *codep++ & 0xff;
1699 x |= (*codep++ & 0xff) << 8;
1700 x |= (*codep++ & 0xff) << 16;
1701 x |= (*codep++ & 0xff) << 24;
1702 return (x);
1705 static int
1706 get16(void)
1708 int x = 0;
1710 x = *codep++ & 0xff;
1711 x |= (*codep++ & 0xff) << 8;
1712 return (x);
1715 static void
1716 OP_REG(int code)
1718 const char *s;
1720 switch (code)
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];
1726 break;
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];
1730 break;
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];
1734 break;
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:
1737 if (dflag)
1738 s = names32[code - eAX_reg];
1739 else
1740 s = names16[code - eAX_reg];
1741 break;
1742 default:
1743 s = "<internal disassembler error>";
1744 break;
1746 oappend (s);
1749 static void
1750 OP_I(int bytemode)
1752 int op;
1754 switch (bytemode)
1756 case b_mode:
1757 op = *codep++ & 0xff;
1758 break;
1759 case v_mode:
1760 if (dflag)
1761 op = get32 ();
1762 else
1763 op = get16 ();
1764 break;
1765 case w_mode:
1766 op = get16 ();
1767 break;
1768 default:
1769 oappend ("<internal disassembler error>");
1770 return;
1772 sprintf (scratchbuf, "$0x%x", op);
1773 oappend (scratchbuf);
1776 static void
1777 OP_sI(int bytemode)
1779 int op;
1781 switch (bytemode)
1783 case b_mode:
1784 op = *(char *)codep++;
1785 break;
1786 case v_mode:
1787 if (dflag)
1788 op = get32 ();
1789 else
1790 op = (short)get16();
1791 break;
1792 case w_mode:
1793 op = (short)get16 ();
1794 break;
1795 default:
1796 oappend ("<internal disassembler error>");
1797 return;
1799 sprintf (scratchbuf, "$0x%x", op);
1800 oappend (scratchbuf);
1803 static void
1804 OP_J(int bytemode)
1806 int disp;
1808 switch (bytemode)
1810 case b_mode:
1811 disp = *(char *)codep++;
1812 append_pc(start_pc + codep - start_codep + disp);
1813 break;
1814 case v_mode:
1815 if (dflag) {
1816 disp = get32 ();
1817 append_pc(start_pc + codep - start_codep + disp);
1818 } else {
1819 disp = (short)get16 ();
1820 disp = (((start_pc + codep - start_codep) & 0xffff) + disp) & 0xffff;
1821 append_pc((start_pc & 0xffff0000) | disp);
1823 break;
1824 default:
1825 oappend ("<internal disassembelr error>");
1826 return;
1829 oappend (scratchbuf);
1832 static void
1833 append_pc(unsigned long pc)
1835 sprintf(scratchbuf, "%04lx:%04lx", pc >> 16, pc & 0xffff);
1838 static void
1839 OP_SEG(int dummy __unused)
1841 static const char *sreg[] = {
1842 "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
1845 oappend (sreg[reg]);
1848 static void
1849 OP_DIR(int size)
1851 int seg, offset;
1853 switch (size)
1855 case lptr:
1856 if (dflag)
1858 offset = get32 ();
1859 seg = get16 ();
1861 else
1863 offset = get16 ();
1864 seg = get16 ();
1866 sprintf (scratchbuf, "%04x:%04x", seg, offset);
1867 oappend (scratchbuf);
1868 break;
1869 case v_mode:
1870 if (aflag)
1871 offset = get32 ();
1872 else
1873 offset = (short)get16 ();
1875 append_pc(start_pc + codep - start_codep + offset);
1876 oappend (scratchbuf);
1877 break;
1878 default:
1879 oappend ("<internal disassembler error>");
1880 break;
1884 static void
1885 OP_OFF(int dummy __unused)
1887 int off;
1889 if (aflag)
1890 off = get32 ();
1891 else
1892 off = get16 ();
1894 sprintf (scratchbuf, "0x%x", off);
1895 oappend (scratchbuf);
1898 static void
1899 OP_ESDI(int dummy __unused)
1901 oappend ("%es:(");
1902 oappend (aflag ? "%edi" : "%di");
1903 oappend (")");
1906 static void
1907 OP_DSSI(int dummy __unused)
1909 oappend ("%ds:(");
1910 oappend (aflag ? "%esi" : "%si");
1911 oappend (")");
1914 static void
1915 OP_C(int dummy __unused)
1917 codep++; /* skip mod/rm */
1918 sprintf (scratchbuf, "%%cr%d", reg);
1919 oappend (scratchbuf);
1922 static void
1923 OP_D(int dummy __unused)
1925 codep++; /* skip mod/rm */
1926 sprintf (scratchbuf, "%%db%d", reg);
1927 oappend (scratchbuf);
1930 static void
1931 OP_T(int dummy __unused)
1933 codep++; /* skip mod/rm */
1934 sprintf (scratchbuf, "%%tr%d", reg);
1935 oappend (scratchbuf);
1938 static void
1939 OP_rm(int bytemode)
1941 switch (bytemode)
1943 case d_mode:
1944 oappend (names32[rm]);
1945 break;
1946 case w_mode:
1947 oappend (names16[rm]);
1948 break;
1952 #else
1954 i386dis (int pc, unsigned char *inbuf, char outbuf, int mode)
1956 strcpy (outbuf, "(no disassembler)");
1957 return (1);
1960 #endif /* DISASSEMBLER */