FreeBSD/Linux Kernel Cross Reference
sys/i386/db_disasm.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_disasm.c,v $
29 * Revision 2.6 92/01/03 20:05:00 dbg
30 * Add a switch to disassemble 16-bit code.
31 * Fix spelling of 'lods' opcodes.
32 * [91/10/30 dbg]
33 *
34 * Revision 2.5 91/10/09 16:05:58 af
35 * Supported disassemble of non current task by passing task parameter.
36 * [91/08/29 tak]
37 *
38 * Revision 2.4 91/05/14 16:05:04 mrt
39 * Correcting copyright
40 *
41 * Revision 2.3 91/02/05 17:11:03 mrt
42 * Changed to new Mach copyright
43 * [91/02/01 17:31:03 mrt]
44 *
45 * Revision 2.2 90/08/27 21:55:56 dbg
46 * Fix register operand for move to/from control/test/debug
47 * register instructions. Add i486 instructions.
48 * [90/08/27 dbg]
49 *
50 * Import db_sym.h. Print instruction displacements in
51 * current radix (signed). Change calling sequence of
52 * db_disasm.
53 * [90/08/21 dbg]
54 * Fix includes.
55 * [90/08/08 dbg]
56 * Created.
57 * [90/07/25 dbg]
58 *
59 */
60
61 /*
62 * Instruction disassembler.
63 */
64 #include <mach/boolean.h>
65 #include <machine/db_machdep.h>
66
67 #include <ddb/db_access.h>
68 #include <ddb/db_sym.h>
69
70 #include <kern/task.h>
71
72 /*
73 * Switch to disassemble 16-bit code.
74 */
75 boolean_t db_disasm_16 = FALSE;
76
77 /*
78 * Size attributes
79 */
80 #define BYTE 0
81 #define WORD 1
82 #define LONG 2
83 #define QUAD 3
84 #define SNGL 4
85 #define DBLR 5
86 #define EXTR 6
87 #define SDEP 7
88 #define NONE 8
89
90 /*
91 * Addressing modes
92 */
93 #define E 1 /* general effective address */
94 #define Eind 2 /* indirect address (jump, call) */
95 #define Ew 3 /* address, word size */
96 #define Eb 4 /* address, byte size */
97 #define R 5 /* register, in 'reg' field */
98 #define Rw 6 /* word register, in 'reg' field */
99 #define Ri 7 /* register in instruction */
100 #define S 8 /* segment reg, in 'reg' field */
101 #define Si 9 /* segment reg, in instruction */
102 #define A 10 /* accumulator */
103 #define BX 11 /* (bx) */
104 #define CL 12 /* cl, for shifts */
105 #define DX 13 /* dx, for IO */
106 #define SI 14 /* si */
107 #define DI 15 /* di */
108 #define CR 16 /* control register */
109 #define DR 17 /* debug register */
110 #define TR 18 /* test register */
111 #define I 19 /* immediate, unsigned */
112 #define Is 20 /* immediate, signed */
113 #define Ib 21 /* byte immediate, unsigned */
114 #define Ibs 22 /* byte immediate, signed */
115 #define Iw 23 /* word immediate, unsigned */
116 #define Il 24 /* long immediate */
117 #define O 25 /* direct address */
118 #define Db 26 /* byte displacement from EIP */
119 #define Dl 27 /* long displacement from EIP */
120 #define o1 28 /* constant 1 */
121 #define o3 29 /* constant 3 */
122 #define OS 30 /* immediate offset/segment */
123 #define ST 31 /* FP stack top */
124 #define STI 32 /* FP stack */
125 #define X 33 /* extended FP op */
126 #define XA 34 /* for 'fstcw %ax' */
127
128 struct inst {
129 char * i_name; /* name */
130 short i_has_modrm; /* has regmodrm byte */
131 short i_size; /* operand size */
132 int i_mode; /* addressing modes */
133 char * i_extra; /* pointer to extra opcode table */
134 };
135
136 #define op1(x) (x)
137 #define op2(x,y) ((x)|((y)<<8))
138 #define op3(x,y,z) ((x)|((y)<<8)|((z)<<16))
139
140 struct finst {
141 char * f_name; /* name for memory instruction */
142 int f_size; /* size for memory instruction */
143 int f_rrmode; /* mode for rr instruction */
144 char * f_rrname; /* name for rr instruction
145 (or pointer to table) */
146 };
147
148 char * db_Grp6[] = {
149 "sldt",
150 "str",
151 "lldt",
152 "ltr",
153 "verr",
154 "verw",
155 "",
156 ""
157 };
158
159 char * db_Grp7[] = {
160 "sgdt",
161 "sidt",
162 "lgdt",
163 "lidt",
164 "smsw",
165 "",
166 "lmsw",
167 "invlpg"
168 };
169
170 char * db_Grp8[] = {
171 "",
172 "",
173 "",
174 "",
175 "bt",
176 "bts",
177 "btr",
178 "btc"
179 };
180
181 struct inst db_inst_0f0x[] = {
182 /*00*/ { "", TRUE, NONE, op1(Ew), (char *)db_Grp6 },
183 /*01*/ { "", TRUE, NONE, op1(Ew), (char *)db_Grp7 },
184 /*02*/ { "lar", TRUE, LONG, op2(E,R), 0 },
185 /*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 },
186 /*04*/ { "", FALSE, NONE, 0, 0 },
187 /*05*/ { "", FALSE, NONE, 0, 0 },
188 /*06*/ { "clts", FALSE, NONE, 0, 0 },
189 /*07*/ { "", FALSE, NONE, 0, 0 },
190
191 /*08*/ { "invd", FALSE, NONE, 0, 0 },
192 /*09*/ { "wbinvd",FALSE, NONE, 0, 0 },
193 /*0a*/ { "", FALSE, NONE, 0, 0 },
194 /*0b*/ { "", FALSE, NONE, 0, 0 },
195 /*0c*/ { "", FALSE, NONE, 0, 0 },
196 /*0d*/ { "", FALSE, NONE, 0, 0 },
197 /*0e*/ { "", FALSE, NONE, 0, 0 },
198 /*0f*/ { "", FALSE, NONE, 0, 0 },
199 };
200
201 struct inst db_inst_0f2x[] = {
202 /*20*/ { "mov", TRUE, LONG, op2(CR,E), 0 }, /* use E for reg */
203 /*21*/ { "mov", TRUE, LONG, op2(DR,E), 0 }, /* since mod == 11 */
204 /*22*/ { "mov", TRUE, LONG, op2(E,CR), 0 },
205 /*23*/ { "mov", TRUE, LONG, op2(E,DR), 0 },
206 /*24*/ { "mov", TRUE, LONG, op2(TR,E), 0 },
207 /*25*/ { "", FALSE, NONE, 0, 0 },
208 /*26*/ { "mov", TRUE, LONG, op2(E,TR), 0 },
209 /*27*/ { "", FALSE, NONE, 0, 0 },
210
211 /*28*/ { "", FALSE, NONE, 0, 0 },
212 /*29*/ { "", FALSE, NONE, 0, 0 },
213 /*2a*/ { "", FALSE, NONE, 0, 0 },
214 /*2b*/ { "", FALSE, NONE, 0, 0 },
215 /*2c*/ { "", FALSE, NONE, 0, 0 },
216 /*2d*/ { "", FALSE, NONE, 0, 0 },
217 /*2e*/ { "", FALSE, NONE, 0, 0 },
218 /*2f*/ { "", FALSE, NONE, 0, 0 },
219 };
220
221 struct inst db_inst_0f8x[] = {
222 /*80*/ { "jo", FALSE, NONE, op1(Dl), 0 },
223 /*81*/ { "jno", FALSE, NONE, op1(Dl), 0 },
224 /*82*/ { "jb", FALSE, NONE, op1(Dl), 0 },
225 /*83*/ { "jnb", FALSE, NONE, op1(Dl), 0 },
226 /*84*/ { "jz", FALSE, NONE, op1(Dl), 0 },
227 /*85*/ { "jnz", FALSE, NONE, op1(Dl), 0 },
228 /*86*/ { "jbe", FALSE, NONE, op1(Dl), 0 },
229 /*87*/ { "jnbe", FALSE, NONE, op1(Dl), 0 },
230
231 /*88*/ { "js", FALSE, NONE, op1(Dl), 0 },
232 /*89*/ { "jns", FALSE, NONE, op1(Dl), 0 },
233 /*8a*/ { "jp", FALSE, NONE, op1(Dl), 0 },
234 /*8b*/ { "jnp", FALSE, NONE, op1(Dl), 0 },
235 /*8c*/ { "jl", FALSE, NONE, op1(Dl), 0 },
236 /*8d*/ { "jnl", FALSE, NONE, op1(Dl), 0 },
237 /*8e*/ { "jle", FALSE, NONE, op1(Dl), 0 },
238 /*8f*/ { "jnle", FALSE, NONE, op1(Dl), 0 },
239 };
240
241 struct inst db_inst_0f9x[] = {
242 /*90*/ { "seto", TRUE, NONE, op1(Eb), 0 },
243 /*91*/ { "setno", TRUE, NONE, op1(Eb), 0 },
244 /*92*/ { "setb", TRUE, NONE, op1(Eb), 0 },
245 /*93*/ { "setnb", TRUE, NONE, op1(Eb), 0 },
246 /*94*/ { "setz", TRUE, NONE, op1(Eb), 0 },
247 /*95*/ { "setnz", TRUE, NONE, op1(Eb), 0 },
248 /*96*/ { "setbe", TRUE, NONE, op1(Eb), 0 },
249 /*97*/ { "setnbe",TRUE, NONE, op1(Eb), 0 },
250
251 /*98*/ { "sets", TRUE, NONE, op1(Eb), 0 },
252 /*99*/ { "setns", TRUE, NONE, op1(Eb), 0 },
253 /*9a*/ { "setp", TRUE, NONE, op1(Eb), 0 },
254 /*9b*/ { "setnp", TRUE, NONE, op1(Eb), 0 },
255 /*9c*/ { "setl", TRUE, NONE, op1(Eb), 0 },
256 /*9d*/ { "setnl", TRUE, NONE, op1(Eb), 0 },
257 /*9e*/ { "setle", TRUE, NONE, op1(Eb), 0 },
258 /*9f*/ { "setnle",TRUE, NONE, op1(Eb), 0 },
259 };
260
261 struct inst db_inst_0fax[] = {
262 /*a0*/ { "push", FALSE, NONE, op1(Si), 0 },
263 /*a1*/ { "pop", FALSE, NONE, op1(Si), 0 },
264 /*a2*/ { "", FALSE, NONE, 0, 0 },
265 /*a3*/ { "bt", TRUE, LONG, op2(E,R), 0 },
266 /*a4*/ { "shld", TRUE, LONG, op3(Ib,E,R), 0 },
267 /*a5*/ { "shld", TRUE, LONG, op3(CL,E,R), 0 },
268 /*a6*/ { "", FALSE, NONE, 0, 0 },
269 /*a7*/ { "", FALSE, NONE, 0, 0 },
270
271 /*a8*/ { "push", FALSE, NONE, op1(Si), 0 },
272 /*a9*/ { "pop", FALSE, NONE, op1(Si), 0 },
273 /*aa*/ { "", FALSE, NONE, 0, 0 },
274 /*ab*/ { "bts", TRUE, LONG, op2(E,R), 0 },
275 /*ac*/ { "shrd", TRUE, LONG, op3(Ib,E,R), 0 },
276 /*ad*/ { "shrd", TRUE, LONG, op3(CL,E,R), 0 },
277 /*a6*/ { "", FALSE, NONE, 0, 0 },
278 /*a7*/ { "imul", TRUE, LONG, op2(E,R), 0 },
279 };
280
281 struct inst db_inst_0fbx[] = {
282 /*b0*/ { "", FALSE, NONE, 0, 0 },
283 /*b1*/ { "", FALSE, NONE, 0, 0 },
284 /*b2*/ { "lss", TRUE, LONG, op2(E, R), 0 },
285 /*b3*/ { "bts", TRUE, LONG, op2(R, E), 0 },
286 /*b4*/ { "lfs", TRUE, LONG, op2(E, R), 0 },
287 /*b5*/ { "lgs", TRUE, LONG, op2(E, R), 0 },
288 /*b6*/ { "movzb", TRUE, LONG, op2(E, R), 0 },
289 /*b7*/ { "movzw", TRUE, LONG, op2(E, R), 0 },
290
291 /*b8*/ { "", FALSE, NONE, 0, 0 },
292 /*b9*/ { "", FALSE, NONE, 0, 0 },
293 /*ba*/ { "", TRUE, LONG, op2(Is, E), (char *)db_Grp8 },
294 /*bb*/ { "btc", TRUE, LONG, op2(R, E), 0 },
295 /*bc*/ { "bsf", TRUE, LONG, op2(E, R), 0 },
296 /*bd*/ { "bsr", TRUE, LONG, op2(E, R), 0 },
297 /*be*/ { "movsb", TRUE, LONG, op2(E, R), 0 },
298 /*bf*/ { "movsw", TRUE, LONG, op2(E, R), 0 },
299 };
300
301 struct inst db_inst_0fcx[] = {
302 /*c0*/ { "xadd", TRUE, BYTE, op2(R, E), 0 },
303 /*c1*/ { "xadd", TRUE, LONG, op2(R, E), 0 },
304 /*c2*/ { "", FALSE, NONE, 0, 0 },
305 /*c3*/ { "", FALSE, NONE, 0, 0 },
306 /*c4*/ { "", FALSE, NONE, 0, 0 },
307 /*c5*/ { "", FALSE, NONE, 0, 0 },
308 /*c6*/ { "", FALSE, NONE, 0, 0 },
309 /*c7*/ { "", FALSE, NONE, 0, 0 },
310 /*c8*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
311 /*c9*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
312 /*ca*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
313 /*cb*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
314 /*cc*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
315 /*cd*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
316 /*ce*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
317 /*cf*/ { "bswap", FALSE, LONG, op1(Ri), 0 },
318 };
319
320 struct inst db_inst_0fdx[] = {
321 /*c0*/ { "cmpxchg",TRUE, BYTE, op2(R, E), 0 },
322 /*c1*/ { "cmpxchg",TRUE, LONG, op2(R, E), 0 },
323 /*c2*/ { "", FALSE, NONE, 0, 0 },
324 /*c3*/ { "", FALSE, NONE, 0, 0 },
325 /*c4*/ { "", FALSE, NONE, 0, 0 },
326 /*c5*/ { "", FALSE, NONE, 0, 0 },
327 /*c6*/ { "", FALSE, NONE, 0, 0 },
328 /*c7*/ { "", FALSE, NONE, 0, 0 },
329 /*c8*/ { "", FALSE, NONE, 0, 0 },
330 /*c9*/ { "", FALSE, NONE, 0, 0 },
331 /*ca*/ { "", FALSE, NONE, 0, 0 },
332 /*cb*/ { "", FALSE, NONE, 0, 0 },
333 /*cc*/ { "", FALSE, NONE, 0, 0 },
334 /*cd*/ { "", FALSE, NONE, 0, 0 },
335 /*ce*/ { "", FALSE, NONE, 0, 0 },
336 /*cf*/ { "", FALSE, NONE, 0, 0 },
337 };
338
339 struct inst *db_inst_0f[] = {
340 db_inst_0f0x,
341 0,
342 db_inst_0f2x,
343 0,
344 0,
345 0,
346 0,
347 0,
348 db_inst_0f8x,
349 db_inst_0f9x,
350 db_inst_0fax,
351 db_inst_0fbx,
352 db_inst_0fcx,
353 db_inst_0fdx,
354 0,
355 0
356 };
357
358 char * db_Esc92[] = {
359 "fnop", "", "", "", "", "", "", ""
360 };
361 char * db_Esc93[] = {
362 "", "", "", "", "", "", "", ""
363 };
364 char * db_Esc94[] = {
365 "fchs", "fabs", "", "", "ftst", "fxam", "", ""
366 };
367 char * db_Esc95[] = {
368 "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz",""
369 };
370 char * db_Esc96[] = {
371 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp",
372 "fincstp"
373 };
374 char * db_Esc97[] = {
375 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"
376 };
377
378 char * db_Esca4[] = {
379 "", "fucompp","", "", "", "", "", ""
380 };
381
382 char * db_Escb4[] = {
383 "", "", "fnclex","fninit","", "", "", ""
384 };
385
386 char * db_Esce3[] = {
387 "", "fcompp","", "", "", "", "", ""
388 };
389
390 char * db_Escf4[] = {
391 "fnstsw","", "", "", "", "", "", ""
392 };
393
394 struct finst db_Esc8[] = {
395 /**/ { "fadd", SNGL, op2(STI,ST), 0 },
396 /*1*/ { "fmul", SNGL, op2(STI,ST), 0 },
397 /*2*/ { "fcom", SNGL, op2(STI,ST), 0 },
398 /*3*/ { "fcomp", SNGL, op2(STI,ST), 0 },
399 /*4*/ { "fsub", SNGL, op2(STI,ST), 0 },
400 /*5*/ { "fsubr", SNGL, op2(STI,ST), 0 },
401 /*6*/ { "fdiv", SNGL, op2(STI,ST), 0 },
402 /*7*/ { "fdivr", SNGL, op2(STI,ST), 0 },
403 };
404
405 struct finst db_Esc9[] = {
406 /**/ { "fld", SNGL, op1(STI), 0 },
407 /*1*/ { "", NONE, op1(STI), "fxch" },
408 /*2*/ { "fst", SNGL, op1(X), (char *)db_Esc92 },
409 /*3*/ { "fstp", SNGL, op1(X), (char *)db_Esc93 },
410 /*4*/ { "fldenv", NONE, op1(X), (char *)db_Esc94 },
411 /*5*/ { "fldcw", NONE, op1(X), (char *)db_Esc95 },
412 /*6*/ { "fnstenv",NONE, op1(X), (char *)db_Esc96 },
413 /*7*/ { "fnstcw", NONE, op1(X), (char *)db_Esc97 },
414 };
415
416 struct finst db_Esca[] = {
417 /**/ { "fiadd", WORD, 0, 0 },
418 /*1*/ { "fimul", WORD, 0, 0 },
419 /*2*/ { "ficom", WORD, 0, 0 },
420 /*3*/ { "ficomp", WORD, 0, 0 },
421 /*4*/ { "fisub", WORD, op1(X), (char *)db_Esca4 },
422 /*5*/ { "fisubr", WORD, 0, 0 },
423 /*6*/ { "fidiv", WORD, 0, 0 },
424 /*7*/ { "fidivr", WORD, 0, 0 }
425 };
426
427 struct finst db_Escb[] = {
428 /**/ { "fild", WORD, 0, 0 },
429 /*1*/ { "", NONE, 0, 0 },
430 /*2*/ { "fist", WORD, 0, 0 },
431 /*3*/ { "fistp", WORD, 0, 0 },
432 /*4*/ { "", WORD, op1(X), (char *)db_Escb4 },
433 /*5*/ { "fld", EXTR, 0, 0 },
434 /*6*/ { "", WORD, 0, 0 },
435 /*7*/ { "fstp", EXTR, 0, 0 },
436 };
437
438 struct finst db_Escc[] = {
439 /**/ { "fadd", DBLR, op2(ST,STI), 0 },
440 /*1*/ { "fmul", DBLR, op2(ST,STI), 0 },
441 /*2*/ { "fcom", DBLR, op2(ST,STI), 0 },
442 /*3*/ { "fcomp", DBLR, op2(ST,STI), 0 },
443 /*4*/ { "fsub", DBLR, op2(ST,STI), "fsubr" },
444 /*5*/ { "fsubr", DBLR, op2(ST,STI), "fsub" },
445 /*6*/ { "fdiv", DBLR, op2(ST,STI), "fdivr" },
446 /*7*/ { "fdivr", DBLR, op2(ST,STI), "fdiv" },
447 };
448
449 struct finst db_Escd[] = {
450 /**/ { "fld", DBLR, op1(STI), "ffree" },
451 /*1*/ { "", NONE, 0, 0 },
452 /*2*/ { "fst", DBLR, op1(STI), 0 },
453 /*3*/ { "fstp", DBLR, op1(STI), 0 },
454 /*4*/ { "frstor", NONE, op1(STI), "fucom" },
455 /*5*/ { "", NONE, op1(STI), "fucomp" },
456 /*6*/ { "fnsave", NONE, 0, 0 },
457 /*7*/ { "fnstsw", NONE, 0, 0 },
458 };
459
460 struct finst db_Esce[] = {
461 /**/ { "fiadd", LONG, op2(ST,STI), "faddp" },
462 /*1*/ { "fimul", LONG, op2(ST,STI), "fmulp" },
463 /*2*/ { "ficom", LONG, 0, 0 },
464 /*3*/ { "ficomp", LONG, op1(X), (char *)db_Esce3 },
465 /*4*/ { "fisub", LONG, op2(ST,STI), "fsubrp" },
466 /*5*/ { "fisubr", LONG, op2(ST,STI), "fsubp" },
467 /*6*/ { "fidiv", LONG, op2(ST,STI), "fdivrp" },
468 /*7*/ { "fidivr", LONG, op2(ST,STI), "fdivp" },
469 };
470
471 struct finst db_Escf[] = {
472 /**/ { "fild", LONG, 0, 0 },
473 /*1*/ { "", LONG, 0, 0 },
474 /*2*/ { "fist", LONG, 0, 0 },
475 /*3*/ { "fistp", LONG, 0, 0 },
476 /*4*/ { "fbld", NONE, op1(XA), (char *)db_Escf4 },
477 /*5*/ { "fld", QUAD, 0, 0 },
478 /*6*/ { "fbstp", NONE, 0, 0 },
479 /*7*/ { "fstp", QUAD, 0, 0 },
480 };
481
482 struct finst *db_Esc_inst[] = {
483 db_Esc8, db_Esc9, db_Esca, db_Escb,
484 db_Escc, db_Escd, db_Esce, db_Escf
485 };
486
487 char * db_Grp1[] = {
488 "add",
489 "or",
490 "adc",
491 "sbb",
492 "and",
493 "sub",
494 "xor",
495 "cmp"
496 };
497
498 char * db_Grp2[] = {
499 "rol",
500 "ror",
501 "rcl",
502 "rcr",
503 "shl",
504 "shr",
505 "shl",
506 "sar"
507 };
508
509 struct inst db_Grp3[] = {
510 { "test", TRUE, NONE, op2(I,E), 0 },
511 { "test", TRUE, NONE, op2(I,E), 0 },
512 { "not", TRUE, NONE, op1(E), 0 },
513 { "neg", TRUE, NONE, op1(E), 0 },
514 { "mul", TRUE, NONE, op2(E,A), 0 },
515 { "imul", TRUE, NONE, op2(E,A), 0 },
516 { "div", TRUE, NONE, op2(E,A), 0 },
517 { "idiv", TRUE, NONE, op2(E,A), 0 },
518 };
519
520 struct inst db_Grp4[] = {
521 { "inc", TRUE, BYTE, op1(E), 0 },
522 { "dec", TRUE, BYTE, op1(E), 0 },
523 { "", TRUE, NONE, 0, 0 },
524 { "", TRUE, NONE, 0, 0 },
525 { "", TRUE, NONE, 0, 0 },
526 { "", TRUE, NONE, 0, 0 },
527 { "", TRUE, NONE, 0, 0 },
528 { "", TRUE, NONE, 0, 0 }
529 };
530
531 struct inst db_Grp5[] = {
532 { "inc", TRUE, LONG, op1(E), 0 },
533 { "dec", TRUE, LONG, op1(E), 0 },
534 { "call", TRUE, NONE, op1(Eind),0 },
535 { "lcall", TRUE, NONE, op1(Eind),0 },
536 { "jmp", TRUE, NONE, op1(Eind),0 },
537 { "ljmp", TRUE, NONE, op1(Eind),0 },
538 { "push", TRUE, LONG, op1(E), 0 },
539 { "", TRUE, NONE, 0, 0 }
540 };
541
542 struct inst db_inst_table[256] = {
543 /*00*/ { "add", TRUE, BYTE, op2(R, E), 0 },
544 /*01*/ { "add", TRUE, LONG, op2(R, E), 0 },
545 /*02*/ { "add", TRUE, BYTE, op2(E, R), 0 },
546 /*03*/ { "add", TRUE, LONG, op2(E, R), 0 },
547 /*04*/ { "add", FALSE, BYTE, op2(Is, A), 0 },
548 /*05*/ { "add", FALSE, LONG, op2(Is, A), 0 },
549 /*06*/ { "push", FALSE, NONE, op1(Si), 0 },
550 /*07*/ { "pop", FALSE, NONE, op1(Si), 0 },
551
552 /*08*/ { "or", TRUE, BYTE, op2(R, E), 0 },
553 /*09*/ { "or", TRUE, LONG, op2(R, E), 0 },
554 /*0a*/ { "or", TRUE, BYTE, op2(E, R), 0 },
555 /*0b*/ { "or", TRUE, LONG, op2(E, R), 0 },
556 /*0c*/ { "or", FALSE, BYTE, op2(I, A), 0 },
557 /*0d*/ { "or", FALSE, LONG, op2(I, A), 0 },
558 /*0e*/ { "push", FALSE, NONE, op1(Si), 0 },
559 /*0f*/ { "", FALSE, NONE, 0, 0 },
560
561 /*10*/ { "adc", TRUE, BYTE, op2(R, E), 0 },
562 /*11*/ { "adc", TRUE, LONG, op2(R, E), 0 },
563 /*12*/ { "adc", TRUE, BYTE, op2(E, R), 0 },
564 /*13*/ { "adc", TRUE, LONG, op2(E, R), 0 },
565 /*14*/ { "adc", FALSE, BYTE, op2(Is, A), 0 },
566 /*15*/ { "adc", FALSE, LONG, op2(Is, A), 0 },
567 /*16*/ { "push", FALSE, NONE, op1(Si), 0 },
568 /*17*/ { "pop", FALSE, NONE, op1(Si), 0 },
569
570 /*18*/ { "sbb", TRUE, BYTE, op2(R, E), 0 },
571 /*19*/ { "sbb", TRUE, LONG, op2(R, E), 0 },
572 /*1a*/ { "sbb", TRUE, BYTE, op2(E, R), 0 },
573 /*1b*/ { "sbb", TRUE, LONG, op2(E, R), 0 },
574 /*1c*/ { "sbb", FALSE, BYTE, op2(Is, A), 0 },
575 /*1d*/ { "sbb", FALSE, LONG, op2(Is, A), 0 },
576 /*1e*/ { "push", FALSE, NONE, op1(Si), 0 },
577 /*1f*/ { "pop", FALSE, NONE, op1(Si), 0 },
578
579 /*20*/ { "and", TRUE, BYTE, op2(R, E), 0 },
580 /*21*/ { "and", TRUE, LONG, op2(R, E), 0 },
581 /*22*/ { "and", TRUE, BYTE, op2(E, R), 0 },
582 /*23*/ { "and", TRUE, LONG, op2(E, R), 0 },
583 /*24*/ { "and", FALSE, BYTE, op2(I, A), 0 },
584 /*25*/ { "and", FALSE, LONG, op2(I, A), 0 },
585 /*26*/ { "", FALSE, NONE, 0, 0 },
586 /*27*/ { "aaa", FALSE, NONE, 0, 0 },
587
588 /*28*/ { "sub", TRUE, BYTE, op2(R, E), 0 },
589 /*29*/ { "sub", TRUE, LONG, op2(R, E), 0 },
590 /*2a*/ { "sub", TRUE, BYTE, op2(E, R), 0 },
591 /*2b*/ { "sub", TRUE, LONG, op2(E, R), 0 },
592 /*2c*/ { "sub", FALSE, BYTE, op2(Is, A), 0 },
593 /*2d*/ { "sub", FALSE, LONG, op2(Is, A), 0 },
594 /*2e*/ { "", FALSE, NONE, 0, 0 },
595 /*2f*/ { "das", FALSE, NONE, 0, 0 },
596
597 /*30*/ { "xor", TRUE, BYTE, op2(R, E), 0 },
598 /*31*/ { "xor", TRUE, LONG, op2(R, E), 0 },
599 /*32*/ { "xor", TRUE, BYTE, op2(E, R), 0 },
600 /*33*/ { "xor", TRUE, LONG, op2(E, R), 0 },
601 /*34*/ { "xor", FALSE, BYTE, op2(I, A), 0 },
602 /*35*/ { "xor", FALSE, LONG, op2(I, A), 0 },
603 /*36*/ { "", FALSE, NONE, 0, 0 },
604 /*37*/ { "daa", FALSE, NONE, 0, 0 },
605
606 /*38*/ { "cmp", TRUE, BYTE, op2(R, E), 0 },
607 /*39*/ { "cmp", TRUE, LONG, op2(R, E), 0 },
608 /*3a*/ { "cmp", TRUE, BYTE, op2(E, R), 0 },
609 /*3b*/ { "cmp", TRUE, LONG, op2(E, R), 0 },
610 /*3c*/ { "cmp", FALSE, BYTE, op2(Is, A), 0 },
611 /*3d*/ { "cmp", FALSE, LONG, op2(Is, A), 0 },
612 /*3e*/ { "", FALSE, NONE, 0, 0 },
613 /*3f*/ { "aas", FALSE, NONE, 0, 0 },
614
615 /*40*/ { "inc", FALSE, LONG, op1(Ri), 0 },
616 /*41*/ { "inc", FALSE, LONG, op1(Ri), 0 },
617 /*42*/ { "inc", FALSE, LONG, op1(Ri), 0 },
618 /*43*/ { "inc", FALSE, LONG, op1(Ri), 0 },
619 /*44*/ { "inc", FALSE, LONG, op1(Ri), 0 },
620 /*45*/ { "inc", FALSE, LONG, op1(Ri), 0 },
621 /*46*/ { "inc", FALSE, LONG, op1(Ri), 0 },
622 /*47*/ { "inc", FALSE, LONG, op1(Ri), 0 },
623
624 /*48*/ { "dec", FALSE, LONG, op1(Ri), 0 },
625 /*49*/ { "dec", FALSE, LONG, op1(Ri), 0 },
626 /*4a*/ { "dec", FALSE, LONG, op1(Ri), 0 },
627 /*4b*/ { "dec", FALSE, LONG, op1(Ri), 0 },
628 /*4c*/ { "dec", FALSE, LONG, op1(Ri), 0 },
629 /*4d*/ { "dec", FALSE, LONG, op1(Ri), 0 },
630 /*4e*/ { "dec", FALSE, LONG, op1(Ri), 0 },
631 /*4f*/ { "dec", FALSE, LONG, op1(Ri), 0 },
632
633 /*50*/ { "push", FALSE, LONG, op1(Ri), 0 },
634 /*51*/ { "push", FALSE, LONG, op1(Ri), 0 },
635 /*52*/ { "push", FALSE, LONG, op1(Ri), 0 },
636 /*53*/ { "push", FALSE, LONG, op1(Ri), 0 },
637 /*54*/ { "push", FALSE, LONG, op1(Ri), 0 },
638 /*55*/ { "push", FALSE, LONG, op1(Ri), 0 },
639 /*56*/ { "push", FALSE, LONG, op1(Ri), 0 },
640 /*57*/ { "push", FALSE, LONG, op1(Ri), 0 },
641
642 /*58*/ { "pop", FALSE, LONG, op1(Ri), 0 },
643 /*59*/ { "pop", FALSE, LONG, op1(Ri), 0 },
644 /*5a*/ { "pop", FALSE, LONG, op1(Ri), 0 },
645 /*5b*/ { "pop", FALSE, LONG, op1(Ri), 0 },
646 /*5c*/ { "pop", FALSE, LONG, op1(Ri), 0 },
647 /*5d*/ { "pop", FALSE, LONG, op1(Ri), 0 },
648 /*5e*/ { "pop", FALSE, LONG, op1(Ri), 0 },
649 /*5f*/ { "pop", FALSE, LONG, op1(Ri), 0 },
650
651 /*60*/ { "pusha", FALSE, LONG, 0, 0 },
652 /*61*/ { "popa", FALSE, LONG, 0, 0 },
653 /*62*/ { "bound", TRUE, LONG, op2(E, R), 0 },
654 /*63*/ { "arpl", TRUE, NONE, op2(Ew,Rw), 0 },
655
656 /*64*/ { "", FALSE, NONE, 0, 0 },
657 /*65*/ { "", FALSE, NONE, 0, 0 },
658 /*66*/ { "", FALSE, NONE, 0, 0 },
659 /*67*/ { "", FALSE, NONE, 0, 0 },
660
661 /*68*/ { "push", FALSE, LONG, op1(I), 0 },
662 /*69*/ { "imul", TRUE, LONG, op3(I,E,R), 0 },
663 /*6a*/ { "push", FALSE, LONG, op1(Ib), 0 },
664 /*6b*/ { "imul", TRUE, LONG, op3(Ibs,E,R),0 },
665 /*6c*/ { "ins", FALSE, BYTE, op2(DX, DI), 0 },
666 /*6d*/ { "ins", FALSE, LONG, op2(DX, DI), 0 },
667 /*6e*/ { "outs", FALSE, BYTE, op2(SI, DX), 0 },
668 /*6f*/ { "outs", FALSE, LONG, op2(SI, DX), 0 },
669
670 /*70*/ { "jo", FALSE, NONE, op1(Db), 0 },
671 /*71*/ { "jno", FALSE, NONE, op1(Db), 0 },
672 /*72*/ { "jb", FALSE, NONE, op1(Db), 0 },
673 /*73*/ { "jnb", FALSE, NONE, op1(Db), 0 },
674 /*74*/ { "jz", FALSE, NONE, op1(Db), 0 },
675 /*75*/ { "jnz", FALSE, NONE, op1(Db), 0 },
676 /*76*/ { "jbe", FALSE, NONE, op1(Db), 0 },
677 /*77*/ { "jnbe", FALSE, NONE, op1(Db), 0 },
678
679 /*78*/ { "js", FALSE, NONE, op1(Db), 0 },
680 /*79*/ { "jns", FALSE, NONE, op1(Db), 0 },
681 /*7a*/ { "jp", FALSE, NONE, op1(Db), 0 },
682 /*7b*/ { "jnp", FALSE, NONE, op1(Db), 0 },
683 /*7c*/ { "jl", FALSE, NONE, op1(Db), 0 },
684 /*7d*/ { "jnl", FALSE, NONE, op1(Db), 0 },
685 /*7e*/ { "jle", FALSE, NONE, op1(Db), 0 },
686 /*7f*/ { "jnle", FALSE, NONE, op1(Db), 0 },
687
688 /*80*/ { "", TRUE, BYTE, op2(I, E), (char *)db_Grp1 },
689 /*81*/ { "", TRUE, LONG, op2(I, E), (char *)db_Grp1 },
690 /*82*/ { "", TRUE, BYTE, op2(Is,E), (char *)db_Grp1 },
691 /*83*/ { "", TRUE, LONG, op2(Ibs,E), (char *)db_Grp1 },
692 /*84*/ { "test", TRUE, BYTE, op2(R, E), 0 },
693 /*85*/ { "test", TRUE, LONG, op2(R, E), 0 },
694 /*86*/ { "xchg", TRUE, BYTE, op2(R, E), 0 },
695 /*87*/ { "xchg", TRUE, LONG, op2(R, E), 0 },
696
697 /*88*/ { "mov", TRUE, BYTE, op2(R, E), 0 },
698 /*89*/ { "mov", TRUE, LONG, op2(R, E), 0 },
699 /*8a*/ { "mov", TRUE, BYTE, op2(E, R), 0 },
700 /*8b*/ { "mov", TRUE, LONG, op2(E, R), 0 },
701 /*8c*/ { "mov", TRUE, NONE, op2(S, Ew), 0 },
702 /*8d*/ { "lea", TRUE, LONG, op2(E, R), 0 },
703 /*8e*/ { "mov", TRUE, NONE, op2(Ew, S), 0 },
704 /*8f*/ { "pop", TRUE, LONG, op1(E), 0 },
705
706 /*90*/ { "nop", FALSE, NONE, 0, 0 },
707 /*91*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
708 /*92*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
709 /*93*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
710 /*94*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
711 /*95*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
712 /*96*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
713 /*97*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 },
714
715 /*98*/ { "cbw", FALSE, SDEP, 0, "cwde" }, /* cbw/cwde */
716 /*99*/ { "cwd", FALSE, SDEP, 0, "cdq" }, /* cwd/cdq */
717 /*9a*/ { "lcall", FALSE, NONE, op1(OS), 0 },
718 /*9b*/ { "wait", FALSE, NONE, 0, 0 },
719 /*9c*/ { "pushf", FALSE, LONG, 0, 0 },
720 /*9d*/ { "popf", FALSE, LONG, 0, 0 },
721 /*9e*/ { "sahf", FALSE, NONE, 0, 0 },
722 /*9f*/ { "lahf", FALSE, NONE, 0, 0 },
723
724 /*a0*/ { "mov", FALSE, BYTE, op2(O, A), 0 },
725 /*a1*/ { "mov", FALSE, LONG, op2(O, A), 0 },
726 /*a2*/ { "mov", FALSE, BYTE, op2(A, O), 0 },
727 /*a3*/ { "mov", FALSE, LONG, op2(A, O), 0 },
728 /*a4*/ { "movs", FALSE, BYTE, op2(SI,DI), 0 },
729 /*a5*/ { "movs", FALSE, LONG, op2(SI,DI), 0 },
730 /*a6*/ { "cmps", FALSE, BYTE, op2(SI,DI), 0 },
731 /*a7*/ { "cmps", FALSE, LONG, op2(SI,DI), 0 },
732
733 /*a8*/ { "test", FALSE, BYTE, op2(I, A), 0 },
734 /*a9*/ { "test", FALSE, LONG, op2(I, A), 0 },
735 /*aa*/ { "stos", FALSE, BYTE, op1(DI), 0 },
736 /*ab*/ { "stos", FALSE, LONG, op1(DI), 0 },
737 /*ac*/ { "lods", FALSE, BYTE, op1(SI), 0 },
738 /*ad*/ { "lods", FALSE, LONG, op1(SI), 0 },
739 /*ae*/ { "scas", FALSE, BYTE, op1(SI), 0 },
740 /*af*/ { "scas", FALSE, LONG, op1(SI), 0 },
741
742 /*b0*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
743 /*b1*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
744 /*b2*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
745 /*b3*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
746 /*b4*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
747 /*b5*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
748 /*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
749 /*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
750
751 /*b8*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
752 /*b9*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
753 /*ba*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
754 /*bb*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
755 /*bc*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
756 /*bd*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
757 /*be*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
758 /*bf*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
759
760 /*c0*/ { "", TRUE, BYTE, op2(Ib, E), (char *)db_Grp2 },
761 /*c1*/ { "", TRUE, LONG, op2(Ib, E), (char *)db_Grp2 },
762 /*c2*/ { "ret", FALSE, NONE, op1(Iw), 0 },
763 /*c3*/ { "ret", FALSE, NONE, 0, 0 },
764 /*c4*/ { "les", TRUE, LONG, op2(E, R), 0 },
765 /*c5*/ { "lds", TRUE, LONG, op2(E, R), 0 },
766 /*c6*/ { "mov", TRUE, BYTE, op2(I, E), 0 },
767 /*c7*/ { "mov", TRUE, LONG, op2(I, E), 0 },
768
769 /*c8*/ { "enter", FALSE, NONE, op2(Ib, Iw), 0 },
770 /*c9*/ { "leave", FALSE, NONE, 0, 0 },
771 /*ca*/ { "lret", FALSE, NONE, op1(Iw), 0 },
772 /*cb*/ { "lret", FALSE, NONE, 0, 0 },
773 /*cc*/ { "int", FALSE, NONE, op1(o3), 0 },
774 /*cd*/ { "int", FALSE, NONE, op1(Ib), 0 },
775 /*ce*/ { "into", FALSE, NONE, 0, 0 },
776 /*cf*/ { "iret", FALSE, NONE, 0, 0 },
777
778 /*d0*/ { "", TRUE, BYTE, op2(o1, E), (char *)db_Grp2 },
779 /*d1*/ { "", TRUE, LONG, op2(o1, E), (char *)db_Grp2 },
780 /*d2*/ { "", TRUE, BYTE, op2(CL, E), (char *)db_Grp2 },
781 /*d3*/ { "", TRUE, LONG, op2(CL, E), (char *)db_Grp2 },
782 /*d4*/ { "aam", TRUE, NONE, 0, 0 },
783 /*d5*/ { "aad", TRUE, NONE, 0, 0 },
784 /*d6*/ { "", FALSE, NONE, 0, 0 },
785 /*d7*/ { "xlat", FALSE, BYTE, op1(BX), 0 },
786
787 /*d8*/ { "", TRUE, NONE, 0, (char *)db_Esc8 },
788 /*d9*/ { "", TRUE, NONE, 0, (char *)db_Esc9 },
789 /*da*/ { "", TRUE, NONE, 0, (char *)db_Esca },
790 /*db*/ { "", TRUE, NONE, 0, (char *)db_Escb },
791 /*dc*/ { "", TRUE, NONE, 0, (char *)db_Escc },
792 /*dd*/ { "", TRUE, NONE, 0, (char *)db_Escd },
793 /*de*/ { "", TRUE, NONE, 0, (char *)db_Esce },
794 /*df*/ { "", TRUE, NONE, 0, (char *)db_Escf },
795
796 /*e0*/ { "loopne",FALSE, NONE, op1(Db), 0 },
797 /*e1*/ { "loope", FALSE, NONE, op1(Db), 0 },
798 /*e2*/ { "loop", FALSE, NONE, op1(Db), 0 },
799 /*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz" },
800 /*e4*/ { "in", FALSE, BYTE, op2(Ib, A), 0 },
801 /*e5*/ { "in", FALSE, LONG, op2(Ib, A) , 0 },
802 /*e6*/ { "out", FALSE, BYTE, op2(A, Ib), 0 },
803 /*e7*/ { "out", FALSE, LONG, op2(A, Ib) , 0 },
804
805 /*e8*/ { "call", FALSE, NONE, op1(Dl), 0 },
806 /*e9*/ { "jmp", FALSE, NONE, op1(Dl), 0 },
807 /*ea*/ { "ljmp", FALSE, NONE, op1(OS), 0 },
808 /*eb*/ { "jmp", FALSE, NONE, op1(Db), 0 },
809 /*ec*/ { "in", FALSE, BYTE, op2(DX, A), 0 },
810 /*ed*/ { "in", FALSE, LONG, op2(DX, A) , 0 },
811 /*ee*/ { "out", FALSE, BYTE, op2(A, DX), 0 },
812 /*ef*/ { "out", FALSE, LONG, op2(A, DX) , 0 },
813
814 /*f0*/ { "", FALSE, NONE, 0, 0 },
815 /*f1*/ { "", FALSE, NONE, 0, 0 },
816 /*f2*/ { "", FALSE, NONE, 0, 0 },
817 /*f3*/ { "", FALSE, NONE, 0, 0 },
818 /*f4*/ { "hlt", FALSE, NONE, 0, 0 },
819 /*f5*/ { "cmc", FALSE, NONE, 0, 0 },
820 /*f6*/ { "", TRUE, BYTE, 0, (char *)db_Grp3 },
821 /*f7*/ { "", TRUE, LONG, 0, (char *)db_Grp3 },
822
823 /*f8*/ { "clc", FALSE, NONE, 0, 0 },
824 /*f9*/ { "stc", FALSE, NONE, 0, 0 },
825 /*fa*/ { "cli", FALSE, NONE, 0, 0 },
826 /*fb*/ { "sti", FALSE, NONE, 0, 0 },
827 /*fc*/ { "cld", FALSE, NONE, 0, 0 },
828 /*fd*/ { "std", FALSE, NONE, 0, 0 },
829 /*fe*/ { "", TRUE, NONE, 0, (char *)db_Grp4 },
830 /*ff*/ { "", TRUE, NONE, 0, (char *)db_Grp5 },
831 };
832
833 struct inst db_bad_inst =
834 { "???", FALSE, NONE, 0, 0 }
835 ;
836
837 #define f_mod(byte) ((byte)>>6)
838 #define f_reg(byte) (((byte)>>3)&0x7)
839 #define f_rm(byte) ((byte)&0x7)
840
841 #define sib_ss(byte) ((byte)>>6)
842 #define sib_index(byte) (((byte)>>3)&0x7)
843 #define sib_base(byte) ((byte)&0x7)
844
845 struct i_addr {
846 int is_reg; /* if reg, reg number is in 'disp' */
847 int disp;
848 char * base;
849 char * index;
850 int ss;
851 };
852
853 char * db_index_reg_16[8] = {
854 "%bx,%si",
855 "%bx,%di",
856 "%bp,%si",
857 "%bp,%di",
858 "%si",
859 "%di",
860 "%bp",
861 "%bx"
862 };
863
864 char * db_reg[3][8] = {
865 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
866 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
867 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
868 };
869
870 char * db_seg_reg[8] = {
871 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", ""
872 };
873
874 /*
875 * lengths for size attributes
876 */
877 int db_lengths[] = {
878 1, /* BYTE */
879 2, /* WORD */
880 4, /* LONG */
881 8, /* QUAD */
882 4, /* SNGL */
883 8, /* DBLR */
884 10, /* EXTR */
885 };
886
887 #define get_value_inc(result, loc, size, is_signed, task) \
888 result = db_get_task_value((loc), (size), (is_signed), (task)); \
889 (loc) += (size);
890
891 /*
892 * Read address at location and return updated location.
893 */
894 db_addr_t
895 db_read_address(loc, short_addr, regmodrm, addrp, task)
896 db_addr_t loc;
897 int short_addr;
898 int regmodrm;
899 struct i_addr *addrp; /* out */
900 task_t task;
901 {
902 int mod, rm, sib, index, ss, disp;
903
904 mod = f_mod(regmodrm);
905 rm = f_rm(regmodrm);
906
907 if (mod == 3) {
908 addrp->is_reg = TRUE;
909 addrp->disp = rm;
910 return (loc);
911 }
912 addrp->is_reg = FALSE;
913 addrp->index = 0;
914
915 if (short_addr) {
916 addrp->index = 0;
917 addrp->ss = 0;
918 switch (mod) {
919 case 0:
920 if (rm == 6) {
921 get_value_inc(disp, loc, 2, TRUE, task);
922 addrp->disp = disp;
923 addrp->base = 0;
924 }
925 else {
926 addrp->disp = 0;
927 addrp->base = db_index_reg_16[rm];
928 }
929 break;
930 case 1:
931 get_value_inc(disp, loc, 1, TRUE, task);
932 addrp->disp = disp;
933 addrp->base = db_index_reg_16[rm];
934 break;
935 case 2:
936 get_value_inc(disp, loc, 2, TRUE, task);
937 addrp->disp = disp;
938 addrp->base = db_index_reg_16[rm];
939 break;
940 }
941 }
942 else {
943 if (mod != 3 && rm == 4) {
944 get_value_inc(sib, loc, 1, FALSE, task);
945 rm = sib_base(sib);
946 index = sib_index(sib);
947 if (index != 4)
948 addrp->index = db_reg[LONG][index];
949 addrp->ss = sib_ss(sib);
950 }
951
952 switch (mod) {
953 case 0:
954 if (rm == 5) {
955 get_value_inc(addrp->disp, loc, 4, FALSE, task);
956 addrp->base = 0;
957 }
958 else {
959 addrp->disp = 0;
960 addrp->base = db_reg[LONG][rm];
961 }
962 break;
963
964 case 1:
965 get_value_inc(disp, loc, 1, TRUE, task);
966 addrp->disp = disp;
967 addrp->base = db_reg[LONG][rm];
968 break;
969
970 case 2:
971 get_value_inc(disp, loc, 4, FALSE, task);
972 addrp->disp = disp;
973 addrp->base = db_reg[LONG][rm];
974 break;
975 }
976 }
977 return (loc);
978 }
979
980 void
981 db_print_address(seg, size, addrp, task)
982 char * seg;
983 int size;
984 struct i_addr *addrp;
985 task_t task;
986 {
987 if (addrp->is_reg) {
988 db_printf("%s", db_reg[size][addrp->disp]);
989 return;
990 }
991
992 if (seg) {
993 db_printf("%s:", seg);
994 }
995
996 if (addrp->base != 0 || addrp->index != 0) {
997 db_printf("%#n", addrp->disp);
998 db_printf("(");
999 if (addrp->base)
1000 db_printf("%s", addrp->base);
1001 if (addrp->index)
1002 db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
1003 db_printf(")");
1004 } else
1005 db_task_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, task);
1006 }
1007
1008 /*
1009 * Disassemble floating-point ("escape") instruction
1010 * and return updated location.
1011 */
1012 db_addr_t
1013 db_disasm_esc(loc, inst, short_addr, size, seg, task)
1014 db_addr_t loc;
1015 int inst;
1016 int short_addr;
1017 int size;
1018 char * seg;
1019 task_t task;
1020 {
1021 int regmodrm;
1022 struct finst *fp;
1023 int mod;
1024 struct i_addr address;
1025 char * name;
1026
1027 get_value_inc(regmodrm, loc, 1, FALSE, task);
1028 fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
1029 mod = f_mod(regmodrm);
1030 if (mod != 3) {
1031 /*
1032 * Normal address modes.
1033 */
1034 loc = db_read_address(loc, short_addr, regmodrm, &address, task);
1035 db_printf(fp->f_name);
1036 switch(fp->f_size) {
1037 case SNGL:
1038 db_printf("s");
1039 break;
1040 case DBLR:
1041 db_printf("l");
1042 break;
1043 case EXTR:
1044 db_printf("t");
1045 break;
1046 case WORD:
1047 db_printf("s");
1048 break;
1049 case LONG:
1050 db_printf("l");
1051 break;
1052 case QUAD:
1053 db_printf("q");
1054 break;
1055 default:
1056 break;
1057 }
1058 db_printf("\t");
1059 db_print_address(seg, BYTE, &address, task);
1060 }
1061 else {
1062 /*
1063 * 'reg-reg' - special formats
1064 */
1065 switch (fp->f_rrmode) {
1066 case op2(ST,STI):
1067 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1068 db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm));
1069 break;
1070 case op2(STI,ST):
1071 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1072 db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm));
1073 break;
1074 case op1(STI):
1075 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
1076 db_printf("%s\t%%st(%d)",name, f_rm(regmodrm));
1077 break;
1078 case op1(X):
1079 db_printf("%s", ((char **)fp->f_rrname)[f_rm(regmodrm)]);
1080 break;
1081 case op1(XA):
1082 db_printf("%s\t%%ax",
1083 ((char **)fp->f_rrname)[f_rm(regmodrm)]);
1084 break;
1085 default:
1086 db_printf("<bad instruction>");
1087 break;
1088 }
1089 }
1090
1091 return (loc);
1092 }
1093
1094 /*
1095 * Disassemble instruction at 'loc'. 'altfmt' specifies an
1096 * (optional) alternate format. Return address of start of
1097 * next instruction.
1098 */
1099 db_addr_t
1100 db_disasm(loc, altfmt, task)
1101 db_addr_t loc;
1102 boolean_t altfmt;
1103 task_t task;
1104 {
1105 int inst;
1106 int size;
1107 int short_addr;
1108 char * seg;
1109 struct inst * ip;
1110 char * i_name;
1111 int i_size;
1112 int i_mode;
1113 int regmodrm;
1114 boolean_t first;
1115 int displ;
1116 int prefix;
1117 int imm;
1118 int imm2;
1119 int len;
1120 struct i_addr address;
1121
1122 get_value_inc(inst, loc, 1, FALSE, task);
1123 if (db_disasm_16) {
1124 short_addr = TRUE;
1125 size = WORD;
1126 }
1127 else {
1128 short_addr = FALSE;
1129 size = LONG;
1130 }
1131 seg = 0;
1132
1133 /*
1134 * Get prefixes
1135 */
1136 prefix = TRUE;
1137 do {
1138 switch (inst) {
1139 case 0x66: /* data16 */
1140 if (size == LONG)
1141 size = WORD;
1142 else
1143 size = LONG;
1144 break;
1145 case 0x67:
1146 short_addr = !short_addr;
1147 break;
1148 case 0x26:
1149 seg = "%es";
1150 break;
1151 case 0x36:
1152 seg = "%ss";
1153 break;
1154 case 0x2e:
1155 seg = "%cs";
1156 break;
1157 case 0x3e:
1158 seg = "%ds";
1159 break;
1160 case 0x64:
1161 seg = "%fs";
1162 break;
1163 case 0x65:
1164 seg = "%gs";
1165 break;
1166 case 0xf0:
1167 db_printf("lock ");
1168 break;
1169 case 0xf2:
1170 db_printf("repne ");
1171 break;
1172 case 0xf3:
1173 db_printf("repe "); /* XXX repe VS rep */
1174 break;
1175 default:
1176 prefix = FALSE;
1177 break;
1178 }
1179 if (prefix) {
1180 get_value_inc(inst, loc, 1, FALSE, task);
1181 }
1182 } while (prefix);
1183
1184 if (inst >= 0xd8 && inst <= 0xdf) {
1185 loc = db_disasm_esc(loc, inst, short_addr, size, seg, task);
1186 db_printf("\n");
1187 return (loc);
1188 }
1189
1190 if (inst == 0x0f) {
1191 get_value_inc(inst, loc, 1, FALSE, task);
1192 ip = db_inst_0f[inst>>4];
1193 if (ip == 0) {
1194 ip = &db_bad_inst;
1195 }
1196 else {
1197 ip = &ip[inst&0xf];
1198 }
1199 }
1200 else
1201 ip = &db_inst_table[inst];
1202
1203 if (ip->i_has_modrm) {
1204 get_value_inc(regmodrm, loc, 1, FALSE, task);
1205 loc = db_read_address(loc, short_addr, regmodrm, &address, task);
1206 }
1207
1208 i_name = ip->i_name;
1209 i_size = ip->i_size;
1210 i_mode = ip->i_mode;
1211
1212 if (ip->i_extra == (char *)db_Grp1 ||
1213 ip->i_extra == (char *)db_Grp2 ||
1214 ip->i_extra == (char *)db_Grp6 ||
1215 ip->i_extra == (char *)db_Grp7 ||
1216 ip->i_extra == (char *)db_Grp8) {
1217 i_name = ((char **)ip->i_extra)[f_reg(regmodrm)];
1218 }
1219 else if (ip->i_extra == (char *)db_Grp3) {
1220 ip = (struct inst *)ip->i_extra;
1221 ip = &ip[f_reg(regmodrm)];
1222 i_name = ip->i_name;
1223 i_mode = ip->i_mode;
1224 }
1225 else if (ip->i_extra == (char *)db_Grp4 ||
1226 ip->i_extra == (char *)db_Grp5) {
1227 ip = (struct inst *)ip->i_extra;
1228 ip = &ip[f_reg(regmodrm)];
1229 i_name = ip->i_name;
1230 i_mode = ip->i_mode;
1231 i_size = ip->i_size;
1232 }
1233
1234 if (i_size == SDEP) {
1235 if (size == WORD)
1236 db_printf(i_name);
1237 else
1238 db_printf(ip->i_extra);
1239 }
1240 else {
1241 db_printf(i_name);
1242 if (i_size != NONE) {
1243 if (i_size == BYTE) {
1244 db_printf("b");
1245 size = BYTE;
1246 }
1247 else if (i_size == WORD) {
1248 db_printf("w");
1249 size = WORD;
1250 }
1251 else if (size == WORD)
1252 db_printf("w");
1253 else
1254 db_printf("l");
1255 }
1256 }
1257 db_printf("\t");
1258 for (first = TRUE;
1259 i_mode != 0;
1260 i_mode >>= 8, first = FALSE)
1261 {
1262 if (!first)
1263 db_printf(",");
1264
1265 switch (i_mode & 0xFF) {
1266
1267 case E:
1268 db_print_address(seg, size, &address, task);
1269 break;
1270
1271 case Eind:
1272 db_printf("*");
1273 db_print_address(seg, size, &address, task);
1274 break;
1275
1276 case Ew:
1277 db_print_address(seg, WORD, &address, task);
1278 break;
1279
1280 case Eb:
1281 db_print_address(seg, BYTE, &address, task);
1282 break;
1283
1284 case R:
1285 db_printf("%s", db_reg[size][f_reg(regmodrm)]);
1286 break;
1287
1288 case Rw:
1289 db_printf("%s", db_reg[WORD][f_reg(regmodrm)]);
1290 break;
1291
1292 case Ri:
1293 db_printf("%s", db_reg[size][f_rm(inst)]);
1294 break;
1295
1296 case S:
1297 db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
1298 break;
1299
1300 case Si:
1301 db_printf("%s", db_seg_reg[f_reg(inst)]);
1302 break;
1303
1304 case A:
1305 db_printf("%s", db_reg[size][0]); /* acc */
1306 break;
1307
1308 case BX:
1309 if (seg)
1310 db_printf("%s:", seg);
1311 db_printf("(%s)", short_addr ? "%bx" : "%ebx");
1312 break;
1313
1314 case CL:
1315 db_printf("%%cl");
1316 break;
1317
1318 case DX:
1319 db_printf("%%dx");
1320 break;
1321
1322 case SI:
1323 if (seg)
1324 db_printf("%s:", seg);
1325 db_printf("(%s)", short_addr ? "%si" : "%esi");
1326 break;
1327
1328 case DI:
1329 db_printf("%%es:(%s)", short_addr ? "%di" : "%edi");
1330 break;
1331
1332 case CR:
1333 db_printf("%%cr%d", f_reg(regmodrm));
1334 break;
1335
1336 case DR:
1337 db_printf("%%dr%d", f_reg(regmodrm));
1338 break;
1339
1340 case TR:
1341 db_printf("%%tr%d", f_reg(regmodrm));
1342 break;
1343
1344 case I:
1345 len = db_lengths[size];
1346 get_value_inc(imm, loc, len, FALSE, task);/* unsigned */
1347 db_printf("$%#n", imm);
1348 break;
1349
1350 case Is:
1351 len = db_lengths[size];
1352 get_value_inc(imm, loc, len, TRUE, task); /* signed */
1353 db_printf("$%#r", imm);
1354 break;
1355
1356 case Ib:
1357 get_value_inc(imm, loc, 1, FALSE, task); /* unsigned */
1358 db_printf("$%#n", imm);
1359 break;
1360
1361 case Ibs:
1362 get_value_inc(imm, loc, 1, TRUE, task); /* signed */
1363 db_printf("$%#r", imm);
1364 break;
1365
1366 case Iw:
1367 get_value_inc(imm, loc, 2, FALSE, task); /* unsigned */
1368 db_printf("$%#n", imm);
1369 break;
1370
1371 case Il:
1372 get_value_inc(imm, loc, 4, FALSE, task);
1373 db_printf("$%#n", imm);
1374 break;
1375
1376 case O:
1377 if (short_addr) {
1378 get_value_inc(displ, loc, 2, TRUE, task);
1379 }
1380 else {
1381 get_value_inc(displ, loc, 4, TRUE, task);
1382 }
1383 if (seg)
1384 db_printf("%s:%#r",seg, displ);
1385 else
1386 db_task_printsym((db_addr_t)displ, DB_STGY_ANY, task);
1387 break;
1388
1389 case Db:
1390 get_value_inc(displ, loc, 1, TRUE, task);
1391 if (short_addr) {
1392 /* offset only affects low 16 bits */
1393 displ = (loc & 0xffff0000)
1394 | ((loc + displ) & 0xffff);
1395 }
1396 else
1397 displ = displ + loc;
1398 db_task_printsym((db_addr_t)displ,DB_STGY_XTRN,task);
1399 break;
1400
1401 case Dl:
1402 if (short_addr) {
1403 get_value_inc(displ, loc, 2, TRUE, task);
1404 /* offset only affects low 16 bits */
1405 displ = (loc & 0xffff0000)
1406 | ((loc + displ) & 0xffff);
1407 }
1408 else {
1409 get_value_inc(displ, loc, 4, TRUE, task);
1410 displ = displ + loc;
1411 }
1412 db_task_printsym((db_addr_t)displ, DB_STGY_XTRN, task);
1413 break;
1414
1415 case o1:
1416 db_printf("$1");
1417 break;
1418
1419 case o3:
1420 db_printf("$3");
1421 break;
1422
1423 case OS:
1424 if (short_addr) {
1425 get_value_inc(imm, loc, 2, FALSE, task); /* offset */
1426 }
1427 else {
1428 get_value_inc(imm, loc, 4, FALSE, task); /* offset */
1429 }
1430 get_value_inc(imm2, loc, 2, FALSE, task); /* segment */
1431 db_printf("$%#n,%#n", imm2, imm);
1432 break;
1433 }
1434 }
1435
1436 if (altfmt == 0 && !db_disasm_16) {
1437 if (inst == 0xe9 || inst == 0xeb) {
1438 /*
1439 * GAS pads to longword boundary after unconditional jumps.
1440 */
1441 loc = (loc + (4-1)) & ~(4-1);
1442 }
1443 }
1444 db_printf("\n");
1445 return (loc);
1446 }
1447
Cache object: 1084b68c9f6abd9b95dd6ee7c3deaf10
|