db_disasm.c revision 115683
11590Srgrimes/* 21590Srgrimes * Mach Operating System 31590Srgrimes * Copyright (c) 1991,1990 Carnegie Mellon University 41590Srgrimes * All Rights Reserved. 51590Srgrimes * 61590Srgrimes * Permission to use, copy, modify and distribute this software and its 71590Srgrimes * documentation is hereby granted, provided that both the copyright 81590Srgrimes * notice and this permission notice appear in all copies of the 91590Srgrimes * software, derivative works or modified versions, and any portions 101590Srgrimes * thereof, and that both notices appear in supporting documentation. 111590Srgrimes * 121590Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 131590Srgrimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 141590Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 151590Srgrimes * 161590Srgrimes * Carnegie Mellon requests users of this software to return to 171590Srgrimes * 181590Srgrimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 191590Srgrimes * School of Computer Science 201590Srgrimes * Carnegie Mellon University 211590Srgrimes * Pittsburgh PA 15213-3890 221590Srgrimes * 231590Srgrimes * any improvements or extensions that they make and grant Carnegie the 241590Srgrimes * rights to redistribute these changes. 251590Srgrimes * 261590Srgrimes */ 271590Srgrimes 281590Srgrimes#include <sys/cdefs.h> 291590Srgrimes__FBSDID("$FreeBSD: head/sys/i386/i386/db_disasm.c 115683 2003-06-02 06:43:15Z obrien $"); 301590Srgrimes 311590Srgrimes/* 321590Srgrimes * Instruction disassembler. 331590Srgrimes */ 341590Srgrimes#include <sys/param.h> 3574769Smikeh 361590Srgrimes#include <ddb/ddb.h> 3774769Smikeh#include <ddb/db_access.h> 3874769Smikeh#include <ddb/db_sym.h> 3974769Smikeh 401590Srgrimes/* 411590Srgrimes * Size attributes 421590Srgrimes */ 431590Srgrimes#define BYTE 0 441590Srgrimes#define WORD 1 451590Srgrimes#define LONG 2 461590Srgrimes#define QUAD 3 471590Srgrimes#define SNGL 4 481590Srgrimes#define DBLR 5 491590Srgrimes#define EXTR 6 501590Srgrimes#define SDEP 7 511590Srgrimes#define NONE 8 521590Srgrimes 531590Srgrimes/* 541590Srgrimes * Addressing modes 551590Srgrimes */ 561590Srgrimes#define E 1 /* general effective address */ 5777274Smikeh#define Eind 2 /* indirect address (jump, call) */ 5877274Smikeh#define Ew 3 /* address, word size */ 591590Srgrimes#define Eb 4 /* address, byte size */ 601590Srgrimes#define R 5 /* register, in 'reg' field */ 611590Srgrimes#define Rw 6 /* word register, in 'reg' field */ 621590Srgrimes#define Ri 7 /* register in instruction */ 631590Srgrimes#define S 8 /* segment reg, in 'reg' field */ 6477274Smikeh#define Si 9 /* segment reg, in instruction */ 651590Srgrimes#define A 10 /* accumulator */ 6677274Smikeh#define BX 11 /* (bx) */ 6777274Smikeh#define CL 12 /* cl, for shifts */ 681590Srgrimes#define DX 13 /* dx, for IO */ 691590Srgrimes#define SI 14 /* si */ 701590Srgrimes#define DI 15 /* di */ 711590Srgrimes#define CR 16 /* control register */ 7274769Smikeh#define DR 17 /* debug register */ 731590Srgrimes#define TR 18 /* test register */ 741590Srgrimes#define I 19 /* immediate, unsigned */ 7574769Smikeh#define Is 20 /* immediate, signed */ 7674769Smikeh#define Ib 21 /* byte immediate, unsigned */ 7774769Smikeh#define Ibs 22 /* byte immediate, signed */ 7877274Smikeh#define Iw 23 /* word immediate, unsigned */ 791590Srgrimes#define O 25 /* direct address */ 801590Srgrimes#define Db 26 /* byte displacement from EIP */ 811590Srgrimes#define Dl 27 /* long displacement from EIP */ 821590Srgrimes#define o1 28 /* constant 1 */ 831590Srgrimes#define o3 29 /* constant 3 */ 841590Srgrimes#define OS 30 /* immediate offset/segment */ 851590Srgrimes#define ST 31 /* FP stack top */ 861590Srgrimes#define STI 32 /* FP stack */ 871590Srgrimes#define X 33 /* extended FP op */ 881590Srgrimes#define XA 34 /* for 'fstcw %ax' */ 891590Srgrimes#define El 35 /* address, long size */ 9074769Smikeh#define Ril 36 /* long register in instruction */ 9174769Smikeh#define Iba 37 /* byte immediate, don't print if 0xa */ 9274769Smikeh 931590Srgrimesstruct inst { 941590Srgrimes const char * i_name; /* name */ 951590Srgrimes short i_has_modrm; /* has regmodrm byte */ 961590Srgrimes short i_size; /* operand size */ 9776455Smikeh int i_mode; /* addressing modes */ 9876455Smikeh const void * i_extra; /* pointer to extra opcode table */ 9976455Smikeh}; 10076455Smikeh 10176455Smikeh#define op1(x) (x) 10276455Smikeh#define op2(x,y) ((x)|((y)<<8)) 10376455Smikeh#define op3(x,y,z) ((x)|((y)<<8)|((z)<<16)) 10476455Smikeh 10576455Smikehstruct finst { 10676455Smikeh const char * f_name; /* name for memory instruction */ 10777274Smikeh int f_size; /* size for memory instruction */ 10874769Smikeh int f_rrmode; /* mode for rr instruction */ 10974769Smikeh const void * f_rrname; /* name for rr instruction 11074769Smikeh (or pointer to table) */ 11174769Smikeh}; 1121590Srgrimes 1131590Srgrimesstatic const char * const db_Grp6[] = { 11474769Smikeh "sldt", 11574769Smikeh "str", 1161590Srgrimes "lldt", 1171590Srgrimes "ltr", 1181590Srgrimes "verr", 1191590Srgrimes "verw", 12067496Sphk "", 1211590Srgrimes "" 1221590Srgrimes}; 1231590Srgrimes 1241590Srgrimesstatic const char * const db_Grp7[] = { 1251590Srgrimes "sgdt", 12677274Smikeh "sidt", 1271590Srgrimes "lgdt", 1281590Srgrimes "lidt", 1291590Srgrimes "smsw", 1301590Srgrimes "", 13177274Smikeh "lmsw", 1321590Srgrimes "invlpg" 1331590Srgrimes}; 1341590Srgrimes 1351590Srgrimesstatic const char * const db_Grp8[] = { 1361590Srgrimes "", 1371590Srgrimes "", 1381590Srgrimes "", 1391590Srgrimes "", 1401590Srgrimes "bt", 1411590Srgrimes "bts", 1421590Srgrimes "btr", 1431590Srgrimes "btc" 1441590Srgrimes}; 1451590Srgrimes 1461590Srgrimesstatic const char * const db_Grp9[] = { 1471590Srgrimes "", 1481590Srgrimes "cmpxchg8b", 1491590Srgrimes "", 1501590Srgrimes "", 1511590Srgrimes "", 1521590Srgrimes "", 1531590Srgrimes "", 1541590Srgrimes "" 1551590Srgrimes}; 1561590Srgrimes 1571590Srgrimesstatic const struct inst db_inst_0f0x[] = { 1581590Srgrimes/*00*/ { "", TRUE, NONE, op1(Ew), db_Grp6 }, 1591590Srgrimes/*01*/ { "", TRUE, NONE, op1(Ew), db_Grp7 }, 16077274Smikeh/*02*/ { "lar", TRUE, LONG, op2(E,R), 0 }, 1611590Srgrimes/*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 }, 1621590Srgrimes/*04*/ { "", FALSE, NONE, 0, 0 }, 16377274Smikeh/*05*/ { "", FALSE, NONE, 0, 0 }, 16477274Smikeh/*06*/ { "clts", FALSE, NONE, 0, 0 }, 1651590Srgrimes/*07*/ { "", FALSE, NONE, 0, 0 }, 1661590Srgrimes 1671590Srgrimes/*08*/ { "invd", FALSE, NONE, 0, 0 }, 1681590Srgrimes/*09*/ { "wbinvd",FALSE, NONE, 0, 0 }, 1691590Srgrimes/*0a*/ { "", FALSE, NONE, 0, 0 }, 1701590Srgrimes/*0b*/ { "", FALSE, NONE, 0, 0 }, 1711590Srgrimes/*0c*/ { "", FALSE, NONE, 0, 0 }, 1721590Srgrimes/*0d*/ { "", FALSE, NONE, 0, 0 }, 17376455Smikeh/*0e*/ { "", FALSE, NONE, 0, 0 }, 1741590Srgrimes/*0f*/ { "", FALSE, NONE, 0, 0 }, 1751590Srgrimes}; 1761590Srgrimes 1771590Srgrimesstatic const struct inst db_inst_0f2x[] = { 1781590Srgrimes/*20*/ { "mov", TRUE, LONG, op2(CR,El), 0 }, 1791590Srgrimes/*21*/ { "mov", TRUE, LONG, op2(DR,El), 0 }, 1801590Srgrimes/*22*/ { "mov", TRUE, LONG, op2(El,CR), 0 }, 18177274Smikeh/*23*/ { "mov", TRUE, LONG, op2(El,DR), 0 }, 1821590Srgrimes/*24*/ { "mov", TRUE, LONG, op2(TR,El), 0 }, 1831590Srgrimes/*25*/ { "", FALSE, NONE, 0, 0 }, 1841590Srgrimes/*26*/ { "mov", TRUE, LONG, op2(El,TR), 0 }, 18577274Smikeh/*27*/ { "", FALSE, NONE, 0, 0 }, 1861590Srgrimes 1871590Srgrimes/*28*/ { "", FALSE, NONE, 0, 0 }, 1881590Srgrimes/*29*/ { "", FALSE, NONE, 0, 0 }, 18976455Smikeh/*2a*/ { "", FALSE, NONE, 0, 0 }, 19076455Smikeh/*2b*/ { "", FALSE, NONE, 0, 0 }, 19177274Smikeh/*2c*/ { "", FALSE, NONE, 0, 0 }, 1921590Srgrimes/*2d*/ { "", FALSE, NONE, 0, 0 }, 1931590Srgrimes/*2e*/ { "", FALSE, NONE, 0, 0 }, 1941590Srgrimes/*2f*/ { "", FALSE, NONE, 0, 0 }, 1951590Srgrimes}; 1961590Srgrimes 1971590Srgrimesstatic const struct inst db_inst_0f3x[] = { 1981590Srgrimes/*30*/ { "wrmsr", FALSE, NONE, 0, 0 }, 1991590Srgrimes/*31*/ { "rdtsc", FALSE, NONE, 0, 0 }, 20077274Smikeh/*32*/ { "rdmsr", FALSE, NONE, 0, 0 }, 2011590Srgrimes/*33*/ { "rdpmc", FALSE, NONE, 0, 0 }, 2021590Srgrimes/*34*/ { "", FALSE, NONE, 0, 0 }, 20377274Smikeh/*35*/ { "", FALSE, NONE, 0, 0 }, 20482793Sache/*36*/ { "", FALSE, NONE, 0, 0 }, 20582793Sache/*37*/ { "", FALSE, NONE, 0, 0 }, 20674769Smikeh 2071590Srgrimes/*38*/ { "", FALSE, NONE, 0, 0 }, 2081590Srgrimes/*39*/ { "", FALSE, NONE, 0, 0 }, 2091590Srgrimes/*3a*/ { "", FALSE, NONE, 0, 0 }, 2101590Srgrimes/*3b*/ { "", FALSE, NONE, 0, 0 }, 2111590Srgrimes/*3c*/ { "", FALSE, NONE, 0, 0 }, 2121590Srgrimes/*3d*/ { "", FALSE, NONE, 0, 0 }, 2131590Srgrimes/*3e*/ { "", FALSE, NONE, 0, 0 }, 2141590Srgrimes/*3f*/ { "", FALSE, NONE, 0, 0 }, 2151590Srgrimes}; 2161590Srgrimes 2171590Srgrimesstatic const struct inst db_inst_0f8x[] = { 21877274Smikeh/*80*/ { "jo", FALSE, NONE, op1(Dl), 0 }, 2191590Srgrimes/*81*/ { "jno", FALSE, NONE, op1(Dl), 0 }, 2201590Srgrimes/*82*/ { "jb", FALSE, NONE, op1(Dl), 0 }, 22177274Smikeh/*83*/ { "jnb", FALSE, NONE, op1(Dl), 0 }, 22277274Smikeh/*84*/ { "jz", FALSE, NONE, op1(Dl), 0 }, 22374769Smikeh/*85*/ { "jnz", FALSE, NONE, op1(Dl), 0 }, 2241590Srgrimes/*86*/ { "jbe", FALSE, NONE, op1(Dl), 0 }, 22577274Smikeh/*87*/ { "jnbe", FALSE, NONE, op1(Dl), 0 }, 22677274Smikeh 22777274Smikeh/*88*/ { "js", FALSE, NONE, op1(Dl), 0 }, 22877274Smikeh/*89*/ { "jns", FALSE, NONE, op1(Dl), 0 }, 22974769Smikeh/*8a*/ { "jp", FALSE, NONE, op1(Dl), 0 }, 2301590Srgrimes/*8b*/ { "jnp", FALSE, NONE, op1(Dl), 0 }, 2311590Srgrimes/*8c*/ { "jl", FALSE, NONE, op1(Dl), 0 }, 23277274Smikeh/*8d*/ { "jnl", FALSE, NONE, op1(Dl), 0 }, 2331590Srgrimes/*8e*/ { "jle", FALSE, NONE, op1(Dl), 0 }, 2341590Srgrimes/*8f*/ { "jnle", FALSE, NONE, op1(Dl), 0 }, 2351590Srgrimes}; 2361590Srgrimes 2371590Srgrimesstatic const struct inst db_inst_0f9x[] = { 2381590Srgrimes/*90*/ { "seto", TRUE, NONE, op1(Eb), 0 }, 2391590Srgrimes/*91*/ { "setno", TRUE, NONE, op1(Eb), 0 }, 2401590Srgrimes/*92*/ { "setb", TRUE, NONE, op1(Eb), 0 }, 2411590Srgrimes/*93*/ { "setnb", TRUE, NONE, op1(Eb), 0 }, 2421590Srgrimes/*94*/ { "setz", TRUE, NONE, op1(Eb), 0 }, 2431590Srgrimes/*95*/ { "setnz", TRUE, NONE, op1(Eb), 0 }, 24477274Smikeh/*96*/ { "setbe", TRUE, NONE, op1(Eb), 0 }, 2451590Srgrimes/*97*/ { "setnbe",TRUE, NONE, op1(Eb), 0 }, 2461590Srgrimes 2471590Srgrimes/*98*/ { "sets", TRUE, NONE, op1(Eb), 0 }, 2481590Srgrimes/*99*/ { "setns", TRUE, NONE, op1(Eb), 0 }, 2491590Srgrimes/*9a*/ { "setp", TRUE, NONE, op1(Eb), 0 }, 2501590Srgrimes/*9b*/ { "setnp", TRUE, NONE, op1(Eb), 0 }, 2511590Srgrimes/*9c*/ { "setl", TRUE, NONE, op1(Eb), 0 }, 2521590Srgrimes/*9d*/ { "setnl", TRUE, NONE, op1(Eb), 0 }, 2531590Srgrimes/*9e*/ { "setle", TRUE, NONE, op1(Eb), 0 }, 2541590Srgrimes/*9f*/ { "setnle",TRUE, NONE, op1(Eb), 0 }, 2551590Srgrimes}; 2561590Srgrimes 25777274Smikehstatic const struct inst db_inst_0fax[] = { 2581590Srgrimes/*a0*/ { "push", FALSE, NONE, op1(Si), 0 }, 2591590Srgrimes/*a1*/ { "pop", FALSE, NONE, op1(Si), 0 }, 26077274Smikeh/*a2*/ { "cpuid", FALSE, NONE, 0, 0 }, 2611590Srgrimes/*a3*/ { "bt", TRUE, LONG, op2(R,E), 0 }, 26277274Smikeh/*a4*/ { "shld", TRUE, LONG, op3(Ib,R,E), 0 }, 2631590Srgrimes/*a5*/ { "shld", TRUE, LONG, op3(CL,R,E), 0 }, 2641590Srgrimes/*a6*/ { "", FALSE, NONE, 0, 0 }, 2651590Srgrimes/*a7*/ { "", FALSE, NONE, 0, 0 }, 2661590Srgrimes 2671590Srgrimes/*a8*/ { "push", FALSE, NONE, op1(Si), 0 }, 2681590Srgrimes/*a9*/ { "pop", FALSE, NONE, op1(Si), 0 }, 2691590Srgrimes/*aa*/ { "rsm", FALSE, NONE, 0, 0 }, 2701590Srgrimes/*ab*/ { "bts", TRUE, LONG, op2(R,E), 0 }, 2711590Srgrimes/*ac*/ { "shrd", TRUE, LONG, op3(Ib,R,E), 0 }, 2721590Srgrimes/*ad*/ { "shrd", TRUE, LONG, op3(CL,R,E), 0 }, 2731590Srgrimes/*a6*/ { "", FALSE, NONE, 0, 0 }, 2741590Srgrimes/*a7*/ { "imul", TRUE, LONG, op2(E,R), 0 }, 2751590Srgrimes}; 2761590Srgrimes 2771590Srgrimesstatic const struct inst db_inst_0fbx[] = { 2781590Srgrimes/*b0*/ { "cmpxchg",TRUE, BYTE, op2(R, E), 0 }, 2791590Srgrimes/*b0*/ { "cmpxchg",TRUE, LONG, op2(R, E), 0 }, 2801590Srgrimes/*b2*/ { "lss", TRUE, LONG, op2(E, R), 0 }, 2811590Srgrimes/*b3*/ { "btr", TRUE, LONG, op2(R, E), 0 }, 2821590Srgrimes/*b4*/ { "lfs", TRUE, LONG, op2(E, R), 0 }, 2831590Srgrimes/*b5*/ { "lgs", TRUE, LONG, op2(E, R), 0 }, 2841590Srgrimes/*b6*/ { "movzb", TRUE, LONG, op2(Eb, R), 0 }, 2851590Srgrimes/*b7*/ { "movzw", TRUE, LONG, op2(Ew, R), 0 }, 28677274Smikeh 2871590Srgrimes/*b8*/ { "", FALSE, NONE, 0, 0 }, 2881590Srgrimes/*b9*/ { "", FALSE, NONE, 0, 0 }, 2891590Srgrimes/*ba*/ { "", TRUE, LONG, op2(Ib, E), db_Grp8 }, 2901590Srgrimes/*bb*/ { "btc", TRUE, LONG, op2(R, E), 0 }, 2911590Srgrimes/*bc*/ { "bsf", TRUE, LONG, op2(E, R), 0 }, 2921590Srgrimes/*bd*/ { "bsr", TRUE, LONG, op2(E, R), 0 }, 2931590Srgrimes/*be*/ { "movsb", TRUE, LONG, op2(Eb, R), 0 }, 2941590Srgrimes/*bf*/ { "movsw", TRUE, LONG, op2(Ew, R), 0 }, 2951590Srgrimes}; 2961590Srgrimes 2971590Srgrimesstatic const struct inst db_inst_0fcx[] = { 2981590Srgrimes/*c0*/ { "xadd", TRUE, BYTE, op2(R, E), 0 }, 2991590Srgrimes/*c1*/ { "xadd", TRUE, LONG, op2(R, E), 0 }, 30077274Smikeh/*c2*/ { "", FALSE, NONE, 0, 0 }, 30177274Smikeh/*c3*/ { "", FALSE, NONE, 0, 0 }, 3021590Srgrimes/*c4*/ { "", FALSE, NONE, 0, 0 }, 3031590Srgrimes/*c5*/ { "", FALSE, NONE, 0, 0 }, 3041590Srgrimes/*c6*/ { "", FALSE, NONE, 0, 0 }, 3051590Srgrimes/*c7*/ { "", TRUE, NONE, op1(E), db_Grp9 }, 3061590Srgrimes/*c8*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3071590Srgrimes/*c9*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3081590Srgrimes/*ca*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3091590Srgrimes/*cb*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3101590Srgrimes/*cc*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3111590Srgrimes/*cd*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3121590Srgrimes/*ce*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3131590Srgrimes/*cf*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 3141590Srgrimes}; 3151590Srgrimes 3161590Srgrimesstatic const struct inst * const db_inst_0f[] = { 31777274Smikeh db_inst_0f0x, 3181590Srgrimes 0, 3191590Srgrimes db_inst_0f2x, 3201590Srgrimes db_inst_0f3x, 32177274Smikeh 0, 32277274Smikeh 0, 3231590Srgrimes 0, 3241590Srgrimes 0, 3251590Srgrimes db_inst_0f8x, 3261590Srgrimes db_inst_0f9x, 3271590Srgrimes db_inst_0fax, 3281590Srgrimes db_inst_0fbx, 3291590Srgrimes db_inst_0fcx, 3301590Srgrimes 0, 3311590Srgrimes 0, 3321590Srgrimes 0 3331590Srgrimes}; 33474769Smikeh 33577274Smikehstatic const char * const db_Esc92[] = { 3361590Srgrimes "fnop", "", "", "", "", "", "", "" 3371590Srgrimes}; 3381590Srgrimesstatic const char * const db_Esc94[] = { 3391590Srgrimes "fchs", "fabs", "", "", "ftst", "fxam", "", "" 3401590Srgrimes}; 34177274Smikehstatic const char * const db_Esc95[] = { 3421590Srgrimes "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","" 34377274Smikeh}; 3441590Srgrimesstatic const char * const db_Esc96[] = { 34577274Smikeh "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp", 3461590Srgrimes "fincstp" 3471590Srgrimes}; 3481590Srgrimesstatic const char * const db_Esc97[] = { 34974769Smikeh "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos" 35077274Smikeh}; 3511590Srgrimes 3521590Srgrimesstatic const char * const db_Esca5[] = { 3531590Srgrimes "", "fucompp","", "", "", "", "", "" 35474769Smikeh}; 35574769Smikeh 35677274Smikehstatic const char * const db_Escb4[] = { 3571590Srgrimes "fneni","fndisi", "fnclex","fninit","fsetpm", "", "", "" 3581590Srgrimes}; 35974769Smikeh 36077274Smikehstatic const char * const db_Esce3[] = { 3611590Srgrimes "", "fcompp","", "", "", "", "", "" 36274769Smikeh}; 36377274Smikeh 3641590Srgrimesstatic const char * const db_Escf4[] = { 36577274Smikeh "fnstsw","", "", "", "", "", "", "" 36677274Smikeh}; 36777274Smikeh 36877274Smikehstatic const struct finst db_Esc8[] = { 3691590Srgrimes/*0*/ { "fadd", SNGL, op2(STI,ST), 0 }, 37077274Smikeh/*1*/ { "fmul", SNGL, op2(STI,ST), 0 }, 37177274Smikeh/*2*/ { "fcom", SNGL, op2(STI,ST), 0 }, 37277274Smikeh/*3*/ { "fcomp", SNGL, op2(STI,ST), 0 }, 3731590Srgrimes/*4*/ { "fsub", SNGL, op2(STI,ST), 0 }, 37477274Smikeh/*5*/ { "fsubr", SNGL, op2(STI,ST), 0 }, 3751590Srgrimes/*6*/ { "fdiv", SNGL, op2(STI,ST), 0 }, 37677274Smikeh/*7*/ { "fdivr", SNGL, op2(STI,ST), 0 }, 37777274Smikeh}; 37877274Smikeh 3791590Srgrimesstatic const struct finst db_Esc9[] = { 38077274Smikeh/*0*/ { "fld", SNGL, op1(STI), 0 }, 3811590Srgrimes/*1*/ { "", NONE, op1(STI), "fxch" }, 3821590Srgrimes/*2*/ { "fst", SNGL, op1(X), db_Esc92 }, 38374769Smikeh/*3*/ { "fstp", SNGL, 0, 0 }, 38477274Smikeh/*4*/ { "fldenv", NONE, op1(X), db_Esc94 }, 3851590Srgrimes/*5*/ { "fldcw", NONE, op1(X), db_Esc95 }, 3861590Srgrimes/*6*/ { "fnstenv",NONE, op1(X), db_Esc96 }, 3871590Srgrimes/*7*/ { "fnstcw", NONE, op1(X), db_Esc97 }, 38877274Smikeh}; 3891590Srgrimes 3901590Srgrimesstatic const struct finst db_Esca[] = { 3911590Srgrimes/*0*/ { "fiadd", LONG, 0, 0 }, 39277274Smikeh/*1*/ { "fimul", LONG, 0, 0 }, 3931590Srgrimes/*2*/ { "ficom", LONG, 0, 0 }, 39474769Smikeh/*3*/ { "ficomp", LONG, 0, 0 }, 3951590Srgrimes/*4*/ { "fisub", LONG, 0, 0 }, 3961590Srgrimes/*5*/ { "fisubr", LONG, op1(X), db_Esca5 }, 3971590Srgrimes/*6*/ { "fidiv", LONG, 0, 0 }, 39874769Smikeh/*7*/ { "fidivr", LONG, 0, 0 } 3991590Srgrimes}; 40077274Smikeh 4011590Srgrimesstatic const struct finst db_Escb[] = { 40277274Smikeh/*0*/ { "fild", LONG, 0, 0 }, 4031590Srgrimes/*1*/ { "", NONE, 0, 0 }, 4041590Srgrimes/*2*/ { "fist", LONG, 0, 0 }, 4051590Srgrimes/*3*/ { "fistp", LONG, 0, 0 }, 4061590Srgrimes/*4*/ { "", WORD, op1(X), db_Escb4 }, 4071590Srgrimes/*5*/ { "fld", EXTR, 0, 0 }, 4081590Srgrimes/*6*/ { "", WORD, 0, 0 }, 40974769Smikeh/*7*/ { "fstp", EXTR, 0, 0 }, 4101590Srgrimes}; 41174769Smikeh 4121590Srgrimesstatic const struct finst db_Escc[] = { 4131590Srgrimes/*0*/ { "fadd", DBLR, op2(ST,STI), 0 }, 41474769Smikeh/*1*/ { "fmul", DBLR, op2(ST,STI), 0 }, 4151590Srgrimes/*2*/ { "fcom", DBLR, 0, 0 }, 41677274Smikeh/*3*/ { "fcomp", DBLR, 0, 0 }, 4171590Srgrimes/*4*/ { "fsub", DBLR, op2(ST,STI), "fsubr" }, 4181590Srgrimes/*5*/ { "fsubr", DBLR, op2(ST,STI), "fsub" }, 41974769Smikeh/*6*/ { "fdiv", DBLR, op2(ST,STI), "fdivr" }, 4201590Srgrimes/*7*/ { "fdivr", DBLR, op2(ST,STI), "fdiv" }, 42177274Smikeh}; 42277274Smikeh 42381979Sbrianstatic const struct finst db_Escd[] = { 4241590Srgrimes/*0*/ { "fld", DBLR, op1(STI), "ffree" }, 4251590Srgrimes/*1*/ { "", NONE, 0, 0 }, 4261590Srgrimes/*2*/ { "fst", DBLR, op1(STI), 0 }, 4271590Srgrimes/*3*/ { "fstp", DBLR, op1(STI), 0 }, 4281590Srgrimes/*4*/ { "frstor", NONE, op1(STI), "fucom" }, 4291590Srgrimes/*5*/ { "", NONE, op1(STI), "fucomp" }, 4301590Srgrimes/*6*/ { "fnsave", NONE, 0, 0 }, 4311590Srgrimes/*7*/ { "fnstsw", NONE, 0, 0 }, 43277274Smikeh}; 4331590Srgrimes 43477274Smikehstatic const struct finst db_Esce[] = { 4351590Srgrimes/*0*/ { "fiadd", WORD, op2(ST,STI), "faddp" }, 4361590Srgrimes/*1*/ { "fimul", WORD, op2(ST,STI), "fmulp" }, 4371590Srgrimes/*2*/ { "ficom", WORD, 0, 0 }, 4381590Srgrimes/*3*/ { "ficomp", WORD, op1(X), db_Esce3 }, 43977274Smikeh/*4*/ { "fisub", WORD, op2(ST,STI), "fsubrp" }, 4401590Srgrimes/*5*/ { "fisubr", WORD, op2(ST,STI), "fsubp" }, 4411590Srgrimes/*6*/ { "fidiv", WORD, op2(ST,STI), "fdivrp" }, 44277274Smikeh/*7*/ { "fidivr", WORD, op2(ST,STI), "fdivp" }, 4431590Srgrimes}; 444 445static const struct finst db_Escf[] = { 446/*0*/ { "fild", WORD, 0, 0 }, 447/*1*/ { "", NONE, 0, 0 }, 448/*2*/ { "fist", WORD, 0, 0 }, 449/*3*/ { "fistp", WORD, 0, 0 }, 450/*4*/ { "fbld", NONE, op1(XA), db_Escf4 }, 451/*5*/ { "fild", QUAD, 0, 0 }, 452/*6*/ { "fbstp", NONE, 0, 0 }, 453/*7*/ { "fistp", QUAD, 0, 0 }, 454}; 455 456static const struct finst * const db_Esc_inst[] = { 457 db_Esc8, db_Esc9, db_Esca, db_Escb, 458 db_Escc, db_Escd, db_Esce, db_Escf 459}; 460 461static const char * const db_Grp1[] = { 462 "add", 463 "or", 464 "adc", 465 "sbb", 466 "and", 467 "sub", 468 "xor", 469 "cmp" 470}; 471 472static const char * const db_Grp2[] = { 473 "rol", 474 "ror", 475 "rcl", 476 "rcr", 477 "shl", 478 "shr", 479 "shl", 480 "sar" 481}; 482 483static const struct inst db_Grp3[] = { 484 { "test", TRUE, NONE, op2(I,E), 0 }, 485 { "test", TRUE, NONE, op2(I,E), 0 }, 486 { "not", TRUE, NONE, op1(E), 0 }, 487 { "neg", TRUE, NONE, op1(E), 0 }, 488 { "mul", TRUE, NONE, op2(E,A), 0 }, 489 { "imul", TRUE, NONE, op2(E,A), 0 }, 490 { "div", TRUE, NONE, op2(E,A), 0 }, 491 { "idiv", TRUE, NONE, op2(E,A), 0 }, 492}; 493 494static const struct inst db_Grp4[] = { 495 { "inc", TRUE, BYTE, op1(E), 0 }, 496 { "dec", TRUE, BYTE, op1(E), 0 }, 497 { "", TRUE, NONE, 0, 0 }, 498 { "", TRUE, NONE, 0, 0 }, 499 { "", TRUE, NONE, 0, 0 }, 500 { "", TRUE, NONE, 0, 0 }, 501 { "", TRUE, NONE, 0, 0 }, 502 { "", TRUE, NONE, 0, 0 } 503}; 504 505static const struct inst db_Grp5[] = { 506 { "inc", TRUE, LONG, op1(E), 0 }, 507 { "dec", TRUE, LONG, op1(E), 0 }, 508 { "call", TRUE, LONG, op1(Eind),0 }, 509 { "lcall", TRUE, LONG, op1(Eind),0 }, 510 { "jmp", TRUE, LONG, op1(Eind),0 }, 511 { "ljmp", TRUE, LONG, op1(Eind),0 }, 512 { "push", TRUE, LONG, op1(E), 0 }, 513 { "", TRUE, NONE, 0, 0 } 514}; 515 516static const struct inst db_inst_table[256] = { 517/*00*/ { "add", TRUE, BYTE, op2(R, E), 0 }, 518/*01*/ { "add", TRUE, LONG, op2(R, E), 0 }, 519/*02*/ { "add", TRUE, BYTE, op2(E, R), 0 }, 520/*03*/ { "add", TRUE, LONG, op2(E, R), 0 }, 521/*04*/ { "add", FALSE, BYTE, op2(I, A), 0 }, 522/*05*/ { "add", FALSE, LONG, op2(Is, A), 0 }, 523/*06*/ { "push", FALSE, NONE, op1(Si), 0 }, 524/*07*/ { "pop", FALSE, NONE, op1(Si), 0 }, 525 526/*08*/ { "or", TRUE, BYTE, op2(R, E), 0 }, 527/*09*/ { "or", TRUE, LONG, op2(R, E), 0 }, 528/*0a*/ { "or", TRUE, BYTE, op2(E, R), 0 }, 529/*0b*/ { "or", TRUE, LONG, op2(E, R), 0 }, 530/*0c*/ { "or", FALSE, BYTE, op2(I, A), 0 }, 531/*0d*/ { "or", FALSE, LONG, op2(I, A), 0 }, 532/*0e*/ { "push", FALSE, NONE, op1(Si), 0 }, 533/*0f*/ { "", FALSE, NONE, 0, 0 }, 534 535/*10*/ { "adc", TRUE, BYTE, op2(R, E), 0 }, 536/*11*/ { "adc", TRUE, LONG, op2(R, E), 0 }, 537/*12*/ { "adc", TRUE, BYTE, op2(E, R), 0 }, 538/*13*/ { "adc", TRUE, LONG, op2(E, R), 0 }, 539/*14*/ { "adc", FALSE, BYTE, op2(I, A), 0 }, 540/*15*/ { "adc", FALSE, LONG, op2(Is, A), 0 }, 541/*16*/ { "push", FALSE, NONE, op1(Si), 0 }, 542/*17*/ { "pop", FALSE, NONE, op1(Si), 0 }, 543 544/*18*/ { "sbb", TRUE, BYTE, op2(R, E), 0 }, 545/*19*/ { "sbb", TRUE, LONG, op2(R, E), 0 }, 546/*1a*/ { "sbb", TRUE, BYTE, op2(E, R), 0 }, 547/*1b*/ { "sbb", TRUE, LONG, op2(E, R), 0 }, 548/*1c*/ { "sbb", FALSE, BYTE, op2(I, A), 0 }, 549/*1d*/ { "sbb", FALSE, LONG, op2(Is, A), 0 }, 550/*1e*/ { "push", FALSE, NONE, op1(Si), 0 }, 551/*1f*/ { "pop", FALSE, NONE, op1(Si), 0 }, 552 553/*20*/ { "and", TRUE, BYTE, op2(R, E), 0 }, 554/*21*/ { "and", TRUE, LONG, op2(R, E), 0 }, 555/*22*/ { "and", TRUE, BYTE, op2(E, R), 0 }, 556/*23*/ { "and", TRUE, LONG, op2(E, R), 0 }, 557/*24*/ { "and", FALSE, BYTE, op2(I, A), 0 }, 558/*25*/ { "and", FALSE, LONG, op2(I, A), 0 }, 559/*26*/ { "", FALSE, NONE, 0, 0 }, 560/*27*/ { "daa", FALSE, NONE, 0, 0 }, 561 562/*28*/ { "sub", TRUE, BYTE, op2(R, E), 0 }, 563/*29*/ { "sub", TRUE, LONG, op2(R, E), 0 }, 564/*2a*/ { "sub", TRUE, BYTE, op2(E, R), 0 }, 565/*2b*/ { "sub", TRUE, LONG, op2(E, R), 0 }, 566/*2c*/ { "sub", FALSE, BYTE, op2(I, A), 0 }, 567/*2d*/ { "sub", FALSE, LONG, op2(Is, A), 0 }, 568/*2e*/ { "", FALSE, NONE, 0, 0 }, 569/*2f*/ { "das", FALSE, NONE, 0, 0 }, 570 571/*30*/ { "xor", TRUE, BYTE, op2(R, E), 0 }, 572/*31*/ { "xor", TRUE, LONG, op2(R, E), 0 }, 573/*32*/ { "xor", TRUE, BYTE, op2(E, R), 0 }, 574/*33*/ { "xor", TRUE, LONG, op2(E, R), 0 }, 575/*34*/ { "xor", FALSE, BYTE, op2(I, A), 0 }, 576/*35*/ { "xor", FALSE, LONG, op2(I, A), 0 }, 577/*36*/ { "", FALSE, NONE, 0, 0 }, 578/*37*/ { "aaa", FALSE, NONE, 0, 0 }, 579 580/*38*/ { "cmp", TRUE, BYTE, op2(R, E), 0 }, 581/*39*/ { "cmp", TRUE, LONG, op2(R, E), 0 }, 582/*3a*/ { "cmp", TRUE, BYTE, op2(E, R), 0 }, 583/*3b*/ { "cmp", TRUE, LONG, op2(E, R), 0 }, 584/*3c*/ { "cmp", FALSE, BYTE, op2(I, A), 0 }, 585/*3d*/ { "cmp", FALSE, LONG, op2(Is, A), 0 }, 586/*3e*/ { "", FALSE, NONE, 0, 0 }, 587/*3f*/ { "aas", FALSE, NONE, 0, 0 }, 588 589/*40*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 590/*41*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 591/*42*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 592/*43*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 593/*44*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 594/*45*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 595/*46*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 596/*47*/ { "inc", FALSE, LONG, op1(Ri), 0 }, 597 598/*48*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 599/*49*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 600/*4a*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 601/*4b*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 602/*4c*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 603/*4d*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 604/*4e*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 605/*4f*/ { "dec", FALSE, LONG, op1(Ri), 0 }, 606 607/*50*/ { "push", FALSE, LONG, op1(Ri), 0 }, 608/*51*/ { "push", FALSE, LONG, op1(Ri), 0 }, 609/*52*/ { "push", FALSE, LONG, op1(Ri), 0 }, 610/*53*/ { "push", FALSE, LONG, op1(Ri), 0 }, 611/*54*/ { "push", FALSE, LONG, op1(Ri), 0 }, 612/*55*/ { "push", FALSE, LONG, op1(Ri), 0 }, 613/*56*/ { "push", FALSE, LONG, op1(Ri), 0 }, 614/*57*/ { "push", FALSE, LONG, op1(Ri), 0 }, 615 616/*58*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 617/*59*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 618/*5a*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 619/*5b*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 620/*5c*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 621/*5d*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 622/*5e*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 623/*5f*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 624 625/*60*/ { "pusha", FALSE, LONG, 0, 0 }, 626/*61*/ { "popa", FALSE, LONG, 0, 0 }, 627/*62*/ { "bound", TRUE, LONG, op2(E, R), 0 }, 628/*63*/ { "arpl", TRUE, NONE, op2(Rw,Ew), 0 }, 629 630/*64*/ { "", FALSE, NONE, 0, 0 }, 631/*65*/ { "", FALSE, NONE, 0, 0 }, 632/*66*/ { "", FALSE, NONE, 0, 0 }, 633/*67*/ { "", FALSE, NONE, 0, 0 }, 634 635/*68*/ { "push", FALSE, LONG, op1(I), 0 }, 636/*69*/ { "imul", TRUE, LONG, op3(I,E,R), 0 }, 637/*6a*/ { "push", FALSE, LONG, op1(Ibs), 0 }, 638/*6b*/ { "imul", TRUE, LONG, op3(Ibs,E,R),0 }, 639/*6c*/ { "ins", FALSE, BYTE, op2(DX, DI), 0 }, 640/*6d*/ { "ins", FALSE, LONG, op2(DX, DI), 0 }, 641/*6e*/ { "outs", FALSE, BYTE, op2(SI, DX), 0 }, 642/*6f*/ { "outs", FALSE, LONG, op2(SI, DX), 0 }, 643 644/*70*/ { "jo", FALSE, NONE, op1(Db), 0 }, 645/*71*/ { "jno", FALSE, NONE, op1(Db), 0 }, 646/*72*/ { "jb", FALSE, NONE, op1(Db), 0 }, 647/*73*/ { "jnb", FALSE, NONE, op1(Db), 0 }, 648/*74*/ { "jz", FALSE, NONE, op1(Db), 0 }, 649/*75*/ { "jnz", FALSE, NONE, op1(Db), 0 }, 650/*76*/ { "jbe", FALSE, NONE, op1(Db), 0 }, 651/*77*/ { "jnbe", FALSE, NONE, op1(Db), 0 }, 652 653/*78*/ { "js", FALSE, NONE, op1(Db), 0 }, 654/*79*/ { "jns", FALSE, NONE, op1(Db), 0 }, 655/*7a*/ { "jp", FALSE, NONE, op1(Db), 0 }, 656/*7b*/ { "jnp", FALSE, NONE, op1(Db), 0 }, 657/*7c*/ { "jl", FALSE, NONE, op1(Db), 0 }, 658/*7d*/ { "jnl", FALSE, NONE, op1(Db), 0 }, 659/*7e*/ { "jle", FALSE, NONE, op1(Db), 0 }, 660/*7f*/ { "jnle", FALSE, NONE, op1(Db), 0 }, 661 662/*80*/ { "", TRUE, BYTE, op2(I, E), db_Grp1 }, 663/*81*/ { "", TRUE, LONG, op2(I, E), db_Grp1 }, 664/*82*/ { "", TRUE, BYTE, op2(I, E), db_Grp1 }, 665/*83*/ { "", TRUE, LONG, op2(Ibs,E), db_Grp1 }, 666/*84*/ { "test", TRUE, BYTE, op2(R, E), 0 }, 667/*85*/ { "test", TRUE, LONG, op2(R, E), 0 }, 668/*86*/ { "xchg", TRUE, BYTE, op2(R, E), 0 }, 669/*87*/ { "xchg", TRUE, LONG, op2(R, E), 0 }, 670 671/*88*/ { "mov", TRUE, BYTE, op2(R, E), 0 }, 672/*89*/ { "mov", TRUE, LONG, op2(R, E), 0 }, 673/*8a*/ { "mov", TRUE, BYTE, op2(E, R), 0 }, 674/*8b*/ { "mov", TRUE, LONG, op2(E, R), 0 }, 675/*8c*/ { "mov", TRUE, NONE, op2(S, Ew), 0 }, 676/*8d*/ { "lea", TRUE, LONG, op2(E, R), 0 }, 677/*8e*/ { "mov", TRUE, NONE, op2(Ew, S), 0 }, 678/*8f*/ { "pop", TRUE, LONG, op1(E), 0 }, 679 680/*90*/ { "nop", FALSE, NONE, 0, 0 }, 681/*91*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 682/*92*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 683/*93*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 684/*94*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 685/*95*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 686/*96*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 687/*97*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 688 689/*98*/ { "cbw", FALSE, SDEP, 0, "cwde" }, /* cbw/cwde */ 690/*99*/ { "cwd", FALSE, SDEP, 0, "cdq" }, /* cwd/cdq */ 691/*9a*/ { "lcall", FALSE, NONE, op1(OS), 0 }, 692/*9b*/ { "wait", FALSE, NONE, 0, 0 }, 693/*9c*/ { "pushf", FALSE, LONG, 0, 0 }, 694/*9d*/ { "popf", FALSE, LONG, 0, 0 }, 695/*9e*/ { "sahf", FALSE, NONE, 0, 0 }, 696/*9f*/ { "lahf", FALSE, NONE, 0, 0 }, 697 698/*a0*/ { "mov", FALSE, BYTE, op2(O, A), 0 }, 699/*a1*/ { "mov", FALSE, LONG, op2(O, A), 0 }, 700/*a2*/ { "mov", FALSE, BYTE, op2(A, O), 0 }, 701/*a3*/ { "mov", FALSE, LONG, op2(A, O), 0 }, 702/*a4*/ { "movs", FALSE, BYTE, op2(SI,DI), 0 }, 703/*a5*/ { "movs", FALSE, LONG, op2(SI,DI), 0 }, 704/*a6*/ { "cmps", FALSE, BYTE, op2(SI,DI), 0 }, 705/*a7*/ { "cmps", FALSE, LONG, op2(SI,DI), 0 }, 706 707/*a8*/ { "test", FALSE, BYTE, op2(I, A), 0 }, 708/*a9*/ { "test", FALSE, LONG, op2(I, A), 0 }, 709/*aa*/ { "stos", FALSE, BYTE, op1(DI), 0 }, 710/*ab*/ { "stos", FALSE, LONG, op1(DI), 0 }, 711/*ac*/ { "lods", FALSE, BYTE, op1(SI), 0 }, 712/*ad*/ { "lods", FALSE, LONG, op1(SI), 0 }, 713/*ae*/ { "scas", FALSE, BYTE, op1(SI), 0 }, 714/*af*/ { "scas", FALSE, LONG, op1(SI), 0 }, 715 716/*b0*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 717/*b1*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 718/*b2*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 719/*b3*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 720/*b4*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 721/*b5*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 722/*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 723/*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 724 725/*b8*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 726/*b9*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 727/*ba*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 728/*bb*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 729/*bc*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 730/*bd*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 731/*be*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 732/*bf*/ { "mov", FALSE, LONG, op2(I, Ri), 0 }, 733 734/*c0*/ { "", TRUE, BYTE, op2(Ib, E), db_Grp2 }, 735/*c1*/ { "", TRUE, LONG, op2(Ib, E), db_Grp2 }, 736/*c2*/ { "ret", FALSE, NONE, op1(Iw), 0 }, 737/*c3*/ { "ret", FALSE, NONE, 0, 0 }, 738/*c4*/ { "les", TRUE, LONG, op2(E, R), 0 }, 739/*c5*/ { "lds", TRUE, LONG, op2(E, R), 0 }, 740/*c6*/ { "mov", TRUE, BYTE, op2(I, E), 0 }, 741/*c7*/ { "mov", TRUE, LONG, op2(I, E), 0 }, 742 743/*c8*/ { "enter", FALSE, NONE, op2(Iw, Ib), 0 }, 744/*c9*/ { "leave", FALSE, NONE, 0, 0 }, 745/*ca*/ { "lret", FALSE, NONE, op1(Iw), 0 }, 746/*cb*/ { "lret", FALSE, NONE, 0, 0 }, 747/*cc*/ { "int", FALSE, NONE, op1(o3), 0 }, 748/*cd*/ { "int", FALSE, NONE, op1(Ib), 0 }, 749/*ce*/ { "into", FALSE, NONE, 0, 0 }, 750/*cf*/ { "iret", FALSE, NONE, 0, 0 }, 751 752/*d0*/ { "", TRUE, BYTE, op2(o1, E), db_Grp2 }, 753/*d1*/ { "", TRUE, LONG, op2(o1, E), db_Grp2 }, 754/*d2*/ { "", TRUE, BYTE, op2(CL, E), db_Grp2 }, 755/*d3*/ { "", TRUE, LONG, op2(CL, E), db_Grp2 }, 756/*d4*/ { "aam", FALSE, NONE, op1(Iba), 0 }, 757/*d5*/ { "aad", FALSE, NONE, op1(Iba), 0 }, 758/*d6*/ { ".byte\t0xd6", FALSE, NONE, 0, 0 }, 759/*d7*/ { "xlat", FALSE, BYTE, op1(BX), 0 }, 760 761/*d8*/ { "", TRUE, NONE, 0, db_Esc8 }, 762/*d9*/ { "", TRUE, NONE, 0, db_Esc9 }, 763/*da*/ { "", TRUE, NONE, 0, db_Esca }, 764/*db*/ { "", TRUE, NONE, 0, db_Escb }, 765/*dc*/ { "", TRUE, NONE, 0, db_Escc }, 766/*dd*/ { "", TRUE, NONE, 0, db_Escd }, 767/*de*/ { "", TRUE, NONE, 0, db_Esce }, 768/*df*/ { "", TRUE, NONE, 0, db_Escf }, 769 770/*e0*/ { "loopne",FALSE, NONE, op1(Db), 0 }, 771/*e1*/ { "loope", FALSE, NONE, op1(Db), 0 }, 772/*e2*/ { "loop", FALSE, NONE, op1(Db), 0 }, 773/*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz" }, 774/*e4*/ { "in", FALSE, BYTE, op2(Ib, A), 0 }, 775/*e5*/ { "in", FALSE, LONG, op2(Ib, A) , 0 }, 776/*e6*/ { "out", FALSE, BYTE, op2(A, Ib), 0 }, 777/*e7*/ { "out", FALSE, LONG, op2(A, Ib) , 0 }, 778 779/*e8*/ { "call", FALSE, NONE, op1(Dl), 0 }, 780/*e9*/ { "jmp", FALSE, NONE, op1(Dl), 0 }, 781/*ea*/ { "ljmp", FALSE, NONE, op1(OS), 0 }, 782/*eb*/ { "jmp", FALSE, NONE, op1(Db), 0 }, 783/*ec*/ { "in", FALSE, BYTE, op2(DX, A), 0 }, 784/*ed*/ { "in", FALSE, LONG, op2(DX, A) , 0 }, 785/*ee*/ { "out", FALSE, BYTE, op2(A, DX), 0 }, 786/*ef*/ { "out", FALSE, LONG, op2(A, DX) , 0 }, 787 788/*f0*/ { "", FALSE, NONE, 0, 0 }, 789/*f1*/ { ".byte\t0xf1", FALSE, NONE, 0, 0 }, 790/*f2*/ { "", FALSE, NONE, 0, 0 }, 791/*f3*/ { "", FALSE, NONE, 0, 0 }, 792/*f4*/ { "hlt", FALSE, NONE, 0, 0 }, 793/*f5*/ { "cmc", FALSE, NONE, 0, 0 }, 794/*f6*/ { "", TRUE, BYTE, 0, db_Grp3 }, 795/*f7*/ { "", TRUE, LONG, 0, db_Grp3 }, 796 797/*f8*/ { "clc", FALSE, NONE, 0, 0 }, 798/*f9*/ { "stc", FALSE, NONE, 0, 0 }, 799/*fa*/ { "cli", FALSE, NONE, 0, 0 }, 800/*fb*/ { "sti", FALSE, NONE, 0, 0 }, 801/*fc*/ { "cld", FALSE, NONE, 0, 0 }, 802/*fd*/ { "std", FALSE, NONE, 0, 0 }, 803/*fe*/ { "", TRUE, NONE, 0, db_Grp4 }, 804/*ff*/ { "", TRUE, NONE, 0, db_Grp5 }, 805}; 806 807static const struct inst db_bad_inst = 808 { "???", FALSE, NONE, 0, 0 } 809; 810 811#define f_mod(byte) ((byte)>>6) 812#define f_reg(byte) (((byte)>>3)&0x7) 813#define f_rm(byte) ((byte)&0x7) 814 815#define sib_ss(byte) ((byte)>>6) 816#define sib_index(byte) (((byte)>>3)&0x7) 817#define sib_base(byte) ((byte)&0x7) 818 819struct i_addr { 820 int is_reg; /* if reg, reg number is in 'disp' */ 821 int disp; 822 const char * base; 823 const char * index; 824 int ss; 825}; 826 827static const char * const db_index_reg_16[8] = { 828 "%bx,%si", 829 "%bx,%di", 830 "%bp,%si", 831 "%bp,%di", 832 "%si", 833 "%di", 834 "%bp", 835 "%bx" 836}; 837 838static const char * const db_reg[3][8] = { 839 { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" }, 840 { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" }, 841 { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" } 842}; 843 844static const char * const db_seg_reg[8] = { 845 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" 846}; 847 848/* 849 * lengths for size attributes 850 */ 851static const int db_lengths[] = { 852 1, /* BYTE */ 853 2, /* WORD */ 854 4, /* LONG */ 855 8, /* QUAD */ 856 4, /* SNGL */ 857 8, /* DBLR */ 858 10, /* EXTR */ 859}; 860 861#define get_value_inc(result, loc, size, is_signed) \ 862 result = db_get_value((loc), (size), (is_signed)); \ 863 (loc) += (size); 864 865static db_addr_t 866 db_disasm_esc(db_addr_t loc, int inst, int short_addr, 867 int size, const char *seg); 868static void db_print_address(const char *seg, int size, 869 struct i_addr *addrp); 870static db_addr_t 871 db_read_address(db_addr_t loc, int short_addr, int regmodrm, 872 struct i_addr *addrp); 873 874/* 875 * Read address at location and return updated location. 876 */ 877static db_addr_t 878db_read_address(loc, short_addr, regmodrm, addrp) 879 db_addr_t loc; 880 int short_addr; 881 int regmodrm; 882 struct i_addr * addrp; /* out */ 883{ 884 int mod, rm, sib, index, disp; 885 886 mod = f_mod(regmodrm); 887 rm = f_rm(regmodrm); 888 889 if (mod == 3) { 890 addrp->is_reg = TRUE; 891 addrp->disp = rm; 892 return (loc); 893 } 894 addrp->is_reg = FALSE; 895 addrp->index = 0; 896 897 if (short_addr) { 898 addrp->index = 0; 899 addrp->ss = 0; 900 switch (mod) { 901 case 0: 902 if (rm == 6) { 903 get_value_inc(disp, loc, 2, FALSE); 904 addrp->disp = disp; 905 addrp->base = 0; 906 } 907 else { 908 addrp->disp = 0; 909 addrp->base = db_index_reg_16[rm]; 910 } 911 break; 912 case 1: 913 get_value_inc(disp, loc, 1, TRUE); 914 disp &= 0xFFFF; 915 addrp->disp = disp; 916 addrp->base = db_index_reg_16[rm]; 917 break; 918 case 2: 919 get_value_inc(disp, loc, 2, FALSE); 920 addrp->disp = disp; 921 addrp->base = db_index_reg_16[rm]; 922 break; 923 } 924 } 925 else { 926 if (mod != 3 && rm == 4) { 927 get_value_inc(sib, loc, 1, FALSE); 928 rm = sib_base(sib); 929 index = sib_index(sib); 930 if (index != 4) 931 addrp->index = db_reg[LONG][index]; 932 addrp->ss = sib_ss(sib); 933 } 934 935 switch (mod) { 936 case 0: 937 if (rm == 5) { 938 get_value_inc(addrp->disp, loc, 4, FALSE); 939 addrp->base = 0; 940 } 941 else { 942 addrp->disp = 0; 943 addrp->base = db_reg[LONG][rm]; 944 } 945 break; 946 947 case 1: 948 get_value_inc(disp, loc, 1, TRUE); 949 addrp->disp = disp; 950 addrp->base = db_reg[LONG][rm]; 951 break; 952 953 case 2: 954 get_value_inc(disp, loc, 4, FALSE); 955 addrp->disp = disp; 956 addrp->base = db_reg[LONG][rm]; 957 break; 958 } 959 } 960 return (loc); 961} 962 963static void 964db_print_address(seg, size, addrp) 965 const char * seg; 966 int size; 967 struct i_addr * addrp; 968{ 969 if (addrp->is_reg) { 970 db_printf("%s", db_reg[size][addrp->disp]); 971 return; 972 } 973 974 if (seg) { 975 db_printf("%s:", seg); 976 } 977 978 db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); 979 if (addrp->base != 0 || addrp->index != 0) { 980 db_printf("("); 981 if (addrp->base) 982 db_printf("%s", addrp->base); 983 if (addrp->index) 984 db_printf(",%s,%d", addrp->index, 1<<addrp->ss); 985 db_printf(")"); 986 } 987} 988 989/* 990 * Disassemble floating-point ("escape") instruction 991 * and return updated location. 992 */ 993static db_addr_t 994db_disasm_esc(loc, inst, short_addr, size, seg) 995 db_addr_t loc; 996 int inst; 997 int short_addr; 998 int size; 999 const char * seg; 1000{ 1001 int regmodrm; 1002 const struct finst * fp; 1003 int mod; 1004 struct i_addr address; 1005 const char * name; 1006 1007 get_value_inc(regmodrm, loc, 1, FALSE); 1008 fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; 1009 mod = f_mod(regmodrm); 1010 if (mod != 3) { 1011 if (*fp->f_name == '\0') { 1012 db_printf("<bad instruction>"); 1013 return (loc); 1014 } 1015 /* 1016 * Normal address modes. 1017 */ 1018 loc = db_read_address(loc, short_addr, regmodrm, &address); 1019 db_printf("%s", fp->f_name); 1020 switch(fp->f_size) { 1021 case SNGL: 1022 db_printf("s"); 1023 break; 1024 case DBLR: 1025 db_printf("l"); 1026 break; 1027 case EXTR: 1028 db_printf("t"); 1029 break; 1030 case WORD: 1031 db_printf("s"); 1032 break; 1033 case LONG: 1034 db_printf("l"); 1035 break; 1036 case QUAD: 1037 db_printf("q"); 1038 break; 1039 default: 1040 break; 1041 } 1042 db_printf("\t"); 1043 db_print_address(seg, BYTE, &address); 1044 } 1045 else { 1046 /* 1047 * 'reg-reg' - special formats 1048 */ 1049 switch (fp->f_rrmode) { 1050 case op2(ST,STI): 1051 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1052 db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm)); 1053 break; 1054 case op2(STI,ST): 1055 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1056 db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm)); 1057 break; 1058 case op1(STI): 1059 name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1060 db_printf("%s\t%%st(%d)",name, f_rm(regmodrm)); 1061 break; 1062 case op1(X): 1063 name = ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]; 1064 if (*name == '\0') 1065 goto bad; 1066 db_printf("%s", name); 1067 break; 1068 case op1(XA): 1069 name = ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]; 1070 if (*name == '\0') 1071 goto bad; 1072 db_printf("%s\t%%ax", name); 1073 break; 1074 default: 1075 bad: 1076 db_printf("<bad instruction>"); 1077 break; 1078 } 1079 } 1080 1081 return (loc); 1082} 1083 1084/* 1085 * Disassemble instruction at 'loc'. 'altfmt' specifies an 1086 * (optional) alternate format. Return address of start of 1087 * next instruction. 1088 */ 1089db_addr_t 1090db_disasm(loc, altfmt) 1091 db_addr_t loc; 1092 boolean_t altfmt; 1093{ 1094 int inst; 1095 int size; 1096 int short_addr; 1097 const char * seg; 1098 const struct inst * ip; 1099 const char * i_name; 1100 int i_size; 1101 int i_mode; 1102 int regmodrm = 0; 1103 boolean_t first; 1104 int displ; 1105 int prefix; 1106 int imm; 1107 int imm2; 1108 int len; 1109 struct i_addr address; 1110 1111 get_value_inc(inst, loc, 1, FALSE); 1112 short_addr = FALSE; 1113 size = LONG; 1114 seg = 0; 1115 1116 /* 1117 * Get prefixes 1118 */ 1119 prefix = TRUE; 1120 do { 1121 switch (inst) { 1122 case 0x66: /* data16 */ 1123 size = WORD; 1124 break; 1125 case 0x67: 1126 short_addr = TRUE; 1127 break; 1128 case 0x26: 1129 seg = "%es"; 1130 break; 1131 case 0x36: 1132 seg = "%ss"; 1133 break; 1134 case 0x2e: 1135 seg = "%cs"; 1136 break; 1137 case 0x3e: 1138 seg = "%ds"; 1139 break; 1140 case 0x64: 1141 seg = "%fs"; 1142 break; 1143 case 0x65: 1144 seg = "%gs"; 1145 break; 1146 case 0xf0: 1147 db_printf("lock "); 1148 break; 1149 case 0xf2: 1150 db_printf("repne "); 1151 break; 1152 case 0xf3: 1153 db_printf("repe "); /* XXX repe VS rep */ 1154 break; 1155 default: 1156 prefix = FALSE; 1157 break; 1158 } 1159 if (prefix) { 1160 get_value_inc(inst, loc, 1, FALSE); 1161 } 1162 } while (prefix); 1163 1164 if (inst >= 0xd8 && inst <= 0xdf) { 1165 loc = db_disasm_esc(loc, inst, short_addr, size, seg); 1166 db_printf("\n"); 1167 return (loc); 1168 } 1169 1170 if (inst == 0x0f) { 1171 get_value_inc(inst, loc, 1, FALSE); 1172 ip = db_inst_0f[inst>>4]; 1173 if (ip == 0) { 1174 ip = &db_bad_inst; 1175 } 1176 else { 1177 ip = &ip[inst&0xf]; 1178 } 1179 } 1180 else 1181 ip = &db_inst_table[inst]; 1182 1183 if (ip->i_has_modrm) { 1184 get_value_inc(regmodrm, loc, 1, FALSE); 1185 loc = db_read_address(loc, short_addr, regmodrm, &address); 1186 } 1187 1188 i_name = ip->i_name; 1189 i_size = ip->i_size; 1190 i_mode = ip->i_mode; 1191 1192 if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 || 1193 ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 || 1194 ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9) { 1195 i_name = ((const char * const *)ip->i_extra)[f_reg(regmodrm)]; 1196 } 1197 else if (ip->i_extra == db_Grp3) { 1198 ip = ip->i_extra; 1199 ip = &ip[f_reg(regmodrm)]; 1200 i_name = ip->i_name; 1201 i_mode = ip->i_mode; 1202 } 1203 else if (ip->i_extra == db_Grp4 || ip->i_extra == db_Grp5) { 1204 ip = ip->i_extra; 1205 ip = &ip[f_reg(regmodrm)]; 1206 i_name = ip->i_name; 1207 i_mode = ip->i_mode; 1208 i_size = ip->i_size; 1209 } 1210 1211 if (i_size == SDEP) { 1212 if (size == WORD) 1213 db_printf("%s", i_name); 1214 else 1215 db_printf("%s", (const char *)ip->i_extra); 1216 } 1217 else { 1218 db_printf("%s", i_name); 1219 if (i_size != NONE) { 1220 if (i_size == BYTE) { 1221 db_printf("b"); 1222 size = BYTE; 1223 } 1224 else if (i_size == WORD) { 1225 db_printf("w"); 1226 size = WORD; 1227 } 1228 else if (size == WORD) 1229 db_printf("w"); 1230 else 1231 db_printf("l"); 1232 } 1233 } 1234 db_printf("\t"); 1235 for (first = TRUE; 1236 i_mode != 0; 1237 i_mode >>= 8, first = FALSE) 1238 { 1239 if (!first) 1240 db_printf(","); 1241 1242 switch (i_mode & 0xFF) { 1243 1244 case E: 1245 db_print_address(seg, size, &address); 1246 break; 1247 1248 case Eind: 1249 db_printf("*"); 1250 db_print_address(seg, size, &address); 1251 break; 1252 1253 case El: 1254 db_print_address(seg, LONG, &address); 1255 break; 1256 1257 case Ew: 1258 db_print_address(seg, WORD, &address); 1259 break; 1260 1261 case Eb: 1262 db_print_address(seg, BYTE, &address); 1263 break; 1264 1265 case R: 1266 db_printf("%s", db_reg[size][f_reg(regmodrm)]); 1267 break; 1268 1269 case Rw: 1270 db_printf("%s", db_reg[WORD][f_reg(regmodrm)]); 1271 break; 1272 1273 case Ri: 1274 db_printf("%s", db_reg[size][f_rm(inst)]); 1275 break; 1276 1277 case Ril: 1278 db_printf("%s", db_reg[LONG][f_rm(inst)]); 1279 break; 1280 1281 case S: 1282 db_printf("%s", db_seg_reg[f_reg(regmodrm)]); 1283 break; 1284 1285 case Si: 1286 db_printf("%s", db_seg_reg[f_reg(inst)]); 1287 break; 1288 1289 case A: 1290 db_printf("%s", db_reg[size][0]); /* acc */ 1291 break; 1292 1293 case BX: 1294 if (seg) 1295 db_printf("%s:", seg); 1296 db_printf("(%s)", short_addr ? "%bx" : "%ebx"); 1297 break; 1298 1299 case CL: 1300 db_printf("%%cl"); 1301 break; 1302 1303 case DX: 1304 db_printf("%%dx"); 1305 break; 1306 1307 case SI: 1308 if (seg) 1309 db_printf("%s:", seg); 1310 db_printf("(%s)", short_addr ? "%si" : "%esi"); 1311 break; 1312 1313 case DI: 1314 db_printf("%%es:(%s)", short_addr ? "%di" : "%edi"); 1315 break; 1316 1317 case CR: 1318 db_printf("%%cr%d", f_reg(regmodrm)); 1319 break; 1320 1321 case DR: 1322 db_printf("%%dr%d", f_reg(regmodrm)); 1323 break; 1324 1325 case TR: 1326 db_printf("%%tr%d", f_reg(regmodrm)); 1327 break; 1328 1329 case I: 1330 len = db_lengths[size]; 1331 get_value_inc(imm, loc, len, FALSE); 1332 db_printf("$%#r", imm); 1333 break; 1334 1335 case Is: 1336 len = db_lengths[size]; 1337 get_value_inc(imm, loc, len, FALSE); 1338 db_printf("$%+#r", imm); 1339 break; 1340 1341 case Ib: 1342 get_value_inc(imm, loc, 1, FALSE); 1343 db_printf("$%#r", imm); 1344 break; 1345 1346 case Iba: 1347 get_value_inc(imm, loc, 1, FALSE); 1348 if (imm != 0x0a) 1349 db_printf("$%#r", imm); 1350 break; 1351 1352 case Ibs: 1353 get_value_inc(imm, loc, 1, TRUE); 1354 if (size == WORD) 1355 imm &= 0xFFFF; 1356 db_printf("$%+#r", imm); 1357 break; 1358 1359 case Iw: 1360 get_value_inc(imm, loc, 2, FALSE); 1361 db_printf("$%#r", imm); 1362 break; 1363 1364 case O: 1365 len = (short_addr ? 2 : 4); 1366 get_value_inc(displ, loc, len, FALSE); 1367 if (seg) 1368 db_printf("%s:%+#r",seg, displ); 1369 else 1370 db_printsym((db_addr_t)displ, DB_STGY_ANY); 1371 break; 1372 1373 case Db: 1374 get_value_inc(displ, loc, 1, TRUE); 1375 displ += loc; 1376 if (size == WORD) 1377 displ &= 0xFFFF; 1378 db_printsym((db_addr_t)displ, DB_STGY_XTRN); 1379 break; 1380 1381 case Dl: 1382 len = db_lengths[size]; 1383 get_value_inc(displ, loc, len, FALSE); 1384 displ += loc; 1385 if (size == WORD) 1386 displ &= 0xFFFF; 1387 db_printsym((db_addr_t)displ, DB_STGY_XTRN); 1388 break; 1389 1390 case o1: 1391 db_printf("$1"); 1392 break; 1393 1394 case o3: 1395 db_printf("$3"); 1396 break; 1397 1398 case OS: 1399 len = db_lengths[size]; 1400 get_value_inc(imm, loc, len, FALSE); /* offset */ 1401 get_value_inc(imm2, loc, 2, FALSE); /* segment */ 1402 db_printf("$%#r,%#r", imm2, imm); 1403 break; 1404 } 1405 } 1406 db_printf("\n"); 1407 return (loc); 1408} 1409