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