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