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