1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * HISTORY
33 *
34 * Revision 1.1.1.1  1998/09/22 21:05:36  wsanchez
35 * Import of Mac OS X kernel (~semeria)
36 *
37 * Revision 1.1.1.1  1998/03/07 02:25:37  wsanchez
38 * Import of OSF Mach kernel (~mburg)
39 *
40 * Revision 1.2.8.3  1996/07/31  09:43:35  paire
41 * 	Merged with nmk20b7_shared (1.2.11.1)
42 * 	[96/06/10            paire]
43 *
44 * Revision 1.2.11.1  1996/05/14  13:49:36  paire
45 * 	Added support for new cmpxchg8b, cpuid, rdtsc, rdwmr, rsm and wrmsr
46 * 	Pentium instructions
47 * 	[95/11/23            paire]
48 *
49 * Revision 1.2.8.2  1994/09/23  01:50:45  ezf
50 * 	change marker to not FREE
51 * 	[1994/09/22  21:21:17  ezf]
52 *
53 * Revision 1.2.8.1  1994/09/16  15:26:28  emcmanus
54 * 	Only skip over GAS-inserted NOPs after branches if they are really
55 * 	NOPs; this depends at least on assembler options.
56 * 	[1994/09/16  15:26:03  emcmanus]
57 *
58 * Revision 1.2.6.3  1994/02/19  15:40:34  bolinger
59 * 	For load/store counting, mark all varieties of "call" as writing
60 * 	memory.
61 * 	[1994/02/15  20:25:18  bolinger]
62 *
63 * Revision 1.2.6.2  1994/02/14  21:46:49  dwm
64 * 	Warning repair
65 * 	[1994/02/14  21:46:14  dwm]
66 *
67 * Revision 1.2.6.1  1994/02/12  23:26:05  bolinger
68 * 	Implement load/store counting for ddb "until" command.
69 * 	[1994/02/12  03:34:55  bolinger]
70 *
71 * Revision 1.2.2.3  1993/08/09  19:39:21  dswartz
72 * 	Add ANSI prototypes - CR#9523
73 * 	[1993/08/06  17:44:13  dswartz]
74 *
75 * Revision 1.2.2.2  1993/06/09  02:27:29  gm
76 * 	Added to OSF/1 R1.3 from NMK15.0.
77 * 	[1993/06/02  21:03:54  jeffc]
78 *
79 * Revision 1.2  1993/04/19  16:12:57  devrcs
80 * 	Print file names and lineno on branch instructions.
81 * 	[barbou@gr.osf.org]
82 * 	[92/12/03            bernadat]
83 *
84 * Revision 1.1  1992/09/30  02:02:19  robert
85 * 	Initial revision
86 *
87 * $EndLog$
88 */
89/* CMU_HIST */
90/*
91 * Revision 2.5.3.1  92/03/03  16:14:27  jeffreyh
92 * 	Pick up changes from TRUNK
93 * 	[92/02/26  11:05:06  jeffreyh]
94 *
95 * Revision 2.6  92/01/03  20:05:00  dbg
96 * 	Add a switch to disassemble 16-bit code.
97 * 	Fix spelling of 'lods' opcodes.
98 * 	[91/10/30            dbg]
99 *
100 * Revision 2.5  91/10/09  16:05:58  af
101 * 	Supported disassemble of non current task by passing task parameter.
102 * 	[91/08/29            tak]
103 *
104 * Revision 2.4  91/05/14  16:05:04  mrt
105 * 	Correcting copyright
106 *
107 * Revision 2.3  91/02/05  17:11:03  mrt
108 * 	Changed to new Mach copyright
109 * 	[91/02/01  17:31:03  mrt]
110 *
111 * Revision 2.2  90/08/27  21:55:56  dbg
112 * 	Fix register operand for move to/from control/test/debug
113 * 	register instructions.  Add i486 instructions.
114 * 	[90/08/27            dbg]
115 *
116 * 	Import db_sym.h.  Print instruction displacements in
117 * 	current radix (signed).  Change calling sequence of
118 * 	db_disasm.
119 * 	[90/08/21            dbg]
120 * 	Fix includes.
121 * 	[90/08/08            dbg]
122 * 	Created.
123 * 	[90/07/25            dbg]
124 *
125 */
126/* CMU_ENDHIST */
127/*
128 * Mach Operating System
129 * Copyright (c) 1991,1990 Carnegie Mellon University
130 * All Rights Reserved.
131 *
132 * Permission to use, copy, modify and distribute this software and its
133 * documentation is hereby granted, provided that both the copyright
134 * notice and this permission notice appear in all copies of the
135 * software, derivative works or modified versions, and any portions
136 * thereof, and that both notices appear in supporting documentation.
137 *
138 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
139 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
140 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
141 *
142 * Carnegie Mellon requests users of this software to return to
143 *
144 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
145 *  School of Computer Science
146 *  Carnegie Mellon University
147 *  Pittsburgh PA 15213-3890
148 *
149 * any improvements or extensions that they make and grant Carnegie Mellon
150 * the rights to redistribute these changes.
151 */
152/*
153 */
154
155/*
156 * Instruction disassembler.
157 */
158
159#include <mach/boolean.h>
160#include <machine/db_machdep.h>
161
162#include <ddb/db_access.h>
163#include <ddb/db_sym.h>
164#include <ddb/db_output.h>
165
166#include <kern/task.h>
167#include <kern/misc_protos.h>
168
169struct i_addr {
170	int		is_reg;	/* if reg, reg number is in 'disp' */
171	int		disp;
172	char *		base;
173	char *		index;
174	int		ss;
175};
176
177/* Forward */
178
179extern db_addr_t	db_read_address(
180				db_addr_t	loc,
181				int		short_addr,
182				int		regmodrm,
183				struct i_addr	* addrp,
184				task_t		task);
185extern void		db_print_address(
186				char *		seg,
187				int		size,
188				struct i_addr	*addrp,
189				task_t		task);
190extern db_addr_t	db_disasm_esc(
191				db_addr_t	loc,
192				int		inst,
193				int		short_addr,
194				int		size,
195				char *		seg,
196				task_t		task);
197
198/*
199 * Switch to disassemble 16-bit code.
200 */
201boolean_t	db_disasm_16 = FALSE;
202
203/*
204 * Size attributes
205 */
206#define	BYTE	0
207#define	WORD	1
208#define	LONG	2
209#define	QUAD	3
210#define	SNGL	4
211#define	DBLR	5
212#define	EXTR	6
213#define	SDEP	7
214#define	NONE	8
215
216/*
217 * Addressing modes
218 */
219#define	E	1			/* general effective address */
220#define	Eind	2			/* indirect address (jump, call) */
221#define	Ew	3			/* address, word size */
222#define	Eb	4			/* address, byte size */
223#define	R	5			/* register, in 'reg' field */
224#define	Rw	6			/* word register, in 'reg' field */
225#define	Ri	7			/* register in instruction */
226#define	S	8			/* segment reg, in 'reg' field */
227#define	Si	9			/* segment reg, in instruction */
228#define	A	10			/* accumulator */
229#define	BX	11			/* (bx) */
230#define	CL	12			/* cl, for shifts */
231#define	DX	13			/* dx, for IO */
232#define	SI	14			/* si */
233#define	DI	15			/* di */
234#define	CR	16			/* control register */
235#define	DR	17			/* debug register */
236#define	TR	18			/* test register */
237#define	I	19			/* immediate, unsigned */
238#define	Is	20			/* immediate, signed */
239#define	Ib	21			/* byte immediate, unsigned */
240#define	Ibs	22			/* byte immediate, signed */
241#define	Iw	23			/* word immediate, unsigned */
242#define	Il	24			/* long immediate */
243#define	O	25			/* direct address */
244#define	Db	26			/* byte displacement from EIP */
245#define	Dl	27			/* long displacement from EIP */
246#define	o1	28			/* constant 1 */
247#define	o3	29			/* constant 3 */
248#define	OS	30			/* immediate offset/segment */
249#define	ST	31			/* FP stack top */
250#define	STI	32			/* FP stack */
251#define	X	33			/* extended FP op */
252#define	XA	34			/* for 'fstcw %ax' */
253
254struct inst {
255	char *	i_name;			/* name */
256	short	i_has_modrm;		/* has regmodrm byte */
257	short	i_size;			/* operand size */
258	int	i_mode;			/* addressing modes */
259	char *	i_extra;		/* pointer to extra opcode table */
260};
261
262#define	op1(x)		(x)
263#define	op2(x,y)	((x)|((y)<<8))
264#define	op3(x,y,z)	((x)|((y)<<8)|((z)<<16))
265
266struct finst {
267	char *	f_name;			/* name for memory instruction */
268	int	f_size;			/* size for memory instruction */
269	int	f_rrmode;		/* mode for rr instruction */
270	char *	f_rrname;		/* name for rr instruction
271					   (or pointer to table) */
272};
273
274char *	db_Grp6[] = {
275	"sldt",
276	"str",
277	"lldt",
278	"ltr",
279	"verr",
280	"verw",
281	"",
282	""
283};
284
285char *	db_Grp7[] = {
286	"sgdt",
287	"sidt",
288	"lgdt",
289	"lidt",
290	"smsw",
291	"",
292	"lmsw",
293	"invlpg"
294};
295
296char *	db_Grp8[] = {
297	"",
298	"",
299	"",
300	"",
301	"bt",
302	"bts",
303	"btr",
304	"btc"
305};
306
307struct inst db_inst_0f0x[] = {
308/*00*/	{ "",	   TRUE,  NONE,  op1(Ew),     (char *)db_Grp6 },
309/*01*/	{ "",	   TRUE,  NONE,  op1(Ew),     (char *)db_Grp7 },
310/*02*/	{ "lar",   TRUE,  LONG,  op2(E,R),    0 },
311/*03*/	{ "lsl",   TRUE,  LONG,  op2(E,R),    0 },
312/*04*/	{ "",      FALSE, NONE,  0,	      0 },
313/*05*/	{ "",      FALSE, NONE,  0,	      0 },
314/*06*/	{ "clts",  FALSE, NONE,  0,	      0 },
315/*07*/	{ "",      FALSE, NONE,  0,	      0 },
316
317/*08*/	{ "invd",  FALSE, NONE,  0,	      0 },
318/*09*/	{ "wbinvd",FALSE, NONE,  0,	      0 },
319/*0a*/	{ "",      FALSE, NONE,  0,	      0 },
320/*0b*/	{ "",      FALSE, NONE,  0,	      0 },
321/*0c*/	{ "",      FALSE, NONE,  0,	      0 },
322/*0d*/	{ "",      FALSE, NONE,  0,	      0 },
323/*0e*/	{ "",      FALSE, NONE,  0,	      0 },
324/*0f*/	{ "",      FALSE, NONE,  0,	      0 },
325};
326
327struct inst	db_inst_0f2x[] = {
328/*20*/	{ "mov",   TRUE,  LONG,  op2(CR,E),   0 }, /* use E for reg */
329/*21*/	{ "mov",   TRUE,  LONG,  op2(DR,E),   0 }, /* since mod == 11 */
330/*22*/	{ "mov",   TRUE,  LONG,  op2(E,CR),   0 },
331/*23*/	{ "mov",   TRUE,  LONG,  op2(E,DR),   0 },
332/*24*/	{ "mov",   TRUE,  LONG,  op2(TR,E),   0 },
333/*25*/	{ "",      FALSE, NONE,  0,	      0 },
334/*26*/	{ "mov",   TRUE,  LONG,  op2(E,TR),   0 },
335/*27*/	{ "",      FALSE, NONE,  0,	      0 },
336
337/*28*/	{ "",      FALSE, NONE,  0,	      0 },
338/*29*/	{ "",      FALSE, NONE,  0,	      0 },
339/*2a*/	{ "",      FALSE, NONE,  0,	      0 },
340/*2b*/	{ "",      FALSE, NONE,  0,	      0 },
341/*2c*/	{ "",      FALSE, NONE,  0,	      0 },
342/*2d*/	{ "",      FALSE, NONE,  0,	      0 },
343/*2e*/	{ "",      FALSE, NONE,  0,	      0 },
344/*2f*/	{ "",      FALSE, NONE,  0,	      0 },
345};
346struct inst	db_inst_0f3x[] = {
347/*30*/	{ "rdtsc", FALSE, NONE,  0,	      0 },
348/*31*/	{ "rdmsr", FALSE, NONE,  0,	      0 },
349/*32*/	{ "wrmsr", FALSE, NONE,  0,	      0 },
350/*33*/	{ "",      FALSE, NONE,  0,	      0 },
351/*34*/	{ "",      FALSE, NONE,  0,	      0 },
352/*35*/	{ "",      FALSE, NONE,  0,	      0 },
353/*36*/	{ "",      FALSE, NONE,  0,	      0 },
354/*37*/	{ "",      FALSE, NONE,  0,	      0 },
355
356/*38*/	{ "",      FALSE, NONE,  0,	      0 },
357/*39*/	{ "",      FALSE, NONE,  0,	      0 },
358/*3a*/	{ "",      FALSE, NONE,  0,	      0 },
359/*3b*/	{ "",      FALSE, NONE,  0,	      0 },
360/*3c*/	{ "",      FALSE, NONE,  0,	      0 },
361/*3d*/	{ "",      FALSE, NONE,  0,	      0 },
362/*3e*/	{ "",      FALSE, NONE,  0,	      0 },
363/*3f*/	{ "",      FALSE, NONE,  0,	      0 },
364};
365
366struct inst	db_inst_0f8x[] = {
367/*80*/	{ "jo",    FALSE, NONE,  op1(Dl),     0 },
368/*81*/	{ "jno",   FALSE, NONE,  op1(Dl),     0 },
369/*82*/	{ "jb",    FALSE, NONE,  op1(Dl),     0 },
370/*83*/	{ "jnb",   FALSE, NONE,  op1(Dl),     0 },
371/*84*/	{ "jz",    FALSE, NONE,  op1(Dl),     0 },
372/*85*/	{ "jnz",   FALSE, NONE,  op1(Dl),     0 },
373/*86*/	{ "jbe",   FALSE, NONE,  op1(Dl),     0 },
374/*87*/	{ "jnbe",  FALSE, NONE,  op1(Dl),     0 },
375
376/*88*/	{ "js",    FALSE, NONE,  op1(Dl),     0 },
377/*89*/	{ "jns",   FALSE, NONE,  op1(Dl),     0 },
378/*8a*/	{ "jp",    FALSE, NONE,  op1(Dl),     0 },
379/*8b*/	{ "jnp",   FALSE, NONE,  op1(Dl),     0 },
380/*8c*/	{ "jl",    FALSE, NONE,  op1(Dl),     0 },
381/*8d*/	{ "jnl",   FALSE, NONE,  op1(Dl),     0 },
382/*8e*/	{ "jle",   FALSE, NONE,  op1(Dl),     0 },
383/*8f*/	{ "jnle",  FALSE, NONE,  op1(Dl),     0 },
384};
385
386struct inst	db_inst_0f9x[] = {
387/*90*/	{ "seto",  TRUE,  NONE,  op1(Eb),     0 },
388/*91*/	{ "setno", TRUE,  NONE,  op1(Eb),     0 },
389/*92*/	{ "setb",  TRUE,  NONE,  op1(Eb),     0 },
390/*93*/	{ "setnb", TRUE,  NONE,  op1(Eb),     0 },
391/*94*/	{ "setz",  TRUE,  NONE,  op1(Eb),     0 },
392/*95*/	{ "setnz", TRUE,  NONE,  op1(Eb),     0 },
393/*96*/	{ "setbe", TRUE,  NONE,  op1(Eb),     0 },
394/*97*/	{ "setnbe",TRUE,  NONE,  op1(Eb),     0 },
395
396/*98*/	{ "sets",  TRUE,  NONE,  op1(Eb),     0 },
397/*99*/	{ "setns", TRUE,  NONE,  op1(Eb),     0 },
398/*9a*/	{ "setp",  TRUE,  NONE,  op1(Eb),     0 },
399/*9b*/	{ "setnp", TRUE,  NONE,  op1(Eb),     0 },
400/*9c*/	{ "setl",  TRUE,  NONE,  op1(Eb),     0 },
401/*9d*/	{ "setnl", TRUE,  NONE,  op1(Eb),     0 },
402/*9e*/	{ "setle", TRUE,  NONE,  op1(Eb),     0 },
403/*9f*/	{ "setnle",TRUE,  NONE,  op1(Eb),     0 },
404};
405
406struct inst	db_inst_0fax[] = {
407/*a0*/	{ "push",  FALSE, NONE,  op1(Si),     0 },
408/*a1*/	{ "pop",   FALSE, NONE,  op1(Si),     0 },
409/*a2*/	{ "cpuid", FALSE, NONE,  0,	      0 },
410/*a3*/	{ "bt",    TRUE,  LONG,  op2(E,R),    0 },
411/*a4*/	{ "shld",  TRUE,  LONG,  op3(Ib,E,R), 0 },
412/*a5*/	{ "shld",  TRUE,  LONG,  op3(CL,E,R), 0 },
413/*a6*/	{ "",      FALSE, NONE,  0,	      0 },
414/*a7*/	{ "",      FALSE, NONE,  0,	      0 },
415
416/*a8*/	{ "push",  FALSE, NONE,  op1(Si),     0 },
417/*a9*/	{ "pop",   FALSE, NONE,  op1(Si),     0 },
418/*aa*/	{ "rsm",   FALSE, NONE,  0,	      0 },
419/*ab*/	{ "bts",   TRUE,  LONG,  op2(E,R),    0 },
420/*ac*/	{ "shrd",  TRUE,  LONG,  op3(Ib,E,R), 0 },
421/*ad*/	{ "shrd",  TRUE,  LONG,  op3(CL,E,R), 0 },
422/*a6*/	{ "",      FALSE, NONE,  0,	      0 },
423/*a7*/	{ "imul",  TRUE,  LONG,  op2(E,R),    0 },
424};
425
426struct inst	db_inst_0fbx[] = {
427/*b0*/	{ "",      FALSE, NONE,  0,	      0 },
428/*b1*/	{ "",      FALSE, NONE,  0,	      0 },
429/*b2*/	{ "lss",   TRUE,  LONG,  op2(E, R),   0 },
430/*b3*/	{ "bts",   TRUE,  LONG,  op2(R, E),   0 },
431/*b4*/	{ "lfs",   TRUE,  LONG,  op2(E, R),   0 },
432/*b5*/	{ "lgs",   TRUE,  LONG,  op2(E, R),   0 },
433/*b6*/	{ "movzb", TRUE,  LONG,  op2(E, R),   0 },
434/*b7*/	{ "movzw", TRUE,  LONG,  op2(E, R),   0 },
435
436/*b8*/	{ "",      FALSE, NONE,  0,	      0 },
437/*b9*/	{ "",      FALSE, NONE,  0,	      0 },
438/*ba*/	{ "",      TRUE,  LONG,  op2(Is, E),  (char *)db_Grp8 },
439/*bb*/	{ "btc",   TRUE,  LONG,  op2(R, E),   0 },
440/*bc*/	{ "bsf",   TRUE,  LONG,  op2(E, R),   0 },
441/*bd*/	{ "bsr",   TRUE,  LONG,  op2(E, R),   0 },
442/*be*/	{ "movsb", TRUE,  LONG,  op2(E, R),   0 },
443/*bf*/	{ "movsw", TRUE,  LONG,  op2(E, R),   0 },
444};
445
446struct inst	db_inst_0fcx[] = {
447/*c0*/	{ "xadd",  TRUE,  BYTE,	 op2(R, E),   0 },
448/*c1*/	{ "xadd",  TRUE,  LONG,	 op2(R, E),   0 },
449/*c2*/	{ "",	   FALSE, NONE,	 0,	      0 },
450/*c3*/	{ "",	   FALSE, NONE,	 0,	      0 },
451/*c4*/	{ "",	   FALSE, NONE,	 0,	      0 },
452/*c5*/	{ "",	   FALSE, NONE,	 0,	      0 },
453/*c6*/	{ "",	   FALSE, NONE,	 0,	      0 },
454/*c7*/	{ "cmpxchg8b", FALSE, NONE, op1(E),   0 },
455/*c8*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
456/*c9*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
457/*ca*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
458/*cb*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
459/*cc*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
460/*cd*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
461/*ce*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
462/*cf*/	{ "bswap", FALSE, LONG,  op1(Ri),     0 },
463};
464
465struct inst	db_inst_0fdx[] = {
466/*c0*/	{ "cmpxchg",TRUE, BYTE,	 op2(R, E),   0 },
467/*c1*/	{ "cmpxchg",TRUE, LONG,	 op2(R, E),   0 },
468/*c2*/	{ "",	   FALSE, NONE,	 0,	      0 },
469/*c3*/	{ "",	   FALSE, NONE,	 0,	      0 },
470/*c4*/	{ "",	   FALSE, NONE,	 0,	      0 },
471/*c5*/	{ "",	   FALSE, NONE,	 0,	      0 },
472/*c6*/	{ "",	   FALSE, NONE,	 0,	      0 },
473/*c7*/	{ "",	   FALSE, NONE,	 0,	      0 },
474/*c8*/	{ "",	   FALSE, NONE,	 0,	      0 },
475/*c9*/	{ "",	   FALSE, NONE,	 0,	      0 },
476/*ca*/	{ "",	   FALSE, NONE,	 0,	      0 },
477/*cb*/	{ "",	   FALSE, NONE,	 0,	      0 },
478/*cc*/	{ "",	   FALSE, NONE,	 0,	      0 },
479/*cd*/	{ "",	   FALSE, NONE,	 0,	      0 },
480/*ce*/	{ "",	   FALSE, NONE,	 0,	      0 },
481/*cf*/	{ "",	   FALSE, NONE,	 0,	      0 },
482};
483
484struct inst *db_inst_0f[] = {
485	db_inst_0f0x,
486	0,
487	db_inst_0f2x,
488	db_inst_0f3x,
489	0,
490	0,
491	0,
492	0,
493	db_inst_0f8x,
494	db_inst_0f9x,
495	db_inst_0fax,
496	db_inst_0fbx,
497	db_inst_0fcx,
498	db_inst_0fdx,
499	0,
500	0
501};
502
503char *	db_Esc92[] = {
504	"fnop",	"",	"",	"",	"",	"",	"",	""
505};
506char *	db_Esc93[] = {
507	"",	"",	"",	"",	"",	"",	"",	""
508};
509char *	db_Esc94[] = {
510	"fchs",	"fabs",	"",	"",	"ftst",	"fxam",	"",	""
511};
512char *	db_Esc95[] = {
513	"fld1",	"fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz",""
514};
515char *	db_Esc96[] = {
516	"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp",
517	"fincstp"
518};
519char *	db_Esc97[] = {
520	"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"
521};
522
523char *	db_Esca4[] = {
524	"",	"fucompp","",	"",	"",	"",	"",	""
525};
526
527char *	db_Escb4[] = {
528	"",	"",	"fnclex","fninit","",	"",	"",	""
529};
530
531char *	db_Esce3[] = {
532	"",	"fcompp","",	"",	"",	"",	"",	""
533};
534
535char *	db_Escf4[] = {
536	"fnstsw","",	"",	"",	"",	"",	"",	""
537};
538
539struct finst db_Esc8[] = {
540/*0*/	{ "fadd",   SNGL,  op2(STI,ST),	0 },
541/*1*/	{ "fmul",   SNGL,  op2(STI,ST),	0 },
542/*2*/	{ "fcom",   SNGL,  op2(STI,ST),	0 },
543/*3*/	{ "fcomp",  SNGL,  op2(STI,ST),	0 },
544/*4*/	{ "fsub",   SNGL,  op2(STI,ST),	0 },
545/*5*/	{ "fsubr",  SNGL,  op2(STI,ST),	0 },
546/*6*/	{ "fdiv",   SNGL,  op2(STI,ST),	0 },
547/*7*/	{ "fdivr",  SNGL,  op2(STI,ST),	0 },
548};
549
550struct finst db_Esc9[] = {
551/*0*/	{ "fld",    SNGL,  op1(STI),	0 },
552/*1*/	{ "",       NONE,  op1(STI),	"fxch" },
553/*2*/	{ "fst",    SNGL,  op1(X),	(char *)db_Esc92 },
554/*3*/	{ "fstp",   SNGL,  op1(X),	(char *)db_Esc93 },
555/*4*/	{ "fldenv", NONE,  op1(X),	(char *)db_Esc94 },
556/*5*/	{ "fldcw",  NONE,  op1(X),	(char *)db_Esc95 },
557/*6*/	{ "fnstenv",NONE,  op1(X),	(char *)db_Esc96 },
558/*7*/	{ "fnstcw", NONE,  op1(X),	(char *)db_Esc97 },
559};
560
561struct finst db_Esca[] = {
562/*0*/	{ "fiadd",  WORD,  0,		0 },
563/*1*/	{ "fimul",  WORD,  0,		0 },
564/*2*/	{ "ficom",  WORD,  0,		0 },
565/*3*/	{ "ficomp", WORD,  0,		0 },
566/*4*/	{ "fisub",  WORD,  op1(X),	(char *)db_Esca4 },
567/*5*/	{ "fisubr", WORD,  0,		0 },
568/*6*/	{ "fidiv",  WORD,  0,		0 },
569/*7*/	{ "fidivr", WORD,  0,		0 }
570};
571
572struct finst db_Escb[] = {
573/*0*/	{ "fild",   WORD,  0,		0 },
574/*1*/	{ "",       NONE,  0,		0 },
575/*2*/	{ "fist",   WORD,  0,		0 },
576/*3*/	{ "fistp",  WORD,  0,		0 },
577/*4*/	{ "",       WORD,  op1(X),	(char *)db_Escb4 },
578/*5*/	{ "fld",    EXTR,  0,		0 },
579/*6*/	{ "",       WORD,  0,		0 },
580/*7*/	{ "fstp",   EXTR,  0,		0 },
581};
582
583struct finst db_Escc[] = {
584/*0*/	{ "fadd",   DBLR,  op2(ST,STI),	0 },
585/*1*/	{ "fmul",   DBLR,  op2(ST,STI),	0 },
586/*2*/	{ "fcom",   DBLR,  op2(ST,STI),	0 },
587/*3*/	{ "fcomp",  DBLR,  op2(ST,STI),	0 },
588/*4*/	{ "fsub",   DBLR,  op2(ST,STI),	"fsubr" },
589/*5*/	{ "fsubr",  DBLR,  op2(ST,STI),	"fsub" },
590/*6*/	{ "fdiv",   DBLR,  op2(ST,STI),	"fdivr" },
591/*7*/	{ "fdivr",  DBLR,  op2(ST,STI),	"fdiv" },
592};
593
594struct finst db_Escd[] = {
595/*0*/	{ "fld",    DBLR,  op1(STI),	"ffree" },
596/*1*/	{ "",       NONE,  0,		0 },
597/*2*/	{ "fst",    DBLR,  op1(STI),	0 },
598/*3*/	{ "fstp",   DBLR,  op1(STI),	0 },
599/*4*/	{ "frstor", NONE,  op1(STI),	"fucom" },
600/*5*/	{ "",       NONE,  op1(STI),	"fucomp" },
601/*6*/	{ "fnsave", NONE,  0,		0 },
602/*7*/	{ "fnstsw", NONE,  0,		0 },
603};
604
605struct finst db_Esce[] = {
606/*0*/	{ "fiadd",  LONG,  op2(ST,STI),	"faddp" },
607/*1*/	{ "fimul",  LONG,  op2(ST,STI),	"fmulp" },
608/*2*/	{ "ficom",  LONG,  0,		0 },
609/*3*/	{ "ficomp", LONG,  op1(X),	(char *)db_Esce3 },
610/*4*/	{ "fisub",  LONG,  op2(ST,STI),	"fsubrp" },
611/*5*/	{ "fisubr", LONG,  op2(ST,STI),	"fsubp" },
612/*6*/	{ "fidiv",  LONG,  op2(ST,STI),	"fdivrp" },
613/*7*/	{ "fidivr", LONG,  op2(ST,STI),	"fdivp" },
614};
615
616struct finst db_Escf[] = {
617/*0*/	{ "fild",   LONG,  0,		0 },
618/*1*/	{ "",       LONG,  0,		0 },
619/*2*/	{ "fist",   LONG,  0,		0 },
620/*3*/	{ "fistp",  LONG,  0,		0 },
621/*4*/	{ "fbld",   NONE,  op1(XA),	(char *)db_Escf4 },
622/*5*/	{ "fld",    QUAD,  0,		0 },
623/*6*/	{ "fbstp",  NONE,  0,		0 },
624/*7*/	{ "fstp",   QUAD,  0,		0 },
625};
626
627struct finst *db_Esc_inst[] = {
628	db_Esc8, db_Esc9, db_Esca, db_Escb,
629	db_Escc, db_Escd, db_Esce, db_Escf
630};
631
632char *	db_Grp1[] = {
633	"add",
634	"or",
635	"adc",
636	"sbb",
637	"and",
638	"sub",
639	"xor",
640	"cmp"
641};
642
643char *	db_Grp2[] = {
644	"rol",
645	"ror",
646	"rcl",
647	"rcr",
648	"shl",
649	"shr",
650	"shl",
651	"sar"
652};
653
654struct inst db_Grp3[] = {
655	{ "test",  TRUE, NONE, op2(I,E), 0 },
656	{ "test",  TRUE, NONE, op2(I,E), 0 },
657	{ "not",   TRUE, NONE, op1(E),   0 },
658	{ "neg",   TRUE, NONE, op1(E),   0 },
659	{ "mul",   TRUE, NONE, op2(E,A), 0 },
660	{ "imul",  TRUE, NONE, op2(E,A), 0 },
661	{ "div",   TRUE, NONE, op2(E,A), 0 },
662	{ "idiv",  TRUE, NONE, op2(E,A), 0 },
663};
664
665struct inst	db_Grp4[] = {
666	{ "inc",   TRUE, BYTE, op1(E),   0 },
667	{ "dec",   TRUE, BYTE, op1(E),   0 },
668	{ "",      TRUE, NONE, 0,	 0 },
669	{ "",      TRUE, NONE, 0,	 0 },
670	{ "",      TRUE, NONE, 0,	 0 },
671	{ "",      TRUE, NONE, 0,	 0 },
672	{ "",      TRUE, NONE, 0,	 0 },
673	{ "",      TRUE, NONE, 0,	 0 }
674};
675
676struct inst	db_Grp5[] = {
677	{ "inc",   TRUE, LONG, op1(E),   0 },
678	{ "dec",   TRUE, LONG, op1(E),   0 },
679	{ "call",  TRUE, NONE, op1(Eind),0 },
680	{ "lcall", TRUE, NONE, op1(Eind),0 },
681	{ "jmp",   TRUE, NONE, op1(Eind),0 },
682	{ "ljmp",  TRUE, NONE, op1(Eind),0 },
683	{ "push",  TRUE, LONG, op1(E),   0 },
684	{ "",      TRUE, NONE, 0,	 0 }
685};
686
687struct inst db_inst_table[256] = {
688/*00*/	{ "add",   TRUE,  BYTE,  op2(R, E),  0 },
689/*01*/	{ "add",   TRUE,  LONG,  op2(R, E),  0 },
690/*02*/	{ "add",   TRUE,  BYTE,  op2(E, R),  0 },
691/*03*/	{ "add",   TRUE,  LONG,  op2(E, R),  0 },
692/*04*/	{ "add",   FALSE, BYTE,  op2(Is, A), 0 },
693/*05*/	{ "add",   FALSE, LONG,  op2(Is, A), 0 },
694/*06*/	{ "push",  FALSE, NONE,  op1(Si),    0 },
695/*07*/	{ "pop",   FALSE, NONE,  op1(Si),    0 },
696
697/*08*/	{ "or",    TRUE,  BYTE,  op2(R, E),  0 },
698/*09*/	{ "or",    TRUE,  LONG,  op2(R, E),  0 },
699/*0a*/	{ "or",    TRUE,  BYTE,  op2(E, R),  0 },
700/*0b*/	{ "or",    TRUE,  LONG,  op2(E, R),  0 },
701/*0c*/	{ "or",    FALSE, BYTE,  op2(I, A),  0 },
702/*0d*/	{ "or",    FALSE, LONG,  op2(I, A),  0 },
703/*0e*/	{ "push",  FALSE, NONE,  op1(Si),    0 },
704/*0f*/	{ "",      FALSE, NONE,  0,	     0 },
705
706/*10*/	{ "adc",   TRUE,  BYTE,  op2(R, E),  0 },
707/*11*/	{ "adc",   TRUE,  LONG,  op2(R, E),  0 },
708/*12*/	{ "adc",   TRUE,  BYTE,  op2(E, R),  0 },
709/*13*/	{ "adc",   TRUE,  LONG,  op2(E, R),  0 },
710/*14*/	{ "adc",   FALSE, BYTE,  op2(Is, A), 0 },
711/*15*/	{ "adc",   FALSE, LONG,  op2(Is, A), 0 },
712/*16*/	{ "push",  FALSE, NONE,  op1(Si),    0 },
713/*17*/	{ "pop",   FALSE, NONE,  op1(Si),    0 },
714
715/*18*/	{ "sbb",   TRUE,  BYTE,  op2(R, E),  0 },
716/*19*/	{ "sbb",   TRUE,  LONG,  op2(R, E),  0 },
717/*1a*/	{ "sbb",   TRUE,  BYTE,  op2(E, R),  0 },
718/*1b*/	{ "sbb",   TRUE,  LONG,  op2(E, R),  0 },
719/*1c*/	{ "sbb",   FALSE, BYTE,  op2(Is, A), 0 },
720/*1d*/	{ "sbb",   FALSE, LONG,  op2(Is, A), 0 },
721/*1e*/	{ "push",  FALSE, NONE,  op1(Si),    0 },
722/*1f*/	{ "pop",   FALSE, NONE,  op1(Si),    0 },
723
724/*20*/	{ "and",   TRUE,  BYTE,  op2(R, E),  0 },
725/*21*/	{ "and",   TRUE,  LONG,  op2(R, E),  0 },
726/*22*/	{ "and",   TRUE,  BYTE,  op2(E, R),  0 },
727/*23*/	{ "and",   TRUE,  LONG,  op2(E, R),  0 },
728/*24*/	{ "and",   FALSE, BYTE,  op2(I, A),  0 },
729/*25*/	{ "and",   FALSE, LONG,  op2(I, A),  0 },
730/*26*/	{ "",      FALSE, NONE,  0,	     0 },
731/*27*/	{ "aaa",   FALSE, NONE,  0,	     0 },
732
733/*28*/	{ "sub",   TRUE,  BYTE,  op2(R, E),  0 },
734/*29*/	{ "sub",   TRUE,  LONG,  op2(R, E),  0 },
735/*2a*/	{ "sub",   TRUE,  BYTE,  op2(E, R),  0 },
736/*2b*/	{ "sub",   TRUE,  LONG,  op2(E, R),  0 },
737/*2c*/	{ "sub",   FALSE, BYTE,  op2(Is, A), 0 },
738/*2d*/	{ "sub",   FALSE, LONG,  op2(Is, A), 0 },
739/*2e*/	{ "",      FALSE, NONE,  0,	     0 },
740/*2f*/	{ "das",   FALSE, NONE,  0,	     0 },
741
742/*30*/	{ "xor",   TRUE,  BYTE,  op2(R, E),  0 },
743/*31*/	{ "xor",   TRUE,  LONG,  op2(R, E),  0 },
744/*32*/	{ "xor",   TRUE,  BYTE,  op2(E, R),  0 },
745/*33*/	{ "xor",   TRUE,  LONG,  op2(E, R),  0 },
746/*34*/	{ "xor",   FALSE, BYTE,  op2(I, A),  0 },
747/*35*/	{ "xor",   FALSE, LONG,  op2(I, A),  0 },
748/*36*/	{ "",      FALSE, NONE,  0,	     0 },
749/*37*/	{ "daa",   FALSE, NONE,  0,	     0 },
750
751/*38*/	{ "cmp",   TRUE,  BYTE,  op2(R, E),  0 },
752/*39*/	{ "cmp",   TRUE,  LONG,  op2(R, E),  0 },
753/*3a*/	{ "cmp",   TRUE,  BYTE,  op2(E, R),  0 },
754/*3b*/	{ "cmp",   TRUE,  LONG,  op2(E, R),  0 },
755/*3c*/	{ "cmp",   FALSE, BYTE,  op2(Is, A), 0 },
756/*3d*/	{ "cmp",   FALSE, LONG,  op2(Is, A), 0 },
757/*3e*/	{ "",      FALSE, NONE,  0,	     0 },
758/*3f*/	{ "aas",   FALSE, NONE,  0,	     0 },
759
760/*40*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
761/*41*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
762/*42*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
763/*43*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
764/*44*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
765/*45*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
766/*46*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
767/*47*/	{ "inc",   FALSE, LONG,  op1(Ri),    0 },
768
769/*48*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
770/*49*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
771/*4a*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
772/*4b*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
773/*4c*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
774/*4d*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
775/*4e*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
776/*4f*/	{ "dec",   FALSE, LONG,  op1(Ri),    0 },
777
778/*50*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
779/*51*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
780/*52*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
781/*53*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
782/*54*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
783/*55*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
784/*56*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
785/*57*/	{ "push",  FALSE, LONG,  op1(Ri),    0 },
786
787/*58*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
788/*59*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
789/*5a*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
790/*5b*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
791/*5c*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
792/*5d*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
793/*5e*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
794/*5f*/	{ "pop",   FALSE, LONG,  op1(Ri),    0 },
795
796/*60*/	{ "pusha", FALSE, LONG,  0,	     0 },
797/*61*/	{ "popa",  FALSE, LONG,  0,	     0 },
798/*62*/  { "bound", TRUE,  LONG,  op2(E, R),  0 },
799/*63*/	{ "arpl",  TRUE,  NONE,  op2(Ew,Rw), 0 },
800
801/*64*/	{ "",      FALSE, NONE,  0,	     0 },
802/*65*/	{ "",      FALSE, NONE,  0,	     0 },
803/*66*/	{ "",      FALSE, NONE,  0,	     0 },
804/*67*/	{ "",      FALSE, NONE,  0,	     0 },
805
806/*68*/	{ "push",  FALSE, LONG,  op1(I),     0 },
807/*69*/  { "imul",  TRUE,  LONG,  op3(I,E,R), 0 },
808/*6a*/	{ "push",  FALSE, LONG,  op1(Ib),    0 },
809/*6b*/  { "imul",  TRUE,  LONG,  op3(Ibs,E,R),0 },
810/*6c*/	{ "ins",   FALSE, BYTE,  op2(DX, DI), 0 },
811/*6d*/	{ "ins",   FALSE, LONG,  op2(DX, DI), 0 },
812/*6e*/	{ "outs",  FALSE, BYTE,  op2(SI, DX), 0 },
813/*6f*/	{ "outs",  FALSE, LONG,  op2(SI, DX), 0 },
814
815/*70*/	{ "jo",    FALSE, NONE,  op1(Db),     0 },
816/*71*/	{ "jno",   FALSE, NONE,  op1(Db),     0 },
817/*72*/	{ "jb",    FALSE, NONE,  op1(Db),     0 },
818/*73*/	{ "jnb",   FALSE, NONE,  op1(Db),     0 },
819/*74*/	{ "jz",    FALSE, NONE,  op1(Db),     0 },
820/*75*/	{ "jnz",   FALSE, NONE,  op1(Db),     0 },
821/*76*/	{ "jbe",   FALSE, NONE,  op1(Db),     0 },
822/*77*/	{ "jnbe",  FALSE, NONE,  op1(Db),     0 },
823
824/*78*/	{ "js",    FALSE, NONE,  op1(Db),     0 },
825/*79*/	{ "jns",   FALSE, NONE,  op1(Db),     0 },
826/*7a*/	{ "jp",    FALSE, NONE,  op1(Db),     0 },
827/*7b*/	{ "jnp",   FALSE, NONE,  op1(Db),     0 },
828/*7c*/	{ "jl",    FALSE, NONE,  op1(Db),     0 },
829/*7d*/	{ "jnl",   FALSE, NONE,  op1(Db),     0 },
830/*7e*/	{ "jle",   FALSE, NONE,  op1(Db),     0 },
831/*7f*/	{ "jnle",  FALSE, NONE,  op1(Db),     0 },
832
833/*80*/  { "",	   TRUE,  BYTE,  op2(I, E),   (char *)db_Grp1 },
834/*81*/  { "",	   TRUE,  LONG,  op2(I, E),   (char *)db_Grp1 },
835/*82*/  { "",	   TRUE,  BYTE,  op2(Is,E),   (char *)db_Grp1 },
836/*83*/  { "",	   TRUE,  LONG,  op2(Ibs,E),  (char *)db_Grp1 },
837/*84*/	{ "test",  TRUE,  BYTE,  op2(R, E),   0 },
838/*85*/	{ "test",  TRUE,  LONG,  op2(R, E),   0 },
839/*86*/	{ "xchg",  TRUE,  BYTE,  op2(R, E),   0 },
840/*87*/	{ "xchg",  TRUE,  LONG,  op2(R, E),   0 },
841
842/*88*/	{ "mov",   TRUE,  BYTE,  op2(R, E),   0 },
843/*89*/	{ "mov",   TRUE,  LONG,  op2(R, E),   0 },
844/*8a*/	{ "mov",   TRUE,  BYTE,  op2(E, R),   0 },
845/*8b*/	{ "mov",   TRUE,  LONG,  op2(E, R),   0 },
846/*8c*/  { "mov",   TRUE,  NONE,  op2(S, Ew),  0 },
847/*8d*/	{ "lea",   TRUE,  LONG,  op2(E, R),   0 },
848/*8e*/	{ "mov",   TRUE,  NONE,  op2(Ew, S),  0 },
849/*8f*/	{ "pop",   TRUE,  LONG,  op1(E),      0 },
850
851/*90*/	{ "nop",   FALSE, NONE,  0,	      0 },
852/*91*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
853/*92*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
854/*93*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
855/*94*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
856/*95*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
857/*96*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
858/*97*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
859
860/*98*/	{ "cbw",   FALSE, SDEP,  0,	      "cwde" },	/* cbw/cwde */
861/*99*/	{ "cwd",   FALSE, SDEP,  0,	      "cdq"  },	/* cwd/cdq */
862/*9a*/	{ "lcall", FALSE, NONE,  op1(OS),     0 },
863/*9b*/	{ "wait",  FALSE, NONE,  0,	      0 },
864/*9c*/	{ "pushf", FALSE, LONG,  0,	      0 },
865/*9d*/	{ "popf",  FALSE, LONG,  0,	      0 },
866/*9e*/	{ "sahf",  FALSE, NONE,  0,	      0 },
867/*9f*/	{ "lahf",  FALSE, NONE,  0,	      0 },
868
869/*a0*/	{ "mov",   FALSE, BYTE,  op2(O, A),   0 },
870/*a1*/	{ "mov",   FALSE, LONG,  op2(O, A),   0 },
871/*a2*/	{ "mov",   FALSE, BYTE,  op2(A, O),   0 },
872/*a3*/	{ "mov",   FALSE, LONG,  op2(A, O),   0 },
873/*a4*/	{ "movs",  FALSE, BYTE,  op2(SI,DI),  0 },
874/*a5*/	{ "movs",  FALSE, LONG,  op2(SI,DI),  0 },
875/*a6*/	{ "cmps",  FALSE, BYTE,  op2(SI,DI),  0 },
876/*a7*/	{ "cmps",  FALSE, LONG,  op2(SI,DI),  0 },
877
878/*a8*/	{ "test",  FALSE, BYTE,  op2(I, A),   0 },
879/*a9*/	{ "test",  FALSE, LONG,  op2(I, A),   0 },
880/*aa*/	{ "stos",  FALSE, BYTE,  op1(DI),     0 },
881/*ab*/	{ "stos",  FALSE, LONG,  op1(DI),     0 },
882/*ac*/	{ "lods",  FALSE, BYTE,  op1(SI),     0 },
883/*ad*/	{ "lods",  FALSE, LONG,  op1(SI),     0 },
884/*ae*/	{ "scas",  FALSE, BYTE,  op1(SI),     0 },
885/*af*/	{ "scas",  FALSE, LONG,  op1(SI),     0 },
886
887/*b0*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
888/*b1*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
889/*b2*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
890/*b3*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
891/*b4*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
892/*b5*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
893/*b6*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
894/*b7*/	{ "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
895
896/*b8*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
897/*b9*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
898/*ba*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
899/*bb*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
900/*bc*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
901/*bd*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
902/*be*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
903/*bf*/	{ "mov",   FALSE, LONG,  op2(I, Ri),  0 },
904
905/*c0*/	{ "",	   TRUE,  BYTE,  op2(Ib, E),  (char *)db_Grp2 },
906/*c1*/	{ "",	   TRUE,  LONG,  op2(Ib, E),  (char *)db_Grp2 },
907/*c2*/	{ "ret",   FALSE, NONE,  op1(Iw),     0 },
908/*c3*/	{ "ret",   FALSE, NONE,  0,	      0 },
909/*c4*/	{ "les",   TRUE,  LONG,  op2(E, R),   0 },
910/*c5*/	{ "lds",   TRUE,  LONG,  op2(E, R),   0 },
911/*c6*/	{ "mov",   TRUE,  BYTE,  op2(I, E),   0 },
912/*c7*/	{ "mov",   TRUE,  LONG,  op2(I, E),   0 },
913
914/*c8*/	{ "enter", FALSE, NONE,  op2(Ib, Iw), 0 },
915/*c9*/	{ "leave", FALSE, NONE,  0,           0 },
916/*ca*/	{ "lret",  FALSE, NONE,  op1(Iw),     0 },
917/*cb*/	{ "lret",  FALSE, NONE,  0,	      0 },
918/*cc*/	{ "int",   FALSE, NONE,  op1(o3),     0 },
919/*cd*/	{ "int",   FALSE, NONE,  op1(Ib),     0 },
920/*ce*/	{ "into",  FALSE, NONE,  0,	      0 },
921/*cf*/	{ "iret",  FALSE, NONE,  0,	      0 },
922
923/*d0*/	{ "",	   TRUE,  BYTE,  op2(o1, E),  (char *)db_Grp2 },
924/*d1*/	{ "",	   TRUE,  LONG,  op2(o1, E),  (char *)db_Grp2 },
925/*d2*/	{ "",	   TRUE,  BYTE,  op2(CL, E),  (char *)db_Grp2 },
926/*d3*/	{ "",	   TRUE,  LONG,  op2(CL, E),  (char *)db_Grp2 },
927/*d4*/	{ "aam",   TRUE,  NONE,  0,	      0 },
928/*d5*/	{ "aad",   TRUE,  NONE,  0,	      0 },
929/*d6*/	{ "",      FALSE, NONE,  0,	      0 },
930/*d7*/	{ "xlat",  FALSE, BYTE,  op1(BX),     0 },
931
932/*d8*/  { "",      TRUE,  NONE,  0,	      (char *)db_Esc8 },
933/*d9*/  { "",      TRUE,  NONE,  0,	      (char *)db_Esc9 },
934/*da*/  { "",      TRUE,  NONE,  0,	      (char *)db_Esca },
935/*db*/  { "",      TRUE,  NONE,  0,	      (char *)db_Escb },
936/*dc*/  { "",      TRUE,  NONE,  0,	      (char *)db_Escc },
937/*dd*/  { "",      TRUE,  NONE,  0,	      (char *)db_Escd },
938/*de*/  { "",      TRUE,  NONE,  0,	      (char *)db_Esce },
939/*df*/  { "",      TRUE,  NONE,  0,	      (char *)db_Escf },
940
941/*e0*/	{ "loopne",FALSE, NONE,  op1(Db),     0 },
942/*e1*/	{ "loope", FALSE, NONE,  op1(Db),     0 },
943/*e2*/	{ "loop",  FALSE, NONE,  op1(Db),     0 },
944/*e3*/	{ "jcxz",  FALSE, SDEP,  op1(Db),     "jecxz" },
945/*e4*/	{ "in",    FALSE, BYTE,  op2(Ib, A),  0 },
946/*e5*/	{ "in",    FALSE, LONG,  op2(Ib, A) , 0 },
947/*e6*/	{ "out",   FALSE, BYTE,  op2(A, Ib),  0 },
948/*e7*/	{ "out",   FALSE, LONG,  op2(A, Ib) , 0 },
949
950/*e8*/	{ "call",  FALSE, NONE,  op1(Dl),     0 },
951/*e9*/	{ "jmp",   FALSE, NONE,  op1(Dl),     0 },
952/*ea*/	{ "ljmp",  FALSE, NONE,  op1(OS),     0 },
953/*eb*/	{ "jmp",   FALSE, NONE,  op1(Db),     0 },
954/*ec*/	{ "in",    FALSE, BYTE,  op2(DX, A),  0 },
955/*ed*/	{ "in",    FALSE, LONG,  op2(DX, A) , 0 },
956/*ee*/	{ "out",   FALSE, BYTE,  op2(A, DX),  0 },
957/*ef*/	{ "out",   FALSE, LONG,  op2(A, DX) , 0 },
958
959/*f0*/	{ "",      FALSE, NONE,  0,	     0 },
960/*f1*/	{ "",      FALSE, NONE,  0,	     0 },
961/*f2*/	{ "",      FALSE, NONE,  0,	     0 },
962/*f3*/	{ "",      FALSE, NONE,  0,	     0 },
963/*f4*/	{ "hlt",   FALSE, NONE,  0,	     0 },
964/*f5*/	{ "cmc",   FALSE, NONE,  0,	     0 },
965/*f6*/	{ "",      TRUE,  BYTE,  0,	     (char *)db_Grp3 },
966/*f7*/	{ "",	   TRUE,  LONG,  0,	     (char *)db_Grp3 },
967
968/*f8*/	{ "clc",   FALSE, NONE,  0,	     0 },
969/*f9*/	{ "stc",   FALSE, NONE,  0,	     0 },
970/*fa*/	{ "cli",   FALSE, NONE,  0,	     0 },
971/*fb*/	{ "sti",   FALSE, NONE,  0,	     0 },
972/*fc*/	{ "cld",   FALSE, NONE,  0,	     0 },
973/*fd*/	{ "std",   FALSE, NONE,  0,	     0 },
974/*fe*/	{ "",	   TRUE,  NONE,  0,	     (char *)db_Grp4 },
975/*ff*/	{ "",	   TRUE,  NONE,  0,	     (char *)db_Grp5 },
976};
977
978struct inst	db_bad_inst =
979	{ "???",   FALSE, NONE,  0,	      0 }
980;
981
982#define	f_mod(byte)	((byte)>>6)
983#define	f_reg(byte)	(((byte)>>3)&0x7)
984#define	f_rm(byte)	((byte)&0x7)
985
986#define	sib_ss(byte)	((byte)>>6)
987#define	sib_index(byte)	(((byte)>>3)&0x7)
988#define	sib_base(byte)	((byte)&0x7)
989
990char *	db_index_reg_16[8] = {
991	"%bx,%si",
992	"%bx,%di",
993	"%bp,%si",
994	"%bp,%di",
995	"%si",
996	"%di",
997	"%bp",
998	"%bx"
999};
1000
1001char *	db_reg[3][8] = {
1002	"%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh",
1003	"%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
1004	"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
1005};
1006
1007char *	db_seg_reg[8] = {
1008	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", ""
1009};
1010
1011/*
1012 * lengths for size attributes
1013 */
1014int db_lengths[] = {
1015	1,	/* BYTE */
1016	2,	/* WORD */
1017	4,	/* LONG */
1018	8,	/* QUAD */
1019	4,	/* SNGL */
1020	8,	/* DBLR */
1021	10,	/* EXTR */
1022};
1023
1024#define	get_value_inc(result, loc, size, is_signed, task) \
1025	result = db_get_task_value((loc), (size), (is_signed), (task)); \
1026	(loc) += (size);
1027
1028/*
1029 * Read address at location and return updated location.
1030 */
1031db_addr_t
1032db_read_address(
1033	db_addr_t	loc,
1034	int		short_addr,
1035	int		regmodrm,
1036	struct i_addr	*addrp,		/* out */
1037	task_t		task)
1038{
1039	int		mod, rm, sib, index, ss, disp;
1040
1041	mod = f_mod(regmodrm);
1042	rm  = f_rm(regmodrm);
1043
1044	if (mod == 3) {
1045	    addrp->is_reg = TRUE;
1046	    addrp->disp = rm;
1047	    return (loc);
1048	}
1049	addrp->is_reg = FALSE;
1050	addrp->index = 0;
1051
1052	if (short_addr) {
1053	    addrp->index = 0;
1054	    addrp->ss = 0;
1055	    switch (mod) {
1056		case 0:
1057		    if (rm == 6) {
1058			get_value_inc(disp, loc, 2, TRUE, task);
1059			addrp->disp = disp;
1060			addrp->base = 0;
1061		    }
1062		    else {
1063			addrp->disp = 0;
1064			addrp->base = db_index_reg_16[rm];
1065		    }
1066		    break;
1067		case 1:
1068		    get_value_inc(disp, loc, 1, TRUE, task);
1069		    addrp->disp = disp;
1070		    addrp->base = db_index_reg_16[rm];
1071		    break;
1072		case 2:
1073		    get_value_inc(disp, loc, 2, TRUE, task);
1074		    addrp->disp = disp;
1075		    addrp->base = db_index_reg_16[rm];
1076		    break;
1077	    }
1078	}
1079	else {
1080	    if (mod != 3 && rm == 4) {
1081		get_value_inc(sib, loc, 1, FALSE, task);
1082		rm = sib_base(sib);
1083		index = sib_index(sib);
1084		if (index != 4)
1085		    addrp->index = db_reg[LONG][index];
1086		addrp->ss = sib_ss(sib);
1087	    }
1088
1089	    switch (mod) {
1090		case 0:
1091		    if (rm == 5) {
1092			get_value_inc(addrp->disp, loc, 4, FALSE, task);
1093			addrp->base = 0;
1094		    }
1095		    else {
1096			addrp->disp = 0;
1097			addrp->base = db_reg[LONG][rm];
1098		    }
1099		    break;
1100
1101		case 1:
1102		    get_value_inc(disp, loc, 1, TRUE, task);
1103		    addrp->disp = disp;
1104		    addrp->base = db_reg[LONG][rm];
1105		    break;
1106
1107		case 2:
1108		    get_value_inc(disp, loc, 4, FALSE, task);
1109		    addrp->disp = disp;
1110		    addrp->base = db_reg[LONG][rm];
1111		    break;
1112	    }
1113	}
1114	return (loc);
1115}
1116
1117void
1118db_print_address(
1119	char *		seg,
1120	int		size,
1121	struct i_addr	*addrp,
1122	task_t		task)
1123{
1124	if (addrp->is_reg) {
1125	    db_printf("%s", db_reg[size][addrp->disp]);
1126	    return;
1127	}
1128
1129	if (seg) {
1130	    db_printf("%s:", seg);
1131	}
1132
1133	if (addrp->base != 0 || addrp->index != 0) {
1134	    db_printf("%#n", addrp->disp);
1135	    db_printf("(");
1136	    if (addrp->base)
1137		db_printf("%s", addrp->base);
1138	    if (addrp->index)
1139		db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
1140	    db_printf(")");
1141	} else
1142	    db_task_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, task);
1143}
1144
1145/*
1146 * Disassemble floating-point ("escape") instruction
1147 * and return updated location.
1148 */
1149db_addr_t
1150db_disasm_esc(
1151	db_addr_t	loc,
1152	int		inst,
1153	int		short_addr,
1154	int		size,
1155	char *		seg,
1156	task_t		task)
1157{
1158	int		regmodrm;
1159	struct finst	*fp;
1160	int		mod;
1161	struct i_addr	address;
1162	char *		name;
1163
1164	get_value_inc(regmodrm, loc, 1, FALSE, task);
1165	fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
1166	mod = f_mod(regmodrm);
1167	if (mod != 3) {
1168	    /*
1169	     * Normal address modes.
1170	     */
1171	    loc = db_read_address(loc, short_addr, regmodrm, &address, task);
1172	    db_printf(fp->f_name);
1173	    switch(fp->f_size) {
1174		case SNGL:
1175		    db_printf("s");
1176		    break;
1177		case DBLR:
1178		    db_printf("l");
1179		    break;
1180		case EXTR:
1181		    db_printf("t");
1182		    break;
1183		case WORD:
1184		    db_printf("s");
1185		    break;
1186		case LONG:
1187		    db_printf("l");
1188		    break;
1189		case QUAD:
1190		    db_printf("q");
1191		    break;
1192		default:
1193		    break;
1194	    }
1195	    db_printf("\t");
1196	    db_print_address(seg, BYTE, &address, task);
1197	}
1198	else {
1199	    /*
1200	     * 'reg-reg' - special formats
1201	     */
1202	    switch (fp->f_rrmode) {
1203		case op2(ST,STI):
1204		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1205		    db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm));
1206		    break;
1207		case op2(STI,ST):
1208		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1209		    db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm));
1210		    break;
1211		case op1(STI):
1212		    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1213		    db_printf("%s\t%%st(%d)",name, f_rm(regmodrm));
1214		    break;
1215		case op1(X):
1216		    db_printf("%s", ((char **)fp->f_rrname)[f_rm(regmodrm)]);
1217		    break;
1218		case op1(XA):
1219		    db_printf("%s\t%%ax",
1220				 ((char **)fp->f_rrname)[f_rm(regmodrm)]);
1221		    break;
1222		default:
1223		    db_printf("<bad instruction>");
1224		    break;
1225	    }
1226	}
1227
1228	return (loc);
1229}
1230
1231/*
1232 * Disassemble instruction at 'loc'.  'altfmt' specifies an
1233 * (optional) alternate format.  Return address of start of
1234 * next instruction.
1235 */
1236db_addr_t
1237db_disasm(
1238	db_addr_t	loc,
1239	boolean_t	altfmt,
1240	task_t		task)
1241{
1242	int	inst;
1243	int	size;
1244	int	short_addr;
1245	char *	seg;
1246	struct inst *	ip;
1247	char *	i_name;
1248	int	i_size;
1249	int	i_mode;
1250	int	regmodrm;
1251	boolean_t	first;
1252	int	displ;
1253	int	prefix;
1254	int	imm;
1255	int	imm2;
1256	int	len;
1257	struct i_addr	address;
1258	char	*filename;
1259	int	linenum;
1260
1261	get_value_inc(inst, loc, 1, FALSE, task);
1262	if (db_disasm_16) {
1263	    short_addr = TRUE;
1264	    size = WORD;
1265	}
1266	else {
1267	    short_addr = FALSE;
1268	    size = LONG;
1269	}
1270	seg = 0;
1271
1272	/*
1273	 * Get prefixes
1274	 */
1275	prefix = TRUE;
1276	do {
1277	    switch (inst) {
1278		case 0x66:		/* data16 */
1279		    if (size == LONG)
1280			size = WORD;
1281		    else
1282			size = LONG;
1283		    break;
1284		case 0x67:
1285		    short_addr = !short_addr;
1286		    break;
1287		case 0x26:
1288		    seg = "%es";
1289		    break;
1290		case 0x36:
1291		    seg = "%ss";
1292		    break;
1293		case 0x2e:
1294		    seg = "%cs";
1295		    break;
1296		case 0x3e:
1297		    seg = "%ds";
1298		    break;
1299		case 0x64:
1300		    seg = "%fs";
1301		    break;
1302		case 0x65:
1303		    seg = "%gs";
1304		    break;
1305		case 0xf0:
1306		    db_printf("lock ");
1307		    break;
1308		case 0xf2:
1309		    db_printf("repne ");
1310		    break;
1311		case 0xf3:
1312		    db_printf("repe ");	/* XXX repe VS rep */
1313		    break;
1314		default:
1315		    prefix = FALSE;
1316		    break;
1317	    }
1318	    if (prefix) {
1319		get_value_inc(inst, loc, 1, FALSE, task);
1320	    }
1321	} while (prefix);
1322
1323	if (inst >= 0xd8 && inst <= 0xdf) {
1324	    loc = db_disasm_esc(loc, inst, short_addr, size, seg, task);
1325	    db_printf("\n");
1326	    return (loc);
1327	}
1328
1329	if (inst == 0x0f) {
1330	    get_value_inc(inst, loc, 1, FALSE, task);
1331	    ip = db_inst_0f[inst>>4];
1332	    if (ip == 0) {
1333		ip = &db_bad_inst;
1334	    }
1335	    else {
1336		ip = &ip[inst&0xf];
1337	    }
1338	}
1339	else
1340	    ip = &db_inst_table[inst];
1341
1342	if (ip->i_has_modrm) {
1343	    get_value_inc(regmodrm, loc, 1, FALSE, task);
1344	    loc = db_read_address(loc, short_addr, regmodrm, &address, task);
1345	}
1346
1347	i_name = ip->i_name;
1348	i_size = ip->i_size;
1349	i_mode = ip->i_mode;
1350
1351	if (ip->i_extra == (char *)db_Grp1 ||
1352	    ip->i_extra == (char *)db_Grp2 ||
1353	    ip->i_extra == (char *)db_Grp6 ||
1354	    ip->i_extra == (char *)db_Grp7 ||
1355	    ip->i_extra == (char *)db_Grp8) {
1356	    i_name = ((char **)ip->i_extra)[f_reg(regmodrm)];
1357	}
1358	else if (ip->i_extra == (char *)db_Grp3) {
1359	    ip = (struct inst *)ip->i_extra;
1360	    ip = &ip[f_reg(regmodrm)];
1361	    i_name = ip->i_name;
1362	    i_mode = ip->i_mode;
1363	}
1364	else if (ip->i_extra == (char *)db_Grp4 ||
1365		 ip->i_extra == (char *)db_Grp5) {
1366	    ip = (struct inst *)ip->i_extra;
1367	    ip = &ip[f_reg(regmodrm)];
1368	    i_name = ip->i_name;
1369	    i_mode = ip->i_mode;
1370	    i_size = ip->i_size;
1371	}
1372
1373	if (i_size == SDEP) {
1374	    if (size == WORD)
1375		db_printf(i_name);
1376	    else
1377		db_printf(ip->i_extra);
1378	}
1379	else {
1380	    db_printf(i_name);
1381	    if (i_size != NONE) {
1382		if (i_size == BYTE) {
1383		    db_printf("b");
1384		    size = BYTE;
1385		}
1386		else if (i_size == WORD) {
1387		    db_printf("w");
1388		    size = WORD;
1389		}
1390		else if (size == WORD)
1391		    db_printf("w");
1392		else
1393		    db_printf("l");
1394	    }
1395	}
1396	db_printf("\t");
1397	for (first = TRUE;
1398	     i_mode != 0;
1399	     i_mode >>= 8, first = FALSE)
1400	{
1401	    if (!first)
1402		db_printf(",");
1403
1404	    switch (i_mode & 0xFF) {
1405
1406		case E:
1407		    db_print_address(seg, size, &address, task);
1408		    break;
1409
1410		case Eind:
1411		    db_printf("*");
1412		    db_print_address(seg, size, &address, task);
1413		    break;
1414
1415		case Ew:
1416		    db_print_address(seg, WORD, &address, task);
1417		    break;
1418
1419		case Eb:
1420		    db_print_address(seg, BYTE, &address, task);
1421		    break;
1422
1423		case R:
1424		    db_printf("%s", db_reg[size][f_reg(regmodrm)]);
1425		    break;
1426
1427		case Rw:
1428		    db_printf("%s", db_reg[WORD][f_reg(regmodrm)]);
1429		    break;
1430
1431		case Ri:
1432		    db_printf("%s", db_reg[size][f_rm(inst)]);
1433		    break;
1434
1435		case S:
1436		    db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
1437		    break;
1438
1439		case Si:
1440		    db_printf("%s", db_seg_reg[f_reg(inst)]);
1441		    break;
1442
1443		case A:
1444		    db_printf("%s", db_reg[size][0]);	/* acc */
1445		    break;
1446
1447		case BX:
1448		    if (seg)
1449			db_printf("%s:", seg);
1450		    db_printf("(%s)", short_addr ? "%bx" : "%ebx");
1451		    break;
1452
1453		case CL:
1454		    db_printf("%%cl");
1455		    break;
1456
1457		case DX:
1458		    db_printf("%%dx");
1459		    break;
1460
1461		case SI:
1462		    if (seg)
1463			db_printf("%s:", seg);
1464		    db_printf("(%s)", short_addr ? "%si" : "%esi");
1465		    break;
1466
1467		case DI:
1468		    db_printf("%%es:(%s)", short_addr ? "%di" : "%edi");
1469		    break;
1470
1471		case CR:
1472		    db_printf("%%cr%d", f_reg(regmodrm));
1473		    break;
1474
1475		case DR:
1476		    db_printf("%%dr%d", f_reg(regmodrm));
1477		    break;
1478
1479		case TR:
1480		    db_printf("%%tr%d", f_reg(regmodrm));
1481		    break;
1482
1483		case I:
1484		    len = db_lengths[size];
1485		    get_value_inc(imm, loc, len, FALSE, task);/* unsigned */
1486		    db_printf("$%#n", imm);
1487		    break;
1488
1489		case Is:
1490		    len = db_lengths[size];
1491		    get_value_inc(imm, loc, len, TRUE, task);	/* signed */
1492		    db_printf("$%#r", imm);
1493		    break;
1494
1495		case Ib:
1496		    get_value_inc(imm, loc, 1, FALSE, task);	/* unsigned */
1497		    db_printf("$%#n", imm);
1498		    break;
1499
1500		case Ibs:
1501		    get_value_inc(imm, loc, 1, TRUE, task);	/* signed */
1502		    db_printf("$%#r", imm);
1503		    break;
1504
1505		case Iw:
1506		    get_value_inc(imm, loc, 2, FALSE, task);	/* unsigned */
1507		    db_printf("$%#n", imm);
1508		    break;
1509
1510		case Il:
1511		    get_value_inc(imm, loc, 4, FALSE, task);
1512		    db_printf("$%#n", imm);
1513		    break;
1514
1515		case O:
1516		    if (short_addr) {
1517			get_value_inc(displ, loc, 2, TRUE, task);
1518		    }
1519		    else {
1520			get_value_inc(displ, loc, 4, TRUE, task);
1521		    }
1522		    if (seg)
1523			db_printf("%s:%#r",seg, displ);
1524		    else
1525			db_task_printsym((db_addr_t)displ, DB_STGY_ANY, task);
1526		    break;
1527
1528		case Db:
1529		    get_value_inc(displ, loc, 1, TRUE, task);
1530		    if (short_addr) {
1531			/* offset only affects low 16 bits */
1532		        displ = (loc & 0xffff0000)
1533			      | ((loc + displ) & 0xffff);
1534		    }
1535		    else
1536			displ = displ + loc;
1537		    db_task_printsym((db_addr_t)displ,DB_STGY_ANY,task);
1538		    if (db_line_at_pc(0, &filename, &linenum, displ)) {
1539			db_printf(" [%s", filename);
1540			if (linenum > 0)
1541			    db_printf(":%d", linenum);
1542			db_printf("]");
1543		    }
1544		    break;
1545
1546		case Dl:
1547		    if (short_addr) {
1548			get_value_inc(displ, loc, 2, TRUE, task);
1549			/* offset only affects low 16 bits */
1550		        displ = (loc & 0xffff0000)
1551			      | ((loc + displ) & 0xffff);
1552		    }
1553		    else {
1554			get_value_inc(displ, loc, 4, TRUE, task);
1555			displ = displ + loc;
1556		    }
1557		    db_task_printsym((db_addr_t)displ, DB_STGY_ANY, task);
1558		    if (db_line_at_pc(0, &filename, &linenum, displ)) {
1559			db_printf(" [%s", filename);
1560			if (linenum > 0)
1561			    db_printf(":%d", linenum);
1562			db_printf("]");
1563		    }
1564		    break;
1565
1566		case o1:
1567		    db_printf("$1");
1568		    break;
1569
1570		case o3:
1571		    db_printf("$3");
1572		    break;
1573
1574		case OS:
1575		    if (short_addr) {
1576			get_value_inc(imm, loc, 2, FALSE, task); /* offset */
1577		    }
1578		    else {
1579			get_value_inc(imm, loc, 4, FALSE, task); /* offset */
1580		    }
1581		    get_value_inc(imm2, loc, 2, FALSE, task);	/* segment */
1582		    db_printf("$%#n,%#n", imm2, imm);
1583		    break;
1584	    }
1585	}
1586
1587	if (altfmt == 0 && !db_disasm_16) {
1588	    if (inst == 0xe9 || inst == 0xeb) {	/* jmp, Dl or Db */
1589		/*
1590		 * GAS pads to longword boundary after unconditional jumps.
1591		 */
1592		while (loc & (4-1)) {
1593		    get_value_inc(inst, loc, 0, FALSE, task);
1594		    if (inst != 0x90)	/* nop */
1595			break;
1596		    loc++;
1597		}
1598	    }
1599	}
1600	db_printf("\n");
1601	return (loc);
1602}
1603
1604/*
1605 * Classify instructions by whether they read or write memory.
1606 */
1607
1608#define	DBLS_LOAD	0x01	/* instruction reads from memory */
1609#define	DBLS_STORE	0x02	/* instruction writes to memory */
1610
1611#define DBLS_MODRM	0x10	/* instruction uses mod r/m byte */
1612#define	DBLS_SECOND	0x20	/* instruction does two operations */
1613#define	DBLS_ESCAPE	0x40	/* escape to two-byte opcodes */
1614#define DBLS_SWREG	0x80	/* need to switch on reg bits of mod r/m */
1615
1616#define DBLS_MODS	0xf0
1617#define DBLS_LMASK	(DBLS_MODS|DBLS_LOAD)
1618#define DBLS_SMASK	(DBLS_MODS|DBLS_STORE)
1619
1620char db_ldstrtab[] = {
1621	0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01,
1622		0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x40,
1623	0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01,
1624		0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x02, 0x01,
1625	0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
1626		0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
1627	0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
1628		0x12, 0x12, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
1629
1630	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1631		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1632	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1633		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1634	0x02, 0x01, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
1635		0x02, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
1636	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1637		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1638
1639	0x12, 0x12, 0x00, 0x12, 0x11, 0x11, 0x13, 0x13,
1640		0x12, 0x12, 0x11, 0x11, 0x12, 0x00, 0x11, 0x03,
1641	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1642		0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00, 0x00,
1643	0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x21, 0x21,
1644		0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
1645	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647
1648	0x13, 0x13, 0x00, 0x00, 0x01, 0x01, 0x12, 0x12,
1649		0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650	0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x01,
1651		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653		0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x13,
1655		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x13,
1656};
1657
1658unsigned char db_ldstrtab0f[] = {
1659	0x80, 0x80, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00,
1660		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1667
1668	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1669		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1670	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1671		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1672	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1673		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1674	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1675		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1676
1677	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1678		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1679	0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
1680		0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
1681	0x02, 0x01, 0x00, 0x11, 0x13, 0x13, 0x00, 0x00,
1682		0x02, 0x01, 0x12, 0x13, 0x13, 0x13, 0x00, 0x11,
1683	0x00, 0x00, 0x01, 0x13, 0x01, 0x01, 0x11, 0x11,
1684		0x00, 0x00, 0x80, 0x13, 0x13, 0x13, 0x11, 0x11,
1685
1686	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1687		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1688	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1689		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1692	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1693		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1694};
1695
1696int db_inst_swreg(boolean_t, unsigned long, unsigned char);
1697
1698/*
1699 * Given four bytes of instruction (stored as an int, not an
1700 * array of characters), compute if the instruction reads
1701 * memory.
1702 */
1703int
1704db_inst_load(
1705	unsigned long insw)
1706{
1707	unsigned char insb, bits;
1708
1709	insb = insw & 0xff;
1710	insw >>= 8;
1711	bits = db_ldstrtab[insb];
1712	if (!(bits & DBLS_LOAD))
1713		return (0);
1714	while (1) {
1715		switch (bits & DBLS_MODS) {
1716		case 0:
1717			return (1);
1718		case DBLS_MODRM:
1719			insb = insw & 0xff;
1720			return ((insb & 0xc0) != 0xc0);
1721		case DBLS_SECOND|DBLS_MODRM:
1722			insb = insw & 0xff;
1723			return ((insb & 0xc0) != 0xc0 ? 2 : 0);
1724		case DBLS_SECOND:
1725			return (2);
1726		case DBLS_ESCAPE:
1727			insb = insw & 0xff;
1728			insw >>= 8;
1729			bits = db_ldstrtab0f[insb];
1730			break;
1731		case DBLS_SWREG:
1732			return (db_inst_swreg(TRUE, insw, insb));
1733		default:
1734			panic ("db_inst_load: unknown mod bits");
1735		}
1736	}
1737}
1738
1739/*
1740 * Given four bytes of instruction (stored as an int, not an
1741 * array of characters), compute if the instruction writes
1742 * memory.
1743 */
1744int
1745db_inst_store(
1746	unsigned long insw)
1747{
1748	unsigned char insb, bits;
1749
1750	insb = insw & 0xff;
1751	insw >>= 8;
1752	bits = db_ldstrtab[insb];
1753	if (!(bits & DBLS_STORE))
1754		return (0);
1755	while (1) {
1756		switch (bits & DBLS_MODS) {
1757		case 0:
1758			return (1);
1759		case DBLS_MODRM:
1760			insb = insw & 0xff;
1761			return ((insb & 0xc0) != 0xc0);
1762		case DBLS_SECOND|DBLS_MODRM:
1763			insb = insw & 0xff;
1764			return ((insb & 0xc0) != 0xc0 ? 2 : 0);
1765		case DBLS_SECOND:
1766			return (2);
1767		case DBLS_ESCAPE:
1768			insb = insw & 0xff;
1769			insw >>= 8;
1770			bits = db_ldstrtab0f[insb];
1771			break;
1772		case DBLS_SWREG:
1773			return (db_inst_swreg(FALSE, insw, insb));
1774		default:
1775			panic ("db_inst_store: unknown mod bits");
1776		}
1777	}
1778}
1779
1780/*
1781 * Parse a mod r/m byte to see if extended opcode reads
1782 * or writes memory.
1783 */
1784int
1785db_inst_swreg(
1786	boolean_t isload,
1787	unsigned long insw,
1788	unsigned char insb)
1789{
1790	unsigned char modrm = insw & 0xff;
1791
1792	switch (insb) {
1793	case 0x00:
1794		switch (modrm & 0x38) {
1795		case 0x00:
1796		case 0x08:
1797		case 0x10:
1798		case 0x18:
1799			return ((modrm & 0xc0) != 0xc0);
1800		}
1801		break;
1802	case 0x01:
1803		switch (modrm & 0x38) {
1804		case 0x00:
1805		case 0x08:
1806		case 0x10:
1807		case 0x18:
1808			return ((modrm & 0xc0) != 0xc0 ? 2 : 0);
1809		case 0x20:
1810		case 0x30:
1811			return ((modrm & 0xc0) != 0xc0);
1812		}
1813		break;
1814	case 0xba:
1815		if (isload)
1816			return ((modrm & 0xc0) != 0xc0);
1817		switch (modrm & 0x38) {
1818		case 0x28:
1819		case 0x30:
1820		case 0x38:
1821			return ((modrm & 0xc0) != 0xc0);
1822		}
1823		break;
1824	}
1825	return (0);
1826}
1827