Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeni386-dis.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/kdbg/i386/i386-dis.c 00005 * PURPOSE: No purpose listed. 00006 * 00007 * PROGRAMMERS: No programmer listed. 00008 */ 00009 00010 #include <ntoskrnl.h> 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 /* ReactOS compatibility stuff. */ 00015 #define PARAMS(X) X 00016 #define PTR void* 00017 typedef enum bfd_flavour 00018 { 00019 bfd_target_unknown_flavour, 00020 } bfd_flavour; 00021 typedef enum bfd_architecture 00022 { 00023 bfd_arch_i386, 00024 } bfd_arch; 00025 typedef unsigned int bfd_vma; 00026 typedef unsigned char bfd_byte; 00027 enum bfd_endian { BFD_ENDIAN_BIG, BIG_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; 00028 typedef void* bfd; 00029 typedef signed int bfd_signed_vma; 00030 #define bfd_mach_x86_64_intel_syntax 0 00031 #define bfd_mach_x86_64 1 00032 #define bfd_mach_i386_i386_intel_syntax 2 00033 #define bfd_mach_i386_i386 3 00034 #define bfd_mach_i386_i8086 4 00035 #define abort() DbgBreakPoint(); 00036 #define _(X) X 00037 #define ATTRIBUTE_UNUSED 00038 extern int sprintf(char *str, const char *format, ...); 00039 #define sprintf_vma(BUF, VMA) sprintf(BUF, "0x%X", VMA) 00040 struct disassemble_info; 00041 00042 int 00043 print_insn_i386 (bfd_vma pc, struct disassemble_info *info); 00044 00045 int 00046 KdbpPrintDisasm(void* Ignored, const char* fmt, ...) 00047 { 00048 va_list ap; 00049 static char buffer[256]; 00050 int ret; 00051 00052 va_start(ap, fmt); 00053 ret = vsprintf(buffer, fmt, ap); 00054 DbgPrint("%s", buffer); 00055 va_end(ap); 00056 return(ret); 00057 } 00058 00059 int 00060 KdbpNopPrintDisasm(void* Ignored, const char* fmt, ...) 00061 { 00062 return(0); 00063 } 00064 00065 static int 00066 KdbpReadMemory(unsigned int Addr, unsigned char* Data, unsigned int Length, 00067 struct disassemble_info * Ignored) 00068 { 00069 return KdbpSafeReadMemory(Data, (void *)Addr, Length); /* 0 means no error */ 00070 } 00071 00072 static void 00073 KdbpMemoryError(int Status, unsigned int Addr, 00074 struct disassemble_info * Ignored) 00075 { 00076 } 00077 00078 static void 00079 KdbpPrintAddressInCode(unsigned int Addr, struct disassemble_info * Ignored) 00080 { 00081 if (!KdbSymPrintAddress((void*)Addr, NULL)) 00082 { 00083 DbgPrint("<%08x>", Addr); 00084 } 00085 } 00086 00087 static void 00088 KdbpNopPrintAddress(unsigned int Addr, struct disassemble_info * Ignored) 00089 { 00090 } 00091 00092 #include "dis-asm.h" 00093 00094 LONG 00095 KdbpGetInstLength(IN ULONG Address) 00096 { 00097 disassemble_info info; 00098 00099 info.fprintf_func = KdbpNopPrintDisasm; 00100 info.stream = NULL; 00101 info.application_data = NULL; 00102 info.flavour = bfd_target_unknown_flavour; 00103 info.arch = bfd_arch_i386; 00104 info.mach = bfd_mach_i386_i386; 00105 info.insn_sets = 0; 00106 info.flags = 0; 00107 info.read_memory_func = KdbpReadMemory; 00108 info.memory_error_func = KdbpMemoryError; 00109 info.print_address_func = KdbpNopPrintAddress; 00110 info.symbol_at_address_func = NULL; 00111 info.buffer = NULL; 00112 info.buffer_vma = info.buffer_length = 0; 00113 info.bytes_per_chunk = 0; 00114 info.display_endian = BIG_ENDIAN_LITTLE; 00115 info.disassembler_options = NULL; 00116 00117 return(print_insn_i386(Address, &info)); 00118 } 00119 00120 LONG 00121 KdbpDisassemble(IN ULONG Address, IN ULONG IntelSyntax) 00122 { 00123 disassemble_info info; 00124 00125 info.fprintf_func = KdbpPrintDisasm; 00126 info.stream = NULL; 00127 info.application_data = NULL; 00128 info.flavour = bfd_target_unknown_flavour; 00129 info.arch = bfd_arch_i386; 00130 info.mach = IntelSyntax ? bfd_mach_i386_i386_intel_syntax : bfd_mach_i386_i386; 00131 info.insn_sets = 0; 00132 info.flags = 0; 00133 info.read_memory_func = KdbpReadMemory; 00134 info.memory_error_func = KdbpMemoryError; 00135 info.print_address_func = KdbpPrintAddressInCode; 00136 info.symbol_at_address_func = NULL; 00137 info.buffer = NULL; 00138 info.buffer_vma = info.buffer_length = 0; 00139 info.bytes_per_chunk = 0; 00140 info.display_endian = BIG_ENDIAN_LITTLE; 00141 info.disassembler_options = NULL; 00142 00143 return(print_insn_i386(Address, &info)); 00144 } 00145 00146 /* Print i386 instructions for GDB, the GNU debugger. 00147 Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 00148 2001 00149 Free Software Foundation, Inc. 00150 00151 This file is part of GDB. 00152 00153 This program is free software; you can redistribute it and/or modify 00154 it under the terms of the GNU General Public License as published by 00155 the Free Software Foundation; either version 2 of the License, or 00156 (at your option) any later version. 00157 00158 This program is distributed in the hope that it will be useful, 00159 but WITHOUT ANY WARRANTY; without even the implied warranty of 00160 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00161 GNU General Public License for more details. 00162 00163 You should have received a copy of the GNU General Public License along 00164 with this program; if not, write to the Free Software Foundation, Inc., 00165 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00166 */ 00167 00168 /* 00169 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) 00170 * July 1988 00171 * modified by John Hassey (hassey@dg-rtp.dg.com) 00172 * x86-64 support added by Jan Hubicka (jh@suse.cz) 00173 */ 00174 00175 /* 00176 * The main tables describing the instructions is essentially a copy 00177 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386 00178 * Programmers Manual. Usually, there is a capital letter, followed 00179 * by a small letter. The capital letter tell the addressing mode, 00180 * and the small letter tells about the operand size. Refer to 00181 * the Intel manual for details. 00182 */ 00183 00184 #include "dis-asm.h" 00185 #if 0 00186 #include "sysdep.h" 00187 #include "opintl.h" 00188 #endif 00189 00190 #define MAXLEN 20 00191 00192 #include <setjmp.h> 00193 00194 #ifndef UNIXWARE_COMPAT 00195 /* Set non-zero for broken, compatible instructions. Set to zero for 00196 non-broken opcodes. */ 00197 #define UNIXWARE_COMPAT 1 00198 #endif 00199 00200 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *)); 00201 static void ckprefix PARAMS ((void)); 00202 static const char *prefix_name PARAMS ((int, int)); 00203 static int print_insn PARAMS ((bfd_vma, disassemble_info *)); 00204 static void dofloat PARAMS ((int)); 00205 static void OP_ST PARAMS ((int, int)); 00206 static void OP_STi PARAMS ((int, int)); 00207 static int putop PARAMS ((const char *, int)); 00208 static void oappend PARAMS ((const char *)); 00209 static void append_seg PARAMS ((void)); 00210 static void OP_indirE PARAMS ((int, int)); 00211 static void print_operand_value PARAMS ((char *, int, bfd_vma)); 00212 static void OP_E PARAMS ((int, int)); 00213 static void OP_G PARAMS ((int, int)); 00214 static bfd_vma get64 PARAMS ((void)); 00215 static bfd_signed_vma get32 PARAMS ((void)); 00216 static bfd_signed_vma get32s PARAMS ((void)); 00217 static int get16 PARAMS ((void)); 00218 static void set_op PARAMS ((bfd_vma, int)); 00219 static void OP_REG PARAMS ((int, int)); 00220 static void OP_IMREG PARAMS ((int, int)); 00221 static void OP_I PARAMS ((int, int)); 00222 static void OP_I64 PARAMS ((int, int)); 00223 static void OP_sI PARAMS ((int, int)); 00224 static void OP_J PARAMS ((int, int)); 00225 static void OP_SEG PARAMS ((int, int)); 00226 static void OP_DIR PARAMS ((int, int)); 00227 static void OP_OFF PARAMS ((int, int)); 00228 static void OP_OFF64 PARAMS ((int, int)); 00229 static void ptr_reg PARAMS ((int, int)); 00230 static void OP_ESreg PARAMS ((int, int)); 00231 static void OP_DSreg PARAMS ((int, int)); 00232 static void OP_C PARAMS ((int, int)); 00233 static void OP_D PARAMS ((int, int)); 00234 static void OP_T PARAMS ((int, int)); 00235 static void OP_Rd PARAMS ((int, int)); 00236 static void OP_MMX PARAMS ((int, int)); 00237 static void OP_XMM PARAMS ((int, int)); 00238 static void OP_EM PARAMS ((int, int)); 00239 static void OP_EX PARAMS ((int, int)); 00240 static void OP_MS PARAMS ((int, int)); 00241 static void OP_XS PARAMS ((int, int)); 00242 static void OP_3DNowSuffix PARAMS ((int, int)); 00243 static void OP_SIMD_Suffix PARAMS ((int, int)); 00244 static void SIMD_Fixup PARAMS ((int, int)); 00245 static void BadOp PARAMS ((void)); 00246 00247 struct dis_private { 00248 /* Points to first byte not fetched. */ 00249 bfd_byte *max_fetched; 00250 bfd_byte the_buffer[MAXLEN]; 00251 bfd_vma insn_start; 00252 int orig_sizeflag; 00253 jmp_buf bailout; 00254 }; 00255 00256 /* The opcode for the fwait instruction, which we treat as a prefix 00257 when we can. */ 00258 #define FWAIT_OPCODE (0x9b) 00259 00260 /* Set to 1 for 64bit mode disassembly. */ 00261 static int mode_64bit; 00262 00263 /* Flags for the prefixes for the current instruction. See below. */ 00264 static int prefixes; 00265 00266 /* REX prefix the current instruction. See below. */ 00267 static int rex; 00268 /* Bits of REX we've already used. */ 00269 static int rex_used; 00270 #define REX_MODE64 8 00271 #define REX_EXTX 4 00272 #define REX_EXTY 2 00273 #define REX_EXTZ 1 00274 /* Mark parts used in the REX prefix. When we are testing for 00275 empty prefix (for 8bit register REX extension), just mask it 00276 out. Otherwise test for REX bit is excuse for existence of REX 00277 only in case value is nonzero. */ 00278 #define USED_REX(value) \ 00279 { \ 00280 if (value) \ 00281 rex_used |= (rex & value) ? (value) | 0x40 : 0; \ 00282 else \ 00283 rex_used |= 0x40; \ 00284 } 00285 00286 /* Flags for prefixes which we somehow handled when printing the 00287 current instruction. */ 00288 static int used_prefixes; 00289 00290 /* Flags stored in PREFIXES. */ 00291 #define PREFIX_REPZ 1 00292 #define PREFIX_REPNZ 2 00293 #define PREFIX_LOCK 4 00294 #define PREFIX_CS 8 00295 #define PREFIX_SS 0x10 00296 #define PREFIX_DS 0x20 00297 #define PREFIX_ES 0x40 00298 #define PREFIX_FS 0x80 00299 #define PREFIX_GS 0x100 00300 #define PREFIX_DATA 0x200 00301 #define PREFIX_ADDR 0x400 00302 #define PREFIX_FWAIT 0x800 00303 00304 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) 00305 to ADDR (exclusive) are valid. Returns 1 for success, longjmps 00306 on error. */ 00307 #define FETCH_DATA(info, addr) \ 00308 ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \ 00309 ? 1 : fetch_data ((info), (addr))) 00310 00311 static int 00312 fetch_data (info, addr) 00313 struct disassemble_info *info; 00314 bfd_byte *addr; 00315 { 00316 int status; 00317 struct dis_private *priv = (struct dis_private *) info->private_data; 00318 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); 00319 00320 status = (*info->read_memory_func) (start, 00321 priv->max_fetched, 00322 addr - priv->max_fetched, 00323 info); 00324 if (status != 0) 00325 { 00326 /* If we did manage to read at least one byte, then 00327 print_insn_i386 will do something sensible. Otherwise, print 00328 an error. We do that here because this is where we know 00329 STATUS. */ 00330 if (priv->max_fetched == priv->the_buffer) 00331 (*info->memory_error_func) (status, start, info); 00332 longjmp (priv->bailout, 1); 00333 } 00334 else 00335 priv->max_fetched = addr; 00336 return 1; 00337 } 00338 00339 #define XX NULL, 0 00340 00341 #define Eb OP_E, b_mode 00342 #define Ev OP_E, v_mode 00343 #define Ed OP_E, d_mode 00344 #define indirEb OP_indirE, b_mode 00345 #define indirEv OP_indirE, v_mode 00346 #define Ew OP_E, w_mode 00347 #define Ma OP_E, v_mode 00348 #define M OP_E, 0 /* lea, lgdt, etc. */ 00349 #define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */ 00350 #define Gb OP_G, b_mode 00351 #define Gv OP_G, v_mode 00352 #define Gd OP_G, d_mode 00353 #define Gw OP_G, w_mode 00354 #define Rd OP_Rd, d_mode 00355 #define Rm OP_Rd, m_mode 00356 #define Ib OP_I, b_mode 00357 #define sIb OP_sI, b_mode /* sign extened byte */ 00358 #define Iv OP_I, v_mode 00359 #define Iq OP_I, q_mode 00360 #define Iv64 OP_I64, v_mode 00361 #define Iw OP_I, w_mode 00362 #define Jb OP_J, b_mode 00363 #define Jv OP_J, v_mode 00364 #define Cm OP_C, m_mode 00365 #define Dm OP_D, m_mode 00366 #define Td OP_T, d_mode 00367 00368 #define RMeAX OP_REG, eAX_reg 00369 #define RMeBX OP_REG, eBX_reg 00370 #define RMeCX OP_REG, eCX_reg 00371 #define RMeDX OP_REG, eDX_reg 00372 #define RMeSP OP_REG, eSP_reg 00373 #define RMeBP OP_REG, eBP_reg 00374 #define RMeSI OP_REG, eSI_reg 00375 #define RMeDI OP_REG, eDI_reg 00376 #define RMrAX OP_REG, rAX_reg 00377 #define RMrBX OP_REG, rBX_reg 00378 #define RMrCX OP_REG, rCX_reg 00379 #define RMrDX OP_REG, rDX_reg 00380 #define RMrSP OP_REG, rSP_reg 00381 #define RMrBP OP_REG, rBP_reg 00382 #define RMrSI OP_REG, rSI_reg 00383 #define RMrDI OP_REG, rDI_reg 00384 #define RMAL OP_REG, al_reg 00385 #define RMAL OP_REG, al_reg 00386 #define RMCL OP_REG, cl_reg 00387 #define RMDL OP_REG, dl_reg 00388 #define RMBL OP_REG, bl_reg 00389 #define RMAH OP_REG, ah_reg 00390 #define RMCH OP_REG, ch_reg 00391 #define RMDH OP_REG, dh_reg 00392 #define RMBH OP_REG, bh_reg 00393 #define RMAX OP_REG, ax_reg 00394 #define RMDX OP_REG, dx_reg 00395 00396 #define eAX OP_IMREG, eAX_reg 00397 #define eBX OP_IMREG, eBX_reg 00398 #define eCX OP_IMREG, eCX_reg 00399 #define eDX OP_IMREG, eDX_reg 00400 #define eSP OP_IMREG, eSP_reg 00401 #define eBP OP_IMREG, eBP_reg 00402 #define eSI OP_IMREG, eSI_reg 00403 #define eDI OP_IMREG, eDI_reg 00404 #define AL OP_IMREG, al_reg 00405 #define AL OP_IMREG, al_reg 00406 #define CL OP_IMREG, cl_reg 00407 #define DL OP_IMREG, dl_reg 00408 #define BL OP_IMREG, bl_reg 00409 #define AH OP_IMREG, ah_reg 00410 #define CH OP_IMREG, ch_reg 00411 #define DH OP_IMREG, dh_reg 00412 #define BH OP_IMREG, bh_reg 00413 #define AX OP_IMREG, ax_reg 00414 #define DX OP_IMREG, dx_reg 00415 #define indirDX OP_IMREG, indir_dx_reg 00416 00417 #define Sw OP_SEG, w_mode 00418 #define Ap OP_DIR, 0 00419 #define Ob OP_OFF, b_mode 00420 #define Ob64 OP_OFF64, b_mode 00421 #define Ov OP_OFF, v_mode 00422 #define Ov64 OP_OFF64, v_mode 00423 #define Xb OP_DSreg, eSI_reg 00424 #define Xv OP_DSreg, eSI_reg 00425 #define Yb OP_ESreg, eDI_reg 00426 #define Yv OP_ESreg, eDI_reg 00427 #define DSBX OP_DSreg, eBX_reg 00428 00429 #define es OP_REG, es_reg 00430 #define ss OP_REG, ss_reg 00431 #define cs OP_REG, cs_reg 00432 #define ds OP_REG, ds_reg 00433 #define fs OP_REG, fs_reg 00434 #define gs OP_REG, gs_reg 00435 00436 #define MX OP_MMX, 0 00437 #define XM OP_XMM, 0 00438 #define EM OP_EM, v_mode 00439 #define EX OP_EX, v_mode 00440 #define MS OP_MS, v_mode 00441 #define XS OP_XS, v_mode 00442 #define None OP_E, 0 00443 #define OPSUF OP_3DNowSuffix, 0 00444 #define OPSIMD OP_SIMD_Suffix, 0 00445 00446 #define cond_jump_flag NULL, cond_jump_mode 00447 #define loop_jcxz_flag NULL, loop_jcxz_mode 00448 00449 /* bits in sizeflag */ 00450 #define SUFFIX_ALWAYS 4 00451 #define AFLAG 2 00452 #define DFLAG 1 00453 00454 #define b_mode 1 /* byte operand */ 00455 #define v_mode 2 /* operand size depends on prefixes */ 00456 #define w_mode 3 /* word operand */ 00457 #define d_mode 4 /* double word operand */ 00458 #define q_mode 5 /* quad word operand */ 00459 #define x_mode 6 00460 #define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */ 00461 #define cond_jump_mode 8 00462 #define loop_jcxz_mode 9 00463 00464 #define es_reg 100 00465 #define cs_reg 101 00466 #define ss_reg 102 00467 #define ds_reg 103 00468 #define fs_reg 104 00469 #define gs_reg 105 00470 00471 #define eAX_reg 108 00472 #define eCX_reg 109 00473 #define eDX_reg 110 00474 #define eBX_reg 111 00475 #define eSP_reg 112 00476 #define eBP_reg 113 00477 #define eSI_reg 114 00478 #define eDI_reg 115 00479 00480 #define al_reg 116 00481 #define cl_reg 117 00482 #define dl_reg 118 00483 #define bl_reg 119 00484 #define ah_reg 120 00485 #define ch_reg 121 00486 #define dh_reg 122 00487 #define bh_reg 123 00488 00489 #define ax_reg 124 00490 #define cx_reg 125 00491 #define dx_reg 126 00492 #define bx_reg 127 00493 #define sp_reg 128 00494 #define bp_reg 129 00495 #define si_reg 130 00496 #define di_reg 131 00497 00498 #define rAX_reg 132 00499 #define rCX_reg 133 00500 #define rDX_reg 134 00501 #define rBX_reg 135 00502 #define rSP_reg 136 00503 #define rBP_reg 137 00504 #define rSI_reg 138 00505 #define rDI_reg 139 00506 00507 #define indir_dx_reg 150 00508 00509 #define FLOATCODE 1 00510 #define USE_GROUPS 2 00511 #define USE_PREFIX_USER_TABLE 3 00512 #define X86_64_SPECIAL 4 00513 00514 #define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0 00515 00516 #define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0 00517 #define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0 00518 #define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0 00519 #define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0 00520 #define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0 00521 #define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0 00522 #define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0 00523 #define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0 00524 #define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0 00525 #define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0 00526 #define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0 00527 #define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0 00528 #define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0 00529 #define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0 00530 #define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0 00531 #define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0 00532 #define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0 00533 #define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0 00534 #define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0 00535 #define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0 00536 #define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0 00537 #define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0 00538 #define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0 00539 00540 #define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0 00541 #define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0 00542 #define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0 00543 #define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0 00544 #define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0 00545 #define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0 00546 #define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0 00547 #define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0 00548 #define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0 00549 #define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0 00550 #define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0 00551 #define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0 00552 #define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0 00553 #define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0 00554 #define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0 00555 #define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0 00556 #define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0 00557 #define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0 00558 #define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0 00559 #define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0 00560 #define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0 00561 #define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0 00562 #define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0 00563 #define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0 00564 #define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0 00565 #define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0 00566 #define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0 00567 00568 #define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0 00569 00570 typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag)); 00571 00572 struct dis386 { 00573 const char *name; 00574 op_rtn op1; 00575 int bytemode1; 00576 op_rtn op2; 00577 int bytemode2; 00578 op_rtn op3; 00579 int bytemode3; 00580 }; 00581 00582 /* Upper case letters in the instruction names here are macros. 00583 'A' => print 'b' if no register operands or suffix_always is true 00584 'B' => print 'b' if suffix_always is true 00585 'E' => print 'e' if 32-bit form of jcxz 00586 'F' => print 'w' or 'l' depending on address size prefix (loop insns) 00587 'H' => print ",pt" or ",pn" branch hint 00588 'L' => print 'l' if suffix_always is true 00589 'N' => print 'n' if instruction has no wait "prefix" 00590 'O' => print 'd', or 'o' 00591 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, 00592 . or suffix_always is true. print 'q' if rex prefix is present. 00593 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always 00594 . is true 00595 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode) 00596 'S' => print 'w', 'l' or 'q' if suffix_always is true 00597 'T' => print 'q' in 64bit mode and behave as 'P' otherwise 00598 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise 00599 'X' => print 's', 'd' depending on data16 prefix (for XMM) 00600 'W' => print 'b' or 'w' ("w" or "de" in intel mode) 00601 'Y' => 'q' if instruction has an REX 64bit overwrite prefix 00602 00603 Many of the above letters print nothing in Intel mode. See "putop" 00604 for the details. 00605 00606 Braces '{' and '}', and vertical bars '|', indicate alternative 00607 mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel 00608 modes. In cases where there are only two alternatives, the X86_64 00609 instruction is reserved, and "(bad)" is printed. 00610 */ 00611 00612 static const struct dis386 dis386[] = { 00613 /* 00 */ 00614 { "addB", Eb, Gb, XX }, 00615 { "addS", Ev, Gv, XX }, 00616 { "addB", Gb, Eb, XX }, 00617 { "addS", Gv, Ev, XX }, 00618 { "addB", AL, Ib, XX }, 00619 { "addS", eAX, Iv, XX }, 00620 { "push{T|}", es, XX, XX }, 00621 { "pop{T|}", es, XX, XX }, 00622 /* 08 */ 00623 { "orB", Eb, Gb, XX }, 00624 { "orS", Ev, Gv, XX }, 00625 { "orB", Gb, Eb, XX }, 00626 { "orS", Gv, Ev, XX }, 00627 { "orB", AL, Ib, XX }, 00628 { "orS", eAX, Iv, XX }, 00629 { "push{T|}", cs, XX, XX }, 00630 { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */ 00631 /* 10 */ 00632 { "adcB", Eb, Gb, XX }, 00633 { "adcS", Ev, Gv, XX }, 00634 { "adcB", Gb, Eb, XX }, 00635 { "adcS", Gv, Ev, XX }, 00636 { "adcB", AL, Ib, XX }, 00637 { "adcS", eAX, Iv, XX }, 00638 { "push{T|}", ss, XX, XX }, 00639 { "popT|}", ss, XX, XX }, 00640 /* 18 */ 00641 { "sbbB", Eb, Gb, XX }, 00642 { "sbbS", Ev, Gv, XX }, 00643 { "sbbB", Gb, Eb, XX }, 00644 { "sbbS", Gv, Ev, XX }, 00645 { "sbbB", AL, Ib, XX }, 00646 { "sbbS", eAX, Iv, XX }, 00647 { "push{T|}", ds, XX, XX }, 00648 { "pop{T|}", ds, XX, XX }, 00649 /* 20 */ 00650 { "andB", Eb, Gb, XX }, 00651 { "andS", Ev, Gv, XX }, 00652 { "andB", Gb, Eb, XX }, 00653 { "andS", Gv, Ev, XX }, 00654 { "andB", AL, Ib, XX }, 00655 { "andS", eAX, Iv, XX }, 00656 { "(bad)", XX, XX, XX }, /* SEG ES prefix */ 00657 { "daa{|}", XX, XX, XX }, 00658 /* 28 */ 00659 { "subB", Eb, Gb, XX }, 00660 { "subS", Ev, Gv, XX }, 00661 { "subB", Gb, Eb, XX }, 00662 { "subS", Gv, Ev, XX }, 00663 { "subB", AL, Ib, XX }, 00664 { "subS", eAX, Iv, XX }, 00665 { "(bad)", XX, XX, XX }, /* SEG CS prefix */ 00666 { "das{|}", XX, XX, XX }, 00667 /* 30 */ 00668 { "xorB", Eb, Gb, XX }, 00669 { "xorS", Ev, Gv, XX }, 00670 { "xorB", Gb, Eb, XX }, 00671 { "xorS", Gv, Ev, XX }, 00672 { "xorB", AL, Ib, XX }, 00673 { "xorS", eAX, Iv, XX }, 00674 { "(bad)", XX, XX, XX }, /* SEG SS prefix */ 00675 { "aaa{|}", XX, XX, XX }, 00676 /* 38 */ 00677 { "cmpB", Eb, Gb, XX }, 00678 { "cmpS", Ev, Gv, XX }, 00679 { "cmpB", Gb, Eb, XX }, 00680 { "cmpS", Gv, Ev, XX }, 00681 { "cmpB", AL, Ib, XX }, 00682 { "cmpS", eAX, Iv, XX }, 00683 { "(bad)", XX, XX, XX }, /* SEG DS prefix */ 00684 { "aas{|}", XX, XX, XX }, 00685 /* 40 */ 00686 { "inc{S|}", RMeAX, XX, XX }, 00687 { "inc{S|}", RMeCX, XX, XX }, 00688 { "inc{S|}", RMeDX, XX, XX }, 00689 { "inc{S|}", RMeBX, XX, XX }, 00690 { "inc{S|}", RMeSP, XX, XX }, 00691 { "inc{S|}", RMeBP, XX, XX }, 00692 { "inc{S|}", RMeSI, XX, XX }, 00693 { "inc{S|}", RMeDI, XX, XX }, 00694 /* 48 */ 00695 { "dec{S|}", RMeAX, XX, XX }, 00696 { "dec{S|}", RMeCX, XX, XX }, 00697 { "dec{S|}", RMeDX, XX, XX }, 00698 { "dec{S|}", RMeBX, XX, XX }, 00699 { "dec{S|}", RMeSP, XX, XX }, 00700 { "dec{S|}", RMeBP, XX, XX }, 00701 { "dec{S|}", RMeSI, XX, XX }, 00702 { "dec{S|}", RMeDI, XX, XX }, 00703 /* 50 */ 00704 { "pushS", RMrAX, XX, XX }, 00705 { "pushS", RMrCX, XX, XX }, 00706 { "pushS", RMrDX, XX, XX }, 00707 { "pushS", RMrBX, XX, XX }, 00708 { "pushS", RMrSP, XX, XX }, 00709 { "pushS", RMrBP, XX, XX }, 00710 { "pushS", RMrSI, XX, XX }, 00711 { "pushS", RMrDI, XX, XX }, 00712 /* 58 */ 00713 { "popS", RMrAX, XX, XX }, 00714 { "popS", RMrCX, XX, XX }, 00715 { "popS", RMrDX, XX, XX }, 00716 { "popS", RMrBX, XX, XX }, 00717 { "popS", RMrSP, XX, XX }, 00718 { "popS", RMrBP, XX, XX }, 00719 { "popS", RMrSI, XX, XX }, 00720 { "popS", RMrDI, XX, XX }, 00721 /* 60 */ 00722 { "pusha{P|}", XX, XX, XX }, 00723 { "popa{P|}", XX, XX, XX }, 00724 { "bound{S|}", Gv, Ma, XX }, 00725 { X86_64_0 }, 00726 { "(bad)", XX, XX, XX }, /* seg fs */ 00727 { "(bad)", XX, XX, XX }, /* seg gs */ 00728 { "(bad)", XX, XX, XX }, /* op size prefix */ 00729 { "(bad)", XX, XX, XX }, /* adr size prefix */ 00730 /* 68 */ 00731 { "pushT", Iq, XX, XX }, 00732 { "imulS", Gv, Ev, Iv }, 00733 { "pushT", sIb, XX, XX }, 00734 { "imulS", Gv, Ev, sIb }, 00735 { "ins{b||b|}", Yb, indirDX, XX }, 00736 { "ins{R||R|}", Yv, indirDX, XX }, 00737 { "outs{b||b|}", indirDX, Xb, XX }, 00738 { "outs{R||R|}", indirDX, Xv, XX }, 00739 /* 70 */ 00740 { "joH", Jb, XX, cond_jump_flag }, 00741 { "jnoH", Jb, XX, cond_jump_flag }, 00742 { "jbH", Jb, XX, cond_jump_flag }, 00743 { "jaeH", Jb, XX, cond_jump_flag }, 00744 { "jeH", Jb, XX, cond_jump_flag }, 00745 { "jneH", Jb, XX, cond_jump_flag }, 00746 { "jbeH", Jb, XX, cond_jump_flag }, 00747 { "jaH", Jb, XX, cond_jump_flag }, 00748 /* 78 */ 00749 { "jsH", Jb, XX, cond_jump_flag }, 00750 { "jnsH", Jb, XX, cond_jump_flag }, 00751 { "jpH", Jb, XX, cond_jump_flag }, 00752 { "jnpH", Jb, XX, cond_jump_flag }, 00753 { "jlH", Jb, XX, cond_jump_flag }, 00754 { "jgeH", Jb, XX, cond_jump_flag }, 00755 { "jleH", Jb, XX, cond_jump_flag }, 00756 { "jgH", Jb, XX, cond_jump_flag }, 00757 /* 80 */ 00758 { GRP1b }, 00759 { GRP1S }, 00760 { "(bad)", XX, XX, XX }, 00761 { GRP1Ss }, 00762 { "testB", Eb, Gb, XX }, 00763 { "testS", Ev, Gv, XX }, 00764 { "xchgB", Eb, Gb, XX }, 00765 { "xchgS", Ev, Gv, XX }, 00766 /* 88 */ 00767 { "movB", Eb, Gb, XX }, 00768 { "movS", Ev, Gv, XX }, 00769 { "movB", Gb, Eb, XX }, 00770 { "movS", Gv, Ev, XX }, 00771 { "movQ", Ev, Sw, XX }, 00772 { "leaS", Gv, M, XX }, 00773 { "movQ", Sw, Ev, XX }, 00774 { "popU", Ev, XX, XX }, 00775 /* 90 */ 00776 { "nop", XX, XX, XX }, 00777 /* FIXME: NOP with REPz prefix is called PAUSE. */ 00778 { "xchgS", RMeCX, eAX, XX }, 00779 { "xchgS", RMeDX, eAX, XX }, 00780 { "xchgS", RMeBX, eAX, XX }, 00781 { "xchgS", RMeSP, eAX, XX }, 00782 { "xchgS", RMeBP, eAX, XX }, 00783 { "xchgS", RMeSI, eAX, XX }, 00784 { "xchgS", RMeDI, eAX, XX }, 00785 /* 98 */ 00786 { "cW{tR||tR|}", XX, XX, XX }, 00787 { "cR{tO||tO|}", XX, XX, XX }, 00788 { "lcall{T|}", Ap, XX, XX }, 00789 { "(bad)", XX, XX, XX }, /* fwait */ 00790 { "pushfT", XX, XX, XX }, 00791 { "popfT", XX, XX, XX }, 00792 { "sahf{|}", XX, XX, XX }, 00793 { "lahf{|}", XX, XX, XX }, 00794 /* a0 */ 00795 { "movB", AL, Ob64, XX }, 00796 { "movS", eAX, Ov64, XX }, 00797 { "movB", Ob64, AL, XX }, 00798 { "movS", Ov64, eAX, XX }, 00799 { "movs{b||b|}", Yb, Xb, XX }, 00800 { "movs{R||R|}", Yv, Xv, XX }, 00801 { "cmps{b||b|}", Xb, Yb, XX }, 00802 { "cmps{R||R|}", Xv, Yv, XX }, 00803 /* a8 */ 00804 { "testB", AL, Ib, XX }, 00805 { "testS", eAX, Iv, XX }, 00806 { "stosB", Yb, AL, XX }, 00807 { "stosS", Yv, eAX, XX }, 00808 { "lodsB", AL, Xb, XX }, 00809 { "lodsS", eAX, Xv, XX }, 00810 { "scasB", AL, Yb, XX }, 00811 { "scasS", eAX, Yv, XX }, 00812 /* b0 */ 00813 { "movB", RMAL, Ib, XX }, 00814 { "movB", RMCL, Ib, XX }, 00815 { "movB", RMDL, Ib, XX }, 00816 { "movB", RMBL, Ib, XX }, 00817 { "movB", RMAH, Ib, XX }, 00818 { "movB", RMCH, Ib, XX }, 00819 { "movB", RMDH, Ib, XX }, 00820 { "movB", RMBH, Ib, XX }, 00821 /* b8 */ 00822 { "movS", RMeAX, Iv64, XX }, 00823 { "movS", RMeCX, Iv64, XX }, 00824 { "movS", RMeDX, Iv64, XX }, 00825 { "movS", RMeBX, Iv64, XX }, 00826 { "movS", RMeSP, Iv64, XX }, 00827 { "movS", RMeBP, Iv64, XX }, 00828 { "movS", RMeSI, Iv64, XX }, 00829 { "movS", RMeDI, Iv64, XX }, 00830 /* c0 */ 00831 { GRP2b }, 00832 { GRP2S }, 00833 { "retT", Iw, XX, XX }, 00834 { "retT", XX, XX, XX }, 00835 { "les{S|}", Gv, Mp, XX }, 00836 { "ldsS", Gv, Mp, XX }, 00837 { "movA", Eb, Ib, XX }, 00838 { "movQ", Ev, Iv, XX }, 00839 /* c8 */ 00840 { "enterT", Iw, Ib, XX }, 00841 { "leaveT", XX, XX, XX }, 00842 { "lretP", Iw, XX, XX }, 00843 { "lretP", XX, XX, XX }, 00844 { "int3", XX, XX, XX }, 00845 { "int", Ib, XX, XX }, 00846 { "into{|}", XX, XX, XX }, 00847 { "iretP", XX, XX, XX }, 00848 /* d0 */ 00849 { GRP2b_one }, 00850 { GRP2S_one }, 00851 { GRP2b_cl }, 00852 { GRP2S_cl }, 00853 { "aam{|}", sIb, XX, XX }, 00854 { "aad{|}", sIb, XX, XX }, 00855 { "(bad)", XX, XX, XX }, 00856 { "xlat", DSBX, XX, XX }, 00857 /* d8 */ 00858 { FLOAT }, 00859 { FLOAT }, 00860 { FLOAT }, 00861 { FLOAT }, 00862 { FLOAT }, 00863 { FLOAT }, 00864 { FLOAT }, 00865 { FLOAT }, 00866 /* e0 */ 00867 { "loopneFH", Jb, XX, loop_jcxz_flag }, 00868 { "loopeFH", Jb, XX, loop_jcxz_flag }, 00869 { "loopFH", Jb, XX, loop_jcxz_flag }, 00870 { "jEcxzH", Jb, XX, loop_jcxz_flag }, 00871 { "inB", AL, Ib, XX }, 00872 { "inS", eAX, Ib, XX }, 00873 { "outB", Ib, AL, XX }, 00874 { "outS", Ib, eAX, XX }, 00875 /* e8 */ 00876 { "callT", Jv, XX, XX }, 00877 { "jmpT", Jv, XX, XX }, 00878 { "ljmp{T|}", Ap, XX, XX }, 00879 { "jmp", Jb, XX, XX }, 00880 { "inB", AL, indirDX, XX }, 00881 { "inS", eAX, indirDX, XX }, 00882 { "outB", indirDX, AL, XX }, 00883 { "outS", indirDX, eAX, XX }, 00884 /* f0 */ 00885 { "(bad)", XX, XX, XX }, /* lock prefix */ 00886 { "(bad)", XX, XX, XX }, 00887 { "(bad)", XX, XX, XX }, /* repne */ 00888 { "(bad)", XX, XX, XX }, /* repz */ 00889 { "hlt", XX, XX, XX }, 00890 { "cmc", XX, XX, XX }, 00891 { GRP3b }, 00892 { GRP3S }, 00893 /* f8 */ 00894 { "clc", XX, XX, XX }, 00895 { "stc", XX, XX, XX }, 00896 { "cli", XX, XX, XX }, 00897 { "sti", XX, XX, XX }, 00898 { "cld", XX, XX, XX }, 00899 { "std", XX, XX, XX }, 00900 { GRP4 }, 00901 { GRP5 }, 00902 }; 00903 00904 static const struct dis386 dis386_twobyte[] = { 00905 /* 00 */ 00906 { GRP6 }, 00907 { GRP7 }, 00908 { "larS", Gv, Ew, XX }, 00909 { "lslS", Gv, Ew, XX }, 00910 { "(bad)", XX, XX, XX }, 00911 { "syscall", XX, XX, XX }, 00912 { "clts", XX, XX, XX }, 00913 { "sysretP", XX, XX, XX }, 00914 /* 08 */ 00915 { "invd", XX, XX, XX }, 00916 { "wbinvd", XX, XX, XX }, 00917 { "(bad)", XX, XX, XX }, 00918 { "ud2a", XX, XX, XX }, 00919 { "(bad)", XX, XX, XX }, 00920 { GRPAMD }, 00921 { "femms", XX, XX, XX }, 00922 { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix. */ 00923 /* 10 */ 00924 { PREGRP8 }, 00925 { PREGRP9 }, 00926 { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */ 00927 { "movlpX", EX, XM, SIMD_Fixup, 'h' }, 00928 { "unpcklpX", XM, EX, XX }, 00929 { "unpckhpX", XM, EX, XX }, 00930 { "movhpX", XM, EX, SIMD_Fixup, 'l' }, 00931 { "movhpX", EX, XM, SIMD_Fixup, 'l' }, 00932 /* 18 */ 00933 { GRP14 }, 00934 { "(bad)", XX, XX, XX }, 00935 { "(bad)", XX, XX, XX }, 00936 { "(bad)", XX, XX, XX }, 00937 { "(bad)", XX, XX, XX }, 00938 { "(bad)", XX, XX, XX }, 00939 { "(bad)", XX, XX, XX }, 00940 { "(bad)", XX, XX, XX }, 00941 /* 20 */ 00942 { "movL", Rm, Cm, XX }, 00943 { "movL", Rm, Dm, XX }, 00944 { "movL", Cm, Rm, XX }, 00945 { "movL", Dm, Rm, XX }, 00946 { "movL", Rd, Td, XX }, 00947 { "(bad)", XX, XX, XX }, 00948 { "movL", Td, Rd, XX }, 00949 { "(bad)", XX, XX, XX }, 00950 /* 28 */ 00951 { "movapX", XM, EX, XX }, 00952 { "movapX", EX, XM, XX }, 00953 { PREGRP2 }, 00954 { "movntpX", Ev, XM, XX }, 00955 { PREGRP4 }, 00956 { PREGRP3 }, 00957 { "ucomisX", XM,EX, XX }, 00958 { "comisX", XM,EX, XX }, 00959 /* 30 */ 00960 { "wrmsr", XX, XX, XX }, 00961 { "rdtsc", XX, XX, XX }, 00962 { "rdmsr", XX, XX, XX }, 00963 { "rdpmc", XX, XX, XX }, 00964 { "sysenter", XX, XX, XX }, 00965 { "sysexit", XX, XX, XX }, 00966 { "(bad)", XX, XX, XX }, 00967 { "(bad)", XX, XX, XX }, 00968 /* 38 */ 00969 { "(bad)", XX, XX, XX }, 00970 { "(bad)", XX, XX, XX }, 00971 { "(bad)", XX, XX, XX }, 00972 { "(bad)", XX, XX, XX }, 00973 { "(bad)", XX, XX, XX }, 00974 { "(bad)", XX, XX, XX }, 00975 { "(bad)", XX, XX, XX }, 00976 { "(bad)", XX, XX, XX }, 00977 /* 40 */ 00978 { "cmovo", Gv, Ev, XX }, 00979 { "cmovno", Gv, Ev, XX }, 00980 { "cmovb", Gv, Ev, XX }, 00981 { "cmovae", Gv, Ev, XX }, 00982 { "cmove", Gv, Ev, XX }, 00983 { "cmovne", Gv, Ev, XX }, 00984 { "cmovbe", Gv, Ev, XX }, 00985 { "cmova", Gv, Ev, XX }, 00986 /* 48 */ 00987 { "cmovs", Gv, Ev, XX }, 00988 { "cmovns", Gv, Ev, XX }, 00989 { "cmovp", Gv, Ev, XX }, 00990 { "cmovnp", Gv, Ev, XX }, 00991 { "cmovl", Gv, Ev, XX }, 00992 { "cmovge", Gv, Ev, XX }, 00993 { "cmovle", Gv, Ev, XX }, 00994 { "cmovg", Gv, Ev, XX }, 00995 /* 50 */ 00996 { "movmskpX", Gd, XS, XX }, 00997 { PREGRP13 }, 00998 { PREGRP12 }, 00999 { PREGRP11 }, 01000 { "andpX", XM, EX, XX }, 01001 { "andnpX", XM, EX, XX }, 01002 { "orpX", XM, EX, XX }, 01003 { "xorpX", XM, EX, XX }, 01004 /* 58 */ 01005 { PREGRP0 }, 01006 { PREGRP10 }, 01007 { PREGRP17 }, 01008 { PREGRP16 }, 01009 { PREGRP14 }, 01010 { PREGRP7 }, 01011 { PREGRP5 }, 01012 { PREGRP6 }, 01013 /* 60 */ 01014 { "punpcklbw", MX, EM, XX }, 01015 { "punpcklwd", MX, EM, XX }, 01016 { "punpckldq", MX, EM, XX }, 01017 { "packsswb", MX, EM, XX }, 01018 { "pcmpgtb", MX, EM, XX }, 01019 { "pcmpgtw", MX, EM, XX }, 01020 { "pcmpgtd", MX, EM, XX }, 01021 { "packuswb", MX, EM, XX }, 01022 /* 68 */ 01023 { "punpckhbw", MX, EM, XX }, 01024 { "punpckhwd", MX, EM, XX }, 01025 { "punpckhdq", MX, EM, XX }, 01026 { "packssdw", MX, EM, XX }, 01027 { PREGRP26 }, 01028 { PREGRP24 }, 01029 { "movd", MX, Ed, XX }, 01030 { PREGRP19 }, 01031 /* 70 */ 01032 { PREGRP22 }, 01033 { GRP10 }, 01034 { GRP11 }, 01035 { GRP12 }, 01036 { "pcmpeqb", MX, EM, XX }, 01037 { "pcmpeqw", MX, EM, XX }, 01038 { "pcmpeqd", MX, EM, XX }, 01039 { "emms", XX, XX, XX }, 01040 /* 78 */ 01041 { "(bad)", XX, XX, XX }, 01042 { "(bad)", XX, XX, XX }, 01043 { "(bad)", XX, XX, XX }, 01044 { "(bad)", XX, XX, XX }, 01045 { "(bad)", XX, XX, XX }, 01046 { "(bad)", XX, XX, XX }, 01047 { PREGRP23 }, 01048 { PREGRP20 }, 01049 /* 80 */ 01050 { "joH", Jv, XX, cond_jump_flag }, 01051 { "jnoH", Jv, XX, cond_jump_flag }, 01052 { "jbH", Jv, XX, cond_jump_flag }, 01053 { "jaeH", Jv, XX, cond_jump_flag }, 01054 { "jeH", Jv, XX, cond_jump_flag }, 01055 { "jneH", Jv, XX, cond_jump_flag }, 01056 { "jbeH", Jv, XX, cond_jump_flag }, 01057 { "jaH", Jv, XX, cond_jump_flag }, 01058 /* 88 */ 01059 { "jsH", Jv, XX, cond_jump_flag }, 01060 { "jnsH", Jv, XX, cond_jump_flag }, 01061 { "jpH", Jv, XX, cond_jump_flag }, 01062 { "jnpH", Jv, XX, cond_jump_flag }, 01063 { "jlH", Jv, XX, cond_jump_flag }, 01064 { "jgeH", Jv, XX, cond_jump_flag }, 01065 { "jleH", Jv, XX, cond_jump_flag }, 01066 { "jgH", Jv, XX, cond_jump_flag }, 01067 /* 90 */ 01068 { "seto", Eb, XX, XX }, 01069 { "setno", Eb, XX, XX }, 01070 { "setb", Eb, XX, XX }, 01071 { "setae", Eb, XX, XX }, 01072 { "sete", Eb, XX, XX }, 01073 { "setne", Eb, XX, XX }, 01074 { "setbe", Eb, XX, XX }, 01075 { "seta", Eb, XX, XX }, 01076 /* 98 */ 01077 { "sets", Eb, XX, XX }, 01078 { "setns", Eb, XX, XX }, 01079 { "setp", Eb, XX, XX }, 01080 { "setnp", Eb, XX, XX }, 01081 { "setl", Eb, XX, XX }, 01082 { "setge", Eb, XX, XX }, 01083 { "setle", Eb, XX, XX }, 01084 { "setg", Eb, XX, XX }, 01085 /* a0 */ 01086 { "pushT", fs, XX, XX }, 01087 { "popT", fs, XX, XX }, 01088 { "cpuid", XX, XX, XX }, 01089 { "btS", Ev, Gv, XX }, 01090 { "shldS", Ev, Gv, Ib }, 01091 { "shldS", Ev, Gv, CL }, 01092 { "(bad)", XX, XX, XX }, 01093 { "(bad)", XX, XX, XX }, 01094 /* a8 */ 01095 { "pushT", gs, XX, XX }, 01096 { "popT", gs, XX, XX }, 01097 { "rsm", XX, XX, XX }, 01098 { "btsS", Ev, Gv, XX }, 01099 { "shrdS", Ev, Gv, Ib }, 01100 { "shrdS", Ev, Gv, CL }, 01101 { GRP13 }, 01102 { "imulS", Gv, Ev, XX }, 01103 /* b0 */ 01104 { "cmpxchgB", Eb, Gb, XX }, 01105 { "cmpxchgS", Ev, Gv, XX }, 01106 { "lssS", Gv, Mp, XX }, 01107 { "btrS", Ev, Gv, XX }, 01108 { "lfsS", Gv, Mp, XX }, 01109 { "lgsS", Gv, Mp, XX }, 01110 { "movz{bR|x|bR|x}", Gv, Eb, XX }, 01111 { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */ 01112 /* b8 */ 01113 { "(bad)", XX, XX, XX }, 01114 { "ud2b", XX, XX, XX }, 01115 { GRP8 }, 01116 { "btcS", Ev, Gv, XX }, 01117 { "bsfS", Gv, Ev, XX }, 01118 { "bsrS", Gv, Ev, XX }, 01119 { "movs{bR|x|bR|x}", Gv, Eb, XX }, 01120 { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */ 01121 /* c0 */ 01122 { "xaddB", Eb, Gb, XX }, 01123 { "xaddS", Ev, Gv, XX }, 01124 { PREGRP1 }, 01125 { "movntiS", Ev, Gv, XX }, 01126 { "pinsrw", MX, Ed, Ib }, 01127 { "pextrw", Gd, MS, Ib }, 01128 { "shufpX", XM, EX, Ib }, 01129 { GRP9 }, 01130 /* c8 */ 01131 { "bswap", RMeAX, XX, XX }, 01132 { "bswap", RMeCX, XX, XX }, 01133 { "bswap", RMeDX, XX, XX }, 01134 { "bswap", RMeBX, XX, XX }, 01135 { "bswap", RMeSP, XX, XX }, 01136 { "bswap", RMeBP, XX, XX }, 01137 { "bswap", RMeSI, XX, XX }, 01138 { "bswap", RMeDI, XX, XX }, 01139 /* d0 */ 01140 { "(bad)", XX, XX, XX }, 01141 { "psrlw", MX, EM, XX }, 01142 { "psrld", MX, EM, XX }, 01143 { "psrlq", MX, EM, XX }, 01144 { "paddq", MX, EM, XX }, 01145 { "pmullw", MX, EM, XX }, 01146 { PREGRP21 }, 01147 { "pmovmskb", Gd, MS, XX }, 01148 /* d8 */ 01149 { "psubusb", MX, EM, XX }, 01150 { "psubusw", MX, EM, XX }, 01151 { "pminub", MX, EM, XX }, 01152 { "pand", MX, EM, XX }, 01153 { "paddusb", MX, EM, XX }, 01154 { "paddusw", MX, EM, XX }, 01155 { "pmaxub", MX, EM, XX }, 01156 { "pandn", MX, EM, XX }, 01157 /* e0 */ 01158 { "pavgb", MX, EM, XX }, 01159 { "psraw", MX, EM, XX }, 01160 { "psrad", MX, EM, XX }, 01161 { "pavgw", MX, EM, XX }, 01162 { "pmulhuw", MX, EM, XX }, 01163 { "pmulhw", MX, EM, XX }, 01164 { PREGRP15 }, 01165 { PREGRP25 }, 01166 /* e8 */ 01167 { "psubsb", MX, EM, XX }, 01168 { "psubsw", MX, EM, XX }, 01169 { "pminsw", MX, EM, XX }, 01170 { "por", MX, EM, XX }, 01171 { "paddsb", MX, EM, XX }, 01172 { "paddsw", MX, EM, XX }, 01173 { "pmaxsw", MX, EM, XX }, 01174 { "pxor", MX, EM, XX }, 01175 /* f0 */ 01176 { "(bad)", XX, XX, XX }, 01177 { "psllw", MX, EM, XX }, 01178 { "pslld", MX, EM, XX }, 01179 { "psllq", MX, EM, XX }, 01180 { "pmuludq", MX, EM, XX }, 01181 { "pmaddwd", MX, EM, XX }, 01182 { "psadbw", MX, EM, XX }, 01183 { PREGRP18 }, 01184 /* f8 */ 01185 { "psubb", MX, EM, XX }, 01186 { "psubw", MX, EM, XX }, 01187 { "psubd", MX, EM, XX }, 01188 { "psubq", MX, EM, XX }, 01189 { "paddb", MX, EM, XX }, 01190 { "paddw", MX, EM, XX }, 01191 { "paddd", MX, EM, XX }, 01192 { "(bad)", XX, XX, XX } 01193 }; 01194 01195 static const unsigned char onebyte_has_modrm[256] = { 01196 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01197 /* ------------------------------- */ 01198 /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */ 01199 /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */ 01200 /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */ 01201 /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */ 01202 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ 01203 /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 01204 /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */ 01205 /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ 01206 /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */ 01207 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ 01208 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */ 01209 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */ 01210 /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */ 01211 /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */ 01212 /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */ 01213 /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */ 01214 /* ------------------------------- */ 01215 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01216 }; 01217 01218 static const unsigned char twobyte_has_modrm[256] = { 01219 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01220 /* ------------------------------- */ 01221 /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ 01222 /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */ 01223 /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ 01224 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ 01225 /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ 01226 /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ 01227 /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ 01228 /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */ 01229 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ 01230 /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ 01231 /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */ 01232 /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */ 01233 /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */ 01234 /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */ 01235 /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */ 01236 /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */ 01237 /* ------------------------------- */ 01238 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01239 }; 01240 01241 static const unsigned char twobyte_uses_SSE_prefix[256] = { 01242 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01243 /* ------------------------------- */ 01244 /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ 01245 /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ 01246 /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */ 01247 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ 01248 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ 01249 /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ 01250 /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ 01251 /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */ 01252 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ 01253 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ 01254 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ 01255 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ 01256 /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ 01257 /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ 01258 /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ 01259 /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */ 01260 /* ------------------------------- */ 01261 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 01262 }; 01263 01264 static char obuf[100]; 01265 static char *obufp; 01266 static char scratchbuf[100]; 01267 static unsigned char *start_codep; 01268 static unsigned char *insn_codep; 01269 static unsigned char *codep; 01270 static disassemble_info *the_info; 01271 static int mod; 01272 static int rm; 01273 static int reg; 01274 static unsigned char need_modrm; 01275 01276 /* If we are accessing mod/rm/reg without need_modrm set, then the 01277 values are stale. Hitting this abort likely indicates that you 01278 need to update onebyte_has_modrm or twobyte_has_modrm. */ 01279 #define MODRM_CHECK if (!need_modrm) abort () 01280 01281 static const char **names64; 01282 static const char **names32; 01283 static const char **names16; 01284 static const char **names8; 01285 static const char **names8rex; 01286 static const char **names_seg; 01287 static const char **index16; 01288 01289 static const char *intel_names64[] = { 01290 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 01291 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 01292 }; 01293 static const char *intel_names32[] = { 01294 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", 01295 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" 01296 }; 01297 static const char *intel_names16[] = { 01298 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", 01299 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" 01300 }; 01301 static const char *intel_names8[] = { 01302 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", 01303 }; 01304 static const char *intel_names8rex[] = { 01305 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 01306 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" 01307 }; 01308 static const char *intel_names_seg[] = { 01309 "es", "cs", "ss", "ds", "fs", "gs", "?", "?", 01310 }; 01311 static const char *intel_index16[] = { 01312 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" 01313 }; 01314 01315 static const char *att_names64[] = { 01316 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 01317 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 01318 }; 01319 static const char *att_names32[] = { 01320 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 01321 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" 01322 }; 01323 static const char *att_names16[] = { 01324 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 01325 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" 01326 }; 01327 static const char *att_names8[] = { 01328 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 01329 }; 01330 static const char *att_names8rex[] = { 01331 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 01332 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 01333 }; 01334 static const char *att_names_seg[] = { 01335 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", 01336 }; 01337 static const char *att_index16[] = { 01338 "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx" 01339 }; 01340 01341 static const struct dis386 grps[][8] = { 01342 /* GRP1b */ 01343 { 01344 { "addA", Eb, Ib, XX }, 01345 { "orA", Eb, Ib, XX }, 01346 { "adcA", Eb, Ib, XX }, 01347 { "sbbA", Eb, Ib, XX }, 01348 { "andA", Eb, Ib, XX }, 01349 { "subA", Eb, Ib, XX }, 01350 { "xorA", Eb, Ib, XX }, 01351 { "cmpA", Eb, Ib, XX } 01352 }, 01353 /* GRP1S */ 01354 { 01355 { "addQ", Ev, Iv, XX }, 01356 { "orQ", Ev, Iv, XX }, 01357 { "adcQ", Ev, Iv, XX }, 01358 { "sbbQ", Ev, Iv, XX }, 01359 { "andQ", Ev, Iv, XX }, 01360 { "subQ", Ev, Iv, XX }, 01361 { "xorQ", Ev, Iv, XX }, 01362 { "cmpQ", Ev, Iv, XX } 01363 }, 01364 /* GRP1Ss */ 01365 { 01366 { "addQ", Ev, sIb, XX }, 01367 { "orQ", Ev, sIb, XX }, 01368 { "adcQ", Ev, sIb, XX }, 01369 { "sbbQ", Ev, sIb, XX }, 01370 { "andQ", Ev, sIb, XX }, 01371 { "subQ", Ev, sIb, XX }, 01372 { "xorQ", Ev, sIb, XX }, 01373 { "cmpQ", Ev, sIb, XX } 01374 }, 01375 /* GRP2b */ 01376 { 01377 { "rolA", Eb, Ib, XX }, 01378 { "rorA", Eb, Ib, XX }, 01379 { "rclA", Eb, Ib, XX }, 01380 { "rcrA", Eb, Ib, XX }, 01381 { "shlA", Eb, Ib, XX }, 01382 { "shrA", Eb, Ib, XX }, 01383 { "(bad)", XX, XX, XX }, 01384 { "sarA", Eb, Ib, XX }, 01385 }, 01386 /* GRP2S */ 01387 { 01388 { "rolQ", Ev, Ib, XX }, 01389 { "rorQ", Ev, Ib, XX }, 01390 { "rclQ", Ev, Ib, XX }, 01391 { "rcrQ", Ev, Ib, XX }, 01392 { "shlQ", Ev, Ib, XX }, 01393 { "shrQ", Ev, Ib, XX }, 01394 { "(bad)", XX, XX, XX }, 01395 { "sarQ", Ev, Ib, XX }, 01396 }, 01397 /* GRP2b_one */ 01398 { 01399 { "rolA", Eb, XX, XX }, 01400 { "rorA", Eb, XX, XX }, 01401 { "rclA", Eb, XX, XX }, 01402 { "rcrA", Eb, XX, XX }, 01403 { "shlA", Eb, XX, XX }, 01404 { "shrA", Eb, XX, XX }, 01405 { "(bad)", XX, XX, XX }, 01406 { "sarA", Eb, XX, XX }, 01407 }, 01408 /* GRP2S_one */ 01409 { 01410 { "rolQ", Ev, XX, XX }, 01411 { "rorQ", Ev, XX, XX }, 01412 { "rclQ", Ev, XX, XX }, 01413 { "rcrQ", Ev, XX, XX }, 01414 { "shlQ", Ev, XX, XX }, 01415 { "shrQ", Ev, XX, XX }, 01416 { "(bad)", XX, XX, XX}, 01417 { "sarQ", Ev, XX, XX }, 01418 }, 01419 /* GRP2b_cl */ 01420 { 01421 { "rolA", Eb, CL, XX }, 01422 { "rorA", Eb, CL, XX }, 01423 { "rclA", Eb, CL, XX }, 01424 { "rcrA", Eb, CL, XX }, 01425 { "shlA", Eb, CL, XX }, 01426 { "shrA", Eb, CL, XX }, 01427 { "(bad)", XX, XX, XX }, 01428 { "sarA", Eb, CL, XX }, 01429 }, 01430 /* GRP2S_cl */ 01431 { 01432 { "rolQ", Ev, CL, XX }, 01433 { "rorQ", Ev, CL, XX }, 01434 { "rclQ", Ev, CL, XX }, 01435 { "rcrQ", Ev, CL, XX }, 01436 { "shlQ", Ev, CL, XX }, 01437 { "shrQ", Ev, CL, XX }, 01438 { "(bad)", XX, XX, XX }, 01439 { "sarQ", Ev, CL, XX } 01440 }, 01441 /* GRP3b */ 01442 { 01443 { "testA", Eb, Ib, XX }, 01444 { "(bad)", Eb, XX, XX }, 01445 { "notA", Eb, XX, XX }, 01446 { "negA", Eb, XX, XX }, 01447 { "mulA", Eb, XX, XX }, /* Don't print the implicit %al register, */ 01448 { "imulA", Eb, XX, XX }, /* to distinguish these opcodes from other */ 01449 { "divA", Eb, XX, XX }, /* mul/imul opcodes. Do the same for div */ 01450 { "idivA", Eb, XX, XX } /* and idiv for consistency. */ 01451 }, 01452 /* GRP3S */ 01453 { 01454 { "testQ", Ev, Iv, XX }, 01455 { "(bad)", XX, XX, XX }, 01456 { "notQ", Ev, XX, XX }, 01457 { "negQ", Ev, XX, XX }, 01458 { "mulQ", Ev, XX, XX }, /* Don't print the implicit register. */ 01459 { "imulQ", Ev, XX, XX }, 01460 { "divQ", Ev, XX, XX }, 01461 { "idivQ", Ev, XX, XX }, 01462 }, 01463 /* GRP4 */ 01464 { 01465 { "incA", Eb, XX, XX }, 01466 { "decA", Eb, XX, XX }, 01467 { "(bad)", XX, XX, XX }, 01468 { "(bad)", XX, XX, XX }, 01469 { "(bad)", XX, XX, XX }, 01470 { "(bad)", XX, XX, XX }, 01471 { "(bad)", XX, XX, XX }, 01472 { "(bad)", XX, XX, XX }, 01473 }, 01474 /* GRP5 */ 01475 { 01476 { "incQ", Ev, XX, XX }, 01477 { "decQ", Ev, XX, XX }, 01478 { "callT", indirEv, XX, XX }, 01479 { "lcallT", indirEv, XX, XX }, 01480 { "jmpT", indirEv, XX, XX }, 01481 { "ljmpT", indirEv, XX, XX }, 01482 { "pushU", Ev, XX, XX }, 01483 { "(bad)", XX, XX, XX }, 01484 }, 01485 /* GRP6 */ 01486 { 01487 { "sldtQ", Ev, XX, XX }, 01488 { "strQ", Ev, XX, XX }, 01489 { "lldt", Ew, XX, XX }, 01490 { "ltr", Ew, XX, XX }, 01491 { "verr", Ew, XX, XX }, 01492 { "verw", Ew, XX, XX }, 01493 { "(bad)", XX, XX, XX }, 01494 { "(bad)", XX, XX, XX } 01495 }, 01496 /* GRP7 */ 01497 { 01498 { "sgdtQ", M, XX, XX }, 01499 { "sidtQ", M, XX, XX }, 01500 { "lgdtQ", M, XX, XX }, 01501 { "lidtQ", M, XX, XX }, 01502 { "smswQ", Ev, XX, XX }, 01503 { "(bad)", XX, XX, XX }, 01504 { "lmsw", Ew, XX, XX }, 01505 { "invlpg", Ew, XX, XX }, 01506 }, 01507 /* GRP8 */ 01508 { 01509 { "(bad)", XX, XX, XX }, 01510 { "(bad)", XX, XX, XX }, 01511 { "(bad)", XX, XX, XX }, 01512 { "(bad)", XX, XX, XX }, 01513 { "btQ", Ev, Ib, XX }, 01514 { "btsQ", Ev, Ib, XX }, 01515 { "btrQ", Ev, Ib, XX }, 01516 { "btcQ", Ev, Ib, XX }, 01517 }, 01518 /* GRP9 */ 01519 { 01520 { "(bad)", XX, XX, XX }, 01521 { "cmpxchg8b", Ev, XX, XX }, 01522 { "(bad)", XX, XX, XX }, 01523 { "(bad)", XX, XX, XX }, 01524 { "(bad)", XX, XX, XX }, 01525 { "(bad)", XX, XX, XX }, 01526 { "(bad)", XX, XX, XX }, 01527 { "(bad)", XX, XX, XX }, 01528 }, 01529 /* GRP10 */ 01530 { 01531 { "(bad)", XX, XX, XX }, 01532 { "(bad)", XX, XX, XX }, 01533 { "psrlw", MS, Ib, XX }, 01534 { "(bad)", XX, XX, XX }, 01535 { "psraw", MS, Ib, XX }, 01536 { "(bad)", XX, XX, XX }, 01537 { "psllw", MS, Ib, XX }, 01538 { "(bad)", XX, XX, XX }, 01539 }, 01540 /* GRP11 */ 01541 { 01542 { "(bad)", XX, XX, XX }, 01543 { "(bad)", XX, XX, XX }, 01544 { "psrld", MS, Ib, XX }, 01545 { "(bad)", XX, XX, XX }, 01546 { "psrad", MS, Ib, XX }, 01547 { "(bad)", XX, XX, XX }, 01548 { "pslld", MS, Ib, XX }, 01549 { "(bad)", XX, XX, XX }, 01550 }, 01551 /* GRP12 */ 01552 { 01553 { "(bad)", XX, XX, XX }, 01554 { "(bad)", XX, XX, XX }, 01555 { "psrlq", MS, Ib, XX }, 01556 { "psrldq", MS, Ib, XX }, 01557 { "(bad)", XX, XX, XX }, 01558 { "(bad)", XX, XX, XX }, 01559 { "psllq", MS, Ib, XX }, 01560 { "pslldq", MS, Ib, XX }, 01561 }, 01562 /* GRP13 */ 01563 { 01564 { "fxsave", Ev, XX, XX }, 01565 { "fxrstor", Ev, XX, XX }, 01566 { "ldmxcsr", Ev, XX, XX }, 01567 { "stmxcsr", Ev, XX, XX }, 01568 { "(bad)", XX, XX, XX }, 01569 { "lfence", None, XX, XX }, 01570 { "mfence", None, XX, XX }, 01571 { "sfence", None, XX, XX }, 01572 /* FIXME: the sfence with memory operand is clflush! */ 01573 }, 01574 /* GRP14 */ 01575 { 01576 { "prefetchnta", Ev, XX, XX }, 01577 { "prefetcht0", Ev, XX, XX }, 01578 { "prefetcht1", Ev, XX, XX }, 01579 { "prefetcht2", Ev, XX, XX }, 01580 { "(bad)", XX, XX, XX }, 01581 { "(bad)", XX, XX, XX }, 01582 { "(bad)", XX, XX, XX }, 01583 { "(bad)", XX, XX, XX }, 01584 }, 01585 /* GRPAMD */ 01586 { 01587 { "prefetch", Eb, XX, XX }, 01588 { "prefetchw", Eb, XX, XX }, 01589 { "(bad)", XX, XX, XX }, 01590 { "(bad)", XX, XX, XX }, 01591 { "(bad)", XX, XX, XX }, 01592 { "(bad)", XX, XX, XX }, 01593 { "(bad)", XX, XX, XX }, 01594 { "(bad)", XX, XX, XX }, 01595 } 01596 }; 01597 01598 static const struct dis386 prefix_user_table[][4] = { 01599 /* PREGRP0 */ 01600 { 01601 { "addps", XM, EX, XX }, 01602 { "addss", XM, EX, XX }, 01603 { "addpd", XM, EX, XX }, 01604 { "addsd", XM, EX, XX }, 01605 }, 01606 /* PREGRP1 */ 01607 { 01608 { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX. */ 01609 { "", XM, EX, OPSIMD }, 01610 { "", XM, EX, OPSIMD }, 01611 { "", XM, EX, OPSIMD }, 01612 }, 01613 /* PREGRP2 */ 01614 { 01615 { "cvtpi2ps", XM, EM, XX }, 01616 { "cvtsi2ssY", XM, Ev, XX }, 01617 { "cvtpi2pd", XM, EM, XX }, 01618 { "cvtsi2sdY", XM, Ev, XX }, 01619 }, 01620 /* PREGRP3 */ 01621 { 01622 { "cvtps2pi", MX, EX, XX }, 01623 { "cvtss2siY", Gv, EX, XX }, 01624 { "cvtpd2pi", MX, EX, XX }, 01625 { "cvtsd2siY", Gv, EX, XX }, 01626 }, 01627 /* PREGRP4 */ 01628 { 01629 { "cvttps2pi", MX, EX, XX }, 01630 { "cvttss2siY", Gv, EX, XX }, 01631 { "cvttpd2pi", MX, EX, XX }, 01632 { "cvttsd2siY", Gv, EX, XX }, 01633 }, 01634 /* PREGRP5 */ 01635 { 01636 { "divps", XM, EX, XX }, 01637 { "divss", XM, EX, XX }, 01638 { "divpd", XM, EX, XX }, 01639 { "divsd", XM, EX, XX }, 01640 }, 01641 /* PREGRP6 */ 01642 { 01643 { "maxps", XM, EX, XX }, 01644 { "maxss", XM, EX, XX }, 01645 { "maxpd", XM, EX, XX }, 01646 { "maxsd", XM, EX, XX }, 01647 }, 01648 /* PREGRP7 */ 01649 { 01650 { "minps", XM, EX, XX }, 01651 { "minss", XM, EX, XX }, 01652 { "minpd", XM, EX, XX }, 01653 { "minsd", XM, EX, XX }, 01654 }, 01655 /* PREGRP8 */ 01656 { 01657 { "movups", XM, EX, XX }, 01658 { "movss", XM, EX, XX }, 01659 { "movupd", XM, EX, XX }, 01660 { "movsd", XM, EX, XX }, 01661 }, 01662 /* PREGRP9 */ 01663 { 01664 { "movups", EX, XM, XX }, 01665 { "movss", EX, XM, XX }, 01666 { "movupd", EX, XM, XX }, 01667 { "movsd", EX, XM, XX }, 01668 }, 01669 /* PREGRP10 */ 01670 { 01671 { "mulps", XM, EX, XX }, 01672 { "mulss", XM, EX, XX }, 01673 { "mulpd", XM, EX, XX }, 01674 { "mulsd", XM, EX, XX }, 01675 }, 01676 /* PREGRP11 */ 01677 { 01678 { "rcpps", XM, EX, XX }, 01679 { "rcpss", XM, EX, XX }, 01680 { "(bad)", XM, EX, XX }, 01681 { "(bad)", XM, EX, XX }, 01682 }, 01683 /* PREGRP12 */ 01684 { 01685 { "rsqrtps", XM, EX, XX }, 01686 { "rsqrtss", XM, EX, XX }, 01687 { "(bad)", XM, EX, XX }, 01688 { "(bad)", XM, EX, XX }, 01689 }, 01690 /* PREGRP13 */ 01691 { 01692 { "sqrtps", XM, EX, XX }, 01693 { "sqrtss", XM, EX, XX }, 01694 { "sqrtpd", XM, EX, XX }, 01695 { "sqrtsd", XM, EX, XX }, 01696 }, 01697 /* PREGRP14 */ 01698 { 01699 { "subps", XM, EX, XX }, 01700 { "subss", XM, EX, XX }, 01701 { "subpd", XM, EX, XX }, 01702 { "subsd", XM, EX, XX }, 01703 }, 01704 /* PREGRP15 */ 01705 { 01706 { "(bad)", XM, EX, XX }, 01707 { "cvtdq2pd", XM, EX, XX }, 01708 { "cvttpd2dq", XM, EX, XX }, 01709 { "cvtpd2dq", XM, EX, XX }, 01710 }, 01711 /* PREGRP16 */ 01712 { 01713 { "cvtdq2ps", XM, EX, XX }, 01714 { "cvttps2dq",XM, EX, XX }, 01715 { "cvtps2dq",XM, EX, XX }, 01716 { "(bad)", XM, EX, XX }, 01717 }, 01718 /* PREGRP17 */ 01719 { 01720 { "cvtps2pd", XM, EX, XX }, 01721 { "cvtss2sd", XM, EX, XX }, 01722 { "cvtpd2ps", XM, EX, XX }, 01723 { "cvtsd2ss", XM, EX, XX }, 01724 }, 01725 /* PREGRP18 */ 01726 { 01727 { "maskmovq", MX, MS, XX }, 01728 { "(bad)", XM, EX, XX }, 01729 { "maskmovdqu", XM, EX, XX }, 01730 { "(bad)", XM, EX, XX }, 01731 }, 01732 /* PREGRP19 */ 01733 { 01734 { "movq", MX, EM, XX }, 01735 { "movdqu", XM, EX, XX }, 01736 { "movdqa", XM, EX, XX }, 01737 { "(bad)", XM, EX, XX }, 01738 }, 01739 /* PREGRP20 */ 01740 { 01741 { "movq", EM, MX, XX }, 01742 { "movdqu", EX, XM, XX }, 01743 { "movdqa", EX, XM, XX }, 01744 { "(bad)", EX, XM, XX }, 01745 }, 01746 /* PREGRP21 */ 01747 { 01748 { "(bad)", EX, XM, XX }, 01749 { "movq2dq", XM, MS, XX }, 01750 { "movq", EX, XM, XX }, 01751 { "movdq2q", MX, XS, XX }, 01752 }, 01753 /* PREGRP22 */ 01754 { 01755 { "pshufw", MX, EM, Ib }, 01756 { "pshufhw", XM, EX, Ib }, 01757 { "pshufd", XM, EX, Ib }, 01758 { "pshuflw", XM, EX, Ib }, 01759 }, 01760 /* PREGRP23 */ 01761 { 01762 { "movd", Ed, MX, XX }, 01763 { "movq", XM, EX, XX }, 01764 { "movd", Ed, XM, XX }, 01765 { "(bad)", Ed, XM, XX }, 01766 }, 01767 /* PREGRP24 */ 01768 { 01769 { "(bad)", MX, EX, XX }, 01770 { "(bad)", XM, EX, XX }, 01771 { "punpckhqdq", XM, EX, XX }, 01772 { "(bad)", XM, EX, XX }, 01773 }, 01774 /* PREGRP25 */ 01775 { 01776 { "movntq", Ev, MX, XX }, 01777 { "(bad)", Ev, XM, XX }, 01778 { "movntdq", Ev, XM, XX }, 01779 { "(bad)", Ev, XM, XX }, 01780 }, 01781 /* PREGRP26 */ 01782 { 01783 { "(bad)", MX, EX, XX }, 01784 { "(bad)", XM, EX, XX }, 01785 { "punpcklqdq", XM, EX, XX }, 01786 { "(bad)", XM, EX, XX }, 01787 }, 01788 }; 01789 01790 static const struct dis386 x86_64_table[][2] = { 01791 { 01792 { "arpl", Ew, Gw, XX }, 01793 { "movs{||lq|xd}", Gv, Ed, XX }, 01794 }, 01795 }; 01796 01797 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>") 01798 01799 static void 01800 ckprefix () 01801 { 01802 int newrex; 01803 rex = 0; 01804 prefixes = 0; 01805 used_prefixes = 0; 01806 rex_used = 0; 01807 while (1) 01808 { 01809 FETCH_DATA (the_info, codep + 1); 01810 newrex = 0; 01811 switch (*codep) 01812 { 01813 /* REX prefixes family. */ 01814 case 0x40: 01815 case 0x41: 01816 case 0x42: 01817 case 0x43: 01818 case 0x44: 01819 case 0x45: 01820 case 0x46: 01821 case 0x47: 01822 case 0x48: 01823 case 0x49: 01824 case 0x4a: 01825 case 0x4b: 01826 case 0x4c: 01827 case 0x4d: 01828 case 0x4e: 01829 case 0x4f: 01830 if (mode_64bit) 01831 newrex = *codep; 01832 else 01833 return; 01834 break; 01835 case 0xf3: 01836 prefixes |= PREFIX_REPZ; 01837 break; 01838 case 0xf2: 01839 prefixes |= PREFIX_REPNZ; 01840 break; 01841 case 0xf0: 01842 prefixes |= PREFIX_LOCK; 01843 break; 01844 case 0x2e: 01845 prefixes |= PREFIX_CS; 01846 break; 01847 case 0x36: 01848 prefixes |= PREFIX_SS; 01849 break; 01850 case 0x3e: 01851 prefixes |= PREFIX_DS; 01852 break; 01853 case 0x26: 01854 prefixes |= PREFIX_ES; 01855 break; 01856 case 0x64: 01857 prefixes |= PREFIX_FS; 01858 break; 01859 case 0x65: 01860 prefixes |= PREFIX_GS; 01861 break; 01862 case 0x66: 01863 prefixes |= PREFIX_DATA; 01864 break; 01865 case 0x67: 01866 prefixes |= PREFIX_ADDR; 01867 break; 01868 case FWAIT_OPCODE: 01869 /* fwait is really an instruction. If there are prefixes 01870 before the fwait, they belong to the fwait, *not* to the 01871 following instruction. */ 01872 if (prefixes) 01873 { 01874 prefixes |= PREFIX_FWAIT; 01875 codep++; 01876 return; 01877 } 01878 prefixes = PREFIX_FWAIT; 01879 break; 01880 default: 01881 return; 01882 } 01883 /* Rex is ignored when followed by another prefix. */ 01884 if (rex) 01885 { 01886 oappend (prefix_name (rex, 0)); 01887 oappend (" "); 01888 } 01889 rex = newrex; 01890 codep++; 01891 } 01892 } 01893 01894 /* Return the name of the prefix byte PREF, or NULL if PREF is not a 01895 prefix byte. */ 01896 01897 static const char * 01898 prefix_name (pref, sizeflag) 01899 int pref; 01900 int sizeflag; 01901 { 01902 switch (pref) 01903 { 01904 /* REX prefixes family. */ 01905 case 0x40: 01906 return "rex"; 01907 case 0x41: 01908 return "rexZ"; 01909 case 0x42: 01910 return "rexY"; 01911 case 0x43: 01912 return "rexYZ"; 01913 case 0x44: 01914 return "rexX"; 01915 case 0x45: 01916 return "rexXZ"; 01917 case 0x46: 01918 return "rexXY"; 01919 case 0x47: 01920 return "rexXYZ"; 01921 case 0x48: 01922 return "rex64"; 01923 case 0x49: 01924 return "rex64Z"; 01925 case 0x4a: 01926 return "rex64Y"; 01927 case 0x4b: 01928 return "rex64YZ"; 01929 case 0x4c: 01930 return "rex64X"; 01931 case 0x4d: 01932 return "rex64XZ"; 01933 case 0x4e: 01934 return "rex64XY"; 01935 case 0x4f: 01936 return "rex64XYZ"; 01937 case 0xf3: 01938 return "repz"; 01939 case 0xf2: 01940 return "repnz"; 01941 case 0xf0: 01942 return "lock"; 01943 case 0x2e: 01944 return "cs"; 01945 case 0x36: 01946 return "ss"; 01947 case 0x3e: 01948 return "ds"; 01949 case 0x26: 01950 return "es"; 01951 case 0x64: 01952 return "fs"; 01953 case 0x65: 01954 return "gs"; 01955 case 0x66: 01956 return (sizeflag & DFLAG) ? "data16" : "data32"; 01957 case 0x67: 01958 if (mode_64bit) 01959 return (sizeflag & AFLAG) ? "addr32" : "addr64"; 01960 else 01961 return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32"; 01962 case FWAIT_OPCODE: 01963 return "fwait"; 01964 default: 01965 return NULL; 01966 } 01967 } 01968 01969 static char op1out[100], op2out[100], op3out[100]; 01970 static int op_ad, op_index[3]; 01971 static bfd_vma op_address[3]; 01972 static bfd_vma op_riprel[3]; 01973 static bfd_vma start_pc; 01974 01975 /* 01976 * On the 386's of 1988, the maximum length of an instruction is 15 bytes. 01977 * (see topic "Redundant prefixes" in the "Differences from 8086" 01978 * section of the "Virtual 8086 Mode" chapter.) 01979 * 'pc' should be the address of this instruction, it will 01980 * be used to print the target address if this is a relative jump or call 01981 * The function returns the length of this instruction in bytes. 01982 */ 01983 01984 static char intel_syntax; 01985 static char open_char; 01986 static char close_char; 01987 static char separator_char; 01988 static char scale_char; 01989 01990 /* Here for backwards compatibility. When gdb stops using 01991 print_insn_i386_att and print_insn_i386_intel these functions can 01992 disappear, and print_insn_i386 be merged into print_insn. */ 01993 int 01994 print_insn_i386_att (pc, info) 01995 bfd_vma pc; 01996 disassemble_info *info; 01997 { 01998 intel_syntax = 0; 01999 02000 return print_insn (pc, info); 02001 } 02002 02003 int 02004 print_insn_i386_intel (pc, info) 02005 bfd_vma pc; 02006 disassemble_info *info; 02007 { 02008 intel_syntax = 1; 02009 02010 return print_insn (pc, info); 02011 } 02012 02013 int 02014 print_insn_i386 (pc, info) 02015 bfd_vma pc; 02016 disassemble_info *info; 02017 { 02018 intel_syntax = -1; 02019 02020 return print_insn (pc, info); 02021 } 02022 02023 static int 02024 print_insn (pc, info) 02025 bfd_vma pc; 02026 disassemble_info *info; 02027 { 02028 const struct dis386 *dp; 02029 int i; 02030 int two_source_ops; 02031 char *first, *second, *third; 02032 int needcomma; 02033 unsigned char uses_SSE_prefix; 02034 int sizeflag; 02035 /*const char *p;*/ 02036 struct dis_private priv; 02037 02038 mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax 02039 || info->mach == bfd_mach_x86_64); 02040 02041 if (intel_syntax == -1) 02042 intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax 02043 || info->mach == bfd_mach_x86_64_intel_syntax); 02044 02045 if (info->mach == bfd_mach_i386_i386 02046 || info->mach == bfd_mach_x86_64 02047 || info->mach == bfd_mach_i386_i386_intel_syntax 02048 || info->mach == bfd_mach_x86_64_intel_syntax) 02049 priv.orig_sizeflag = AFLAG | DFLAG; 02050 else if (info->mach == bfd_mach_i386_i8086) 02051 priv.orig_sizeflag = 0; 02052 else 02053 abort (); 02054 02055 #if 0 02056 for (p = info->disassembler_options; p != NULL; ) 02057 { 02058 if (strncmp (p, "x86-64", 6) == 0) 02059 { 02060 mode_64bit = 1; 02061 priv.orig_sizeflag = AFLAG | DFLAG; 02062 } 02063 else if (strncmp (p, "i386", 4) == 0) 02064 { 02065 mode_64bit = 0; 02066 priv.orig_sizeflag = AFLAG | DFLAG; 02067 } 02068 else if (strncmp (p, "i8086", 5) == 0) 02069 { 02070 mode_64bit = 0; 02071 priv.orig_sizeflag = 0; 02072 } 02073 else if (strncmp (p, "intel", 5) == 0) 02074 { 02075 intel_syntax = 1; 02076 } 02077 else if (strncmp (p, "att", 3) == 0) 02078 { 02079 intel_syntax = 0; 02080 } 02081 else if (strncmp (p, "addr", 4) == 0) 02082 { 02083 if (p[4] == '1' && p[5] == '6') 02084 priv.orig_sizeflag &= ~AFLAG; 02085 else if (p[4] == '3' && p[5] == '2') 02086 priv.orig_sizeflag |= AFLAG; 02087 } 02088 else if (strncmp (p, "data", 4) == 0) 02089 { 02090 if (p[4] == '1' && p[5] == '6') 02091 priv.orig_sizeflag &= ~DFLAG; 02092 else if (p[4] == '3' && p[5] == '2') 02093 priv.orig_sizeflag |= DFLAG; 02094 } 02095 else if (strncmp (p, "suffix", 6) == 0) 02096 priv.orig_sizeflag |= SUFFIX_ALWAYS; 02097 02098 p = strchr (p, ','); 02099 if (p != NULL) 02100 p++; 02101 } 02102 #else 02103 mode_64bit = 0; 02104 priv.orig_sizeflag = AFLAG | DFLAG; 02105 /*intel_syntax = 0;*/ 02106 #endif 02107 02108 if (intel_syntax) 02109 { 02110 names64 = intel_names64; 02111 names32 = intel_names32; 02112 names16 = intel_names16; 02113 names8 = intel_names8; 02114 names8rex = intel_names8rex; 02115 names_seg = intel_names_seg; 02116 index16 = intel_index16; 02117 open_char = '['; 02118 close_char = ']'; 02119 separator_char = '+'; 02120 scale_char = '*'; 02121 } 02122 else 02123 { 02124 names64 = att_names64; 02125 names32 = att_names32; 02126 names16 = att_names16; 02127 names8 = att_names8; 02128 names8rex = att_names8rex; 02129 names_seg = att_names_seg; 02130 index16 = att_index16; 02131 open_char = '('; 02132 close_char = ')'; 02133 separator_char = ','; 02134 scale_char = ','; 02135 } 02136 02137 /* The output looks better if we put 7 bytes on a line, since that 02138 puts most long word instructions on a single line. */ 02139 info->bytes_per_line = 7; 02140 02141 info->private_data = (PTR) &priv; 02142 priv.max_fetched = priv.the_buffer; 02143 priv.insn_start = pc; 02144 02145 obuf[0] = 0; 02146 op1out[0] = 0; 02147 op2out[0] = 0; 02148 op3out[0] = 0; 02149 02150 op_index[0] = op_index[1] = op_index[2] = -1; 02151 02152 the_info = info; 02153 start_pc = pc; 02154 start_codep = priv.the_buffer; 02155 codep = priv.the_buffer; 02156 02157 if (_setjmp (priv.bailout) != 0) 02158 { 02159 const char *name; 02160 02161 /* Getting here means we tried for data but didn't get it. That 02162 means we have an incomplete instruction of some sort. Just 02163 print the first byte as a prefix or a .byte pseudo-op. */ 02164 if (codep > priv.the_buffer) 02165 { 02166 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); 02167 if (name != NULL) 02168 (*info->fprintf_func) (info->stream, "%s", name); 02169 else 02170 { 02171 /* Just print the first byte as a .byte instruction. */ 02172 (*info->fprintf_func) (info->stream, ".byte 0x%x", 02173 (unsigned int) priv.the_buffer[0]); 02174 } 02175 02176 return 1; 02177 } 02178 02179 return -1; 02180 } 02181 02182 obufp = obuf; 02183 ckprefix (); 02184 02185 insn_codep = codep; 02186 sizeflag = priv.orig_sizeflag; 02187 02188 FETCH_DATA (info, codep + 1); 02189 two_source_ops = (*codep == 0x62) || (*codep == 0xc8); 02190 02191 if ((prefixes & PREFIX_FWAIT) 02192 && ((*codep < 0xd8) || (*codep > 0xdf))) 02193 { 02194 const char *name; 02195 02196 /* fwait not followed by floating point instruction. Print the 02197 first prefix, which is probably fwait itself. */ 02198 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); 02199 if (name == NULL) 02200 name = INTERNAL_DISASSEMBLER_ERROR; 02201 (*info->fprintf_func) (info->stream, "%s", name); 02202 return 1; 02203 } 02204 02205 if (*codep == 0x0f) 02206 { 02207 FETCH_DATA (info, codep + 2); 02208 dp = &dis386_twobyte[*++codep]; 02209 need_modrm = twobyte_has_modrm[*codep]; 02210 uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep]; 02211 } 02212 else 02213 { 02214 dp = &dis386[*codep]; 02215 need_modrm = onebyte_has_modrm[*codep]; 02216 uses_SSE_prefix = 0; 02217 } 02218 codep++; 02219 02220 if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ)) 02221 { 02222 oappend ("repz "); 02223 used_prefixes |= PREFIX_REPZ; 02224 } 02225 if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ)) 02226 { 02227 oappend ("repnz "); 02228 used_prefixes |= PREFIX_REPNZ; 02229 } 02230 if (prefixes & PREFIX_LOCK) 02231 { 02232 oappend ("lock "); 02233 used_prefixes |= PREFIX_LOCK; 02234 } 02235 02236 if (prefixes & PREFIX_ADDR) 02237 { 02238 sizeflag ^= AFLAG; 02239 if (dp->bytemode3 != loop_jcxz_mode || intel_syntax) 02240 { 02241 if ((sizeflag & AFLAG) || mode_64bit) 02242 oappend ("addr32 "); 02243 else 02244 oappend ("addr16 "); 02245 used_prefixes |= PREFIX_ADDR; 02246 } 02247 } 02248 02249 if (!uses_SSE_prefix && (prefixes & PREFIX_DATA)) 02250 { 02251 sizeflag ^= DFLAG; 02252 if (dp->bytemode3 == cond_jump_mode 02253 && dp->bytemode1 == v_mode 02254 && !intel_syntax) 02255 { 02256 if (sizeflag & DFLAG) 02257 oappend ("data32 "); 02258 else 02259 oappend ("data16 "); 02260 used_prefixes |= PREFIX_DATA; 02261 } 02262 } 02263 02264 if (need_modrm) 02265 { 02266 FETCH_DATA (info, codep + 1); 02267 mod = (*codep >> 6) & 3; 02268 reg = (*codep >> 3) & 7; 02269 rm = *codep & 7; 02270 } 02271 02272 if (dp->name == NULL && dp->bytemode1 == FLOATCODE) 02273 { 02274 dofloat (sizeflag); 02275 } 02276 else 02277 { 02278 int index; 02279 if (dp->name == NULL) 02280 { 02281 switch (dp->bytemode1) 02282 { 02283 case USE_GROUPS: 02284 dp = &grps[dp->bytemode2][reg]; 02285 break; 02286 02287 case USE_PREFIX_USER_TABLE: 02288 index = 0; 02289 used_prefixes |= (prefixes & PREFIX_REPZ); 02290 if (prefixes & PREFIX_REPZ) 02291 index = 1; 02292 else 02293 { 02294 used_prefixes |= (prefixes & PREFIX_DATA); 02295 if (prefixes & PREFIX_DATA) 02296 index = 2; 02297 else 02298 { 02299 used_prefixes |= (prefixes & PREFIX_REPNZ); 02300 if (prefixes & PREFIX_REPNZ) 02301 index = 3; 02302 } 02303 } 02304 dp = &prefix_user_table[dp->bytemode2][index]; 02305 break; 02306 02307 case X86_64_SPECIAL: 02308 dp = &x86_64_table[dp->bytemode2][mode_64bit]; 02309 break; 02310 02311 default: 02312 oappend (INTERNAL_DISASSEMBLER_ERROR); 02313 break; 02314 } 02315 } 02316 02317 if (putop (dp->name, sizeflag) == 0) 02318 { 02319 obufp = op1out; 02320 op_ad = 2; 02321 if (dp->op1) 02322 (*dp->op1) (dp->bytemode1, sizeflag); 02323 02324 obufp = op2out; 02325 op_ad = 1; 02326 if (dp->op2) 02327 (*dp->op2) (dp->bytemode2, sizeflag); 02328 02329 obufp = op3out; 02330 op_ad = 0; 02331 if (dp->op3) 02332 (*dp->op3) (dp->bytemode3, sizeflag); 02333 } 02334 } 02335 02336 /* See if any prefixes were not used. If so, print the first one 02337 separately. If we don't do this, we'll wind up printing an 02338 instruction stream which does not precisely correspond to the 02339 bytes we are disassembling. */ 02340 if ((prefixes & ~used_prefixes) != 0) 02341 { 02342 const char *name; 02343 02344 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); 02345 if (name == NULL) 02346 name = INTERNAL_DISASSEMBLER_ERROR; 02347 (*info->fprintf_func) (info->stream, "%s", name); 02348 return 1; 02349 } 02350 if (rex & ~rex_used) 02351 { 02352 const char *name; 02353 name = prefix_name (rex | 0x40, priv.orig_sizeflag); 02354 if (name == NULL) 02355 name = INTERNAL_DISASSEMBLER_ERROR; 02356 (*info->fprintf_func) (info->stream, "%s ", name); 02357 } 02358 02359 obufp = obuf + strlen (obuf); 02360 for (i = strlen (obuf); i < 6; i++) 02361 oappend (" "); 02362 oappend (" "); 02363 (*info->fprintf_func) (info->stream, "%s", obuf); 02364 02365 /* The enter and bound instructions are printed with operands in the same 02366 order as the intel book; everything else is printed in reverse order. */ 02367 if (intel_syntax || two_source_ops) 02368 { 02369 first = op1out; 02370 second = op2out; 02371 third = op3out; 02372 op_ad = op_index[0]; 02373 op_index[0] = op_index[2]; 02374 op_index[2] = op_ad; 02375 } 02376 else 02377 { 02378 first = op3out; 02379 second = op2out; 02380 third = op1out; 02381 } 02382 needcomma = 0; 02383 if (*first) 02384 { 02385 if (op_index[0] != -1 && !op_riprel[0]) 02386 (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info); 02387 else 02388 (*info->fprintf_func) (info->stream, "%s", first); 02389 needcomma = 1; 02390 } 02391 if (*second) 02392 { 02393 if (needcomma) 02394 (*info->fprintf_func) (info->stream, ","); 02395 if (op_index[1] != -1 && !op_riprel[1]) 02396 (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info); 02397 else 02398 (*info->fprintf_func) (info->stream, "%s", second); 02399 needcomma = 1; 02400 } 02401 if (*third) 02402 { 02403 if (needcomma) 02404 (*info->fprintf_func) (info->stream, ","); 02405 if (op_index[2] != -1 && !op_riprel[2]) 02406 (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info); 02407 else 02408 (*info->fprintf_func) (info->stream, "%s", third); 02409 } 02410 for (i = 0; i < 3; i++) 02411 if (op_index[i] != -1 && op_riprel[i]) 02412 { 02413 (*info->fprintf_func) (info->stream, " # "); 02414 (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep 02415 + op_address[op_index[i]]), info); 02416 } 02417 return codep - priv.the_buffer; 02418 } 02419 02420 static const char *float_mem[] = { 02421 /* d8 */ 02422 "fadd{s||s|}", 02423 "fmul{s||s|}", 02424 "fcom{s||s|}", 02425 "fcomp{s||s|}", 02426 "fsub{s||s|}", 02427 "fsubr{s||s|}", 02428 "fdiv{s||s|}", 02429 "fdivr{s||s|}", 02430 /* d9 */ 02431 "fld{s||s|}", 02432 "(bad)", 02433 "fst{s||s|}", 02434 "fstp{s||s|}", 02435 "fldenv", 02436 "fldcw", 02437 "fNstenv", 02438 "fNstcw", 02439 /* da */ 02440 "fiadd{l||l|}", 02441 "fimul{l||l|}", 02442 "ficom{l||l|}", 02443 "ficomp{l||l|}", 02444 "fisub{l||l|}", 02445 "fisubr{l||l|}", 02446 "fidiv{l||l|}", 02447 "fidivr{l||l|}", 02448 /* db */ 02449 "fild{l||l|}", 02450 "(bad)", 02451 "fist{l||l|}", 02452 "fistp{l||l|}", 02453 "(bad)", 02454 "fld{t||t|}", 02455 "(bad)", 02456 "fstp{t||t|}", 02457 /* dc */ 02458 "fadd{l||l|}", 02459 "fmul{l||l|}", 02460 "fcom{l||l|}", 02461 "fcomp{l||l|}", 02462 "fsub{l||l|}", 02463 "fsubr{l||l|}", 02464 "fdiv{l||l|}", 02465 "fdivr{l||l|}", 02466 /* dd */ 02467 "fld{l||l|}", 02468 "(bad)", 02469 "fst{l||l|}", 02470 "fstp{l||l|}", 02471 "frstor", 02472 "(bad)", 02473 "fNsave", 02474 "fNstsw", 02475 /* de */ 02476 "fiadd", 02477 "fimul", 02478 "ficom", 02479 "ficomp", 02480 "fisub", 02481 "fisubr", 02482 "fidiv", 02483 "fidivr", 02484 /* df */ 02485 "fild", 02486 "(bad)", 02487 "fist", 02488 "fistp", 02489 "fbld", 02490 "fild{ll||ll|}", 02491 "fbstp", 02492 "fistpll", 02493 }; 02494 02495 #define ST OP_ST, 0 02496 #define STi OP_STi, 0 02497 02498 #define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0 02499 #define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0 02500 #define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0 02501 #define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0 02502 #define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0 02503 #define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0 02504 #define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0 02505 #define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0 02506 #define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0 02507 02508 static const struct dis386 float_reg[][8] = { 02509 /* d8 */ 02510 { 02511 { "fadd", ST, STi, XX }, 02512 { "fmul", ST, STi, XX }, 02513 { "fcom", STi, XX, XX }, 02514 { "fcomp", STi, XX, XX }, 02515 { "fsub", ST, STi, XX }, 02516 { "fsubr", ST, STi, XX }, 02517 { "fdiv", ST, STi, XX }, 02518 { "fdivr", ST, STi, XX }, 02519 }, 02520 /* d9 */ 02521 { 02522 { "fld", STi, XX, XX }, 02523 { "fxch", STi, XX, XX }, 02524 { FGRPd9_2 }, 02525 { "(bad)", XX, XX, XX }, 02526 { FGRPd9_4 }, 02527 { FGRPd9_5 }, 02528 { FGRPd9_6 }, 02529 { FGRPd9_7 }, 02530 }, 02531 /* da */ 02532 { 02533 { "fcmovb", ST, STi, XX }, 02534 { "fcmove", ST, STi, XX }, 02535 { "fcmovbe",ST, STi, XX }, 02536 { "fcmovu", ST, STi, XX }, 02537 { "(bad)", XX, XX, XX }, 02538 { FGRPda_5 }, 02539 { "(bad)", XX, XX, XX }, 02540 { "(bad)", XX, XX, XX }, 02541 }, 02542 /* db */ 02543 { 02544 { "fcmovnb",ST, STi, XX }, 02545 { "fcmovne",ST, STi, XX }, 02546 { "fcmovnbe",ST, STi, XX }, 02547 { "fcmovnu",ST, STi, XX }, 02548 { FGRPdb_4 }, 02549 { "fucomi", ST, STi, XX }, 02550 { "fcomi", ST, STi, XX }, 02551 { "(bad)", XX, XX, XX }, 02552 }, 02553 /* dc */ 02554 { 02555 { "fadd", STi, ST, XX }, 02556 { "fmul", STi, ST, XX }, 02557 { "(bad)", XX, XX, XX }, 02558 { "(bad)", XX, XX, XX }, 02559 #if UNIXWARE_COMPAT 02560 { "fsub", STi, ST, XX }, 02561 { "fsubr", STi, ST, XX }, 02562 { "fdiv", STi, ST, XX }, 02563 { "fdivr", STi, ST, XX }, 02564 #else 02565 { "fsubr", STi, ST, XX }, 02566 { "fsub", STi, ST, XX }, 02567 { "fdivr", STi, ST, XX }, 02568 { "fdiv", STi, ST, XX }, 02569 #endif 02570 }, 02571 /* dd */ 02572 { 02573 { "ffree", STi, XX, XX }, 02574 { "(bad)", XX, XX, XX }, 02575 { "fst", STi, XX, XX }, 02576 { "fstp", STi, XX, XX }, 02577 { "fucom", STi, XX, XX }, 02578 { "fucomp", STi, XX, XX }, 02579 { "(bad)", XX, XX, XX }, 02580 { "(bad)", XX, XX, XX }, 02581 }, 02582 /* de */ 02583 { 02584 { "faddp", STi, ST, XX }, 02585 { "fmulp", STi, ST, XX }, 02586 { "(bad)", XX, XX, XX }, 02587 { FGRPde_3 }, 02588 #if UNIXWARE_COMPAT 02589 { "fsubp", STi, ST, XX }, 02590 { "fsubrp", STi, ST, XX }, 02591 { "fdivp", STi, ST, XX }, 02592 { "fdivrp", STi, ST, XX }, 02593 #else 02594 { "fsubrp", STi, ST, XX }, 02595 { "fsubp", STi, ST, XX }, 02596 { "fdivrp", STi, ST, XX }, 02597 { "fdivp", STi, ST, XX }, 02598 #endif 02599 }, 02600 /* df */ 02601 { 02602 { "ffreep", STi, XX, XX }, 02603 { "(bad)", XX, XX, XX }, 02604 { "(bad)", XX, XX, XX }, 02605 { "(bad)", XX, XX, XX }, 02606 { FGRPdf_4 }, 02607 { "fucomip",ST, STi, XX }, 02608 { "fcomip", ST, STi, XX }, 02609 { "(bad)", XX, XX, XX }, 02610 }, 02611 }; 02612 02613 static char *fgrps[][8] = { 02614 /* d9_2 0 */ 02615 { 02616 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", 02617 }, 02618 02619 /* d9_4 1 */ 02620 { 02621 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)", 02622 }, 02623 02624 /* d9_5 2 */ 02625 { 02626 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)", 02627 }, 02628 02629 /* d9_6 3 */ 02630 { 02631 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp", 02632 }, 02633 02634 /* d9_7 4 */ 02635 { 02636 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos", 02637 }, 02638 02639 /* da_5 5 */ 02640 { 02641 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", 02642 }, 02643 02644 /* db_4 6 */ 02645 { 02646 "feni(287 only)","fdisi(287 only)","fNclex","fNinit", 02647 "fNsetpm(287 only)","(bad)","(bad)","(bad)", 02648 }, 02649 02650 /* de_3 7 */ 02651 { 02652 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", 02653 }, 02654 02655 /* df_4 8 */ 02656 { 02657 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", 02658 }, 02659 }; 02660 02661 static void 02662 dofloat (sizeflag) 02663 int sizeflag; 02664 { 02665 const struct dis386 *dp; 02666 unsigned char floatop; 02667 02668 floatop = codep[-1]; 02669 02670 if (mod != 3) 02671 { 02672 putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag); 02673 obufp = op1out; 02674 if (floatop == 0xdb) 02675 OP_E (x_mode, sizeflag); 02676 else if (floatop == 0xdd) 02677 OP_E (d_mode, sizeflag); 02678 else 02679 OP_E (v_mode, sizeflag); 02680 return; 02681 } 02682 /* Skip mod/rm byte. */ 02683 MODRM_CHECK; 02684 codep++; 02685 02686 dp = &float_reg[floatop - 0xd8][reg]; 02687 if (dp->name == NULL) 02688 { 02689 putop (fgrps[dp->bytemode1][rm], sizeflag); 02690 02691 /* Instruction fnstsw is only one with strange arg. */ 02692 if (floatop == 0xdf && codep[-1] == 0xe0) 02693 strcpy (op1out, names16[0]); 02694 } 02695 else 02696 { 02697 putop (dp->name, sizeflag); 02698 02699 obufp = op1out; 02700 if (dp->op1) 02701 (*dp->op1) (dp->bytemode1, sizeflag); 02702 obufp = op2out; 02703 if (dp->op2) 02704 (*dp->op2) (dp->bytemode2, sizeflag); 02705 } 02706 } 02707 02708 static void 02709 OP_ST (bytemode, sizeflag) 02710 int bytemode ATTRIBUTE_UNUSED; 02711 int sizeflag ATTRIBUTE_UNUSED; 02712 { 02713 oappend ("%st"); 02714 } 02715 02716 static void 02717 OP_STi (bytemode, sizeflag) 02718 int bytemode ATTRIBUTE_UNUSED; 02719 int sizeflag ATTRIBUTE_UNUSED; 02720 { 02721 sprintf (scratchbuf, "%%st(%d)", rm); 02722 oappend (scratchbuf + intel_syntax); 02723 } 02724 02725 /* Capital letters in template are macros. */ 02726 static int 02727 putop (template, sizeflag) 02728 const char *template; 02729 int sizeflag; 02730 { 02731 const char *p; 02732 int alt; 02733 02734 for (p = template; *p; p++) 02735 { 02736 switch (*p) 02737 { 02738 default: 02739 *obufp++ = *p; 02740 break; 02741 case '{': 02742 alt = 0; 02743 if (intel_syntax) 02744 alt += 1; 02745 if (mode_64bit) 02746 alt += 2; 02747 while (alt != 0) 02748 { 02749 while (*++p != '|') 02750 { 02751 if (*p == '}') 02752 { 02753 /* Alternative not valid. */ 02754 strcpy (obuf, "(bad)"); 02755 obufp = obuf + 5; 02756 return 1; 02757 } 02758 else if (*p == '\0') 02759 abort (); 02760 } 02761 alt--; 02762 } 02763 break; 02764 case '|': 02765 while (*++p != '}') 02766 { 02767 if (*p == '\0') 02768 abort (); 02769 } 02770 break; 02771 case '}': 02772 break; 02773 case 'A': 02774 if (intel_syntax) 02775 break; 02776 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) 02777 *obufp++ = 'b'; 02778 break; 02779 case 'B': 02780 if (intel_syntax) 02781 break; 02782 if (sizeflag & SUFFIX_ALWAYS) 02783 *obufp++ = 'b'; 02784 break; 02785 case 'E': /* For jcxz/jecxz */ 02786 if (mode_64bit) 02787 { 02788 if (sizeflag & AFLAG) 02789 *obufp++ = 'r'; 02790 else 02791 *obufp++ = 'e'; 02792 } 02793 else 02794 if (sizeflag & AFLAG) 02795 *obufp++ = 'e'; 02796 used_prefixes |= (prefixes & PREFIX_ADDR); 02797 break; 02798 case 'F': 02799 if (intel_syntax) 02800 break; 02801 if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS)) 02802 { 02803 if (sizeflag & AFLAG) 02804 *obufp++ = mode_64bit ? 'q' : 'l'; 02805 else 02806 *obufp++ = mode_64bit ? 'l' : 'w'; 02807 used_prefixes |= (prefixes & PREFIX_ADDR); 02808 } 02809 break; 02810 case 'H': 02811 if (intel_syntax) 02812 break; 02813 if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS 02814 || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS) 02815 { 02816 used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS); 02817 *obufp++ = ','; 02818 *obufp++ = 'p'; 02819 if (prefixes & PREFIX_DS) 02820 *obufp++ = 't'; 02821 else 02822 *obufp++ = 'n'; 02823 } 02824 break; 02825 case 'L': 02826 if (intel_syntax) 02827 break; 02828 if (sizeflag & SUFFIX_ALWAYS) 02829 *obufp++ = 'l'; 02830 break; 02831 case 'N': 02832 if ((prefixes & PREFIX_FWAIT) == 0) 02833 *obufp++ = 'n'; 02834 else 02835 used_prefixes |= PREFIX_FWAIT; 02836 break; 02837 case 'O': 02838 USED_REX (REX_MODE64); 02839 if (rex & REX_MODE64) 02840 *obufp++ = 'o'; 02841 else 02842 *obufp++ = 'd'; 02843 break; 02844 case 'T': 02845 if (intel_syntax) 02846 break; 02847 if (mode_64bit) 02848 { 02849 *obufp++ = 'q'; 02850 break; 02851 } 02852 /* Fall through. */ 02853 case 'P': 02854 if (intel_syntax) 02855 break; 02856 if ((prefixes & PREFIX_DATA) 02857 || (rex & REX_MODE64) 02858 || (sizeflag & SUFFIX_ALWAYS)) 02859 { 02860 USED_REX (REX_MODE64); 02861 if (rex & REX_MODE64) 02862 *obufp++ = 'q'; 02863 else 02864 { 02865 if (sizeflag & DFLAG) 02866 *obufp++ = 'l'; 02867 else 02868 *obufp++ = 'w'; 02869 used_prefixes |= (prefixes & PREFIX_DATA); 02870 } 02871 } 02872 break; 02873 case 'U': 02874 if (intel_syntax) 02875 break; 02876 if (mode_64bit) 02877 { 02878 *obufp++ = 'q'; 02879 break; 02880 } 02881 /* Fall through. */ 02882 case 'Q': 02883 if (intel_syntax) 02884 break; 02885 USED_REX (REX_MODE64); 02886 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) 02887 { 02888 if (rex & REX_MODE64) 02889 *obufp++ = 'q'; 02890 else 02891 { 02892 if (sizeflag & DFLAG) 02893 *obufp++ = 'l'; 02894 else 02895 *obufp++ = 'w'; 02896 used_prefixes |= (prefixes & PREFIX_DATA); 02897 } 02898 } 02899 break; 02900 case 'R': 02901 USED_REX (REX_MODE64); 02902 if (intel_syntax) 02903 { 02904 if (rex & REX_MODE64) 02905 { 02906 *obufp++ = 'q'; 02907 *obufp++ = 't'; 02908 } 02909 else if (sizeflag & DFLAG) 02910 { 02911 *obufp++ = 'd'; 02912 *obufp++ = 'q'; 02913 } 02914 else 02915 { 02916 *obufp++ = 'w'; 02917 *obufp++ = 'd'; 02918 } 02919 } 02920 else 02921 { 02922 if (rex & REX_MODE64) 02923 *obufp++ = 'q'; 02924 else if (sizeflag & DFLAG) 02925 *obufp++ = 'l'; 02926 else 02927 *obufp++ = 'w'; 02928 } 02929 if (!(rex & REX_MODE64)) 02930 used_prefixes |= (prefixes & PREFIX_DATA); 02931 break; 02932 case 'S': 02933 if (intel_syntax) 02934 break; 02935 if (sizeflag & SUFFIX_ALWAYS) 02936 { 02937 if (rex & REX_MODE64) 02938 *obufp++ = 'q'; 02939 else 02940 { 02941 if (sizeflag & DFLAG) 02942 *obufp++ = 'l'; 02943 else 02944 *obufp++ = 'w'; 02945 used_prefixes |= (prefixes & PREFIX_DATA); 02946 } 02947 } 02948 break; 02949 case 'X': 02950 if (prefixes & PREFIX_DATA) 02951 *obufp++ = 'd'; 02952 else 02953 *obufp++ = 's'; 02954 used_prefixes |= (prefixes & PREFIX_DATA); 02955 break; 02956 case 'Y': 02957 if (intel_syntax) 02958 break; 02959 if (rex & REX_MODE64) 02960 { 02961 USED_REX (REX_MODE64); 02962 *obufp++ = 'q'; 02963 } 02964 break; 02965 /* implicit operand size 'l' for i386 or 'q' for x86-64 */ 02966 case 'W': 02967 /* operand size flag for cwtl, cbtw */ 02968 USED_REX (0); 02969 if (rex) 02970 *obufp++ = 'l'; 02971 else if (sizeflag & DFLAG) 02972 *obufp++ = 'w'; 02973 else 02974 *obufp++ = 'b'; 02975 if (intel_syntax) 02976 { 02977 if (rex) 02978 { 02979 *obufp++ = 'q'; 02980 *obufp++ = 'e'; 02981 } 02982 if (sizeflag & DFLAG) 02983 { 02984 *obufp++ = 'd'; 02985 *obufp++ = 'e'; 02986 } 02987 else 02988 { 02989 *obufp++ = 'w'; 02990 } 02991 } 02992 if (!rex) 02993 used_prefixes |= (prefixes & PREFIX_DATA); 02994 break; 02995 } 02996 } 02997 *obufp = 0; 02998 return 0; 02999 } 03000 03001 static void 03002 oappend (s) 03003 const char *s; 03004 { 03005 strcpy (obufp, s); 03006 obufp += strlen (s); 03007 } 03008 03009 static void 03010 append_seg () 03011 { 03012 if (prefixes & PREFIX_CS) 03013 { 03014 used_prefixes |= PREFIX_CS; 03015 oappend ("%cs:" + intel_syntax); 03016 } 03017 if (prefixes & PREFIX_DS) 03018 { 03019 used_prefixes |= PREFIX_DS; 03020 oappend ("%ds:" + intel_syntax); 03021 } 03022 if (prefixes & PREFIX_SS) 03023 { 03024 used_prefixes |= PREFIX_SS; 03025 oappend ("%ss:" + intel_syntax); 03026 } 03027 if (prefixes & PREFIX_ES) 03028 { 03029 used_prefixes |= PREFIX_ES; 03030 oappend ("%es:" + intel_syntax); 03031 } 03032 if (prefixes & PREFIX_FS) 03033 { 03034 used_prefixes |= PREFIX_FS; 03035 oappend ("%fs:" + intel_syntax); 03036 } 03037 if (prefixes & PREFIX_GS) 03038 { 03039 used_prefixes |= PREFIX_GS; 03040 oappend ("%gs:" + intel_syntax); 03041 } 03042 } 03043 03044 static void 03045 OP_indirE (bytemode, sizeflag) 03046 int bytemode; 03047 int sizeflag; 03048 { 03049 if (!intel_syntax) 03050 oappend ("*"); 03051 OP_E (bytemode, sizeflag); 03052 } 03053 03054 static void 03055 print_operand_value (buf, hex, disp) 03056 char *buf; 03057 int hex; 03058 bfd_vma disp; 03059 { 03060 if (mode_64bit) 03061 { 03062 if (hex) 03063 { 03064 char tmp[30]; 03065 int i; 03066 buf[0] = '0'; 03067 buf[1] = 'x'; 03068 sprintf_vma (tmp, disp); 03069 for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++); 03070 strcpy (buf + 2, tmp + i); 03071 } 03072 else 03073 { 03074 bfd_signed_vma v = disp; 03075 char tmp[30]; 03076 int i; 03077 if (v < 0) 03078 { 03079 *(buf++) = '-'; 03080 v = -disp; 03081 /* Check for possible overflow on 0x8000000000000000. */ 03082 if (v < 0) 03083 { 03084 strcpy (buf, "9223372036854775808"); 03085 return; 03086 } 03087 } 03088 if (!v) 03089 { 03090 strcpy (buf, "0"); 03091 return; 03092 } 03093 03094 i = 0; 03095 tmp[29] = 0; 03096 while (v) 03097 { 03098 tmp[28 - i] = (v % 10) + '0'; 03099 v /= 10; 03100 i++; 03101 } 03102 strcpy (buf, tmp + 29 - i); 03103 } 03104 } 03105 else 03106 { 03107 if (hex) 03108 sprintf (buf, "0x%x", (unsigned int) disp); 03109 else 03110 sprintf (buf, "%d", (int) disp); 03111 } 03112 } 03113 03114 static void 03115 OP_E (bytemode, sizeflag) 03116 int bytemode; 03117 int sizeflag; 03118 { 03119 bfd_vma disp; 03120 int add = 0; 03121 int riprel = 0; 03122 USED_REX (REX_EXTZ); 03123 if (rex & REX_EXTZ) 03124 add += 8; 03125 03126 /* Skip mod/rm byte. */ 03127 MODRM_CHECK; 03128 codep++; 03129 03130 if (mod == 3) 03131 { 03132 switch (bytemode) 03133 { 03134 case b_mode: 03135 USED_REX (0); 03136 if (rex) 03137 oappend (names8rex[rm + add]); 03138 else 03139 oappend (names8[rm + add]); 03140 break; 03141 case w_mode: 03142 oappend (names16[rm + add]); 03143 break; 03144 case d_mode: 03145 oappend (names32[rm + add]); 03146 break; 03147 case q_mode: 03148 oappend (names64[rm + add]); 03149 break; 03150 case m_mode: 03151 if (mode_64bit) 03152 oappend (names64[rm + add]); 03153 else 03154 oappend (names32[rm + add]); 03155 break; 03156 case v_mode: 03157 USED_REX (REX_MODE64); 03158 if (rex & REX_MODE64) 03159 oappend (names64[rm + add]); 03160 else if (sizeflag & DFLAG) 03161 oappend (names32[rm + add]); 03162 else 03163 oappend (names16[rm + add]); 03164 used_prefixes |= (prefixes & PREFIX_DATA); 03165 break; 03166 case 0: 03167 if (!(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */) 03168 && !(codep[-2] == 0xAE && codep[-1] == 0xF0 /* mfence */) 03169 && !(codep[-2] == 0xAE && codep[-1] == 0xe8 /* lfence */)) 03170 BadOp (); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */ 03171 break; 03172 default: 03173 oappend (INTERNAL_DISASSEMBLER_ERROR); 03174 break; 03175 } 03176 return; 03177 } 03178 03179 disp = 0; 03180 append_seg (); 03181 03182 if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */ 03183 { 03184 int havesib; 03185 int havebase; 03186 int base; 03187 int index = 0; 03188 int scale = 0; 03189 03190 havesib = 0; 03191 havebase = 1; 03192 base = rm; 03193 03194 if (base == 4) 03195 { 03196 havesib = 1; 03197 FETCH_DATA (the_info, codep + 1); 03198 scale = (*codep >> 6) & 3; 03199 index = (*codep >> 3) & 7; 03200 base = *codep & 7; 03201 USED_REX (REX_EXTY); 03202 USED_REX (REX_EXTZ); 03203 if (rex & REX_EXTY) 03204 index += 8; 03205 if (rex & REX_EXTZ) 03206 base += 8; 03207 codep++; 03208 } 03209 03210 switch (mod) 03211 { 03212 case 0: 03213 if ((base & 7) == 5) 03214 { 03215 havebase = 0; 03216 if (mode_64bit && !havesib && (sizeflag & AFLAG)) 03217 riprel = 1; 03218 disp = get32s (); 03219 } 03220 break; 03221 case 1: 03222 FETCH_DATA (the_info, codep + 1); 03223 disp = *codep++; 03224 if ((disp & 0x80) != 0) 03225 disp -= 0x100; 03226 break; 03227 case 2: 03228 disp = get32s (); 03229 break; 03230 } 03231 03232 if (!intel_syntax) 03233 if (mod != 0 || (base & 7) == 5) 03234 { 03235 print_operand_value (scratchbuf, !riprel, disp); 03236 oappend (scratchbuf); 03237 if (riprel) 03238 { 03239 set_op (disp, 1); 03240 oappend ("(%rip)"); 03241 } 03242 } 03243 03244 if (havebase || (havesib && (index != 4 || scale != 0))) 03245 { 03246 if (intel_syntax) 03247 { 03248 switch (bytemode) 03249 { 03250 case b_mode: 03251 oappend ("BYTE PTR "); 03252 break; 03253 case w_mode: 03254 oappend ("WORD PTR "); 03255 break; 03256 case v_mode: 03257 oappend ("DWORD PTR "); 03258 break; 03259 case d_mode: 03260 oappend ("QWORD PTR "); 03261 break; 03262 case m_mode: 03263 if (mode_64bit) 03264 oappend ("DWORD PTR "); 03265 else 03266 oappend ("QWORD PTR "); 03267 break; 03268 case x_mode: 03269 oappend ("XWORD PTR "); 03270 break; 03271 default: 03272 break; 03273 } 03274 } 03275 *obufp++ = open_char; 03276 if (intel_syntax && riprel) 03277 oappend ("rip + "); 03278 *obufp = '\0'; 03279 USED_REX (REX_EXTZ); 03280 if (!havesib && (rex & REX_EXTZ)) 03281 base += 8; 03282 if (havebase) 03283 oappend (mode_64bit && (sizeflag & AFLAG) 03284 ? names64[base] : names32[base]); 03285 if (havesib) 03286 { 03287 if (index != 4) 03288 { 03289 if (intel_syntax) 03290 { 03291 if (havebase) 03292 { 03293 *obufp++ = separator_char; 03294 *obufp = '\0'; 03295 } 03296 sprintf (scratchbuf, "%s", 03297 mode_64bit && (sizeflag & AFLAG) 03298 ? names64[index] : names32[index]); 03299 } 03300 else 03301 sprintf (scratchbuf, ",%s", 03302 mode_64bit && (sizeflag & AFLAG) 03303 ? names64[index] : names32[index]); 03304 oappend (scratchbuf); 03305 } 03306 if (!intel_syntax 03307 || (intel_syntax 03308 && bytemode != b_mode 03309 && bytemode != w_mode 03310 && bytemode != v_mode)) 03311 { 03312 *obufp++ = scale_char; 03313 *obufp = '\0'; 03314 sprintf (scratchbuf, "%d", 1 << scale); 03315 oappend (scratchbuf); 03316 } 03317 } 03318 if (intel_syntax) 03319 if (mod != 0 || (base & 7) == 5) 03320 { 03321 /* Don't print zero displacements. */ 03322 if (disp != 0) 03323 { 03324 if ((bfd_signed_vma) disp > 0) 03325 { 03326 *obufp++ = '+'; 03327 *obufp = '\0'; 03328 } 03329 03330 print_operand_value (scratchbuf, 0, disp); 03331 oappend (scratchbuf); 03332 } 03333 } 03334 03335 *obufp++ = close_char; 03336 *obufp = '\0'; 03337 } 03338 else if (intel_syntax) 03339 { 03340 if (mod != 0 || (base & 7) == 5) 03341 { 03342 if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS 03343 | PREFIX_ES | PREFIX_FS | PREFIX_GS)) 03344 ; 03345 else 03346 { 03347 oappend (names_seg[ds_reg - es_reg]); 03348 oappend (":"); 03349 } 03350 print_operand_value (scratchbuf, 1, disp); 03351 oappend (scratchbuf); 03352 } 03353 } 03354 } 03355 else 03356 { /* 16 bit address mode */ 03357 switch (mod) 03358 { 03359 case 0: 03360 if ((rm & 7) == 6) 03361 { 03362 disp = get16 (); 03363 if ((disp & 0x8000) != 0) 03364 disp -= 0x10000; 03365 } 03366 break; 03367 case 1: 03368 FETCH_DATA (the_info, codep + 1); 03369 disp = *codep++; 03370 if ((disp & 0x80) != 0) 03371 disp -= 0x100; 03372 break; 03373 case 2: 03374 disp = get16 (); 03375 if ((disp & 0x8000) != 0) 03376 disp -= 0x10000; 03377 break; 03378 } 03379 03380 if (!intel_syntax) 03381 if (mod != 0 || (rm & 7) == 6) 03382 { 03383 print_operand_value (scratchbuf, 0, disp); 03384 oappend (scratchbuf); 03385 } 03386 03387 if (mod != 0 || (rm & 7) != 6) 03388 { 03389 *obufp++ = open_char; 03390 *obufp = '\0'; 03391 oappend (index16[rm + add]); 03392 *obufp++ = close_char; 03393 *obufp = '\0'; 03394 } 03395 } 03396 } 03397 03398 static void 03399 OP_G (bytemode, sizeflag) 03400 int bytemode; 03401 int sizeflag; 03402 { 03403 int add = 0; 03404 USED_REX (REX_EXTX); 03405 if (rex & REX_EXTX) 03406 add += 8; 03407 switch (bytemode) 03408 { 03409 case b_mode: 03410 USED_REX (0); 03411 if (rex) 03412 oappend (names8rex[reg + add]); 03413 else 03414 oappend (names8[reg + add]); 03415 break; 03416 case w_mode: 03417 oappend (names16[reg + add]); 03418 break; 03419 case d_mode: 03420 oappend (names32[reg + add]); 03421 break; 03422 case q_mode: 03423 oappend (names64[reg + add]); 03424 break; 03425 case v_mode: 03426 USED_REX (REX_MODE64); 03427 if (rex & REX_MODE64) 03428 oappend (names64[reg + add]); 03429 else if (sizeflag & DFLAG) 03430 oappend (names32[reg + add]); 03431 else 03432 oappend (names16[reg + add]); 03433 used_prefixes |= (prefixes & PREFIX_DATA); 03434 break; 03435 default: 03436 oappend (INTERNAL_DISASSEMBLER_ERROR); 03437 break; 03438 } 03439 } 03440 03441 static bfd_vma 03442 get64 () 03443 { 03444 bfd_vma x; 03445 #ifdef BFD64 03446 unsigned int a; 03447 unsigned int b; 03448 03449 FETCH_DATA (the_info, codep + 8); 03450 a = *codep++ & 0xff; 03451 a |= (*codep++ & 0xff) << 8; 03452 a |= (*codep++ & 0xff) << 16; 03453 a |= (*codep++ & 0xff) << 24; 03454 b = *codep++ & 0xff; 03455 b |= (*codep++ & 0xff) << 8; 03456 b |= (*codep++ & 0xff) << 16; 03457 b |= (*codep++ & 0xff) << 24; 03458 x = a + ((bfd_vma) b << 32); 03459 #else 03460 abort (); 03461 x = 0; 03462 #endif 03463 return x; 03464 } 03465 03466 static bfd_signed_vma 03467 get32 () 03468 { 03469 bfd_signed_vma x = 0; 03470 03471 FETCH_DATA (the_info, codep + 4); 03472 x = *codep++ & (bfd_signed_vma) 0xff; 03473 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; 03474 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; 03475 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; 03476 return x; 03477 } 03478 03479 static bfd_signed_vma 03480 get32s () 03481 { 03482 bfd_signed_vma x = 0; 03483 03484 FETCH_DATA (the_info, codep + 4); 03485 x = *codep++ & (bfd_signed_vma) 0xff; 03486 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; 03487 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; 03488 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; 03489 03490 x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31); 03491 03492 return x; 03493 } 03494 03495 static int 03496 get16 () 03497 { 03498 int x = 0; 03499 03500 FETCH_DATA (the_info, codep + 2); 03501 x = *codep++ & 0xff; 03502 x |= (*codep++ & 0xff) << 8; 03503 return x; 03504 } 03505 03506 static void 03507 set_op (op, riprel) 03508 bfd_vma op; 03509 int riprel; 03510 { 03511 op_index[op_ad] = op_ad; 03512 if (mode_64bit) 03513 { 03514 op_address[op_ad] = op; 03515 op_riprel[op_ad] = riprel; 03516 } 03517 else 03518 { 03519 /* Mask to get a 32-bit address. */ 03520 op_address[op_ad] = op & 0xffffffff; 03521 op_riprel[op_ad] = riprel & 0xffffffff; 03522 } 03523 } 03524 03525 static void 03526 OP_REG (code, sizeflag) 03527 int code; 03528 int sizeflag; 03529 { 03530 const char *s; 03531 int add = 0; 03532 USED_REX (REX_EXTZ); 03533 if (rex & REX_EXTZ) 03534 add = 8; 03535 03536 switch (code) 03537 { 03538 case indir_dx_reg: 03539 if (intel_syntax) 03540 s = "[dx]"; 03541 else 03542 s = "(%dx)"; 03543 break; 03544 case ax_reg: case cx_reg: case dx_reg: case bx_reg: 03545 case sp_reg: case bp_reg: case si_reg: case di_reg: 03546 s = names16[code - ax_reg + add]; 03547 break; 03548 case es_reg: case ss_reg: case cs_reg: 03549 case ds_reg: case fs_reg: case gs_reg: 03550 s = names_seg[code - es_reg + add]; 03551 break; 03552 case al_reg: case ah_reg: case cl_reg: case ch_reg: 03553 case dl_reg: case dh_reg: case bl_reg: case bh_reg: 03554 USED_REX (0); 03555 if (rex) 03556 s = names8rex[code - al_reg + add]; 03557 else 03558 s = names8[code - al_reg]; 03559 break; 03560 case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg: 03561 case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg: 03562 if (mode_64bit) 03563 { 03564 s = names64[code - rAX_reg + add]; 03565 break; 03566 } 03567 code += eAX_reg - rAX_reg; 03568 /* Fall through. */ 03569 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: 03570 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: 03571 USED_REX (REX_MODE64); 03572 if (rex & REX_MODE64) 03573 s = names64[code - eAX_reg + add]; 03574 else if (sizeflag & DFLAG) 03575 s = names32[code - eAX_reg + add]; 03576 else 03577 s = names16[code - eAX_reg + add]; 03578 used_prefixes |= (prefixes & PREFIX_DATA); 03579 break; 03580 default: 03581 s = INTERNAL_DISASSEMBLER_ERROR; 03582 break; 03583 } 03584 oappend (s); 03585 } 03586 03587 static void 03588 OP_IMREG (code, sizeflag) 03589 int code; 03590 int sizeflag; 03591 { 03592 const char *s; 03593 03594 switch (code) 03595 { 03596 case indir_dx_reg: 03597 if (intel_syntax) 03598 s = "[dx]"; 03599 else 03600 s = "(%dx)"; 03601 break; 03602 case ax_reg: case cx_reg: case dx_reg: case bx_reg: 03603 case sp_reg: case bp_reg: case si_reg: case di_reg: 03604 s = names16[code - ax_reg]; 03605 break; 03606 case es_reg: case ss_reg: case cs_reg: 03607 case ds_reg: case fs_reg: case gs_reg: 03608 s = names_seg[code - es_reg]; 03609 break; 03610 case al_reg: case ah_reg: case cl_reg: case ch_reg: 03611 case dl_reg: case dh_reg: case bl_reg: case bh_reg: 03612 USED_REX (0); 03613 if (rex) 03614 s = names8rex[code - al_reg]; 03615 else 03616 s = names8[code - al_reg]; 03617 break; 03618 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: 03619 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: 03620 USED_REX (REX_MODE64); 03621 if (rex & REX_MODE64) 03622 s = names64[code - eAX_reg]; 03623 else if (sizeflag & DFLAG) 03624 s = names32[code - eAX_reg]; 03625 else 03626 s = names16[code - eAX_reg]; 03627 used_prefixes |= (prefixes & PREFIX_DATA); 03628 break; 03629 default: 03630 s = INTERNAL_DISASSEMBLER_ERROR; 03631 break; 03632 } 03633 oappend (s); 03634 } 03635 03636 static void 03637 OP_I (bytemode, sizeflag) 03638 int bytemode; 03639 int sizeflag; 03640 { 03641 bfd_signed_vma op; 03642 bfd_signed_vma mask = -1; 03643 03644 switch (bytemode) 03645 { 03646 case b_mode: 03647 FETCH_DATA (the_info, codep + 1); 03648 op = *codep++; 03649 mask = 0xff; 03650 break; 03651 case q_mode: 03652 if (mode_64bit) 03653 { 03654 op = get32s (); 03655 break; 03656 } 03657 /* Fall through. */ 03658 case v_mode: 03659 USED_REX (REX_MODE64); 03660 if (rex & REX_MODE64) 03661 op = get32s (); 03662 else if (sizeflag & DFLAG) 03663 { 03664 op = get32 (); 03665 mask = 0xffffffff; 03666 } 03667 else 03668 { 03669 op = get16 (); 03670 mask = 0xfffff; 03671 } 03672 used_prefixes |= (prefixes & PREFIX_DATA); 03673 break; 03674 case w_mode: 03675 mask = 0xfffff; 03676 op = get16 (); 03677 break; 03678 default: 03679 oappend (INTERNAL_DISASSEMBLER_ERROR); 03680 return; 03681 } 03682 03683 op &= mask; 03684 scratchbuf[0] = '$'; 03685 print_operand_value (scratchbuf + 1, 1, op); 03686 oappend (scratchbuf + intel_syntax); 03687 scratchbuf[0] = '\0'; 03688 } 03689 03690 static void 03691 OP_I64 (bytemode, sizeflag) 03692 int bytemode; 03693 int sizeflag; 03694 { 03695 bfd_signed_vma op; 03696 bfd_signed_vma mask = -1; 03697 03698 if (!mode_64bit) 03699 { 03700 OP_I (bytemode, sizeflag); 03701 return; 03702 } 03703 03704 switch (bytemode) 03705 { 03706 case b_mode: 03707 FETCH_DATA (the_info, codep + 1); 03708 op = *codep++; 03709 mask = 0xff; 03710 break; 03711 case v_mode: 03712 USED_REX (REX_MODE64); 03713 if (rex & REX_MODE64) 03714 op = get64 (); 03715 else if (sizeflag & DFLAG) 03716 { 03717 op = get32 (); 03718 mask = 0xffffffff; 03719 } 03720 else 03721 { 03722 op = get16 (); 03723 mask = 0xfffff; 03724 } 03725 used_prefixes |= (prefixes & PREFIX_DATA); 03726 break; 03727 case w_mode: 03728 mask = 0xfffff; 03729 op = get16 (); 03730 break; 03731 default: 03732 oappend (INTERNAL_DISASSEMBLER_ERROR); 03733 return; 03734 } 03735 03736 op &= mask; 03737 scratchbuf[0] = '$'; 03738 print_operand_value (scratchbuf + 1, 1, op); 03739 oappend (scratchbuf + intel_syntax); 03740 scratchbuf[0] = '\0'; 03741 } 03742 03743 static void 03744 OP_sI (bytemode, sizeflag) 03745 int bytemode; 03746 int sizeflag; 03747 { 03748 bfd_signed_vma op; 03749 03750 switch (bytemode) 03751 { 03752 case b_mode: 03753 FETCH_DATA (the_info, codep + 1); 03754 op = *codep++; 03755 if ((op & 0x80) != 0) 03756 op -= 0x100; 03757 break; 03758 case v_mode: 03759 USED_REX (REX_MODE64); 03760 if (rex & REX_MODE64) 03761 op = get32s (); 03762 else if (sizeflag & DFLAG) 03763 { 03764 op = get32s (); 03765 } 03766 else 03767 { 03768 op = get16 (); 03769 if ((op & 0x8000) != 0) 03770 op -= 0x10000; 03771 } 03772 used_prefixes |= (prefixes & PREFIX_DATA); 03773 break; 03774 case w_mode: 03775 op = get16 (); 03776 if ((op & 0x8000) != 0) 03777 op -= 0x10000; 03778 break; 03779 default: 03780 oappend (INTERNAL_DISASSEMBLER_ERROR); 03781 return; 03782 } 03783 03784 scratchbuf[0] = '$'; 03785 print_operand_value (scratchbuf + 1, 1, op); 03786 oappend (scratchbuf + intel_syntax); 03787 } 03788 03789 static void 03790 OP_J (bytemode, sizeflag) 03791 int bytemode; 03792 int sizeflag; 03793 { 03794 bfd_vma disp; 03795 bfd_vma mask = -1; 03796 03797 switch (bytemode) 03798 { 03799 case b_mode: 03800 FETCH_DATA (the_info, codep + 1); 03801 disp = *codep++; 03802 if ((disp & 0x80) != 0) 03803 disp -= 0x100; 03804 break; 03805 case v_mode: 03806 if (sizeflag & DFLAG) 03807 disp = get32s (); 03808 else 03809 { 03810 disp = get16 (); 03811 /* For some reason, a data16 prefix on a jump instruction 03812 means that the pc is masked to 16 bits after the 03813 displacement is added! */ 03814 mask = 0xffff; 03815 } 03816 break; 03817 default: 03818 oappend (INTERNAL_DISASSEMBLER_ERROR); 03819 return; 03820 } 03821 disp = (start_pc + codep - start_codep + disp) & mask; 03822 set_op (disp, 0); 03823 print_operand_value (scratchbuf, 1, disp); 03824 oappend (scratchbuf); 03825 } 03826 03827 static void 03828 OP_SEG (dummy, sizeflag) 03829 int dummy ATTRIBUTE_UNUSED; 03830 int sizeflag ATTRIBUTE_UNUSED; 03831 { 03832 oappend (names_seg[reg]); 03833 } 03834 03835 static void 03836 OP_DIR (dummy, sizeflag) 03837 int dummy ATTRIBUTE_UNUSED; 03838 int sizeflag; 03839 { 03840 int seg, offset; 03841 03842 if (sizeflag & DFLAG) 03843 { 03844 offset = get32 (); 03845 seg = get16 (); 03846 } 03847 else 03848 { 03849 offset = get16 (); 03850 seg = get16 (); 03851 } 03852 used_prefixes |= (prefixes & PREFIX_DATA); 03853 if (intel_syntax) 03854 sprintf (scratchbuf, "0x%x,0x%x", seg, offset); 03855 else 03856 sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset); 03857 oappend (scratchbuf); 03858 } 03859 03860 static void 03861 OP_OFF (bytemode, sizeflag) 03862 int bytemode ATTRIBUTE_UNUSED; 03863 int sizeflag; 03864 { 03865 bfd_vma off; 03866 03867 append_seg (); 03868 03869 if ((sizeflag & AFLAG) || mode_64bit) 03870 off = get32 (); 03871 else 03872 off = get16 (); 03873 03874 if (intel_syntax) 03875 { 03876 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS 03877 | PREFIX_ES | PREFIX_FS | PREFIX_GS))) 03878 { 03879 oappend (names_seg[ds_reg - es_reg]); 03880 oappend (":"); 03881 } 03882 } 03883 print_operand_value (scratchbuf, 1, off); 03884 oappend (scratchbuf); 03885 } 03886 03887 static void 03888 OP_OFF64 (bytemode, sizeflag) 03889 int bytemode ATTRIBUTE_UNUSED; 03890 int sizeflag ATTRIBUTE_UNUSED; 03891 { 03892 bfd_vma off; 03893 03894 if (!mode_64bit) 03895 { 03896 OP_OFF (bytemode, sizeflag); 03897 return; 03898 } 03899 03900 append_seg (); 03901 03902 off = get64 (); 03903 03904 if (intel_syntax) 03905 { 03906 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS 03907 | PREFIX_ES | PREFIX_FS | PREFIX_GS))) 03908 { 03909 oappend (names_seg[ds_reg - es_reg]); 03910 oappend (":"); 03911 } 03912 } 03913 print_operand_value (scratchbuf, 1, off); 03914 oappend (scratchbuf); 03915 } 03916 03917 static void 03918 ptr_reg (code, sizeflag) 03919 int code; 03920 int sizeflag; 03921 { 03922 const char *s; 03923 if (intel_syntax) 03924 oappend ("["); 03925 else 03926 oappend ("("); 03927 03928 USED_REX (REX_MODE64); 03929 if (rex & REX_MODE64) 03930 { 03931 if (!(sizeflag & AFLAG)) 03932 s = names32[code - eAX_reg]; 03933 else 03934 s = names64[code - eAX_reg]; 03935 } 03936 else if (sizeflag & AFLAG) 03937 s = names32[code - eAX_reg]; 03938 else 03939 s = names16[code - eAX_reg]; 03940 oappend (s); 03941 if (intel_syntax) 03942 oappend ("]"); 03943 else 03944 oappend (")"); 03945 } 03946 03947 static void 03948 OP_ESreg (code, sizeflag) 03949 int code; 03950 int sizeflag; 03951 { 03952 oappend ("%es:" + intel_syntax); 03953 ptr_reg (code, sizeflag); 03954 } 03955 03956 static void 03957 OP_DSreg (code, sizeflag) 03958 int code; 03959 int sizeflag; 03960 { 03961 if ((prefixes 03962 & (PREFIX_CS 03963 | PREFIX_DS 03964 | PREFIX_SS 03965 | PREFIX_ES 03966 | PREFIX_FS 03967 | PREFIX_GS)) == 0) 03968 prefixes |= PREFIX_DS; 03969 append_seg (); 03970 ptr_reg (code, sizeflag); 03971 } 03972 03973 static void 03974 OP_C (dummy, sizeflag) 03975 int dummy ATTRIBUTE_UNUSED; 03976 int sizeflag ATTRIBUTE_UNUSED; 03977 { 03978 int add = 0; 03979 USED_REX (REX_EXTX); 03980 if (rex & REX_EXTX) 03981 add = 8; 03982 sprintf (scratchbuf, "%%cr%d", reg + add); 03983 oappend (scratchbuf + intel_syntax); 03984 } 03985 03986 static void 03987 OP_D (dummy, sizeflag) 03988 int dummy ATTRIBUTE_UNUSED; 03989 int sizeflag ATTRIBUTE_UNUSED; 03990 { 03991 int add = 0; 03992 USED_REX (REX_EXTX); 03993 if (rex & REX_EXTX) 03994 add = 8; 03995 if (intel_syntax) 03996 sprintf (scratchbuf, "db%d", reg + add); 03997 else 03998 sprintf (scratchbuf, "%%db%d", reg + add); 03999 oappend (scratchbuf); 04000 } 04001 04002 static void 04003 OP_T (dummy, sizeflag) 04004 int dummy ATTRIBUTE_UNUSED; 04005 int sizeflag ATTRIBUTE_UNUSED; 04006 { 04007 sprintf (scratchbuf, "%%tr%d", reg); 04008 oappend (scratchbuf + intel_syntax); 04009 } 04010 04011 static void 04012 OP_Rd (bytemode, sizeflag) 04013 int bytemode; 04014 int sizeflag; 04015 { 04016 if (mod == 3) 04017 OP_E (bytemode, sizeflag); 04018 else 04019 BadOp (); 04020 } 04021 04022 static void 04023 OP_MMX (bytemode, sizeflag) 04024 int bytemode ATTRIBUTE_UNUSED; 04025 int sizeflag ATTRIBUTE_UNUSED; 04026 { 04027 int add = 0; 04028 USED_REX (REX_EXTX); 04029 if (rex & REX_EXTX) 04030 add = 8; 04031 used_prefixes |= (prefixes & PREFIX_DATA); 04032 if (prefixes & PREFIX_DATA) 04033 sprintf (scratchbuf, "%%xmm%d", reg + add); 04034 else 04035 sprintf (scratchbuf, "%%mm%d", reg + add); 04036 oappend (scratchbuf + intel_syntax); 04037 } 04038 04039 static void 04040 OP_XMM (bytemode, sizeflag) 04041 int bytemode ATTRIBUTE_UNUSED; 04042 int sizeflag ATTRIBUTE_UNUSED; 04043 { 04044 int add = 0; 04045 USED_REX (REX_EXTX); 04046 if (rex & REX_EXTX) 04047 add = 8; 04048 sprintf (scratchbuf, "%%xmm%d", reg + add); 04049 oappend (scratchbuf + intel_syntax); 04050 } 04051 04052 static void 04053 OP_EM (bytemode, sizeflag) 04054 int bytemode; 04055 int sizeflag; 04056 { 04057 int add = 0; 04058 if (mod != 3) 04059 { 04060 OP_E (bytemode, sizeflag); 04061 return; 04062 } 04063 USED_REX (REX_EXTZ); 04064 if (rex & REX_EXTZ) 04065 add = 8; 04066 04067 /* Skip mod/rm byte. */ 04068 MODRM_CHECK; 04069 codep++; 04070 used_prefixes |= (prefixes & PREFIX_DATA); 04071 if (prefixes & PREFIX_DATA) 04072 sprintf (scratchbuf, "%%xmm%d", rm + add); 04073 else 04074 sprintf (scratchbuf, "%%mm%d", rm + add); 04075 oappend (scratchbuf + intel_syntax); 04076 } 04077 04078 static void 04079 OP_EX (bytemode, sizeflag) 04080 int bytemode; 04081 int sizeflag; 04082 { 04083 int add = 0; 04084 if (mod != 3) 04085 { 04086 OP_E (bytemode, sizeflag); 04087 return; 04088 } 04089 USED_REX (REX_EXTZ); 04090 if (rex & REX_EXTZ) 04091 add = 8; 04092 04093 /* Skip mod/rm byte. */ 04094 MODRM_CHECK; 04095 codep++; 04096 sprintf (scratchbuf, "%%xmm%d", rm + add); 04097 oappend (scratchbuf + intel_syntax); 04098 } 04099 04100 static void 04101 OP_MS (bytemode, sizeflag) 04102 int bytemode; 04103 int sizeflag; 04104 { 04105 if (mod == 3) 04106 OP_EM (bytemode, sizeflag); 04107 else 04108 BadOp (); 04109 } 04110 04111 static void 04112 OP_XS (bytemode, sizeflag) 04113 int bytemode; 04114 int sizeflag; 04115 { 04116 if (mod == 3) 04117 OP_EX (bytemode, sizeflag); 04118 else 04119 BadOp (); 04120 } 04121 04122 static const char *Suffix3DNow[] = { 04123 /* 00 */ NULL, NULL, NULL, NULL, 04124 /* 04 */ NULL, NULL, NULL, NULL, 04125 /* 08 */ NULL, NULL, NULL, NULL, 04126 /* 0C */ "pi2fw", "pi2fd", NULL, NULL, 04127 /* 10 */ NULL, NULL, NULL, NULL, 04128 /* 14 */ NULL, NULL, NULL, NULL, 04129 /* 18 */ NULL, NULL, NULL, NULL, 04130 /* 1C */ "pf2iw", "pf2id", NULL, NULL, 04131 /* 20 */ NULL, NULL, NULL, NULL, 04132 /* 24 */ NULL, NULL, NULL, NULL, 04133 /* 28 */ NULL, NULL, NULL, NULL, 04134 /* 2C */ NULL, NULL, NULL, NULL, 04135 /* 30 */ NULL, NULL, NULL, NULL, 04136 /* 34 */ NULL, NULL, NULL, NULL, 04137 /* 38 */ NULL, NULL, NULL, NULL, 04138 /* 3C */ NULL, NULL, NULL, NULL, 04139 /* 40 */ NULL, NULL, NULL, NULL, 04140 /* 44 */ NULL, NULL, NULL, NULL, 04141 /* 48 */ NULL, NULL, NULL, NULL, 04142 /* 4C */ NULL, NULL, NULL, NULL, 04143 /* 50 */ NULL, NULL, NULL, NULL, 04144 /* 54 */ NULL, NULL, NULL, NULL, 04145 /* 58 */ NULL, NULL, NULL, NULL, 04146 /* 5C */ NULL, NULL, NULL, NULL, 04147 /* 60 */ NULL, NULL, NULL, NULL, 04148 /* 64 */ NULL, NULL, NULL, NULL, 04149 /* 68 */ NULL, NULL, NULL, NULL, 04150 /* 6C */ NULL, NULL, NULL, NULL, 04151 /* 70 */ NULL, NULL, NULL, NULL, 04152 /* 74 */ NULL, NULL, NULL, NULL, 04153 /* 78 */ NULL, NULL, NULL, NULL, 04154 /* 7C */ NULL, NULL, NULL, NULL, 04155 /* 80 */ NULL, NULL, NULL, NULL, 04156 /* 84 */ NULL, NULL, NULL, NULL, 04157 /* 88 */ NULL, NULL, "pfnacc", NULL, 04158 /* 8C */ NULL, NULL, "pfpnacc", NULL, 04159 /* 90 */ "pfcmpge", NULL, NULL, NULL, 04160 /* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt", 04161 /* 98 */ NULL, NULL, "pfsub", NULL, 04162 /* 9C */ NULL, NULL, "pfadd", NULL, 04163 /* A0 */ "pfcmpgt", NULL, NULL, NULL, 04164 /* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1", 04165 /* A8 */ NULL, NULL, "pfsubr", NULL, 04166 /* AC */ NULL, NULL, "pfacc", NULL, 04167 /* B0 */ "pfcmpeq", NULL, NULL, NULL, 04168 /* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw", 04169 /* B8 */ NULL, NULL, NULL, "pswapd", 04170 /* BC */ NULL, NULL, NULL, "pavgusb", 04171 /* C0 */ NULL, NULL, NULL, NULL, 04172 /* C4 */ NULL, NULL, NULL, NULL, 04173 /* C8 */ NULL, NULL, NULL, NULL, 04174 /* CC */ NULL, NULL, NULL, NULL, 04175 /* D0 */ NULL, NULL, NULL, NULL, 04176 /* D4 */ NULL, NULL, NULL, NULL, 04177 /* D8 */ NULL, NULL, NULL, NULL, 04178 /* DC */ NULL, NULL, NULL, NULL, 04179 /* E0 */ NULL, NULL, NULL, NULL, 04180 /* E4 */ NULL, NULL, NULL, NULL, 04181 /* E8 */ NULL, NULL, NULL, NULL, 04182 /* EC */ NULL, NULL, NULL, NULL, 04183 /* F0 */ NULL, NULL, NULL, NULL, 04184 /* F4 */ NULL, NULL, NULL, NULL, 04185 /* F8 */ NULL, NULL, NULL, NULL, 04186 /* FC */ NULL, NULL, NULL, NULL, 04187 }; 04188 04189 static void 04190 OP_3DNowSuffix (bytemode, sizeflag) 04191 int bytemode ATTRIBUTE_UNUSED; 04192 int sizeflag ATTRIBUTE_UNUSED; 04193 { 04194 const char *mnemonic; 04195 04196 FETCH_DATA (the_info, codep + 1); 04197 /* AMD 3DNow! instructions are specified by an opcode suffix in the 04198 place where an 8-bit immediate would normally go. ie. the last 04199 byte of the instruction. */ 04200 obufp = obuf + strlen (obuf); 04201 mnemonic = Suffix3DNow[*codep++ & 0xff]; 04202 if (mnemonic) 04203 oappend (mnemonic); 04204 else 04205 { 04206 /* Since a variable sized modrm/sib chunk is between the start 04207 of the opcode (0x0f0f) and the opcode suffix, we need to do 04208 all the modrm processing first, and don't know until now that 04209 we have a bad opcode. This necessitates some cleaning up. */ 04210 op1out[0] = '\0'; 04211 op2out[0] = '\0'; 04212 BadOp (); 04213 } 04214 } 04215 04216 static const char *simd_cmp_op[] = { 04217 "eq", 04218 "lt", 04219 "le", 04220 "unord", 04221 "neq", 04222 "nlt", 04223 "nle", 04224 "ord" 04225 }; 04226 04227 static void 04228 OP_SIMD_Suffix (bytemode, sizeflag) 04229 int bytemode ATTRIBUTE_UNUSED; 04230 int sizeflag ATTRIBUTE_UNUSED; 04231 { 04232 unsigned int cmp_type; 04233 04234 FETCH_DATA (the_info, codep + 1); 04235 obufp = obuf + strlen (obuf); 04236 cmp_type = *codep++ & 0xff; 04237 if (cmp_type < 8) 04238 { 04239 char suffix1 = 'p', suffix2 = 's'; 04240 used_prefixes |= (prefixes & PREFIX_REPZ); 04241 if (prefixes & PREFIX_REPZ) 04242 suffix1 = 's'; 04243 else 04244 { 04245 used_prefixes |= (prefixes & PREFIX_DATA); 04246 if (prefixes & PREFIX_DATA) 04247 suffix2 = 'd'; 04248 else 04249 { 04250 used_prefixes |= (prefixes & PREFIX_REPNZ); 04251 if (prefixes & PREFIX_REPNZ) 04252 suffix1 = 's', suffix2 = 'd'; 04253 } 04254 } 04255 sprintf (scratchbuf, "cmp%s%c%c", 04256 simd_cmp_op[cmp_type], suffix1, suffix2); 04257 used_prefixes |= (prefixes & PREFIX_REPZ); 04258 oappend (scratchbuf); 04259 } 04260 else 04261 { 04262 /* We have a bad extension byte. Clean up. */ 04263 op1out[0] = '\0'; 04264 op2out[0] = '\0'; 04265 BadOp (); 04266 } 04267 } 04268 04269 static void 04270 SIMD_Fixup (extrachar, sizeflag) 04271 int extrachar; 04272 int sizeflag ATTRIBUTE_UNUSED; 04273 { 04274 /* Change movlps/movhps to movhlps/movlhps for 2 register operand 04275 forms of these instructions. */ 04276 if (mod == 3) 04277 { 04278 char *p = obuf + strlen (obuf); 04279 *(p + 1) = '\0'; 04280 *p = *(p - 1); 04281 *(p - 1) = *(p - 2); 04282 *(p - 2) = *(p - 3); 04283 *(p - 3) = extrachar; 04284 } 04285 } 04286 04287 static void 04288 BadOp (void) 04289 { 04290 /* Throw away prefixes and 1st. opcode byte. */ 04291 codep = insn_codep + 1; 04292 oappend ("(bad)"); 04293 } Generated on Sun May 27 2012 04:37:28 for ReactOS by
1.7.6.1
|