Bug Summary

File:src/gnu/usr.bin/binutils/opcodes/i386-dis.c
Warning:line 3626, column 4
Value stored to 'mask' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name i386-dis.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/binutils/obj/opcodes -resource-dir /usr/local/lib/clang/13.0.0 -D HAVE_CONFIG_H -I . -I /usr/src/gnu/usr.bin/binutils/opcodes -I . -D _GNU_SOURCE -I . -I /usr/src/gnu/usr.bin/binutils/opcodes -I ../bfd -I /usr/src/gnu/usr.bin/binutils/opcodes/../include -I /usr/src/gnu/usr.bin/binutils/opcodes/../bfd -I /usr/src/gnu/usr.bin/binutils/opcodes/../intl -I ../intl -D PIE_DEFAULT=1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.bin/binutils/obj/opcodes -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.bin/binutils/opcodes/i386-dis.c
1/* Print i386 instructions for GDB, the GNU debugger.
2 Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21/*
22 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
23 * July 1988
24 * modified by John Hassey (hassey@dg-rtp.dg.com)
25 * x86-64 support added by Jan Hubicka (jh@suse.cz)
26 * VIA PadLock support by Michal Ludvig (mludvig@suse.cz)
27 */
28
29/*
30 * The main tables describing the instructions is essentially a copy
31 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
32 * Programmers Manual. Usually, there is a capital letter, followed
33 * by a small letter. The capital letter tell the addressing mode,
34 * and the small letter tells about the operand size. Refer to
35 * the Intel manual for details.
36 */
37
38#include "dis-asm.h"
39#include "sysdep.h"
40#include "opintl.h"
41
42#define MAXLEN20 20
43
44#include <setjmp.h>
45
46#ifndef UNIXWARE_COMPAT1
47/* Set non-zero for broken, compatible instructions. Set to zero for
48 non-broken opcodes. */
49#define UNIXWARE_COMPAT1 1
50#endif
51
52static int fetch_data (struct disassemble_info *, bfd_byte *);
53static void ckprefix (void);
54static const char *prefix_name (int, int);
55static int print_insn (bfd_vma, disassemble_info *);
56static void dofloat (int);
57static void OP_ST (int, int);
58static void OP_STi (int, int);
59static int putop (const char *, int);
60static void oappend (const char *);
61static void append_seg (void);
62static void OP_indirE (int, int);
63static void print_operand_value (char *, int, bfd_vma);
64static void OP_E (int, int);
65static void OP_G (int, int);
66static bfd_vma get64 (void);
67static bfd_signed_vma get32 (void);
68static bfd_signed_vma get32s (void);
69static int get16 (void);
70static void set_op (bfd_vma, int);
71static void OP_REG (int, int);
72static void OP_IMREG (int, int);
73static void OP_I (int, int);
74static void OP_I64 (int, int);
75static void OP_sI (int, int);
76static void OP_J (int, int);
77static void OP_SEG (int, int);
78static void OP_DIR (int, int);
79static void OP_OFF (int, int);
80static void OP_OFF64 (int, int);
81static void ptr_reg (int, int);
82static void OP_ESreg (int, int);
83static void OP_DSreg (int, int);
84static void OP_C (int, int);
85static void OP_D (int, int);
86static void OP_T (int, int);
87static void OP_Rd (int, int);
88static void OP_MMX (int, int);
89static void OP_XMM (int, int);
90static void OP_EM (int, int);
91static void OP_EX (int, int);
92static void OP_MS (int, int);
93static void OP_XS (int, int);
94static void OP_M (int, int);
95static void OP_0fae (int, int);
96static void NOP_Fixup (int, int);
97static void OP_3DNowSuffix (int, int);
98static void OP_xcrypt2 (int, int);
99static void OP_xcrypt (int, int);
100static void OP_SIMD_Suffix (int, int);
101static void SIMD_Fixup (int, int);
102static void PNI_Fixup (int, int);
103static void XCR_Fixup (int, int);
104static void INVLPG_Fixup (int, int);
105static void OP_0f38 (int, int);
106static void OP_0f3a (int, int);
107static void BadOp (void);
108
109struct dis_private {
110 /* Points to first byte not fetched. */
111 bfd_byte *max_fetched;
112 bfd_byte the_buffer[MAXLEN20];
113 bfd_vma insn_start;
114 int orig_sizeflag;
115 jmp_buf bailout;
116};
117
118/* The opcode for the fwait instruction, which we treat as a prefix
119 when we can. */
120#define FWAIT_OPCODE(0x9b) (0x9b)
121
122/* Set to 1 for 64bit mode disassembly. */
123static int mode_64bit;
124
125/* Flags for the prefixes for the current instruction. See below. */
126static int prefixes;
127
128/* REX prefix the current instruction. See below. */
129static int rex;
130/* Bits of REX we've already used. */
131static int rex_used;
132#define REX_MODE648 8
133#define REX_EXTX4 4
134#define REX_EXTY2 2
135#define REX_EXTZ1 1
136/* Mark parts used in the REX prefix. When we are testing for
137 empty prefix (for 8bit register REX extension), just mask it
138 out. Otherwise test for REX bit is excuse for existence of REX
139 only in case value is nonzero. */
140#define USED_REX(value){ if (value) rex_used |= (rex & value) ? (value) | 0x40 :
0; else rex_used |= 0x40; }
\
141 { \
142 if (value) \
143 rex_used |= (rex & value) ? (value) | 0x40 : 0; \
144 else \
145 rex_used |= 0x40; \
146 }
147
148/* Flags for prefixes which we somehow handled when printing the
149 current instruction. */
150static int used_prefixes;
151
152/* Flags stored in PREFIXES. */
153#define PREFIX_REPZ1 1
154#define PREFIX_REPNZ2 2
155#define PREFIX_LOCK4 4
156#define PREFIX_CS8 8
157#define PREFIX_SS0x10 0x10
158#define PREFIX_DS0x20 0x20
159#define PREFIX_ES0x40 0x40
160#define PREFIX_FS0x80 0x80
161#define PREFIX_GS0x100 0x100
162#define PREFIX_DATA0x200 0x200
163#define PREFIX_ADDR0x400 0x400
164#define PREFIX_FWAIT0x800 0x800
165
166/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
167 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
168 on error. */
169#define FETCH_DATA(info, addr)((addr) <= ((struct dis_private *) (info->private_data)
)->max_fetched ? 1 : fetch_data ((info), (addr)))
\
170 ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
171 ? 1 : fetch_data ((info), (addr)))
172
173static int
174fetch_data (struct disassemble_info *info, bfd_byte *addr)
175{
176 int status;
177 struct dis_private *priv = (struct dis_private *) info->private_data;
178 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
179
180 status = (*info->read_memory_func) (start,
181 priv->max_fetched,
182 addr - priv->max_fetched,
183 info);
184 if (status != 0)
185 {
186 /* If we did manage to read at least one byte, then
187 print_insn_i386 will do something sensible. Otherwise, print
188 an error. We do that here because this is where we know
189 STATUS. */
190 if (priv->max_fetched == priv->the_buffer)
191 (*info->memory_error_func) (status, start, info);
192 longjmp (priv->bailout, 1);
193 }
194 else
195 priv->max_fetched = addr;
196 return 1;
197}
198
199#define XX((void *)0), 0 NULL((void *)0), 0
200
201#define EbOP_E, 1 OP_E, b_mode1
202#define EvOP_E, 2 OP_E, v_mode2
203#define EdOP_E, 4 OP_E, d_mode4
204#define EdqOP_E, 10 OP_E, dq_mode10
205#define indirEbOP_indirE, 1 OP_indirE, b_mode1
206#define indirEvOP_indirE, 2 OP_indirE, v_mode2
207#define EwOP_E, 3 OP_E, w_mode3
208#define MaOP_E, 2 OP_E, v_mode2
209#define MOP_M, 0 OP_M, 0 /* lea, lgdt, etc. */
210#define MpOP_M, 0 OP_M, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
211#define GbOP_G, 1 OP_G, b_mode1
212#define GvOP_G, 2 OP_G, v_mode2
213#define GdOP_G, 4 OP_G, d_mode4
214#define GwOP_G, 3 OP_G, w_mode3
215#define RdOP_Rd, 4 OP_Rd, d_mode4
216#define RmOP_Rd, 7 OP_Rd, m_mode7
217#define IbOP_I, 1 OP_I, b_mode1
218#define sIbOP_sI, 1 OP_sI, b_mode1 /* sign extened byte */
219#define IvOP_I, 2 OP_I, v_mode2
220#define IqOP_I, 5 OP_I, q_mode5
221#define Iv64OP_I64, 2 OP_I64, v_mode2
222#define IwOP_I, 3 OP_I, w_mode3
223#define JbOP_J, 1 OP_J, b_mode1
224#define JvOP_J, 2 OP_J, v_mode2
225#define CmOP_C, 7 OP_C, m_mode7
226#define DmOP_D, 7 OP_D, m_mode7
227#define TdOP_T, 4 OP_T, d_mode4
228
229#define RMeAXOP_REG, 108 OP_REG, eAX_reg108
230#define RMeBXOP_REG, 111 OP_REG, eBX_reg111
231#define RMeCXOP_REG, 109 OP_REG, eCX_reg109
232#define RMeDXOP_REG, 110 OP_REG, eDX_reg110
233#define RMeSPOP_REG, 112 OP_REG, eSP_reg112
234#define RMeBPOP_REG, 113 OP_REG, eBP_reg113
235#define RMeSIOP_REG, 114 OP_REG, eSI_reg114
236#define RMeDIOP_REG, 115 OP_REG, eDI_reg115
237#define RMrAXOP_REG, 132 OP_REG, rAX_reg132
238#define RMrBXOP_REG, 135 OP_REG, rBX_reg135
239#define RMrCXOP_REG, 133 OP_REG, rCX_reg133
240#define RMrDXOP_REG, 134 OP_REG, rDX_reg134
241#define RMrSPOP_REG, 136 OP_REG, rSP_reg136
242#define RMrBPOP_REG, 137 OP_REG, rBP_reg137
243#define RMrSIOP_REG, 138 OP_REG, rSI_reg138
244#define RMrDIOP_REG, 139 OP_REG, rDI_reg139
245#define RMALOP_REG, 116 OP_REG, al_reg116
246#define RMALOP_REG, 116 OP_REG, al_reg116
247#define RMCLOP_REG, 117 OP_REG, cl_reg117
248#define RMDLOP_REG, 118 OP_REG, dl_reg118
249#define RMBLOP_REG, 119 OP_REG, bl_reg119
250#define RMAHOP_REG, 120 OP_REG, ah_reg120
251#define RMCHOP_REG, 121 OP_REG, ch_reg121
252#define RMDHOP_REG, 122 OP_REG, dh_reg122
253#define RMBHOP_REG, 123 OP_REG, bh_reg123
254#define RMAXOP_REG, 124 OP_REG, ax_reg124
255#define RMDXOP_REG, 126 OP_REG, dx_reg126
256
257#define eAXOP_IMREG, 108 OP_IMREG, eAX_reg108
258#define eBXOP_IMREG, 111 OP_IMREG, eBX_reg111
259#define eCXOP_IMREG, 109 OP_IMREG, eCX_reg109
260#define eDXOP_IMREG, 110 OP_IMREG, eDX_reg110
261#define eSPOP_IMREG, 112 OP_IMREG, eSP_reg112
262#define eBPOP_IMREG, 113 OP_IMREG, eBP_reg113
263#define eSIOP_IMREG, 114 OP_IMREG, eSI_reg114
264#define eDIOP_IMREG, 115 OP_IMREG, eDI_reg115
265#define ALOP_IMREG, 116 OP_IMREG, al_reg116
266#define ALOP_IMREG, 116 OP_IMREG, al_reg116
267#define CLOP_IMREG, 117 OP_IMREG, cl_reg117
268#define DLOP_IMREG, 118 OP_IMREG, dl_reg118
269#define BLOP_IMREG, 119 OP_IMREG, bl_reg119
270#define AHOP_IMREG, 120 OP_IMREG, ah_reg120
271#define CHOP_IMREG, 121 OP_IMREG, ch_reg121
272#define DHOP_IMREG, 122 OP_IMREG, dh_reg122
273#define BHOP_IMREG, 123 OP_IMREG, bh_reg123
274#define AXOP_IMREG, 124 OP_IMREG, ax_reg124
275#define DXOP_IMREG, 126 OP_IMREG, dx_reg126
276#define indirDXOP_IMREG, 150 OP_IMREG, indir_dx_reg150
277
278#define SwOP_SEG, 3 OP_SEG, w_mode3
279#define ApOP_DIR, 0 OP_DIR, 0
280#define ObOP_OFF, 1 OP_OFF, b_mode1
281#define Ob64OP_OFF64, 1 OP_OFF64, b_mode1
282#define OvOP_OFF, 2 OP_OFF, v_mode2
283#define Ov64OP_OFF64, 2 OP_OFF64, v_mode2
284#define XbOP_DSreg, 114 OP_DSreg, eSI_reg114
285#define XvOP_DSreg, 114 OP_DSreg, eSI_reg114
286#define YbOP_ESreg, 115 OP_ESreg, eDI_reg115
287#define YvOP_ESreg, 115 OP_ESreg, eDI_reg115
288#define DSBXOP_DSreg, 111 OP_DSreg, eBX_reg111
289
290#define esOP_REG, 100 OP_REG, es_reg100
291#define ssOP_REG, 102 OP_REG, ss_reg102
292#define csOP_REG, 101 OP_REG, cs_reg101
293#define dsOP_REG, 103 OP_REG, ds_reg103
294#define fsOP_REG, 104 OP_REG, fs_reg104
295#define gsOP_REG, 105 OP_REG, gs_reg105
296
297#define MXOP_MMX, 0 OP_MMX, 0
298#define XMOP_XMM, 0 OP_XMM, 0
299#define EMOP_EM, 2 OP_EM, v_mode2
300#define EXOP_EX, 2 OP_EX, v_mode2
301#define MSOP_MS, 2 OP_MS, v_mode2
302#define XSOP_XS, 2 OP_XS, v_mode2
303#define OPSUFOP_3DNowSuffix, 0 OP_3DNowSuffix, 0
304#define OPXCRYPTOP_xcrypt, 0 OP_xcrypt, 0
305#define OPXCRYPT2OP_xcrypt2, 0 OP_xcrypt2, 0
306#define OPSIMDOP_SIMD_Suffix, 0 OP_SIMD_Suffix, 0
307#define OP0F38OP_0f38, 0 OP_0f38, 0
308#define OP0F3AOP_0f3a, 0 OP_0f3a, 0
309
310#define cond_jump_flag((void *)0), 8 NULL((void *)0), cond_jump_mode8
311#define loop_jcxz_flag((void *)0), 9 NULL((void *)0), loop_jcxz_mode9
312
313/* bits in sizeflag */
314#define SUFFIX_ALWAYS4 4
315#define AFLAG2 2
316#define DFLAG1 1
317
318#define b_mode1 1 /* byte operand */
319#define v_mode2 2 /* operand size depends on prefixes */
320#define w_mode3 3 /* word operand */
321#define d_mode4 4 /* double word operand */
322#define q_mode5 5 /* quad word operand */
323#define x_mode6 6
324#define m_mode7 7 /* d_mode in 32bit, q_mode in 64bit mode. */
325#define cond_jump_mode8 8
326#define loop_jcxz_mode9 9
327#define dq_mode10 10 /* operand size depends on REX prefixes. */
328
329#define es_reg100 100
330#define cs_reg101 101
331#define ss_reg102 102
332#define ds_reg103 103
333#define fs_reg104 104
334#define gs_reg105 105
335
336#define eAX_reg108 108
337#define eCX_reg109 109
338#define eDX_reg110 110
339#define eBX_reg111 111
340#define eSP_reg112 112
341#define eBP_reg113 113
342#define eSI_reg114 114
343#define eDI_reg115 115
344
345#define al_reg116 116
346#define cl_reg117 117
347#define dl_reg118 118
348#define bl_reg119 119
349#define ah_reg120 120
350#define ch_reg121 121
351#define dh_reg122 122
352#define bh_reg123 123
353
354#define ax_reg124 124
355#define cx_reg125 125
356#define dx_reg126 126
357#define bx_reg127 127
358#define sp_reg128 128
359#define bp_reg129 129
360#define si_reg130 130
361#define di_reg131 131
362
363#define rAX_reg132 132
364#define rCX_reg133 133
365#define rDX_reg134 134
366#define rBX_reg135 135
367#define rSP_reg136 136
368#define rBP_reg137 137
369#define rSI_reg138 138
370#define rDI_reg139 139
371
372#define indir_dx_reg150 150
373
374#define FLOATCODE1 1
375#define USE_GROUPS2 2
376#define USE_PREFIX_USER_TABLE3 3
377#define X86_64_SPECIAL4 4
378
379#define FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), FLOATCODE1, NULL((void *)0), 0, NULL((void *)0), 0
380
381#define GRP1b((void *)0), ((void *)0), 2, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 0, NULL((void *)0), 0
382#define GRP1S((void *)0), ((void *)0), 2, ((void *)0), 1, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 1, NULL((void *)0), 0
383#define GRP1Ss((void *)0), ((void *)0), 2, ((void *)0), 2, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 2, NULL((void *)0), 0
384#define GRP2b((void *)0), ((void *)0), 2, ((void *)0), 3, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 3, NULL((void *)0), 0
385#define GRP2S((void *)0), ((void *)0), 2, ((void *)0), 4, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 4, NULL((void *)0), 0
386#define GRP2b_one((void *)0), ((void *)0), 2, ((void *)0), 5, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 5, NULL((void *)0), 0
387#define GRP2S_one((void *)0), ((void *)0), 2, ((void *)0), 6, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 6, NULL((void *)0), 0
388#define GRP2b_cl((void *)0), ((void *)0), 2, ((void *)0), 7, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 7, NULL((void *)0), 0
389#define GRP2S_cl((void *)0), ((void *)0), 2, ((void *)0), 8, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 8, NULL((void *)0), 0
390#define GRP3b((void *)0), ((void *)0), 2, ((void *)0), 9, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 9, NULL((void *)0), 0
391#define GRP3S((void *)0), ((void *)0), 2, ((void *)0), 10, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 10, NULL((void *)0), 0
392#define GRP4((void *)0), ((void *)0), 2, ((void *)0), 11, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 11, NULL((void *)0), 0
393#define GRP5((void *)0), ((void *)0), 2, ((void *)0), 12, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 12, NULL((void *)0), 0
394#define GRP6((void *)0), ((void *)0), 2, ((void *)0), 13, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 13, NULL((void *)0), 0
395#define GRP7((void *)0), ((void *)0), 2, ((void *)0), 14, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 14, NULL((void *)0), 0
396#define GRP8((void *)0), ((void *)0), 2, ((void *)0), 15, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 15, NULL((void *)0), 0
397#define GRP9((void *)0), ((void *)0), 2, ((void *)0), 16, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 16, NULL((void *)0), 0
398#define GRP10((void *)0), ((void *)0), 2, ((void *)0), 17, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 17, NULL((void *)0), 0
399#define GRP11((void *)0), ((void *)0), 2, ((void *)0), 18, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 18, NULL((void *)0), 0
400#define GRP12((void *)0), ((void *)0), 2, ((void *)0), 19, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 19, NULL((void *)0), 0
401#define GRP13((void *)0), ((void *)0), 2, ((void *)0), 20, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 20, NULL((void *)0), 0
402#define GRP14((void *)0), ((void *)0), 2, ((void *)0), 21, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 21, NULL((void *)0), 0
403#define GRPAMD((void *)0), ((void *)0), 2, ((void *)0), 22, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_GROUPS2, NULL((void *)0), 22, NULL((void *)0), 0
404
405#define PREGRP0((void *)0), ((void *)0), 3, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 0, NULL((void *)0), 0
406#define PREGRP1((void *)0), ((void *)0), 3, ((void *)0), 1, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 1, NULL((void *)0), 0
407#define PREGRP2((void *)0), ((void *)0), 3, ((void *)0), 2, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 2, NULL((void *)0), 0
408#define PREGRP3((void *)0), ((void *)0), 3, ((void *)0), 3, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 3, NULL((void *)0), 0
409#define PREGRP4((void *)0), ((void *)0), 3, ((void *)0), 4, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 4, NULL((void *)0), 0
410#define PREGRP5((void *)0), ((void *)0), 3, ((void *)0), 5, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 5, NULL((void *)0), 0
411#define PREGRP6((void *)0), ((void *)0), 3, ((void *)0), 6, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 6, NULL((void *)0), 0
412#define PREGRP7((void *)0), ((void *)0), 3, ((void *)0), 7, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 7, NULL((void *)0), 0
413#define PREGRP8((void *)0), ((void *)0), 3, ((void *)0), 8, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 8, NULL((void *)0), 0
414#define PREGRP9((void *)0), ((void *)0), 3, ((void *)0), 9, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 9, NULL((void *)0), 0
415#define PREGRP10((void *)0), ((void *)0), 3, ((void *)0), 10, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 10, NULL((void *)0), 0
416#define PREGRP11((void *)0), ((void *)0), 3, ((void *)0), 11, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 11, NULL((void *)0), 0
417#define PREGRP12((void *)0), ((void *)0), 3, ((void *)0), 12, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 12, NULL((void *)0), 0
418#define PREGRP13((void *)0), ((void *)0), 3, ((void *)0), 13, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 13, NULL((void *)0), 0
419#define PREGRP14((void *)0), ((void *)0), 3, ((void *)0), 14, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 14, NULL((void *)0), 0
420#define PREGRP15((void *)0), ((void *)0), 3, ((void *)0), 15, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 15, NULL((void *)0), 0
421#define PREGRP16((void *)0), ((void *)0), 3, ((void *)0), 16, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 16, NULL((void *)0), 0
422#define PREGRP17((void *)0), ((void *)0), 3, ((void *)0), 17, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 17, NULL((void *)0), 0
423#define PREGRP18((void *)0), ((void *)0), 3, ((void *)0), 18, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 18, NULL((void *)0), 0
424#define PREGRP19((void *)0), ((void *)0), 3, ((void *)0), 19, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 19, NULL((void *)0), 0
425#define PREGRP20((void *)0), ((void *)0), 3, ((void *)0), 20, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 20, NULL((void *)0), 0
426#define PREGRP21((void *)0), ((void *)0), 3, ((void *)0), 21, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 21, NULL((void *)0), 0
427#define PREGRP22((void *)0), ((void *)0), 3, ((void *)0), 22, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 22, NULL((void *)0), 0
428#define PREGRP23((void *)0), ((void *)0), 3, ((void *)0), 23, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 23, NULL((void *)0), 0
429#define PREGRP24((void *)0), ((void *)0), 3, ((void *)0), 24, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 24, NULL((void *)0), 0
430#define PREGRP25((void *)0), ((void *)0), 3, ((void *)0), 25, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 25, NULL((void *)0), 0
431#define PREGRP26((void *)0), ((void *)0), 3, ((void *)0), 26, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 26, NULL((void *)0), 0
432#define PREGRP27((void *)0), ((void *)0), 3, ((void *)0), 27, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 27, NULL((void *)0), 0
433#define PREGRP28((void *)0), ((void *)0), 3, ((void *)0), 28, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 28, NULL((void *)0), 0
434#define PREGRP29((void *)0), ((void *)0), 3, ((void *)0), 29, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 29, NULL((void *)0), 0
435#define PREGRP30((void *)0), ((void *)0), 3, ((void *)0), 30, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 30, NULL((void *)0), 0
436#define PREGRP31((void *)0), ((void *)0), 3, ((void *)0), 31, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 31, NULL((void *)0), 0
437#define PREGRP32((void *)0), ((void *)0), 3, ((void *)0), 32, ((void *)0), 0 NULL((void *)0), NULL((void *)0), USE_PREFIX_USER_TABLE3, NULL((void *)0), 32, NULL((void *)0), 0
438
439#define X86_64_0((void *)0), ((void *)0), 4, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), X86_64_SPECIAL4, NULL((void *)0), 0, NULL((void *)0), 0
440
441typedef void (*op_rtn) (int bytemode, int sizeflag);
442
443struct dis386 {
444 const char *name;
445 op_rtn op1;
446 int bytemode1;
447 op_rtn op2;
448 int bytemode2;
449 op_rtn op3;
450 int bytemode3;
451};
452
453/* Upper case letters in the instruction names here are macros.
454 'A' => print 'b' if no register operands or suffix_always is true
455 'B' => print 'b' if suffix_always is true
456 'E' => print 'e' if 32-bit form of jcxz
457 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
458 'H' => print ",pt" or ",pn" branch hint
459 'L' => print 'l' if suffix_always is true
460 'N' => print 'n' if instruction has no wait "prefix"
461 'O' => print 'd', or 'o'
462 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
463 . or suffix_always is true. print 'q' if rex prefix is present.
464 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
465 . is true
466 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
467 'S' => print 'w', 'l' or 'q' if suffix_always is true
468 'T' => print 'q' in 64bit mode and behave as 'P' otherwise
469 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
470 'X' => print 's', 'd' depending on data16 prefix (for XMM)
471 'W' => print 'b' or 'w' ("w" or "de" in intel mode)
472 'Y' => 'q' if instruction has an REX 64bit overwrite prefix
473
474 Many of the above letters print nothing in Intel mode. See "putop"
475 for the details.
476
477 Braces '{' and '}', and vertical bars '|', indicate alternative
478 mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
479 modes. In cases where there are only two alternatives, the X86_64
480 instruction is reserved, and "(bad)" is printed.
481*/
482
483static const struct dis386 dis386[] = {
484 /* 00 */
485 { "addB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
486 { "addS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
487 { "addB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
488 { "addS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
489 { "addB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
490 { "addS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
491 { "push{T|}", esOP_REG, 100, XX((void *)0), 0, XX((void *)0), 0 },
492 { "pop{T|}", esOP_REG, 100, XX((void *)0), 0, XX((void *)0), 0 },
493 /* 08 */
494 { "orB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
495 { "orS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
496 { "orB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
497 { "orS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
498 { "orB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
499 { "orS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
500 { "push{T|}", csOP_REG, 101, XX((void *)0), 0, XX((void *)0), 0 },
501 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* 0x0f extended opcode escape */
502 /* 10 */
503 { "adcB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
504 { "adcS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
505 { "adcB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
506 { "adcS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
507 { "adcB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
508 { "adcS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
509 { "push{T|}", ssOP_REG, 102, XX((void *)0), 0, XX((void *)0), 0 },
510 { "popT|}", ssOP_REG, 102, XX((void *)0), 0, XX((void *)0), 0 },
511 /* 18 */
512 { "sbbB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
513 { "sbbS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
514 { "sbbB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
515 { "sbbS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
516 { "sbbB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
517 { "sbbS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
518 { "push{T|}", dsOP_REG, 103, XX((void *)0), 0, XX((void *)0), 0 },
519 { "pop{T|}", dsOP_REG, 103, XX((void *)0), 0, XX((void *)0), 0 },
520 /* 20 */
521 { "andB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
522 { "andS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
523 { "andB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
524 { "andS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
525 { "andB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
526 { "andS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
527 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* SEG ES prefix */
528 { "daa{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
529 /* 28 */
530 { "subB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
531 { "subS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
532 { "subB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
533 { "subS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
534 { "subB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
535 { "subS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
536 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* SEG CS prefix */
537 { "das{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
538 /* 30 */
539 { "xorB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
540 { "xorS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
541 { "xorB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
542 { "xorS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
543 { "xorB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
544 { "xorS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
545 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* SEG SS prefix */
546 { "aaa{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
547 /* 38 */
548 { "cmpB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
549 { "cmpS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
550 { "cmpB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
551 { "cmpS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
552 { "cmpB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
553 { "cmpS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
554 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* SEG DS prefix */
555 { "aas{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
556 /* 40 */
557 { "inc{S|}", RMeAXOP_REG, 108, XX((void *)0), 0, XX((void *)0), 0 },
558 { "inc{S|}", RMeCXOP_REG, 109, XX((void *)0), 0, XX((void *)0), 0 },
559 { "inc{S|}", RMeDXOP_REG, 110, XX((void *)0), 0, XX((void *)0), 0 },
560 { "inc{S|}", RMeBXOP_REG, 111, XX((void *)0), 0, XX((void *)0), 0 },
561 { "inc{S|}", RMeSPOP_REG, 112, XX((void *)0), 0, XX((void *)0), 0 },
562 { "inc{S|}", RMeBPOP_REG, 113, XX((void *)0), 0, XX((void *)0), 0 },
563 { "inc{S|}", RMeSIOP_REG, 114, XX((void *)0), 0, XX((void *)0), 0 },
564 { "inc{S|}", RMeDIOP_REG, 115, XX((void *)0), 0, XX((void *)0), 0 },
565 /* 48 */
566 { "dec{S|}", RMeAXOP_REG, 108, XX((void *)0), 0, XX((void *)0), 0 },
567 { "dec{S|}", RMeCXOP_REG, 109, XX((void *)0), 0, XX((void *)0), 0 },
568 { "dec{S|}", RMeDXOP_REG, 110, XX((void *)0), 0, XX((void *)0), 0 },
569 { "dec{S|}", RMeBXOP_REG, 111, XX((void *)0), 0, XX((void *)0), 0 },
570 { "dec{S|}", RMeSPOP_REG, 112, XX((void *)0), 0, XX((void *)0), 0 },
571 { "dec{S|}", RMeBPOP_REG, 113, XX((void *)0), 0, XX((void *)0), 0 },
572 { "dec{S|}", RMeSIOP_REG, 114, XX((void *)0), 0, XX((void *)0), 0 },
573 { "dec{S|}", RMeDIOP_REG, 115, XX((void *)0), 0, XX((void *)0), 0 },
574 /* 50 */
575 { "pushS", RMrAXOP_REG, 132, XX((void *)0), 0, XX((void *)0), 0 },
576 { "pushS", RMrCXOP_REG, 133, XX((void *)0), 0, XX((void *)0), 0 },
577 { "pushS", RMrDXOP_REG, 134, XX((void *)0), 0, XX((void *)0), 0 },
578 { "pushS", RMrBXOP_REG, 135, XX((void *)0), 0, XX((void *)0), 0 },
579 { "pushS", RMrSPOP_REG, 136, XX((void *)0), 0, XX((void *)0), 0 },
580 { "pushS", RMrBPOP_REG, 137, XX((void *)0), 0, XX((void *)0), 0 },
581 { "pushS", RMrSIOP_REG, 138, XX((void *)0), 0, XX((void *)0), 0 },
582 { "pushS", RMrDIOP_REG, 139, XX((void *)0), 0, XX((void *)0), 0 },
583 /* 58 */
584 { "popS", RMrAXOP_REG, 132, XX((void *)0), 0, XX((void *)0), 0 },
585 { "popS", RMrCXOP_REG, 133, XX((void *)0), 0, XX((void *)0), 0 },
586 { "popS", RMrDXOP_REG, 134, XX((void *)0), 0, XX((void *)0), 0 },
587 { "popS", RMrBXOP_REG, 135, XX((void *)0), 0, XX((void *)0), 0 },
588 { "popS", RMrSPOP_REG, 136, XX((void *)0), 0, XX((void *)0), 0 },
589 { "popS", RMrBPOP_REG, 137, XX((void *)0), 0, XX((void *)0), 0 },
590 { "popS", RMrSIOP_REG, 138, XX((void *)0), 0, XX((void *)0), 0 },
591 { "popS", RMrDIOP_REG, 139, XX((void *)0), 0, XX((void *)0), 0 },
592 /* 60 */
593 { "pusha{P|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
594 { "popa{P|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
595 { "bound{S|}", GvOP_G, 2, MaOP_E, 2, XX((void *)0), 0 },
596 { X86_64_0((void *)0), ((void *)0), 4, ((void *)0), 0, ((void *)0), 0 },
597 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* seg fs */
598 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* seg gs */
599 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* op size prefix */
600 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* adr size prefix */
601 /* 68 */
602 { "pushT", IqOP_I, 5, XX((void *)0), 0, XX((void *)0), 0 },
603 { "imulS", GvOP_G, 2, EvOP_E, 2, IvOP_I, 2 },
604 { "pushT", sIbOP_sI, 1, XX((void *)0), 0, XX((void *)0), 0 },
605 { "imulS", GvOP_G, 2, EvOP_E, 2, sIbOP_sI, 1 },
606 { "ins{b||b|}", YbOP_ESreg, 115, indirDXOP_IMREG, 150, XX((void *)0), 0 },
607 { "ins{R||R|}", YvOP_ESreg, 115, indirDXOP_IMREG, 150, XX((void *)0), 0 },
608 { "outs{b||b|}", indirDXOP_IMREG, 150, XbOP_DSreg, 114, XX((void *)0), 0 },
609 { "outs{R||R|}", indirDXOP_IMREG, 150, XvOP_DSreg, 114, XX((void *)0), 0 },
610 /* 70 */
611 { "joH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
612 { "jnoH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
613 { "jbH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
614 { "jaeH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
615 { "jeH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
616 { "jneH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
617 { "jbeH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
618 { "jaH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
619 /* 78 */
620 { "jsH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
621 { "jnsH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
622 { "jpH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
623 { "jnpH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
624 { "jlH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
625 { "jgeH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
626 { "jleH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
627 { "jgH", JbOP_J, 1, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
628 /* 80 */
629 { GRP1b((void *)0), ((void *)0), 2, ((void *)0), 0, ((void *)0), 0 },
630 { GRP1S((void *)0), ((void *)0), 2, ((void *)0), 1, ((void *)0), 0 },
631 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
632 { GRP1Ss((void *)0), ((void *)0), 2, ((void *)0), 2, ((void *)0), 0 },
633 { "testB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
634 { "testS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
635 { "xchgB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
636 { "xchgS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
637 /* 88 */
638 { "movB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
639 { "movS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
640 { "movB", GbOP_G, 1, EbOP_E, 1, XX((void *)0), 0 },
641 { "movS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
642 { "movQ", EvOP_E, 2, SwOP_SEG, 3, XX((void *)0), 0 },
643 { "leaS", GvOP_G, 2, MOP_M, 0, XX((void *)0), 0 },
644 { "movQ", SwOP_SEG, 3, EvOP_E, 2, XX((void *)0), 0 },
645 { "popU", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
646 /* 90 */
647 { "nop", NOP_Fixup, 0, XX((void *)0), 0, XX((void *)0), 0 },
648 { "xchgS", RMeCXOP_REG, 109, eAXOP_IMREG, 108, XX((void *)0), 0 },
649 { "xchgS", RMeDXOP_REG, 110, eAXOP_IMREG, 108, XX((void *)0), 0 },
650 { "xchgS", RMeBXOP_REG, 111, eAXOP_IMREG, 108, XX((void *)0), 0 },
651 { "xchgS", RMeSPOP_REG, 112, eAXOP_IMREG, 108, XX((void *)0), 0 },
652 { "xchgS", RMeBPOP_REG, 113, eAXOP_IMREG, 108, XX((void *)0), 0 },
653 { "xchgS", RMeSIOP_REG, 114, eAXOP_IMREG, 108, XX((void *)0), 0 },
654 { "xchgS", RMeDIOP_REG, 115, eAXOP_IMREG, 108, XX((void *)0), 0 },
655 /* 98 */
656 { "cW{tR||tR|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
657 { "cR{tO||tO|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
658 { "lcall{T|}", ApOP_DIR, 0, XX((void *)0), 0, XX((void *)0), 0 },
659 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* fwait */
660 { "pushfT", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
661 { "popfT", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
662 { "sahf{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
663 { "lahf{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
664 /* a0 */
665 { "movB", ALOP_IMREG, 116, Ob64OP_OFF64, 1, XX((void *)0), 0 },
666 { "movS", eAXOP_IMREG, 108, Ov64OP_OFF64, 2, XX((void *)0), 0 },
667 { "movB", Ob64OP_OFF64, 1, ALOP_IMREG, 116, XX((void *)0), 0 },
668 { "movS", Ov64OP_OFF64, 2, eAXOP_IMREG, 108, XX((void *)0), 0 },
669 { "movs{b||b|}", YbOP_ESreg, 115, XbOP_DSreg, 114, XX((void *)0), 0 },
670 { "movs{R||R|}", YvOP_ESreg, 115, XvOP_DSreg, 114, XX((void *)0), 0 },
671 { "cmps{b||b|}", XbOP_DSreg, 114, YbOP_ESreg, 115, XX((void *)0), 0 },
672 { "cmps{R||R|}", XvOP_DSreg, 114, YvOP_ESreg, 115, XX((void *)0), 0 },
673 /* a8 */
674 { "testB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
675 { "testS", eAXOP_IMREG, 108, IvOP_I, 2, XX((void *)0), 0 },
676 { "stosB", YbOP_ESreg, 115, ALOP_IMREG, 116, XX((void *)0), 0 },
677 { "stosS", YvOP_ESreg, 115, eAXOP_IMREG, 108, XX((void *)0), 0 },
678 { "lodsB", ALOP_IMREG, 116, XbOP_DSreg, 114, XX((void *)0), 0 },
679 { "lodsS", eAXOP_IMREG, 108, XvOP_DSreg, 114, XX((void *)0), 0 },
680 { "scasB", ALOP_IMREG, 116, YbOP_ESreg, 115, XX((void *)0), 0 },
681 { "scasS", eAXOP_IMREG, 108, YvOP_ESreg, 115, XX((void *)0), 0 },
682 /* b0 */
683 { "movB", RMALOP_REG, 116, IbOP_I, 1, XX((void *)0), 0 },
684 { "movB", RMCLOP_REG, 117, IbOP_I, 1, XX((void *)0), 0 },
685 { "movB", RMDLOP_REG, 118, IbOP_I, 1, XX((void *)0), 0 },
686 { "movB", RMBLOP_REG, 119, IbOP_I, 1, XX((void *)0), 0 },
687 { "movB", RMAHOP_REG, 120, IbOP_I, 1, XX((void *)0), 0 },
688 { "movB", RMCHOP_REG, 121, IbOP_I, 1, XX((void *)0), 0 },
689 { "movB", RMDHOP_REG, 122, IbOP_I, 1, XX((void *)0), 0 },
690 { "movB", RMBHOP_REG, 123, IbOP_I, 1, XX((void *)0), 0 },
691 /* b8 */
692 { "movS", RMeAXOP_REG, 108, Iv64OP_I64, 2, XX((void *)0), 0 },
693 { "movS", RMeCXOP_REG, 109, Iv64OP_I64, 2, XX((void *)0), 0 },
694 { "movS", RMeDXOP_REG, 110, Iv64OP_I64, 2, XX((void *)0), 0 },
695 { "movS", RMeBXOP_REG, 111, Iv64OP_I64, 2, XX((void *)0), 0 },
696 { "movS", RMeSPOP_REG, 112, Iv64OP_I64, 2, XX((void *)0), 0 },
697 { "movS", RMeBPOP_REG, 113, Iv64OP_I64, 2, XX((void *)0), 0 },
698 { "movS", RMeSIOP_REG, 114, Iv64OP_I64, 2, XX((void *)0), 0 },
699 { "movS", RMeDIOP_REG, 115, Iv64OP_I64, 2, XX((void *)0), 0 },
700 /* c0 */
701 { GRP2b((void *)0), ((void *)0), 2, ((void *)0), 3, ((void *)0), 0 },
702 { GRP2S((void *)0), ((void *)0), 2, ((void *)0), 4, ((void *)0), 0 },
703 { "retT", IwOP_I, 3, XX((void *)0), 0, XX((void *)0), 0 },
704 { "retT", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
705 { "les{S|}", GvOP_G, 2, MpOP_M, 0, XX((void *)0), 0 },
706 { "ldsS", GvOP_G, 2, MpOP_M, 0, XX((void *)0), 0 },
707 { "movA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
708 { "movQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
709 /* c8 */
710 { "enterT", IwOP_I, 3, IbOP_I, 1, XX((void *)0), 0 },
711 { "leaveT", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
712 { "lretP", IwOP_I, 3, XX((void *)0), 0, XX((void *)0), 0 },
713 { "lretP", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
714 { "int3", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
715 { "int", IbOP_I, 1, XX((void *)0), 0, XX((void *)0), 0 },
716 { "into{|}", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
717 { "iretP", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
718 /* d0 */
719 { GRP2b_one((void *)0), ((void *)0), 2, ((void *)0), 5, ((void *)0), 0 },
720 { GRP2S_one((void *)0), ((void *)0), 2, ((void *)0), 6, ((void *)0), 0 },
721 { GRP2b_cl((void *)0), ((void *)0), 2, ((void *)0), 7, ((void *)0), 0 },
722 { GRP2S_cl((void *)0), ((void *)0), 2, ((void *)0), 8, ((void *)0), 0 },
723 { "aam{|}", sIbOP_sI, 1, XX((void *)0), 0, XX((void *)0), 0 },
724 { "aad{|}", sIbOP_sI, 1, XX((void *)0), 0, XX((void *)0), 0 },
725 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
726 { "xlat", DSBXOP_DSreg, 111, XX((void *)0), 0, XX((void *)0), 0 },
727 /* d8 */
728 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
729 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
730 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
731 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
732 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
733 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
734 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
735 { FLOAT((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
736 /* e0 */
737 { "loopneFH", JbOP_J, 1, XX((void *)0), 0, loop_jcxz_flag((void *)0), 9 },
738 { "loopeFH", JbOP_J, 1, XX((void *)0), 0, loop_jcxz_flag((void *)0), 9 },
739 { "loopFH", JbOP_J, 1, XX((void *)0), 0, loop_jcxz_flag((void *)0), 9 },
740 { "jEcxzH", JbOP_J, 1, XX((void *)0), 0, loop_jcxz_flag((void *)0), 9 },
741 { "inB", ALOP_IMREG, 116, IbOP_I, 1, XX((void *)0), 0 },
742 { "inS", eAXOP_IMREG, 108, IbOP_I, 1, XX((void *)0), 0 },
743 { "outB", IbOP_I, 1, ALOP_IMREG, 116, XX((void *)0), 0 },
744 { "outS", IbOP_I, 1, eAXOP_IMREG, 108, XX((void *)0), 0 },
745 /* e8 */
746 { "callT", JvOP_J, 2, XX((void *)0), 0, XX((void *)0), 0 },
747 { "jmpT", JvOP_J, 2, XX((void *)0), 0, XX((void *)0), 0 },
748 { "ljmp{T|}", ApOP_DIR, 0, XX((void *)0), 0, XX((void *)0), 0 },
749 { "jmp", JbOP_J, 1, XX((void *)0), 0, XX((void *)0), 0 },
750 { "inB", ALOP_IMREG, 116, indirDXOP_IMREG, 150, XX((void *)0), 0 },
751 { "inS", eAXOP_IMREG, 108, indirDXOP_IMREG, 150, XX((void *)0), 0 },
752 { "outB", indirDXOP_IMREG, 150, ALOP_IMREG, 116, XX((void *)0), 0 },
753 { "outS", indirDXOP_IMREG, 150, eAXOP_IMREG, 108, XX((void *)0), 0 },
754 /* f0 */
755 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* lock prefix */
756 { "icebp", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
757 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* repne */
758 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }, /* repz */
759 { "hlt", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
760 { "cmc", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
761 { GRP3b((void *)0), ((void *)0), 2, ((void *)0), 9, ((void *)0), 0 },
762 { GRP3S((void *)0), ((void *)0), 2, ((void *)0), 10, ((void *)0), 0 },
763 /* f8 */
764 { "clc", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
765 { "stc", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
766 { "cli", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
767 { "sti", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
768 { "cld", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
769 { "std", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
770 { GRP4((void *)0), ((void *)0), 2, ((void *)0), 11, ((void *)0), 0 },
771 { GRP5((void *)0), ((void *)0), 2, ((void *)0), 12, ((void *)0), 0 },
772};
773
774static const struct dis386 dis386_twobyte[] = {
775 /* 00 */
776 { GRP6((void *)0), ((void *)0), 2, ((void *)0), 13, ((void *)0), 0 },
777 { GRP7((void *)0), ((void *)0), 2, ((void *)0), 14, ((void *)0), 0 },
778 { "larS", GvOP_G, 2, EwOP_E, 3, XX((void *)0), 0 },
779 { "lslS", GvOP_G, 2, EwOP_E, 3, XX((void *)0), 0 },
780 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
781 { "syscall", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
782 { "clts", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
783 { "sysretP", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
784 /* 08 */
785 { "invd", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
786 { "wbinvd", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
787 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
788 { "ud2a", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
789 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
790 { GRPAMD((void *)0), ((void *)0), 2, ((void *)0), 22, ((void *)0), 0 },
791 { "femms", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
792 { "", MXOP_MMX, 0, EMOP_EM, 2, OPSUFOP_3DNowSuffix, 0 }, /* See OP_3DNowSuffix. */
793 /* 10 */
794 { PREGRP8((void *)0), ((void *)0), 3, ((void *)0), 8, ((void *)0), 0 },
795 { PREGRP9((void *)0), ((void *)0), 3, ((void *)0), 9, ((void *)0), 0 },
796 { PREGRP30((void *)0), ((void *)0), 3, ((void *)0), 30, ((void *)0), 0 },
797 { "movlpX", EXOP_EX, 2, XMOP_XMM, 0, SIMD_Fixup, 'h' },
798 { "unpcklpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
799 { "unpckhpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
800 { PREGRP31((void *)0), ((void *)0), 3, ((void *)0), 31, ((void *)0), 0 },
801 { "movhpX", EXOP_EX, 2, XMOP_XMM, 0, SIMD_Fixup, 'l' },
802 /* 18 */
803 { GRP14((void *)0), ((void *)0), 2, ((void *)0), 21, ((void *)0), 0 },
804 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
805 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
806 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
807 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
808 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
809 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
810 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
811 /* 20 */
812 { "movL", RmOP_Rd, 7, CmOP_C, 7, XX((void *)0), 0 },
813 { "movL", RmOP_Rd, 7, DmOP_D, 7, XX((void *)0), 0 },
814 { "movL", CmOP_C, 7, RmOP_Rd, 7, XX((void *)0), 0 },
815 { "movL", DmOP_D, 7, RmOP_Rd, 7, XX((void *)0), 0 },
816 { "movL", RdOP_Rd, 4, TdOP_T, 4, XX((void *)0), 0 },
817 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
818 { "movL", TdOP_T, 4, RdOP_Rd, 4, XX((void *)0), 0 },
819 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
820 /* 28 */
821 { "movapX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
822 { "movapX", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
823 { PREGRP2((void *)0), ((void *)0), 3, ((void *)0), 2, ((void *)0), 0 },
824 { "movntpX", EvOP_E, 2, XMOP_XMM, 0, XX((void *)0), 0 },
825 { PREGRP4((void *)0), ((void *)0), 3, ((void *)0), 4, ((void *)0), 0 },
826 { PREGRP3((void *)0), ((void *)0), 3, ((void *)0), 3, ((void *)0), 0 },
827 { "ucomisX", XMOP_XMM, 0,EXOP_EX, 2, XX((void *)0), 0 },
828 { "comisX", XMOP_XMM, 0,EXOP_EX, 2, XX((void *)0), 0 },
829 /* 30 */
830 { "wrmsr", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
831 { "rdtsc", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
832 { "rdmsr", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
833 { "rdpmc", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
834 { "sysenter", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
835 { "sysexit", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
836 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
837 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
838 /* 38 */
839 { "", OP0F38OP_0f38, 0, XX((void *)0), 0, XX((void *)0), 0 },
840 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
841 { "", OP0F3AOP_0f3a, 0, XX((void *)0), 0, XX((void *)0), 0 },
842 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
843 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
844 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
845 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
846 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
847 /* 40 */
848 { "cmovo", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
849 { "cmovno", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
850 { "cmovb", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
851 { "cmovae", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
852 { "cmove", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
853 { "cmovne", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
854 { "cmovbe", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
855 { "cmova", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
856 /* 48 */
857 { "cmovs", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
858 { "cmovns", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
859 { "cmovp", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
860 { "cmovnp", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
861 { "cmovl", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
862 { "cmovge", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
863 { "cmovle", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
864 { "cmovg", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
865 /* 50 */
866 { "movmskpX", GdOP_G, 4, XSOP_XS, 2, XX((void *)0), 0 },
867 { PREGRP13((void *)0), ((void *)0), 3, ((void *)0), 13, ((void *)0), 0 },
868 { PREGRP12((void *)0), ((void *)0), 3, ((void *)0), 12, ((void *)0), 0 },
869 { PREGRP11((void *)0), ((void *)0), 3, ((void *)0), 11, ((void *)0), 0 },
870 { "andpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
871 { "andnpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
872 { "orpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
873 { "xorpX", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
874 /* 58 */
875 { PREGRP0((void *)0), ((void *)0), 3, ((void *)0), 0, ((void *)0), 0 },
876 { PREGRP10((void *)0), ((void *)0), 3, ((void *)0), 10, ((void *)0), 0 },
877 { PREGRP17((void *)0), ((void *)0), 3, ((void *)0), 17, ((void *)0), 0 },
878 { PREGRP16((void *)0), ((void *)0), 3, ((void *)0), 16, ((void *)0), 0 },
879 { PREGRP14((void *)0), ((void *)0), 3, ((void *)0), 14, ((void *)0), 0 },
880 { PREGRP7((void *)0), ((void *)0), 3, ((void *)0), 7, ((void *)0), 0 },
881 { PREGRP5((void *)0), ((void *)0), 3, ((void *)0), 5, ((void *)0), 0 },
882 { PREGRP6((void *)0), ((void *)0), 3, ((void *)0), 6, ((void *)0), 0 },
883 /* 60 */
884 { "punpcklbw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
885 { "punpcklwd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
886 { "punpckldq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
887 { "packsswb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
888 { "pcmpgtb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
889 { "pcmpgtw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
890 { "pcmpgtd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
891 { "packuswb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
892 /* 68 */
893 { "punpckhbw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
894 { "punpckhwd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
895 { "punpckhdq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
896 { "packssdw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
897 { PREGRP26((void *)0), ((void *)0), 3, ((void *)0), 26, ((void *)0), 0 },
898 { PREGRP24((void *)0), ((void *)0), 3, ((void *)0), 24, ((void *)0), 0 },
899 { "movd", MXOP_MMX, 0, EdqOP_E, 10, XX((void *)0), 0 },
900 { PREGRP19((void *)0), ((void *)0), 3, ((void *)0), 19, ((void *)0), 0 },
901 /* 70 */
902 { PREGRP22((void *)0), ((void *)0), 3, ((void *)0), 22, ((void *)0), 0 },
903 { GRP10((void *)0), ((void *)0), 2, ((void *)0), 17, ((void *)0), 0 },
904 { GRP11((void *)0), ((void *)0), 2, ((void *)0), 18, ((void *)0), 0 },
905 { GRP12((void *)0), ((void *)0), 2, ((void *)0), 19, ((void *)0), 0 },
906 { "pcmpeqb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
907 { "pcmpeqw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
908 { "pcmpeqd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
909 { "emms", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
910 /* 78 */
911 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
912 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
913 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
914 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
915 { PREGRP28((void *)0), ((void *)0), 3, ((void *)0), 28, ((void *)0), 0 },
916 { PREGRP29((void *)0), ((void *)0), 3, ((void *)0), 29, ((void *)0), 0 },
917 { PREGRP23((void *)0), ((void *)0), 3, ((void *)0), 23, ((void *)0), 0 },
918 { PREGRP20((void *)0), ((void *)0), 3, ((void *)0), 20, ((void *)0), 0 },
919 /* 80 */
920 { "joH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
921 { "jnoH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
922 { "jbH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
923 { "jaeH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
924 { "jeH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
925 { "jneH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
926 { "jbeH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
927 { "jaH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
928 /* 88 */
929 { "jsH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
930 { "jnsH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
931 { "jpH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
932 { "jnpH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
933 { "jlH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
934 { "jgeH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
935 { "jleH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
936 { "jgH", JvOP_J, 2, XX((void *)0), 0, cond_jump_flag((void *)0), 8 },
937 /* 90 */
938 { "seto", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
939 { "setno", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
940 { "setb", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
941 { "setae", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
942 { "sete", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
943 { "setne", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
944 { "setbe", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
945 { "seta", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
946 /* 98 */
947 { "sets", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
948 { "setns", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
949 { "setp", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
950 { "setnp", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
951 { "setl", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
952 { "setge", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
953 { "setle", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
954 { "setg", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
955 /* a0 */
956 { "pushT", fsOP_REG, 104, XX((void *)0), 0, XX((void *)0), 0 },
957 { "popT", fsOP_REG, 104, XX((void *)0), 0, XX((void *)0), 0 },
958 { "cpuid", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
959 { "btS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
960 { "shldS", EvOP_E, 2, GvOP_G, 2, IbOP_I, 1 },
961 { "shldS", EvOP_E, 2, GvOP_G, 2, CLOP_IMREG, 117 },
962 { "", OPXCRYPT2OP_xcrypt2, 0, XX((void *)0), 0, XX((void *)0), 0 },
963 { "", OPXCRYPTOP_xcrypt, 0, XX((void *)0), 0, XX((void *)0), 0 },
964 /* a8 */
965 { "pushT", gsOP_REG, 105, XX((void *)0), 0, XX((void *)0), 0 },
966 { "popT", gsOP_REG, 105, XX((void *)0), 0, XX((void *)0), 0 },
967 { "rsm", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
968 { "btsS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
969 { "shrdS", EvOP_E, 2, GvOP_G, 2, IbOP_I, 1 },
970 { "shrdS", EvOP_E, 2, GvOP_G, 2, CLOP_IMREG, 117 },
971 { GRP13((void *)0), ((void *)0), 2, ((void *)0), 20, ((void *)0), 0 },
972 { "imulS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
973 /* b0 */
974 { "cmpxchgB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
975 { "cmpxchgS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
976 { "lssS", GvOP_G, 2, MpOP_M, 0, XX((void *)0), 0 },
977 { "btrS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
978 { "lfsS", GvOP_G, 2, MpOP_M, 0, XX((void *)0), 0 },
979 { "lgsS", GvOP_G, 2, MpOP_M, 0, XX((void *)0), 0 },
980 { "movz{bR|x|bR|x}", GvOP_G, 2, EbOP_E, 1, XX((void *)0), 0 },
981 { "movz{wR|x|wR|x}", GvOP_G, 2, EwOP_E, 3, XX((void *)0), 0 }, /* yes, there really is movzww ! */
982 /* b8 */
983 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
984 { "ud2b", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
985 { GRP8((void *)0), ((void *)0), 2, ((void *)0), 15, ((void *)0), 0 },
986 { "btcS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
987 { "bsfS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
988 { "bsrS", GvOP_G, 2, EvOP_E, 2, XX((void *)0), 0 },
989 { "movs{bR|x|bR|x}", GvOP_G, 2, EbOP_E, 1, XX((void *)0), 0 },
990 { "movs{wR|x|wR|x}", GvOP_G, 2, EwOP_E, 3, XX((void *)0), 0 }, /* yes, there really is movsww ! */
991 /* c0 */
992 { "xaddB", EbOP_E, 1, GbOP_G, 1, XX((void *)0), 0 },
993 { "xaddS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
994 { PREGRP1((void *)0), ((void *)0), 3, ((void *)0), 1, ((void *)0), 0 },
995 { "movntiS", EvOP_E, 2, GvOP_G, 2, XX((void *)0), 0 },
996 { "pinsrw", MXOP_MMX, 0, EdOP_E, 4, IbOP_I, 1 },
997 { "pextrw", GdOP_G, 4, MSOP_MS, 2, IbOP_I, 1 },
998 { "shufpX", XMOP_XMM, 0, EXOP_EX, 2, IbOP_I, 1 },
999 { GRP9((void *)0), ((void *)0), 2, ((void *)0), 16, ((void *)0), 0 },
1000 /* c8 */
1001 { "bswap", RMeAXOP_REG, 108, XX((void *)0), 0, XX((void *)0), 0 },
1002 { "bswap", RMeCXOP_REG, 109, XX((void *)0), 0, XX((void *)0), 0 },
1003 { "bswap", RMeDXOP_REG, 110, XX((void *)0), 0, XX((void *)0), 0 },
1004 { "bswap", RMeBXOP_REG, 111, XX((void *)0), 0, XX((void *)0), 0 },
1005 { "bswap", RMeSPOP_REG, 112, XX((void *)0), 0, XX((void *)0), 0 },
1006 { "bswap", RMeBPOP_REG, 113, XX((void *)0), 0, XX((void *)0), 0 },
1007 { "bswap", RMeSIOP_REG, 114, XX((void *)0), 0, XX((void *)0), 0 },
1008 { "bswap", RMeDIOP_REG, 115, XX((void *)0), 0, XX((void *)0), 0 },
1009 /* d0 */
1010 { PREGRP27((void *)0), ((void *)0), 3, ((void *)0), 27, ((void *)0), 0 },
1011 { "psrlw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1012 { "psrld", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1013 { "psrlq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1014 { "paddq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1015 { "pmullw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1016 { PREGRP21((void *)0), ((void *)0), 3, ((void *)0), 21, ((void *)0), 0 },
1017 { "pmovmskb", GdOP_G, 4, MSOP_MS, 2, XX((void *)0), 0 },
1018 /* d8 */
1019 { "psubusb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1020 { "psubusw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1021 { "pminub", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1022 { "pand", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1023 { "paddusb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1024 { "paddusw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1025 { "pmaxub", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1026 { "pandn", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1027 /* e0 */
1028 { "pavgb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1029 { "psraw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1030 { "psrad", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1031 { "pavgw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1032 { "pmulhuw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1033 { "pmulhw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1034 { PREGRP15((void *)0), ((void *)0), 3, ((void *)0), 15, ((void *)0), 0 },
1035 { PREGRP25((void *)0), ((void *)0), 3, ((void *)0), 25, ((void *)0), 0 },
1036 /* e8 */
1037 { "psubsb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1038 { "psubsw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1039 { "pminsw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1040 { "por", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1041 { "paddsb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1042 { "paddsw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1043 { "pmaxsw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1044 { "pxor", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1045 /* f0 */
1046 { PREGRP32((void *)0), ((void *)0), 3, ((void *)0), 32, ((void *)0), 0 },
1047 { "psllw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1048 { "pslld", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1049 { "psllq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1050 { "pmuludq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1051 { "pmaddwd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1052 { "psadbw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1053 { PREGRP18((void *)0), ((void *)0), 3, ((void *)0), 18, ((void *)0), 0 },
1054 /* f8 */
1055 { "psubb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1056 { "psubw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1057 { "psubd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1058 { "psubq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1059 { "paddb", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1060 { "paddw", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1061 { "paddd", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1062 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }
1063};
1064
1065static const unsigned char onebyte_has_modrm[256] = {
1066 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1067 /* ------------------------------- */
1068 /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
1069 /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
1070 /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
1071 /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
1072 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
1073 /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
1074 /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
1075 /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
1076 /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
1077 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
1078 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
1079 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
1080 /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
1081 /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
1082 /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
1083 /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
1084 /* ------------------------------- */
1085 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1086};
1087
1088static const unsigned char twobyte_has_modrm[256] = {
1089 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1090 /* ------------------------------- */
1091 /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
1092 /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
1093 /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
1094 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1095 /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
1096 /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
1097 /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
1098 /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */
1099 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1100 /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
1101 /* a0 */ 0,0,0,1,1,1,0,1,0,0,0,1,1,1,1,1, /* af */
1102 /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
1103 /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
1104 /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
1105 /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
1106 /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
1107 /* ------------------------------- */
1108 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1109};
1110
1111static const unsigned char twobyte_uses_SSE_prefix[256] = {
1112 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1113 /* ------------------------------- */
1114 /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
1115 /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
1116 /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
1117 /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
1118 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
1119 /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
1120 /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
1121 /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 7f */
1122 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1123 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
1124 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
1125 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
1126 /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
1127 /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
1128 /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
1129 /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
1130 /* ------------------------------- */
1131 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1132};
1133
1134static char obuf[100];
1135static char *obufp;
1136static char scratchbuf[100];
1137static unsigned char *start_codep;
1138static unsigned char *insn_codep;
1139static unsigned char *codep;
1140static disassemble_info *the_info;
1141static int mod;
1142static int rm;
1143static int reg;
1144static unsigned char need_modrm;
1145
1146/* If we are accessing mod/rm/reg without need_modrm set, then the
1147 values are stale. Hitting this abort likely indicates that you
1148 need to update onebyte_has_modrm or twobyte_has_modrm. */
1149#define MODRM_CHECKif (!need_modrm) abort () if (!need_modrm) abort ()
1150
1151static const char **names64;
1152static const char **names32;
1153static const char **names16;
1154static const char **names8;
1155static const char **names8rex;
1156static const char **names_seg;
1157static const char **index16;
1158
1159static const char *intel_names64[] = {
1160 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1161 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1162};
1163static const char *intel_names32[] = {
1164 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
1165 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
1166};
1167static const char *intel_names16[] = {
1168 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
1169 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
1170};
1171static const char *intel_names8[] = {
1172 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
1173};
1174static const char *intel_names8rex[] = {
1175 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1176 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
1177};
1178static const char *intel_names_seg[] = {
1179 "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
1180};
1181static const char *intel_index16[] = {
1182 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
1183};
1184
1185static const char *att_names64[] = {
1186 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1187 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
1188};
1189static const char *att_names32[] = {
1190 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
1191 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
1192};
1193static const char *att_names16[] = {
1194 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
1195 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
1196};
1197static const char *att_names8[] = {
1198 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
1199};
1200static const char *att_names8rex[] = {
1201 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
1202 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
1203};
1204static const char *att_names_seg[] = {
1205 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
1206};
1207static const char *att_index16[] = {
1208 "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
1209};
1210
1211static const struct dis386 grps[][8] = {
1212 /* GRP1b */
1213 {
1214 { "addA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1215 { "orA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1216 { "adcA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1217 { "sbbA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1218 { "andA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1219 { "subA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1220 { "xorA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1221 { "cmpA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 }
1222 },
1223 /* GRP1S */
1224 {
1225 { "addQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1226 { "orQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1227 { "adcQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1228 { "sbbQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1229 { "andQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1230 { "subQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1231 { "xorQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1232 { "cmpQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 }
1233 },
1234 /* GRP1Ss */
1235 {
1236 { "addQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1237 { "orQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1238 { "adcQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1239 { "sbbQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1240 { "andQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1241 { "subQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1242 { "xorQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 },
1243 { "cmpQ", EvOP_E, 2, sIbOP_sI, 1, XX((void *)0), 0 }
1244 },
1245 /* GRP2b */
1246 {
1247 { "rolA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1248 { "rorA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1249 { "rclA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1250 { "rcrA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1251 { "shlA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1252 { "shrA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1253 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1254 { "sarA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1255 },
1256 /* GRP2S */
1257 {
1258 { "rolQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1259 { "rorQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1260 { "rclQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1261 { "rcrQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1262 { "shlQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1263 { "shrQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1264 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1265 { "sarQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1266 },
1267 /* GRP2b_one */
1268 {
1269 { "rolA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1270 { "rorA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1271 { "rclA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1272 { "rcrA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1273 { "shlA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1274 { "shrA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1275 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1276 { "sarA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1277 },
1278 /* GRP2S_one */
1279 {
1280 { "rolQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1281 { "rorQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1282 { "rclQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1283 { "rcrQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1284 { "shlQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1285 { "shrQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1286 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0},
1287 { "sarQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1288 },
1289 /* GRP2b_cl */
1290 {
1291 { "rolA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1292 { "rorA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1293 { "rclA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1294 { "rcrA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1295 { "shlA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1296 { "shrA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1297 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1298 { "sarA", EbOP_E, 1, CLOP_IMREG, 117, XX((void *)0), 0 },
1299 },
1300 /* GRP2S_cl */
1301 {
1302 { "rolQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1303 { "rorQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1304 { "rclQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1305 { "rcrQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1306 { "shlQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1307 { "shrQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 },
1308 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1309 { "sarQ", EvOP_E, 2, CLOP_IMREG, 117, XX((void *)0), 0 }
1310 },
1311 /* GRP3b */
1312 {
1313 { "testA", EbOP_E, 1, IbOP_I, 1, XX((void *)0), 0 },
1314 { "(bad)", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1315 { "notA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1316 { "negA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1317 { "mulA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 }, /* Don't print the implicit %al register, */
1318 { "imulA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 }, /* to distinguish these opcodes from other */
1319 { "divA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 }, /* mul/imul opcodes. Do the same for div */
1320 { "idivA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 } /* and idiv for consistency. */
1321 },
1322 /* GRP3S */
1323 {
1324 { "testQ", EvOP_E, 2, IvOP_I, 2, XX((void *)0), 0 },
1325 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1326 { "notQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1327 { "negQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1328 { "mulQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 }, /* Don't print the implicit register. */
1329 { "imulQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1330 { "divQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1331 { "idivQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1332 },
1333 /* GRP4 */
1334 {
1335 { "incA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1336 { "decA", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1337 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1338 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1339 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1340 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1341 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1342 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1343 },
1344 /* GRP5 */
1345 {
1346 { "incQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1347 { "decQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1348 { "callT", indirEvOP_indirE, 2, XX((void *)0), 0, XX((void *)0), 0 },
1349 { "lcallT", indirEvOP_indirE, 2, XX((void *)0), 0, XX((void *)0), 0 },
1350 { "jmpT", indirEvOP_indirE, 2, XX((void *)0), 0, XX((void *)0), 0 },
1351 { "ljmpT", indirEvOP_indirE, 2, XX((void *)0), 0, XX((void *)0), 0 },
1352 { "pushU", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1353 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1354 },
1355 /* GRP6 */
1356 {
1357 { "sldtQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1358 { "strQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1359 { "lldt", EwOP_E, 3, XX((void *)0), 0, XX((void *)0), 0 },
1360 { "ltr", EwOP_E, 3, XX((void *)0), 0, XX((void *)0), 0 },
1361 { "verr", EwOP_E, 3, XX((void *)0), 0, XX((void *)0), 0 },
1362 { "verw", EwOP_E, 3, XX((void *)0), 0, XX((void *)0), 0 },
1363 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1364 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 }
1365 },
1366 /* GRP7 */
1367 {
1368 { "sgdtQ", MOP_M, 0, XX((void *)0), 0, XX((void *)0), 0 },
1369 { "sidtQ", PNI_Fixup, 0, XX((void *)0), 0, XX((void *)0), 0 },
1370 { "lgdtQ", XCR_Fixup, 0, XX((void *)0), 0, XX((void *)0), 0 },
1371 { "lidtQ", MOP_M, 0, XX((void *)0), 0, XX((void *)0), 0 },
1372 { "smswQ", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1373 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1374 { "lmsw", EwOP_E, 3, XX((void *)0), 0, XX((void *)0), 0 },
1375 { "invlpg", INVLPG_Fixup, w_mode3, XX((void *)0), 0, XX((void *)0), 0 },
1376 },
1377 /* GRP8 */
1378 {
1379 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1380 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1381 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1382 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1383 { "btQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1384 { "btsQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1385 { "btrQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1386 { "btcQ", EvOP_E, 2, IbOP_I, 1, XX((void *)0), 0 },
1387 },
1388 /* GRP9 */
1389 {
1390 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1391 { "cmpxchg8b", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1392 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1393 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1394 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1395 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1396 { "rdrand", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1397 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1398 },
1399 /* GRP10 */
1400 {
1401 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1402 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1403 { "psrlw", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1404 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1405 { "psraw", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1406 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1407 { "psllw", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1408 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1409 },
1410 /* GRP11 */
1411 {
1412 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1413 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1414 { "psrld", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1415 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1416 { "psrad", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1417 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1418 { "pslld", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1419 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1420 },
1421 /* GRP12 */
1422 {
1423 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1424 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1425 { "psrlq", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1426 { "psrldq", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1427 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1428 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1429 { "psllq", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1430 { "pslldq", MSOP_MS, 2, IbOP_I, 1, XX((void *)0), 0 },
1431 },
1432 /* GRP13 */
1433 {
1434 { "fxsave", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1435 { "fxrstor", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1436 { "ldmxcsr", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1437 { "stmxcsr", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1438 { "xsave", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1439 { "xrstor", OP_0fae, v_mode2, XX((void *)0), 0, XX((void *)0), 0 },
1440 { "xsaveopt", OP_0fae, v_mode2, XX((void *)0), 0, XX((void *)0), 0 },
1441 { "clflush", OP_0fae, v_mode2, XX((void *)0), 0, XX((void *)0), 0 },
1442 },
1443 /* GRP14 */
1444 {
1445 { "prefetchnta", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1446 { "prefetcht0", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1447 { "prefetcht1", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1448 { "prefetcht2", EvOP_E, 2, XX((void *)0), 0, XX((void *)0), 0 },
1449 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1450 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1451 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1452 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1453 },
1454 /* GRPAMD */
1455 {
1456 { "prefetch", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1457 { "prefetchw", EbOP_E, 1, XX((void *)0), 0, XX((void *)0), 0 },
1458 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1459 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1460 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1461 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1462 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1463 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
1464 },
1465};
1466
1467static const struct dis386 prefix_user_table[][4] = {
1468 /* PREGRP0 */
1469 {
1470 { "addps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1471 { "addss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1472 { "addpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1473 { "addsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1474 },
1475 /* PREGRP1 */
1476 {
1477 { "", XMOP_XMM, 0, EXOP_EX, 2, OPSIMDOP_SIMD_Suffix, 0 }, /* See OP_SIMD_SUFFIX. */
1478 { "", XMOP_XMM, 0, EXOP_EX, 2, OPSIMDOP_SIMD_Suffix, 0 },
1479 { "", XMOP_XMM, 0, EXOP_EX, 2, OPSIMDOP_SIMD_Suffix, 0 },
1480 { "", XMOP_XMM, 0, EXOP_EX, 2, OPSIMDOP_SIMD_Suffix, 0 },
1481 },
1482 /* PREGRP2 */
1483 {
1484 { "cvtpi2ps", XMOP_XMM, 0, EMOP_EM, 2, XX((void *)0), 0 },
1485 { "cvtsi2ssY", XMOP_XMM, 0, EvOP_E, 2, XX((void *)0), 0 },
1486 { "cvtpi2pd", XMOP_XMM, 0, EMOP_EM, 2, XX((void *)0), 0 },
1487 { "cvtsi2sdY", XMOP_XMM, 0, EvOP_E, 2, XX((void *)0), 0 },
1488 },
1489 /* PREGRP3 */
1490 {
1491 { "cvtps2pi", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1492 { "cvtss2siY", GvOP_G, 2, EXOP_EX, 2, XX((void *)0), 0 },
1493 { "cvtpd2pi", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1494 { "cvtsd2siY", GvOP_G, 2, EXOP_EX, 2, XX((void *)0), 0 },
1495 },
1496 /* PREGRP4 */
1497 {
1498 { "cvttps2pi", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1499 { "cvttss2siY", GvOP_G, 2, EXOP_EX, 2, XX((void *)0), 0 },
1500 { "cvttpd2pi", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1501 { "cvttsd2siY", GvOP_G, 2, EXOP_EX, 2, XX((void *)0), 0 },
1502 },
1503 /* PREGRP5 */
1504 {
1505 { "divps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1506 { "divss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1507 { "divpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1508 { "divsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1509 },
1510 /* PREGRP6 */
1511 {
1512 { "maxps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1513 { "maxss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1514 { "maxpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1515 { "maxsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1516 },
1517 /* PREGRP7 */
1518 {
1519 { "minps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1520 { "minss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1521 { "minpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1522 { "minsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1523 },
1524 /* PREGRP8 */
1525 {
1526 { "movups", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1527 { "movss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1528 { "movupd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1529 { "movsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1530 },
1531 /* PREGRP9 */
1532 {
1533 { "movups", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1534 { "movss", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1535 { "movupd", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1536 { "movsd", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1537 },
1538 /* PREGRP10 */
1539 {
1540 { "mulps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1541 { "mulss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1542 { "mulpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1543 { "mulsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1544 },
1545 /* PREGRP11 */
1546 {
1547 { "rcpps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1548 { "rcpss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1549 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1550 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1551 },
1552 /* PREGRP12 */
1553 {
1554 { "rsqrtps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1555 { "rsqrtss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1556 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1557 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1558 },
1559 /* PREGRP13 */
1560 {
1561 { "sqrtps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1562 { "sqrtss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1563 { "sqrtpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1564 { "sqrtsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1565 },
1566 /* PREGRP14 */
1567 {
1568 { "subps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1569 { "subss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1570 { "subpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1571 { "subsd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1572 },
1573 /* PREGRP15 */
1574 {
1575 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1576 { "cvtdq2pd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1577 { "cvttpd2dq", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1578 { "cvtpd2dq", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1579 },
1580 /* PREGRP16 */
1581 {
1582 { "cvtdq2ps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1583 { "cvttps2dq",XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1584 { "cvtps2dq",XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1585 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1586 },
1587 /* PREGRP17 */
1588 {
1589 { "cvtps2pd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1590 { "cvtss2sd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1591 { "cvtpd2ps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1592 { "cvtsd2ss", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1593 },
1594 /* PREGRP18 */
1595 {
1596 { "maskmovq", MXOP_MMX, 0, MSOP_MS, 2, XX((void *)0), 0 },
1597 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1598 { "maskmovdqu", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1599 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1600 },
1601 /* PREGRP19 */
1602 {
1603 { "movq", MXOP_MMX, 0, EMOP_EM, 2, XX((void *)0), 0 },
1604 { "movdqu", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1605 { "movdqa", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1606 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1607 },
1608 /* PREGRP20 */
1609 {
1610 { "movq", EMOP_EM, 2, MXOP_MMX, 0, XX((void *)0), 0 },
1611 { "movdqu", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1612 { "movdqa", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1613 { "(bad)", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1614 },
1615 /* PREGRP21 */
1616 {
1617 { "(bad)", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1618 { "movq2dq", XMOP_XMM, 0, MSOP_MS, 2, XX((void *)0), 0 },
1619 { "movq", EXOP_EX, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1620 { "movdq2q", MXOP_MMX, 0, XSOP_XS, 2, XX((void *)0), 0 },
1621 },
1622 /* PREGRP22 */
1623 {
1624 { "pshufw", MXOP_MMX, 0, EMOP_EM, 2, IbOP_I, 1 },
1625 { "pshufhw", XMOP_XMM, 0, EXOP_EX, 2, IbOP_I, 1 },
1626 { "pshufd", XMOP_XMM, 0, EXOP_EX, 2, IbOP_I, 1 },
1627 { "pshuflw", XMOP_XMM, 0, EXOP_EX, 2, IbOP_I, 1 },
1628 },
1629 /* PREGRP23 */
1630 {
1631 { "movd", EdqOP_E, 10, MXOP_MMX, 0, XX((void *)0), 0 },
1632 { "movq", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1633 { "movd", EdqOP_E, 10, XMOP_XMM, 0, XX((void *)0), 0 },
1634 { "(bad)", EdOP_E, 4, XMOP_XMM, 0, XX((void *)0), 0 },
1635 },
1636 /* PREGRP24 */
1637 {
1638 { "(bad)", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1639 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1640 { "punpckhqdq", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1641 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1642 },
1643 /* PREGRP25 */
1644 {
1645 { "movntq", EvOP_E, 2, MXOP_MMX, 0, XX((void *)0), 0 },
1646 { "(bad)", EvOP_E, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1647 { "movntdq", EvOP_E, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1648 { "(bad)", EvOP_E, 2, XMOP_XMM, 0, XX((void *)0), 0 },
1649 },
1650 /* PREGRP26 */
1651 {
1652 { "(bad)", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1653 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1654 { "punpcklqdq", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1655 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1656 },
1657 /* PREGRP27 */
1658 {
1659 { "(bad)", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1660 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1661 { "addsubpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1662 { "addsubps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1663 },
1664 /* PREGRP28 */
1665 {
1666 { "(bad)", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1667 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1668 { "haddpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1669 { "haddps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1670 },
1671 /* PREGRP29 */
1672 {
1673 { "(bad)", MXOP_MMX, 0, EXOP_EX, 2, XX((void *)0), 0 },
1674 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1675 { "hsubpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1676 { "hsubps", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1677 },
1678 /* PREGRP30 */
1679 {
1680 { "movlpX", XMOP_XMM, 0, EXOP_EX, 2, SIMD_Fixup, 'h' }, /* really only 2 operands */
1681 { "movsldup", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1682 { "movlpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1683 { "movddup", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1684 },
1685 /* PREGRP31 */
1686 {
1687 { "movhpX", XMOP_XMM, 0, EXOP_EX, 2, SIMD_Fixup, 'l' },
1688 { "movshdup", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1689 { "movhpd", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1690 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1691 },
1692 /* PREGRP32 */
1693 {
1694 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1695 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1696 { "(bad)", XMOP_XMM, 0, EXOP_EX, 2, XX((void *)0), 0 },
1697 { "lddqu", XMOP_XMM, 0, MOP_M, 0, XX((void *)0), 0 },
1698 },
1699};
1700
1701static const struct dis386 x86_64_table[][2] = {
1702 {
1703 { "arpl", EwOP_E, 3, GwOP_G, 3, XX((void *)0), 0 },
1704 { "movs{||lq|xd}", GvOP_G, 2, EdOP_E, 4, XX((void *)0), 0 },
1705 },
1706};
1707
1708#define INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>") _("<internal disassembler error>")("<internal disassembler error>")
1709
1710static void
1711ckprefix (void)
1712{
1713 int newrex;
1714 rex = 0;
1715 prefixes = 0;
1716 used_prefixes = 0;
1717 rex_used = 0;
1718 while (1)
1719 {
1720 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
1721 newrex = 0;
1722 switch (*codep)
1723 {
1724 /* REX prefixes family. */
1725 case 0x40:
1726 case 0x41:
1727 case 0x42:
1728 case 0x43:
1729 case 0x44:
1730 case 0x45:
1731 case 0x46:
1732 case 0x47:
1733 case 0x48:
1734 case 0x49:
1735 case 0x4a:
1736 case 0x4b:
1737 case 0x4c:
1738 case 0x4d:
1739 case 0x4e:
1740 case 0x4f:
1741 if (mode_64bit)
1742 newrex = *codep;
1743 else
1744 return;
1745 break;
1746 case 0xf3:
1747 prefixes |= PREFIX_REPZ1;
1748 break;
1749 case 0xf2:
1750 prefixes |= PREFIX_REPNZ2;
1751 break;
1752 case 0xf0:
1753 prefixes |= PREFIX_LOCK4;
1754 break;
1755 case 0x2e:
1756 prefixes |= PREFIX_CS8;
1757 break;
1758 case 0x36:
1759 prefixes |= PREFIX_SS0x10;
1760 break;
1761 case 0x3e:
1762 prefixes |= PREFIX_DS0x20;
1763 break;
1764 case 0x26:
1765 prefixes |= PREFIX_ES0x40;
1766 break;
1767 case 0x64:
1768 prefixes |= PREFIX_FS0x80;
1769 break;
1770 case 0x65:
1771 prefixes |= PREFIX_GS0x100;
1772 break;
1773 case 0x66:
1774 prefixes |= PREFIX_DATA0x200;
1775 break;
1776 case 0x67:
1777 prefixes |= PREFIX_ADDR0x400;
1778 break;
1779 case FWAIT_OPCODE(0x9b):
1780 /* fwait is really an instruction. If there are prefixes
1781 before the fwait, they belong to the fwait, *not* to the
1782 following instruction. */
1783 if (prefixes)
1784 {
1785 prefixes |= PREFIX_FWAIT0x800;
1786 codep++;
1787 return;
1788 }
1789 prefixes = PREFIX_FWAIT0x800;
1790 break;
1791 default:
1792 return;
1793 }
1794 /* Rex is ignored when followed by another prefix. */
1795 if (rex)
1796 {
1797 oappend (prefix_name (rex, 0));
1798 oappend (" ");
1799 }
1800 rex = newrex;
1801 codep++;
1802 }
1803}
1804
1805/* Return the name of the prefix byte PREF, or NULL if PREF is not a
1806 prefix byte. */
1807
1808static const char *
1809prefix_name (int pref, int sizeflag)
1810{
1811 switch (pref)
1812 {
1813 /* REX prefixes family. */
1814 case 0x40:
1815 return "rex";
1816 case 0x41:
1817 return "rexZ";
1818 case 0x42:
1819 return "rexY";
1820 case 0x43:
1821 return "rexYZ";
1822 case 0x44:
1823 return "rexX";
1824 case 0x45:
1825 return "rexXZ";
1826 case 0x46:
1827 return "rexXY";
1828 case 0x47:
1829 return "rexXYZ";
1830 case 0x48:
1831 return "rex64";
1832 case 0x49:
1833 return "rex64Z";
1834 case 0x4a:
1835 return "rex64Y";
1836 case 0x4b:
1837 return "rex64YZ";
1838 case 0x4c:
1839 return "rex64X";
1840 case 0x4d:
1841 return "rex64XZ";
1842 case 0x4e:
1843 return "rex64XY";
1844 case 0x4f:
1845 return "rex64XYZ";
1846 case 0xf3:
1847 return "repz";
1848 case 0xf2:
1849 return "repnz";
1850 case 0xf0:
1851 return "lock";
1852 case 0x2e:
1853 return "cs";
1854 case 0x36:
1855 return "ss";
1856 case 0x3e:
1857 return "ds";
1858 case 0x26:
1859 return "es";
1860 case 0x64:
1861 return "fs";
1862 case 0x65:
1863 return "gs";
1864 case 0x66:
1865 return (sizeflag & DFLAG1) ? "data16" : "data32";
1866 case 0x67:
1867 if (mode_64bit)
1868 return (sizeflag & AFLAG2) ? "addr32" : "addr64";
1869 else
1870 return ((sizeflag & AFLAG2) && !mode_64bit) ? "addr16" : "addr32";
1871 case FWAIT_OPCODE(0x9b):
1872 return "fwait";
1873 default:
1874 return NULL((void *)0);
1875 }
1876}
1877
1878static char op1out[100], op2out[100], op3out[100];
1879static int op_ad, op_index[3];
1880static bfd_vma op_address[3];
1881static bfd_vma op_riprel[3];
1882static bfd_vma start_pc;
1883
1884/*
1885 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1886 * (see topic "Redundant prefixes" in the "Differences from 8086"
1887 * section of the "Virtual 8086 Mode" chapter.)
1888 * 'pc' should be the address of this instruction, it will
1889 * be used to print the target address if this is a relative jump or call
1890 * The function returns the length of this instruction in bytes.
1891 */
1892
1893static char intel_syntax;
1894static char open_char;
1895static char close_char;
1896static char separator_char;
1897static char scale_char;
1898
1899/* Here for backwards compatibility. When gdb stops using
1900 print_insn_i386_att and print_insn_i386_intel these functions can
1901 disappear, and print_insn_i386 be merged into print_insn. */
1902int
1903print_insn_i386_att (bfd_vma pc, disassemble_info *info)
1904{
1905 intel_syntax = 0;
1906
1907 return print_insn (pc, info);
1908}
1909
1910int
1911print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
1912{
1913 intel_syntax = 1;
1914
1915 return print_insn (pc, info);
1916}
1917
1918int
1919print_insn_i386 (bfd_vma pc, disassemble_info *info)
1920{
1921 intel_syntax = -1;
1922
1923 return print_insn (pc, info);
1924}
1925
1926static int
1927print_insn (bfd_vma pc, disassemble_info *info)
1928{
1929 const struct dis386 *dp;
1930 int i;
1931 int two_source_ops;
1932 char *first, *second, *third;
1933 int needcomma;
1934 unsigned char uses_SSE_prefix;
1935 int sizeflag;
1936 const char *p;
1937 struct dis_private priv;
1938
1939 mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax65
1940 || info->mach == bfd_mach_x86_6464);
1941
1942 if (intel_syntax == (char) -1)
1943 intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax3
1944 || info->mach == bfd_mach_x86_64_intel_syntax65);
1945
1946 if (info->mach == bfd_mach_i386_i3861
1947 || info->mach == bfd_mach_x86_6464
1948 || info->mach == bfd_mach_i386_i386_intel_syntax3
1949 || info->mach == bfd_mach_x86_64_intel_syntax65)
1950 priv.orig_sizeflag = AFLAG2 | DFLAG1;
1951 else if (info->mach == bfd_mach_i386_i80862)
1952 priv.orig_sizeflag = 0;
1953 else
1954 abort ();
1955
1956 for (p = info->disassembler_options; p != NULL((void *)0); )
1957 {
1958 if (strncmp (p, "x86-64", 6) == 0)
1959 {
1960 mode_64bit = 1;
1961 priv.orig_sizeflag = AFLAG2 | DFLAG1;
1962 }
1963 else if (strncmp (p, "i386", 4) == 0)
1964 {
1965 mode_64bit = 0;
1966 priv.orig_sizeflag = AFLAG2 | DFLAG1;
1967 }
1968 else if (strncmp (p, "i8086", 5) == 0)
1969 {
1970 mode_64bit = 0;
1971 priv.orig_sizeflag = 0;
1972 }
1973 else if (strncmp (p, "intel", 5) == 0)
1974 {
1975 intel_syntax = 1;
1976 }
1977 else if (strncmp (p, "att", 3) == 0)
1978 {
1979 intel_syntax = 0;
1980 }
1981 else if (strncmp (p, "addr", 4) == 0)
1982 {
1983 if (p[4] == '1' && p[5] == '6')
1984 priv.orig_sizeflag &= ~AFLAG2;
1985 else if (p[4] == '3' && p[5] == '2')
1986 priv.orig_sizeflag |= AFLAG2;
1987 }
1988 else if (strncmp (p, "data", 4) == 0)
1989 {
1990 if (p[4] == '1' && p[5] == '6')
1991 priv.orig_sizeflag &= ~DFLAG1;
1992 else if (p[4] == '3' && p[5] == '2')
1993 priv.orig_sizeflag |= DFLAG1;
1994 }
1995 else if (strncmp (p, "suffix", 6) == 0)
1996 priv.orig_sizeflag |= SUFFIX_ALWAYS4;
1997
1998 p = strchr (p, ',');
1999 if (p != NULL((void *)0))
2000 p++;
2001 }
2002
2003 if (intel_syntax)
2004 {
2005 names64 = intel_names64;
2006 names32 = intel_names32;
2007 names16 = intel_names16;
2008 names8 = intel_names8;
2009 names8rex = intel_names8rex;
2010 names_seg = intel_names_seg;
2011 index16 = intel_index16;
2012 open_char = '[';
2013 close_char = ']';
2014 separator_char = '+';
2015 scale_char = '*';
2016 }
2017 else
2018 {
2019 names64 = att_names64;
2020 names32 = att_names32;
2021 names16 = att_names16;
2022 names8 = att_names8;
2023 names8rex = att_names8rex;
2024 names_seg = att_names_seg;
2025 index16 = att_index16;
2026 open_char = '(';
2027 close_char = ')';
2028 separator_char = ',';
2029 scale_char = ',';
2030 }
2031
2032 /* The output looks better if we put 7 bytes on a line, since that
2033 puts most long word instructions on a single line. */
2034 info->bytes_per_line = 7;
2035
2036 info->private_data = &priv;
2037 priv.max_fetched = priv.the_buffer;
2038 priv.insn_start = pc;
2039
2040 obuf[0] = 0;
2041 op1out[0] = 0;
2042 op2out[0] = 0;
2043 op3out[0] = 0;
2044
2045 op_index[0] = op_index[1] = op_index[2] = -1;
2046
2047 the_info = info;
2048 start_pc = pc;
2049 start_codep = priv.the_buffer;
2050 codep = priv.the_buffer;
2051
2052 if (setjmp (priv.bailout) != 0)
2053 {
2054 const char *name;
2055
2056 /* Getting here means we tried for data but didn't get it. That
2057 means we have an incomplete instruction of some sort. Just
2058 print the first byte as a prefix or a .byte pseudo-op. */
2059 if (codep > priv.the_buffer)
2060 {
2061 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2062 if (name != NULL((void *)0))
2063 (*info->fprintf_func) (info->stream, "%s", name);
2064 else
2065 {
2066 /* Just print the first byte as a .byte instruction. */
2067 (*info->fprintf_func) (info->stream, ".byte 0x%x",
2068 (unsigned int) priv.the_buffer[0]);
2069 }
2070
2071 return 1;
2072 }
2073
2074 return -1;
2075 }
2076
2077 obufp = obuf;
2078 ckprefix ();
2079
2080 insn_codep = codep;
2081 sizeflag = priv.orig_sizeflag;
2082
2083 FETCH_DATA (info, codep + 1)((codep + 1) <= ((struct dis_private *) (info->private_data
))->max_fetched ? 1 : fetch_data ((info), (codep + 1)))
;
2084 two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
2085
2086 if ((prefixes & PREFIX_FWAIT0x800)
2087 && ((*codep < 0xd8) || (*codep > 0xdf)))
2088 {
2089 const char *name;
2090
2091 /* fwait not followed by floating point instruction. Print the
2092 first prefix, which is probably fwait itself. */
2093 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2094 if (name == NULL((void *)0))
2095 name = INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>");
2096 (*info->fprintf_func) (info->stream, "%s", name);
2097 return 1;
2098 }
2099
2100 if (*codep == 0x0f)
2101 {
2102 FETCH_DATA (info, codep + 2)((codep + 2) <= ((struct dis_private *) (info->private_data
))->max_fetched ? 1 : fetch_data ((info), (codep + 2)))
;
2103 dp = &dis386_twobyte[*++codep];
2104 need_modrm = twobyte_has_modrm[*codep];
2105 uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
2106 }
2107 else
2108 {
2109 dp = &dis386[*codep];
2110 need_modrm = onebyte_has_modrm[*codep];
2111 uses_SSE_prefix = 0;
2112 }
2113 codep++;
2114
2115 if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ1))
2116 {
2117 oappend ("repz ");
2118 used_prefixes |= PREFIX_REPZ1;
2119 }
2120 if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ2))
2121 {
2122 oappend ("repnz ");
2123 used_prefixes |= PREFIX_REPNZ2;
2124 }
2125 if (prefixes & PREFIX_LOCK4)
2126 {
2127 oappend ("lock ");
2128 used_prefixes |= PREFIX_LOCK4;
2129 }
2130
2131 if (prefixes & PREFIX_ADDR0x400)
2132 {
2133 sizeflag ^= AFLAG2;
2134 if (dp->bytemode3 != loop_jcxz_mode9 || intel_syntax)
2135 {
2136 if ((sizeflag & AFLAG2) || mode_64bit)
2137 oappend ("addr32 ");
2138 else
2139 oappend ("addr16 ");
2140 used_prefixes |= PREFIX_ADDR0x400;
2141 }
2142 }
2143
2144 if (!uses_SSE_prefix && (prefixes & PREFIX_DATA0x200))
2145 {
2146 sizeflag ^= DFLAG1;
2147 if (dp->bytemode3 == cond_jump_mode8
2148 && dp->bytemode1 == v_mode2
2149 && !intel_syntax)
2150 {
2151 if (sizeflag & DFLAG1)
2152 oappend ("data32 ");
2153 else
2154 oappend ("data16 ");
2155 used_prefixes |= PREFIX_DATA0x200;
2156 }
2157 }
2158
2159 if (need_modrm)
2160 {
2161 FETCH_DATA (info, codep + 1)((codep + 1) <= ((struct dis_private *) (info->private_data
))->max_fetched ? 1 : fetch_data ((info), (codep + 1)))
;
2162 mod = (*codep >> 6) & 3;
2163 reg = (*codep >> 3) & 7;
2164 rm = *codep & 7;
2165 }
2166
2167 if (dp->name == NULL((void *)0) && dp->bytemode1 == FLOATCODE1)
2168 {
2169 dofloat (sizeflag);
2170 }
2171 else
2172 {
2173 int index;
2174 if (dp->name == NULL((void *)0))
2175 {
2176 switch (dp->bytemode1)
2177 {
2178 case USE_GROUPS2:
2179 dp = &grps[dp->bytemode2][reg];
2180 break;
2181
2182 case USE_PREFIX_USER_TABLE3:
2183 index = 0;
2184 used_prefixes |= (prefixes & PREFIX_REPZ1);
2185 if (prefixes & PREFIX_REPZ1)
2186 index = 1;
2187 else
2188 {
2189 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2190 if (prefixes & PREFIX_DATA0x200)
2191 index = 2;
2192 else
2193 {
2194 used_prefixes |= (prefixes & PREFIX_REPNZ2);
2195 if (prefixes & PREFIX_REPNZ2)
2196 index = 3;
2197 }
2198 }
2199 dp = &prefix_user_table[dp->bytemode2][index];
2200 break;
2201
2202 case X86_64_SPECIAL4:
2203 dp = &x86_64_table[dp->bytemode2][mode_64bit];
2204 break;
2205
2206 default:
2207 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
2208 break;
2209 }
2210 }
2211
2212 if (putop (dp->name, sizeflag) == 0)
2213 {
2214 obufp = op1out;
2215 op_ad = 2;
2216 if (dp->op1)
2217 (*dp->op1) (dp->bytemode1, sizeflag);
2218
2219 obufp = op2out;
2220 op_ad = 1;
2221 if (dp->op2)
2222 (*dp->op2) (dp->bytemode2, sizeflag);
2223
2224 obufp = op3out;
2225 op_ad = 0;
2226 if (dp->op3)
2227 (*dp->op3) (dp->bytemode3, sizeflag);
2228 }
2229 }
2230
2231 /* See if any prefixes were not used. If so, print the first one
2232 separately. If we don't do this, we'll wind up printing an
2233 instruction stream which does not precisely correspond to the
2234 bytes we are disassembling. */
2235 if ((prefixes & ~used_prefixes) != 0)
2236 {
2237 const char *name;
2238
2239 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2240 if (name == NULL((void *)0))
2241 name = INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>");
2242 (*info->fprintf_func) (info->stream, "%s", name);
2243 return 1;
2244 }
2245 if (rex & ~rex_used)
2246 {
2247 const char *name;
2248 name = prefix_name (rex | 0x40, priv.orig_sizeflag);
2249 if (name == NULL((void *)0))
2250 name = INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>");
2251 (*info->fprintf_func) (info->stream, "%s ", name);
2252 }
2253
2254 obufp = obuf + strlen (obuf);
2255 for (i = strlen (obuf); i < 6; i++)
2256 oappend (" ");
2257 oappend (" ");
2258 (*info->fprintf_func) (info->stream, "%s", obuf);
2259
2260 /* The enter and bound instructions are printed with operands in the same
2261 order as the intel book; everything else is printed in reverse order. */
2262 if (intel_syntax || two_source_ops)
2263 {
2264 first = op1out;
2265 second = op2out;
2266 third = op3out;
2267 op_ad = op_index[0];
2268 op_index[0] = op_index[2];
2269 op_index[2] = op_ad;
2270 }
2271 else
2272 {
2273 first = op3out;
2274 second = op2out;
2275 third = op1out;
2276 }
2277 needcomma = 0;
2278 if (*first)
2279 {
2280 if (op_index[0] != -1 && !op_riprel[0])
2281 (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
2282 else
2283 (*info->fprintf_func) (info->stream, "%s", first);
2284 needcomma = 1;
2285 }
2286 if (*second)
2287 {
2288 if (needcomma)
2289 (*info->fprintf_func) (info->stream, ",");
2290 if (op_index[1] != -1 && !op_riprel[1])
2291 (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
2292 else
2293 (*info->fprintf_func) (info->stream, "%s", second);
2294 needcomma = 1;
2295 }
2296 if (*third)
2297 {
2298 if (needcomma)
2299 (*info->fprintf_func) (info->stream, ",");
2300 if (op_index[2] != -1 && !op_riprel[2])
2301 (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
2302 else
2303 (*info->fprintf_func) (info->stream, "%s", third);
2304 }
2305 for (i = 0; i < 3; i++)
2306 if (op_index[i] != -1 && op_riprel[i])
2307 {
2308 (*info->fprintf_func) (info->stream, " # ");
2309 (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
2310 + op_address[op_index[i]]), info);
2311 }
2312 return codep - priv.the_buffer;
2313}
2314
2315static const char *float_mem[] = {
2316 /* d8 */
2317 "fadd{s||s|}",
2318 "fmul{s||s|}",
2319 "fcom{s||s|}",
2320 "fcomp{s||s|}",
2321 "fsub{s||s|}",
2322 "fsubr{s||s|}",
2323 "fdiv{s||s|}",
2324 "fdivr{s||s|}",
2325 /* d9 */
2326 "fld{s||s|}",
2327 "(bad)",
2328 "fst{s||s|}",
2329 "fstp{s||s|}",
2330 "fldenv",
2331 "fldcw",
2332 "fNstenv",
2333 "fNstcw",
2334 /* da */
2335 "fiadd{l||l|}",
2336 "fimul{l||l|}",
2337 "ficom{l||l|}",
2338 "ficomp{l||l|}",
2339 "fisub{l||l|}",
2340 "fisubr{l||l|}",
2341 "fidiv{l||l|}",
2342 "fidivr{l||l|}",
2343 /* db */
2344 "fild{l||l|}",
2345 "fisttp{l||l|}",
2346 "fist{l||l|}",
2347 "fistp{l||l|}",
2348 "(bad)",
2349 "fld{t||t|}",
2350 "(bad)",
2351 "fstp{t||t|}",
2352 /* dc */
2353 "fadd{l||l|}",
2354 "fmul{l||l|}",
2355 "fcom{l||l|}",
2356 "fcomp{l||l|}",
2357 "fsub{l||l|}",
2358 "fsubr{l||l|}",
2359 "fdiv{l||l|}",
2360 "fdivr{l||l|}",
2361 /* dd */
2362 "fld{l||l|}",
2363 "fisttpll",
2364 "fst{l||l|}",
2365 "fstp{l||l|}",
2366 "frstor",
2367 "(bad)",
2368 "fNsave",
2369 "fNstsw",
2370 /* de */
2371 "fiadd",
2372 "fimul",
2373 "ficom",
2374 "ficomp",
2375 "fisub",
2376 "fisubr",
2377 "fidiv",
2378 "fidivr",
2379 /* df */
2380 "fild",
2381 "fisttp",
2382 "fist",
2383 "fistp",
2384 "fbld",
2385 "fild{ll||ll|}",
2386 "fbstp",
2387 "fistpll",
2388};
2389
2390#define STOP_ST, 0 OP_ST, 0
2391#define STiOP_STi, 0 OP_STi, 0
2392
2393#define FGRPd9_2((void *)0), ((void *)0), 0, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 0, NULL((void *)0), 0, NULL((void *)0), 0
2394#define FGRPd9_4((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 1, NULL((void *)0), 0, NULL((void *)0), 0
2395#define FGRPd9_5((void *)0), ((void *)0), 2, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 2, NULL((void *)0), 0, NULL((void *)0), 0
2396#define FGRPd9_6((void *)0), ((void *)0), 3, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 3, NULL((void *)0), 0, NULL((void *)0), 0
2397#define FGRPd9_7((void *)0), ((void *)0), 4, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 4, NULL((void *)0), 0, NULL((void *)0), 0
2398#define FGRPda_5((void *)0), ((void *)0), 5, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 5, NULL((void *)0), 0, NULL((void *)0), 0
2399#define FGRPdb_4((void *)0), ((void *)0), 6, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 6, NULL((void *)0), 0, NULL((void *)0), 0
2400#define FGRPde_3((void *)0), ((void *)0), 7, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 7, NULL((void *)0), 0, NULL((void *)0), 0
2401#define FGRPdf_4((void *)0), ((void *)0), 8, ((void *)0), 0, ((void *)0), 0 NULL((void *)0), NULL((void *)0), 8, NULL((void *)0), 0, NULL((void *)0), 0
2402
2403static const struct dis386 float_reg[][8] = {
2404 /* d8 */
2405 {
2406 { "fadd", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2407 { "fmul", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2408 { "fcom", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2409 { "fcomp", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2410 { "fsub", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2411 { "fsubr", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2412 { "fdiv", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2413 { "fdivr", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2414 },
2415 /* d9 */
2416 {
2417 { "fld", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2418 { "fxch", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2419 { FGRPd9_2((void *)0), ((void *)0), 0, ((void *)0), 0, ((void *)0), 0 },
2420 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2421 { FGRPd9_4((void *)0), ((void *)0), 1, ((void *)0), 0, ((void *)0), 0 },
2422 { FGRPd9_5((void *)0), ((void *)0), 2, ((void *)0), 0, ((void *)0), 0 },
2423 { FGRPd9_6((void *)0), ((void *)0), 3, ((void *)0), 0, ((void *)0), 0 },
2424 { FGRPd9_7((void *)0), ((void *)0), 4, ((void *)0), 0, ((void *)0), 0 },
2425 },
2426 /* da */
2427 {
2428 { "fcmovb", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2429 { "fcmove", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2430 { "fcmovbe",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2431 { "fcmovu", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2432 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2433 { FGRPda_5((void *)0), ((void *)0), 5, ((void *)0), 0, ((void *)0), 0 },
2434 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2435 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2436 },
2437 /* db */
2438 {
2439 { "fcmovnb",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2440 { "fcmovne",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2441 { "fcmovnbe",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2442 { "fcmovnu",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2443 { FGRPdb_4((void *)0), ((void *)0), 6, ((void *)0), 0, ((void *)0), 0 },
2444 { "fucomi", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2445 { "fcomi", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2446 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2447 },
2448 /* dc */
2449 {
2450 { "fadd", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2451 { "fmul", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2452 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2453 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2454#if UNIXWARE_COMPAT1
2455 { "fsub", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2456 { "fsubr", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2457 { "fdiv", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2458 { "fdivr", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2459#else
2460 { "fsubr", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2461 { "fsub", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2462 { "fdivr", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2463 { "fdiv", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2464#endif
2465 },
2466 /* dd */
2467 {
2468 { "ffree", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2469 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2470 { "fst", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2471 { "fstp", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2472 { "fucom", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2473 { "fucomp", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2474 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2475 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2476 },
2477 /* de */
2478 {
2479 { "faddp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2480 { "fmulp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2481 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2482 { FGRPde_3((void *)0), ((void *)0), 7, ((void *)0), 0, ((void *)0), 0 },
2483#if UNIXWARE_COMPAT1
2484 { "fsubp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2485 { "fsubrp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2486 { "fdivp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2487 { "fdivrp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2488#else
2489 { "fsubrp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2490 { "fsubp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2491 { "fdivrp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2492 { "fdivp", STiOP_STi, 0, STOP_ST, 0, XX((void *)0), 0 },
2493#endif
2494 },
2495 /* df */
2496 {
2497 { "ffreep", STiOP_STi, 0, XX((void *)0), 0, XX((void *)0), 0 },
2498 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2499 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2500 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2501 { FGRPdf_4((void *)0), ((void *)0), 8, ((void *)0), 0, ((void *)0), 0 },
2502 { "fucomip",STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2503 { "fcomip", STOP_ST, 0, STiOP_STi, 0, XX((void *)0), 0 },
2504 { "(bad)", XX((void *)0), 0, XX((void *)0), 0, XX((void *)0), 0 },
2505 },
2506};
2507
2508static char *fgrps[][8] = {
2509 /* d9_2 0 */
2510 {
2511 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2512 },
2513
2514 /* d9_4 1 */
2515 {
2516 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
2517 },
2518
2519 /* d9_5 2 */
2520 {
2521 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
2522 },
2523
2524 /* d9_6 3 */
2525 {
2526 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
2527 },
2528
2529 /* d9_7 4 */
2530 {
2531 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
2532 },
2533
2534 /* da_5 5 */
2535 {
2536 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2537 },
2538
2539 /* db_4 6 */
2540 {
2541 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
2542 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
2543 },
2544
2545 /* de_3 7 */
2546 {
2547 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2548 },
2549
2550 /* df_4 8 */
2551 {
2552 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2553 },
2554};
2555
2556static void
2557dofloat (int sizeflag)
2558{
2559 const struct dis386 *dp;
2560 unsigned char floatop;
2561
2562 floatop = codep[-1];
2563
2564 if (mod != 3)
2565 {
2566 putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag);
2567 obufp = op1out;
2568 if (floatop == 0xdb)
2569 OP_E (x_mode6, sizeflag);
2570 else if (floatop == 0xdd)
2571 OP_E (d_mode4, sizeflag);
2572 else
2573 OP_E (v_mode2, sizeflag);
2574 return;
2575 }
2576 /* Skip mod/rm byte. */
2577 MODRM_CHECKif (!need_modrm) abort ();
2578 codep++;
2579
2580 dp = &float_reg[floatop - 0xd8][reg];
2581 if (dp->name == NULL((void *)0))
2582 {
2583 putop (fgrps[dp->bytemode1][rm], sizeflag);
2584
2585 /* Instruction fnstsw is only one with strange arg. */
2586 if (floatop == 0xdf && codep[-1] == 0xe0)
2587 strcpy (op1out, names16[0]);
2588 }
2589 else
2590 {
2591 putop (dp->name, sizeflag);
2592
2593 obufp = op1out;
2594 if (dp->op1)
2595 (*dp->op1) (dp->bytemode1, sizeflag);
2596 obufp = op2out;
2597 if (dp->op2)
2598 (*dp->op2) (dp->bytemode2, sizeflag);
2599 }
2600}
2601
2602static void
2603OP_ST (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
2604{
2605 oappend ("%st");
2606}
2607
2608static void
2609OP_STi (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
2610{
2611 sprintf (scratchbuf, "%%st(%d)", rm);
2612 oappend (scratchbuf + intel_syntax);
2613}
2614
2615/* Capital letters in template are macros. */
2616static int
2617putop (const char *template, int sizeflag)
2618{
2619 const char *p;
2620 int alt;
2621
2622 for (p = template; *p; p++)
2623 {
2624 switch (*p)
2625 {
2626 default:
2627 *obufp++ = *p;
2628 break;
2629 case '{':
2630 alt = 0;
2631 if (intel_syntax)
2632 alt += 1;
2633 if (mode_64bit)
2634 alt += 2;
2635 while (alt != 0)
2636 {
2637 while (*++p != '|')
2638 {
2639 if (*p == '}')
2640 {
2641 /* Alternative not valid. */
2642 strcpy (obuf, "(bad)");
2643 obufp = obuf + 5;
2644 return 1;
2645 }
2646 else if (*p == '\0')
2647 abort ();
2648 }
2649 alt--;
2650 }
2651 break;
2652 case '|':
2653 while (*++p != '}')
2654 {
2655 if (*p == '\0')
2656 abort ();
2657 }
2658 break;
2659 case '}':
2660 break;
2661 case 'A':
2662 if (intel_syntax)
2663 break;
2664 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS4))
2665 *obufp++ = 'b';
2666 break;
2667 case 'B':
2668 if (intel_syntax)
2669 break;
2670 if (sizeflag & SUFFIX_ALWAYS4)
2671 *obufp++ = 'b';
2672 break;
2673 case 'E': /* For jcxz/jecxz */
2674 if (mode_64bit)
2675 {
2676 if (sizeflag & AFLAG2)
2677 *obufp++ = 'r';
2678 else
2679 *obufp++ = 'e';
2680 }
2681 else
2682 if (sizeflag & AFLAG2)
2683 *obufp++ = 'e';
2684 used_prefixes |= (prefixes & PREFIX_ADDR0x400);
2685 break;
2686 case 'F':
2687 if (intel_syntax)
2688 break;
2689 if ((prefixes & PREFIX_ADDR0x400) || (sizeflag & SUFFIX_ALWAYS4))
2690 {
2691 if (sizeflag & AFLAG2)
2692 *obufp++ = mode_64bit ? 'q' : 'l';
2693 else
2694 *obufp++ = mode_64bit ? 'l' : 'w';
2695 used_prefixes |= (prefixes & PREFIX_ADDR0x400);
2696 }
2697 break;
2698 case 'H':
2699 if (intel_syntax)
2700 break;
2701 if ((prefixes & (PREFIX_CS8 | PREFIX_DS0x20)) == PREFIX_CS8
2702 || (prefixes & (PREFIX_CS8 | PREFIX_DS0x20)) == PREFIX_DS0x20)
2703 {
2704 used_prefixes |= prefixes & (PREFIX_CS8 | PREFIX_DS0x20);
2705 *obufp++ = ',';
2706 *obufp++ = 'p';
2707 if (prefixes & PREFIX_DS0x20)
2708 *obufp++ = 't';
2709 else
2710 *obufp++ = 'n';
2711 }
2712 break;
2713 case 'L':
2714 if (intel_syntax)
2715 break;
2716 if (sizeflag & SUFFIX_ALWAYS4)
2717 *obufp++ = 'l';
2718 break;
2719 case 'N':
2720 if ((prefixes & PREFIX_FWAIT0x800) == 0)
2721 *obufp++ = 'n';
2722 else
2723 used_prefixes |= PREFIX_FWAIT0x800;
2724 break;
2725 case 'O':
2726 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
2727 if (rex & REX_MODE648)
2728 *obufp++ = 'o';
2729 else
2730 *obufp++ = 'd';
2731 break;
2732 case 'T':
2733 if (intel_syntax)
2734 break;
2735 if (mode_64bit)
2736 {
2737 *obufp++ = 'q';
2738 break;
2739 }
2740 /* Fall through. */
2741 case 'P':
2742 if (intel_syntax)
2743 break;
2744 if ((prefixes & PREFIX_DATA0x200)
2745 || (rex & REX_MODE648)
2746 || (sizeflag & SUFFIX_ALWAYS4))
2747 {
2748 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
2749 if (rex & REX_MODE648)
2750 *obufp++ = 'q';
2751 else
2752 {
2753 if (sizeflag & DFLAG1)
2754 *obufp++ = 'l';
2755 else
2756 *obufp++ = 'w';
2757 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2758 }
2759 }
2760 break;
2761 case 'U':
2762 if (intel_syntax)
2763 break;
2764 if (mode_64bit)
2765 {
2766 *obufp++ = 'q';
2767 break;
2768 }
2769 /* Fall through. */
2770 case 'Q':
2771 if (intel_syntax)
2772 break;
2773 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
2774 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS4))
2775 {
2776 if (rex & REX_MODE648)
2777 *obufp++ = 'q';
2778 else
2779 {
2780 if (sizeflag & DFLAG1)
2781 *obufp++ = 'l';
2782 else
2783 *obufp++ = 'w';
2784 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2785 }
2786 }
2787 break;
2788 case 'R':
2789 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
2790 if (intel_syntax)
2791 {
2792 if (rex & REX_MODE648)
2793 {
2794 *obufp++ = 'q';
2795 *obufp++ = 't';
2796 }
2797 else if (sizeflag & DFLAG1)
2798 {
2799 *obufp++ = 'd';
2800 *obufp++ = 'q';
2801 }
2802 else
2803 {
2804 *obufp++ = 'w';
2805 *obufp++ = 'd';
2806 }
2807 }
2808 else
2809 {
2810 if (rex & REX_MODE648)
2811 *obufp++ = 'q';
2812 else if (sizeflag & DFLAG1)
2813 *obufp++ = 'l';
2814 else
2815 *obufp++ = 'w';
2816 }
2817 if (!(rex & REX_MODE648))
2818 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2819 break;
2820 case 'S':
2821 if (intel_syntax)
2822 break;
2823 if (sizeflag & SUFFIX_ALWAYS4)
2824 {
2825 if (rex & REX_MODE648)
2826 *obufp++ = 'q';
2827 else
2828 {
2829 if (sizeflag & DFLAG1)
2830 *obufp++ = 'l';
2831 else
2832 *obufp++ = 'w';
2833 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2834 }
2835 }
2836 break;
2837 case 'X':
2838 if (prefixes & PREFIX_DATA0x200)
2839 *obufp++ = 'd';
2840 else
2841 *obufp++ = 's';
2842 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2843 break;
2844 case 'Y':
2845 if (intel_syntax)
2846 break;
2847 if (rex & REX_MODE648)
2848 {
2849 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
2850 *obufp++ = 'q';
2851 }
2852 break;
2853 /* implicit operand size 'l' for i386 or 'q' for x86-64 */
2854 case 'W':
2855 /* operand size flag for cwtl, cbtw */
2856 USED_REX (0){ if (0) rex_used |= (rex & 0) ? (0) | 0x40 : 0; else rex_used
|= 0x40; }
;
2857 if (rex)
2858 *obufp++ = 'l';
2859 else if (sizeflag & DFLAG1)
2860 *obufp++ = 'w';
2861 else
2862 *obufp++ = 'b';
2863 if (intel_syntax)
2864 {
2865 if (rex)
2866 {
2867 *obufp++ = 'q';
2868 *obufp++ = 'e';
2869 }
2870 if (sizeflag & DFLAG1)
2871 {
2872 *obufp++ = 'd';
2873 *obufp++ = 'e';
2874 }
2875 else
2876 {
2877 *obufp++ = 'w';
2878 }
2879 }
2880 if (!rex)
2881 used_prefixes |= (prefixes & PREFIX_DATA0x200);
2882 break;
2883 }
2884 }
2885 *obufp = 0;
2886 return 0;
2887}
2888
2889static void
2890oappend (const char *s)
2891{
2892 strcpy (obufp, s);
2893 obufp += strlen (s);
2894}
2895
2896static void
2897append_seg (void)
2898{
2899 if (prefixes & PREFIX_CS8)
2900 {
2901 used_prefixes |= PREFIX_CS8;
2902 oappend ("%cs:" + intel_syntax);
2903 }
2904 if (prefixes & PREFIX_DS0x20)
2905 {
2906 used_prefixes |= PREFIX_DS0x20;
2907 oappend ("%ds:" + intel_syntax);
2908 }
2909 if (prefixes & PREFIX_SS0x10)
2910 {
2911 used_prefixes |= PREFIX_SS0x10;
2912 oappend ("%ss:" + intel_syntax);
2913 }
2914 if (prefixes & PREFIX_ES0x40)
2915 {
2916 used_prefixes |= PREFIX_ES0x40;
2917 oappend ("%es:" + intel_syntax);
2918 }
2919 if (prefixes & PREFIX_FS0x80)
2920 {
2921 used_prefixes |= PREFIX_FS0x80;
2922 oappend ("%fs:" + intel_syntax);
2923 }
2924 if (prefixes & PREFIX_GS0x100)
2925 {
2926 used_prefixes |= PREFIX_GS0x100;
2927 oappend ("%gs:" + intel_syntax);
2928 }
2929}
2930
2931static void
2932OP_indirE (int bytemode, int sizeflag)
2933{
2934 if (!intel_syntax)
2935 oappend ("*");
2936 OP_E (bytemode, sizeflag);
2937}
2938
2939static void
2940print_operand_value (char *buf, int hex, bfd_vma disp)
2941{
2942 if (mode_64bit)
2943 {
2944 if (hex)
2945 {
2946 char tmp[30];
2947 int i;
2948 buf[0] = '0';
2949 buf[1] = 'x';
2950 sprintf_vma (tmp, disp)sprintf (tmp, "%016lx", disp);
2951 for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
2952 strcpy (buf + 2, tmp + i);
2953 }
2954 else
2955 {
2956 bfd_signed_vma v = disp;
2957 char tmp[30];
2958 int i;
2959 if (v < 0)
2960 {
2961 *(buf++) = '-';
2962 v = -disp;
2963 /* Check for possible overflow on 0x8000000000000000. */
2964 if (v < 0)
2965 {
2966 strcpy (buf, "9223372036854775808");
2967 return;
2968 }
2969 }
2970 if (!v)
2971 {
2972 strcpy (buf, "0");
2973 return;
2974 }
2975
2976 i = 0;
2977 tmp[29] = 0;
2978 while (v)
2979 {
2980 tmp[28 - i] = (v % 10) + '0';
2981 v /= 10;
2982 i++;
2983 }
2984 strcpy (buf, tmp + 29 - i);
2985 }
2986 }
2987 else
2988 {
2989 if (hex)
2990 sprintf (buf, "0x%x", (unsigned int) disp);
2991 else
2992 sprintf (buf, "%d", (int) disp);
2993 }
2994}
2995
2996static void
2997OP_E (int bytemode, int sizeflag)
2998{
2999 bfd_vma disp;
3000 int add = 0;
3001 int riprel = 0;
3002 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3003 if (rex & REX_EXTZ1)
3004 add += 8;
3005
3006 /* Skip mod/rm byte. */
3007 MODRM_CHECKif (!need_modrm) abort ();
3008 codep++;
3009
3010 if (mod == 3)
3011 {
3012 switch (bytemode)
3013 {
3014 case b_mode1:
3015 USED_REX (0){ if (0) rex_used |= (rex & 0) ? (0) | 0x40 : 0; else rex_used
|= 0x40; }
;
3016 if (rex)
3017 oappend (names8rex[rm + add]);
3018 else
3019 oappend (names8[rm + add]);
3020 break;
3021 case w_mode3:
3022 oappend (names16[rm + add]);
3023 break;
3024 case d_mode4:
3025 oappend (names32[rm + add]);
3026 break;
3027 case q_mode5:
3028 oappend (names64[rm + add]);
3029 break;
3030 case m_mode7:
3031 if (mode_64bit)
3032 oappend (names64[rm + add]);
3033 else
3034 oappend (names32[rm + add]);
3035 break;
3036 case v_mode2:
3037 case dq_mode10:
3038 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3039 if (rex & REX_MODE648)
3040 oappend (names64[rm + add]);
3041 else if ((sizeflag & DFLAG1) || bytemode == dq_mode10)
3042 oappend (names32[rm + add]);
3043 else
3044 oappend (names16[rm + add]);
3045 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3046 break;
3047 case 0:
3048 break;
3049 default:
3050 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3051 break;
3052 }
3053 return;
3054 }
3055
3056 disp = 0;
3057 append_seg ();
3058
3059 if ((sizeflag & AFLAG2) || mode_64bit) /* 32 bit address mode */
3060 {
3061 int havesib;
3062 int havebase;
3063 int base;
3064 int index = 0;
3065 int scale = 0;
3066
3067 havesib = 0;
3068 havebase = 1;
3069 base = rm;
3070
3071 if (base == 4)
3072 {
3073 havesib = 1;
3074 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3075 scale = (*codep >> 6) & 3;
3076 index = (*codep >> 3) & 7;
3077 base = *codep & 7;
3078 USED_REX (REX_EXTY){ if (2) rex_used |= (rex & 2) ? (2) | 0x40 : 0; else rex_used
|= 0x40; }
;
3079 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3080 if (rex & REX_EXTY2)
3081 index += 8;
3082 if (rex & REX_EXTZ1)
3083 base += 8;
3084 codep++;
3085 }
3086
3087 switch (mod)
3088 {
3089 case 0:
3090 if ((base & 7) == 5)
3091 {
3092 havebase = 0;
3093 if (mode_64bit && !havesib && (sizeflag & AFLAG2))
3094 riprel = 1;
3095 disp = get32s ();
3096 }
3097 break;
3098 case 1:
3099 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3100 disp = *codep++;
3101 if ((disp & 0x80) != 0)
3102 disp -= 0x100;
3103 break;
3104 case 2:
3105 disp = get32s ();
3106 break;
3107 }
3108
3109 if (!intel_syntax)
3110 if (mod != 0 || (base & 7) == 5)
3111 {
3112 print_operand_value (scratchbuf, !riprel, disp);
3113 oappend (scratchbuf);
3114 if (riprel)
3115 {
3116 set_op (disp, 1);
3117 oappend ("(%rip)");
3118 }
3119 }
3120
3121 if (havebase || (havesib && (index != 4 || scale != 0)))
3122 {
3123 if (intel_syntax)
3124 {
3125 switch (bytemode)
3126 {
3127 case b_mode1:
3128 oappend ("BYTE PTR ");
3129 break;
3130 case w_mode3:
3131 oappend ("WORD PTR ");
3132 break;
3133 case v_mode2:
3134 oappend ("DWORD PTR ");
3135 break;
3136 case d_mode4:
3137 oappend ("QWORD PTR ");
3138 break;
3139 case m_mode7:
3140 if (mode_64bit)
3141 oappend ("DWORD PTR ");
3142 else
3143 oappend ("QWORD PTR ");
3144 break;
3145 case x_mode6:
3146 oappend ("XWORD PTR ");
3147 break;
3148 default:
3149 break;
3150 }
3151 }
3152 *obufp++ = open_char;
3153 if (intel_syntax && riprel)
3154 oappend ("rip + ");
3155 *obufp = '\0';
3156 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3157 if (!havesib && (rex & REX_EXTZ1))
3158 base += 8;
3159 if (havebase)
3160 oappend (mode_64bit && (sizeflag & AFLAG2)
3161 ? names64[base] : names32[base]);
3162 if (havesib)
3163 {
3164 if (index != 4)
3165 {
3166 if (intel_syntax)
3167 {
3168 if (havebase)
3169 {
3170 *obufp++ = separator_char;
3171 *obufp = '\0';
3172 }
3173 sprintf (scratchbuf, "%s",
3174 mode_64bit && (sizeflag & AFLAG2)
3175 ? names64[index] : names32[index]);
3176 }
3177 else
3178 sprintf (scratchbuf, ",%s",
3179 mode_64bit && (sizeflag & AFLAG2)
3180 ? names64[index] : names32[index]);
3181 oappend (scratchbuf);
3182 }
3183 if (scale != 0 || (!intel_syntax && index != 4))
3184 {
3185 *obufp++ = scale_char;
3186 *obufp = '\0';
3187 sprintf (scratchbuf, "%d", 1 << scale);
3188 oappend (scratchbuf);
3189 }
3190 }
3191 if (intel_syntax)
3192 if (mod != 0 || (base & 7) == 5)
3193 {
3194 /* Don't print zero displacements. */
3195 if (disp != 0)
3196 {
3197 if ((bfd_signed_vma) disp > 0)
3198 {
3199 *obufp++ = '+';
3200 *obufp = '\0';
3201 }
3202
3203 print_operand_value (scratchbuf, 0, disp);
3204 oappend (scratchbuf);
3205 }
3206 }
3207
3208 *obufp++ = close_char;
3209 *obufp = '\0';
3210 }
3211 else if (intel_syntax)
3212 {
3213 if (mod != 0 || (base & 7) == 5)
3214 {
3215 if (prefixes & (PREFIX_CS8 | PREFIX_SS0x10 | PREFIX_DS0x20
3216 | PREFIX_ES0x40 | PREFIX_FS0x80 | PREFIX_GS0x100))
3217 ;
3218 else
3219 {
3220 oappend (names_seg[ds_reg103 - es_reg100]);
3221 oappend (":");
3222 }
3223 print_operand_value (scratchbuf, 1, disp);
3224 oappend (scratchbuf);
3225 }
3226 }
3227 }
3228 else
3229 { /* 16 bit address mode */
3230 switch (mod)
3231 {
3232 case 0:
3233 if ((rm & 7) == 6)
3234 {
3235 disp = get16 ();
3236 if ((disp & 0x8000) != 0)
3237 disp -= 0x10000;
3238 }
3239 break;
3240 case 1:
3241 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3242 disp = *codep++;
3243 if ((disp & 0x80) != 0)
3244 disp -= 0x100;
3245 break;
3246 case 2:
3247 disp = get16 ();
3248 if ((disp & 0x8000) != 0)
3249 disp -= 0x10000;
3250 break;
3251 }
3252
3253 if (!intel_syntax)
3254 if (mod != 0 || (rm & 7) == 6)
3255 {
3256 print_operand_value (scratchbuf, 0, disp);
3257 oappend (scratchbuf);
3258 }
3259
3260 if (mod != 0 || (rm & 7) != 6)
3261 {
3262 *obufp++ = open_char;
3263 *obufp = '\0';
3264 oappend (index16[rm + add]);
3265 *obufp++ = close_char;
3266 *obufp = '\0';
3267 }
3268 }
3269}
3270
3271static void
3272OP_G (int bytemode, int sizeflag)
3273{
3274 int add = 0;
3275 USED_REX (REX_EXTX){ if (4) rex_used |= (rex & 4) ? (4) | 0x40 : 0; else rex_used
|= 0x40; }
;
3276 if (rex & REX_EXTX4)
3277 add += 8;
3278 switch (bytemode)
3279 {
3280 case b_mode1:
3281 USED_REX (0){ if (0) rex_used |= (rex & 0) ? (0) | 0x40 : 0; else rex_used
|= 0x40; }
;
3282 if (rex)
3283 oappend (names8rex[reg + add]);
3284 else
3285 oappend (names8[reg + add]);
3286 break;
3287 case w_mode3:
3288 oappend (names16[reg + add]);
3289 break;
3290 case d_mode4:
3291 oappend (names32[reg + add]);
3292 break;
3293 case q_mode5:
3294 oappend (names64[reg + add]);
3295 break;
3296 case v_mode2:
3297 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3298 if (rex & REX_MODE648)
3299 oappend (names64[reg + add]);
3300 else if (sizeflag & DFLAG1)
3301 oappend (names32[reg + add]);
3302 else
3303 oappend (names16[reg + add]);
3304 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3305 break;
3306 default:
3307 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3308 break;
3309 }
3310}
3311
3312static bfd_vma
3313get64 (void)
3314{
3315 bfd_vma x;
3316#ifdef BFD64
3317 unsigned int a;
3318 unsigned int b;
3319
3320 FETCH_DATA (the_info, codep + 8)((codep + 8) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 8))
)
;
3321 a = *codep++ & 0xff;
3322 a |= (*codep++ & 0xff) << 8;
3323 a |= (*codep++ & 0xff) << 16;
3324 a |= (*codep++ & 0xff) << 24;
3325 b = *codep++ & 0xff;
3326 b |= (*codep++ & 0xff) << 8;
3327 b |= (*codep++ & 0xff) << 16;
3328 b |= (*codep++ & 0xff) << 24;
3329 x = a + ((bfd_vma) b << 32);
3330#else
3331 abort ();
3332 x = 0;
3333#endif
3334 return x;
3335}
3336
3337static bfd_signed_vma
3338get32 (void)
3339{
3340 bfd_signed_vma x = 0;
3341
3342 FETCH_DATA (the_info, codep + 4)((codep + 4) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 4))
)
;
3343 x = *codep++ & (bfd_signed_vma) 0xff;
3344 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
3345 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
3346 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
3347 return x;
3348}
3349
3350static bfd_signed_vma
3351get32s (void)
3352{
3353 bfd_signed_vma x = 0;
3354
3355 FETCH_DATA (the_info, codep + 4)((codep + 4) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 4))
)
;
3356 x = *codep++ & (bfd_signed_vma) 0xff;
3357 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
3358 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
3359 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
3360
3361 x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
3362
3363 return x;
3364}
3365
3366static int
3367get16 (void)
3368{
3369 int x = 0;
3370
3371 FETCH_DATA (the_info, codep + 2)((codep + 2) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 2))
)
;
3372 x = *codep++ & 0xff;
3373 x |= (*codep++ & 0xff) << 8;
3374 return x;
3375}
3376
3377static void
3378set_op (bfd_vma op, int riprel)
3379{
3380 op_index[op_ad] = op_ad;
3381 if (mode_64bit)
3382 {
3383 op_address[op_ad] = op;
3384 op_riprel[op_ad] = riprel;
3385 }
3386 else
3387 {
3388 /* Mask to get a 32-bit address. */
3389 op_address[op_ad] = op & 0xffffffff;
3390 op_riprel[op_ad] = riprel & 0xffffffff;
3391 }
3392}
3393
3394static void
3395OP_REG (int code, int sizeflag)
3396{
3397 const char *s;
3398 int add = 0;
3399 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3400 if (rex & REX_EXTZ1)
3401 add = 8;
3402
3403 switch (code)
3404 {
3405 case indir_dx_reg150:
3406 if (intel_syntax)
3407 s = "[dx]";
3408 else
3409 s = "(%dx)";
3410 break;
3411 case ax_reg124: case cx_reg125: case dx_reg126: case bx_reg127:
3412 case sp_reg128: case bp_reg129: case si_reg130: case di_reg131:
3413 s = names16[code - ax_reg124 + add];
3414 break;
3415 case es_reg100: case ss_reg102: case cs_reg101:
3416 case ds_reg103: case fs_reg104: case gs_reg105:
3417 s = names_seg[code - es_reg100 + add];
3418 break;
3419 case al_reg116: case ah_reg120: case cl_reg117: case ch_reg121:
3420 case dl_reg118: case dh_reg122: case bl_reg119: case bh_reg123:
3421 USED_REX (0){ if (0) rex_used |= (rex & 0) ? (0) | 0x40 : 0; else rex_used
|= 0x40; }
;
3422 if (rex)
3423 s = names8rex[code - al_reg116 + add];
3424 else
3425 s = names8[code - al_reg116];
3426 break;
3427 case rAX_reg132: case rCX_reg133: case rDX_reg134: case rBX_reg135:
3428 case rSP_reg136: case rBP_reg137: case rSI_reg138: case rDI_reg139:
3429 if (mode_64bit)
3430 {
3431 s = names64[code - rAX_reg132 + add];
3432 break;
3433 }
3434 code += eAX_reg108 - rAX_reg132;
3435 /* Fall through. */
3436 case eAX_reg108: case eCX_reg109: case eDX_reg110: case eBX_reg111:
3437 case eSP_reg112: case eBP_reg113: case eSI_reg114: case eDI_reg115:
3438 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3439 if (rex & REX_MODE648)
3440 s = names64[code - eAX_reg108 + add];
3441 else if (sizeflag & DFLAG1)
3442 s = names32[code - eAX_reg108 + add];
3443 else
3444 s = names16[code - eAX_reg108 + add];
3445 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3446 break;
3447 default:
3448 s = INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>");
3449 break;
3450 }
3451 oappend (s);
3452}
3453
3454static void
3455OP_IMREG (int code, int sizeflag)
3456{
3457 const char *s;
3458
3459 switch (code)
3460 {
3461 case indir_dx_reg150:
3462 if (intel_syntax)
3463 s = "[dx]";
3464 else
3465 s = "(%dx)";
3466 break;
3467 case ax_reg124: case cx_reg125: case dx_reg126: case bx_reg127:
3468 case sp_reg128: case bp_reg129: case si_reg130: case di_reg131:
3469 s = names16[code - ax_reg124];
3470 break;
3471 case es_reg100: case ss_reg102: case cs_reg101:
3472 case ds_reg103: case fs_reg104: case gs_reg105:
3473 s = names_seg[code - es_reg100];
3474 break;
3475 case al_reg116: case ah_reg120: case cl_reg117: case ch_reg121:
3476 case dl_reg118: case dh_reg122: case bl_reg119: case bh_reg123:
3477 USED_REX (0){ if (0) rex_used |= (rex & 0) ? (0) | 0x40 : 0; else rex_used
|= 0x40; }
;
3478 if (rex)
3479 s = names8rex[code - al_reg116];
3480 else
3481 s = names8[code - al_reg116];
3482 break;
3483 case eAX_reg108: case eCX_reg109: case eDX_reg110: case eBX_reg111:
3484 case eSP_reg112: case eBP_reg113: case eSI_reg114: case eDI_reg115:
3485 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3486 if (rex & REX_MODE648)
3487 s = names64[code - eAX_reg108];
3488 else if (sizeflag & DFLAG1)
3489 s = names32[code - eAX_reg108];
3490 else
3491 s = names16[code - eAX_reg108];
3492 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3493 break;
3494 default:
3495 s = INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>");
3496 break;
3497 }
3498 oappend (s);
3499}
3500
3501static void
3502OP_I (int bytemode, int sizeflag)
3503{
3504 bfd_signed_vma op;
3505 bfd_signed_vma mask = -1;
3506
3507 switch (bytemode)
3508 {
3509 case b_mode1:
3510 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3511 op = *codep++;
3512 mask = 0xff;
3513 break;
3514 case q_mode5:
3515 if (mode_64bit)
3516 {
3517 op = get32s ();
3518 break;
3519 }
3520 /* Fall through. */
3521 case v_mode2:
3522 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3523 if (rex & REX_MODE648)
3524 op = get32s ();
3525 else if (sizeflag & DFLAG1)
3526 {
3527 op = get32 ();
3528 mask = 0xffffffff;
3529 }
3530 else
3531 {
3532 op = get16 ();
3533 mask = 0xfffff;
3534 }
3535 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3536 break;
3537 case w_mode3:
3538 mask = 0xfffff;
3539 op = get16 ();
3540 break;
3541 default:
3542 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3543 return;
3544 }
3545
3546 op &= mask;
3547 scratchbuf[0] = '$';
3548 print_operand_value (scratchbuf + 1, 1, op);
3549 oappend (scratchbuf + intel_syntax);
3550 scratchbuf[0] = '\0';
3551}
3552
3553static void
3554OP_I64 (int bytemode, int sizeflag)
3555{
3556 bfd_signed_vma op;
3557 bfd_signed_vma mask = -1;
3558
3559 if (!mode_64bit)
3560 {
3561 OP_I (bytemode, sizeflag);
3562 return;
3563 }
3564
3565 switch (bytemode)
3566 {
3567 case b_mode1:
3568 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3569 op = *codep++;
3570 mask = 0xff;
3571 break;
3572 case v_mode2:
3573 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3574 if (rex & REX_MODE648)
3575 op = get64 ();
3576 else if (sizeflag & DFLAG1)
3577 {
3578 op = get32 ();
3579 mask = 0xffffffff;
3580 }
3581 else
3582 {
3583 op = get16 ();
3584 mask = 0xfffff;
3585 }
3586 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3587 break;
3588 case w_mode3:
3589 mask = 0xfffff;
3590 op = get16 ();
3591 break;
3592 default:
3593 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3594 return;
3595 }
3596
3597 op &= mask;
3598 scratchbuf[0] = '$';
3599 print_operand_value (scratchbuf + 1, 1, op);
3600 oappend (scratchbuf + intel_syntax);
3601 scratchbuf[0] = '\0';
3602}
3603
3604static void
3605OP_sI (int bytemode, int sizeflag)
3606{
3607 bfd_signed_vma op;
3608 bfd_signed_vma mask = -1;
3609
3610 switch (bytemode)
3611 {
3612 case b_mode1:
3613 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3614 op = *codep++;
3615 if ((op & 0x80) != 0)
3616 op -= 0x100;
3617 mask = 0xffffffff;
3618 break;
3619 case v_mode2:
3620 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3621 if (rex & REX_MODE648)
3622 op = get32s ();
3623 else if (sizeflag & DFLAG1)
3624 {
3625 op = get32s ();
3626 mask = 0xffffffff;
Value stored to 'mask' is never read
3627 }
3628 else
3629 {
3630 mask = 0xffffffff;
3631 op = get16 ();
3632 if ((op & 0x8000) != 0)
3633 op -= 0x10000;
3634 }
3635 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3636 break;
3637 case w_mode3:
3638 op = get16 ();
3639 mask = 0xffffffff;
3640 if ((op & 0x8000) != 0)
3641 op -= 0x10000;
3642 break;
3643 default:
3644 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3645 return;
3646 }
3647
3648 scratchbuf[0] = '$';
3649 print_operand_value (scratchbuf + 1, 1, op);
3650 oappend (scratchbuf + intel_syntax);
3651}
3652
3653static void
3654OP_J (int bytemode, int sizeflag)
3655{
3656 bfd_vma disp;
3657 bfd_vma mask = -1;
3658
3659 switch (bytemode)
3660 {
3661 case b_mode1:
3662 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
3663 disp = *codep++;
3664 if ((disp & 0x80) != 0)
3665 disp -= 0x100;
3666 break;
3667 case v_mode2:
3668 if (sizeflag & DFLAG1)
3669 disp = get32s ();
3670 else
3671 {
3672 disp = get16 ();
3673 /* For some reason, a data16 prefix on a jump instruction
3674 means that the pc is masked to 16 bits after the
3675 displacement is added! */
3676 mask = 0xffff;
3677 }
3678 break;
3679 default:
3680 oappend (INTERNAL_DISASSEMBLER_ERROR("<internal disassembler error>"));
3681 return;
3682 }
3683 disp = (start_pc + codep - start_codep + disp) & mask;
3684 set_op (disp, 0);
3685 print_operand_value (scratchbuf, 1, disp);
3686 oappend (scratchbuf);
3687}
3688
3689static void
3690OP_SEG (int dummy ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3691{
3692 oappend (names_seg[reg]);
3693}
3694
3695static void
3696OP_DIR (int dummy ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag)
3697{
3698 int seg, offset;
3699
3700 if (sizeflag & DFLAG1)
3701 {
3702 offset = get32 ();
3703 seg = get16 ();
3704 }
3705 else
3706 {
3707 offset = get16 ();
3708 seg = get16 ();
3709 }
3710 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3711 if (intel_syntax)
3712 sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
3713 else
3714 sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
3715 oappend (scratchbuf);
3716}
3717
3718static void
3719OP_OFF (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag)
3720{
3721 bfd_vma off;
3722
3723 append_seg ();
3724
3725 if ((sizeflag & AFLAG2) || mode_64bit)
3726 off = get32 ();
3727 else
3728 off = get16 ();
3729
3730 if (intel_syntax)
3731 {
3732 if (!(prefixes & (PREFIX_CS8 | PREFIX_SS0x10 | PREFIX_DS0x20
3733 | PREFIX_ES0x40 | PREFIX_FS0x80 | PREFIX_GS0x100)))
3734 {
3735 oappend (names_seg[ds_reg103 - es_reg100]);
3736 oappend (":");
3737 }
3738 }
3739 print_operand_value (scratchbuf, 1, off);
3740 oappend (scratchbuf);
3741}
3742
3743static void
3744OP_OFF64 (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3745{
3746 bfd_vma off;
3747
3748 if (!mode_64bit)
3749 {
3750 OP_OFF (bytemode, sizeflag);
3751 return;
3752 }
3753
3754 append_seg ();
3755
3756 off = get64 ();
3757
3758 if (intel_syntax)
3759 {
3760 if (!(prefixes & (PREFIX_CS8 | PREFIX_SS0x10 | PREFIX_DS0x20
3761 | PREFIX_ES0x40 | PREFIX_FS0x80 | PREFIX_GS0x100)))
3762 {
3763 oappend (names_seg[ds_reg103 - es_reg100]);
3764 oappend (":");
3765 }
3766 }
3767 print_operand_value (scratchbuf, 1, off);
3768 oappend (scratchbuf);
3769}
3770
3771static void
3772ptr_reg (int code, int sizeflag)
3773{
3774 const char *s;
3775 if (intel_syntax)
3776 oappend ("[");
3777 else
3778 oappend ("(");
3779
3780 USED_REX (REX_MODE64){ if (8) rex_used |= (rex & 8) ? (8) | 0x40 : 0; else rex_used
|= 0x40; }
;
3781 if (rex & REX_MODE648)
3782 {
3783 if (!(sizeflag & AFLAG2))
3784 s = names32[code - eAX_reg108];
3785 else
3786 s = names64[code - eAX_reg108];
3787 }
3788 else if (sizeflag & AFLAG2)
3789 s = names32[code - eAX_reg108];
3790 else
3791 s = names16[code - eAX_reg108];
3792 oappend (s);
3793 if (intel_syntax)
3794 oappend ("]");
3795 else
3796 oappend (")");
3797}
3798
3799static void
3800OP_ESreg (int code, int sizeflag)
3801{
3802 oappend ("%es:" + intel_syntax);
3803 ptr_reg (code, sizeflag);
3804}
3805
3806static void
3807OP_DSreg (int code, int sizeflag)
3808{
3809 if ((prefixes
3810 & (PREFIX_CS8
3811 | PREFIX_DS0x20
3812 | PREFIX_SS0x10
3813 | PREFIX_ES0x40
3814 | PREFIX_FS0x80
3815 | PREFIX_GS0x100)) == 0)
3816 prefixes |= PREFIX_DS0x20;
3817 append_seg ();
3818 ptr_reg (code, sizeflag);
3819}
3820
3821static void
3822OP_C (int dummy ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3823{
3824 int add = 0;
3825 USED_REX (REX_EXTX){ if (4) rex_used |= (rex & 4) ? (4) | 0x40 : 0; else rex_used
|= 0x40; }
;
3826 if (rex & REX_EXTX4)
3827 add = 8;
3828 sprintf (scratchbuf, "%%cr%d", reg + add);
3829 oappend (scratchbuf + intel_syntax);
3830}
3831
3832static void
3833OP_D (int dummy ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3834{
3835 int add = 0;
3836 USED_REX (REX_EXTX){ if (4) rex_used |= (rex & 4) ? (4) | 0x40 : 0; else rex_used
|= 0x40; }
;
3837 if (rex & REX_EXTX4)
3838 add = 8;
3839 if (intel_syntax)
3840 sprintf (scratchbuf, "db%d", reg + add);
3841 else
3842 sprintf (scratchbuf, "%%db%d", reg + add);
3843 oappend (scratchbuf);
3844}
3845
3846static void
3847OP_T (int dummy ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3848{
3849 sprintf (scratchbuf, "%%tr%d", reg);
3850 oappend (scratchbuf + intel_syntax);
3851}
3852
3853static void
3854OP_Rd (int bytemode, int sizeflag)
3855{
3856 if (mod == 3)
3857 OP_E (bytemode, sizeflag);
3858 else
3859 BadOp ();
3860}
3861
3862static void
3863OP_MMX (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3864{
3865 int add = 0;
3866 USED_REX (REX_EXTX){ if (4) rex_used |= (rex & 4) ? (4) | 0x40 : 0; else rex_used
|= 0x40; }
;
3867 if (rex & REX_EXTX4)
3868 add = 8;
3869 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3870 if (prefixes & PREFIX_DATA0x200)
3871 sprintf (scratchbuf, "%%xmm%d", reg + add);
3872 else
3873 sprintf (scratchbuf, "%%mm%d", reg + add);
3874 oappend (scratchbuf + intel_syntax);
3875}
3876
3877static void
3878OP_XMM (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3879{
3880 int add = 0;
3881 USED_REX (REX_EXTX){ if (4) rex_used |= (rex & 4) ? (4) | 0x40 : 0; else rex_used
|= 0x40; }
;
3882 if (rex & REX_EXTX4)
3883 add = 8;
3884 sprintf (scratchbuf, "%%xmm%d", reg + add);
3885 oappend (scratchbuf + intel_syntax);
3886}
3887
3888static void
3889OP_EM (int bytemode, int sizeflag)
3890{
3891 int add = 0;
3892 if (mod != 3)
3893 {
3894 OP_E (bytemode, sizeflag);
3895 return;
3896 }
3897 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3898 if (rex & REX_EXTZ1)
3899 add = 8;
3900
3901 /* Skip mod/rm byte. */
3902 MODRM_CHECKif (!need_modrm) abort ();
3903 codep++;
3904 used_prefixes |= (prefixes & PREFIX_DATA0x200);
3905 if (prefixes & PREFIX_DATA0x200)
3906 sprintf (scratchbuf, "%%xmm%d", rm + add);
3907 else
3908 sprintf (scratchbuf, "%%mm%d", rm + add);
3909 oappend (scratchbuf + intel_syntax);
3910}
3911
3912static void
3913OP_EX (int bytemode, int sizeflag)
3914{
3915 int add = 0;
3916 if (mod != 3)
3917 {
3918 OP_E (bytemode, sizeflag);
3919 return;
3920 }
3921 USED_REX (REX_EXTZ){ if (1) rex_used |= (rex & 1) ? (1) | 0x40 : 0; else rex_used
|= 0x40; }
;
3922 if (rex & REX_EXTZ1)
3923 add = 8;
3924
3925 /* Skip mod/rm byte. */
3926 MODRM_CHECKif (!need_modrm) abort ();
3927 codep++;
3928 sprintf (scratchbuf, "%%xmm%d", rm + add);
3929 oappend (scratchbuf + intel_syntax);
3930}
3931
3932static void
3933OP_MS (int bytemode, int sizeflag)
3934{
3935 if (mod == 3)
3936 OP_EM (bytemode, sizeflag);
3937 else
3938 BadOp ();
3939}
3940
3941static void
3942OP_XS (int bytemode, int sizeflag)
3943{
3944 if (mod == 3)
3945 OP_EX (bytemode, sizeflag);
3946 else
3947 BadOp ();
3948}
3949
3950static void
3951OP_M (int bytemode, int sizeflag)
3952{
3953 if (mod == 3)
3954 BadOp (); /* bad lea,lds,les,lfs,lgs,lss modrm */
3955 else
3956 OP_E (bytemode, sizeflag);
3957}
3958
3959static void
3960OP_0fae (int bytemode, int sizeflag)
3961{
3962 if (mod == 3)
3963 {
3964 if (reg == 7)
3965 strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
3966 else if (reg == 6)
3967 strcpy (obuf + strlen (obuf) - sizeof ("xsaveopt") + 1, "mfence");
3968 else if (reg == 5)
3969 strcpy (obuf + strlen (obuf) - sizeof ("xrstor") + 1, "lfence");
3970 bytemode = 0;
3971
3972 if (reg < 5 || rm != 0)
3973 {
3974 BadOp (); /* bad sfence, mfence, or lfence */
3975 return;
3976 }
3977 }
3978 else if (reg < 5)
3979 {
3980 BadOp (); /* bad sfence, mfence, or lfence */
3981 return;
3982 }
3983
3984 OP_E (bytemode, sizeflag);
3985}
3986
3987static void
3988NOP_Fixup (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3989{
3990 /* NOP with REPZ prefix is called PAUSE. */
3991 if (prefixes == PREFIX_REPZ1)
3992 strcpy (obuf, "pause");
3993}
3994
3995static const char *const Suffix3DNow[] = {
3996/* 00 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
3997/* 04 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
3998/* 08 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
3999/* 0C */ "pi2fw", "pi2fd", NULL((void *)0), NULL((void *)0),
4000/* 10 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4001/* 14 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4002/* 18 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4003/* 1C */ "pf2iw", "pf2id", NULL((void *)0), NULL((void *)0),
4004/* 20 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4005/* 24 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4006/* 28 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4007/* 2C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4008/* 30 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4009/* 34 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4010/* 38 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4011/* 3C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4012/* 40 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4013/* 44 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4014/* 48 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4015/* 4C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4016/* 50 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4017/* 54 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4018/* 58 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4019/* 5C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4020/* 60 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4021/* 64 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4022/* 68 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4023/* 6C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4024/* 70 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4025/* 74 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4026/* 78 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4027/* 7C */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4028/* 80 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4029/* 84 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4030/* 88 */ NULL((void *)0), NULL((void *)0), "pfnacc", NULL((void *)0),
4031/* 8C */ NULL((void *)0), NULL((void *)0), "pfpnacc", NULL((void *)0),
4032/* 90 */ "pfcmpge", NULL((void *)0), NULL((void *)0), NULL((void *)0),
4033/* 94 */ "pfmin", NULL((void *)0), "pfrcp", "pfrsqrt",
4034/* 98 */ NULL((void *)0), NULL((void *)0), "pfsub", NULL((void *)0),
4035/* 9C */ NULL((void *)0), NULL((void *)0), "pfadd", NULL((void *)0),
4036/* A0 */ "pfcmpgt", NULL((void *)0), NULL((void *)0), NULL((void *)0),
4037/* A4 */ "pfmax", NULL((void *)0), "pfrcpit1", "pfrsqit1",
4038/* A8 */ NULL((void *)0), NULL((void *)0), "pfsubr", NULL((void *)0),
4039/* AC */ NULL((void *)0), NULL((void *)0), "pfacc", NULL((void *)0),
4040/* B0 */ "pfcmpeq", NULL((void *)0), NULL((void *)0), NULL((void *)0),
4041/* B4 */ "pfmul", NULL((void *)0), "pfrcpit2", "pfmulhrw",
4042/* B8 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), "pswapd",
4043/* BC */ NULL((void *)0), NULL((void *)0), NULL((void *)0), "pavgusb",
4044/* C0 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4045/* C4 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4046/* C8 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4047/* CC */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4048/* D0 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4049/* D4 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4050/* D8 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4051/* DC */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4052/* E0 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4053/* E4 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4054/* E8 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4055/* EC */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4056/* F0 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4057/* F4 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4058/* F8 */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4059/* FC */ NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0),
4060};
4061
4062static void
4063OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
4064{
4065 const char *mnemonic;
4066
4067 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4068 /* AMD 3DNow! instructions are specified by an opcode suffix in the
4069 place where an 8-bit immediate would normally go. ie. the last
4070 byte of the instruction. */
4071 obufp = obuf + strlen (obuf);
4072 mnemonic = Suffix3DNow[*codep++ & 0xff];
4073 if (mnemonic)
4074 oappend (mnemonic);
4075 else
4076 {
4077 /* Since a variable sized modrm/sib chunk is between the start
4078 of the opcode (0x0f0f) and the opcode suffix, we need to do
4079 all the modrm processing first, and don't know until now that
4080 we have a bad opcode. This necessitates some cleaning up. */
4081 op1out[0] = '\0';
4082 op2out[0] = '\0';
4083 BadOp ();
4084 }
4085}
4086
4087static const char *simd_cmp_op[] = {
4088 "eq",
4089 "lt",
4090 "le",
4091 "unord",
4092 "neq",
4093 "nlt",
4094 "nle",
4095 "ord"
4096};
4097
4098static void
4099OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
4100{
4101 unsigned int cmp_type;
4102
4103 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4104 obufp = obuf + strlen (obuf);
4105 cmp_type = *codep++ & 0xff;
4106 if (cmp_type < 8)
4107 {
4108 char suffix1 = 'p', suffix2 = 's';
4109 used_prefixes |= (prefixes & PREFIX_REPZ1);
4110 if (prefixes & PREFIX_REPZ1)
4111 suffix1 = 's';
4112 else
4113 {
4114 used_prefixes |= (prefixes & PREFIX_DATA0x200);
4115 if (prefixes & PREFIX_DATA0x200)
4116 suffix2 = 'd';
4117 else
4118 {
4119 used_prefixes |= (prefixes & PREFIX_REPNZ2);
4120 if (prefixes & PREFIX_REPNZ2)
4121 suffix1 = 's', suffix2 = 'd';
4122 }
4123 }
4124 sprintf (scratchbuf, "cmp%s%c%c",
4125 simd_cmp_op[cmp_type], suffix1, suffix2);
4126 used_prefixes |= (prefixes & PREFIX_REPZ1);
4127 oappend (scratchbuf);
4128 }
4129 else
4130 {
4131 /* We have a bad extension byte. Clean up. */
4132 op1out[0] = '\0';
4133 op2out[0] = '\0';
4134 BadOp ();
4135 }
4136}
4137
4138static void
4139SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
4140{
4141 /* Change movlps/movhps to movhlps/movlhps for 2 register operand
4142 forms of these instructions. */
4143 if (mod == 3)
4144 {
4145 char *p = obuf + strlen (obuf);
4146 *(p + 1) = '\0';
4147 *p = *(p - 1);
4148 *(p - 1) = *(p - 2);
4149 *(p - 2) = *(p - 3);
4150 *(p - 3) = extrachar;
4151 }
4152}
4153
4154static void
4155PNI_Fixup (int extrachar ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag)
4156{
4157 if (mod == 3 && reg == 1 && rm <= 1)
4158 {
4159 char *p = obuf + strlen (obuf);
4160
4161 /* Override "sidt". */
4162 if (rm)
4163 {
4164 /* mwait %eax,%ecx */
4165 strcpy (p - 4, "mwait %eax,%ecx");
4166 }
4167 else
4168 {
4169 /* monitor %eax,%ecx,%edx" */
4170 strcpy (p - 4, "monitor %eax,%ecx,%edx");
4171 }
4172
4173 codep++;
4174 }
4175 else if (mod == 3 && reg == 1 && rm <= 3)
4176 {
4177 size_t olen = strlen (obuf);
4178 char *p = obuf + olen - 4;
4179 if (*codep == 0xca)
4180 strcpy (p, "clac");
4181 else if (*codep == 0xcb)
4182 strcpy (p, "stac");
4183 codep++;
4184 }
4185 else
4186 OP_E (0, sizeflag);
4187}
4188
4189static void
4190XCR_Fixup (int extrachar ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int sizeflag)
4191{
4192 if (mod == 3 && reg == 2 && rm <= 1)
4193 {
4194 char *p = obuf + strlen (obuf);
4195
4196 /* Override "lgdt". */
4197 if (rm)
4198 {
4199 strcpy (p - 4, "xsetbv");
4200 }
4201 else
4202 {
4203 strcpy (p - 4, "xgetbv");
4204 }
4205
4206 codep++;
4207 }
4208 else
4209 OP_M (0, sizeflag);
4210}
4211
4212static void
4213INVLPG_Fixup (int bytemode, int sizeflag)
4214{
4215 const char *alt;
4216
4217 switch (*codep)
4218 {
4219 case 0xf8:
4220 alt = "swapgs";
4221 break;
4222 case 0xf9:
4223 alt = "rdtscp";
4224 break;
4225 default:
4226 OP_M (bytemode, sizeflag);
4227 return;
4228 }
4229 /* Override "invlpg". */
4230 strcpy (obuf + strlen (obuf) - 6, alt);
4231 codep++;
4232}
4233
4234static struct {
4235 unsigned char opc;
4236 char *name;
4237} xcrypt[] = {
4238 { 0xc0, "xstore-rng" },
4239 { 0xc8, "xcrypt-ecb" },
4240 { 0xd0, "xcrypt-cbc" },
4241 { 0xd8, "xcrypt-ctr" },
4242 { 0xe0, "xcrypt-cfb" },
4243 { 0xe8, "xcrypt-ofb" },
4244};
4245
4246static struct {
4247 unsigned char opc;
4248 char *name;
4249} xcrypt2[] = {
4250 { 0xc0, "montmul" },
4251 { 0xc8, "xsha1" },
4252 { 0xd0, "xsha256" },
4253};
4254
4255static void
4256OP_xcrypt (bytemode, sizeflag)
4257 int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4258 int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4259{
4260 const char *mnemonic = NULL((void *)0);
4261 unsigned int i;
4262
4263 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4264 /* VIA C3 xcrypt-* & xmove-* instructions are specified by an opcode
4265 suffix in the place where an 8-bit immediate would normally go.
4266 ie. the last byte of the instruction. */
4267 obufp = obuf + strlen(obuf);
4268
4269 for (i = 0; i < sizeof(xcrypt) / sizeof(xcrypt[0]); i++)
4270 if (xcrypt[i].opc == (*codep & 0xff))
4271 mnemonic = xcrypt[i].name;
4272 codep++;
4273 if (mnemonic)
4274 oappend (mnemonic);
4275 else
4276 BadOp();
4277}
4278
4279static void
4280OP_xcrypt2 (bytemode, sizeflag)
4281 int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4282 int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4283{
4284 const char *mnemonic = NULL((void *)0);
4285 unsigned int i;
4286
4287 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4288 /* VIA C3 xcrypt2 instructions are specified by an opcode
4289 suffix in the place where an 8-bit immediate would normally go.
4290 ie. the last byte of the instruction. */
4291 obufp = obuf + strlen(obuf);
4292
4293 for (i = 0; i < sizeof(xcrypt2) / sizeof(xcrypt2[0]); i++)
4294 if (xcrypt2[i].opc == (*codep & 0xff))
4295 mnemonic = xcrypt2[i].name;
4296 codep++;
4297 if (mnemonic)
4298 oappend (mnemonic);
4299 else
4300 BadOp();
4301 }
4302
4303static struct {
4304 unsigned char opc;
4305 char *name;
4306} aes[] = {
4307 { 0x00, "pshufb" },
4308 { 0xdb, "aesimc" },
4309 { 0xdc, "aesenc" },
4310 { 0xde, "aesdec" },
4311 { 0xdd, "aesenclast" },
4312 { 0xdf, "aesdeclast" }
4313};
4314
4315#define XMM_DST(rex, modrm)(((((rex) & ~0x40) & 0x4) ? 8 : 0) | (((modrm) & ~
0xc0) >> 3))
\
4316 (((((rex) & ~0x40) & 0x4) ? 8 : 0) | (((modrm) & ~0xc0) >> 3))
4317#define XMM_SRC(rex, modrm)(((((rex) & ~0x40) & 0x1) ? 8 : 0) | (((modrm) & ~
0xc0) & 7))
\
4318 (((((rex) & ~0x40) & 0x1) ? 8 : 0) | (((modrm) & ~0xc0) & 7))
4319
4320static void
4321OP_0f38 (bytemode, sizeflag)
4322 int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4323 int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4324{
4325 const char *mnemonic = NULL((void *)0);
4326 unsigned int i;
4327
4328 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4329 obufp = obuf + strlen (obuf);
4330
4331 for (i = 0; i < sizeof(aes) / sizeof(aes[0]); i++)
4332 if (aes[i].opc == (*codep & 0xff))
4333 mnemonic = aes[i].name;
4334
4335 codep++;
4336 if (mnemonic)
4337 {
4338 oappend (mnemonic);
4339
4340 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4341 sprintf (scratchbuf, " %%xmm%d", XMM_SRC (rex, *codep)(((((rex) & ~0x40) & 0x1) ? 8 : 0) | (((*codep) &
~0xc0) & 7))
);
4342 oappend (scratchbuf);
4343 sprintf (scratchbuf, ",%%xmm%d", XMM_DST (rex, *codep)(((((rex) & ~0x40) & 0x4) ? 8 : 0) | (((*codep) &
~0xc0) >> 3))
);
4344 oappend (scratchbuf);
4345
4346 codep++;
4347 used_prefixes |= (prefixes & PREFIX_DATA0x200);
4348 USED_REX(rex){ if (rex) rex_used |= (rex & rex) ? (rex) | 0x40 : 0; else
rex_used |= 0x40; }
;
4349 }
4350 else
4351 BadOp();
4352}
4353
4354static struct {
4355 unsigned char opc;
4356 char *name;
4357} pclmul[] = {
4358 { 0x00, "pclmullqlqdq" },
4359 { 0x01, "pclmulhqlqdq" },
4360 { 0x10, "pclmullqhqdq" },
4361 { 0x11, "pclmulhqhqdq" },
4362};
4363
4364static void
4365OP_0f3a (bytemode, sizeflag)
4366 int bytemode ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4367 int sizeflag ATTRIBUTE_UNUSED__attribute__ ((__unused__));
4368{
4369 const char *mnemonic = NULL((void *)0);
4370 unsigned int i, xmms;
4371 unsigned char op, imm;
4372
4373 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4374 obufp = obuf + strlen (obuf);
4375
4376 op = *codep;
4377 codep++;
4378
4379 FETCH_DATA (the_info, codep + 1)((codep + 1) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 1))
)
;
4380
4381 /* save xmm pair */
4382 xmms = XMM_DST (rex, *codep)(((((rex) & ~0x40) & 0x4) ? 8 : 0) | (((*codep) &
~0xc0) >> 3))
<< 8;
4383 xmms |= XMM_SRC (rex, *codep)(((((rex) & ~0x40) & 0x1) ? 8 : 0) | (((*codep) &
~0xc0) & 7))
;
4384 codep++;
4385
4386 /* save immediate field */
4387 FETCH_DATA (the_info, codep + 2)((codep + 2) <= ((struct dis_private *) (the_info->private_data
))->max_fetched ? 1 : fetch_data ((the_info), (codep + 2))
)
;
4388 imm = *codep;
4389 codep++;
4390
4391 if (op != 0x44 && op != 0xdf)
4392 {
4393 BadOp();
4394 return;
4395 }
4396
4397 switch (op)
4398 {
4399 case 0x44:
4400 for (i = 0; i < sizeof(pclmul) / sizeof(pclmul[0]); i++)
4401 if (pclmul[i].opc == imm)
4402 mnemonic = pclmul[i].name;
4403
4404 if (!mnemonic)
4405 {
4406 oappend ("pclmulqdq");
4407 sprintf (scratchbuf, " $%#x,", imm);
4408 oappend (scratchbuf);
4409 }
4410 else
4411 {
4412 oappend (mnemonic);
4413 oappend (" ");
4414 }
4415 break;
4416 case 0xdf:
4417 oappend ("aeskeygenassist ");
4418 sprintf (scratchbuf, " $%#x,", imm);
4419 oappend (scratchbuf);
4420 break;
4421 }
4422
4423 sprintf (scratchbuf, "%%xmm%d,", xmms & 0xff);
4424 oappend (scratchbuf);
4425 sprintf (scratchbuf, "%%xmm%d", xmms >> 8);
4426 oappend (scratchbuf);
4427
4428 used_prefixes |= (prefixes & PREFIX_DATA0x200);
4429 USED_REX(rex){ if (rex) rex_used |= (rex & rex) ? (rex) | 0x40 : 0; else
rex_used |= 0x40; }
;
4430}
4431
4432static void
4433BadOp (void)
4434{
4435 /* Throw away prefixes and 1st. opcode byte. */
4436 codep = insn_codep + 1;
4437 oappend ("(bad)");
4438}