Annotation of sys/arch/i386/i386/db_disasm.c, Revision 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