* Silence -Wold-style-definition (i.e., ansify).
[dragonfly.git] / usr.bin / doscmd / i386-pinsn.c
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.4 2008/10/16 01:52:32 swildner Exp $
4  */
5 #ifdef DISASSEMBLER
6
7 /* Print i386 instructions for GDB, the GNU debugger.
8    Copyright (C) 1988, 1989 Free Software Foundation, Inc.
9
10 This file is part of GDB.
11
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.
16
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.
21
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.  */
25
26 /*
27  * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
28  * July 1988
29  */
30
31 /*
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.
38  */
39
40 #include <stdio.h>
41 #include <ctype.h>
42
43 #include "doscmd.h"
44
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 *);
57
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
80
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
100
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
110
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
117
118 #define b_mode 1
119 #define v_mode 2
120 #define w_mode 3
121 #define d_mode 4
122
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
137
138 #define lptr 115
139
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
148
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
157
158 #define indir_dx_reg 150
159
160 #define NOFUNC NULL, 0
161
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
178
179 #define FLOATCODE 50
180 #define FLOAT NULL, NULL, FLOATCODE, NOFUNC, NOFUNC
181
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;
190 };
191
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 },
481 };
482
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 },  
773 };
774
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;
783
784 static const char *names32[]={
785   "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
786 };
787 static const char *names16[] = {
788   "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
789 };
790 static const char *names8[] = {
791   "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
792 };
793 static const char *names_seg[] = {
794   "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
795 };
796 static const char *names16_pairs[] = {
797   "%bx+%si","%bx+%di","%bp+%si","%bp+%di","%si","%di","%bp","%bx",
798 };
799
800 struct dis386 grps[][8] = {
801   /* GRP1b */
802   {
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 }
811   },
812   /* GRP1S */
813   {
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 }
822   },
823   /* GRP1Ss */
824   {
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 }
833   },
834   /* GRP2b */
835   {
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 },
844   },
845   /* GRP2S */
846   {
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 },
855   },
856   /* GRP2b_one */
857   {
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 },
866   },
867   /* GRP2S_one */
868   {
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 },
877   },
878   /* GRP2b_cl */
879   {
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 },
888   },
889   /* GRP2S_cl */
890   {
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 }
899   },
900   /* GRP3b */
901   {
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 }
910   },
911   /* GRP3S */
912   {
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 },
921   },
922   /* GRP4 */
923   {
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 },
932   },
933   /* GRP5 */
934   {
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 },
943   },
944   /* GRP6 */
945   {
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 }
954   },
955   /* GRP7 */
956   {
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 },
965   },
966   /* GRP8 */
967   {
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 },
976   }
977 };
978
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
991
992 static int prefixes;
993
994 static void
995 ckprefix(void)
996 {
997   prefixes = 0;
998   while (1)
999     {
1000       switch (*codep)
1001         {
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;
1040         }
1041       codep++;
1042     }
1043 }
1044
1045 static int dflag;
1046 static int aflag;               
1047
1048 static char op1out[100], op2out[100], op3out[100];
1049 static unsigned long start_pc;
1050
1051 /*
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.
1063  */
1064 int
1065 i386dis (unsigned short ucs, unsigned short uip, unsigned char *inbuf,
1066          char *outbuf, int mode)
1067 {
1068   struct dis386 *dp;
1069   int i;
1070   int enter_instruction;
1071   char *first, *second, *third;
1072   int needcomma;
1073   
1074   obuf[0] = 0;
1075   op1out[0] = 0;
1076   op2out[0] = 0;
1077   op3out[0] = 0;
1078   
1079   start_pc = ucs << 16 | uip;
1080   start_codep = inbuf;
1081   codep = inbuf;
1082   
1083   ckprefix ();
1084   
1085   if (*codep == 0xc8)
1086     enter_instruction = 1;
1087   else
1088     enter_instruction = 0;
1089   
1090   obufp = obuf;
1091   
1092   if (prefixes & PREFIX_REPZ)
1093     oappend ("repz ");
1094   if (prefixes & PREFIX_REPNZ)
1095     oappend ("repnz ");
1096   if (prefixes & PREFIX_LOCK)
1097     oappend ("lock ");
1098   
1099   if ((prefixes & PREFIX_FWAIT)
1100       && ((*codep < 0xd8) || (*codep > 0xdf)))
1101     {
1102       /* fwait not followed by floating point instruction */
1103       oappend ("fwait");
1104       strcpy (outbuf, obuf);
1105       return (1);
1106     }
1107   
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;
1115   }
1116   
1117   if (prefixes & PREFIX_DATA)
1118     dflag ^= 1;
1119   
1120   if (prefixes & PREFIX_ADR)
1121     {
1122       aflag ^= 1;
1123       oappend ("addr16 ");
1124     }
1125   
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;
1134   
1135   if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1136     {
1137       dofloat ();
1138     }
1139   else
1140     {
1141       if (dp->name == NULL)
1142         dp = &grps[dp->bytemode1][reg];
1143       
1144       putop (dp->name);
1145       
1146       obufp = op1out;
1147       if (dp->op1)
1148         (*dp->op1)(dp->bytemode1);
1149       
1150       obufp = op2out;
1151       if (dp->op2)
1152         (*dp->op2)(dp->bytemode2);
1153       
1154       obufp = op3out;
1155       if (dp->op3)
1156         (*dp->op3)(dp->bytemode3);
1157     }
1158   
1159   obufp = obuf + strlen (obuf);
1160   for (i = strlen (obuf); i < 6; i++)
1161     oappend (" ");
1162   oappend (" ");
1163   
1164   /* enter instruction is printed with operands in the
1165    * same order as the intel book; everything else
1166    * is printed in reverse order 
1167    */
1168   if (enter_instruction)
1169     {
1170       first = op1out;
1171       second = op2out;
1172       third = op3out;
1173     }
1174   else
1175     {
1176       first = op3out;
1177       second = op2out;
1178       third = op1out;
1179     }
1180   needcomma = 0;
1181   if (*first)
1182     {
1183       oappend (first);
1184       needcomma = 1;
1185     }
1186   if (*second)
1187     {
1188       if (needcomma)
1189         oappend (",");
1190       oappend (second);
1191       needcomma = 1;
1192     }
1193   if (*third)
1194     {
1195       if (needcomma)
1196         oappend (",");
1197       oappend (third);
1198     }
1199   strcpy (outbuf, obuf);
1200   return (codep - inbuf);
1201 }
1202
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",
1276 };
1277
1278 #define ST OP_ST, 0
1279 #define STi OP_STi, 0
1280
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
1290
1291 struct dis386 float_reg[][8] = {
1292   /* d8 */
1293   {
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 },
1302   },
1303   /* d9 */
1304   {
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 },
1313   },
1314   /* da */
1315   {
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 },
1324   },
1325   /* db */
1326   {
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 },
1335   },
1336   /* dc */
1337   {
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 },
1346   },
1347   /* dd */
1348   {
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 },
1357   },
1358   /* de */
1359   {
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 },
1368   },
1369   /* df */
1370   {
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 },
1379   },
1380 };
1381
1382
1383 const char *fgrps[][8] = {
1384   /* d9_2  0 */
1385   {
1386     "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1387   },
1388
1389   /* d9_4  1 */
1390   {
1391     "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1392   },
1393
1394   /* d9_5  2 */
1395   {
1396     "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1397   },
1398
1399   /* d9_6  3 */
1400   {
1401     "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1402   },
1403
1404   /* d9_7  4 */
1405   {
1406     "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1407   },
1408
1409   /* da_5  5 */
1410   {
1411     "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1412   },
1413
1414   /* db_4  6 */
1415   {
1416     "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1417     "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1418   },
1419
1420   /* de_3  7 */
1421   {
1422     "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1423   },
1424
1425   /* df_4  8 */
1426   {
1427     "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1428   },
1429 };
1430
1431
1432 static void
1433 dofloat (void)
1434 {
1435   struct dis386 *dp;
1436   unsigned char floatop;
1437   
1438   floatop = codep[-1];
1439   
1440   if (mod != 3)
1441     {
1442       putop (float_mem[(floatop - 0xd8) * 8 + reg]);
1443       obufp = op1out;
1444       OP_E (v_mode);
1445       return;
1446     }
1447   codep++;
1448   
1449   dp = &float_reg[floatop - 0xd8][reg];
1450   if (dp->name == NULL)
1451     {
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");
1456     }
1457   else
1458     {
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);
1466     }
1467 }
1468
1469 static void
1470 OP_ST(int dummy __unused)
1471 {
1472   oappend ("%st");
1473 }
1474
1475 static void
1476 OP_STi(int dummy __unused)
1477 {
1478   sprintf (scratchbuf, "%%st(%d)", rm);
1479   oappend (scratchbuf);
1480 }
1481
1482
1483 /* capital letters in template are macros */
1484 static void
1485 putop(const char *template)
1486 {
1487   const char *p;
1488   
1489   for (p = template; *p; p++)
1490     {
1491       switch (*p)
1492         {
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;
1511         }
1512     }
1513   *obufp = 0;
1514 }
1515
1516 static void
1517 oappend(const char *s)
1518 {
1519   strcpy (obufp, s);
1520   obufp += strlen (s);
1521   *obufp = 0;
1522 }
1523
1524 static void
1525 append_prefix(void)
1526 {
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:");
1539 }
1540
1541 static void
1542 OP_indirE(int bytemode)
1543 {
1544   oappend ("*");
1545   OP_E (bytemode);
1546 }
1547
1548 static void
1549 OP_E(int bytemode)
1550 {
1551   int disp;
1552   int havesib;
1553   int base;
1554   int idx;
1555   int scale;
1556   int havebase;
1557   
1558   /* skip mod/rm byte */
1559   codep++;
1560   
1561   havesib = 0;
1562   havebase = 0;
1563   disp = 0;
1564   
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;
1582       }
1583       return;
1584   }
1585   
1586   append_prefix ();
1587
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++;
1595   }
1596   
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 ();
1606               }
1607               break;
1608           case 5:
1609               disp = get32 ();
1610               break;
1611           default:
1612               havebase = 1;
1613               base = rm;
1614               break;
1615           }
1616       } else {
1617           if (rm == 6) {
1618             havebase = 0;
1619             disp = get16 ();
1620           } else {
1621             havebase = 1;
1622             base = rm;
1623           }
1624       }
1625       break;
1626   case 1:
1627       disp = *(char *)codep++;
1628       if (!aflag || rm != 4) {
1629           havebase = 1;
1630           base = rm;
1631       }
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;
1641       }
1642       break;
1643   }
1644   
1645   if (mod != 0 || ((aflag && rm == 5) || (havesib && base == 5))
1646                || (!aflag && rm == 6)) {
1647     sprintf (scratchbuf, "0x%x", disp);
1648     oappend (scratchbuf);
1649   }
1650   
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);
1659           }
1660           sprintf (scratchbuf, ",%d", 1 << scale);
1661           oappend (scratchbuf);
1662       }
1663       oappend (")");
1664   }
1665 }
1666
1667 static void
1668 OP_G(int bytemode)
1669 {
1670   switch (bytemode) 
1671     {
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;
1690     }
1691 }
1692
1693 static int
1694 get32(void)
1695 {
1696   int x = 0;
1697   
1698   x = *codep++ & 0xff;
1699   x |= (*codep++ & 0xff) << 8;
1700   x |= (*codep++ & 0xff) << 16;
1701   x |= (*codep++ & 0xff) << 24;
1702   return (x);
1703 }
1704
1705 static int
1706 get16(void)
1707 {
1708   int x = 0;
1709   
1710   x = *codep++ & 0xff;
1711   x |= (*codep++ & 0xff) << 8;
1712   return (x);
1713 }
1714
1715 static void
1716 OP_REG(int code)
1717 {
1718   const char *s;
1719   
1720   switch (code) 
1721     {
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;
1745     }
1746   oappend (s);
1747 }
1748
1749 static void
1750 OP_I(int bytemode)
1751 {
1752   int op;
1753   
1754   switch (bytemode) 
1755     {
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;
1771     }
1772   sprintf (scratchbuf, "$0x%x", op);
1773   oappend (scratchbuf);
1774 }
1775
1776 static void
1777 OP_sI(int bytemode)
1778 {
1779   int op;
1780   
1781   switch (bytemode) 
1782     {
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;
1798     }
1799   sprintf (scratchbuf, "$0x%x", op);
1800   oappend (scratchbuf);
1801 }
1802
1803 static void
1804 OP_J(int bytemode)
1805 {
1806   int disp;
1807   
1808   switch (bytemode) 
1809     {
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);
1822       }
1823       break;
1824     default:
1825       oappend ("<internal disassembelr error>");
1826       return;
1827     }
1828   
1829   oappend (scratchbuf);
1830 }
1831
1832 static void
1833 append_pc(unsigned long pc)
1834 {
1835   sprintf(scratchbuf, "%04lx:%04lx", pc >> 16, pc & 0xffff);
1836 }
1837
1838 static void
1839 OP_SEG(int dummy __unused)
1840 {
1841   static const char *sreg[] = {
1842     "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
1843   };
1844
1845   oappend (sreg[reg]);
1846 }
1847
1848 static void
1849 OP_DIR(int size)
1850 {
1851   int seg, offset;
1852   
1853   switch (size) 
1854     {
1855     case lptr:
1856       if (dflag) 
1857         {
1858           offset = get32 ();
1859           seg = get16 ();
1860         } 
1861       else 
1862         {
1863           offset = get16 ();
1864           seg = get16 ();
1865         }
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 ();
1874       
1875       append_pc(start_pc + codep - start_codep + offset);
1876       oappend (scratchbuf);
1877       break;
1878     default:
1879       oappend ("<internal disassembler error>");
1880       break;
1881     }
1882 }
1883
1884 static void
1885 OP_OFF(int dummy __unused)
1886 {
1887   int off;
1888   
1889   if (aflag)
1890     off = get32 ();
1891   else
1892     off = get16 ();
1893   
1894   sprintf (scratchbuf, "0x%x", off);
1895   oappend (scratchbuf);
1896 }
1897
1898 static void
1899 OP_ESDI(int dummy __unused)
1900 {
1901   oappend ("%es:(");
1902   oappend (aflag ? "%edi" : "%di");
1903   oappend (")");
1904 }
1905
1906 static void
1907 OP_DSSI(int dummy __unused)
1908 {
1909   oappend ("%ds:(");
1910   oappend (aflag ? "%esi" : "%si");
1911   oappend (")");
1912 }
1913
1914 static void
1915 OP_C(int dummy __unused)
1916 {
1917   codep++; /* skip mod/rm */
1918   sprintf (scratchbuf, "%%cr%d", reg);
1919   oappend (scratchbuf);
1920 }
1921
1922 static void
1923 OP_D(int dummy __unused)
1924 {
1925   codep++; /* skip mod/rm */
1926   sprintf (scratchbuf, "%%db%d", reg);
1927   oappend (scratchbuf);
1928 }
1929
1930 static void
1931 OP_T(int dummy __unused)
1932 {
1933   codep++; /* skip mod/rm */
1934   sprintf (scratchbuf, "%%tr%d", reg);
1935   oappend (scratchbuf);
1936 }
1937
1938 static void
1939 OP_rm(int bytemode)
1940 {
1941   switch (bytemode) 
1942     {
1943     case d_mode:
1944       oappend (names32[rm]);
1945       break;
1946     case w_mode:
1947       oappend (names16[rm]);
1948       break;
1949     }
1950 }
1951
1952 #else
1953
1954 i386dis (int pc, unsigned char *inbuf, char outbuf, int mode)
1955 {
1956         strcpy (outbuf, "(no disassembler)");
1957         return (1);
1958 }
1959
1960 #endif /* DISASSEMBLER */