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