1/*-
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19 *  School of Computer Science
20 *  Carnegie Mellon University
21 *  Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26
27#include <sys/cdefs.h>
28/*
29 * Instruction disassembler.
30 */
31#include <sys/param.h>
32#include <sys/libkern.h>
33
34#include <ddb/ddb.h>
35#include <ddb/db_access.h>
36#include <ddb/db_sym.h>
37
38/*
39 * Size attributes
40 */
41#define	BYTE	0
42#define	WORD	1
43#define	LONG	2
44#define	QUAD	3
45#define	SNGL	4
46#define	DBLR	5
47#define	EXTR	6
48#define	SDEP	7
49#define	ADEP	8
50#define	ESC	9
51#define	NONE	10
52
53/*
54 * REX prefix and bits
55 */
56#define REX_B	1
57#define REX_X	2
58#define REX_R	4
59#define REX_W	8
60#define REX	0x40
61
62/*
63 * Addressing modes
64 */
65#define	E	1			/* general effective address */
66#define	Eind	2			/* indirect address (jump, call) */
67#define	Ew	3			/* address, word size */
68#define	Eb	4			/* address, byte size */
69#define	R	5			/* register, in 'reg' field */
70#define	Rw	6			/* word register, in 'reg' field */
71#define	Rq	39			/* quad register, in 'reg' field */
72#define	Rv	40			/* register in 'r/m' field */
73#define	Ri	7			/* register in instruction */
74#define	S	8			/* segment reg, in 'reg' field */
75#define	Si	9			/* segment reg, in instruction */
76#define	A	10			/* accumulator */
77#define	BX	11			/* (bx) */
78#define	CL	12			/* cl, for shifts */
79#define	DX	13			/* dx, for IO */
80#define	SI	14			/* si */
81#define	DI	15			/* di */
82#define	CR	16			/* control register */
83#define	DR	17			/* debug register */
84#define	TR	18			/* test register */
85#define	I	19			/* immediate, unsigned */
86#define	Is	20			/* immediate, signed */
87#define	Ib	21			/* byte immediate, unsigned */
88#define	Ibs	22			/* byte immediate, signed */
89#define	Iw	23			/* word immediate, unsigned */
90#define	Ilq	24			/* long/quad immediate, unsigned */
91#define	O	25			/* direct address */
92#define	Db	26			/* byte displacement from EIP */
93#define	Dl	27			/* long displacement from EIP */
94#define	o1	28			/* constant 1 */
95#define	o3	29			/* constant 3 */
96#define	OS	30			/* immediate offset/segment */
97#define	ST	31			/* FP stack top */
98#define	STI	32			/* FP stack */
99#define	X	33			/* extended FP op */
100#define	XA	34			/* for 'fstcw %ax' */
101#define	El	35			/* address, long/quad size */
102#define	Ril	36			/* long register in instruction */
103#define	Iba	37			/* byte immediate, don't print if 0xa */
104#define	EL	38			/* address, explicitly long size */
105
106struct inst {
107	const char *	i_name;		/* name */
108	bool	i_has_modrm;		/* has regmodrm byte */
109	short	i_size;			/* operand size */
110	int	i_mode;			/* addressing modes */
111	const void *	i_extra;	/* pointer to extra opcode table */
112};
113
114#define	op1(x)		(x)
115#define	op2(x,y)	((x)|((y)<<8))
116#define	op3(x,y,z)	((x)|((y)<<8)|((z)<<16))
117
118struct finst {
119	const char *	f_name;		/* name for memory instruction */
120	int	f_size;			/* size for memory instruction */
121	int	f_rrmode;		/* mode for rr instruction */
122	const void *	f_rrname;	/* name for rr instruction
123					   (or pointer to table) */
124};
125
126static const struct inst db_inst_0f388x[] = {
127/*80*/	{ "",	   true,  SDEP,  op2(E, Rq),  "invept" },
128/*81*/	{ "",	   true,  SDEP,  op2(E, Rq),  "invvpid" },
129/*82*/	{ "",	   true,  SDEP,  op2(E, Rq),  "invpcid" },
130/*83*/	{ "",	   false, NONE,  0,	      0 },
131/*84*/	{ "",	   false, NONE,  0,	      0 },
132/*85*/	{ "",	   false, NONE,  0,	      0 },
133/*86*/	{ "",	   false, NONE,  0,	      0 },
134/*87*/	{ "",	   false, NONE,  0,	      0 },
135
136/*88*/	{ "",	   false, NONE,  0,	      0 },
137/*89*/	{ "",	   false, NONE,  0,	      0 },
138/*8a*/	{ "",	   false, NONE,  0,	      0 },
139/*8b*/	{ "",	   false, NONE,  0,	      0 },
140/*8c*/	{ "",	   false, NONE,  0,	      0 },
141/*8d*/	{ "",	   false, NONE,  0,	      0 },
142/*8e*/	{ "",	   false, NONE,  0,	      0 },
143/*8f*/	{ "",	   false, NONE,  0,	      0 },
144};
145
146static const struct inst db_inst_0f38fx[] = {
147/*f0*/	{ "crc32b",true,  NONE,  op2(Eb, R),  0 },
148/*f1*/	{ "crc32", true,  LONG,  op2(E, R),   0 },
149/*f2*/	{ "",	   false, NONE,  0,	      0 },
150/*f3*/	{ "",	   false, NONE,  0,	      0 },
151/*f4*/	{ "",	   false, NONE,  0,	      0 },
152/*f5*/	{ "",	   false, NONE,  0,	      0 },
153/*f6*/	{ "",	   false, NONE,  0,	      0 },
154/*f7*/	{ "",	   false, NONE,  0,	      0 },
155
156/*f8*/	{ "",	   false, NONE,  0,	      0 },
157/*f9*/	{ "",	   false, NONE,  0,	      0 },
158/*fa*/	{ "",	   false, NONE,  0,	      0 },
159/*fb*/	{ "",	   false, NONE,  0,	      0 },
160/*fc*/	{ "",	   false, NONE,  0,	      0 },
161/*fd*/	{ "",	   false, NONE,  0,	      0 },
162/*fe*/	{ "",	   false, NONE,  0,	      0 },
163/*ff*/	{ "",	   false, NONE,  0,	      0 },
164};
165
166static const struct inst * const db_inst_0f38[] = {
167	0,
168	0,
169	0,
170	0,
171	0,
172	0,
173	0,
174	0,
175	db_inst_0f388x,
176	0,
177	0,
178	0,
179	0,
180	0,
181	0,
182	db_inst_0f38fx
183};
184
185static const char * const db_Grp6[] = {
186	"sldt",
187	"str",
188	"lldt",
189	"ltr",
190	"verr",
191	"verw",
192	"",
193	""
194};
195
196static const char * const db_Grp7[] = {
197	"sgdt",
198	"sidt",
199	"lgdt",
200	"lidt",
201	"smsw",
202	"",
203	"lmsw",
204	"invlpg"
205};
206
207static const char * const db_Grp8[] = {
208	"",
209	"",
210	"",
211	"",
212	"bt",
213	"bts",
214	"btr",
215	"btc"
216};
217
218static const char * const db_Grp9[] = {
219	"",
220	"cmpxchg8b",
221	"",
222	"",
223	"",
224	"",
225	"vmptrld",
226	"vmptrst"
227};
228
229static const char * const db_Grp15[] = {
230	"fxsave",
231	"fxrstor",
232	"ldmxcsr",
233	"stmxcsr",
234	"xsave",
235	"xrstor",
236	"xsaveopt",
237	"clflush"
238};
239
240static const char * const db_Grp15b[] = {
241	"",
242	"",
243	"",
244	"",
245	"",
246	"lfence",
247	"mfence",
248	"sfence"
249};
250
251static const struct inst db_inst_0f0x[] = {
252/*00*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp6 },
253/*01*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp7 },
254/*02*/	{ "lar",   true,  LONG,  op2(E,R),    0 },
255/*03*/	{ "lsl",   true,  LONG,  op2(E,R),    0 },
256/*04*/	{ "",      false, NONE,  0,	      0 },
257/*05*/	{ "syscall",false,NONE,  0,	      0 },
258/*06*/	{ "clts",  false, NONE,  0,	      0 },
259/*07*/	{ "sysret",false, NONE,  0,	      0 },
260
261/*08*/	{ "invd",  false, NONE,  0,	      0 },
262/*09*/	{ "wbinvd",false, NONE,  0,	      0 },
263/*0a*/	{ "",      false, NONE,  0,	      0 },
264/*0b*/	{ "",      false, NONE,  0,	      0 },
265/*0c*/	{ "",      false, NONE,  0,	      0 },
266/*0d*/	{ "",      false, NONE,  0,	      0 },
267/*0e*/	{ "",      false, NONE,  0,	      0 },
268/*0f*/	{ "",      false, NONE,  0,	      0 },
269};
270
271static const struct inst db_inst_0f1x[] = {
272/*10*/	{ "",      false, NONE,  0,	      0 },
273/*11*/	{ "",      false, NONE,  0,	      0 },
274/*12*/	{ "",      false, NONE,  0,	      0 },
275/*13*/	{ "",      false, NONE,  0,	      0 },
276/*14*/	{ "",      false, NONE,  0,	      0 },
277/*15*/	{ "",      false, NONE,  0,	      0 },
278/*16*/	{ "",      false, NONE,  0,	      0 },
279/*17*/	{ "",      false, NONE,  0,	      0 },
280
281/*18*/	{ "",      false, NONE,  0,	      0 },
282/*19*/	{ "",      false, NONE,  0,	      0 },
283/*1a*/	{ "",      false, NONE,  0,	      0 },
284/*1b*/	{ "",      false, NONE,  0,	      0 },
285/*1c*/	{ "",      false, NONE,  0,	      0 },
286/*1d*/	{ "",      false, NONE,  0,	      0 },
287/*1e*/	{ "",      false, NONE,  0,	      0 },
288/*1f*/	{ "nopl",  true,  SDEP,  0,	      "nopw" },
289};
290
291static const struct inst db_inst_0f2x[] = {
292/*20*/	{ "mov",   true,  LONG,  op2(CR,El),  0 },
293/*21*/	{ "mov",   true,  LONG,  op2(DR,El),  0 },
294/*22*/	{ "mov",   true,  LONG,  op2(El,CR),  0 },
295/*23*/	{ "mov",   true,  LONG,  op2(El,DR),  0 },
296/*24*/	{ "mov",   true,  LONG,  op2(TR,El),  0 },
297/*25*/	{ "",      false, NONE,  0,	      0 },
298/*26*/	{ "mov",   true,  LONG,  op2(El,TR),  0 },
299/*27*/	{ "",      false, NONE,  0,	      0 },
300
301/*28*/	{ "",      false, NONE,  0,	      0 },
302/*29*/	{ "",      false, NONE,  0,	      0 },
303/*2a*/	{ "",      false, NONE,  0,	      0 },
304/*2b*/	{ "",      false, NONE,  0,	      0 },
305/*2c*/	{ "",      false, NONE,  0,	      0 },
306/*2d*/	{ "",      false, NONE,  0,	      0 },
307/*2e*/	{ "",      false, NONE,  0,	      0 },
308/*2f*/	{ "",      false, NONE,  0,	      0 },
309};
310
311static const struct inst db_inst_0f3x[] = {
312/*30*/	{ "wrmsr", false, NONE,  0,	      0 },
313/*31*/	{ "rdtsc", false, NONE,  0,	      0 },
314/*32*/	{ "rdmsr", false, NONE,  0,	      0 },
315/*33*/	{ "rdpmc", false, NONE,  0,	      0 },
316/*34*/	{ "sysenter",false,NONE,  0,	      0 },
317/*35*/	{ "sysexit",false,NONE,  0,	      0 },
318/*36*/	{ "",	   false, NONE,  0,	      0 },
319/*37*/	{ "getsec",false, NONE,  0,	      0 },
320
321/*38*/	{ "",	   false, ESC,  0,	      db_inst_0f38 },
322/*39*/	{ "",	   false, NONE,  0,	      0 },
323/*3a*/	{ "",	   false, NONE,  0,	      0 },
324/*3b*/	{ "",	   false, NONE,  0,	      0 },
325/*3c*/	{ "",	   false, NONE,  0,	      0 },
326/*3d*/	{ "",	   false, NONE,  0,	      0 },
327/*3e*/	{ "",	   false, NONE,  0,	      0 },
328/*3f*/	{ "",	   false, NONE,  0,	      0 },
329};
330
331static const struct inst db_inst_0f4x[] = {
332/*40*/	{ "cmovo",  true, NONE,  op2(E, R),   0 },
333/*41*/	{ "cmovno", true, NONE,  op2(E, R),   0 },
334/*42*/	{ "cmovb",  true, NONE,  op2(E, R),   0 },
335/*43*/	{ "cmovnb", true, NONE,  op2(E, R),   0 },
336/*44*/	{ "cmovz",  true, NONE,  op2(E, R),   0 },
337/*45*/	{ "cmovnz", true, NONE,  op2(E, R),   0 },
338/*46*/	{ "cmovbe", true, NONE,  op2(E, R),   0 },
339/*47*/	{ "cmovnbe",true, NONE,  op2(E, R),   0 },
340
341/*48*/	{ "cmovs",  true, NONE,  op2(E, R),   0 },
342/*49*/	{ "cmovns", true, NONE,  op2(E, R),   0 },
343/*4a*/	{ "cmovp",  true, NONE,  op2(E, R),   0 },
344/*4b*/	{ "cmovnp", true, NONE,  op2(E, R),   0 },
345/*4c*/	{ "cmovl",  true, NONE,  op2(E, R),   0 },
346/*4d*/	{ "cmovnl", true, NONE,  op2(E, R),   0 },
347/*4e*/	{ "cmovle", true, NONE,  op2(E, R),   0 },
348/*4f*/	{ "cmovnle",true, NONE,  op2(E, R),   0 },
349};
350
351static const struct inst db_inst_0f7x[] = {
352/*70*/	{ "",	   false, NONE,  0,	      0 },
353/*71*/	{ "",	   false, NONE,  0,	      0 },
354/*72*/	{ "",	   false, NONE,  0,	      0 },
355/*73*/	{ "",	   false, NONE,  0,	      0 },
356/*74*/	{ "",	   false, NONE,  0,	      0 },
357/*75*/	{ "",	   false, NONE,  0,	      0 },
358/*76*/	{ "",	   false, NONE,  0,	      0 },
359/*77*/	{ "",	   false, NONE,  0,	      0 },
360
361/*78*/	{ "vmread", true, NONE,  op2(Rq, E),  0 },
362/*79*/	{ "vmwrite",true, NONE,  op2(E, Rq),  0 },
363/*7a*/	{ "",	   false, NONE,  0,	      0 },
364/*7b*/	{ "",	   false, NONE,  0,	      0 },
365/*7c*/	{ "",	   false, NONE,  0,	      0 },
366/*7d*/	{ "",	   false, NONE,  0,	      0 },
367/*7e*/	{ "",	   false, NONE,  0,	      0 },
368/*7f*/	{ "",	   false, NONE,  0,	      0 },
369};
370
371static const struct inst db_inst_0f8x[] = {
372/*80*/	{ "jo",    false, NONE,  op1(Dl),     0 },
373/*81*/	{ "jno",   false, NONE,  op1(Dl),     0 },
374/*82*/	{ "jb",    false, NONE,  op1(Dl),     0 },
375/*83*/	{ "jnb",   false, NONE,  op1(Dl),     0 },
376/*84*/	{ "jz",    false, NONE,  op1(Dl),     0 },
377/*85*/	{ "jnz",   false, NONE,  op1(Dl),     0 },
378/*86*/	{ "jbe",   false, NONE,  op1(Dl),     0 },
379/*87*/	{ "jnbe",  false, NONE,  op1(Dl),     0 },
380
381/*88*/	{ "js",    false, NONE,  op1(Dl),     0 },
382/*89*/	{ "jns",   false, NONE,  op1(Dl),     0 },
383/*8a*/	{ "jp",    false, NONE,  op1(Dl),     0 },
384/*8b*/	{ "jnp",   false, NONE,  op1(Dl),     0 },
385/*8c*/	{ "jl",    false, NONE,  op1(Dl),     0 },
386/*8d*/	{ "jnl",   false, NONE,  op1(Dl),     0 },
387/*8e*/	{ "jle",   false, NONE,  op1(Dl),     0 },
388/*8f*/	{ "jnle",  false, NONE,  op1(Dl),     0 },
389};
390
391static const struct inst db_inst_0f9x[] = {
392/*90*/	{ "seto",  true,  NONE,  op1(Eb),     0 },
393/*91*/	{ "setno", true,  NONE,  op1(Eb),     0 },
394/*92*/	{ "setb",  true,  NONE,  op1(Eb),     0 },
395/*93*/	{ "setnb", true,  NONE,  op1(Eb),     0 },
396/*94*/	{ "setz",  true,  NONE,  op1(Eb),     0 },
397/*95*/	{ "setnz", true,  NONE,  op1(Eb),     0 },
398/*96*/	{ "setbe", true,  NONE,  op1(Eb),     0 },
399/*97*/	{ "setnbe",true,  NONE,  op1(Eb),     0 },
400
401/*98*/	{ "sets",  true,  NONE,  op1(Eb),     0 },
402/*99*/	{ "setns", true,  NONE,  op1(Eb),     0 },
403/*9a*/	{ "setp",  true,  NONE,  op1(Eb),     0 },
404/*9b*/	{ "setnp", true,  NONE,  op1(Eb),     0 },
405/*9c*/	{ "setl",  true,  NONE,  op1(Eb),     0 },
406/*9d*/	{ "setnl", true,  NONE,  op1(Eb),     0 },
407/*9e*/	{ "setle", true,  NONE,  op1(Eb),     0 },
408/*9f*/	{ "setnle",true,  NONE,  op1(Eb),     0 },
409};
410
411static const struct inst db_inst_0fax[] = {
412/*a0*/	{ "push",  false, NONE,  op1(Si),     0 },
413/*a1*/	{ "pop",   false, NONE,  op1(Si),     0 },
414/*a2*/	{ "cpuid", false, NONE,  0,	      0 },
415/*a3*/	{ "bt",    true,  LONG,  op2(R,E),    0 },
416/*a4*/	{ "shld",  true,  LONG,  op3(Ib,R,E), 0 },
417/*a5*/	{ "shld",  true,  LONG,  op3(CL,R,E), 0 },
418/*a6*/	{ "",      false, NONE,  0,	      0 },
419/*a7*/	{ "",      false, NONE,  0,	      0 },
420
421/*a8*/	{ "push",  false, NONE,  op1(Si),     0 },
422/*a9*/	{ "pop",   false, NONE,  op1(Si),     0 },
423/*aa*/	{ "rsm",   false, NONE,  0,	      0 },
424/*ab*/	{ "bts",   true,  LONG,  op2(R,E),    0 },
425/*ac*/	{ "shrd",  true,  LONG,  op3(Ib,R,E), 0 },
426/*ad*/	{ "shrd",  true,  LONG,  op3(CL,R,E), 0 },
427/*ae*/	{ "",      true,  LONG,  op1(E),      db_Grp15 },
428/*af*/	{ "imul",  true,  LONG,  op2(E,R),    0 },
429};
430
431static const struct inst db_inst_0fbx[] = {
432/*b0*/	{ "cmpxchg",true, BYTE,	 op2(R, E),   0 },
433/*b0*/	{ "cmpxchg",true, LONG,	 op2(R, E),   0 },
434/*b2*/	{ "lss",   true,  LONG,  op2(E, R),   0 },
435/*b3*/	{ "btr",   true,  LONG,  op2(R, E),   0 },
436/*b4*/	{ "lfs",   true,  LONG,  op2(E, R),   0 },
437/*b5*/	{ "lgs",   true,  LONG,  op2(E, R),   0 },
438/*b6*/	{ "movzb", true,  LONG,  op2(Eb, R),  0 },
439/*b7*/	{ "movzw", true,  LONG,  op2(Ew, R),  0 },
440
441/*b8*/	{ "",      false, NONE,  0,	      0 },
442/*b9*/	{ "",      false, NONE,  0,	      0 },
443/*ba*/	{ "",      true,  LONG,  op2(Ib, E),  db_Grp8 },
444/*bb*/	{ "btc",   true,  LONG,  op2(R, E),   0 },
445/*bc*/	{ "bsf",   true,  LONG,  op2(E, R),   0 },
446/*bd*/	{ "bsr",   true,  LONG,  op2(E, R),   0 },
447/*be*/	{ "movsb", true,  LONG,  op2(Eb, R),  0 },
448/*bf*/	{ "movsw", true,  LONG,  op2(Ew, R),  0 },
449};
450
451static const struct inst db_inst_0fcx[] = {
452/*c0*/	{ "xadd",  true,  BYTE,	 op2(R, E),   0 },
453/*c1*/	{ "xadd",  true,  LONG,	 op2(R, E),   0 },
454/*c2*/	{ "",	   false, NONE,	 0,	      0 },
455/*c3*/	{ "",	   false, NONE,	 0,	      0 },
456/*c4*/	{ "",	   false, NONE,	 0,	      0 },
457/*c5*/	{ "",	   false, NONE,	 0,	      0 },
458/*c6*/	{ "",	   false, NONE,	 0,	      0 },
459/*c7*/	{ "",	   true,  NONE,  op1(E),      db_Grp9 },
460/*c8*/	{ "bswap", false, LONG,  op1(Ril),    0 },
461/*c9*/	{ "bswap", false, LONG,  op1(Ril),    0 },
462/*ca*/	{ "bswap", false, LONG,  op1(Ril),    0 },
463/*cb*/	{ "bswap", false, LONG,  op1(Ril),    0 },
464/*cc*/	{ "bswap", false, LONG,  op1(Ril),    0 },
465/*cd*/	{ "bswap", false, LONG,  op1(Ril),    0 },
466/*ce*/	{ "bswap", false, LONG,  op1(Ril),    0 },
467/*cf*/	{ "bswap", false, LONG,  op1(Ril),    0 },
468};
469
470static const struct inst * const db_inst_0f[] = {
471	db_inst_0f0x,
472	db_inst_0f1x,
473	db_inst_0f2x,
474	db_inst_0f3x,
475	db_inst_0f4x,
476	0,
477	0,
478	db_inst_0f7x,
479	db_inst_0f8x,
480	db_inst_0f9x,
481	db_inst_0fax,
482	db_inst_0fbx,
483	db_inst_0fcx,
484	0,
485	0,
486	0
487};
488
489static const char * const db_Esc92[] = {
490	"fnop",	"",	"",	"",	"",	"",	"",	""
491};
492static const char * const db_Esc94[] = {
493	"fchs",	"fabs",	"",	"",	"ftst",	"fxam",	"",	""
494};
495static const char * const db_Esc95[] = {
496	"fld1",	"fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz",""
497};
498static const char * const db_Esc96[] = {
499	"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp",
500	"fincstp"
501};
502static const char * const db_Esc97[] = {
503	"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"
504};
505
506static const char * const db_Esca5[] = {
507	"",	"fucompp","",	"",	"",	"",	"",	""
508};
509
510static const char * const db_Escb4[] = {
511	"fneni","fndisi",	"fnclex","fninit","fsetpm",	"",	"",	""
512};
513
514static const char * const db_Esce3[] = {
515	"",	"fcompp","",	"",	"",	"",	"",	""
516};
517
518static const char * const db_Escf4[] = {
519	"fnstsw","",	"",	"",	"",	"",	"",	""
520};
521
522static const struct finst db_Esc8[] = {
523/*0*/	{ "fadd",   SNGL,  op2(STI,ST),	0 },
524/*1*/	{ "fmul",   SNGL,  op2(STI,ST),	0 },
525/*2*/	{ "fcom",   SNGL,  op2(STI,ST),	0 },
526/*3*/	{ "fcomp",  SNGL,  op2(STI,ST),	0 },
527/*4*/	{ "fsub",   SNGL,  op2(STI,ST),	0 },
528/*5*/	{ "fsubr",  SNGL,  op2(STI,ST),	0 },
529/*6*/	{ "fdiv",   SNGL,  op2(STI,ST),	0 },
530/*7*/	{ "fdivr",  SNGL,  op2(STI,ST),	0 },
531};
532
533static const struct finst db_Esc9[] = {
534/*0*/	{ "fld",    SNGL,  op1(STI),	0 },
535/*1*/	{ "",       NONE,  op1(STI),	"fxch" },
536/*2*/	{ "fst",    SNGL,  op1(X),	db_Esc92 },
537/*3*/	{ "fstp",   SNGL,  0,		0 },
538/*4*/	{ "fldenv", NONE,  op1(X),	db_Esc94 },
539/*5*/	{ "fldcw",  NONE,  op1(X),	db_Esc95 },
540/*6*/	{ "fnstenv",NONE,  op1(X),	db_Esc96 },
541/*7*/	{ "fnstcw", NONE,  op1(X),	db_Esc97 },
542};
543
544static const struct finst db_Esca[] = {
545/*0*/	{ "fiadd",  LONG,  0,		0 },
546/*1*/	{ "fimul",  LONG,  0,		0 },
547/*2*/	{ "ficom",  LONG,  0,		0 },
548/*3*/	{ "ficomp", LONG,  0,		0 },
549/*4*/	{ "fisub",  LONG,  0,		0 },
550/*5*/	{ "fisubr", LONG,  op1(X),	db_Esca5 },
551/*6*/	{ "fidiv",  LONG,  0,		0 },
552/*7*/	{ "fidivr", LONG,  0,		0 }
553};
554
555static const struct finst db_Escb[] = {
556/*0*/	{ "fild",   LONG,  0,		0 },
557/*1*/	{ "",       NONE,  0,		0 },
558/*2*/	{ "fist",   LONG,  0,		0 },
559/*3*/	{ "fistp",  LONG,  0,		0 },
560/*4*/	{ "",       WORD,  op1(X),	db_Escb4 },
561/*5*/	{ "fld",    EXTR,  0,		0 },
562/*6*/	{ "",       WORD,  0,		0 },
563/*7*/	{ "fstp",   EXTR,  0,		0 },
564};
565
566static const struct finst db_Escc[] = {
567/*0*/	{ "fadd",   DBLR,  op2(ST,STI),	0 },
568/*1*/	{ "fmul",   DBLR,  op2(ST,STI),	0 },
569/*2*/	{ "fcom",   DBLR,  0,		0 },
570/*3*/	{ "fcomp",  DBLR,  0,		0 },
571/*4*/	{ "fsub",   DBLR,  op2(ST,STI),	"fsubr" },
572/*5*/	{ "fsubr",  DBLR,  op2(ST,STI),	"fsub" },
573/*6*/	{ "fdiv",   DBLR,  op2(ST,STI),	"fdivr" },
574/*7*/	{ "fdivr",  DBLR,  op2(ST,STI),	"fdiv" },
575};
576
577static const struct finst db_Escd[] = {
578/*0*/	{ "fld",    DBLR,  op1(STI),	"ffree" },
579/*1*/	{ "",       NONE,  0,		0 },
580/*2*/	{ "fst",    DBLR,  op1(STI),	0 },
581/*3*/	{ "fstp",   DBLR,  op1(STI),	0 },
582/*4*/	{ "frstor", NONE,  op1(STI),	"fucom" },
583/*5*/	{ "",       NONE,  op1(STI),	"fucomp" },
584/*6*/	{ "fnsave", NONE,  0,		0 },
585/*7*/	{ "fnstsw", NONE,  0,		0 },
586};
587
588static const struct finst db_Esce[] = {
589/*0*/	{ "fiadd",  WORD,  op2(ST,STI),	"faddp" },
590/*1*/	{ "fimul",  WORD,  op2(ST,STI),	"fmulp" },
591/*2*/	{ "ficom",  WORD,  0,		0 },
592/*3*/	{ "ficomp", WORD,  op1(X),	db_Esce3 },
593/*4*/	{ "fisub",  WORD,  op2(ST,STI),	"fsubrp" },
594/*5*/	{ "fisubr", WORD,  op2(ST,STI),	"fsubp" },
595/*6*/	{ "fidiv",  WORD,  op2(ST,STI),	"fdivrp" },
596/*7*/	{ "fidivr", WORD,  op2(ST,STI),	"fdivp" },
597};
598
599static const struct finst db_Escf[] = {
600/*0*/	{ "fild",   WORD,  0,		0 },
601/*1*/	{ "",       NONE,  0,		0 },
602/*2*/	{ "fist",   WORD,  0,		0 },
603/*3*/	{ "fistp",  WORD,  0,		0 },
604/*4*/	{ "fbld",   NONE,  op1(XA),	db_Escf4 },
605/*5*/	{ "fild",   QUAD,  0,		0 },
606/*6*/	{ "fbstp",  NONE,  0,		0 },
607/*7*/	{ "fistp",  QUAD,  0,		0 },
608};
609
610static const struct finst * const db_Esc_inst[] = {
611	db_Esc8, db_Esc9, db_Esca, db_Escb,
612	db_Escc, db_Escd, db_Esce, db_Escf
613};
614
615static const char * const db_Grp1[] = {
616	"add",
617	"or",
618	"adc",
619	"sbb",
620	"and",
621	"sub",
622	"xor",
623	"cmp"
624};
625
626static const char * const db_Grp2[] = {
627	"rol",
628	"ror",
629	"rcl",
630	"rcr",
631	"shl",
632	"shr",
633	"shl",
634	"sar"
635};
636
637static const struct inst db_Grp3[] = {
638	{ "test",  true, NONE, op2(I,E), 0 },
639	{ "test",  true, NONE, op2(I,E), 0 },
640	{ "not",   true, NONE, op1(E),   0 },
641	{ "neg",   true, NONE, op1(E),   0 },
642	{ "mul",   true, NONE, op2(E,A), 0 },
643	{ "imul",  true, NONE, op2(E,A), 0 },
644	{ "div",   true, NONE, op2(E,A), 0 },
645	{ "idiv",  true, NONE, op2(E,A), 0 },
646};
647
648static const struct inst db_Grp4[] = {
649	{ "inc",   true, BYTE, op1(E),   0 },
650	{ "dec",   true, BYTE, op1(E),   0 },
651	{ "",      true, NONE, 0,	 0 },
652	{ "",      true, NONE, 0,	 0 },
653	{ "",      true, NONE, 0,	 0 },
654	{ "",      true, NONE, 0,	 0 },
655	{ "",      true, NONE, 0,	 0 },
656	{ "",      true, NONE, 0,	 0 }
657};
658
659static const struct inst db_Grp5[] = {
660	{ "inc",   true, LONG, op1(E),   0 },
661	{ "dec",   true, LONG, op1(E),   0 },
662	{ "call",  true, LONG, op1(Eind),0 },
663	{ "lcall", true, LONG, op1(Eind),0 },
664	{ "jmp",   true, LONG, op1(Eind),0 },
665	{ "ljmp",  true, LONG, op1(Eind),0 },
666	{ "push",  true, LONG, op1(E),   0 },
667	{ "",      true, NONE, 0,	 0 }
668};
669
670static const struct inst db_Grp9b[] = {
671	{ "",      true, NONE, 0,	 0 },
672	{ "",      true, NONE, 0,	 0 },
673	{ "",      true, NONE, 0,	 0 },
674	{ "",      true, NONE, 0,	 0 },
675	{ "",      true, NONE, 0,	 0 },
676	{ "",      true, NONE, 0,	 0 },
677	{ "rdrand",true, LONG, op1(Rv),  0 },
678	{ "rdseed",true, LONG, op1(Rv),  0 }
679};
680
681static const struct inst db_inst_table[256] = {
682/*00*/	{ "add",   true,  BYTE,  op2(R, E),  0 },
683/*01*/	{ "add",   true,  LONG,  op2(R, E),  0 },
684/*02*/	{ "add",   true,  BYTE,  op2(E, R),  0 },
685/*03*/	{ "add",   true,  LONG,  op2(E, R),  0 },
686/*04*/	{ "add",   false, BYTE,  op2(I, A),  0 },
687/*05*/	{ "add",   false, LONG,  op2(Is, A), 0 },
688/*06*/	{ "push",  false, NONE,  op1(Si),    0 },
689/*07*/	{ "pop",   false, NONE,  op1(Si),    0 },
690
691/*08*/	{ "or",    true,  BYTE,  op2(R, E),  0 },
692/*09*/	{ "or",    true,  LONG,  op2(R, E),  0 },
693/*0a*/	{ "or",    true,  BYTE,  op2(E, R),  0 },
694/*0b*/	{ "or",    true,  LONG,  op2(E, R),  0 },
695/*0c*/	{ "or",    false, BYTE,  op2(I, A),  0 },
696/*0d*/	{ "or",    false, LONG,  op2(I, A),  0 },
697/*0e*/	{ "push",  false, NONE,  op1(Si),    0 },
698/*0f*/	{ "",      false, ESC,   0,	     db_inst_0f },
699
700/*10*/	{ "adc",   true,  BYTE,  op2(R, E),  0 },
701/*11*/	{ "adc",   true,  LONG,  op2(R, E),  0 },
702/*12*/	{ "adc",   true,  BYTE,  op2(E, R),  0 },
703/*13*/	{ "adc",   true,  LONG,  op2(E, R),  0 },
704/*14*/	{ "adc",   false, BYTE,  op2(I, A),  0 },
705/*15*/	{ "adc",   false, LONG,  op2(Is, A), 0 },
706/*16*/	{ "push",  false, NONE,  op1(Si),    0 },
707/*17*/	{ "pop",   false, NONE,  op1(Si),    0 },
708
709/*18*/	{ "sbb",   true,  BYTE,  op2(R, E),  0 },
710/*19*/	{ "sbb",   true,  LONG,  op2(R, E),  0 },
711/*1a*/	{ "sbb",   true,  BYTE,  op2(E, R),  0 },
712/*1b*/	{ "sbb",   true,  LONG,  op2(E, R),  0 },
713/*1c*/	{ "sbb",   false, BYTE,  op2(I, A),  0 },
714/*1d*/	{ "sbb",   false, LONG,  op2(Is, A), 0 },
715/*1e*/	{ "push",  false, NONE,  op1(Si),    0 },
716/*1f*/	{ "pop",   false, NONE,  op1(Si),    0 },
717
718/*20*/	{ "and",   true,  BYTE,  op2(R, E),  0 },
719/*21*/	{ "and",   true,  LONG,  op2(R, E),  0 },
720/*22*/	{ "and",   true,  BYTE,  op2(E, R),  0 },
721/*23*/	{ "and",   true,  LONG,  op2(E, R),  0 },
722/*24*/	{ "and",   false, BYTE,  op2(I, A),  0 },
723/*25*/	{ "and",   false, LONG,  op2(I, A),  0 },
724/*26*/	{ "",      false, NONE,  0,	     0 },
725/*27*/	{ "daa",   false, NONE,  0,	     0 },
726
727/*28*/	{ "sub",   true,  BYTE,  op2(R, E),  0 },
728/*29*/	{ "sub",   true,  LONG,  op2(R, E),  0 },
729/*2a*/	{ "sub",   true,  BYTE,  op2(E, R),  0 },
730/*2b*/	{ "sub",   true,  LONG,  op2(E, R),  0 },
731/*2c*/	{ "sub",   false, BYTE,  op2(I, A),  0 },
732/*2d*/	{ "sub",   false, LONG,  op2(Is, A), 0 },
733/*2e*/	{ "",      false, NONE,  0,	     0 },
734/*2f*/	{ "das",   false, NONE,  0,	     0 },
735
736/*30*/	{ "xor",   true,  BYTE,  op2(R, E),  0 },
737/*31*/	{ "xor",   true,  LONG,  op2(R, E),  0 },
738/*32*/	{ "xor",   true,  BYTE,  op2(E, R),  0 },
739/*33*/	{ "xor",   true,  LONG,  op2(E, R),  0 },
740/*34*/	{ "xor",   false, BYTE,  op2(I, A),  0 },
741/*35*/	{ "xor",   false, LONG,  op2(I, A),  0 },
742/*36*/	{ "",      false, NONE,  0,	     0 },
743/*37*/	{ "aaa",   false, NONE,  0,	     0 },
744
745/*38*/	{ "cmp",   true,  BYTE,  op2(R, E),  0 },
746/*39*/	{ "cmp",   true,  LONG,  op2(R, E),  0 },
747/*3a*/	{ "cmp",   true,  BYTE,  op2(E, R),  0 },
748/*3b*/	{ "cmp",   true,  LONG,  op2(E, R),  0 },
749/*3c*/	{ "cmp",   false, BYTE,  op2(I, A),  0 },
750/*3d*/	{ "cmp",   false, LONG,  op2(Is, A), 0 },
751/*3e*/	{ "",      false, NONE,  0,	     0 },
752/*3f*/	{ "aas",   false, NONE,  0,	     0 },
753
754/*40*/	{ "rex",   false, NONE,  0,          0 },
755/*41*/	{ "rex.b", false, NONE,  0,          0 },
756/*42*/	{ "rex.x", false, NONE,  0,          0 },
757/*43*/	{ "rex.xb", false, NONE, 0,          0 },
758/*44*/	{ "rex.r", false, NONE,  0,          0 },
759/*45*/	{ "rex.rb", false, NONE, 0,          0 },
760/*46*/	{ "rex.rx", false, NONE, 0,          0 },
761/*47*/	{ "rex.rxb", false, NONE, 0,         0 },
762
763/*48*/	{ "rex.w", false, NONE,  0,          0 },
764/*49*/	{ "rex.wb", false, NONE, 0,          0 },
765/*4a*/	{ "rex.wx", false, NONE, 0,          0 },
766/*4b*/	{ "rex.wxb", false, NONE, 0,         0 },
767/*4c*/	{ "rex.wr", false, NONE, 0,          0 },
768/*4d*/	{ "rex.wrb", false, NONE, 0,         0 },
769/*4e*/	{ "rex.wrx", false, NONE, 0,         0 },
770/*4f*/	{ "rex.wrxb", false, NONE, 0,        0 },
771
772/*50*/	{ "push",  false, LONG,  op1(Ri),    0 },
773/*51*/	{ "push",  false, LONG,  op1(Ri),    0 },
774/*52*/	{ "push",  false, LONG,  op1(Ri),    0 },
775/*53*/	{ "push",  false, LONG,  op1(Ri),    0 },
776/*54*/	{ "push",  false, LONG,  op1(Ri),    0 },
777/*55*/	{ "push",  false, LONG,  op1(Ri),    0 },
778/*56*/	{ "push",  false, LONG,  op1(Ri),    0 },
779/*57*/	{ "push",  false, LONG,  op1(Ri),    0 },
780
781/*58*/	{ "pop",   false, LONG,  op1(Ri),    0 },
782/*59*/	{ "pop",   false, LONG,  op1(Ri),    0 },
783/*5a*/	{ "pop",   false, LONG,  op1(Ri),    0 },
784/*5b*/	{ "pop",   false, LONG,  op1(Ri),    0 },
785/*5c*/	{ "pop",   false, LONG,  op1(Ri),    0 },
786/*5d*/	{ "pop",   false, LONG,  op1(Ri),    0 },
787/*5e*/	{ "pop",   false, LONG,  op1(Ri),    0 },
788/*5f*/	{ "pop",   false, LONG,  op1(Ri),    0 },
789
790/*60*/	{ "pusha", false, LONG,  0,	     0 },
791/*61*/	{ "popa",  false, LONG,  0,	     0 },
792/*62*/  { "bound", true,  LONG,  op2(E, R),  0 },
793/*63*/	{ "movslq",  true,  NONE,  op2(EL,R), 0 },
794
795/*64*/	{ "",      false, NONE,  0,	     0 },
796/*65*/	{ "",      false, NONE,  0,	     0 },
797/*66*/	{ "",      false, NONE,  0,	     0 },
798/*67*/	{ "",      false, NONE,  0,	     0 },
799
800/*68*/	{ "push",  false, LONG,  op1(I),     0 },
801/*69*/  { "imul",  true,  LONG,  op3(I,E,R), 0 },
802/*6a*/	{ "push",  false, LONG,  op1(Ibs),   0 },
803/*6b*/  { "imul",  true,  LONG,  op3(Ibs,E,R),0 },
804/*6c*/	{ "ins",   false, BYTE,  op2(DX, DI), 0 },
805/*6d*/	{ "ins",   false, LONG,  op2(DX, DI), 0 },
806/*6e*/	{ "outs",  false, BYTE,  op2(SI, DX), 0 },
807/*6f*/	{ "outs",  false, LONG,  op2(SI, DX), 0 },
808
809/*70*/	{ "jo",    false, NONE,  op1(Db),     0 },
810/*71*/	{ "jno",   false, NONE,  op1(Db),     0 },
811/*72*/	{ "jb",    false, NONE,  op1(Db),     0 },
812/*73*/	{ "jnb",   false, NONE,  op1(Db),     0 },
813/*74*/	{ "jz",    false, NONE,  op1(Db),     0 },
814/*75*/	{ "jnz",   false, NONE,  op1(Db),     0 },
815/*76*/	{ "jbe",   false, NONE,  op1(Db),     0 },
816/*77*/	{ "jnbe",  false, NONE,  op1(Db),     0 },
817
818/*78*/	{ "js",    false, NONE,  op1(Db),     0 },
819/*79*/	{ "jns",   false, NONE,  op1(Db),     0 },
820/*7a*/	{ "jp",    false, NONE,  op1(Db),     0 },
821/*7b*/	{ "jnp",   false, NONE,  op1(Db),     0 },
822/*7c*/	{ "jl",    false, NONE,  op1(Db),     0 },
823/*7d*/	{ "jnl",   false, NONE,  op1(Db),     0 },
824/*7e*/	{ "jle",   false, NONE,  op1(Db),     0 },
825/*7f*/	{ "jnle",  false, NONE,  op1(Db),     0 },
826
827/*80*/  { "",	   true,  BYTE,  op2(I, E),   db_Grp1 },
828/*81*/  { "",	   true,  LONG,  op2(I, E),   db_Grp1 },
829/*82*/  { "",	   true,  BYTE,  op2(I, E),   db_Grp1 },
830/*83*/  { "",	   true,  LONG,  op2(Ibs,E),  db_Grp1 },
831/*84*/	{ "test",  true,  BYTE,  op2(R, E),   0 },
832/*85*/	{ "test",  true,  LONG,  op2(R, E),   0 },
833/*86*/	{ "xchg",  true,  BYTE,  op2(R, E),   0 },
834/*87*/	{ "xchg",  true,  LONG,  op2(R, E),   0 },
835
836/*88*/	{ "mov",   true,  BYTE,  op2(R, E),   0 },
837/*89*/	{ "mov",   true,  LONG,  op2(R, E),   0 },
838/*8a*/	{ "mov",   true,  BYTE,  op2(E, R),   0 },
839/*8b*/	{ "mov",   true,  LONG,  op2(E, R),   0 },
840/*8c*/  { "mov",   true,  NONE,  op2(S, Ew),  0 },
841/*8d*/	{ "lea",   true,  LONG,  op2(E, R),   0 },
842/*8e*/	{ "mov",   true,  NONE,  op2(Ew, S),  0 },
843/*8f*/	{ "pop",   true,  LONG,  op1(E),      0 },
844
845/*90*/	{ "nop",   false, NONE,  0,	      0 },
846/*91*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
847/*92*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
848/*93*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
849/*94*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
850/*95*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
851/*96*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
852/*97*/	{ "xchg",  false, LONG,  op2(A, Ri),  0 },
853
854/*98*/	{ "cwde",  false, SDEP,  0,	      "cbw" },
855/*99*/	{ "cdq",   false, SDEP,  0,	      "cwd" },
856/*9a*/	{ "lcall", false, NONE,  op1(OS),     0 },
857/*9b*/	{ "wait",  false, NONE,  0,	      0 },
858/*9c*/	{ "pushf", false, LONG,  0,	      0 },
859/*9d*/	{ "popf",  false, LONG,  0,	      0 },
860/*9e*/	{ "sahf",  false, NONE,  0,	      0 },
861/*9f*/	{ "lahf",  false, NONE,  0,	      0 },
862
863/*a0*/	{ "mov",   false, BYTE,  op2(O, A),   0 },
864/*a1*/	{ "mov",   false, LONG,  op2(O, A),   0 },
865/*a2*/	{ "mov",   false, BYTE,  op2(A, O),   0 },
866/*a3*/	{ "mov",   false, LONG,  op2(A, O),   0 },
867/*a4*/	{ "movs",  false, BYTE,  op2(SI,DI),  0 },
868/*a5*/	{ "movs",  false, LONG,  op2(SI,DI),  0 },
869/*a6*/	{ "cmps",  false, BYTE,  op2(SI,DI),  0 },
870/*a7*/	{ "cmps",  false, LONG,  op2(SI,DI),  0 },
871
872/*a8*/	{ "test",  false, BYTE,  op2(I, A),   0 },
873/*a9*/	{ "test",  false, LONG,  op2(I, A),   0 },
874/*aa*/	{ "stos",  false, BYTE,  op1(DI),     0 },
875/*ab*/	{ "stos",  false, LONG,  op1(DI),     0 },
876/*ac*/	{ "lods",  false, BYTE,  op1(SI),     0 },
877/*ad*/	{ "lods",  false, LONG,  op1(SI),     0 },
878/*ae*/	{ "scas",  false, BYTE,  op1(SI),     0 },
879/*af*/	{ "scas",  false, LONG,  op1(SI),     0 },
880
881/*b0*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
882/*b1*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
883/*b2*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
884/*b3*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
885/*b4*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
886/*b5*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
887/*b6*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
888/*b7*/	{ "mov",   false, BYTE,  op2(I, Ri),  0 },
889
890/*b8*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
891/*b9*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
892/*ba*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
893/*bb*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
894/*bc*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
895/*bd*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
896/*be*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
897/*bf*/	{ "mov",   false, LONG,  op2(Ilq, Ri),  0 },
898
899/*c0*/	{ "",	   true,  BYTE,  op2(Ib, E),  db_Grp2 },
900/*c1*/	{ "",	   true,  LONG,  op2(Ib, E),  db_Grp2 },
901/*c2*/	{ "ret",   false, NONE,  op1(Iw),     0 },
902/*c3*/	{ "ret",   false, NONE,  0,	      0 },
903/*c4*/	{ "les",   true,  LONG,  op2(E, R),   0 },
904/*c5*/	{ "lds",   true,  LONG,  op2(E, R),   0 },
905/*c6*/	{ "mov",   true,  BYTE,  op2(I, E),   0 },
906/*c7*/	{ "mov",   true,  LONG,  op2(I, E),   0 },
907
908/*c8*/	{ "enter", false, NONE,  op2(Iw, Ib), 0 },
909/*c9*/	{ "leave", false, NONE,  0,           0 },
910/*ca*/	{ "lret",  false, NONE,  op1(Iw),     0 },
911/*cb*/	{ "lret",  false, NONE,  0,	      0 },
912/*cc*/	{ "int",   false, NONE,  op1(o3),     0 },
913/*cd*/	{ "int",   false, NONE,  op1(Ib),     0 },
914/*ce*/	{ "into",  false, NONE,  0,	      0 },
915/*cf*/	{ "iret",  false, NONE,  0,	      0 },
916
917/*d0*/	{ "",	   true,  BYTE,  op2(o1, E),  db_Grp2 },
918/*d1*/	{ "",	   true,  LONG,  op2(o1, E),  db_Grp2 },
919/*d2*/	{ "",	   true,  BYTE,  op2(CL, E),  db_Grp2 },
920/*d3*/	{ "",	   true,  LONG,  op2(CL, E),  db_Grp2 },
921/*d4*/	{ "aam",   false, NONE,  op1(Iba),    0 },
922/*d5*/	{ "aad",   false, NONE,  op1(Iba),    0 },
923/*d6*/	{ ".byte\t0xd6", false, NONE, 0,      0 },
924/*d7*/	{ "xlat",  false, BYTE,  op1(BX),     0 },
925
926/*d8*/  { "",      true,  NONE,  0,	      db_Esc8 },
927/*d9*/  { "",      true,  NONE,  0,	      db_Esc9 },
928/*da*/  { "",      true,  NONE,  0,	      db_Esca },
929/*db*/  { "",      true,  NONE,  0,	      db_Escb },
930/*dc*/  { "",      true,  NONE,  0,	      db_Escc },
931/*dd*/  { "",      true,  NONE,  0,	      db_Escd },
932/*de*/  { "",      true,  NONE,  0,	      db_Esce },
933/*df*/  { "",      true,  NONE,  0,	      db_Escf },
934
935/*e0*/	{ "loopne",false, NONE,  op1(Db),     0 },
936/*e1*/	{ "loope", false, NONE,  op1(Db),     0 },
937/*e2*/	{ "loop",  false, NONE,  op1(Db),     0 },
938/*e3*/	{ "jrcxz", false, ADEP,  op1(Db),     "jecxz" },
939/*e4*/	{ "in",    false, BYTE,  op2(Ib, A),  0 },
940/*e5*/	{ "in",    false, LONG,  op2(Ib, A) , 0 },
941/*e6*/	{ "out",   false, BYTE,  op2(A, Ib),  0 },
942/*e7*/	{ "out",   false, LONG,  op2(A, Ib) , 0 },
943
944/*e8*/	{ "call",  false, NONE,  op1(Dl),     0 },
945/*e9*/	{ "jmp",   false, NONE,  op1(Dl),     0 },
946/*ea*/	{ "ljmp",  false, NONE,  op1(OS),     0 },
947/*eb*/	{ "jmp",   false, NONE,  op1(Db),     0 },
948/*ec*/	{ "in",    false, BYTE,  op2(DX, A),  0 },
949/*ed*/	{ "in",    false, LONG,  op2(DX, A) , 0 },
950/*ee*/	{ "out",   false, BYTE,  op2(A, DX),  0 },
951/*ef*/	{ "out",   false, LONG,  op2(A, DX) , 0 },
952
953/*f0*/	{ "",      false, NONE,  0,	     0 },
954/*f1*/	{ ".byte\t0xf1", false, NONE, 0,     0 },
955/*f2*/	{ "",      false, NONE,  0,	     0 },
956/*f3*/	{ "",      false, NONE,  0,	     0 },
957/*f4*/	{ "hlt",   false, NONE,  0,	     0 },
958/*f5*/	{ "cmc",   false, NONE,  0,	     0 },
959/*f6*/	{ "",      true,  BYTE,  0,	     db_Grp3 },
960/*f7*/	{ "",	   true,  LONG,  0,	     db_Grp3 },
961
962/*f8*/	{ "clc",   false, NONE,  0,	     0 },
963/*f9*/	{ "stc",   false, NONE,  0,	     0 },
964/*fa*/	{ "cli",   false, NONE,  0,	     0 },
965/*fb*/	{ "sti",   false, NONE,  0,	     0 },
966/*fc*/	{ "cld",   false, NONE,  0,	     0 },
967/*fd*/	{ "std",   false, NONE,  0,	     0 },
968/*fe*/	{ "",	   true,  NONE,  0,	     db_Grp4 },
969/*ff*/	{ "",	   true,  NONE,  0,	     db_Grp5 },
970};
971
972static const struct inst db_bad_inst =
973	{ "???",   false, NONE,  0,	      0 }
974;
975
976#define	f_mod(rex, byte)	((byte)>>6)
977#define	f_reg(rex, byte)	((((byte)>>3)&0x7) | (rex & REX_R ? 0x8 : 0x0))
978#define	f_rm(rex, byte)		(((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
979
980#define	sib_ss(rex, byte)	((byte)>>6)
981#define	sib_index(rex, byte)	((((byte)>>3)&0x7) | (rex & REX_X ? 0x8 : 0x0))
982#define	sib_base(rex, byte)	(((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
983
984struct i_addr {
985	bool		is_reg;	/* if reg, reg number is in 'disp' */
986	int		disp;
987	const char *	base;
988	const char *	index;
989	int		ss;
990};
991
992static const char * const db_reg[2][4][16] = {
993	{{"%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh",
994	  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
995	{ "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
996	  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
997	{ "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
998	  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
999	{ "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1000	  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }},
1001
1002	{{"%al",  "%cl",  "%dl",  "%bl",  "%spl",  "%bpl",  "%sil",  "%dil",
1003	  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
1004	{ "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
1005	  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
1006	{ "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
1007	  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
1008	{ "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1009	  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }}
1010};
1011
1012static const char * const db_seg_reg[8] = {
1013	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", ""
1014};
1015
1016/*
1017 * lengths for size attributes
1018 */
1019static const int db_lengths[] = {
1020	1,	/* BYTE */
1021	2,	/* WORD */
1022	4,	/* LONG */
1023	8,	/* QUAD */
1024	4,	/* SNGL */
1025	8,	/* DBLR */
1026	10,	/* EXTR */
1027};
1028
1029#define	get_value_inc(result, loc, size, is_signed) \
1030	result = db_get_value((loc), (size), (is_signed)); \
1031	(loc) += (size);
1032
1033static db_addr_t
1034		db_disasm_esc(db_addr_t loc, int inst, int rex, bool short_addr,
1035		    int size, const char *seg);
1036static void	db_print_address(const char *seg, int size, int rex,
1037		    struct i_addr *addrp);
1038static db_addr_t
1039		db_read_address(db_addr_t loc, bool short_addr, int rex, int regmodrm,
1040		    struct i_addr *addrp);
1041
1042/*
1043 * Read address at location and return updated location.
1044 */
1045static db_addr_t
1046db_read_address(db_addr_t loc, bool short_addr, int rex, int regmodrm,
1047    struct i_addr *addrp)
1048{
1049	int		mod, rm, sib, index, disp, size, have_sib;
1050
1051	mod = f_mod(rex, regmodrm);
1052	rm  = f_rm(rex, regmodrm);
1053
1054	if (mod == 3) {
1055	    addrp->is_reg = true;
1056	    addrp->disp = rm;
1057	    return (loc);
1058	}
1059	addrp->is_reg = false;
1060	addrp->index = NULL;
1061
1062	if (short_addr)
1063	    size = LONG;
1064	else
1065	    size = QUAD;
1066
1067	if ((rm & 0x7) == 4) {
1068	    get_value_inc(sib, loc, 1, false);
1069	    rm = sib_base(rex, sib);
1070	    index = sib_index(rex, sib);
1071	    if (index != 4)
1072		addrp->index = db_reg[1][size][index];
1073	    addrp->ss = sib_ss(rex, sib);
1074	    have_sib = 1;
1075	} else
1076	    have_sib = 0;
1077
1078	switch (mod) {
1079	    case 0:
1080		if (rm == 5) {
1081		    get_value_inc(addrp->disp, loc, 4, false);
1082		    if (have_sib)
1083			addrp->base = NULL;
1084		    else if (short_addr)
1085			addrp->base = "%eip";
1086		    else
1087			addrp->base = "%rip";
1088		} else {
1089		    addrp->disp = 0;
1090		    addrp->base = db_reg[1][size][rm];
1091		}
1092		break;
1093
1094	    case 1:
1095		get_value_inc(disp, loc, 1, true);
1096		addrp->disp = disp;
1097		addrp->base = db_reg[1][size][rm];
1098		break;
1099
1100	    case 2:
1101		get_value_inc(disp, loc, 4, false);
1102		addrp->disp = disp;
1103		addrp->base = db_reg[1][size][rm];
1104		break;
1105	}
1106	return (loc);
1107}
1108
1109static void
1110db_print_address(const char *seg, int size, int rex, struct i_addr *addrp)
1111{
1112	if (addrp->is_reg) {
1113	    db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][addrp->disp]);
1114	    return;
1115	}
1116
1117	if (seg) {
1118	    db_printf("%s:", seg);
1119	}
1120
1121	if (addrp->disp != 0 || (addrp->base == NULL && addrp->index == NULL))
1122		db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
1123	if (addrp->base != NULL || addrp->index != NULL) {
1124	    db_printf("(");
1125	    if (addrp->base)
1126		db_printf("%s", addrp->base);
1127	    if (addrp->index)
1128		db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
1129	    db_printf(")");
1130	}
1131}
1132
1133/*
1134 * Disassemble floating-point ("escape") instruction
1135 * and return updated location.
1136 */
1137static db_addr_t
1138db_disasm_esc(db_addr_t loc, int inst, int rex, bool short_addr, int size,
1139    const char *seg)
1140{
1141	int		regmodrm;
1142	const struct finst *	fp;
1143	int		mod;
1144	struct i_addr	address;
1145	const char *	name;
1146
1147	get_value_inc(regmodrm, loc, 1, false);
1148	fp = &db_Esc_inst[inst - 0xd8][f_reg(rex, regmodrm)];
1149	mod = f_mod(rex, regmodrm);
1150	if (mod != 3) {
1151	    if (*fp->f_name == '\0') {
1152		db_printf("<bad instruction>");
1153		return (loc);
1154	    }
1155	    /*
1156	     * Normal address modes.
1157	     */
1158	    loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
1159	    db_printf("%s", fp->f_name);
1160	    switch(fp->f_size) {
1161		case SNGL:
1162		    db_printf("s");
1163		    break;
1164		case DBLR:
1165		    db_printf("l");
1166		    break;
1167		case EXTR:
1168		    db_printf("t");
1169		    break;
1170		case WORD:
1171		    db_printf("s");
1172		    break;
1173		case LONG:
1174		    db_printf("l");
1175		    break;
1176		case QUAD:
1177		    db_printf("q");
1178		    break;
1179		default:
1180		    break;
1181	    }
1182	    db_printf("\t");
1183	    db_print_address(seg, BYTE, rex, &address);
1184	}
1185	else {
1186	    /*
1187	     * 'reg-reg' - special formats
1188	     */
1189	    switch (fp->f_rrmode) {
1190		case op2(ST,STI):
1191		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1192		    db_printf("%s\t%%st,%%st(%d)",name,f_rm(rex, regmodrm));
1193		    break;
1194		case op2(STI,ST):
1195		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1196		    db_printf("%s\t%%st(%d),%%st",name, f_rm(rex, regmodrm));
1197		    break;
1198		case op1(STI):
1199		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1200		    db_printf("%s\t%%st(%d)",name, f_rm(rex, regmodrm));
1201		    break;
1202		case op1(X):
1203		    name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
1204		    if (*name == '\0')
1205			goto bad;
1206		    db_printf("%s", name);
1207		    break;
1208		case op1(XA):
1209		    name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
1210		    if (*name == '\0')
1211			goto bad;
1212		    db_printf("%s\t%%ax", name);
1213		    break;
1214		default:
1215		bad:
1216		    db_printf("<bad instruction>");
1217		    break;
1218	    }
1219	}
1220
1221	return (loc);
1222}
1223
1224/*
1225 * Disassemble instruction at 'loc'.  'altfmt' specifies an
1226 * (optional) alternate format.  Return address of start of
1227 * next instruction.
1228 */
1229db_addr_t
1230db_disasm(db_addr_t loc, bool altfmt)
1231{
1232	int	inst;
1233	int	size;
1234	bool	short_addr;
1235	const char *	seg;
1236	const struct inst *	ip;
1237	const char *	i_name;
1238	int	i_size;
1239	int	i_mode;
1240	int	rex = 0;
1241	int	regmodrm = 0;
1242	bool	first;
1243	int	displ;
1244	bool	prefix;
1245	bool	rep, repne;
1246	int	imm;
1247	int	imm2;
1248	long	imm64;
1249	int	len;
1250	struct i_addr	address;
1251
1252	get_value_inc(inst, loc, 1, false);
1253	short_addr = false;
1254	size = LONG;
1255	seg = NULL;
1256
1257	/*
1258	 * Get prefixes
1259	 */
1260	rep = false;
1261	repne = false;
1262	prefix = true;
1263	do {
1264	    switch (inst) {
1265		case 0x66:		/* data16 */
1266		    size = WORD;
1267		    break;
1268		case 0x67:
1269		    short_addr = true;
1270		    break;
1271		case 0x26:
1272		    seg = "%es";
1273		    break;
1274		case 0x36:
1275		    seg = "%ss";
1276		    break;
1277		case 0x2e:
1278		    seg = "%cs";
1279		    break;
1280		case 0x3e:
1281		    seg = "%ds";
1282		    break;
1283		case 0x64:
1284		    seg = "%fs";
1285		    break;
1286		case 0x65:
1287		    seg = "%gs";
1288		    break;
1289		case 0xf0:
1290		    db_printf("lock ");
1291		    break;
1292		    /*
1293		     * XXX repne/repe are only actually valid for MOVS, CMPS,
1294		     * SCAS, LODS, STOS, INS, OUTS.
1295		     */
1296		case 0xf2:
1297		    repne = true;
1298		    break;
1299		case 0xf3:
1300		    rep = true;
1301		    break;
1302		default:
1303		    prefix = false;
1304		    break;
1305	    }
1306	    if (inst >= 0x40 && inst < 0x50) {
1307		rex = inst;
1308		prefix = true;
1309	    }
1310	    if (prefix) {
1311		get_value_inc(inst, loc, 1, false);
1312	    }
1313	} while (prefix);
1314
1315	if (inst >= 0xd8 && inst <= 0xdf) {
1316	    loc = db_disasm_esc(loc, inst, rex, short_addr, size, seg);
1317	    db_printf("\n");
1318	    return (loc);
1319	}
1320
1321	ip = &db_inst_table[inst];
1322	while (ip->i_size == ESC) {
1323	    get_value_inc(inst, loc, 1, false);
1324	    ip = ((const struct inst * const *)ip->i_extra)[inst>>4];
1325	    if (ip == NULL) {
1326		ip = &db_bad_inst;
1327	    }
1328	    else {
1329		ip = &ip[inst&0xf];
1330	    }
1331	}
1332
1333	if (ip->i_has_modrm) {
1334	    get_value_inc(regmodrm, loc, 1, false);
1335	    loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
1336	}
1337
1338	i_name = ip->i_name;
1339	i_size = ip->i_size;
1340	i_mode = ip->i_mode;
1341
1342	if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) == 3) {
1343	    ip = &db_Grp9b[f_reg(rex, regmodrm)];
1344	    i_name = ip->i_name;
1345	    i_size = ip->i_size;
1346	    i_mode = ip->i_mode;
1347	}
1348	else if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 ||
1349	    ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 ||
1350	    ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9 ||
1351	    ip->i_extra == db_Grp15) {
1352	    i_name = ((const char * const *)ip->i_extra)[f_reg(rex, regmodrm)];
1353	}
1354	else if (ip->i_extra == db_Grp3) {
1355	    ip = ip->i_extra;
1356	    ip = &ip[f_reg(rex, regmodrm)];
1357	    i_name = ip->i_name;
1358	    i_mode = ip->i_mode;
1359	}
1360	else if (ip->i_extra == db_Grp4 || ip->i_extra == db_Grp5) {
1361	    ip = ip->i_extra;
1362	    ip = &ip[f_reg(rex, regmodrm)];
1363	    i_name = ip->i_name;
1364	    i_mode = ip->i_mode;
1365	    i_size = ip->i_size;
1366	}
1367
1368	/* Special cases that don't fit well in the tables. */
1369	if (ip->i_extra == db_Grp7 && f_mod(rex, regmodrm) == 3) {
1370		switch (regmodrm) {
1371		case 0xc1:
1372			i_name = "vmcall";
1373			i_size = NONE;
1374			i_mode = 0;
1375			break;
1376		case 0xc2:
1377			i_name = "vmlaunch";
1378			i_size = NONE;
1379			i_mode = 0;
1380			break;
1381		case 0xc3:
1382			i_name = "vmresume";
1383			i_size = NONE;
1384			i_mode = 0;
1385			break;
1386		case 0xc4:
1387			i_name = "vmxoff";
1388			i_size = NONE;
1389			i_mode = 0;
1390			break;
1391		case 0xc8:
1392			i_name = "monitor";
1393			i_size = NONE;
1394			i_mode = 0;
1395			break;
1396		case 0xc9:
1397			i_name = "mwait";
1398			i_size = NONE;
1399			i_mode = 0;
1400			break;
1401		case 0xca:
1402			i_name = "clac";
1403			i_size = NONE;
1404			i_mode = 0;
1405			break;
1406		case 0xcb:
1407			i_name = "stac";
1408			i_size = NONE;
1409			i_mode = 0;
1410			break;
1411		case 0xd0:
1412			i_name = "xgetbv";
1413			i_size = NONE;
1414			i_mode = 0;
1415			break;
1416		case 0xd1:
1417			i_name = "xsetbv";
1418			i_size = NONE;
1419			i_mode = 0;
1420			break;
1421		case 0xd8:
1422			i_name = "vmrun";
1423			i_size = NONE;
1424			i_mode = 0;
1425			break;
1426		case 0xd9:
1427			i_name = "vmmcall";
1428			i_size = NONE;
1429			i_mode = 0;
1430			break;
1431		case 0xda:
1432			i_name = "vmload";
1433			i_size = NONE;
1434			i_mode = 0;
1435			break;
1436		case 0xdb:
1437			i_name = "vmsave";
1438			i_size = NONE;
1439			i_mode = 0;
1440			break;
1441		case 0xdc:
1442			i_name = "stgi";
1443			i_size = NONE;
1444			i_mode = 0;
1445			break;
1446		case 0xdd:
1447			i_name = "clgi";
1448			i_size = NONE;
1449			i_mode = 0;
1450			break;
1451		case 0xde:
1452			i_name = "skinit";
1453			i_size = NONE;
1454			i_mode = 0;
1455			break;
1456		case 0xdf:
1457			i_name = "invlpga";
1458			i_size = NONE;
1459			i_mode = 0;
1460			break;
1461		case 0xf8:
1462			i_name = "swapgs";
1463			i_size = NONE;
1464			i_mode = 0;
1465			break;
1466		case 0xf9:
1467			i_name = "rdtscp";
1468			i_size = NONE;
1469			i_mode = 0;
1470			break;
1471		}
1472	}
1473	if (ip->i_extra == db_Grp15 && f_mod(rex, regmodrm) == 3) {
1474		i_name = db_Grp15b[f_reg(rex, regmodrm)];
1475		i_size = NONE;
1476		i_mode = 0;
1477	}
1478
1479	/* Handle instructions identified by mandatory prefixes. */
1480	if (rep) {
1481	    if (inst == 0x90) {
1482		i_name = "pause";
1483		i_size = NONE;
1484		i_mode = 0;
1485		rep = false;
1486	    } else if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) != 3 &&
1487		f_reg(rex, regmodrm) == 0x6) {
1488		i_name = "vmxon";
1489		rep = false;
1490	    }
1491	}
1492	/* N.B., likely highly incomplete. */
1493	if (repne) {
1494		if (ip == &db_inst_0f38fx[0] || ip == &db_inst_0f38fx[1])
1495			repne = false;
1496	}
1497	if (size == WORD) {
1498	    if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) != 3 &&
1499		f_reg(rex, regmodrm) == 0x6) {
1500		i_name = "vmclear";
1501	    }
1502	}
1503	if (rex & REX_W) {
1504	    if (strcmp(i_name, "cwde") == 0)
1505		i_name = "cdqe";
1506	    else if (strcmp(i_name, "cmpxchg8b") == 0)
1507		i_name = "cmpxchg16b";
1508	}
1509
1510	if (rep)
1511	    db_printf("repe ");	/* XXX repe VS rep */
1512	if (repne)
1513	    db_printf("repne ");
1514
1515	if (i_size == SDEP) {
1516	    if (size == LONG)
1517		db_printf("%s", i_name);
1518	    else
1519		db_printf("%s", (const char *)ip->i_extra);
1520	} else if (i_size == ADEP) {
1521	    if (!short_addr)
1522		db_printf("%s", i_name);
1523	    else
1524		db_printf("%s", (const char *)ip->i_extra);
1525	}
1526	else {
1527	    db_printf("%s", i_name);
1528	    if ((inst >= 0x50 && inst <= 0x5f) || inst == 0x68 || inst == 0x6a) {
1529		i_size = NONE;
1530		db_printf("q");
1531	    }
1532	    if (i_size != NONE) {
1533		if (i_size == BYTE) {
1534		    db_printf("b");
1535		    size = BYTE;
1536		}
1537		else if (i_size == WORD) {
1538		    db_printf("w");
1539		    size = WORD;
1540		}
1541		else if (size == WORD)
1542		    db_printf("w");
1543		else {
1544		    if (rex & REX_W)
1545			db_printf("q");
1546		    else
1547			db_printf("l");
1548		}
1549	    }
1550	}
1551	db_printf("\t");
1552	for (first = true;
1553	     i_mode != 0;
1554	     i_mode >>= 8, first = false)
1555	{
1556	    if (!first)
1557		db_printf(",");
1558
1559	    switch (i_mode & 0xFF) {
1560		case E:
1561		    db_print_address(seg, size, rex, &address);
1562		    break;
1563
1564		case Eind:
1565		    db_printf("*");
1566		    db_print_address(seg, size, rex, &address);
1567		    break;
1568
1569		case El:
1570		    db_print_address(seg, (rex & REX_W) ? QUAD : LONG, rex, &address);
1571		    break;
1572
1573		case EL:
1574		    db_print_address(seg, LONG, 0, &address);
1575		    break;
1576
1577		case Ew:
1578		    db_print_address(seg, WORD, rex, &address);
1579		    break;
1580
1581		case Eb:
1582		    db_print_address(seg, BYTE, rex, &address);
1583		    break;
1584
1585		case R:
1586		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][f_reg(rex, regmodrm)]);
1587		    break;
1588
1589		case Rw:
1590		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][WORD][f_reg(rex, regmodrm)]);
1591		    break;
1592
1593		case Rq:
1594		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][QUAD][f_reg(rex, regmodrm)]);
1595		    break;
1596
1597		case Ri:
1598		    db_printf("%s", db_reg[0][QUAD][f_rm(rex, inst)]);
1599		    break;
1600
1601		case Ril:
1602		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][(rex & REX_R) ? QUAD : LONG][f_rm(rex, inst)]);
1603		    break;
1604
1605	        case Rv:
1606		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][f_rm(rex, regmodrm)]);
1607		    break;
1608
1609		case S:
1610		    db_printf("%s", db_seg_reg[f_reg(rex, regmodrm)]);
1611		    break;
1612
1613		case Si:
1614		    db_printf("%s", db_seg_reg[f_reg(rex, inst)]);
1615		    break;
1616
1617		case A:
1618		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][size][0]);	/* acc */
1619		    break;
1620
1621		case BX:
1622		    if (seg)
1623			db_printf("%s:", seg);
1624		    db_printf("(%s)", short_addr ? "%bx" : "%ebx");
1625		    break;
1626
1627		case CL:
1628		    db_printf("%%cl");
1629		    break;
1630
1631		case DX:
1632		    db_printf("%%dx");
1633		    break;
1634
1635		case SI:
1636		    if (seg)
1637			db_printf("%s:", seg);
1638		    db_printf("(%s)", short_addr ? "%si" : "%rsi");
1639		    break;
1640
1641		case DI:
1642		    db_printf("%%es:(%s)", short_addr ? "%di" : "%rdi");
1643		    break;
1644
1645		case CR:
1646		    db_printf("%%cr%d", f_reg(rex, regmodrm));
1647		    break;
1648
1649		case DR:
1650		    db_printf("%%dr%d", f_reg(rex, regmodrm));
1651		    break;
1652
1653		case TR:
1654		    db_printf("%%tr%d", f_reg(rex, regmodrm));
1655		    break;
1656
1657		case I:
1658		    len = db_lengths[size];
1659		    get_value_inc(imm, loc, len, false);
1660		    db_printf("$%#r", imm);
1661		    break;
1662
1663		case Is:
1664		    len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size];
1665		    get_value_inc(imm, loc, len, false);
1666		    db_printf("$%+#r", imm);
1667		    break;
1668
1669		case Ib:
1670		    get_value_inc(imm, loc, 1, false);
1671		    db_printf("$%#r", imm);
1672		    break;
1673
1674		case Iba:
1675		    get_value_inc(imm, loc, 1, false);
1676		    if (imm != 0x0a)
1677			db_printf("$%#r", imm);
1678		    break;
1679
1680		case Ibs:
1681		    get_value_inc(imm, loc, 1, true);
1682		    if (size == WORD)
1683			imm &= 0xFFFF;
1684		    db_printf("$%+#r", imm);
1685		    break;
1686
1687		case Iw:
1688		    get_value_inc(imm, loc, 2, false);
1689		    db_printf("$%#r", imm);
1690		    break;
1691
1692		case Ilq:
1693		    len = db_lengths[rex & REX_W ? QUAD : LONG];
1694		    get_value_inc(imm64, loc, len, false);
1695		    db_printf("$%#lr", imm64);
1696		    break;
1697
1698		case O:
1699		    len = (short_addr ? 2 : 4);
1700		    get_value_inc(displ, loc, len, false);
1701		    if (seg)
1702			db_printf("%s:%+#r",seg, displ);
1703		    else
1704			db_printsym((db_addr_t)displ, DB_STGY_ANY);
1705		    break;
1706
1707		case Db:
1708		    get_value_inc(displ, loc, 1, true);
1709		    displ += loc;
1710		    if (size == WORD)
1711			displ &= 0xFFFF;
1712		    db_printsym((db_addr_t)displ, DB_STGY_XTRN);
1713		    break;
1714
1715		case Dl:
1716		    len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size];
1717		    get_value_inc(displ, loc, len, false);
1718		    displ += loc;
1719		    if (size == WORD)
1720			displ &= 0xFFFF;
1721		    db_printsym((db_addr_t)displ, DB_STGY_XTRN);
1722		    break;
1723
1724		case o1:
1725		    db_printf("$1");
1726		    break;
1727
1728		case o3:
1729		    db_printf("$3");
1730		    break;
1731
1732		case OS:
1733		    len = db_lengths[size];
1734		    get_value_inc(imm, loc, len, false);	/* offset */
1735		    get_value_inc(imm2, loc, 2, false);	/* segment */
1736		    db_printf("$%#r,%#r", imm2, imm);
1737		    break;
1738	    }
1739	}
1740	db_printf("\n");
1741	return (loc);
1742}
1743