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