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