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