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