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