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