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