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