]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/db_disasm.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / osfmk / i386 / db_disasm.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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}