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