db_disasm.c revision 238109
1177867Sjfv/*- 287189Spdeuskar * Mach Operating System 3284444Ssbruno * Copyright (c) 1991,1990 Carnegie Mellon University 4177867Sjfv * All Rights Reserved. 5177867Sjfv * 6177867Sjfv * Permission to use, copy, modify and distribute this software and its 7177867Sjfv * documentation is hereby granted, provided that both the copyright 8177867Sjfv * notice and this permission notice appear in all copies of the 9177867Sjfv * software, derivative works or modified versions, and any portions 10177867Sjfv * thereof, and that both notices appear in supporting documentation. 11177867Sjfv * 12177867Sjfv * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13177867Sjfv * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14177867Sjfv * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15177867Sjfv * 16177867Sjfv * Carnegie Mellon requests users of this software to return to 17177867Sjfv * 18177867Sjfv * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19177867Sjfv * School of Computer Science 20177867Sjfv * Carnegie Mellon University 21177867Sjfv * Pittsburgh PA 15213-3890 22177867Sjfv * 23177867Sjfv * any improvements or extensions that they make and grant Carnegie the 24177867Sjfv * rights to redistribute these changes. 25177867Sjfv */ 26177867Sjfv 27177867Sjfv#include <sys/cdefs.h> 28177867Sjfv__FBSDID("$FreeBSD: head/sys/amd64/amd64/db_disasm.c 238109 2012-07-04 16:47:39Z jhb $"); 29177867Sjfv 30177867Sjfv/* 3187189Spdeuskar * Instruction disassembler. 32177867Sjfv */ 33177867Sjfv#include <sys/param.h> 3487189Spdeuskar 35284522Ssbruno#include <ddb/ddb.h> 36284522Ssbruno#include <ddb/db_access.h> 37253303Sjfv#include <ddb/db_sym.h> 38253303Sjfv 39253303Sjfv/* 40150968Sglebius * Size attributes 41150968Sglebius */ 42150968Sglebius#define BYTE 0 43150968Sglebius#define WORD 1 44155674Sglebius#define LONG 2 45155674Sglebius#define QUAD 3 46284522Ssbruno#define SNGL 4 47284522Ssbruno#define DBLR 5 48284522Ssbruno#define EXTR 6 49284522Ssbruno#define SDEP 7 50194865Sjfv#define NONE 8 51191038Skmacy 52194865Sjfv/* 53155674Sglebius * REX prefix and bits 54155674Sglebius */ 55155674Sglebius#define REX_B 1 56155674Sglebius#define REX_X 2 57155674Sglebius#define REX_R 4 58155674Sglebius#define REX_W 8 59155674Sglebius#define REX 0x40 60155674Sglebius 61284522Ssbruno/* 62155674Sglebius * Addressing modes 63155674Sglebius */ 64155674Sglebius#define E 1 /* general effective address */ 65155674Sglebius#define Eind 2 /* indirect address (jump, call) */ 66185353Sjfv#define Ew 3 /* address, word size */ 67155674Sglebius#define Eb 4 /* address, byte size */ 68155674Sglebius#define R 5 /* register, in 'reg' field */ 69155674Sglebius#define Rw 6 /* word register, in 'reg' field */ 70155674Sglebius#define Ri 7 /* register in instruction */ 71155674Sglebius#define S 8 /* segment reg, in 'reg' field */ 72155674Sglebius#define Si 9 /* segment reg, in instruction */ 73155674Sglebius#define A 10 /* accumulator */ 74155674Sglebius#define BX 11 /* (bx) */ 75155674Sglebius#define CL 12 /* cl, for shifts */ 76155674Sglebius#define DX 13 /* dx, for IO */ 77155674Sglebius#define SI 14 /* si */ 78155674Sglebius#define DI 15 /* di */ 79155674Sglebius#define CR 16 /* control register */ 80155674Sglebius#define DR 17 /* debug register */ 81155674Sglebius#define TR 18 /* test register */ 82160519Syongari#define I 19 /* immediate, unsigned */ 83155674Sglebius#define Is 20 /* immediate, signed */ 84163730Sjfv#define Ib 21 /* byte immediate, unsigned */ 85155674Sglebius#define Ibs 22 /* byte immediate, signed */ 86155674Sglebius#define Iw 23 /* word immediate, unsigned */ 87155674Sglebius#define Ilq 24 /* long/quad immediate, unsigned */ 88162187Spdeuskar#define O 25 /* direct address */ 89206001Smarius#define Db 26 /* byte displacement from EIP */ 90155674Sglebius#define Dl 27 /* long displacement from EIP */ 91155674Sglebius#define o1 28 /* constant 1 */ 9287189Spdeuskar#define o3 29 /* constant 3 */ 93169240Sjfv#define OS 30 /* immediate offset/segment */ 94179181Sjfv#define ST 31 /* FP stack top */ 95169240Sjfv#define STI 32 /* FP stack */ 96169240Sjfv#define X 33 /* extended FP op */ 9787189Spdeuskar#define XA 34 /* for 'fstcw %ax' */ 98169240Sjfv#define El 35 /* address, long/quad size */ 9987189Spdeuskar#define Ril 36 /* long register in instruction */ 100296055Serj#define Iba 37 /* byte immediate, don't print if 0xa */ 10187189Spdeuskar#define EL 38 /* address, explicitly long size */ 10287189Spdeuskar 10387189Spdeuskarstruct inst { 10487189Spdeuskar const char * i_name; /* name */ 10587189Spdeuskar short i_has_modrm; /* has regmodrm byte */ 106169240Sjfv short i_size; /* operand size */ 10787189Spdeuskar int i_mode; /* addressing modes */ 10887189Spdeuskar const void * i_extra; /* pointer to extra opcode table */ 10987189Spdeuskar}; 11087189Spdeuskar 111112472Spdeuskar#define op1(x) (x) 11287189Spdeuskar#define op2(x,y) ((x)|((y)<<8)) 11387189Spdeuskar#define op3(x,y,z) ((x)|((y)<<8)|((z)<<16)) 114155709Sglebius 115155709Sglebiusstruct finst { 116155709Sglebius const char * f_name; /* name for memory instruction */ 117155709Sglebius int f_size; /* size for memory instruction */ 118179181Sjfv int f_rrmode; /* mode for rr instruction */ 119179181Sjfv const void * f_rrname; /* name for rr instruction 120179181Sjfv (or pointer to table) */ 121179181Sjfv}; 122161205Sglebius 123161205Sglebiusstatic const char * const db_Grp6[] = { 124169240Sjfv "sldt", 125163824Sglebius "str", 126169240Sjfv "lldt", 127169240Sjfv "ltr", 128173788Sjfv "verr", 129173788Sjfv "verw", 130155709Sglebius "", 131155709Sglebius "" 132155709Sglebius}; 133157566Sglebius 134152740Sglebiusstatic const char * const db_Grp7[] = { 135155709Sglebius "sgdt", 136155709Sglebius "sidt", 137155709Sglebius "lgdt", 138194865Sjfv "lidt", 139160949Sglebius "smsw", 140160949Sglebius "", 141160949Sglebius "lmsw", 142160949Sglebius "invlpg" 143157566Sglebius}; 144157566Sglebius 145157566Sglebiusstatic const char * const db_Grp8[] = { 146157566Sglebius "", 147163824Sglebius "", 148160949Sglebius "", 149160949Sglebius "", 150160949Sglebius "bt", 151163824Sglebius "bts", 152163824Sglebius "btr", 153163824Sglebius "btc" 154200243Sjfv}; 155179181Sjfv 156169240Sjfvstatic const char * const db_Grp9[] = { 157169240Sjfv "", 158179181Sjfv "cmpxchg8b", 159179181Sjfv "", 160169240Sjfv "", 161169240Sjfv "", 162169240Sjfv "", 163179136Sjfv "", 164178523Sjfv "" 165194865Sjfv}; 166179181Sjfv 167179181Sjfvstatic const char * const db_Grp15[] = { 168179181Sjfv "fxsave", 169178523Sjfv "fxrstor", 170178523Sjfv "ldmxcsr", 171213234Sjfv "stmxcsr", 172200243Sjfv "xsave", 173200243Sjfv "xrstor", 174200243Sjfv "xsaveopt", 175200243Sjfv "clflush" 176214363Sjfv}; 177214363Sjfv 178247064Sjfvstatic const char * const db_Grp15b[] = { 179247064Sjfv "", 180247064Sjfv "", 181247064Sjfv "", 182247064Sjfv "", 183247064Sjfv "", 184269196Sjfv "lfence", 185269196Sjfv "mfence", 186269196Sjfv "sfence" 187269196Sjfv}; 188296055Serj 189296055Serjstatic const struct inst db_inst_0f0x[] = { 190296055Serj/*00*/ { "", TRUE, NONE, op1(Ew), db_Grp6 }, 191296055Serj/*01*/ { "", TRUE, NONE, op1(Ew), db_Grp7 }, 192296055Serj/*02*/ { "lar", TRUE, LONG, op2(E,R), 0 }, 193296055Serj/*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 }, 194296055Serj/*04*/ { "", FALSE, NONE, 0, 0 }, 195155709Sglebius/*05*/ { "syscall",FALSE,NONE, 0, 0 }, 196155709Sglebius/*06*/ { "clts", FALSE, NONE, 0, 0 }, 19787189Spdeuskar/*07*/ { "sysret",FALSE, NONE, 0, 0 }, 19887189Spdeuskar 19987189Spdeuskar/*08*/ { "invd", FALSE, NONE, 0, 0 }, 20087189Spdeuskar/*09*/ { "wbinvd",FALSE, NONE, 0, 0 }, 20187189Spdeuskar/*0a*/ { "", FALSE, NONE, 0, 0 }, 20287189Spdeuskar/*0b*/ { "", FALSE, NONE, 0, 0 }, 20387189Spdeuskar/*0c*/ { "", FALSE, NONE, 0, 0 }, 20497785Spdeuskar/*0d*/ { "", FALSE, NONE, 0, 0 }, 20587189Spdeuskar/*0e*/ { "", FALSE, NONE, 0, 0 }, 20687189Spdeuskar/*0f*/ { "", FALSE, NONE, 0, 0 }, 20787189Spdeuskar}; 208154571Sglebius 20987189Spdeuskarstatic const struct inst db_inst_0f2x[] = { 210155709Sglebius/*20*/ { "mov", TRUE, LONG, op2(CR,El), 0 }, 211155709Sglebius/*21*/ { "mov", TRUE, LONG, op2(DR,El), 0 }, 212155709Sglebius/*22*/ { "mov", TRUE, LONG, op2(El,CR), 0 }, 213155709Sglebius/*23*/ { "mov", TRUE, LONG, op2(El,DR), 0 }, 214155709Sglebius/*24*/ { "mov", TRUE, LONG, op2(TR,El), 0 }, 215155709Sglebius/*25*/ { "", FALSE, NONE, 0, 0 }, 216206429Sjfv/*26*/ { "mov", TRUE, LONG, op2(El,TR), 0 }, 217194865Sjfv/*27*/ { "", FALSE, NONE, 0, 0 }, 218205869Sjfv 219284522Ssbruno/*28*/ { "", FALSE, NONE, 0, 0 }, 220194865Sjfv/*29*/ { "", FALSE, NONE, 0, 0 }, 221233708Sjhb/*2a*/ { "", FALSE, NONE, 0, 0 }, 222233708Sjhb/*2b*/ { "", FALSE, NONE, 0, 0 }, 223233708Sjhb/*2c*/ { "", FALSE, NONE, 0, 0 }, 224194865Sjfv/*2d*/ { "", FALSE, NONE, 0, 0 }, 225155709Sglebius/*2e*/ { "", FALSE, NONE, 0, 0 }, 226155709Sglebius/*2f*/ { "", FALSE, NONE, 0, 0 }, 227160956Spdeuskar}; 228155709Sglebius 229155709Sglebiusstatic const struct inst db_inst_0f3x[] = { 230155709Sglebius/*30*/ { "wrmsr", FALSE, NONE, 0, 0 }, 231160956Spdeuskar/*31*/ { "rdtsc", FALSE, NONE, 0, 0 }, 232160956Spdeuskar/*32*/ { "rdmsr", FALSE, NONE, 0, 0 }, 233205869Sjfv/*33*/ { "rdpmc", FALSE, NONE, 0, 0 }, 234205869Sjfv/*34*/ { "sysenter",FALSE,NONE, 0, 0 }, 235205869Sjfv/*35*/ { "sysexit",FALSE,NONE, 0, 0 }, 236176667Sjfv/*36*/ { "", FALSE, NONE, 0, 0 }, 237160956Spdeuskar/*37*/ { "getsec",FALSE, NONE, 0, 0 }, 238155709Sglebius 239205869Sjfv/*38*/ { "", FALSE, NONE, 0, 0 }, 240211907Syongari/*39*/ { "", FALSE, NONE, 0, 0 }, 241296055Serj/*3a*/ { "", FALSE, NONE, 0, 0 }, 242205869Sjfv/*3b*/ { "", FALSE, NONE, 0, 0 }, 243173788Sjfv/*3c*/ { "", FALSE, NONE, 0, 0 }, 244160956Spdeuskar/*3d*/ { "", FALSE, NONE, 0, 0 }, 245205869Sjfv/*3e*/ { "", FALSE, NONE, 0, 0 }, 246205869Sjfv/*3f*/ { "", FALSE, NONE, 0, 0 }, 247205869Sjfv}; 248205869Sjfv 249160956Spdeuskarstatic const struct inst db_inst_0f4x[] = { 250205869Sjfv/*40*/ { "cmovo", TRUE, NONE, op2(E, R), 0 }, 251160956Spdeuskar/*41*/ { "cmovno", TRUE, NONE, op2(E, R), 0 }, 252205869Sjfv/*42*/ { "cmovb", TRUE, NONE, op2(E, R), 0 }, 253205869Sjfv/*43*/ { "cmovnb", TRUE, NONE, op2(E, R), 0 }, 254205869Sjfv/*44*/ { "cmovz", TRUE, NONE, op2(E, R), 0 }, 255160956Spdeuskar/*45*/ { "cmovnz", TRUE, NONE, op2(E, R), 0 }, 256160956Spdeuskar/*46*/ { "cmovbe", TRUE, NONE, op2(E, R), 0 }, 257160956Spdeuskar/*47*/ { "cmovnbe",TRUE, NONE, op2(E, R), 0 }, 258209242Sgnn 259233708Sjhb/*48*/ { "cmovs", TRUE, NONE, op2(E, R), 0 }, 260209238Sjfv/*49*/ { "cmovns", TRUE, NONE, op2(E, R), 0 }, 261153474Syongari/*4a*/ { "cmovp", TRUE, NONE, op2(E, R), 0 }, 262205869Sjfv/*4b*/ { "cmovnp", TRUE, NONE, op2(E, R), 0 }, 263153474Syongari/*4c*/ { "cmovl", TRUE, NONE, op2(E, R), 0 }, 264294958Smarius/*4d*/ { "cmovnl", TRUE, NONE, op2(E, R), 0 }, 265294958Smarius/*4e*/ { "cmovle", TRUE, NONE, op2(E, R), 0 }, 266294958Smarius/*4f*/ { "cmovnle",TRUE, NONE, op2(E, R), 0 }, 267213234Sjfv}; 268213234Sjfv 269213234Sjfvstatic const struct inst db_inst_0f8x[] = { 270213234Sjfv/*80*/ { "jo", FALSE, NONE, op1(Dl), 0 }, 271160956Spdeuskar/*81*/ { "jno", FALSE, NONE, op1(Dl), 0 }, 272160956Spdeuskar/*82*/ { "jb", FALSE, NONE, op1(Dl), 0 }, 273160956Spdeuskar/*83*/ { "jnb", FALSE, NONE, op1(Dl), 0 }, 274160956Spdeuskar/*84*/ { "jz", FALSE, NONE, op1(Dl), 0 }, 275205869Sjfv/*85*/ { "jnz", FALSE, NONE, op1(Dl), 0 }, 276185353Sjfv/*86*/ { "jbe", FALSE, NONE, op1(Dl), 0 }, 277185353Sjfv/*87*/ { "jnbe", FALSE, NONE, op1(Dl), 0 }, 278194865Sjfv 279205869Sjfv/*88*/ { "js", FALSE, NONE, op1(Dl), 0 }, 280160956Spdeuskar/*89*/ { "jns", FALSE, NONE, op1(Dl), 0 }, 281169240Sjfv/*8a*/ { "jp", FALSE, NONE, op1(Dl), 0 }, 282160956Spdeuskar/*8b*/ { "jnp", FALSE, NONE, op1(Dl), 0 }, 283209242Sgnn/*8c*/ { "jl", FALSE, NONE, op1(Dl), 0 }, 284173788Sjfv/*8d*/ { "jnl", FALSE, NONE, op1(Dl), 0 }, 285214363Sjfv/*8e*/ { "jle", FALSE, NONE, op1(Dl), 0 }, 286214363Sjfv/*8f*/ { "jnle", FALSE, NONE, op1(Dl), 0 }, 287176667Sjfv}; 288155709Sglebius 289160956Spdeuskarstatic const struct inst db_inst_0f9x[] = { 290169240Sjfv/*90*/ { "seto", TRUE, NONE, op1(Eb), 0 }, 291169240Sjfv/*91*/ { "setno", TRUE, NONE, op1(Eb), 0 }, 292169240Sjfv/*92*/ { "setb", TRUE, NONE, op1(Eb), 0 }, 293169240Sjfv/*93*/ { "setnb", TRUE, NONE, op1(Eb), 0 }, 294169240Sjfv/*94*/ { "setz", TRUE, NONE, op1(Eb), 0 }, 295169240Sjfv/*95*/ { "setnz", TRUE, NONE, op1(Eb), 0 }, 296200243Sjfv/*96*/ { "setbe", TRUE, NONE, op1(Eb), 0 }, 297169240Sjfv/*97*/ { "setnbe",TRUE, NONE, op1(Eb), 0 }, 298200243Sjfv 299206001Smarius/*98*/ { "sets", TRUE, NONE, op1(Eb), 0 }, 300215808Sjfv/*99*/ { "setns", TRUE, NONE, op1(Eb), 0 }, 301159330Sglebius/*9a*/ { "setp", TRUE, NONE, op1(Eb), 0 }, 302176667Sjfv/*9b*/ { "setnp", TRUE, NONE, op1(Eb), 0 }, 303190872Sjfv/*9c*/ { "setl", TRUE, NONE, op1(Eb), 0 }, 304178523Sjfv/*9d*/ { "setnl", TRUE, NONE, op1(Eb), 0 }, 305178523Sjfv/*9e*/ { "setle", TRUE, NONE, op1(Eb), 0 }, 306178523Sjfv/*9f*/ { "setnle",TRUE, NONE, op1(Eb), 0 }, 307178523Sjfv}; 308205869Sjfv 309176667Sjfvstatic const struct inst db_inst_0fax[] = { 310205869Sjfv/*a0*/ { "push", FALSE, NONE, op1(Si), 0 }, 311190872Sjfv/*a1*/ { "pop", FALSE, NONE, op1(Si), 0 }, 312284522Ssbruno/*a2*/ { "cpuid", FALSE, NONE, 0, 0 }, 313284522Ssbruno/*a3*/ { "bt", TRUE, LONG, op2(R,E), 0 }, 314284522Ssbruno/*a4*/ { "shld", TRUE, LONG, op3(Ib,R,E), 0 }, 315284522Ssbruno/*a5*/ { "shld", TRUE, LONG, op3(CL,R,E), 0 }, 316219753Sjfv/*a6*/ { "", FALSE, NONE, 0, 0 }, 317190872Sjfv/*a7*/ { "", FALSE, NONE, 0, 0 }, 318228387Sjfv 319238214Sjfv/*a8*/ { "push", FALSE, NONE, op1(Si), 0 }, 32097785Spdeuskar/*a9*/ { "pop", FALSE, NONE, op1(Si), 0 }, 321212303Sjfv/*aa*/ { "rsm", FALSE, NONE, 0, 0 }, 322212303Sjfv/*ab*/ { "bts", TRUE, LONG, op2(R,E), 0 }, 323173820Sru/*ac*/ { "shrd", TRUE, LONG, op3(Ib,R,E), 0 }, 324173820Sru/*ad*/ { "shrd", TRUE, LONG, op3(CL,R,E), 0 }, 325173820Sru/*ae*/ { "", TRUE, LONG, op1(E), db_Grp15 }, 326173820Sru/*af*/ { "imul", TRUE, LONG, op2(E,R), 0 }, 32787189Spdeuskar}; 328154571Sglebius 32987189Spdeuskarstatic const struct inst db_inst_0fbx[] = { 33087189Spdeuskar/*b0*/ { "cmpxchg",TRUE, BYTE, op2(R, E), 0 }, 33187189Spdeuskar/*b0*/ { "cmpxchg",TRUE, LONG, op2(R, E), 0 }, 33297785Spdeuskar/*b2*/ { "lss", TRUE, LONG, op2(E, R), 0 }, 33397785Spdeuskar/*b3*/ { "btr", TRUE, LONG, op2(R, E), 0 }, 33497785Spdeuskar/*b4*/ { "lfs", TRUE, LONG, op2(E, R), 0 }, 33597785Spdeuskar/*b5*/ { "lgs", TRUE, LONG, op2(E, R), 0 }, 33697785Spdeuskar/*b6*/ { "movzb", TRUE, LONG, op2(Eb, R), 0 }, 337153729Sglebius/*b7*/ { "movzw", TRUE, LONG, op2(Ew, R), 0 }, 338153729Sglebius 339246128Ssbz/*b8*/ { "", FALSE, NONE, 0, 0 }, 34087189Spdeuskar/*b9*/ { "", FALSE, NONE, 0, 0 }, 34187189Spdeuskar/*ba*/ { "", TRUE, LONG, op2(Ib, E), db_Grp8 }, 34287189Spdeuskar/*bb*/ { "btc", TRUE, LONG, op2(R, E), 0 }, 343160956Spdeuskar/*bc*/ { "bsf", TRUE, LONG, op2(E, R), 0 }, 34487189Spdeuskar/*bd*/ { "bsr", TRUE, LONG, op2(E, R), 0 }, 34587189Spdeuskar/*be*/ { "movsb", TRUE, LONG, op2(Eb, R), 0 }, 346205869Sjfv/*bf*/ { "movsw", TRUE, LONG, op2(Ew, R), 0 }, 347113506Smdodd}; 348113506Smdodd 349113506Smdoddstatic const struct inst db_inst_0fcx[] = { 35087189Spdeuskar/*c0*/ { "xadd", TRUE, BYTE, op2(R, E), 0 }, 35187189Spdeuskar/*c1*/ { "xadd", TRUE, LONG, op2(R, E), 0 }, 352118314Sjdp/*c2*/ { "", FALSE, NONE, 0, 0 }, 353118314Sjdp/*c3*/ { "", FALSE, NONE, 0, 0 }, 354118314Sjdp/*c4*/ { "", FALSE, NONE, 0, 0 }, 355169240Sjfv/*c5*/ { "", FALSE, NONE, 0, 0 }, 356169240Sjfv/*c6*/ { "", FALSE, NONE, 0, 0 }, 357163730Sjfv/*c7*/ { "", TRUE, NONE, op1(E), db_Grp9 }, 358118314Sjdp/*c8*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 359250414Sluigi/*c9*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 360250414Sluigi/*ca*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 361250414Sluigi/*cb*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 362173788Sjfv/*cc*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 363173788Sjfv/*cd*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 364173788Sjfv/*ce*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 365173788Sjfv/*cf*/ { "bswap", FALSE, LONG, op1(Ril), 0 }, 366173788Sjfv}; 367294958Smarius 368294958Smariusstatic const struct inst * const db_inst_0f[] = { 369227309Sed db_inst_0f0x, 370223676Sjhb 0, 371294958Smarius db_inst_0f2x, 372294958Smarius db_inst_0f3x, 373294958Smarius db_inst_0f4x, 374294958Smarius 0, 375169240Sjfv 0, 376169240Sjfv 0, 377205869Sjfv db_inst_0f8x, 378205869Sjfv db_inst_0f9x, 379223676Sjhb db_inst_0fax, 380223676Sjhb db_inst_0fbx, 381223676Sjhb db_inst_0fcx, 382223676Sjhb 0, 383205869Sjfv 0, 384169240Sjfv 0 385169240Sjfv}; 386205869Sjfv 387205869Sjfvstatic const char * const db_Esc92[] = { 388223676Sjhb "fnop", "", "", "", "", "", "", "" 389223676Sjhb}; 390223676Sjhbstatic const char * const db_Esc94[] = { 391223676Sjhb "fchs", "fabs", "", "", "ftst", "fxam", "", "" 392223676Sjhb}; 393223676Sjhbstatic const char * const db_Esc95[] = { 394205869Sjfv "fld1", "fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","" 395152545Sglebius}; 396152545Sglebiusstatic const char * const db_Esc96[] = { 397205869Sjfv "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp", 398205869Sjfv "fincstp" 399223676Sjhb}; 400223676Sjhbstatic const char * const db_Esc97[] = { 401223676Sjhb "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos" 402223676Sjhb}; 403205869Sjfv 404160949Sglebiusstatic const char * const db_Esca5[] = { 405205869Sjfv "", "fucompp","", "", "", "", "", "" 406223676Sjhb}; 407223676Sjhb 408205869Sjfvstatic const char * const db_Escb4[] = { 409178523Sjfv "fneni","fndisi", "fnclex","fninit","fsetpm", "", "", "" 410178523Sjfv}; 411178523Sjfv 412223676Sjhbstatic const char * const db_Esce3[] = { 413223676Sjhb "", "fcompp","", "", "", "", "", "" 414176667Sjfv}; 415205869Sjfv 416205869Sjfvstatic const char * const db_Escf4[] = { 417223676Sjhb "fnstsw","", "", "", "", "", "", "" 418223676Sjhb}; 419205869Sjfv 420284522Ssbrunostatic const struct finst db_Esc8[] = { 421284522Ssbruno/*0*/ { "fadd", SNGL, op2(STI,ST), 0 }, 422284522Ssbruno/*1*/ { "fmul", SNGL, op2(STI,ST), 0 }, 423284522Ssbruno/*2*/ { "fcom", SNGL, op2(STI,ST), 0 }, 424284522Ssbruno/*3*/ { "fcomp", SNGL, op2(STI,ST), 0 }, 425284522Ssbruno/*4*/ { "fsub", SNGL, op2(STI,ST), 0 }, 426284522Ssbruno/*5*/ { "fsubr", SNGL, op2(STI,ST), 0 }, 427284522Ssbruno/*6*/ { "fdiv", SNGL, op2(STI,ST), 0 }, 428284522Ssbruno/*7*/ { "fdivr", SNGL, op2(STI,ST), 0 }, 429284522Ssbruno}; 430284522Ssbruno 431284522Ssbrunostatic const struct finst db_Esc9[] = { 432284522Ssbruno/*0*/ { "fld", SNGL, op1(STI), 0 }, 433284522Ssbruno/*1*/ { "", NONE, op1(STI), "fxch" }, 434169240Sjfv/*2*/ { "fst", SNGL, op1(X), db_Esc92 }, 435163730Sjfv/*3*/ { "fstp", SNGL, 0, 0 }, 436163730Sjfv/*4*/ { "fldenv", NONE, op1(X), db_Esc94 }, 437223676Sjhb/*5*/ { "fldcw", NONE, op1(X), db_Esc95 }, 438223676Sjhb/*6*/ { "fnstenv",NONE, op1(X), db_Esc96 }, 439228387Sjfv/*7*/ { "fnstcw", NONE, op1(X), db_Esc97 }, 440228387Sjfv}; 441176667Sjfv 442219753Sjfvstatic const struct finst db_Esca[] = { 443238214Sjfv/*0*/ { "fiadd", LONG, 0, 0 }, 444219753Sjfv/*1*/ { "fimul", LONG, 0, 0 }, 445223676Sjhb/*2*/ { "ficom", LONG, 0, 0 }, 446223676Sjhb/*3*/ { "ficomp", LONG, 0, 0 }, 447219753Sjfv/*4*/ { "fisub", LONG, 0, 0 }, 448169240Sjfv/*5*/ { "fisubr", LONG, op1(X), db_Esca5 }, 449169240Sjfv/*6*/ { "fidiv", LONG, 0, 0 }, 450118314Sjdp/*7*/ { "fidivr", LONG, 0, 0 } 451228281Sluigi}; 452228281Sluigi 453228281Sluigistatic const struct finst db_Escb[] = { 454228281Sluigi/*0*/ { "fild", LONG, 0, 0 }, 455118314Sjdp/*1*/ { "", NONE, 0, 0 }, 45687189Spdeuskar/*2*/ { "fist", LONG, 0, 0 }, 45787189Spdeuskar/*3*/ { "fistp", LONG, 0, 0 }, 45887189Spdeuskar/*4*/ { "", WORD, op1(X), db_Escb4 }, 45987189Spdeuskar/*5*/ { "fld", EXTR, 0, 0 }, 46087189Spdeuskar/*6*/ { "", WORD, 0, 0 }, 461143161Simp/*7*/ { "fstp", EXTR, 0, 0 }, 46287189Spdeuskar}; 46387189Spdeuskar 46487189Spdeuskarstatic const struct finst db_Escc[] = { 46587189Spdeuskar/*0*/ { "fadd", DBLR, op2(ST,STI), 0 }, 46687189Spdeuskar/*1*/ { "fmul", DBLR, op2(ST,STI), 0 }, 467155709Sglebius/*2*/ { "fcom", DBLR, 0, 0 }, 468284522Ssbruno/*3*/ { "fcomp", DBLR, 0, 0 }, 469284522Ssbruno/*4*/ { "fsub", DBLR, op2(ST,STI), "fsubr" }, 470284522Ssbruno/*5*/ { "fsubr", DBLR, op2(ST,STI), "fsub" }, 471284522Ssbruno/*6*/ { "fdiv", DBLR, op2(ST,STI), "fdivr" }, 47297785Spdeuskar/*7*/ { "fdivr", DBLR, op2(ST,STI), "fdiv" }, 47387189Spdeuskar}; 47497785Spdeuskar 47587189Spdeuskarstatic const struct finst db_Escd[] = { 47697785Spdeuskar/*0*/ { "fld", DBLR, op1(STI), "ffree" }, 47797785Spdeuskar/*1*/ { "", NONE, 0, 0 }, 478155709Sglebius/*2*/ { "fst", DBLR, op1(STI), 0 }, 47987189Spdeuskar/*3*/ { "fstp", DBLR, op1(STI), 0 }, 48097785Spdeuskar/*4*/ { "frstor", NONE, op1(STI), "fucom" }, 48197785Spdeuskar/*5*/ { "", NONE, op1(STI), "fucomp" }, 48297785Spdeuskar/*6*/ { "fnsave", NONE, 0, 0 }, 48387189Spdeuskar/*7*/ { "fnstsw", NONE, 0, 0 }, 48497785Spdeuskar}; 48597785Spdeuskar 48697785Spdeuskarstatic const struct finst db_Esce[] = { 48797785Spdeuskar/*0*/ { "fiadd", WORD, op2(ST,STI), "faddp" }, 48887189Spdeuskar/*1*/ { "fimul", WORD, op2(ST,STI), "fmulp" }, 48997785Spdeuskar/*2*/ { "ficom", WORD, 0, 0 }, 490155709Sglebius/*3*/ { "ficomp", WORD, op1(X), db_Esce3 }, 49187189Spdeuskar/*4*/ { "fisub", WORD, op2(ST,STI), "fsubrp" }, 49297785Spdeuskar/*5*/ { "fisubr", WORD, op2(ST,STI), "fsubp" }, 493155709Sglebius/*6*/ { "fidiv", WORD, op2(ST,STI), "fdivrp" }, 494154571Sglebius/*7*/ { "fidivr", WORD, op2(ST,STI), "fdivp" }, 495154571Sglebius}; 49697785Spdeuskar 49797785Spdeuskarstatic const struct finst db_Escf[] = { 498155709Sglebius/*0*/ { "fild", WORD, 0, 0 }, 49997785Spdeuskar/*1*/ { "", NONE, 0, 0 }, 50097785Spdeuskar/*2*/ { "fist", WORD, 0, 0 }, 50197785Spdeuskar/*3*/ { "fistp", WORD, 0, 0 }, 50297785Spdeuskar/*4*/ { "fbld", NONE, op1(XA), db_Escf4 }, 503155709Sglebius/*5*/ { "fild", QUAD, 0, 0 }, 50487189Spdeuskar/*6*/ { "fbstp", NONE, 0, 0 }, 50587189Spdeuskar/*7*/ { "fistp", QUAD, 0, 0 }, 50687189Spdeuskar}; 50787189Spdeuskar 50887189Spdeuskarstatic const struct finst * const db_Esc_inst[] = { 50987189Spdeuskar db_Esc8, db_Esc9, db_Esca, db_Escb, 510154571Sglebius db_Escc, db_Escd, db_Esce, db_Escf 511154571Sglebius}; 512154571Sglebius 51387189Spdeuskarstatic const char * const db_Grp1[] = { 51487189Spdeuskar "add", 51587189Spdeuskar "or", 51687189Spdeuskar "adc", 51787189Spdeuskar "sbb", 51887189Spdeuskar "and", 519160956Spdeuskar "sub", 520219753Sjfv "xor", 521115878Spdeuskar "cmp" 52287189Spdeuskar}; 52397785Spdeuskar 52487189Spdeuskarstatic const char * const db_Grp2[] = { 525241885Seadler "rol", 526241885Seadler "ror", 527241885Seadler "rcl", 528241885Seadler "rcr", 529241885Seadler "shl", 530160956Spdeuskar "shr", 531160956Spdeuskar "shl", 532219753Sjfv "sar" 533173788Sjfv}; 53487189Spdeuskar 535115878Spdeuskarstatic const struct inst db_Grp3[] = { 536155709Sglebius { "test", TRUE, NONE, op2(I,E), 0 }, 537155709Sglebius { "test", TRUE, NONE, op2(I,E), 0 }, 538209242Sgnn { "not", TRUE, NONE, op1(E), 0 }, 539209242Sgnn { "neg", TRUE, NONE, op1(E), 0 }, 540154571Sglebius { "mul", TRUE, NONE, op2(E,A), 0 }, 541214363Sjfv { "imul", TRUE, NONE, op2(E,A), 0 }, 542214363Sjfv { "div", TRUE, NONE, op2(E,A), 0 }, 543214363Sjfv { "idiv", TRUE, NONE, op2(E,A), 0 }, 544214363Sjfv}; 545214363Sjfv 546228387Sjfvstatic const struct inst db_Grp4[] = { 547228387Sjfv { "inc", TRUE, BYTE, op1(E), 0 }, 548228387Sjfv { "dec", TRUE, BYTE, op1(E), 0 }, 549228387Sjfv { "", TRUE, NONE, 0, 0 }, 550228387Sjfv { "", TRUE, NONE, 0, 0 }, 551173788Sjfv { "", TRUE, NONE, 0, 0 }, 55287189Spdeuskar { "", TRUE, NONE, 0, 0 }, 553169637Sjfv { "", TRUE, NONE, 0, 0 }, 554160956Spdeuskar { "", TRUE, NONE, 0, 0 } 555118314Sjdp}; 556169240Sjfv 557169240Sjfvstatic const struct inst db_Grp5[] = { 558169240Sjfv { "inc", TRUE, LONG, op1(E), 0 }, 559169240Sjfv { "dec", TRUE, LONG, op1(E), 0 }, 560169240Sjfv { "call", TRUE, LONG, op1(Eind),0 }, 561169240Sjfv { "lcall", TRUE, LONG, op1(Eind),0 }, 562169240Sjfv { "jmp", TRUE, LONG, op1(Eind),0 }, 563169240Sjfv { "ljmp", TRUE, LONG, op1(Eind),0 }, 564169240Sjfv { "push", TRUE, LONG, op1(E), 0 }, 565169240Sjfv { "", TRUE, NONE, 0, 0 } 566169240Sjfv}; 567169240Sjfv 568169240Sjfvstatic const struct inst db_inst_table[256] = { 569219753Sjfv/*00*/ { "add", TRUE, BYTE, op2(R, E), 0 }, 570219753Sjfv/*01*/ { "add", TRUE, LONG, op2(R, E), 0 }, 571219753Sjfv/*02*/ { "add", TRUE, BYTE, op2(E, R), 0 }, 572219753Sjfv/*03*/ { "add", TRUE, LONG, op2(E, R), 0 }, 573247064Sjfv/*04*/ { "add", FALSE, BYTE, op2(I, A), 0 }, 574247064Sjfv/*05*/ { "add", FALSE, LONG, op2(Is, A), 0 }, 575169240Sjfv/*06*/ { "push", FALSE, NONE, op1(Si), 0 }, 576176667Sjfv/*07*/ { "pop", FALSE, NONE, op1(Si), 0 }, 577169240Sjfv 578176667Sjfv/*08*/ { "or", TRUE, BYTE, op2(R, E), 0 }, 579176667Sjfv/*09*/ { "or", TRUE, LONG, op2(R, E), 0 }, 580176667Sjfv/*0a*/ { "or", TRUE, BYTE, op2(E, R), 0 }, 581176667Sjfv/*0b*/ { "or", TRUE, LONG, op2(E, R), 0 }, 582176667Sjfv/*0c*/ { "or", FALSE, BYTE, op2(I, A), 0 }, 583169240Sjfv/*0d*/ { "or", FALSE, LONG, op2(I, A), 0 }, 584219753Sjfv/*0e*/ { "push", FALSE, NONE, op1(Si), 0 }, 585169240Sjfv/*0f*/ { "", FALSE, NONE, 0, 0 }, 586176667Sjfv 587169240Sjfv/*10*/ { "adc", TRUE, BYTE, op2(R, E), 0 }, 588176667Sjfv/*11*/ { "adc", TRUE, LONG, op2(R, E), 0 }, 589169240Sjfv/*12*/ { "adc", TRUE, BYTE, op2(E, R), 0 }, 590296055Serj/*13*/ { "adc", TRUE, LONG, op2(E, R), 0 }, 591296055Serj/*14*/ { "adc", FALSE, BYTE, op2(I, A), 0 }, 592296055Serj/*15*/ { "adc", FALSE, LONG, op2(Is, A), 0 }, 593296055Serj/*16*/ { "push", FALSE, NONE, op1(Si), 0 }, 594296055Serj/*17*/ { "pop", FALSE, NONE, op1(Si), 0 }, 595296055Serj 596296055Serj/*18*/ { "sbb", TRUE, BYTE, op2(R, E), 0 }, 597296055Serj/*19*/ { "sbb", TRUE, LONG, op2(R, E), 0 }, 598296055Serj/*1a*/ { "sbb", TRUE, BYTE, op2(E, R), 0 }, 599296055Serj/*1b*/ { "sbb", TRUE, LONG, op2(E, R), 0 }, 600296055Serj/*1c*/ { "sbb", FALSE, BYTE, op2(I, A), 0 }, 601296055Serj/*1d*/ { "sbb", FALSE, LONG, op2(Is, A), 0 }, 602296055Serj/*1e*/ { "push", FALSE, NONE, op1(Si), 0 }, 603169240Sjfv/*1f*/ { "pop", FALSE, NONE, op1(Si), 0 }, 604169240Sjfv 605296055Serj/*20*/ { "and", TRUE, BYTE, op2(R, E), 0 }, 606296055Serj/*21*/ { "and", TRUE, LONG, op2(R, E), 0 }, 607296055Serj/*22*/ { "and", TRUE, BYTE, op2(E, R), 0 }, 608296055Serj/*23*/ { "and", TRUE, LONG, op2(E, R), 0 }, 609169240Sjfv/*24*/ { "and", FALSE, BYTE, op2(I, A), 0 }, 610169240Sjfv/*25*/ { "and", FALSE, LONG, op2(I, A), 0 }, 611169240Sjfv/*26*/ { "", FALSE, NONE, 0, 0 }, 612169240Sjfv/*27*/ { "daa", FALSE, NONE, 0, 0 }, 613284522Ssbruno 614284522Ssbruno/*28*/ { "sub", TRUE, BYTE, op2(R, E), 0 }, 615284522Ssbruno/*29*/ { "sub", TRUE, LONG, op2(R, E), 0 }, 616284522Ssbruno/*2a*/ { "sub", TRUE, BYTE, op2(E, R), 0 }, 617284522Ssbruno/*2b*/ { "sub", TRUE, LONG, op2(E, R), 0 }, 618219753Sjfv/*2c*/ { "sub", FALSE, BYTE, op2(I, A), 0 }, 619169240Sjfv/*2d*/ { "sub", FALSE, LONG, op2(Is, A), 0 }, 620118314Sjdp/*2e*/ { "", FALSE, NONE, 0, 0 }, 621160956Spdeuskar/*2f*/ { "das", FALSE, NONE, 0, 0 }, 622160956Spdeuskar 623219753Sjfv/*30*/ { "xor", TRUE, BYTE, op2(R, E), 0 }, 624160956Spdeuskar/*31*/ { "xor", TRUE, LONG, op2(R, E), 0 }, 625160956Spdeuskar/*32*/ { "xor", TRUE, BYTE, op2(E, R), 0 }, 626219753Sjfv/*33*/ { "xor", TRUE, LONG, op2(E, R), 0 }, 627205869Sjfv/*34*/ { "xor", FALSE, BYTE, op2(I, A), 0 }, 628205869Sjfv/*35*/ { "xor", FALSE, LONG, op2(I, A), 0 }, 629205869Sjfv/*36*/ { "", FALSE, NONE, 0, 0 }, 630219753Sjfv/*37*/ { "aaa", FALSE, NONE, 0, 0 }, 631205869Sjfv 632205869Sjfv/*38*/ { "cmp", TRUE, BYTE, op2(R, E), 0 }, 633205869Sjfv/*39*/ { "cmp", TRUE, LONG, op2(R, E), 0 }, 634205869Sjfv/*3a*/ { "cmp", TRUE, BYTE, op2(E, R), 0 }, 635219753Sjfv/*3b*/ { "cmp", TRUE, LONG, op2(E, R), 0 }, 636205869Sjfv/*3c*/ { "cmp", FALSE, BYTE, op2(I, A), 0 }, 637250414Sluigi/*3d*/ { "cmp", FALSE, LONG, op2(Is, A), 0 }, 638250414Sluigi/*3e*/ { "", FALSE, NONE, 0, 0 }, 639250414Sluigi/*3f*/ { "aas", FALSE, NONE, 0, 0 }, 640250414Sluigi 641250414Sluigi/*40*/ { "rex", FALSE, NONE, 0, 0 }, 642152545Sglebius/*41*/ { "rex.b", FALSE, NONE, 0, 0 }, 643214363Sjfv/*42*/ { "rex.x", FALSE, NONE, 0, 0 }, 644219753Sjfv/*43*/ { "rex.xb", FALSE, NONE, 0, 0 }, 645163730Sjfv/*44*/ { "rex.r", FALSE, NONE, 0, 0 }, 646163730Sjfv/*45*/ { "rex.rb", FALSE, NONE, 0, 0 }, 647163730Sjfv/*46*/ { "rex.rx", FALSE, NONE, 0, 0 }, 648152545Sglebius/*47*/ { "rex.rxb", FALSE, NONE, 0, 0 }, 649152545Sglebius 650152545Sglebius/*48*/ { "rex.w", FALSE, NONE, 0, 0 }, 651169240Sjfv/*49*/ { "rex.wb", FALSE, NONE, 0, 0 }, 652152545Sglebius/*4a*/ { "rex.wx", FALSE, NONE, 0, 0 }, 653169240Sjfv/*4b*/ { "rex.wxb", FALSE, NONE, 0, 0 }, 654205869Sjfv/*4c*/ { "rex.wr", FALSE, NONE, 0, 0 }, 655155709Sglebius/*4d*/ { "rex.wrb", FALSE, NONE, 0, 0 }, 656155709Sglebius/*4e*/ { "rex.wrx", FALSE, NONE, 0, 0 }, 657160956Spdeuskar/*4f*/ { "rex.wrxb", FALSE, NONE, 0, 0 }, 658152545Sglebius 659160956Spdeuskar/*50*/ { "push", FALSE, LONG, op1(Ri), 0 }, 660205869Sjfv/*51*/ { "push", FALSE, LONG, op1(Ri), 0 }, 661294958Smarius/*52*/ { "push", FALSE, LONG, op1(Ri), 0 }, 662205869Sjfv/*53*/ { "push", FALSE, LONG, op1(Ri), 0 }, 663155709Sglebius/*54*/ { "push", FALSE, LONG, op1(Ri), 0 }, 664155709Sglebius/*55*/ { "push", FALSE, LONG, op1(Ri), 0 }, 665160956Spdeuskar/*56*/ { "push", FALSE, LONG, op1(Ri), 0 }, 666152545Sglebius/*57*/ { "push", FALSE, LONG, op1(Ri), 0 }, 667160956Spdeuskar 668152545Sglebius/*58*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 669219753Sjfv/*59*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 670219753Sjfv/*5a*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 671219753Sjfv/*5b*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 672154571Sglebius/*5c*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 673169240Sjfv/*5d*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 674219753Sjfv/*5e*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 675219753Sjfv/*5f*/ { "pop", FALSE, LONG, op1(Ri), 0 }, 676219753Sjfv 677219753Sjfv/*60*/ { "pusha", FALSE, LONG, 0, 0 }, 678169240Sjfv/*61*/ { "popa", FALSE, LONG, 0, 0 }, 679169240Sjfv/*62*/ { "bound", TRUE, LONG, op2(E, R), 0 }, 680154571Sglebius/*63*/ { "movslq", TRUE, NONE, op2(EL,R), 0 }, 681173788Sjfv 682173788Sjfv/*64*/ { "", FALSE, NONE, 0, 0 }, 683154571Sglebius/*65*/ { "", FALSE, NONE, 0, 0 }, 684247064Sjfv/*66*/ { "", FALSE, NONE, 0, 0 }, 685247064Sjfv/*67*/ { "", FALSE, NONE, 0, 0 }, 68687189Spdeuskar 687154571Sglebius/*68*/ { "push", FALSE, LONG, op1(I), 0 }, 688154571Sglebius/*69*/ { "imul", TRUE, LONG, op3(I,E,R), 0 }, 689154571Sglebius/*6a*/ { "push", FALSE, LONG, op1(Ibs), 0 }, 690112472Spdeuskar/*6b*/ { "imul", TRUE, LONG, op3(Ibs,E,R),0 }, 691219753Sjfv/*6c*/ { "ins", FALSE, BYTE, op2(DX, DI), 0 }, 692112472Spdeuskar/*6d*/ { "ins", FALSE, LONG, op2(DX, DI), 0 }, 693205869Sjfv/*6e*/ { "outs", FALSE, BYTE, op2(SI, DX), 0 }, 694205869Sjfv/*6f*/ { "outs", FALSE, LONG, op2(SI, DX), 0 }, 695205869Sjfv 696205869Sjfv/*70*/ { "jo", FALSE, NONE, op1(Db), 0 }, 697115878Spdeuskar/*71*/ { "jno", FALSE, NONE, op1(Db), 0 }, 698205869Sjfv/*72*/ { "jb", FALSE, NONE, op1(Db), 0 }, 699155709Sglebius/*73*/ { "jnb", FALSE, NONE, op1(Db), 0 }, 70087189Spdeuskar/*74*/ { "jz", FALSE, NONE, op1(Db), 0 }, 701211913Syongari/*75*/ { "jnz", FALSE, NONE, op1(Db), 0 }, 702211913Syongari/*76*/ { "jbe", FALSE, NONE, op1(Db), 0 }, 703211913Syongari/*77*/ { "jnbe", FALSE, NONE, op1(Db), 0 }, 704211913Syongari 705211913Syongari/*78*/ { "js", FALSE, NONE, op1(Db), 0 }, 706211913Syongari/*79*/ { "jns", FALSE, NONE, op1(Db), 0 }, 707211913Syongari/*7a*/ { "jp", FALSE, NONE, op1(Db), 0 }, 708211913Syongari/*7b*/ { "jnp", FALSE, NONE, op1(Db), 0 }, 709211913Syongari/*7c*/ { "jl", FALSE, NONE, op1(Db), 0 }, 710214363Sjfv/*7d*/ { "jnl", FALSE, NONE, op1(Db), 0 }, 711219753Sjfv/*7e*/ { "jle", FALSE, NONE, op1(Db), 0 }, 712214363Sjfv/*7f*/ { "jnle", FALSE, NONE, op1(Db), 0 }, 713214363Sjfv 714214363Sjfv/*80*/ { "", TRUE, BYTE, op2(I, E), db_Grp1 }, 715219753Sjfv/*81*/ { "", TRUE, LONG, op2(I, E), db_Grp1 }, 716238214Sjfv/*82*/ { "", TRUE, BYTE, op2(I, E), db_Grp1 }, 717238214Sjfv/*83*/ { "", TRUE, LONG, op2(Ibs,E), db_Grp1 }, 718238214Sjfv/*84*/ { "test", TRUE, BYTE, op2(R, E), 0 }, 719238214Sjfv/*85*/ { "test", TRUE, LONG, op2(R, E), 0 }, 720238214Sjfv/*86*/ { "xchg", TRUE, BYTE, op2(R, E), 0 }, 721238214Sjfv/*87*/ { "xchg", TRUE, LONG, op2(R, E), 0 }, 722219753Sjfv 723190872Sjfv/*88*/ { "mov", TRUE, BYTE, op2(R, E), 0 }, 724190872Sjfv/*89*/ { "mov", TRUE, LONG, op2(R, E), 0 }, 725190872Sjfv/*8a*/ { "mov", TRUE, BYTE, op2(E, R), 0 }, 726190872Sjfv/*8b*/ { "mov", TRUE, LONG, op2(E, R), 0 }, 727190872Sjfv/*8c*/ { "mov", TRUE, NONE, op2(S, Ew), 0 }, 728219753Sjfv/*8d*/ { "lea", TRUE, LONG, op2(E, R), 0 }, 729190872Sjfv/*8e*/ { "mov", TRUE, NONE, op2(Ew, S), 0 }, 730219753Sjfv/*8f*/ { "pop", TRUE, LONG, op1(E), 0 }, 731169240Sjfv 732219753Sjfv/*90*/ { "nop", FALSE, NONE, 0, 0 }, 733169240Sjfv/*91*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 734169240Sjfv/*92*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 735169240Sjfv/*93*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 736169240Sjfv/*94*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 737169240Sjfv/*95*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 738219753Sjfv/*96*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 739169240Sjfv/*97*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, 740169240Sjfv 741169240Sjfv/*98*/ { "cbw", FALSE, SDEP, 0, "cwde" }, /* cbw/cwde */ 742205869Sjfv/*99*/ { "cwd", FALSE, SDEP, 0, "cdq" }, /* cwd/cdq */ 743169240Sjfv/*9a*/ { "lcall", FALSE, NONE, op1(OS), 0 }, 744169240Sjfv/*9b*/ { "wait", FALSE, NONE, 0, 0 }, 745169240Sjfv/*9c*/ { "pushf", FALSE, LONG, 0, 0 }, 746100184Spdeuskar/*9d*/ { "popf", FALSE, LONG, 0, 0 }, 747219753Sjfv/*9e*/ { "sahf", FALSE, NONE, 0, 0 }, 748155709Sglebius/*9f*/ { "lahf", FALSE, NONE, 0, 0 }, 749155709Sglebius 750115878Spdeuskar/*a0*/ { "mov", FALSE, BYTE, op2(O, A), 0 }, 751205869Sjfv/*a1*/ { "mov", FALSE, LONG, op2(O, A), 0 }, 752100184Spdeuskar/*a2*/ { "mov", FALSE, BYTE, op2(A, O), 0 }, 753100184Spdeuskar/*a3*/ { "mov", FALSE, LONG, op2(A, O), 0 }, 754219753Sjfv/*a4*/ { "movs", FALSE, BYTE, op2(SI,DI), 0 }, 755155709Sglebius/*a5*/ { "movs", FALSE, LONG, op2(SI,DI), 0 }, 756155709Sglebius/*a6*/ { "cmps", FALSE, BYTE, op2(SI,DI), 0 }, 757205869Sjfv/*a7*/ { "cmps", FALSE, LONG, op2(SI,DI), 0 }, 758155709Sglebius 759115878Spdeuskar/*a8*/ { "test", FALSE, BYTE, op2(I, A), 0 }, 760269196Sjfv/*a9*/ { "test", FALSE, LONG, op2(I, A), 0 }, 761269196Sjfv/*aa*/ { "stos", FALSE, BYTE, op1(DI), 0 }, 762269196Sjfv/*ab*/ { "stos", FALSE, LONG, op1(DI), 0 }, 763176667Sjfv/*ac*/ { "lods", FALSE, BYTE, op1(SI), 0 }, 764176667Sjfv/*ad*/ { "lods", FALSE, LONG, op1(SI), 0 }, 765176667Sjfv/*ae*/ { "scas", FALSE, BYTE, op1(SI), 0 }, 766205869Sjfv/*af*/ { "scas", FALSE, LONG, op1(SI), 0 }, 767176667Sjfv 768176667Sjfv/*b0*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 769176667Sjfv/*b1*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 770176667Sjfv/*b2*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 771205869Sjfv/*b3*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 772176667Sjfv/*b4*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 773200243Sjfv/*b5*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 774200243Sjfv/*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 775200243Sjfv/*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 }, 776200243Sjfv 777200243Sjfv/*b8*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 77897785Spdeuskar/*b9*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 779211907Syongari/*ba*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 780211907Syongari/*bb*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 78187189Spdeuskar/*bc*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 782205869Sjfv/*bd*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 783205869Sjfv/*be*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 78497785Spdeuskar/*bf*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 }, 785160956Spdeuskar 786169240Sjfv/*c0*/ { "", TRUE, BYTE, op2(Ib, E), db_Grp2 }, 787219753Sjfv/*c1*/ { "", TRUE, LONG, op2(Ib, E), db_Grp2 }, 788160956Spdeuskar/*c2*/ { "ret", FALSE, NONE, op1(Iw), 0 }, 78987189Spdeuskar/*c3*/ { "ret", FALSE, NONE, 0, 0 }, 790185353Sjfv/*c4*/ { "les", TRUE, LONG, op2(E, R), 0 }, 791185353Sjfv/*c5*/ { "lds", TRUE, LONG, op2(E, R), 0 }, 792195857Sjfv/*c6*/ { "mov", TRUE, BYTE, op2(I, E), 0 }, 793185353Sjfv/*c7*/ { "mov", TRUE, LONG, op2(I, E), 0 }, 794195857Sjfv 795185353Sjfv/*c8*/ { "enter", FALSE, NONE, op2(Iw, Ib), 0 }, 796209242Sgnn/*c9*/ { "leave", FALSE, NONE, 0, 0 }, 797209242Sgnn/*ca*/ { "lret", FALSE, NONE, op1(Iw), 0 }, 798200243Sjfv/*cb*/ { "lret", FALSE, NONE, 0, 0 }, 799200243Sjfv/*cc*/ { "int", FALSE, NONE, op1(o3), 0 }, 800200243Sjfv/*cd*/ { "int", FALSE, NONE, op1(Ib), 0 }, 801200243Sjfv/*ce*/ { "into", FALSE, NONE, 0, 0 }, 802169240Sjfv/*cf*/ { "iret", FALSE, NONE, 0, 0 }, 803228387Sjfv 804228387Sjfv/*d0*/ { "", TRUE, BYTE, op2(o1, E), db_Grp2 }, 805169240Sjfv/*d1*/ { "", TRUE, LONG, op2(o1, E), db_Grp2 }, 806206001Smarius/*d2*/ { "", TRUE, BYTE, op2(CL, E), db_Grp2 }, 807206001Smarius/*d3*/ { "", TRUE, LONG, op2(CL, E), db_Grp2 }, 808228281Sluigi/*d4*/ { "aam", FALSE, NONE, op1(Iba), 0 }, 809228281Sluigi/*d5*/ { "aad", FALSE, NONE, op1(Iba), 0 }, 810228281Sluigi/*d6*/ { ".byte\t0xd6", FALSE, NONE, 0, 0 }, 811206001Smarius/*d7*/ { "xlat", FALSE, BYTE, op1(BX), 0 }, 81297785Spdeuskar 813115878Spdeuskar/*d8*/ { "", TRUE, NONE, 0, db_Esc8 }, 814155709Sglebius/*d9*/ { "", TRUE, NONE, 0, db_Esc9 }, 815155709Sglebius/*da*/ { "", TRUE, NONE, 0, db_Esca }, 816205869Sjfv/*db*/ { "", TRUE, NONE, 0, db_Escb }, 817173788Sjfv/*dc*/ { "", TRUE, NONE, 0, db_Escc }, 818205869Sjfv/*dd*/ { "", TRUE, NONE, 0, db_Escd }, 819169240Sjfv/*de*/ { "", TRUE, NONE, 0, db_Esce }, 820211907Syongari/*df*/ { "", TRUE, NONE, 0, db_Escf }, 821211907Syongari 822115878Spdeuskar/*e0*/ { "loopne",FALSE, NONE, op1(Db), 0 }, 823160956Spdeuskar/*e1*/ { "loope", FALSE, NONE, op1(Db), 0 }, 824211913Syongari/*e2*/ { "loop", FALSE, NONE, op1(Db), 0 }, 825173788Sjfv/*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz" }, 826115878Spdeuskar/*e4*/ { "in", FALSE, BYTE, op2(Ib, A), 0 }, 827155709Sglebius/*e5*/ { "in", FALSE, LONG, op2(Ib, A) , 0 }, 82887189Spdeuskar/*e6*/ { "out", FALSE, BYTE, op2(A, Ib), 0 }, 82987189Spdeuskar/*e7*/ { "out", FALSE, LONG, op2(A, Ib) , 0 }, 83087189Spdeuskar 83187189Spdeuskar/*e8*/ { "call", FALSE, NONE, op1(Dl), 0 }, 83287189Spdeuskar/*e9*/ { "jmp", FALSE, NONE, op1(Dl), 0 }, 83387189Spdeuskar/*ea*/ { "ljmp", FALSE, NONE, op1(OS), 0 }, 83487189Spdeuskar/*eb*/ { "jmp", FALSE, NONE, op1(Db), 0 }, 83587189Spdeuskar/*ec*/ { "in", FALSE, BYTE, op2(DX, A), 0 }, 836154571Sglebius/*ed*/ { "in", FALSE, LONG, op2(DX, A) , 0 }, 83787189Spdeuskar/*ee*/ { "out", FALSE, BYTE, op2(A, DX), 0 }, 83887189Spdeuskar/*ef*/ { "out", FALSE, LONG, op2(A, DX) , 0 }, 83987189Spdeuskar 84087189Spdeuskar/*f0*/ { "", FALSE, NONE, 0, 0 }, 84187189Spdeuskar/*f1*/ { ".byte\t0xf1", FALSE, NONE, 0, 0 }, 84287189Spdeuskar/*f2*/ { "", FALSE, NONE, 0, 0 }, 843160956Spdeuskar/*f3*/ { "", FALSE, NONE, 0, 0 }, 844160956Spdeuskar/*f4*/ { "hlt", FALSE, NONE, 0, 0 }, 84587189Spdeuskar/*f5*/ { "cmc", FALSE, NONE, 0, 0 }, 84697785Spdeuskar/*f6*/ { "", TRUE, BYTE, 0, db_Grp3 }, 84787189Spdeuskar/*f7*/ { "", TRUE, LONG, 0, db_Grp3 }, 848173788Sjfv 849173788Sjfv/*f8*/ { "clc", FALSE, NONE, 0, 0 }, 850173788Sjfv/*f9*/ { "stc", FALSE, NONE, 0, 0 }, 851173788Sjfv/*fa*/ { "cli", FALSE, NONE, 0, 0 }, 852173788Sjfv/*fb*/ { "sti", FALSE, NONE, 0, 0 }, 853173788Sjfv/*fc*/ { "cld", FALSE, NONE, 0, 0 }, 854150789Sglebius/*fd*/ { "std", FALSE, NONE, 0, 0 }, 855150789Sglebius/*fe*/ { "", TRUE, NONE, 0, db_Grp4 }, 856150789Sglebius/*ff*/ { "", TRUE, NONE, 0, db_Grp5 }, 857150789Sglebius}; 858150789Sglebius 859208117Smariusstatic const struct inst db_bad_inst = 860208117Smarius { "???", FALSE, NONE, 0, 0 } 861208117Smarius; 862173788Sjfv 863160956Spdeuskar#define f_mod(rex, byte) ((byte)>>6) 864160956Spdeuskar#define f_reg(rex, byte) ((((byte)>>3)&0x7) | (rex & REX_R ? 0x8 : 0x0)) 865205869Sjfv#define f_rm(rex, byte) (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0)) 866205869Sjfv 867205869Sjfv#define sib_ss(rex, byte) ((byte)>>6) 868169240Sjfv#define sib_index(rex, byte) ((((byte)>>3)&0x7) | (rex & REX_X ? 0x8 : 0x0)) 869169240Sjfv#define sib_base(rex, byte) (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0)) 870169240Sjfv 871205869Sjfvstruct i_addr { 872170141Sjfv int is_reg; /* if reg, reg number is in 'disp' */ 873185353Sjfv int disp; 874185353Sjfv const char * base; 875185353Sjfv const char * index; 876185353Sjfv int ss; 877185353Sjfv}; 878185353Sjfv 879160956Spdeuskarstatic const char * const db_reg[2][4][16] = { 880163827Sjhb 881163827Sjhb {{"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 882228281Sluigi "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" }, 883228281Sluigi { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 884228281Sluigi "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" }, 885228281Sluigi { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 886160956Spdeuskar "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" }, 887125673Spdeuskar { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 888150306Simp "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }}, 889125673Spdeuskar 890163828Sjhb {{"%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 891163828Sjhb "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" }, 892163828Sjhb { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 893200243Sjfv "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" }, 894211913Syongari { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 895120989Ssam "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" }, 896155709Sglebius { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 89787189Spdeuskar "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }} 89887189Spdeuskar}; 899106649Spdeuskar 900106649Spdeuskarstatic const char * const db_seg_reg[8] = { 901106649Spdeuskar "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" 902108229Spdeuskar}; 903154571Sglebius 904106649Spdeuskar/* 90587189Spdeuskar * lengths for size attributes 90687189Spdeuskar */ 90787189Spdeuskarstatic const int db_lengths[] = { 908169240Sjfv 1, /* BYTE */ 90987189Spdeuskar 2, /* WORD */ 91087189Spdeuskar 4, /* LONG */ 911153729Sglebius 8, /* QUAD */ 912153729Sglebius 4, /* SNGL */ 913153729Sglebius 8, /* DBLR */ 914153729Sglebius 10, /* EXTR */ 915153729Sglebius}; 916153729Sglebius 917160956Spdeuskar#define get_value_inc(result, loc, size, is_signed) \ 918108229Spdeuskar result = db_get_value((loc), (size), (is_signed)); \ 919173788Sjfv (loc) += (size); 920173952Sjfv 921169240Sjfvstatic db_addr_t 922200243Sjfv db_disasm_esc(db_addr_t loc, int inst, int rex, int short_addr, 923200243Sjfv int size, const char *seg); 924170141Sjfvstatic void db_print_address(const char *seg, int size, int rex, 925173788Sjfv struct i_addr *addrp); 926153729Sglebiusstatic db_addr_t 927153729Sglebius db_read_address(db_addr_t loc, int short_addr, int rex, int regmodrm, 928153729Sglebius struct i_addr *addrp); 929153729Sglebius 930153729Sglebius/* 931153729Sglebius * Read address at location and return updated location. 932153729Sglebius */ 933160956Spdeuskarstatic db_addr_t 934233708Sjhbdb_read_address(loc, short_addr, rex, regmodrm, addrp) 935160956Spdeuskar db_addr_t loc; 936153729Sglebius int short_addr; 937173788Sjfv int rex; 938228387Sjfv int regmodrm; 939228387Sjfv struct i_addr * addrp; /* out */ 940160956Spdeuskar{ 941169240Sjfv int mod, rm, sib, index, disp, size, have_sib; 942233708Sjhb 943233708Sjhb mod = f_mod(rex, regmodrm); 944233708Sjhb rm = f_rm(rex, regmodrm); 945233708Sjhb 946233708Sjhb if (mod == 3) { 947233708Sjhb addrp->is_reg = TRUE; 948233708Sjhb addrp->disp = rm; 949284522Ssbruno return (loc); 950233708Sjhb } 951233708Sjhb addrp->is_reg = FALSE; 952233708Sjhb addrp->index = 0; 953233708Sjhb 954233708Sjhb if (short_addr) 955233708Sjhb size = LONG; 956233708Sjhb else 957173788Sjfv size = QUAD; 958153729Sglebius 959153729Sglebius if ((rm & 0x7) == 4) { 960153729Sglebius get_value_inc(sib, loc, 1, FALSE); 961153729Sglebius rm = sib_base(rex, sib); 962153729Sglebius index = sib_index(rex, sib); 963284522Ssbruno if (index != 4) 964284522Ssbruno addrp->index = db_reg[1][size][index]; 965284522Ssbruno addrp->ss = sib_ss(rex, sib); 966284522Ssbruno have_sib = 1; 967284522Ssbruno } else 968284522Ssbruno have_sib = 0; 969284522Ssbruno 970284522Ssbruno switch (mod) { 971284522Ssbruno case 0: 972284522Ssbruno if (rm == 5) { 973284522Ssbruno get_value_inc(addrp->disp, loc, 4, FALSE); 974284522Ssbruno if (have_sib) 975284522Ssbruno addrp->base = 0; 976284522Ssbruno else if (short_addr) 977284522Ssbruno addrp->base = "%eip"; 978284522Ssbruno else 979284522Ssbruno addrp->base = "%rip"; 980284522Ssbruno } else { 981284522Ssbruno addrp->disp = 0; 982284522Ssbruno addrp->base = db_reg[1][size][rm]; 983284522Ssbruno } 984284522Ssbruno break; 985284522Ssbruno 986284522Ssbruno case 1: 987284522Ssbruno get_value_inc(disp, loc, 1, TRUE); 988284522Ssbruno addrp->disp = disp; 989284522Ssbruno addrp->base = db_reg[1][size][rm]; 990284522Ssbruno break; 991284522Ssbruno 992284522Ssbruno case 2: 993284522Ssbruno get_value_inc(disp, loc, 4, FALSE); 994284522Ssbruno addrp->disp = disp; 995284522Ssbruno addrp->base = db_reg[1][size][rm]; 996284522Ssbruno break; 997284522Ssbruno } 998284522Ssbruno return (loc); 999284522Ssbruno} 1000284522Ssbruno 1001284522Ssbrunostatic void 1002284522Ssbrunodb_print_address(seg, size, rex, addrp) 1003284522Ssbruno const char * seg; 1004284522Ssbruno int size; 1005284522Ssbruno int rex; 1006284522Ssbruno struct i_addr * addrp; 1007284522Ssbruno{ 1008284522Ssbruno if (addrp->is_reg) { 1009284522Ssbruno db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][addrp->disp]); 1010284522Ssbruno return; 1011284522Ssbruno } 1012284522Ssbruno 1013284522Ssbruno if (seg) { 1014284522Ssbruno db_printf("%s:", seg); 1015284522Ssbruno } 1016284522Ssbruno 1017284522Ssbruno if (addrp->disp != 0 || (addrp->base == 0 && addrp->index == 0)) 1018284522Ssbruno db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); 1019284522Ssbruno if (addrp->base != 0 || addrp->index != 0) { 1020284522Ssbruno db_printf("("); 1021284522Ssbruno if (addrp->base) 1022284522Ssbruno db_printf("%s", addrp->base); 1023284522Ssbruno if (addrp->index) 1024284522Ssbruno db_printf(",%s,%d", addrp->index, 1<<addrp->ss); 1025284522Ssbruno db_printf(")"); 1026284522Ssbruno } 102787189Spdeuskar} 1028228387Sjfv 102987189Spdeuskar/* 1030228387Sjfv * Disassemble floating-point ("escape") instruction 1031228387Sjfv * and return updated location. 1032228387Sjfv */ 1033228387Sjfvstatic db_addr_t 103487189Spdeuskardb_disasm_esc(loc, inst, rex, short_addr, size, seg) 1035284522Ssbruno db_addr_t loc; 1036284522Ssbruno int inst; 1037284522Ssbruno int rex; 1038191038Skmacy int short_addr; 1039284522Ssbruno int size; 1040191038Skmacy const char * seg; 1041284522Ssbruno{ 1042284522Ssbruno int regmodrm; 1043284522Ssbruno const struct finst * fp; 1044284522Ssbruno int mod; 1045284522Ssbruno struct i_addr address; 1046284522Ssbruno const char * name; 1047284522Ssbruno 1048284522Ssbruno get_value_inc(regmodrm, loc, 1, FALSE); 1049284522Ssbruno fp = &db_Esc_inst[inst - 0xd8][f_reg(rex, regmodrm)]; 1050284522Ssbruno mod = f_mod(rex, regmodrm); 1051284522Ssbruno if (mod != 3) { 1052284522Ssbruno if (*fp->f_name == '\0') { 1053284522Ssbruno db_printf("<bad instruction>"); 1054284522Ssbruno return (loc); 1055284522Ssbruno } 1056284522Ssbruno /* 1057284522Ssbruno * Normal address modes. 1058284522Ssbruno */ 1059284522Ssbruno loc = db_read_address(loc, short_addr, rex, regmodrm, &address); 1060284522Ssbruno db_printf("%s", fp->f_name); 1061284522Ssbruno switch(fp->f_size) { 1062284522Ssbruno case SNGL: 1063284522Ssbruno db_printf("s"); 1064284522Ssbruno break; 1065284522Ssbruno case DBLR: 1066284522Ssbruno db_printf("l"); 1067284522Ssbruno break; 1068205869Sjfv case EXTR: 1069205869Sjfv db_printf("t"); 1070205869Sjfv break; 1071191038Skmacy case WORD: 1072205869Sjfv db_printf("s"); 1073205869Sjfv break; 1074284522Ssbruno case LONG: 1075205869Sjfv db_printf("l"); 1076205869Sjfv break; 1077205869Sjfv case QUAD: 1078246482Srrs db_printf("q"); 1079205869Sjfv break; 1080284522Ssbruno default: 1081284522Ssbruno break; 1082246482Srrs } 1083284522Ssbruno db_printf("\t"); 1084284522Ssbruno db_print_address(seg, BYTE, rex, &address); 1085284522Ssbruno } 1086284522Ssbruno else { 1087284522Ssbruno /* 1088284522Ssbruno * 'reg-reg' - special formats 1089246482Srrs */ 1090284522Ssbruno switch (fp->f_rrmode) { 1091246482Srrs case op2(ST,STI): 1092197073Sjfv name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1093246482Srrs db_printf("%s\t%%st,%%st(%d)",name,f_rm(rex, regmodrm)); 1094205869Sjfv break; 1095241037Sglebius case op2(STI,ST): 1096241037Sglebius name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1097241037Sglebius db_printf("%s\t%%st(%d),%%st",name, f_rm(rex, regmodrm)); 1098205869Sjfv break; 1099205869Sjfv case op1(STI): 1100205869Sjfv name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; 1101205869Sjfv db_printf("%s\t%%st(%d)",name, f_rm(rex, regmodrm)); 1102205869Sjfv break; 1103284444Ssbruno case op1(X): 1104284444Ssbruno name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)]; 1105284444Ssbruno if (*name == '\0') 1106228387Sjfv goto bad; 1107228387Sjfv db_printf("%s", name); 1108228387Sjfv break; 1109284522Ssbruno case op1(XA): 1110228387Sjfv name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)]; 1111284522Ssbruno if (*name == '\0') 1112205869Sjfv goto bad; 1113191038Skmacy db_printf("%s\t%%ax", name); 1114194865Sjfv break; 1115194865Sjfv default: 1116205869Sjfv bad: 1117205869Sjfv db_printf("<bad instruction>"); 111887189Spdeuskar break; 1119191038Skmacy } 1120191038Skmacy } 1121205869Sjfv 1122205869Sjfv return (loc); 1123205869Sjfv} 1124191038Skmacy 1125205869Sjfv/* 1126205869Sjfv * Disassemble instruction at 'loc'. 'altfmt' specifies an 1127205869Sjfv * (optional) alternate format. Return address of start of 1128205869Sjfv * next instruction. 1129205869Sjfv */ 1130205869Sjfvdb_addr_t 1131191162Skmacydb_disasm(loc, altfmt) 1132191038Skmacy db_addr_t loc; 1133233708Sjhb boolean_t altfmt; 1134120364Ssam{ 113587189Spdeuskar int inst; 113687189Spdeuskar int size; 113787189Spdeuskar int short_addr; 113887189Spdeuskar const char * seg; 113987189Spdeuskar const struct inst * ip; 114087189Spdeuskar const char * i_name; 114187189Spdeuskar int i_size; 114287189Spdeuskar int i_mode; 114387189Spdeuskar int rex = 0; 114487189Spdeuskar int regmodrm = 0; 1145112472Spdeuskar boolean_t first; 114687189Spdeuskar int displ; 1147160956Spdeuskar int prefix; 1148228387Sjfv int rep; 1149228387Sjfv int imm; 1150228387Sjfv int imm2; 1151228415Sjfv long imm64; 1152228405Sjfv int len; 1153228387Sjfv struct i_addr address; 115487189Spdeuskar 1155160956Spdeuskar get_value_inc(inst, loc, 1, FALSE); 1156155709Sglebius short_addr = FALSE; 1157122681Spdeuskar size = LONG; 115897785Spdeuskar seg = 0; 115997785Spdeuskar 1160184717Sbz /* 1161228387Sjfv * Get prefixes 1162228387Sjfv */ 1163228387Sjfv rep = FALSE; 1164228405Sjfv prefix = TRUE; 1165228405Sjfv do { 1166228405Sjfv switch (inst) { 1167228405Sjfv case 0x66: /* data16 */ 1168228387Sjfv size = WORD; 1169228387Sjfv break; 1170228387Sjfv case 0x67: 1171228387Sjfv short_addr = TRUE; 1172228387Sjfv break; 1173160519Syongari case 0x26: 1174228387Sjfv seg = "%es"; 1175228387Sjfv break; 1176228415Sjfv case 0x36: 1177228387Sjfv seg = "%ss"; 1178228387Sjfv break; 1179228415Sjfv case 0x2e: 1180160519Syongari seg = "%cs"; 1181160519Syongari break; 118297785Spdeuskar case 0x3e: 118397785Spdeuskar seg = "%ds"; 1184152740Sglebius break; 1185152740Sglebius case 0x64: 1186152740Sglebius seg = "%fs"; 1187152740Sglebius break; 1188152740Sglebius case 0x65: 1189173788Sjfv seg = "%gs"; 1190169240Sjfv break; 1191169240Sjfv case 0xf0: 1192169240Sjfv db_printf("lock "); 1193169240Sjfv break; 1194178523Sjfv case 0xf2: 1195214363Sjfv db_printf("repne "); 1196247064Sjfv break; 1197296055Serj case 0xf3: 1198178523Sjfv rep = TRUE; 1199228387Sjfv break; 1200205869Sjfv default: 1201157566Sglebius prefix = FALSE; 1202152740Sglebius break; 1203200243Sjfv } 1204200243Sjfv if (inst >= 0x40 && inst < 0x50) { 1205200243Sjfv rex = inst; 1206169918Sjfv prefix = TRUE; 1207169240Sjfv } 1208160949Sglebius if (prefix) { 1209160949Sglebius get_value_inc(inst, loc, 1, FALSE); 1210152740Sglebius } 1211152740Sglebius if (rep == TRUE) { 1212152740Sglebius if (inst == 0x90) { 1213152740Sglebius db_printf("pause\n"); 1214152740Sglebius return (loc); 1215173788Sjfv } 121697785Spdeuskar db_printf("repe "); /* XXX repe VS rep */ 1217152740Sglebius rep = FALSE; 121897785Spdeuskar } 1219152740Sglebius } while (prefix); 1220152740Sglebius 1221247064Sjfv if (inst >= 0xd8 && inst <= 0xdf) { 1222173788Sjfv loc = db_disasm_esc(loc, inst, rex, short_addr, size, seg); 1223160956Spdeuskar db_printf("\n"); 1224173788Sjfv return (loc); 122597785Spdeuskar } 1226152740Sglebius 1227112472Spdeuskar if (inst == 0x0f) { 1228169240Sjfv get_value_inc(inst, loc, 1, FALSE); 1229169240Sjfv ip = db_inst_0f[inst>>4]; 1230173788Sjfv if (ip == 0) { 1231112472Spdeuskar ip = &db_bad_inst; 1232160519Syongari } 1233160956Spdeuskar else { 1234178523Sjfv ip = &ip[inst&0xf]; 1235160956Spdeuskar } 1236160956Spdeuskar } 1237160519Syongari else 1238160519Syongari ip = &db_inst_table[inst]; 1239160956Spdeuskar 1240169240Sjfv if (ip->i_has_modrm) { 1241205869Sjfv get_value_inc(regmodrm, loc, 1, FALSE); 1242160956Spdeuskar loc = db_read_address(loc, short_addr, rex, regmodrm, &address); 1243160956Spdeuskar } 1244173788Sjfv 1245112472Spdeuskar i_name = ip->i_name; 124697785Spdeuskar i_size = ip->i_size; 124797785Spdeuskar i_mode = ip->i_mode; 124897785Spdeuskar 1249148887Srwatson if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 || 1250173788Sjfv ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 || 1251160956Spdeuskar ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9 || 1252160956Spdeuskar ip->i_extra == db_Grp15) { 1253115878Spdeuskar i_name = ((const char * const *)ip->i_extra)[f_reg(rex, regmodrm)]; 1254155709Sglebius } 1255115878Spdeuskar else if (ip->i_extra == db_Grp3) { 1256160956Spdeuskar ip = ip->i_extra; 1257173788Sjfv ip = &ip[f_reg(rex, regmodrm)]; 125897785Spdeuskar i_name = ip->i_name; 125997785Spdeuskar i_mode = ip->i_mode; 126097785Spdeuskar } 1261163824Sglebius else if (ip->i_extra == db_Grp4 || ip->i_extra == db_Grp5) { 1262173788Sjfv ip = ip->i_extra; 1263169240Sjfv ip = &ip[f_reg(rex, regmodrm)]; 1264173788Sjfv i_name = ip->i_name; 1265163824Sglebius i_mode = ip->i_mode; 1266169240Sjfv i_size = ip->i_size; 1267163824Sglebius } 1268163824Sglebius 1269173788Sjfv /* Special cases that don't fit well in the tables. */ 1270214363Sjfv if (ip->i_extra == db_Grp7 && f_mod(rex, regmodrm) == 3) { 127197785Spdeuskar switch (regmodrm) { 1272169240Sjfv case 0xc8: 1273169240Sjfv i_name = "monitor"; 1274160956Spdeuskar i_size = NONE; 127597785Spdeuskar i_mode = 0; 127697785Spdeuskar break; 1277152740Sglebius case 0xc9: 1278152740Sglebius i_name = "mwait"; 1279152740Sglebius i_size = NONE; 128097785Spdeuskar i_mode = 0; 1281130079Syar break; 128297785Spdeuskar case 0xd0: 1283150789Sglebius i_name = "xgetbv"; 1284150789Sglebius i_size = NONE; 1285150789Sglebius i_mode = 0; 1286150789Sglebius break; 1287150789Sglebius case 0xd1: 1288155709Sglebius i_name = "xsetbv"; 1289173788Sjfv i_size = NONE; 1290160956Spdeuskar i_mode = 0; 1291150789Sglebius break; 1292173788Sjfv case 0xf8: 1293150789Sglebius i_name = "swapgs"; 1294150789Sglebius i_size = NONE; 1295150789Sglebius i_mode = 0; 1296173788Sjfv break; 1297160956Spdeuskar case 0xf9: 1298150789Sglebius i_name = "rdtscp"; 1299173788Sjfv i_size = NONE; 1300150789Sglebius i_mode = 0; 1301150789Sglebius break; 1302150789Sglebius } 130397785Spdeuskar } 1304128139Sru if (ip->i_extra == db_Grp15 && f_mod(rex, regmodrm) == 3) { 1305130079Syar i_name = db_Grp15b[f_reg(rex, regmodrm)]; 130697785Spdeuskar i_size = NONE; 1307163730Sjfv i_mode = 0; 1308163730Sjfv } 1309163730Sjfv 1310163730Sjfv if (i_size == SDEP) { 1311130079Syar if (size == WORD) 1312130079Syar db_printf("%s", i_name); 1313130079Syar else 1314130079Syar db_printf("%s", (const char *)ip->i_extra); 1315206388Sjfv } 1316206388Sjfv else { 1317206388Sjfv db_printf("%s", i_name); 1318206388Sjfv if ((inst >= 0x50 && inst <= 0x5f) || inst == 0x68 || inst == 0x6a) { 1319228387Sjfv i_size = NONE; 1320228387Sjfv db_printf("q"); 1321228387Sjfv } 1322228387Sjfv if (i_size != NONE) { 1323200243Sjfv if (i_size == BYTE) { 1324200243Sjfv db_printf("b"); 1325200243Sjfv size = BYTE; 1326200243Sjfv } 1327200243Sjfv else if (i_size == WORD) { 1328200243Sjfv db_printf("w"); 1329200243Sjfv size = WORD; 1330148887Srwatson } 1331160956Spdeuskar else if (size == WORD) 1332163730Sjfv db_printf("w"); 133397785Spdeuskar else { 1334152740Sglebius if (rex & REX_W) 1335176667Sjfv db_printf("q"); 133697785Spdeuskar else 1337160519Syongari db_printf("l"); 1338160519Syongari } 133997785Spdeuskar } 134087189Spdeuskar } 1341155709Sglebius db_printf("\t"); 134287189Spdeuskar for (first = TRUE; 134387189Spdeuskar i_mode != 0; 134487189Spdeuskar i_mode >>= 8, first = FALSE) 134587189Spdeuskar { 134687189Spdeuskar if (!first) 134787189Spdeuskar db_printf(","); 134887189Spdeuskar 134987189Spdeuskar switch (i_mode & 0xFF) { 1350154571Sglebius 135187189Spdeuskar case E: 135287189Spdeuskar db_print_address(seg, size, rex, &address); 135387189Spdeuskar break; 135487189Spdeuskar 135587189Spdeuskar case Eind: 135687189Spdeuskar db_printf("*"); 1357160956Spdeuskar db_print_address(seg, size, rex, &address); 135887189Spdeuskar break; 1359160956Spdeuskar 1360160956Spdeuskar case El: 1361130079Syar db_print_address(seg, (rex & REX_W) ? QUAD : LONG, rex, &address); 136297785Spdeuskar break; 136387189Spdeuskar 1364173788Sjfv case EL: 136587189Spdeuskar db_print_address(seg, LONG, 0, &address); 1366205869Sjfv break; 1367205869Sjfv 136887189Spdeuskar case Ew: 1369122681Spdeuskar db_print_address(seg, WORD, rex, &address); 1370169240Sjfv break; 1371169240Sjfv 1372122681Spdeuskar case Eb: 1373169397Sjfv db_print_address(seg, BYTE, rex, &address); 1374169397Sjfv break; 1375169397Sjfv 1376169397Sjfv case R: 1377173788Sjfv db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][f_reg(rex, regmodrm)]); 1378173788Sjfv break; 1379173788Sjfv 1380173788Sjfv case Rw: 1381169397Sjfv db_printf("%s", db_reg[rex != 0 ? 1 : 0][WORD][f_reg(rex, regmodrm)]); 1382173788Sjfv break; 1383173788Sjfv 1384173788Sjfv case Ri: 1385173788Sjfv db_printf("%s", db_reg[0][QUAD][f_rm(rex, inst)]); 1386173788Sjfv break; 1387169397Sjfv 1388155911Sglebius case Ril: 1389205869Sjfv db_printf("%s", db_reg[rex != 0 ? 1 : 0][(rex & REX_R) ? QUAD : LONG][f_rm(rex, inst)]); 1390160956Spdeuskar break; 1391155911Sglebius 1392173788Sjfv case S: 1393173788Sjfv db_printf("%s", db_seg_reg[f_reg(rex, regmodrm)]); 1394185353Sjfv break; 1395169240Sjfv 1396162532Sandre case Si: 1397205869Sjfv db_printf("%s", db_seg_reg[f_reg(rex, inst)]); 1398205869Sjfv break; 1399295287Smarius 1400295287Smarius case A: 1401295287Smarius db_printf("%s", db_reg[rex != 0 ? 1 : 0][size][0]); /* acc */ 1402295287Smarius break; 1403295287Smarius 1404295287Smarius case BX: 1405295287Smarius if (seg) 1406295287Smarius db_printf("%s:", seg); 1407295287Smarius db_printf("(%s)", short_addr ? "%bx" : "%ebx"); 1408162532Sandre break; 1409169240Sjfv 1410169240Sjfv case CL: 1411169240Sjfv db_printf("%%cl"); 141297785Spdeuskar break; 1413173788Sjfv 1414160956Spdeuskar case DX: 141587189Spdeuskar db_printf("%%dx"); 141697785Spdeuskar break; 1417160956Spdeuskar 141887189Spdeuskar case SI: 1419214363Sjfv if (seg) 1420214363Sjfv db_printf("%s:", seg); 1421214363Sjfv db_printf("(%s)", short_addr ? "%si" : "%rsi"); 1422214363Sjfv break; 1423247064Sjfv 1424214363Sjfv case DI: 1425247064Sjfv db_printf("%%es:(%s)", short_addr ? "%di" : "%rdi"); 1426214363Sjfv break; 1427214363Sjfv 1428214363Sjfv case CR: 1429214363Sjfv db_printf("%%cr%d", f_reg(rex, regmodrm)); 143097785Spdeuskar break; 1431160956Spdeuskar 1432155709Sglebius case DR: 1433160956Spdeuskar db_printf("%%dr%d", f_reg(rex, regmodrm)); 143497785Spdeuskar break; 143597785Spdeuskar 1436160956Spdeuskar case TR: 1437154571Sglebius db_printf("%%tr%d", f_reg(rex, regmodrm)); 1438214363Sjfv break; 1439214363Sjfv 1440214363Sjfv case I: 1441214363Sjfv len = db_lengths[size]; 1442214363Sjfv get_value_inc(imm, loc, len, FALSE); 1443214363Sjfv db_printf("$%#r", imm); 1444214363Sjfv break; 1445214363Sjfv 1446214363Sjfv case Is: 1447214363Sjfv len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size]; 1448214363Sjfv get_value_inc(imm, loc, len, FALSE); 1449214363Sjfv db_printf("$%+#r", imm); 1450214363Sjfv break; 1451160964Syar 1452160956Spdeuskar case Ib: 145387189Spdeuskar get_value_inc(imm, loc, 1, FALSE); 1454228387Sjfv db_printf("$%#r", imm); 1455148887Srwatson break; 1456148887Srwatson 145787189Spdeuskar case Iba: 1458160956Spdeuskar get_value_inc(imm, loc, 1, FALSE); 1459169240Sjfv if (imm != 0x0a) 1460169240Sjfv db_printf("$%#r", imm); 1461178523Sjfv break; 1462178523Sjfv 1463178523Sjfv case Ibs: 1464178523Sjfv get_value_inc(imm, loc, 1, TRUE); 1465178523Sjfv if (size == WORD) 1466178523Sjfv imm &= 0xFFFF; 1467205869Sjfv db_printf("$%+#r", imm); 1468205869Sjfv break; 1469178523Sjfv 1470177867Sjfv case Iw: 1471107242Sluigi get_value_inc(imm, loc, 2, FALSE); 1472155709Sglebius db_printf("$%#r", imm); 1473155709Sglebius break; 1474155709Sglebius 1475155709Sglebius case Ilq: 1476155709Sglebius len = db_lengths[rex & REX_W ? QUAD : LONG]; 1477160956Spdeuskar get_value_inc(imm64, loc, len, FALSE); 1478155709Sglebius db_printf("$%#lr", imm64); 1479107242Sluigi break; 1480160956Spdeuskar 148197785Spdeuskar case O: 1482200243Sjfv len = (short_addr ? 2 : 4); 1483200243Sjfv get_value_inc(displ, loc, len, FALSE); 1484200243Sjfv if (seg) 148587189Spdeuskar db_printf("%s:%+#r",seg, displ); 148687189Spdeuskar else 1487120364Ssam db_printsym((db_addr_t)displ, DB_STGY_ANY); 1488120364Ssam break; 1489120364Ssam 1490160956Spdeuskar case Db: 1491112472Spdeuskar get_value_inc(displ, loc, 1, TRUE); 1492173788Sjfv displ += loc; 1493160956Spdeuskar if (size == WORD) 1494173788Sjfv displ &= 0xFFFF; 1495120364Ssam db_printsym((db_addr_t)displ, DB_STGY_XTRN); 1496120364Ssam break; 1497120364Ssam 1498107242Sluigi case Dl: 1499163730Sjfv len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size]; 1500163730Sjfv get_value_inc(displ, loc, len, FALSE); 1501205869Sjfv displ += loc; 1502163730Sjfv if (size == WORD) 1503163730Sjfv displ &= 0xFFFF; 1504193096Sattilio db_printsym((db_addr_t)displ, DB_STGY_XTRN); 1505159330Sglebius break; 1506107242Sluigi 1507194865Sjfv case o1: 1508205869Sjfv db_printf("$1"); 1509205869Sjfv break; 1510209238Sjfv 1511209238Sjfv case o3: 1512107242Sluigi db_printf("$3"); 1513173788Sjfv break; 1514159330Sglebius 1515173788Sjfv case OS: 1516209238Sjfv len = db_lengths[size]; 1517159330Sglebius get_value_inc(imm, loc, len, FALSE); /* offset */ 1518120364Ssam get_value_inc(imm2, loc, 2, FALSE); /* segment */ 1519154571Sglebius db_printf("$%#r,%#r", imm2, imm); 1520169240Sjfv break; 1521154571Sglebius } 1522205869Sjfv } 1523169240Sjfv db_printf("\n"); 1524160956Spdeuskar return (loc); 1525205869Sjfv} 1526205869Sjfv