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