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