blob: 0496e141d4a0978f0649830b09203811688b6193 [file] [log] [blame]
bellarddc990652003-03-19 00:00:28 +00001/* Print i386 instructions for GDB, the GNU debugger.
bellardbc51c5c2004-03-17 23:46:04 +00002 Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2001
bellarddc990652003-03-19 00:00:28 +00004 Free Software Foundation, Inc.
5
6This file is part of GDB.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22/*
23 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
24 * July 1988
25 * modified by John Hassey (hassey@dg-rtp.dg.com)
bellardbc51c5c2004-03-17 23:46:04 +000026 * x86-64 support added by Jan Hubicka (jh@suse.cz)
bellarddc990652003-03-19 00:00:28 +000027 */
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,
bellardbc51c5c2004-03-17 23:46:04 +000034 * and the small letter tells about the operand size. Refer to
bellarddc990652003-03-19 00:00:28 +000035 * the Intel manual for details.
36 */
37
bellardbb0ebb12003-04-10 00:02:33 +000038#include <stdlib.h>
bellarddc990652003-03-19 00:00:28 +000039#include "dis-asm.h"
40
41#define MAXLEN 20
42
bellardbc51c5c2004-03-17 23:46:04 +000043#include <setjmp.h>
bellarddc990652003-03-19 00:00:28 +000044
bellardbc51c5c2004-03-17 23:46:04 +000045#ifndef UNIXWARE_COMPAT
46/* Set non-zero for broken, compatible instructions. Set to zero for
47 non-broken opcodes. */
48#define UNIXWARE_COMPAT 1
49#endif
50
51static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
52static void ckprefix PARAMS ((void));
53static const char *prefix_name PARAMS ((int, int));
54static int print_insn PARAMS ((bfd_vma, disassemble_info *));
55static void dofloat PARAMS ((int));
56static void OP_ST PARAMS ((int, int));
57static void OP_STi PARAMS ((int, int));
58static int putop PARAMS ((const char *, int));
59static void oappend PARAMS ((const char *));
60static void append_seg PARAMS ((void));
61static void OP_indirE PARAMS ((int, int));
62static void print_operand_value PARAMS ((char *, int, bfd_vma));
63static void OP_E PARAMS ((int, int));
64static void OP_G PARAMS ((int, int));
65static bfd_vma get64 PARAMS ((void));
66static bfd_signed_vma get32 PARAMS ((void));
67static bfd_signed_vma get32s PARAMS ((void));
68static int get16 PARAMS ((void));
69static void set_op PARAMS ((bfd_vma, int));
70static void OP_REG PARAMS ((int, int));
71static void OP_IMREG PARAMS ((int, int));
72static void OP_I PARAMS ((int, int));
73static void OP_I64 PARAMS ((int, int));
74static void OP_sI PARAMS ((int, int));
75static void OP_J PARAMS ((int, int));
76static void OP_SEG PARAMS ((int, int));
77static void OP_DIR PARAMS ((int, int));
78static void OP_OFF PARAMS ((int, int));
79static void OP_OFF64 PARAMS ((int, int));
80static void ptr_reg PARAMS ((int, int));
81static void OP_ESreg PARAMS ((int, int));
82static void OP_DSreg PARAMS ((int, int));
83static void OP_C PARAMS ((int, int));
84static void OP_D PARAMS ((int, int));
85static void OP_T PARAMS ((int, int));
86static void OP_Rd PARAMS ((int, int));
87static void OP_MMX PARAMS ((int, int));
88static void OP_XMM PARAMS ((int, int));
89static void OP_EM PARAMS ((int, int));
90static void OP_EX PARAMS ((int, int));
91static void OP_MS PARAMS ((int, int));
92static void OP_XS PARAMS ((int, int));
93static void OP_3DNowSuffix PARAMS ((int, int));
94static void OP_SIMD_Suffix PARAMS ((int, int));
95static void SIMD_Fixup PARAMS ((int, int));
96static void BadOp PARAMS ((void));
97
98struct dis_private {
bellarddc990652003-03-19 00:00:28 +000099 /* Points to first byte not fetched. */
100 bfd_byte *max_fetched;
101 bfd_byte the_buffer[MAXLEN];
102 bfd_vma insn_start;
bellardbc51c5c2004-03-17 23:46:04 +0000103 int orig_sizeflag;
bellarddc990652003-03-19 00:00:28 +0000104 jmp_buf bailout;
105};
106
bellardbc51c5c2004-03-17 23:46:04 +0000107/* The opcode for the fwait instruction, which we treat as a prefix
108 when we can. */
109#define FWAIT_OPCODE (0x9b)
110
111/* Set to 1 for 64bit mode disassembly. */
112static int mode_64bit;
113
114/* Flags for the prefixes for the current instruction. See below. */
115static int prefixes;
116
117/* REX prefix the current instruction. See below. */
118static int rex;
119/* Bits of REX we've already used. */
120static int rex_used;
121#define REX_MODE64 8
122#define REX_EXTX 4
123#define REX_EXTY 2
124#define REX_EXTZ 1
125/* Mark parts used in the REX prefix. When we are testing for
126 empty prefix (for 8bit register REX extension), just mask it
127 out. Otherwise test for REX bit is excuse for existence of REX
128 only in case value is nonzero. */
129#define USED_REX(value) \
130 { \
131 if (value) \
132 rex_used |= (rex & value) ? (value) | 0x40 : 0; \
133 else \
134 rex_used |= 0x40; \
135 }
136
137/* Flags for prefixes which we somehow handled when printing the
138 current instruction. */
139static int used_prefixes;
140
141/* Flags stored in PREFIXES. */
142#define PREFIX_REPZ 1
143#define PREFIX_REPNZ 2
144#define PREFIX_LOCK 4
145#define PREFIX_CS 8
146#define PREFIX_SS 0x10
147#define PREFIX_DS 0x20
148#define PREFIX_ES 0x40
149#define PREFIX_FS 0x80
150#define PREFIX_GS 0x100
151#define PREFIX_DATA 0x200
152#define PREFIX_ADDR 0x400
153#define PREFIX_FWAIT 0x800
154
bellarddc990652003-03-19 00:00:28 +0000155/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
156 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
157 on error. */
158#define FETCH_DATA(info, addr) \
bellardbc51c5c2004-03-17 23:46:04 +0000159 ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
bellarddc990652003-03-19 00:00:28 +0000160 ? 1 : fetch_data ((info), (addr)))
161
162static int
163fetch_data (info, addr)
164 struct disassemble_info *info;
165 bfd_byte *addr;
166{
167 int status;
bellardbc51c5c2004-03-17 23:46:04 +0000168 struct dis_private *priv = (struct dis_private *) info->private_data;
bellarddc990652003-03-19 00:00:28 +0000169 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
170
171 status = (*info->read_memory_func) (start,
172 priv->max_fetched,
173 addr - priv->max_fetched,
174 info);
175 if (status != 0)
176 {
bellardbc51c5c2004-03-17 23:46:04 +0000177 /* If we did manage to read at least one byte, then
178 print_insn_i386 will do something sensible. Otherwise, print
179 an error. We do that here because this is where we know
180 STATUS. */
181 if (priv->max_fetched == priv->the_buffer)
182 (*info->memory_error_func) (status, start, info);
bellarddc990652003-03-19 00:00:28 +0000183 longjmp (priv->bailout, 1);
184 }
185 else
186 priv->max_fetched = addr;
187 return 1;
188}
189
bellardbc51c5c2004-03-17 23:46:04 +0000190#define XX NULL, 0
191
bellarddc990652003-03-19 00:00:28 +0000192#define Eb OP_E, b_mode
bellarddc990652003-03-19 00:00:28 +0000193#define Ev OP_E, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000194#define Ed OP_E, d_mode
195#define indirEb OP_indirE, b_mode
bellarddc990652003-03-19 00:00:28 +0000196#define indirEv OP_indirE, v_mode
197#define Ew OP_E, w_mode
198#define Ma OP_E, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000199#define M OP_E, 0 /* lea, lgdt, etc. */
200#define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
201#define Gb OP_G, b_mode
bellarddc990652003-03-19 00:00:28 +0000202#define Gv OP_G, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000203#define Gd OP_G, d_mode
bellarddc990652003-03-19 00:00:28 +0000204#define Gw OP_G, w_mode
bellardbc51c5c2004-03-17 23:46:04 +0000205#define Rd OP_Rd, d_mode
206#define Rm OP_Rd, m_mode
bellarddc990652003-03-19 00:00:28 +0000207#define Ib OP_I, b_mode
208#define sIb OP_sI, b_mode /* sign extened byte */
209#define Iv OP_I, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000210#define Iq OP_I, q_mode
211#define Iv64 OP_I64, v_mode
bellarddc990652003-03-19 00:00:28 +0000212#define Iw OP_I, w_mode
213#define Jb OP_J, b_mode
214#define Jv OP_J, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000215#define Cm OP_C, m_mode
216#define Dm OP_D, m_mode
bellarddc990652003-03-19 00:00:28 +0000217#define Td OP_T, d_mode
218
bellardbc51c5c2004-03-17 23:46:04 +0000219#define RMeAX OP_REG, eAX_reg
220#define RMeBX OP_REG, eBX_reg
221#define RMeCX OP_REG, eCX_reg
222#define RMeDX OP_REG, eDX_reg
223#define RMeSP OP_REG, eSP_reg
224#define RMeBP OP_REG, eBP_reg
225#define RMeSI OP_REG, eSI_reg
226#define RMeDI OP_REG, eDI_reg
227#define RMrAX OP_REG, rAX_reg
228#define RMrBX OP_REG, rBX_reg
229#define RMrCX OP_REG, rCX_reg
230#define RMrDX OP_REG, rDX_reg
231#define RMrSP OP_REG, rSP_reg
232#define RMrBP OP_REG, rBP_reg
233#define RMrSI OP_REG, rSI_reg
234#define RMrDI OP_REG, rDI_reg
235#define RMAL OP_REG, al_reg
236#define RMAL OP_REG, al_reg
237#define RMCL OP_REG, cl_reg
238#define RMDL OP_REG, dl_reg
239#define RMBL OP_REG, bl_reg
240#define RMAH OP_REG, ah_reg
241#define RMCH OP_REG, ch_reg
242#define RMDH OP_REG, dh_reg
243#define RMBH OP_REG, bh_reg
244#define RMAX OP_REG, ax_reg
245#define RMDX OP_REG, dx_reg
246
247#define eAX OP_IMREG, eAX_reg
248#define eBX OP_IMREG, eBX_reg
249#define eCX OP_IMREG, eCX_reg
250#define eDX OP_IMREG, eDX_reg
251#define eSP OP_IMREG, eSP_reg
252#define eBP OP_IMREG, eBP_reg
253#define eSI OP_IMREG, eSI_reg
254#define eDI OP_IMREG, eDI_reg
255#define AL OP_IMREG, al_reg
256#define AL OP_IMREG, al_reg
257#define CL OP_IMREG, cl_reg
258#define DL OP_IMREG, dl_reg
259#define BL OP_IMREG, bl_reg
260#define AH OP_IMREG, ah_reg
261#define CH OP_IMREG, ch_reg
262#define DH OP_IMREG, dh_reg
263#define BH OP_IMREG, bh_reg
264#define AX OP_IMREG, ax_reg
265#define DX OP_IMREG, dx_reg
266#define indirDX OP_IMREG, indir_dx_reg
bellarddc990652003-03-19 00:00:28 +0000267
268#define Sw OP_SEG, w_mode
bellardbc51c5c2004-03-17 23:46:04 +0000269#define Ap OP_DIR, 0
bellarddc990652003-03-19 00:00:28 +0000270#define Ob OP_OFF, b_mode
bellardbc51c5c2004-03-17 23:46:04 +0000271#define Ob64 OP_OFF64, b_mode
bellarddc990652003-03-19 00:00:28 +0000272#define Ov OP_OFF, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000273#define Ov64 OP_OFF64, v_mode
274#define Xb OP_DSreg, eSI_reg
275#define Xv OP_DSreg, eSI_reg
276#define Yb OP_ESreg, eDI_reg
277#define Yv OP_ESreg, eDI_reg
278#define DSBX OP_DSreg, eBX_reg
bellarddc990652003-03-19 00:00:28 +0000279
280#define es OP_REG, es_reg
281#define ss OP_REG, ss_reg
282#define cs OP_REG, cs_reg
283#define ds OP_REG, ds_reg
284#define fs OP_REG, fs_reg
285#define gs OP_REG, gs_reg
286
287#define MX OP_MMX, 0
bellardbc51c5c2004-03-17 23:46:04 +0000288#define XM OP_XMM, 0
bellarddc990652003-03-19 00:00:28 +0000289#define EM OP_EM, v_mode
bellardbc51c5c2004-03-17 23:46:04 +0000290#define EX OP_EX, v_mode
291#define MS OP_MS, v_mode
292#define XS OP_XS, v_mode
293#define None OP_E, 0
294#define OPSUF OP_3DNowSuffix, 0
295#define OPSIMD OP_SIMD_Suffix, 0
bellarddc990652003-03-19 00:00:28 +0000296
bellardbc51c5c2004-03-17 23:46:04 +0000297#define cond_jump_flag NULL, cond_jump_mode
298#define loop_jcxz_flag NULL, loop_jcxz_mode
bellarddc990652003-03-19 00:00:28 +0000299
bellardbc51c5c2004-03-17 23:46:04 +0000300/* bits in sizeflag */
301#define SUFFIX_ALWAYS 4
302#define AFLAG 2
303#define DFLAG 1
bellarddc990652003-03-19 00:00:28 +0000304
bellardbc51c5c2004-03-17 23:46:04 +0000305#define b_mode 1 /* byte operand */
306#define v_mode 2 /* operand size depends on prefixes */
307#define w_mode 3 /* word operand */
308#define d_mode 4 /* double word operand */
309#define q_mode 5 /* quad word operand */
310#define x_mode 6
311#define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */
312#define cond_jump_mode 8
313#define loop_jcxz_mode 9
bellarddc990652003-03-19 00:00:28 +0000314
315#define es_reg 100
316#define cs_reg 101
317#define ss_reg 102
318#define ds_reg 103
319#define fs_reg 104
320#define gs_reg 105
bellarddc990652003-03-19 00:00:28 +0000321
bellardbc51c5c2004-03-17 23:46:04 +0000322#define eAX_reg 108
323#define eCX_reg 109
324#define eDX_reg 110
325#define eBX_reg 111
326#define eSP_reg 112
327#define eBP_reg 113
328#define eSI_reg 114
329#define eDI_reg 115
bellarddc990652003-03-19 00:00:28 +0000330
331#define al_reg 116
332#define cl_reg 117
333#define dl_reg 118
334#define bl_reg 119
335#define ah_reg 120
336#define ch_reg 121
337#define dh_reg 122
338#define bh_reg 123
339
340#define ax_reg 124
341#define cx_reg 125
342#define dx_reg 126
343#define bx_reg 127
344#define sp_reg 128
345#define bp_reg 129
346#define si_reg 130
347#define di_reg 131
348
bellardbc51c5c2004-03-17 23:46:04 +0000349#define rAX_reg 132
350#define rCX_reg 133
351#define rDX_reg 134
352#define rBX_reg 135
353#define rSP_reg 136
354#define rBP_reg 137
355#define rSI_reg 138
356#define rDI_reg 139
357
bellarddc990652003-03-19 00:00:28 +0000358#define indir_dx_reg 150
359
bellardbc51c5c2004-03-17 23:46:04 +0000360#define FLOATCODE 1
361#define USE_GROUPS 2
362#define USE_PREFIX_USER_TABLE 3
363#define X86_64_SPECIAL 4
bellarddc990652003-03-19 00:00:28 +0000364
bellardbc51c5c2004-03-17 23:46:04 +0000365#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
366
367#define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0
368#define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0
369#define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0
370#define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0
371#define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0
372#define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0
373#define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0
374#define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0
375#define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0
376#define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0
377#define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
378#define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
379#define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
380#define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
381#define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
382#define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
383#define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
384#define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
385#define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
386#define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
387#define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
388#define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
389#define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
390
391#define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0
392#define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0
393#define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0
394#define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0
395#define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0
396#define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0
397#define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0
398#define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0
399#define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0
400#define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0
401#define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
402#define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
403#define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
404#define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
405#define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
406#define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
407#define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
408#define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
409#define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
410#define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
411#define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
412#define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
413#define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
414#define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
415#define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
416#define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
417#define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
418
419#define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0
420
421typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
bellarddc990652003-03-19 00:00:28 +0000422
423struct dis386 {
bellardbc51c5c2004-03-17 23:46:04 +0000424 const char *name;
bellarddc990652003-03-19 00:00:28 +0000425 op_rtn op1;
426 int bytemode1;
427 op_rtn op2;
428 int bytemode2;
429 op_rtn op3;
430 int bytemode3;
431};
432
bellardbc51c5c2004-03-17 23:46:04 +0000433/* Upper case letters in the instruction names here are macros.
434 'A' => print 'b' if no register operands or suffix_always is true
435 'B' => print 'b' if suffix_always is true
436 'E' => print 'e' if 32-bit form of jcxz
437 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
438 'H' => print ",pt" or ",pn" branch hint
439 'L' => print 'l' if suffix_always is true
440 'N' => print 'n' if instruction has no wait "prefix"
441 'O' => print 'd', or 'o'
442 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
443 . or suffix_always is true. print 'q' if rex prefix is present.
444 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
445 . is true
446 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
447 'S' => print 'w', 'l' or 'q' if suffix_always is true
448 'T' => print 'q' in 64bit mode and behave as 'P' otherwise
449 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
450 'X' => print 's', 'd' depending on data16 prefix (for XMM)
451 'W' => print 'b' or 'w' ("w" or "de" in intel mode)
452 'Y' => 'q' if instruction has an REX 64bit overwrite prefix
453
454 Many of the above letters print nothing in Intel mode. See "putop"
455 for the details.
456
457 Braces '{' and '}', and vertical bars '|', indicate alternative
458 mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
459 modes. In cases where there are only two alternatives, the X86_64
460 instruction is reserved, and "(bad)" is printed.
461*/
462
463static const struct dis386 dis386[] = {
bellarddc990652003-03-19 00:00:28 +0000464 /* 00 */
bellardbc51c5c2004-03-17 23:46:04 +0000465 { "addB", Eb, Gb, XX },
466 { "addS", Ev, Gv, XX },
467 { "addB", Gb, Eb, XX },
468 { "addS", Gv, Ev, XX },
469 { "addB", AL, Ib, XX },
470 { "addS", eAX, Iv, XX },
471 { "push{T|}", es, XX, XX },
472 { "pop{T|}", es, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000473 /* 08 */
bellardbc51c5c2004-03-17 23:46:04 +0000474 { "orB", Eb, Gb, XX },
475 { "orS", Ev, Gv, XX },
476 { "orB", Gb, Eb, XX },
477 { "orS", Gv, Ev, XX },
478 { "orB", AL, Ib, XX },
479 { "orS", eAX, Iv, XX },
480 { "push{T|}", cs, XX, XX },
481 { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */
bellarddc990652003-03-19 00:00:28 +0000482 /* 10 */
bellardbc51c5c2004-03-17 23:46:04 +0000483 { "adcB", Eb, Gb, XX },
484 { "adcS", Ev, Gv, XX },
485 { "adcB", Gb, Eb, XX },
486 { "adcS", Gv, Ev, XX },
487 { "adcB", AL, Ib, XX },
488 { "adcS", eAX, Iv, XX },
489 { "push{T|}", ss, XX, XX },
490 { "popT|}", ss, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000491 /* 18 */
bellardbc51c5c2004-03-17 23:46:04 +0000492 { "sbbB", Eb, Gb, XX },
493 { "sbbS", Ev, Gv, XX },
494 { "sbbB", Gb, Eb, XX },
495 { "sbbS", Gv, Ev, XX },
496 { "sbbB", AL, Ib, XX },
497 { "sbbS", eAX, Iv, XX },
498 { "push{T|}", ds, XX, XX },
499 { "pop{T|}", ds, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000500 /* 20 */
bellardbc51c5c2004-03-17 23:46:04 +0000501 { "andB", Eb, Gb, XX },
502 { "andS", Ev, Gv, XX },
503 { "andB", Gb, Eb, XX },
504 { "andS", Gv, Ev, XX },
505 { "andB", AL, Ib, XX },
506 { "andS", eAX, Iv, XX },
507 { "(bad)", XX, XX, XX }, /* SEG ES prefix */
508 { "daa{|}", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000509 /* 28 */
bellardbc51c5c2004-03-17 23:46:04 +0000510 { "subB", Eb, Gb, XX },
511 { "subS", Ev, Gv, XX },
512 { "subB", Gb, Eb, XX },
513 { "subS", Gv, Ev, XX },
514 { "subB", AL, Ib, XX },
515 { "subS", eAX, Iv, XX },
516 { "(bad)", XX, XX, XX }, /* SEG CS prefix */
517 { "das{|}", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000518 /* 30 */
bellardbc51c5c2004-03-17 23:46:04 +0000519 { "xorB", Eb, Gb, XX },
520 { "xorS", Ev, Gv, XX },
521 { "xorB", Gb, Eb, XX },
522 { "xorS", Gv, Ev, XX },
523 { "xorB", AL, Ib, XX },
524 { "xorS", eAX, Iv, XX },
525 { "(bad)", XX, XX, XX }, /* SEG SS prefix */
526 { "aaa{|}", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000527 /* 38 */
bellardbc51c5c2004-03-17 23:46:04 +0000528 { "cmpB", Eb, Gb, XX },
529 { "cmpS", Ev, Gv, XX },
530 { "cmpB", Gb, Eb, XX },
531 { "cmpS", Gv, Ev, XX },
532 { "cmpB", AL, Ib, XX },
533 { "cmpS", eAX, Iv, XX },
534 { "(bad)", XX, XX, XX }, /* SEG DS prefix */
535 { "aas{|}", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000536 /* 40 */
bellardbc51c5c2004-03-17 23:46:04 +0000537 { "inc{S|}", RMeAX, XX, XX },
538 { "inc{S|}", RMeCX, XX, XX },
539 { "inc{S|}", RMeDX, XX, XX },
540 { "inc{S|}", RMeBX, XX, XX },
541 { "inc{S|}", RMeSP, XX, XX },
542 { "inc{S|}", RMeBP, XX, XX },
543 { "inc{S|}", RMeSI, XX, XX },
544 { "inc{S|}", RMeDI, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000545 /* 48 */
bellardbc51c5c2004-03-17 23:46:04 +0000546 { "dec{S|}", RMeAX, XX, XX },
547 { "dec{S|}", RMeCX, XX, XX },
548 { "dec{S|}", RMeDX, XX, XX },
549 { "dec{S|}", RMeBX, XX, XX },
550 { "dec{S|}", RMeSP, XX, XX },
551 { "dec{S|}", RMeBP, XX, XX },
552 { "dec{S|}", RMeSI, XX, XX },
553 { "dec{S|}", RMeDI, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000554 /* 50 */
bellardbc51c5c2004-03-17 23:46:04 +0000555 { "pushS", RMrAX, XX, XX },
556 { "pushS", RMrCX, XX, XX },
557 { "pushS", RMrDX, XX, XX },
558 { "pushS", RMrBX, XX, XX },
559 { "pushS", RMrSP, XX, XX },
560 { "pushS", RMrBP, XX, XX },
561 { "pushS", RMrSI, XX, XX },
562 { "pushS", RMrDI, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000563 /* 58 */
bellardbc51c5c2004-03-17 23:46:04 +0000564 { "popS", RMrAX, XX, XX },
565 { "popS", RMrCX, XX, XX },
566 { "popS", RMrDX, XX, XX },
567 { "popS", RMrBX, XX, XX },
568 { "popS", RMrSP, XX, XX },
569 { "popS", RMrBP, XX, XX },
570 { "popS", RMrSI, XX, XX },
571 { "popS", RMrDI, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000572 /* 60 */
bellardbc51c5c2004-03-17 23:46:04 +0000573 { "pusha{P|}", XX, XX, XX },
574 { "popa{P|}", XX, XX, XX },
575 { "bound{S|}", Gv, Ma, XX },
576 { X86_64_0 },
577 { "(bad)", XX, XX, XX }, /* seg fs */
578 { "(bad)", XX, XX, XX }, /* seg gs */
579 { "(bad)", XX, XX, XX }, /* op size prefix */
580 { "(bad)", XX, XX, XX }, /* adr size prefix */
bellarddc990652003-03-19 00:00:28 +0000581 /* 68 */
bellardbc51c5c2004-03-17 23:46:04 +0000582 { "pushT", Iq, XX, XX },
583 { "imulS", Gv, Ev, Iv },
584 { "pushT", sIb, XX, XX },
585 { "imulS", Gv, Ev, sIb },
586 { "ins{b||b|}", Yb, indirDX, XX },
587 { "ins{R||R|}", Yv, indirDX, XX },
588 { "outs{b||b|}", indirDX, Xb, XX },
589 { "outs{R||R|}", indirDX, Xv, XX },
bellarddc990652003-03-19 00:00:28 +0000590 /* 70 */
bellardbc51c5c2004-03-17 23:46:04 +0000591 { "joH", Jb, XX, cond_jump_flag },
592 { "jnoH", Jb, XX, cond_jump_flag },
593 { "jbH", Jb, XX, cond_jump_flag },
594 { "jaeH", Jb, XX, cond_jump_flag },
595 { "jeH", Jb, XX, cond_jump_flag },
596 { "jneH", Jb, XX, cond_jump_flag },
597 { "jbeH", Jb, XX, cond_jump_flag },
598 { "jaH", Jb, XX, cond_jump_flag },
bellarddc990652003-03-19 00:00:28 +0000599 /* 78 */
bellardbc51c5c2004-03-17 23:46:04 +0000600 { "jsH", Jb, XX, cond_jump_flag },
601 { "jnsH", Jb, XX, cond_jump_flag },
602 { "jpH", Jb, XX, cond_jump_flag },
603 { "jnpH", Jb, XX, cond_jump_flag },
604 { "jlH", Jb, XX, cond_jump_flag },
605 { "jgeH", Jb, XX, cond_jump_flag },
606 { "jleH", Jb, XX, cond_jump_flag },
607 { "jgH", Jb, XX, cond_jump_flag },
bellarddc990652003-03-19 00:00:28 +0000608 /* 80 */
609 { GRP1b },
610 { GRP1S },
bellardbc51c5c2004-03-17 23:46:04 +0000611 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000612 { GRP1Ss },
bellardbc51c5c2004-03-17 23:46:04 +0000613 { "testB", Eb, Gb, XX },
614 { "testS", Ev, Gv, XX },
615 { "xchgB", Eb, Gb, XX },
616 { "xchgS", Ev, Gv, XX },
bellarddc990652003-03-19 00:00:28 +0000617 /* 88 */
bellardbc51c5c2004-03-17 23:46:04 +0000618 { "movB", Eb, Gb, XX },
619 { "movS", Ev, Gv, XX },
620 { "movB", Gb, Eb, XX },
621 { "movS", Gv, Ev, XX },
622 { "movQ", Ev, Sw, XX },
623 { "leaS", Gv, M, XX },
624 { "movQ", Sw, Ev, XX },
625 { "popU", Ev, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000626 /* 90 */
bellardbc51c5c2004-03-17 23:46:04 +0000627 { "nop", XX, XX, XX },
628 /* FIXME: NOP with REPz prefix is called PAUSE. */
629 { "xchgS", RMeCX, eAX, XX },
630 { "xchgS", RMeDX, eAX, XX },
631 { "xchgS", RMeBX, eAX, XX },
632 { "xchgS", RMeSP, eAX, XX },
633 { "xchgS", RMeBP, eAX, XX },
634 { "xchgS", RMeSI, eAX, XX },
635 { "xchgS", RMeDI, eAX, XX },
bellarddc990652003-03-19 00:00:28 +0000636 /* 98 */
bellardbc51c5c2004-03-17 23:46:04 +0000637 { "cW{tR||tR|}", XX, XX, XX },
638 { "cR{tO||tO|}", XX, XX, XX },
639 { "lcall{T|}", Ap, XX, XX },
640 { "(bad)", XX, XX, XX }, /* fwait */
641 { "pushfT", XX, XX, XX },
642 { "popfT", XX, XX, XX },
643 { "sahf{|}", XX, XX, XX },
644 { "lahf{|}", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000645 /* a0 */
bellardbc51c5c2004-03-17 23:46:04 +0000646 { "movB", AL, Ob64, XX },
647 { "movS", eAX, Ov64, XX },
648 { "movB", Ob64, AL, XX },
649 { "movS", Ov64, eAX, XX },
650 { "movs{b||b|}", Yb, Xb, XX },
651 { "movs{R||R|}", Yv, Xv, XX },
652 { "cmps{b||b|}", Xb, Yb, XX },
653 { "cmps{R||R|}", Xv, Yv, XX },
bellarddc990652003-03-19 00:00:28 +0000654 /* a8 */
bellardbc51c5c2004-03-17 23:46:04 +0000655 { "testB", AL, Ib, XX },
656 { "testS", eAX, Iv, XX },
657 { "stosB", Yb, AL, XX },
658 { "stosS", Yv, eAX, XX },
659 { "lodsB", AL, Xb, XX },
660 { "lodsS", eAX, Xv, XX },
661 { "scasB", AL, Yb, XX },
662 { "scasS", eAX, Yv, XX },
bellarddc990652003-03-19 00:00:28 +0000663 /* b0 */
bellardbc51c5c2004-03-17 23:46:04 +0000664 { "movB", RMAL, Ib, XX },
665 { "movB", RMCL, Ib, XX },
666 { "movB", RMDL, Ib, XX },
667 { "movB", RMBL, Ib, XX },
668 { "movB", RMAH, Ib, XX },
669 { "movB", RMCH, Ib, XX },
670 { "movB", RMDH, Ib, XX },
671 { "movB", RMBH, Ib, XX },
bellarddc990652003-03-19 00:00:28 +0000672 /* b8 */
bellardbc51c5c2004-03-17 23:46:04 +0000673 { "movS", RMeAX, Iv64, XX },
674 { "movS", RMeCX, Iv64, XX },
675 { "movS", RMeDX, Iv64, XX },
676 { "movS", RMeBX, Iv64, XX },
677 { "movS", RMeSP, Iv64, XX },
678 { "movS", RMeBP, Iv64, XX },
679 { "movS", RMeSI, Iv64, XX },
680 { "movS", RMeDI, Iv64, XX },
bellarddc990652003-03-19 00:00:28 +0000681 /* c0 */
682 { GRP2b },
683 { GRP2S },
bellardbc51c5c2004-03-17 23:46:04 +0000684 { "retT", Iw, XX, XX },
685 { "retT", XX, XX, XX },
686 { "les{S|}", Gv, Mp, XX },
687 { "ldsS", Gv, Mp, XX },
688 { "movA", Eb, Ib, XX },
689 { "movQ", Ev, Iv, XX },
bellarddc990652003-03-19 00:00:28 +0000690 /* c8 */
bellardbc51c5c2004-03-17 23:46:04 +0000691 { "enterT", Iw, Ib, XX },
692 { "leaveT", XX, XX, XX },
693 { "lretP", Iw, XX, XX },
694 { "lretP", XX, XX, XX },
695 { "int3", XX, XX, XX },
696 { "int", Ib, XX, XX },
697 { "into{|}", XX, XX, XX },
698 { "iretP", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000699 /* d0 */
700 { GRP2b_one },
701 { GRP2S_one },
702 { GRP2b_cl },
703 { GRP2S_cl },
bellardbc51c5c2004-03-17 23:46:04 +0000704 { "aam{|}", sIb, XX, XX },
705 { "aad{|}", sIb, XX, XX },
706 { "(bad)", XX, XX, XX },
707 { "xlat", DSBX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000708 /* d8 */
709 { FLOAT },
710 { FLOAT },
711 { FLOAT },
712 { FLOAT },
713 { FLOAT },
714 { FLOAT },
715 { FLOAT },
716 { FLOAT },
717 /* e0 */
bellardbc51c5c2004-03-17 23:46:04 +0000718 { "loopneFH", Jb, XX, loop_jcxz_flag },
719 { "loopeFH", Jb, XX, loop_jcxz_flag },
720 { "loopFH", Jb, XX, loop_jcxz_flag },
721 { "jEcxzH", Jb, XX, loop_jcxz_flag },
722 { "inB", AL, Ib, XX },
723 { "inS", eAX, Ib, XX },
724 { "outB", Ib, AL, XX },
725 { "outS", Ib, eAX, XX },
bellarddc990652003-03-19 00:00:28 +0000726 /* e8 */
bellardbc51c5c2004-03-17 23:46:04 +0000727 { "callT", Jv, XX, XX },
728 { "jmpT", Jv, XX, XX },
729 { "ljmp{T|}", Ap, XX, XX },
730 { "jmp", Jb, XX, XX },
731 { "inB", AL, indirDX, XX },
732 { "inS", eAX, indirDX, XX },
733 { "outB", indirDX, AL, XX },
734 { "outS", indirDX, eAX, XX },
bellarddc990652003-03-19 00:00:28 +0000735 /* f0 */
bellardbc51c5c2004-03-17 23:46:04 +0000736 { "(bad)", XX, XX, XX }, /* lock prefix */
737 { "(bad)", XX, XX, XX },
738 { "(bad)", XX, XX, XX }, /* repne */
739 { "(bad)", XX, XX, XX }, /* repz */
740 { "hlt", XX, XX, XX },
741 { "cmc", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000742 { GRP3b },
743 { GRP3S },
744 /* f8 */
bellardbc51c5c2004-03-17 23:46:04 +0000745 { "clc", XX, XX, XX },
746 { "stc", XX, XX, XX },
747 { "cli", XX, XX, XX },
748 { "sti", XX, XX, XX },
749 { "cld", XX, XX, XX },
750 { "std", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000751 { GRP4 },
752 { GRP5 },
753};
754
bellardbc51c5c2004-03-17 23:46:04 +0000755static const struct dis386 dis386_twobyte[] = {
bellarddc990652003-03-19 00:00:28 +0000756 /* 00 */
757 { GRP6 },
758 { GRP7 },
bellardbc51c5c2004-03-17 23:46:04 +0000759 { "larS", Gv, Ew, XX },
760 { "lslS", Gv, Ew, XX },
761 { "(bad)", XX, XX, XX },
762 { "syscall", XX, XX, XX },
763 { "clts", XX, XX, XX },
764 { "sysretP", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000765 /* 08 */
bellardbc51c5c2004-03-17 23:46:04 +0000766 { "invd", XX, XX, XX },
767 { "wbinvd", XX, XX, XX },
768 { "(bad)", XX, XX, XX },
769 { "ud2a", XX, XX, XX },
770 { "(bad)", XX, XX, XX },
771 { GRPAMD },
772 { "femms", XX, XX, XX },
773 { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix. */
bellarddc990652003-03-19 00:00:28 +0000774 /* 10 */
bellardbc51c5c2004-03-17 23:46:04 +0000775 { PREGRP8 },
776 { PREGRP9 },
777 { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
778 { "movlpX", EX, XM, SIMD_Fixup, 'h' },
779 { "unpcklpX", XM, EX, XX },
780 { "unpckhpX", XM, EX, XX },
781 { "movhpX", XM, EX, SIMD_Fixup, 'l' },
782 { "movhpX", EX, XM, SIMD_Fixup, 'l' },
bellarddc990652003-03-19 00:00:28 +0000783 /* 18 */
bellardbc51c5c2004-03-17 23:46:04 +0000784 { GRP14 },
785 { "(bad)", XX, XX, XX },
786 { "(bad)", XX, XX, XX },
787 { "(bad)", XX, XX, XX },
788 { "(bad)", XX, XX, XX },
789 { "(bad)", XX, XX, XX },
790 { "(bad)", XX, XX, XX },
791 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000792 /* 20 */
bellardbc51c5c2004-03-17 23:46:04 +0000793 { "movL", Rm, Cm, XX },
794 { "movL", Rm, Dm, XX },
795 { "movL", Cm, Rm, XX },
796 { "movL", Dm, Rm, XX },
797 { "movL", Rd, Td, XX },
798 { "(bad)", XX, XX, XX },
799 { "movL", Td, Rd, XX },
800 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000801 /* 28 */
bellardbc51c5c2004-03-17 23:46:04 +0000802 { "movapX", XM, EX, XX },
803 { "movapX", EX, XM, XX },
804 { PREGRP2 },
805 { "movntpX", Ev, XM, XX },
806 { PREGRP4 },
807 { PREGRP3 },
808 { "ucomisX", XM,EX, XX },
809 { "comisX", XM,EX, XX },
bellarddc990652003-03-19 00:00:28 +0000810 /* 30 */
bellardbc51c5c2004-03-17 23:46:04 +0000811 { "wrmsr", XX, XX, XX },
812 { "rdtsc", XX, XX, XX },
813 { "rdmsr", XX, XX, XX },
814 { "rdpmc", XX, XX, XX },
815 { "sysenter", XX, XX, XX },
816 { "sysexit", XX, XX, XX },
817 { "(bad)", XX, XX, XX },
818 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000819 /* 38 */
bellardbc51c5c2004-03-17 23:46:04 +0000820 { "(bad)", XX, XX, XX },
821 { "(bad)", XX, XX, XX },
822 { "(bad)", XX, XX, XX },
823 { "(bad)", XX, XX, XX },
824 { "(bad)", XX, XX, XX },
825 { "(bad)", XX, XX, XX },
826 { "(bad)", XX, XX, XX },
827 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000828 /* 40 */
bellardbc51c5c2004-03-17 23:46:04 +0000829 { "cmovo", Gv, Ev, XX },
830 { "cmovno", Gv, Ev, XX },
831 { "cmovb", Gv, Ev, XX },
832 { "cmovae", Gv, Ev, XX },
833 { "cmove", Gv, Ev, XX },
834 { "cmovne", Gv, Ev, XX },
835 { "cmovbe", Gv, Ev, XX },
836 { "cmova", Gv, Ev, XX },
bellarddc990652003-03-19 00:00:28 +0000837 /* 48 */
bellardbc51c5c2004-03-17 23:46:04 +0000838 { "cmovs", Gv, Ev, XX },
839 { "cmovns", Gv, Ev, XX },
840 { "cmovp", Gv, Ev, XX },
841 { "cmovnp", Gv, Ev, XX },
842 { "cmovl", Gv, Ev, XX },
843 { "cmovge", Gv, Ev, XX },
844 { "cmovle", Gv, Ev, XX },
845 { "cmovg", Gv, Ev, XX },
bellarddc990652003-03-19 00:00:28 +0000846 /* 50 */
bellardbc51c5c2004-03-17 23:46:04 +0000847 { "movmskpX", Gd, XS, XX },
848 { PREGRP13 },
849 { PREGRP12 },
850 { PREGRP11 },
851 { "andpX", XM, EX, XX },
852 { "andnpX", XM, EX, XX },
853 { "orpX", XM, EX, XX },
854 { "xorpX", XM, EX, XX },
bellarddc990652003-03-19 00:00:28 +0000855 /* 58 */
bellardbc51c5c2004-03-17 23:46:04 +0000856 { PREGRP0 },
857 { PREGRP10 },
858 { PREGRP17 },
859 { PREGRP16 },
860 { PREGRP14 },
861 { PREGRP7 },
862 { PREGRP5 },
863 { PREGRP6 },
bellarddc990652003-03-19 00:00:28 +0000864 /* 60 */
bellardbc51c5c2004-03-17 23:46:04 +0000865 { "punpcklbw", MX, EM, XX },
866 { "punpcklwd", MX, EM, XX },
867 { "punpckldq", MX, EM, XX },
868 { "packsswb", MX, EM, XX },
869 { "pcmpgtb", MX, EM, XX },
870 { "pcmpgtw", MX, EM, XX },
871 { "pcmpgtd", MX, EM, XX },
872 { "packuswb", MX, EM, XX },
bellarddc990652003-03-19 00:00:28 +0000873 /* 68 */
bellardbc51c5c2004-03-17 23:46:04 +0000874 { "punpckhbw", MX, EM, XX },
875 { "punpckhwd", MX, EM, XX },
876 { "punpckhdq", MX, EM, XX },
877 { "packssdw", MX, EM, XX },
878 { PREGRP26 },
879 { PREGRP24 },
880 { "movd", MX, Ed, XX },
881 { PREGRP19 },
bellarddc990652003-03-19 00:00:28 +0000882 /* 70 */
bellardbc51c5c2004-03-17 23:46:04 +0000883 { PREGRP22 },
bellarddc990652003-03-19 00:00:28 +0000884 { GRP10 },
885 { GRP11 },
886 { GRP12 },
bellardbc51c5c2004-03-17 23:46:04 +0000887 { "pcmpeqb", MX, EM, XX },
888 { "pcmpeqw", MX, EM, XX },
889 { "pcmpeqd", MX, EM, XX },
890 { "emms", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000891 /* 78 */
bellardbc51c5c2004-03-17 23:46:04 +0000892 { "(bad)", XX, XX, XX },
893 { "(bad)", XX, XX, XX },
894 { "(bad)", XX, XX, XX },
895 { "(bad)", XX, XX, XX },
896 { "(bad)", XX, XX, XX },
897 { "(bad)", XX, XX, XX },
898 { PREGRP23 },
899 { PREGRP20 },
bellarddc990652003-03-19 00:00:28 +0000900 /* 80 */
bellardbc51c5c2004-03-17 23:46:04 +0000901 { "joH", Jv, XX, cond_jump_flag },
902 { "jnoH", Jv, XX, cond_jump_flag },
903 { "jbH", Jv, XX, cond_jump_flag },
904 { "jaeH", Jv, XX, cond_jump_flag },
905 { "jeH", Jv, XX, cond_jump_flag },
906 { "jneH", Jv, XX, cond_jump_flag },
907 { "jbeH", Jv, XX, cond_jump_flag },
908 { "jaH", Jv, XX, cond_jump_flag },
bellarddc990652003-03-19 00:00:28 +0000909 /* 88 */
bellardbc51c5c2004-03-17 23:46:04 +0000910 { "jsH", Jv, XX, cond_jump_flag },
911 { "jnsH", Jv, XX, cond_jump_flag },
912 { "jpH", Jv, XX, cond_jump_flag },
913 { "jnpH", Jv, XX, cond_jump_flag },
914 { "jlH", Jv, XX, cond_jump_flag },
915 { "jgeH", Jv, XX, cond_jump_flag },
916 { "jleH", Jv, XX, cond_jump_flag },
917 { "jgH", Jv, XX, cond_jump_flag },
bellarddc990652003-03-19 00:00:28 +0000918 /* 90 */
bellardbc51c5c2004-03-17 23:46:04 +0000919 { "seto", Eb, XX, XX },
920 { "setno", Eb, XX, XX },
921 { "setb", Eb, XX, XX },
922 { "setae", Eb, XX, XX },
923 { "sete", Eb, XX, XX },
924 { "setne", Eb, XX, XX },
925 { "setbe", Eb, XX, XX },
926 { "seta", Eb, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000927 /* 98 */
bellardbc51c5c2004-03-17 23:46:04 +0000928 { "sets", Eb, XX, XX },
929 { "setns", Eb, XX, XX },
930 { "setp", Eb, XX, XX },
931 { "setnp", Eb, XX, XX },
932 { "setl", Eb, XX, XX },
933 { "setge", Eb, XX, XX },
934 { "setle", Eb, XX, XX },
935 { "setg", Eb, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000936 /* a0 */
bellardbc51c5c2004-03-17 23:46:04 +0000937 { "pushT", fs, XX, XX },
938 { "popT", fs, XX, XX },
939 { "cpuid", XX, XX, XX },
940 { "btS", Ev, Gv, XX },
941 { "shldS", Ev, Gv, Ib },
942 { "shldS", Ev, Gv, CL },
943 { "(bad)", XX, XX, XX },
944 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000945 /* a8 */
bellardbc51c5c2004-03-17 23:46:04 +0000946 { "pushT", gs, XX, XX },
947 { "popT", gs, XX, XX },
948 { "rsm", XX, XX, XX },
949 { "btsS", Ev, Gv, XX },
950 { "shrdS", Ev, Gv, Ib },
951 { "shrdS", Ev, Gv, CL },
952 { GRP13 },
953 { "imulS", Gv, Ev, XX },
bellarddc990652003-03-19 00:00:28 +0000954 /* b0 */
bellardbc51c5c2004-03-17 23:46:04 +0000955 { "cmpxchgB", Eb, Gb, XX },
956 { "cmpxchgS", Ev, Gv, XX },
957 { "lssS", Gv, Mp, XX },
958 { "btrS", Ev, Gv, XX },
959 { "lfsS", Gv, Mp, XX },
960 { "lgsS", Gv, Mp, XX },
961 { "movz{bR|x|bR|x}", Gv, Eb, XX },
962 { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */
bellarddc990652003-03-19 00:00:28 +0000963 /* b8 */
bellardbc51c5c2004-03-17 23:46:04 +0000964 { "(bad)", XX, XX, XX },
965 { "ud2b", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000966 { GRP8 },
bellardbc51c5c2004-03-17 23:46:04 +0000967 { "btcS", Ev, Gv, XX },
968 { "bsfS", Gv, Ev, XX },
969 { "bsrS", Gv, Ev, XX },
970 { "movs{bR|x|bR|x}", Gv, Eb, XX },
971 { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */
bellarddc990652003-03-19 00:00:28 +0000972 /* c0 */
bellardbc51c5c2004-03-17 23:46:04 +0000973 { "xaddB", Eb, Gb, XX },
974 { "xaddS", Ev, Gv, XX },
975 { PREGRP1 },
976 { "movntiS", Ev, Gv, XX },
977 { "pinsrw", MX, Ed, Ib },
978 { "pextrw", Gd, MS, Ib },
979 { "shufpX", XM, EX, Ib },
980 { GRP9 },
bellarddc990652003-03-19 00:00:28 +0000981 /* c8 */
bellardbc51c5c2004-03-17 23:46:04 +0000982 { "bswap", RMeAX, XX, XX },
983 { "bswap", RMeCX, XX, XX },
984 { "bswap", RMeDX, XX, XX },
985 { "bswap", RMeBX, XX, XX },
986 { "bswap", RMeSP, XX, XX },
987 { "bswap", RMeBP, XX, XX },
988 { "bswap", RMeSI, XX, XX },
989 { "bswap", RMeDI, XX, XX },
bellarddc990652003-03-19 00:00:28 +0000990 /* d0 */
bellardbc51c5c2004-03-17 23:46:04 +0000991 { "(bad)", XX, XX, XX },
992 { "psrlw", MX, EM, XX },
993 { "psrld", MX, EM, XX },
994 { "psrlq", MX, EM, XX },
995 { "paddq", MX, EM, XX },
996 { "pmullw", MX, EM, XX },
997 { PREGRP21 },
998 { "pmovmskb", Gd, MS, XX },
bellarddc990652003-03-19 00:00:28 +0000999 /* d8 */
bellardbc51c5c2004-03-17 23:46:04 +00001000 { "psubusb", MX, EM, XX },
1001 { "psubusw", MX, EM, XX },
1002 { "pminub", MX, EM, XX },
1003 { "pand", MX, EM, XX },
1004 { "paddusb", MX, EM, XX },
1005 { "paddusw", MX, EM, XX },
1006 { "pmaxub", MX, EM, XX },
1007 { "pandn", MX, EM, XX },
bellarddc990652003-03-19 00:00:28 +00001008 /* e0 */
bellardbc51c5c2004-03-17 23:46:04 +00001009 { "pavgb", MX, EM, XX },
1010 { "psraw", MX, EM, XX },
1011 { "psrad", MX, EM, XX },
1012 { "pavgw", MX, EM, XX },
1013 { "pmulhuw", MX, EM, XX },
1014 { "pmulhw", MX, EM, XX },
1015 { PREGRP15 },
1016 { PREGRP25 },
bellarddc990652003-03-19 00:00:28 +00001017 /* e8 */
bellardbc51c5c2004-03-17 23:46:04 +00001018 { "psubsb", MX, EM, XX },
1019 { "psubsw", MX, EM, XX },
1020 { "pminsw", MX, EM, XX },
1021 { "por", MX, EM, XX },
1022 { "paddsb", MX, EM, XX },
1023 { "paddsw", MX, EM, XX },
1024 { "pmaxsw", MX, EM, XX },
1025 { "pxor", MX, EM, XX },
bellarddc990652003-03-19 00:00:28 +00001026 /* f0 */
bellardbc51c5c2004-03-17 23:46:04 +00001027 { "(bad)", XX, XX, XX },
1028 { "psllw", MX, EM, XX },
1029 { "pslld", MX, EM, XX },
1030 { "psllq", MX, EM, XX },
1031 { "pmuludq", MX, EM, XX },
1032 { "pmaddwd", MX, EM, XX },
1033 { "psadbw", MX, EM, XX },
1034 { PREGRP18 },
bellarddc990652003-03-19 00:00:28 +00001035 /* f8 */
bellardbc51c5c2004-03-17 23:46:04 +00001036 { "psubb", MX, EM, XX },
1037 { "psubw", MX, EM, XX },
1038 { "psubd", MX, EM, XX },
1039 { "psubq", MX, EM, XX },
1040 { "paddb", MX, EM, XX },
1041 { "paddw", MX, EM, XX },
1042 { "paddd", MX, EM, XX },
1043 { "(bad)", XX, XX, XX }
bellarddc990652003-03-19 00:00:28 +00001044};
1045
1046static const unsigned char onebyte_has_modrm[256] = {
bellardbc51c5c2004-03-17 23:46:04 +00001047 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1048 /* ------------------------------- */
1049 /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
1050 /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
1051 /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
1052 /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
1053 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
1054 /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
1055 /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
1056 /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
1057 /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
1058 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
1059 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
1060 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
1061 /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
1062 /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
1063 /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
1064 /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
1065 /* ------------------------------- */
1066 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
bellarddc990652003-03-19 00:00:28 +00001067};
1068
1069static const unsigned char twobyte_has_modrm[256] = {
bellardbc51c5c2004-03-17 23:46:04 +00001070 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1071 /* ------------------------------- */
1072 /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
1073 /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
1074 /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
bellarddc990652003-03-19 00:00:28 +00001075 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1076 /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
bellardbc51c5c2004-03-17 23:46:04 +00001077 /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
1078 /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
1079 /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
bellarddc990652003-03-19 00:00:28 +00001080 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1081 /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
bellardbc51c5c2004-03-17 23:46:04 +00001082 /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */
bellarddc990652003-03-19 00:00:28 +00001083 /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
1084 /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
bellardbc51c5c2004-03-17 23:46:04 +00001085 /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
1086 /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
1087 /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
1088 /* ------------------------------- */
1089 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1090};
1091
1092static const unsigned char twobyte_uses_SSE_prefix[256] = {
1093 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1094 /* ------------------------------- */
1095 /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
1096 /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
1097 /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
1098 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1099 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
1100 /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
1101 /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
1102 /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */
1103 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1104 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
1105 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
1106 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
1107 /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
1108 /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
1109 /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
1110 /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
1111 /* ------------------------------- */
1112 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
bellarddc990652003-03-19 00:00:28 +00001113};
1114
1115static char obuf[100];
1116static char *obufp;
1117static char scratchbuf[100];
1118static unsigned char *start_codep;
bellardbc51c5c2004-03-17 23:46:04 +00001119static unsigned char *insn_codep;
bellarddc990652003-03-19 00:00:28 +00001120static unsigned char *codep;
1121static disassemble_info *the_info;
1122static int mod;
1123static int rm;
1124static int reg;
bellardbc51c5c2004-03-17 23:46:04 +00001125static unsigned char need_modrm;
bellarddc990652003-03-19 00:00:28 +00001126
bellardbc51c5c2004-03-17 23:46:04 +00001127/* If we are accessing mod/rm/reg without need_modrm set, then the
1128 values are stale. Hitting this abort likely indicates that you
1129 need to update onebyte_has_modrm or twobyte_has_modrm. */
1130#define MODRM_CHECK if (!need_modrm) abort ()
1131
1132static const char **names64;
1133static const char **names32;
1134static const char **names16;
1135static const char **names8;
1136static const char **names8rex;
1137static const char **names_seg;
1138static const char **index16;
1139
1140static const char *intel_names64[] = {
1141 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1142 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
bellarddc990652003-03-19 00:00:28 +00001143};
bellardbc51c5c2004-03-17 23:46:04 +00001144static const char *intel_names32[] = {
1145 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
1146 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
bellarddc990652003-03-19 00:00:28 +00001147};
bellardbc51c5c2004-03-17 23:46:04 +00001148static const char *intel_names16[] = {
1149 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
1150 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
bellarddc990652003-03-19 00:00:28 +00001151};
bellardbc51c5c2004-03-17 23:46:04 +00001152static const char *intel_names8[] = {
1153 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
bellarddc990652003-03-19 00:00:28 +00001154};
bellardbc51c5c2004-03-17 23:46:04 +00001155static const char *intel_names8rex[] = {
1156 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1157 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
1158};
1159static const char *intel_names_seg[] = {
1160 "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
1161};
1162static const char *intel_index16[] = {
1163 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
bellarddc990652003-03-19 00:00:28 +00001164};
1165
bellardbc51c5c2004-03-17 23:46:04 +00001166static const char *att_names64[] = {
1167 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1168 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
1169};
1170static const char *att_names32[] = {
1171 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
1172 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
1173};
1174static const char *att_names16[] = {
1175 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
1176 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
1177};
1178static const char *att_names8[] = {
1179 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
1180};
1181static const char *att_names8rex[] = {
1182 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
1183 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
1184};
1185static const char *att_names_seg[] = {
1186 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
1187};
1188static const char *att_index16[] = {
1189 "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
1190};
1191
1192static const struct dis386 grps[][8] = {
bellarddc990652003-03-19 00:00:28 +00001193 /* GRP1b */
1194 {
bellardbc51c5c2004-03-17 23:46:04 +00001195 { "addA", Eb, Ib, XX },
1196 { "orA", Eb, Ib, XX },
1197 { "adcA", Eb, Ib, XX },
1198 { "sbbA", Eb, Ib, XX },
1199 { "andA", Eb, Ib, XX },
1200 { "subA", Eb, Ib, XX },
1201 { "xorA", Eb, Ib, XX },
1202 { "cmpA", Eb, Ib, XX }
bellarddc990652003-03-19 00:00:28 +00001203 },
1204 /* GRP1S */
1205 {
bellardbc51c5c2004-03-17 23:46:04 +00001206 { "addQ", Ev, Iv, XX },
1207 { "orQ", Ev, Iv, XX },
1208 { "adcQ", Ev, Iv, XX },
1209 { "sbbQ", Ev, Iv, XX },
1210 { "andQ", Ev, Iv, XX },
1211 { "subQ", Ev, Iv, XX },
1212 { "xorQ", Ev, Iv, XX },
1213 { "cmpQ", Ev, Iv, XX }
bellarddc990652003-03-19 00:00:28 +00001214 },
1215 /* GRP1Ss */
1216 {
bellardbc51c5c2004-03-17 23:46:04 +00001217 { "addQ", Ev, sIb, XX },
1218 { "orQ", Ev, sIb, XX },
1219 { "adcQ", Ev, sIb, XX },
1220 { "sbbQ", Ev, sIb, XX },
1221 { "andQ", Ev, sIb, XX },
1222 { "subQ", Ev, sIb, XX },
1223 { "xorQ", Ev, sIb, XX },
1224 { "cmpQ", Ev, sIb, XX }
bellarddc990652003-03-19 00:00:28 +00001225 },
1226 /* GRP2b */
1227 {
bellardbc51c5c2004-03-17 23:46:04 +00001228 { "rolA", Eb, Ib, XX },
1229 { "rorA", Eb, Ib, XX },
1230 { "rclA", Eb, Ib, XX },
1231 { "rcrA", Eb, Ib, XX },
1232 { "shlA", Eb, Ib, XX },
1233 { "shrA", Eb, Ib, XX },
1234 { "(bad)", XX, XX, XX },
1235 { "sarA", Eb, Ib, XX },
bellarddc990652003-03-19 00:00:28 +00001236 },
1237 /* GRP2S */
1238 {
bellardbc51c5c2004-03-17 23:46:04 +00001239 { "rolQ", Ev, Ib, XX },
1240 { "rorQ", Ev, Ib, XX },
1241 { "rclQ", Ev, Ib, XX },
1242 { "rcrQ", Ev, Ib, XX },
1243 { "shlQ", Ev, Ib, XX },
1244 { "shrQ", Ev, Ib, XX },
1245 { "(bad)", XX, XX, XX },
1246 { "sarQ", Ev, Ib, XX },
bellarddc990652003-03-19 00:00:28 +00001247 },
1248 /* GRP2b_one */
1249 {
bellardbc51c5c2004-03-17 23:46:04 +00001250 { "rolA", Eb, XX, XX },
1251 { "rorA", Eb, XX, XX },
1252 { "rclA", Eb, XX, XX },
1253 { "rcrA", Eb, XX, XX },
1254 { "shlA", Eb, XX, XX },
1255 { "shrA", Eb, XX, XX },
1256 { "(bad)", XX, XX, XX },
1257 { "sarA", Eb, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001258 },
1259 /* GRP2S_one */
1260 {
bellardbc51c5c2004-03-17 23:46:04 +00001261 { "rolQ", Ev, XX, XX },
1262 { "rorQ", Ev, XX, XX },
1263 { "rclQ", Ev, XX, XX },
1264 { "rcrQ", Ev, XX, XX },
1265 { "shlQ", Ev, XX, XX },
1266 { "shrQ", Ev, XX, XX },
1267 { "(bad)", XX, XX, XX},
1268 { "sarQ", Ev, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001269 },
1270 /* GRP2b_cl */
1271 {
bellardbc51c5c2004-03-17 23:46:04 +00001272 { "rolA", Eb, CL, XX },
1273 { "rorA", Eb, CL, XX },
1274 { "rclA", Eb, CL, XX },
1275 { "rcrA", Eb, CL, XX },
1276 { "shlA", Eb, CL, XX },
1277 { "shrA", Eb, CL, XX },
1278 { "(bad)", XX, XX, XX },
1279 { "sarA", Eb, CL, XX },
bellarddc990652003-03-19 00:00:28 +00001280 },
1281 /* GRP2S_cl */
1282 {
bellardbc51c5c2004-03-17 23:46:04 +00001283 { "rolQ", Ev, CL, XX },
1284 { "rorQ", Ev, CL, XX },
1285 { "rclQ", Ev, CL, XX },
1286 { "rcrQ", Ev, CL, XX },
1287 { "shlQ", Ev, CL, XX },
1288 { "shrQ", Ev, CL, XX },
1289 { "(bad)", XX, XX, XX },
1290 { "sarQ", Ev, CL, XX }
bellarddc990652003-03-19 00:00:28 +00001291 },
1292 /* GRP3b */
1293 {
bellardbc51c5c2004-03-17 23:46:04 +00001294 { "testA", Eb, Ib, XX },
1295 { "(bad)", Eb, XX, XX },
1296 { "notA", Eb, XX, XX },
1297 { "negA", Eb, XX, XX },
1298 { "mulA", Eb, XX, XX }, /* Don't print the implicit %al register, */
1299 { "imulA", Eb, XX, XX }, /* to distinguish these opcodes from other */
1300 { "divA", Eb, XX, XX }, /* mul/imul opcodes. Do the same for div */
1301 { "idivA", Eb, XX, XX } /* and idiv for consistency. */
bellarddc990652003-03-19 00:00:28 +00001302 },
1303 /* GRP3S */
1304 {
bellardbc51c5c2004-03-17 23:46:04 +00001305 { "testQ", Ev, Iv, XX },
1306 { "(bad)", XX, XX, XX },
1307 { "notQ", Ev, XX, XX },
1308 { "negQ", Ev, XX, XX },
1309 { "mulQ", Ev, XX, XX }, /* Don't print the implicit register. */
1310 { "imulQ", Ev, XX, XX },
1311 { "divQ", Ev, XX, XX },
1312 { "idivQ", Ev, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001313 },
1314 /* GRP4 */
1315 {
bellardbc51c5c2004-03-17 23:46:04 +00001316 { "incA", Eb, XX, XX },
1317 { "decA", Eb, XX, XX },
1318 { "(bad)", XX, XX, XX },
1319 { "(bad)", XX, XX, XX },
1320 { "(bad)", XX, XX, XX },
1321 { "(bad)", XX, XX, XX },
1322 { "(bad)", XX, XX, XX },
1323 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001324 },
1325 /* GRP5 */
1326 {
bellardbc51c5c2004-03-17 23:46:04 +00001327 { "incQ", Ev, XX, XX },
1328 { "decQ", Ev, XX, XX },
1329 { "callT", indirEv, XX, XX },
1330 { "lcallT", indirEv, XX, XX },
1331 { "jmpT", indirEv, XX, XX },
1332 { "ljmpT", indirEv, XX, XX },
1333 { "pushU", Ev, XX, XX },
1334 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001335 },
1336 /* GRP6 */
1337 {
bellardbc51c5c2004-03-17 23:46:04 +00001338 { "sldtQ", Ev, XX, XX },
1339 { "strQ", Ev, XX, XX },
1340 { "lldt", Ew, XX, XX },
1341 { "ltr", Ew, XX, XX },
1342 { "verr", Ew, XX, XX },
1343 { "verw", Ew, XX, XX },
1344 { "(bad)", XX, XX, XX },
1345 { "(bad)", XX, XX, XX }
bellarddc990652003-03-19 00:00:28 +00001346 },
1347 /* GRP7 */
1348 {
bellardbc51c5c2004-03-17 23:46:04 +00001349 { "sgdtQ", M, XX, XX },
1350 { "sidtQ", M, XX, XX },
1351 { "lgdtQ", M, XX, XX },
1352 { "lidtQ", M, XX, XX },
1353 { "smswQ", Ev, XX, XX },
1354 { "(bad)", XX, XX, XX },
1355 { "lmsw", Ew, XX, XX },
1356 { "invlpg", Ew, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001357 },
1358 /* GRP8 */
1359 {
bellardbc51c5c2004-03-17 23:46:04 +00001360 { "(bad)", XX, XX, XX },
1361 { "(bad)", XX, XX, XX },
1362 { "(bad)", XX, XX, XX },
1363 { "(bad)", XX, XX, XX },
1364 { "btQ", Ev, Ib, XX },
1365 { "btsQ", Ev, Ib, XX },
1366 { "btrQ", Ev, Ib, XX },
1367 { "btcQ", Ev, Ib, XX },
bellarddc990652003-03-19 00:00:28 +00001368 },
1369 /* GRP9 */
1370 {
bellardbc51c5c2004-03-17 23:46:04 +00001371 { "(bad)", XX, XX, XX },
1372 { "cmpxchg8b", Ev, XX, XX },
1373 { "(bad)", XX, XX, XX },
1374 { "(bad)", XX, XX, XX },
1375 { "(bad)", XX, XX, XX },
1376 { "(bad)", XX, XX, XX },
1377 { "(bad)", XX, XX, XX },
1378 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001379 },
1380 /* GRP10 */
1381 {
bellardbc51c5c2004-03-17 23:46:04 +00001382 { "(bad)", XX, XX, XX },
1383 { "(bad)", XX, XX, XX },
1384 { "psrlw", MS, Ib, XX },
1385 { "(bad)", XX, XX, XX },
1386 { "psraw", MS, Ib, XX },
1387 { "(bad)", XX, XX, XX },
1388 { "psllw", MS, Ib, XX },
1389 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001390 },
1391 /* GRP11 */
1392 {
bellardbc51c5c2004-03-17 23:46:04 +00001393 { "(bad)", XX, XX, XX },
1394 { "(bad)", XX, XX, XX },
1395 { "psrld", MS, Ib, XX },
1396 { "(bad)", XX, XX, XX },
1397 { "psrad", MS, Ib, XX },
1398 { "(bad)", XX, XX, XX },
1399 { "pslld", MS, Ib, XX },
1400 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001401 },
1402 /* GRP12 */
1403 {
bellardbc51c5c2004-03-17 23:46:04 +00001404 { "(bad)", XX, XX, XX },
1405 { "(bad)", XX, XX, XX },
1406 { "psrlq", MS, Ib, XX },
1407 { "psrldq", MS, Ib, XX },
1408 { "(bad)", XX, XX, XX },
1409 { "(bad)", XX, XX, XX },
1410 { "psllq", MS, Ib, XX },
1411 { "pslldq", MS, Ib, XX },
1412 },
1413 /* GRP13 */
1414 {
1415 { "fxsave", Ev, XX, XX },
1416 { "fxrstor", Ev, XX, XX },
1417 { "ldmxcsr", Ev, XX, XX },
1418 { "stmxcsr", Ev, XX, XX },
1419 { "(bad)", XX, XX, XX },
1420 { "lfence", None, XX, XX },
1421 { "mfence", None, XX, XX },
1422 { "sfence", None, XX, XX },
1423 /* FIXME: the sfence with memory operand is clflush! */
1424 },
1425 /* GRP14 */
1426 {
1427 { "prefetchnta", Ev, XX, XX },
1428 { "prefetcht0", Ev, XX, XX },
1429 { "prefetcht1", Ev, XX, XX },
1430 { "prefetcht2", Ev, XX, XX },
1431 { "(bad)", XX, XX, XX },
1432 { "(bad)", XX, XX, XX },
1433 { "(bad)", XX, XX, XX },
1434 { "(bad)", XX, XX, XX },
1435 },
1436 /* GRPAMD */
1437 {
1438 { "prefetch", Eb, XX, XX },
1439 { "prefetchw", Eb, XX, XX },
1440 { "(bad)", XX, XX, XX },
1441 { "(bad)", XX, XX, XX },
1442 { "(bad)", XX, XX, XX },
1443 { "(bad)", XX, XX, XX },
1444 { "(bad)", XX, XX, XX },
1445 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00001446 }
1447};
1448
bellardbc51c5c2004-03-17 23:46:04 +00001449static const struct dis386 prefix_user_table[][4] = {
1450 /* PREGRP0 */
1451 {
1452 { "addps", XM, EX, XX },
1453 { "addss", XM, EX, XX },
1454 { "addpd", XM, EX, XX },
1455 { "addsd", XM, EX, XX },
1456 },
1457 /* PREGRP1 */
1458 {
1459 { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX. */
1460 { "", XM, EX, OPSIMD },
1461 { "", XM, EX, OPSIMD },
1462 { "", XM, EX, OPSIMD },
1463 },
1464 /* PREGRP2 */
1465 {
1466 { "cvtpi2ps", XM, EM, XX },
1467 { "cvtsi2ssY", XM, Ev, XX },
1468 { "cvtpi2pd", XM, EM, XX },
1469 { "cvtsi2sdY", XM, Ev, XX },
1470 },
1471 /* PREGRP3 */
1472 {
1473 { "cvtps2pi", MX, EX, XX },
1474 { "cvtss2siY", Gv, EX, XX },
1475 { "cvtpd2pi", MX, EX, XX },
1476 { "cvtsd2siY", Gv, EX, XX },
1477 },
1478 /* PREGRP4 */
1479 {
1480 { "cvttps2pi", MX, EX, XX },
1481 { "cvttss2siY", Gv, EX, XX },
1482 { "cvttpd2pi", MX, EX, XX },
1483 { "cvttsd2siY", Gv, EX, XX },
1484 },
1485 /* PREGRP5 */
1486 {
1487 { "divps", XM, EX, XX },
1488 { "divss", XM, EX, XX },
1489 { "divpd", XM, EX, XX },
1490 { "divsd", XM, EX, XX },
1491 },
1492 /* PREGRP6 */
1493 {
1494 { "maxps", XM, EX, XX },
1495 { "maxss", XM, EX, XX },
1496 { "maxpd", XM, EX, XX },
1497 { "maxsd", XM, EX, XX },
1498 },
1499 /* PREGRP7 */
1500 {
1501 { "minps", XM, EX, XX },
1502 { "minss", XM, EX, XX },
1503 { "minpd", XM, EX, XX },
1504 { "minsd", XM, EX, XX },
1505 },
1506 /* PREGRP8 */
1507 {
1508 { "movups", XM, EX, XX },
1509 { "movss", XM, EX, XX },
1510 { "movupd", XM, EX, XX },
1511 { "movsd", XM, EX, XX },
1512 },
1513 /* PREGRP9 */
1514 {
1515 { "movups", EX, XM, XX },
1516 { "movss", EX, XM, XX },
1517 { "movupd", EX, XM, XX },
1518 { "movsd", EX, XM, XX },
1519 },
1520 /* PREGRP10 */
1521 {
1522 { "mulps", XM, EX, XX },
1523 { "mulss", XM, EX, XX },
1524 { "mulpd", XM, EX, XX },
1525 { "mulsd", XM, EX, XX },
1526 },
1527 /* PREGRP11 */
1528 {
1529 { "rcpps", XM, EX, XX },
1530 { "rcpss", XM, EX, XX },
1531 { "(bad)", XM, EX, XX },
1532 { "(bad)", XM, EX, XX },
1533 },
1534 /* PREGRP12 */
1535 {
1536 { "rsqrtps", XM, EX, XX },
1537 { "rsqrtss", XM, EX, XX },
1538 { "(bad)", XM, EX, XX },
1539 { "(bad)", XM, EX, XX },
1540 },
1541 /* PREGRP13 */
1542 {
1543 { "sqrtps", XM, EX, XX },
1544 { "sqrtss", XM, EX, XX },
1545 { "sqrtpd", XM, EX, XX },
1546 { "sqrtsd", XM, EX, XX },
1547 },
1548 /* PREGRP14 */
1549 {
1550 { "subps", XM, EX, XX },
1551 { "subss", XM, EX, XX },
1552 { "subpd", XM, EX, XX },
1553 { "subsd", XM, EX, XX },
1554 },
1555 /* PREGRP15 */
1556 {
1557 { "(bad)", XM, EX, XX },
1558 { "cvtdq2pd", XM, EX, XX },
1559 { "cvttpd2dq", XM, EX, XX },
1560 { "cvtpd2dq", XM, EX, XX },
1561 },
1562 /* PREGRP16 */
1563 {
1564 { "cvtdq2ps", XM, EX, XX },
1565 { "cvttps2dq",XM, EX, XX },
1566 { "cvtps2dq",XM, EX, XX },
1567 { "(bad)", XM, EX, XX },
1568 },
1569 /* PREGRP17 */
1570 {
1571 { "cvtps2pd", XM, EX, XX },
1572 { "cvtss2sd", XM, EX, XX },
1573 { "cvtpd2ps", XM, EX, XX },
1574 { "cvtsd2ss", XM, EX, XX },
1575 },
1576 /* PREGRP18 */
1577 {
1578 { "maskmovq", MX, MS, XX },
1579 { "(bad)", XM, EX, XX },
1580 { "maskmovdqu", XM, EX, XX },
1581 { "(bad)", XM, EX, XX },
1582 },
1583 /* PREGRP19 */
1584 {
1585 { "movq", MX, EM, XX },
1586 { "movdqu", XM, EX, XX },
1587 { "movdqa", XM, EX, XX },
1588 { "(bad)", XM, EX, XX },
1589 },
1590 /* PREGRP20 */
1591 {
1592 { "movq", EM, MX, XX },
1593 { "movdqu", EX, XM, XX },
1594 { "movdqa", EX, XM, XX },
1595 { "(bad)", EX, XM, XX },
1596 },
1597 /* PREGRP21 */
1598 {
1599 { "(bad)", EX, XM, XX },
1600 { "movq2dq", XM, MS, XX },
1601 { "movq", EX, XM, XX },
1602 { "movdq2q", MX, XS, XX },
1603 },
1604 /* PREGRP22 */
1605 {
1606 { "pshufw", MX, EM, Ib },
1607 { "pshufhw", XM, EX, Ib },
1608 { "pshufd", XM, EX, Ib },
1609 { "pshuflw", XM, EX, Ib },
1610 },
1611 /* PREGRP23 */
1612 {
1613 { "movd", Ed, MX, XX },
1614 { "movq", XM, EX, XX },
1615 { "movd", Ed, XM, XX },
1616 { "(bad)", Ed, XM, XX },
1617 },
1618 /* PREGRP24 */
1619 {
1620 { "(bad)", MX, EX, XX },
1621 { "(bad)", XM, EX, XX },
1622 { "punpckhqdq", XM, EX, XX },
1623 { "(bad)", XM, EX, XX },
1624 },
1625 /* PREGRP25 */
1626 {
1627 { "movntq", Ev, MX, XX },
1628 { "(bad)", Ev, XM, XX },
1629 { "movntdq", Ev, XM, XX },
1630 { "(bad)", Ev, XM, XX },
1631 },
1632 /* PREGRP26 */
1633 {
1634 { "(bad)", MX, EX, XX },
1635 { "(bad)", XM, EX, XX },
1636 { "punpcklqdq", XM, EX, XX },
1637 { "(bad)", XM, EX, XX },
1638 },
1639};
bellarddc990652003-03-19 00:00:28 +00001640
bellardbc51c5c2004-03-17 23:46:04 +00001641static const struct dis386 x86_64_table[][2] = {
1642 {
1643 { "arpl", Ew, Gw, XX },
1644 { "movs{||lq|xd}", Gv, Ed, XX },
1645 },
1646};
1647
1648#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
bellarddc990652003-03-19 00:00:28 +00001649
1650static void
1651ckprefix ()
1652{
bellardbc51c5c2004-03-17 23:46:04 +00001653 int newrex;
1654 rex = 0;
bellarddc990652003-03-19 00:00:28 +00001655 prefixes = 0;
bellardbc51c5c2004-03-17 23:46:04 +00001656 used_prefixes = 0;
1657 rex_used = 0;
bellarddc990652003-03-19 00:00:28 +00001658 while (1)
1659 {
1660 FETCH_DATA (the_info, codep + 1);
bellardbc51c5c2004-03-17 23:46:04 +00001661 newrex = 0;
bellarddc990652003-03-19 00:00:28 +00001662 switch (*codep)
1663 {
bellardbc51c5c2004-03-17 23:46:04 +00001664 /* REX prefixes family. */
1665 case 0x40:
1666 case 0x41:
1667 case 0x42:
1668 case 0x43:
1669 case 0x44:
1670 case 0x45:
1671 case 0x46:
1672 case 0x47:
1673 case 0x48:
1674 case 0x49:
1675 case 0x4a:
1676 case 0x4b:
1677 case 0x4c:
1678 case 0x4d:
1679 case 0x4e:
1680 case 0x4f:
1681 if (mode_64bit)
1682 newrex = *codep;
1683 else
1684 return;
1685 break;
bellarddc990652003-03-19 00:00:28 +00001686 case 0xf3:
1687 prefixes |= PREFIX_REPZ;
1688 break;
1689 case 0xf2:
1690 prefixes |= PREFIX_REPNZ;
1691 break;
1692 case 0xf0:
1693 prefixes |= PREFIX_LOCK;
1694 break;
1695 case 0x2e:
1696 prefixes |= PREFIX_CS;
1697 break;
1698 case 0x36:
1699 prefixes |= PREFIX_SS;
1700 break;
1701 case 0x3e:
1702 prefixes |= PREFIX_DS;
1703 break;
1704 case 0x26:
1705 prefixes |= PREFIX_ES;
1706 break;
1707 case 0x64:
1708 prefixes |= PREFIX_FS;
1709 break;
1710 case 0x65:
1711 prefixes |= PREFIX_GS;
1712 break;
1713 case 0x66:
1714 prefixes |= PREFIX_DATA;
1715 break;
1716 case 0x67:
bellardbc51c5c2004-03-17 23:46:04 +00001717 prefixes |= PREFIX_ADDR;
bellarddc990652003-03-19 00:00:28 +00001718 break;
bellardbc51c5c2004-03-17 23:46:04 +00001719 case FWAIT_OPCODE:
1720 /* fwait is really an instruction. If there are prefixes
1721 before the fwait, they belong to the fwait, *not* to the
1722 following instruction. */
1723 if (prefixes)
1724 {
1725 prefixes |= PREFIX_FWAIT;
1726 codep++;
1727 return;
1728 }
1729 prefixes = PREFIX_FWAIT;
bellarddc990652003-03-19 00:00:28 +00001730 break;
1731 default:
1732 return;
1733 }
bellardbc51c5c2004-03-17 23:46:04 +00001734 /* Rex is ignored when followed by another prefix. */
1735 if (rex)
1736 {
1737 oappend (prefix_name (rex, 0));
1738 oappend (" ");
1739 }
1740 rex = newrex;
bellarddc990652003-03-19 00:00:28 +00001741 codep++;
1742 }
1743}
1744
bellardbc51c5c2004-03-17 23:46:04 +00001745/* Return the name of the prefix byte PREF, or NULL if PREF is not a
1746 prefix byte. */
bellarddc990652003-03-19 00:00:28 +00001747
bellardbc51c5c2004-03-17 23:46:04 +00001748static const char *
1749prefix_name (pref, sizeflag)
1750 int pref;
1751 int sizeflag;
1752{
1753 switch (pref)
1754 {
1755 /* REX prefixes family. */
1756 case 0x40:
1757 return "rex";
1758 case 0x41:
1759 return "rexZ";
1760 case 0x42:
1761 return "rexY";
1762 case 0x43:
1763 return "rexYZ";
1764 case 0x44:
1765 return "rexX";
1766 case 0x45:
1767 return "rexXZ";
1768 case 0x46:
1769 return "rexXY";
1770 case 0x47:
1771 return "rexXYZ";
1772 case 0x48:
1773 return "rex64";
1774 case 0x49:
1775 return "rex64Z";
1776 case 0x4a:
1777 return "rex64Y";
1778 case 0x4b:
1779 return "rex64YZ";
1780 case 0x4c:
1781 return "rex64X";
1782 case 0x4d:
1783 return "rex64XZ";
1784 case 0x4e:
1785 return "rex64XY";
1786 case 0x4f:
1787 return "rex64XYZ";
1788 case 0xf3:
1789 return "repz";
1790 case 0xf2:
1791 return "repnz";
1792 case 0xf0:
1793 return "lock";
1794 case 0x2e:
1795 return "cs";
1796 case 0x36:
1797 return "ss";
1798 case 0x3e:
1799 return "ds";
1800 case 0x26:
1801 return "es";
1802 case 0x64:
1803 return "fs";
1804 case 0x65:
1805 return "gs";
1806 case 0x66:
1807 return (sizeflag & DFLAG) ? "data16" : "data32";
1808 case 0x67:
1809 if (mode_64bit)
1810 return (sizeflag & AFLAG) ? "addr32" : "addr64";
1811 else
1812 return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32";
1813 case FWAIT_OPCODE:
1814 return "fwait";
1815 default:
1816 return NULL;
1817 }
1818}
1819
1820static char op1out[100], op2out[100], op3out[100];
1821static int op_ad, op_index[3];
1822static bfd_vma op_address[3];
1823static bfd_vma op_riprel[3];
1824static bfd_vma start_pc;
bellarddc990652003-03-19 00:00:28 +00001825
1826/*
1827 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1828 * (see topic "Redundant prefixes" in the "Differences from 8086"
1829 * section of the "Virtual 8086 Mode" chapter.)
1830 * 'pc' should be the address of this instruction, it will
1831 * be used to print the target address if this is a relative jump or call
1832 * The function returns the length of this instruction in bytes.
1833 */
1834
bellardb8b5ac62004-10-12 21:52:40 +00001835static int8_t intel_syntax;
bellardbc51c5c2004-03-17 23:46:04 +00001836static char open_char;
1837static char close_char;
1838static char separator_char;
1839static char scale_char;
1840
1841/* Here for backwards compatibility. When gdb stops using
1842 print_insn_i386_att and print_insn_i386_intel these functions can
1843 disappear, and print_insn_i386 be merged into print_insn. */
1844int
1845print_insn_i386_att (pc, info)
1846 bfd_vma pc;
1847 disassemble_info *info;
1848{
1849 intel_syntax = 0;
1850
1851 return print_insn (pc, info);
1852}
1853
1854int
1855print_insn_i386_intel (pc, info)
1856 bfd_vma pc;
1857 disassemble_info *info;
1858{
1859 intel_syntax = 1;
1860
1861 return print_insn (pc, info);
1862}
1863
bellarddc990652003-03-19 00:00:28 +00001864int
1865print_insn_i386 (pc, info)
1866 bfd_vma pc;
1867 disassemble_info *info;
1868{
bellardbc51c5c2004-03-17 23:46:04 +00001869 intel_syntax = -1;
1870
1871 return print_insn (pc, info);
bellarddc990652003-03-19 00:00:28 +00001872}
1873
bellardbc51c5c2004-03-17 23:46:04 +00001874static int
1875print_insn (pc, info)
bellarddc990652003-03-19 00:00:28 +00001876 bfd_vma pc;
1877 disassemble_info *info;
bellarddc990652003-03-19 00:00:28 +00001878{
bellardbc51c5c2004-03-17 23:46:04 +00001879 const struct dis386 *dp;
bellarddc990652003-03-19 00:00:28 +00001880 int i;
bellardbc51c5c2004-03-17 23:46:04 +00001881 int two_source_ops;
bellarddc990652003-03-19 00:00:28 +00001882 char *first, *second, *third;
1883 int needcomma;
bellardbc51c5c2004-03-17 23:46:04 +00001884 unsigned char uses_SSE_prefix;
1885 int sizeflag;
1886 const char *p;
bellarddc990652003-03-19 00:00:28 +00001887 struct dis_private priv;
bellarddc990652003-03-19 00:00:28 +00001888
bellardbc51c5c2004-03-17 23:46:04 +00001889 mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
1890 || info->mach == bfd_mach_x86_64);
1891
1892 if (intel_syntax == -1)
1893 intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
1894 || info->mach == bfd_mach_x86_64_intel_syntax);
1895
1896 if (info->mach == bfd_mach_i386_i386
1897 || info->mach == bfd_mach_x86_64
1898 || info->mach == bfd_mach_i386_i386_intel_syntax
1899 || info->mach == bfd_mach_x86_64_intel_syntax)
1900 priv.orig_sizeflag = AFLAG | DFLAG;
1901 else if (info->mach == bfd_mach_i386_i8086)
1902 priv.orig_sizeflag = 0;
1903 else
1904 abort ();
1905
1906 for (p = info->disassembler_options; p != NULL; )
1907 {
1908 if (strncmp (p, "x86-64", 6) == 0)
1909 {
1910 mode_64bit = 1;
1911 priv.orig_sizeflag = AFLAG | DFLAG;
1912 }
1913 else if (strncmp (p, "i386", 4) == 0)
1914 {
1915 mode_64bit = 0;
1916 priv.orig_sizeflag = AFLAG | DFLAG;
1917 }
1918 else if (strncmp (p, "i8086", 5) == 0)
1919 {
1920 mode_64bit = 0;
1921 priv.orig_sizeflag = 0;
1922 }
1923 else if (strncmp (p, "intel", 5) == 0)
1924 {
1925 intel_syntax = 1;
1926 }
1927 else if (strncmp (p, "att", 3) == 0)
1928 {
1929 intel_syntax = 0;
1930 }
1931 else if (strncmp (p, "addr", 4) == 0)
1932 {
1933 if (p[4] == '1' && p[5] == '6')
1934 priv.orig_sizeflag &= ~AFLAG;
1935 else if (p[4] == '3' && p[5] == '2')
1936 priv.orig_sizeflag |= AFLAG;
1937 }
1938 else if (strncmp (p, "data", 4) == 0)
1939 {
1940 if (p[4] == '1' && p[5] == '6')
1941 priv.orig_sizeflag &= ~DFLAG;
1942 else if (p[4] == '3' && p[5] == '2')
1943 priv.orig_sizeflag |= DFLAG;
1944 }
1945 else if (strncmp (p, "suffix", 6) == 0)
1946 priv.orig_sizeflag |= SUFFIX_ALWAYS;
1947
1948 p = strchr (p, ',');
1949 if (p != NULL)
1950 p++;
1951 }
1952
1953 if (intel_syntax)
1954 {
1955 names64 = intel_names64;
1956 names32 = intel_names32;
1957 names16 = intel_names16;
1958 names8 = intel_names8;
1959 names8rex = intel_names8rex;
1960 names_seg = intel_names_seg;
1961 index16 = intel_index16;
1962 open_char = '[';
1963 close_char = ']';
1964 separator_char = '+';
1965 scale_char = '*';
1966 }
1967 else
1968 {
1969 names64 = att_names64;
1970 names32 = att_names32;
1971 names16 = att_names16;
1972 names8 = att_names8;
1973 names8rex = att_names8rex;
1974 names_seg = att_names_seg;
1975 index16 = att_index16;
1976 open_char = '(';
1977 close_char = ')';
1978 separator_char = ',';
1979 scale_char = ',';
1980 }
1981
1982 /* The output looks better if we put 7 bytes on a line, since that
1983 puts most long word instructions on a single line. */
1984 info->bytes_per_line = 7;
bellarddc990652003-03-19 00:00:28 +00001985
1986 info->private_data = (PTR) &priv;
1987 priv.max_fetched = priv.the_buffer;
1988 priv.insn_start = pc;
bellarddc990652003-03-19 00:00:28 +00001989
1990 obuf[0] = 0;
1991 op1out[0] = 0;
1992 op2out[0] = 0;
1993 op3out[0] = 0;
1994
1995 op_index[0] = op_index[1] = op_index[2] = -1;
1996
1997 the_info = info;
1998 start_pc = pc;
bellardbc51c5c2004-03-17 23:46:04 +00001999 start_codep = priv.the_buffer;
2000 codep = priv.the_buffer;
2001
2002 if (setjmp (priv.bailout) != 0)
2003 {
2004 const char *name;
2005
2006 /* Getting here means we tried for data but didn't get it. That
2007 means we have an incomplete instruction of some sort. Just
2008 print the first byte as a prefix or a .byte pseudo-op. */
2009 if (codep > priv.the_buffer)
2010 {
2011 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2012 if (name != NULL)
2013 (*info->fprintf_func) (info->stream, "%s", name);
2014 else
2015 {
2016 /* Just print the first byte as a .byte instruction. */
2017 (*info->fprintf_func) (info->stream, ".byte 0x%x",
2018 (unsigned int) priv.the_buffer[0]);
2019 }
2020
2021 return 1;
2022 }
2023
2024 return -1;
2025 }
2026
2027 obufp = obuf;
bellarddc990652003-03-19 00:00:28 +00002028 ckprefix ();
2029
bellardbc51c5c2004-03-17 23:46:04 +00002030 insn_codep = codep;
2031 sizeflag = priv.orig_sizeflag;
2032
bellarddc990652003-03-19 00:00:28 +00002033 FETCH_DATA (info, codep + 1);
bellardbc51c5c2004-03-17 23:46:04 +00002034 two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
2035
bellarddc990652003-03-19 00:00:28 +00002036 if ((prefixes & PREFIX_FWAIT)
2037 && ((*codep < 0xd8) || (*codep > 0xdf)))
2038 {
bellardbc51c5c2004-03-17 23:46:04 +00002039 const char *name;
2040
2041 /* fwait not followed by floating point instruction. Print the
2042 first prefix, which is probably fwait itself. */
2043 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2044 if (name == NULL)
2045 name = INTERNAL_DISASSEMBLER_ERROR;
2046 (*info->fprintf_func) (info->stream, "%s", name);
2047 return 1;
bellarddc990652003-03-19 00:00:28 +00002048 }
bellardbc51c5c2004-03-17 23:46:04 +00002049
bellarddc990652003-03-19 00:00:28 +00002050 if (*codep == 0x0f)
2051 {
2052 FETCH_DATA (info, codep + 2);
2053 dp = &dis386_twobyte[*++codep];
2054 need_modrm = twobyte_has_modrm[*codep];
bellardbc51c5c2004-03-17 23:46:04 +00002055 uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
bellarddc990652003-03-19 00:00:28 +00002056 }
2057 else
2058 {
2059 dp = &dis386[*codep];
2060 need_modrm = onebyte_has_modrm[*codep];
bellardbc51c5c2004-03-17 23:46:04 +00002061 uses_SSE_prefix = 0;
bellarddc990652003-03-19 00:00:28 +00002062 }
2063 codep++;
2064
bellardbc51c5c2004-03-17 23:46:04 +00002065 if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
2066 {
2067 oappend ("repz ");
2068 used_prefixes |= PREFIX_REPZ;
2069 }
2070 if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
2071 {
2072 oappend ("repnz ");
2073 used_prefixes |= PREFIX_REPNZ;
2074 }
2075 if (prefixes & PREFIX_LOCK)
2076 {
2077 oappend ("lock ");
2078 used_prefixes |= PREFIX_LOCK;
2079 }
2080
2081 if (prefixes & PREFIX_ADDR)
2082 {
2083 sizeflag ^= AFLAG;
2084 if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
2085 {
2086 if ((sizeflag & AFLAG) || mode_64bit)
2087 oappend ("addr32 ");
2088 else
2089 oappend ("addr16 ");
2090 used_prefixes |= PREFIX_ADDR;
2091 }
2092 }
2093
2094 if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
2095 {
2096 sizeflag ^= DFLAG;
2097 if (dp->bytemode3 == cond_jump_mode
2098 && dp->bytemode1 == v_mode
2099 && !intel_syntax)
2100 {
2101 if (sizeflag & DFLAG)
2102 oappend ("data32 ");
2103 else
2104 oappend ("data16 ");
2105 used_prefixes |= PREFIX_DATA;
2106 }
2107 }
2108
bellarddc990652003-03-19 00:00:28 +00002109 if (need_modrm)
2110 {
2111 FETCH_DATA (info, codep + 1);
2112 mod = (*codep >> 6) & 3;
2113 reg = (*codep >> 3) & 7;
2114 rm = *codep & 7;
2115 }
2116
2117 if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
2118 {
bellardbc51c5c2004-03-17 23:46:04 +00002119 dofloat (sizeflag);
bellarddc990652003-03-19 00:00:28 +00002120 }
2121 else
2122 {
bellardbc51c5c2004-03-17 23:46:04 +00002123 int index;
bellarddc990652003-03-19 00:00:28 +00002124 if (dp->name == NULL)
bellardbc51c5c2004-03-17 23:46:04 +00002125 {
2126 switch (dp->bytemode1)
2127 {
2128 case USE_GROUPS:
2129 dp = &grps[dp->bytemode2][reg];
2130 break;
2131
2132 case USE_PREFIX_USER_TABLE:
2133 index = 0;
2134 used_prefixes |= (prefixes & PREFIX_REPZ);
2135 if (prefixes & PREFIX_REPZ)
2136 index = 1;
2137 else
2138 {
2139 used_prefixes |= (prefixes & PREFIX_DATA);
2140 if (prefixes & PREFIX_DATA)
2141 index = 2;
2142 else
2143 {
2144 used_prefixes |= (prefixes & PREFIX_REPNZ);
2145 if (prefixes & PREFIX_REPNZ)
2146 index = 3;
2147 }
2148 }
2149 dp = &prefix_user_table[dp->bytemode2][index];
2150 break;
2151
2152 case X86_64_SPECIAL:
2153 dp = &x86_64_table[dp->bytemode2][mode_64bit];
2154 break;
2155
2156 default:
2157 oappend (INTERNAL_DISASSEMBLER_ERROR);
2158 break;
2159 }
2160 }
2161
2162 if (putop (dp->name, sizeflag) == 0)
2163 {
2164 obufp = op1out;
2165 op_ad = 2;
2166 if (dp->op1)
2167 (*dp->op1) (dp->bytemode1, sizeflag);
2168
2169 obufp = op2out;
2170 op_ad = 1;
2171 if (dp->op2)
2172 (*dp->op2) (dp->bytemode2, sizeflag);
2173
2174 obufp = op3out;
2175 op_ad = 0;
2176 if (dp->op3)
2177 (*dp->op3) (dp->bytemode3, sizeflag);
2178 }
bellarddc990652003-03-19 00:00:28 +00002179 }
bellardbc51c5c2004-03-17 23:46:04 +00002180
2181 /* See if any prefixes were not used. If so, print the first one
2182 separately. If we don't do this, we'll wind up printing an
2183 instruction stream which does not precisely correspond to the
2184 bytes we are disassembling. */
2185 if ((prefixes & ~used_prefixes) != 0)
2186 {
2187 const char *name;
2188
2189 name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
2190 if (name == NULL)
2191 name = INTERNAL_DISASSEMBLER_ERROR;
2192 (*info->fprintf_func) (info->stream, "%s", name);
2193 return 1;
2194 }
2195 if (rex & ~rex_used)
2196 {
2197 const char *name;
2198 name = prefix_name (rex | 0x40, priv.orig_sizeflag);
2199 if (name == NULL)
2200 name = INTERNAL_DISASSEMBLER_ERROR;
2201 (*info->fprintf_func) (info->stream, "%s ", name);
2202 }
2203
bellarddc990652003-03-19 00:00:28 +00002204 obufp = obuf + strlen (obuf);
2205 for (i = strlen (obuf); i < 6; i++)
2206 oappend (" ");
2207 oappend (" ");
2208 (*info->fprintf_func) (info->stream, "%s", obuf);
bellardbc51c5c2004-03-17 23:46:04 +00002209
2210 /* The enter and bound instructions are printed with operands in the same
2211 order as the intel book; everything else is printed in reverse order. */
2212 if (intel_syntax || two_source_ops)
bellarddc990652003-03-19 00:00:28 +00002213 {
2214 first = op1out;
2215 second = op2out;
2216 third = op3out;
2217 op_ad = op_index[0];
2218 op_index[0] = op_index[2];
2219 op_index[2] = op_ad;
2220 }
2221 else
2222 {
2223 first = op3out;
2224 second = op2out;
2225 third = op1out;
2226 }
2227 needcomma = 0;
2228 if (*first)
2229 {
bellardbc51c5c2004-03-17 23:46:04 +00002230 if (op_index[0] != -1 && !op_riprel[0])
2231 (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
bellarddc990652003-03-19 00:00:28 +00002232 else
2233 (*info->fprintf_func) (info->stream, "%s", first);
2234 needcomma = 1;
2235 }
2236 if (*second)
2237 {
2238 if (needcomma)
2239 (*info->fprintf_func) (info->stream, ",");
bellardbc51c5c2004-03-17 23:46:04 +00002240 if (op_index[1] != -1 && !op_riprel[1])
2241 (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
bellarddc990652003-03-19 00:00:28 +00002242 else
2243 (*info->fprintf_func) (info->stream, "%s", second);
2244 needcomma = 1;
2245 }
2246 if (*third)
2247 {
2248 if (needcomma)
2249 (*info->fprintf_func) (info->stream, ",");
bellardbc51c5c2004-03-17 23:46:04 +00002250 if (op_index[2] != -1 && !op_riprel[2])
2251 (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
bellarddc990652003-03-19 00:00:28 +00002252 else
2253 (*info->fprintf_func) (info->stream, "%s", third);
2254 }
bellardbc51c5c2004-03-17 23:46:04 +00002255 for (i = 0; i < 3; i++)
2256 if (op_index[i] != -1 && op_riprel[i])
2257 {
2258 (*info->fprintf_func) (info->stream, " # ");
2259 (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
2260 + op_address[op_index[i]]), info);
2261 }
2262 return codep - priv.the_buffer;
bellarddc990652003-03-19 00:00:28 +00002263}
2264
bellardbc51c5c2004-03-17 23:46:04 +00002265static const char *float_mem[] = {
bellarddc990652003-03-19 00:00:28 +00002266 /* d8 */
bellardbc51c5c2004-03-17 23:46:04 +00002267 "fadd{s||s|}",
2268 "fmul{s||s|}",
2269 "fcom{s||s|}",
2270 "fcomp{s||s|}",
2271 "fsub{s||s|}",
2272 "fsubr{s||s|}",
2273 "fdiv{s||s|}",
2274 "fdivr{s||s|}",
bellarddc990652003-03-19 00:00:28 +00002275 /* d9 */
bellardbc51c5c2004-03-17 23:46:04 +00002276 "fld{s||s|}",
bellarddc990652003-03-19 00:00:28 +00002277 "(bad)",
bellardbc51c5c2004-03-17 23:46:04 +00002278 "fst{s||s|}",
2279 "fstp{s||s|}",
bellarddc990652003-03-19 00:00:28 +00002280 "fldenv",
2281 "fldcw",
2282 "fNstenv",
2283 "fNstcw",
2284 /* da */
bellardbc51c5c2004-03-17 23:46:04 +00002285 "fiadd{l||l|}",
2286 "fimul{l||l|}",
2287 "ficom{l||l|}",
2288 "ficomp{l||l|}",
2289 "fisub{l||l|}",
2290 "fisubr{l||l|}",
2291 "fidiv{l||l|}",
2292 "fidivr{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002293 /* db */
bellardbc51c5c2004-03-17 23:46:04 +00002294 "fild{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002295 "(bad)",
bellardbc51c5c2004-03-17 23:46:04 +00002296 "fist{l||l|}",
2297 "fistp{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002298 "(bad)",
bellardbc51c5c2004-03-17 23:46:04 +00002299 "fld{t||t|}",
bellarddc990652003-03-19 00:00:28 +00002300 "(bad)",
bellardbc51c5c2004-03-17 23:46:04 +00002301 "fstp{t||t|}",
bellarddc990652003-03-19 00:00:28 +00002302 /* dc */
bellardbc51c5c2004-03-17 23:46:04 +00002303 "fadd{l||l|}",
2304 "fmul{l||l|}",
2305 "fcom{l||l|}",
2306 "fcomp{l||l|}",
2307 "fsub{l||l|}",
2308 "fsubr{l||l|}",
2309 "fdiv{l||l|}",
2310 "fdivr{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002311 /* dd */
bellardbc51c5c2004-03-17 23:46:04 +00002312 "fld{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002313 "(bad)",
bellardbc51c5c2004-03-17 23:46:04 +00002314 "fst{l||l|}",
2315 "fstp{l||l|}",
bellarddc990652003-03-19 00:00:28 +00002316 "frstor",
2317 "(bad)",
2318 "fNsave",
2319 "fNstsw",
2320 /* de */
2321 "fiadd",
2322 "fimul",
2323 "ficom",
2324 "ficomp",
2325 "fisub",
2326 "fisubr",
2327 "fidiv",
2328 "fidivr",
2329 /* df */
2330 "fild",
2331 "(bad)",
2332 "fist",
2333 "fistp",
2334 "fbld",
bellardbc51c5c2004-03-17 23:46:04 +00002335 "fild{ll||ll|}",
bellarddc990652003-03-19 00:00:28 +00002336 "fbstp",
2337 "fistpll",
2338};
2339
2340#define ST OP_ST, 0
2341#define STi OP_STi, 0
2342
bellardbc51c5c2004-03-17 23:46:04 +00002343#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
2344#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
2345#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
2346#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
2347#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
2348#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
2349#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
2350#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
2351#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
bellarddc990652003-03-19 00:00:28 +00002352
bellardbc51c5c2004-03-17 23:46:04 +00002353static const struct dis386 float_reg[][8] = {
bellarddc990652003-03-19 00:00:28 +00002354 /* d8 */
2355 {
bellardbc51c5c2004-03-17 23:46:04 +00002356 { "fadd", ST, STi, XX },
2357 { "fmul", ST, STi, XX },
2358 { "fcom", STi, XX, XX },
2359 { "fcomp", STi, XX, XX },
2360 { "fsub", ST, STi, XX },
2361 { "fsubr", ST, STi, XX },
2362 { "fdiv", ST, STi, XX },
2363 { "fdivr", ST, STi, XX },
bellarddc990652003-03-19 00:00:28 +00002364 },
2365 /* d9 */
2366 {
bellardbc51c5c2004-03-17 23:46:04 +00002367 { "fld", STi, XX, XX },
2368 { "fxch", STi, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002369 { FGRPd9_2 },
bellardbc51c5c2004-03-17 23:46:04 +00002370 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002371 { FGRPd9_4 },
2372 { FGRPd9_5 },
2373 { FGRPd9_6 },
2374 { FGRPd9_7 },
2375 },
2376 /* da */
2377 {
bellardbc51c5c2004-03-17 23:46:04 +00002378 { "fcmovb", ST, STi, XX },
2379 { "fcmove", ST, STi, XX },
2380 { "fcmovbe",ST, STi, XX },
2381 { "fcmovu", ST, STi, XX },
2382 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002383 { FGRPda_5 },
bellardbc51c5c2004-03-17 23:46:04 +00002384 { "(bad)", XX, XX, XX },
2385 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002386 },
2387 /* db */
2388 {
bellardbc51c5c2004-03-17 23:46:04 +00002389 { "fcmovnb",ST, STi, XX },
2390 { "fcmovne",ST, STi, XX },
2391 { "fcmovnbe",ST, STi, XX },
2392 { "fcmovnu",ST, STi, XX },
bellarddc990652003-03-19 00:00:28 +00002393 { FGRPdb_4 },
bellardbc51c5c2004-03-17 23:46:04 +00002394 { "fucomi", ST, STi, XX },
2395 { "fcomi", ST, STi, XX },
2396 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002397 },
2398 /* dc */
2399 {
bellardbc51c5c2004-03-17 23:46:04 +00002400 { "fadd", STi, ST, XX },
2401 { "fmul", STi, ST, XX },
2402 { "(bad)", XX, XX, XX },
2403 { "(bad)", XX, XX, XX },
2404#if UNIXWARE_COMPAT
2405 { "fsub", STi, ST, XX },
2406 { "fsubr", STi, ST, XX },
2407 { "fdiv", STi, ST, XX },
2408 { "fdivr", STi, ST, XX },
2409#else
2410 { "fsubr", STi, ST, XX },
2411 { "fsub", STi, ST, XX },
2412 { "fdivr", STi, ST, XX },
2413 { "fdiv", STi, ST, XX },
2414#endif
bellarddc990652003-03-19 00:00:28 +00002415 },
2416 /* dd */
2417 {
bellardbc51c5c2004-03-17 23:46:04 +00002418 { "ffree", STi, XX, XX },
2419 { "(bad)", XX, XX, XX },
2420 { "fst", STi, XX, XX },
2421 { "fstp", STi, XX, XX },
2422 { "fucom", STi, XX, XX },
2423 { "fucomp", STi, XX, XX },
2424 { "(bad)", XX, XX, XX },
2425 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002426 },
2427 /* de */
2428 {
bellardbc51c5c2004-03-17 23:46:04 +00002429 { "faddp", STi, ST, XX },
2430 { "fmulp", STi, ST, XX },
2431 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002432 { FGRPde_3 },
bellardbc51c5c2004-03-17 23:46:04 +00002433#if UNIXWARE_COMPAT
2434 { "fsubp", STi, ST, XX },
2435 { "fsubrp", STi, ST, XX },
2436 { "fdivp", STi, ST, XX },
2437 { "fdivrp", STi, ST, XX },
2438#else
2439 { "fsubrp", STi, ST, XX },
2440 { "fsubp", STi, ST, XX },
2441 { "fdivrp", STi, ST, XX },
2442 { "fdivp", STi, ST, XX },
2443#endif
bellarddc990652003-03-19 00:00:28 +00002444 },
2445 /* df */
2446 {
bellardbc51c5c2004-03-17 23:46:04 +00002447 { "ffreep", STi, XX, XX },
2448 { "(bad)", XX, XX, XX },
2449 { "(bad)", XX, XX, XX },
2450 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002451 { FGRPdf_4 },
bellardbc51c5c2004-03-17 23:46:04 +00002452 { "fucomip",ST, STi, XX },
2453 { "fcomip", ST, STi, XX },
2454 { "(bad)", XX, XX, XX },
bellarddc990652003-03-19 00:00:28 +00002455 },
2456};
2457
bellarddc990652003-03-19 00:00:28 +00002458static char *fgrps[][8] = {
2459 /* d9_2 0 */
2460 {
2461 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2462 },
2463
2464 /* d9_4 1 */
2465 {
2466 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
2467 },
2468
2469 /* d9_5 2 */
2470 {
2471 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
2472 },
2473
2474 /* d9_6 3 */
2475 {
2476 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
2477 },
2478
2479 /* d9_7 4 */
2480 {
2481 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
2482 },
2483
2484 /* da_5 5 */
2485 {
2486 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2487 },
2488
2489 /* db_4 6 */
2490 {
2491 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
2492 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
2493 },
2494
2495 /* de_3 7 */
2496 {
2497 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2498 },
2499
2500 /* df_4 8 */
2501 {
2502 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2503 },
2504};
2505
2506static void
bellardbc51c5c2004-03-17 23:46:04 +00002507dofloat (sizeflag)
2508 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00002509{
bellardbc51c5c2004-03-17 23:46:04 +00002510 const struct dis386 *dp;
bellarddc990652003-03-19 00:00:28 +00002511 unsigned char floatop;
bellardbc51c5c2004-03-17 23:46:04 +00002512
bellarddc990652003-03-19 00:00:28 +00002513 floatop = codep[-1];
bellardbc51c5c2004-03-17 23:46:04 +00002514
bellarddc990652003-03-19 00:00:28 +00002515 if (mod != 3)
2516 {
bellardbc51c5c2004-03-17 23:46:04 +00002517 putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag);
bellarddc990652003-03-19 00:00:28 +00002518 obufp = op1out;
bellardbc51c5c2004-03-17 23:46:04 +00002519 if (floatop == 0xdb)
2520 OP_E (x_mode, sizeflag);
2521 else if (floatop == 0xdd)
2522 OP_E (d_mode, sizeflag);
2523 else
2524 OP_E (v_mode, sizeflag);
bellarddc990652003-03-19 00:00:28 +00002525 return;
2526 }
bellardbc51c5c2004-03-17 23:46:04 +00002527 /* Skip mod/rm byte. */
2528 MODRM_CHECK;
bellarddc990652003-03-19 00:00:28 +00002529 codep++;
bellardbc51c5c2004-03-17 23:46:04 +00002530
bellarddc990652003-03-19 00:00:28 +00002531 dp = &float_reg[floatop - 0xd8][reg];
2532 if (dp->name == NULL)
2533 {
bellardbc51c5c2004-03-17 23:46:04 +00002534 putop (fgrps[dp->bytemode1][rm], sizeflag);
2535
2536 /* Instruction fnstsw is only one with strange arg. */
2537 if (floatop == 0xdf && codep[-1] == 0xe0)
2538 strcpy (op1out, names16[0]);
bellarddc990652003-03-19 00:00:28 +00002539 }
2540 else
2541 {
bellardbc51c5c2004-03-17 23:46:04 +00002542 putop (dp->name, sizeflag);
2543
bellarddc990652003-03-19 00:00:28 +00002544 obufp = op1out;
2545 if (dp->op1)
bellardbc51c5c2004-03-17 23:46:04 +00002546 (*dp->op1) (dp->bytemode1, sizeflag);
bellarddc990652003-03-19 00:00:28 +00002547 obufp = op2out;
2548 if (dp->op2)
bellardbc51c5c2004-03-17 23:46:04 +00002549 (*dp->op2) (dp->bytemode2, sizeflag);
bellarddc990652003-03-19 00:00:28 +00002550 }
2551}
2552
bellardbc51c5c2004-03-17 23:46:04 +00002553static void
2554OP_ST (bytemode, sizeflag)
2555 int bytemode;
2556 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00002557{
2558 oappend ("%st");
bellarddc990652003-03-19 00:00:28 +00002559}
2560
bellardbc51c5c2004-03-17 23:46:04 +00002561static void
2562OP_STi (bytemode, sizeflag)
2563 int bytemode;
2564 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00002565{
2566 sprintf (scratchbuf, "%%st(%d)", rm);
bellardbc51c5c2004-03-17 23:46:04 +00002567 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00002568}
2569
bellardbc51c5c2004-03-17 23:46:04 +00002570/* Capital letters in template are macros. */
2571static int
2572putop (template, sizeflag)
2573 const char *template;
2574 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00002575{
bellardbc51c5c2004-03-17 23:46:04 +00002576 const char *p;
2577 int alt;
2578
bellarddc990652003-03-19 00:00:28 +00002579 for (p = template; *p; p++)
2580 {
2581 switch (*p)
2582 {
2583 default:
2584 *obufp++ = *p;
2585 break;
bellardbc51c5c2004-03-17 23:46:04 +00002586 case '{':
2587 alt = 0;
2588 if (intel_syntax)
2589 alt += 1;
2590 if (mode_64bit)
2591 alt += 2;
2592 while (alt != 0)
2593 {
2594 while (*++p != '|')
2595 {
2596 if (*p == '}')
2597 {
2598 /* Alternative not valid. */
2599 strcpy (obuf, "(bad)");
2600 obufp = obuf + 5;
2601 return 1;
2602 }
2603 else if (*p == '\0')
2604 abort ();
2605 }
2606 alt--;
2607 }
2608 break;
2609 case '|':
2610 while (*++p != '}')
2611 {
2612 if (*p == '\0')
2613 abort ();
2614 }
2615 break;
2616 case '}':
2617 break;
2618 case 'A':
2619 if (intel_syntax)
2620 break;
2621 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
2622 *obufp++ = 'b';
2623 break;
2624 case 'B':
2625 if (intel_syntax)
2626 break;
2627 if (sizeflag & SUFFIX_ALWAYS)
2628 *obufp++ = 'b';
2629 break;
2630 case 'E': /* For jcxz/jecxz */
2631 if (mode_64bit)
2632 {
2633 if (sizeflag & AFLAG)
2634 *obufp++ = 'r';
2635 else
2636 *obufp++ = 'e';
2637 }
2638 else
2639 if (sizeflag & AFLAG)
2640 *obufp++ = 'e';
2641 used_prefixes |= (prefixes & PREFIX_ADDR);
2642 break;
2643 case 'F':
2644 if (intel_syntax)
2645 break;
2646 if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
2647 {
2648 if (sizeflag & AFLAG)
2649 *obufp++ = mode_64bit ? 'q' : 'l';
2650 else
2651 *obufp++ = mode_64bit ? 'l' : 'w';
2652 used_prefixes |= (prefixes & PREFIX_ADDR);
2653 }
2654 break;
2655 case 'H':
2656 if (intel_syntax)
2657 break;
2658 if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
2659 || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
2660 {
2661 used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
2662 *obufp++ = ',';
2663 *obufp++ = 'p';
2664 if (prefixes & PREFIX_DS)
2665 *obufp++ = 't';
2666 else
2667 *obufp++ = 'n';
2668 }
2669 break;
2670 case 'L':
2671 if (intel_syntax)
2672 break;
2673 if (sizeflag & SUFFIX_ALWAYS)
2674 *obufp++ = 'l';
bellarddc990652003-03-19 00:00:28 +00002675 break;
2676 case 'N':
2677 if ((prefixes & PREFIX_FWAIT) == 0)
2678 *obufp++ = 'n';
bellardbc51c5c2004-03-17 23:46:04 +00002679 else
2680 used_prefixes |= PREFIX_FWAIT;
2681 break;
2682 case 'O':
2683 USED_REX (REX_MODE64);
2684 if (rex & REX_MODE64)
2685 *obufp++ = 'o';
2686 else
2687 *obufp++ = 'd';
2688 break;
2689 case 'T':
2690 if (intel_syntax)
2691 break;
2692 if (mode_64bit)
2693 {
2694 *obufp++ = 'q';
2695 break;
2696 }
2697 /* Fall through. */
2698 case 'P':
2699 if (intel_syntax)
2700 break;
2701 if ((prefixes & PREFIX_DATA)
2702 || (rex & REX_MODE64)
2703 || (sizeflag & SUFFIX_ALWAYS))
2704 {
2705 USED_REX (REX_MODE64);
2706 if (rex & REX_MODE64)
2707 *obufp++ = 'q';
2708 else
2709 {
2710 if (sizeflag & DFLAG)
2711 *obufp++ = 'l';
2712 else
2713 *obufp++ = 'w';
2714 used_prefixes |= (prefixes & PREFIX_DATA);
2715 }
2716 }
2717 break;
2718 case 'U':
2719 if (intel_syntax)
2720 break;
2721 if (mode_64bit)
2722 {
2723 *obufp++ = 'q';
2724 break;
2725 }
2726 /* Fall through. */
2727 case 'Q':
2728 if (intel_syntax)
2729 break;
2730 USED_REX (REX_MODE64);
2731 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
2732 {
2733 if (rex & REX_MODE64)
2734 *obufp++ = 'q';
2735 else
2736 {
2737 if (sizeflag & DFLAG)
2738 *obufp++ = 'l';
2739 else
2740 *obufp++ = 'w';
2741 used_prefixes |= (prefixes & PREFIX_DATA);
2742 }
2743 }
2744 break;
2745 case 'R':
2746 USED_REX (REX_MODE64);
2747 if (intel_syntax)
2748 {
2749 if (rex & REX_MODE64)
2750 {
2751 *obufp++ = 'q';
2752 *obufp++ = 't';
2753 }
2754 else if (sizeflag & DFLAG)
2755 {
2756 *obufp++ = 'd';
2757 *obufp++ = 'q';
2758 }
2759 else
2760 {
2761 *obufp++ = 'w';
2762 *obufp++ = 'd';
2763 }
2764 }
2765 else
2766 {
2767 if (rex & REX_MODE64)
2768 *obufp++ = 'q';
2769 else if (sizeflag & DFLAG)
2770 *obufp++ = 'l';
2771 else
2772 *obufp++ = 'w';
2773 }
2774 if (!(rex & REX_MODE64))
2775 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00002776 break;
2777 case 'S':
bellardbc51c5c2004-03-17 23:46:04 +00002778 if (intel_syntax)
2779 break;
2780 if (sizeflag & SUFFIX_ALWAYS)
2781 {
2782 if (rex & REX_MODE64)
2783 *obufp++ = 'q';
2784 else
2785 {
2786 if (sizeflag & DFLAG)
2787 *obufp++ = 'l';
2788 else
2789 *obufp++ = 'w';
2790 used_prefixes |= (prefixes & PREFIX_DATA);
2791 }
2792 }
bellarddc990652003-03-19 00:00:28 +00002793 break;
bellardbc51c5c2004-03-17 23:46:04 +00002794 case 'X':
2795 if (prefixes & PREFIX_DATA)
2796 *obufp++ = 'd';
2797 else
2798 *obufp++ = 's';
2799 used_prefixes |= (prefixes & PREFIX_DATA);
2800 break;
2801 case 'Y':
2802 if (intel_syntax)
2803 break;
2804 if (rex & REX_MODE64)
2805 {
2806 USED_REX (REX_MODE64);
2807 *obufp++ = 'q';
2808 }
2809 break;
2810 /* implicit operand size 'l' for i386 or 'q' for x86-64 */
bellarddc990652003-03-19 00:00:28 +00002811 case 'W':
2812 /* operand size flag for cwtl, cbtw */
bellardbc51c5c2004-03-17 23:46:04 +00002813 USED_REX (0);
2814 if (rex)
2815 *obufp++ = 'l';
2816 else if (sizeflag & DFLAG)
bellarddc990652003-03-19 00:00:28 +00002817 *obufp++ = 'w';
2818 else
2819 *obufp++ = 'b';
bellardbc51c5c2004-03-17 23:46:04 +00002820 if (intel_syntax)
2821 {
2822 if (rex)
2823 {
2824 *obufp++ = 'q';
2825 *obufp++ = 'e';
2826 }
2827 if (sizeflag & DFLAG)
2828 {
2829 *obufp++ = 'd';
2830 *obufp++ = 'e';
2831 }
2832 else
2833 {
2834 *obufp++ = 'w';
2835 }
2836 }
2837 if (!rex)
2838 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00002839 break;
2840 }
2841 }
2842 *obufp = 0;
bellardbc51c5c2004-03-17 23:46:04 +00002843 return 0;
bellarddc990652003-03-19 00:00:28 +00002844}
2845
2846static void
2847oappend (s)
bellardbc51c5c2004-03-17 23:46:04 +00002848 const char *s;
bellarddc990652003-03-19 00:00:28 +00002849{
2850 strcpy (obufp, s);
2851 obufp += strlen (s);
bellarddc990652003-03-19 00:00:28 +00002852}
2853
2854static void
bellardbc51c5c2004-03-17 23:46:04 +00002855append_seg ()
bellarddc990652003-03-19 00:00:28 +00002856{
2857 if (prefixes & PREFIX_CS)
bellardbc51c5c2004-03-17 23:46:04 +00002858 {
2859 used_prefixes |= PREFIX_CS;
2860 oappend ("%cs:" + intel_syntax);
2861 }
bellarddc990652003-03-19 00:00:28 +00002862 if (prefixes & PREFIX_DS)
bellardbc51c5c2004-03-17 23:46:04 +00002863 {
2864 used_prefixes |= PREFIX_DS;
2865 oappend ("%ds:" + intel_syntax);
2866 }
bellarddc990652003-03-19 00:00:28 +00002867 if (prefixes & PREFIX_SS)
bellardbc51c5c2004-03-17 23:46:04 +00002868 {
2869 used_prefixes |= PREFIX_SS;
2870 oappend ("%ss:" + intel_syntax);
2871 }
bellarddc990652003-03-19 00:00:28 +00002872 if (prefixes & PREFIX_ES)
bellardbc51c5c2004-03-17 23:46:04 +00002873 {
2874 used_prefixes |= PREFIX_ES;
2875 oappend ("%es:" + intel_syntax);
2876 }
bellarddc990652003-03-19 00:00:28 +00002877 if (prefixes & PREFIX_FS)
bellardbc51c5c2004-03-17 23:46:04 +00002878 {
2879 used_prefixes |= PREFIX_FS;
2880 oappend ("%fs:" + intel_syntax);
2881 }
bellarddc990652003-03-19 00:00:28 +00002882 if (prefixes & PREFIX_GS)
bellardbc51c5c2004-03-17 23:46:04 +00002883 {
2884 used_prefixes |= PREFIX_GS;
2885 oappend ("%gs:" + intel_syntax);
2886 }
bellarddc990652003-03-19 00:00:28 +00002887}
2888
bellardbc51c5c2004-03-17 23:46:04 +00002889static void
2890OP_indirE (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00002891 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00002892 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00002893{
bellardbc51c5c2004-03-17 23:46:04 +00002894 if (!intel_syntax)
2895 oappend ("*");
2896 OP_E (bytemode, sizeflag);
bellarddc990652003-03-19 00:00:28 +00002897}
2898
bellardbc51c5c2004-03-17 23:46:04 +00002899static void
2900print_operand_value (buf, hex, disp)
2901 char *buf;
2902 int hex;
2903 bfd_vma disp;
bellarddc990652003-03-19 00:00:28 +00002904{
bellardbc51c5c2004-03-17 23:46:04 +00002905 if (mode_64bit)
2906 {
2907 if (hex)
2908 {
2909 char tmp[30];
2910 int i;
2911 buf[0] = '0';
2912 buf[1] = 'x';
2913 sprintf_vma (tmp, disp);
2914 for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
2915 strcpy (buf + 2, tmp + i);
2916 }
2917 else
2918 {
2919 bfd_signed_vma v = disp;
2920 char tmp[30];
2921 int i;
2922 if (v < 0)
2923 {
2924 *(buf++) = '-';
2925 v = -disp;
2926 /* Check for possible overflow on 0x8000000000000000. */
2927 if (v < 0)
2928 {
2929 strcpy (buf, "9223372036854775808");
2930 return;
2931 }
2932 }
2933 if (!v)
2934 {
2935 strcpy (buf, "0");
2936 return;
2937 }
bellarddc990652003-03-19 00:00:28 +00002938
bellardbc51c5c2004-03-17 23:46:04 +00002939 i = 0;
2940 tmp[29] = 0;
2941 while (v)
2942 {
2943 tmp[28 - i] = (v % 10) + '0';
2944 v /= 10;
2945 i++;
2946 }
2947 strcpy (buf, tmp + 29 - i);
2948 }
2949 }
2950 else
2951 {
2952 if (hex)
2953 sprintf (buf, "0x%x", (unsigned int) disp);
2954 else
2955 sprintf (buf, "%d", (int) disp);
2956 }
2957}
2958
2959static void
2960OP_E (bytemode, sizeflag)
2961 int bytemode;
2962 int sizeflag;
2963{
2964 bfd_vma disp;
2965 int add = 0;
2966 int riprel = 0;
2967 USED_REX (REX_EXTZ);
2968 if (rex & REX_EXTZ)
2969 add += 8;
2970
2971 /* Skip mod/rm byte. */
2972 MODRM_CHECK;
bellarddc990652003-03-19 00:00:28 +00002973 codep++;
2974
2975 if (mod == 3)
2976 {
2977 switch (bytemode)
2978 {
2979 case b_mode:
bellardbc51c5c2004-03-17 23:46:04 +00002980 USED_REX (0);
2981 if (rex)
2982 oappend (names8rex[rm + add]);
2983 else
2984 oappend (names8[rm + add]);
bellarddc990652003-03-19 00:00:28 +00002985 break;
2986 case w_mode:
bellardbc51c5c2004-03-17 23:46:04 +00002987 oappend (names16[rm + add]);
2988 break;
2989 case d_mode:
2990 oappend (names32[rm + add]);
2991 break;
2992 case q_mode:
2993 oappend (names64[rm + add]);
2994 break;
2995 case m_mode:
2996 if (mode_64bit)
2997 oappend (names64[rm + add]);
2998 else
2999 oappend (names32[rm + add]);
bellarddc990652003-03-19 00:00:28 +00003000 break;
3001 case v_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003002 USED_REX (REX_MODE64);
3003 if (rex & REX_MODE64)
3004 oappend (names64[rm + add]);
3005 else if (sizeflag & DFLAG)
3006 oappend (names32[rm + add]);
bellarddc990652003-03-19 00:00:28 +00003007 else
bellardbc51c5c2004-03-17 23:46:04 +00003008 oappend (names16[rm + add]);
3009 used_prefixes |= (prefixes & PREFIX_DATA);
3010 break;
3011 case 0:
3012 if (!(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */)
3013 && !(codep[-2] == 0xAE && codep[-1] == 0xF0 /* mfence */)
3014 && !(codep[-2] == 0xAE && codep[-1] == 0xe8 /* lfence */))
3015 BadOp (); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
bellarddc990652003-03-19 00:00:28 +00003016 break;
3017 default:
bellardbc51c5c2004-03-17 23:46:04 +00003018 oappend (INTERNAL_DISASSEMBLER_ERROR);
bellarddc990652003-03-19 00:00:28 +00003019 break;
3020 }
bellardbc51c5c2004-03-17 23:46:04 +00003021 return;
bellarddc990652003-03-19 00:00:28 +00003022 }
3023
3024 disp = 0;
bellardbc51c5c2004-03-17 23:46:04 +00003025 append_seg ();
bellarddc990652003-03-19 00:00:28 +00003026
bellardbc51c5c2004-03-17 23:46:04 +00003027 if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */
bellarddc990652003-03-19 00:00:28 +00003028 {
3029 int havesib;
3030 int havebase;
3031 int base;
3032 int index = 0;
3033 int scale = 0;
3034
3035 havesib = 0;
3036 havebase = 1;
3037 base = rm;
3038
3039 if (base == 4)
3040 {
3041 havesib = 1;
3042 FETCH_DATA (the_info, codep + 1);
3043 scale = (*codep >> 6) & 3;
3044 index = (*codep >> 3) & 7;
3045 base = *codep & 7;
bellardbc51c5c2004-03-17 23:46:04 +00003046 USED_REX (REX_EXTY);
3047 USED_REX (REX_EXTZ);
3048 if (rex & REX_EXTY)
3049 index += 8;
3050 if (rex & REX_EXTZ)
3051 base += 8;
bellarddc990652003-03-19 00:00:28 +00003052 codep++;
3053 }
3054
3055 switch (mod)
3056 {
3057 case 0:
bellardbc51c5c2004-03-17 23:46:04 +00003058 if ((base & 7) == 5)
bellarddc990652003-03-19 00:00:28 +00003059 {
3060 havebase = 0;
bellardbc51c5c2004-03-17 23:46:04 +00003061 if (mode_64bit && !havesib && (sizeflag & AFLAG))
3062 riprel = 1;
3063 disp = get32s ();
bellarddc990652003-03-19 00:00:28 +00003064 }
3065 break;
3066 case 1:
3067 FETCH_DATA (the_info, codep + 1);
3068 disp = *codep++;
3069 if ((disp & 0x80) != 0)
3070 disp -= 0x100;
3071 break;
3072 case 2:
bellardbc51c5c2004-03-17 23:46:04 +00003073 disp = get32s ();
bellarddc990652003-03-19 00:00:28 +00003074 break;
3075 }
3076
bellardbc51c5c2004-03-17 23:46:04 +00003077 if (!intel_syntax)
3078 if (mod != 0 || (base & 7) == 5)
3079 {
3080 print_operand_value (scratchbuf, !riprel, disp);
3081 oappend (scratchbuf);
3082 if (riprel)
3083 {
3084 set_op (disp, 1);
3085 oappend ("(%rip)");
3086 }
3087 }
bellarddc990652003-03-19 00:00:28 +00003088
3089 if (havebase || (havesib && (index != 4 || scale != 0)))
3090 {
bellardbc51c5c2004-03-17 23:46:04 +00003091 if (intel_syntax)
3092 {
3093 switch (bytemode)
3094 {
3095 case b_mode:
3096 oappend ("BYTE PTR ");
3097 break;
3098 case w_mode:
3099 oappend ("WORD PTR ");
3100 break;
3101 case v_mode:
3102 oappend ("DWORD PTR ");
3103 break;
3104 case d_mode:
3105 oappend ("QWORD PTR ");
3106 break;
3107 case m_mode:
3108 if (mode_64bit)
3109 oappend ("DWORD PTR ");
3110 else
3111 oappend ("QWORD PTR ");
3112 break;
3113 case x_mode:
3114 oappend ("XWORD PTR ");
3115 break;
3116 default:
3117 break;
3118 }
3119 }
3120 *obufp++ = open_char;
3121 if (intel_syntax && riprel)
3122 oappend ("rip + ");
3123 *obufp = '\0';
3124 USED_REX (REX_EXTZ);
3125 if (!havesib && (rex & REX_EXTZ))
3126 base += 8;
bellarddc990652003-03-19 00:00:28 +00003127 if (havebase)
bellardbc51c5c2004-03-17 23:46:04 +00003128 oappend (mode_64bit && (sizeflag & AFLAG)
3129 ? names64[base] : names32[base]);
bellarddc990652003-03-19 00:00:28 +00003130 if (havesib)
3131 {
3132 if (index != 4)
3133 {
bellardbc51c5c2004-03-17 23:46:04 +00003134 if (intel_syntax)
3135 {
3136 if (havebase)
3137 {
3138 *obufp++ = separator_char;
3139 *obufp = '\0';
3140 }
3141 sprintf (scratchbuf, "%s",
3142 mode_64bit && (sizeflag & AFLAG)
3143 ? names64[index] : names32[index]);
3144 }
3145 else
3146 sprintf (scratchbuf, ",%s",
3147 mode_64bit && (sizeflag & AFLAG)
3148 ? names64[index] : names32[index]);
bellarddc990652003-03-19 00:00:28 +00003149 oappend (scratchbuf);
3150 }
bellardbc51c5c2004-03-17 23:46:04 +00003151 if (!intel_syntax
3152 || (intel_syntax
3153 && bytemode != b_mode
3154 && bytemode != w_mode
3155 && bytemode != v_mode))
3156 {
3157 *obufp++ = scale_char;
3158 *obufp = '\0';
3159 sprintf (scratchbuf, "%d", 1 << scale);
3160 oappend (scratchbuf);
3161 }
bellarddc990652003-03-19 00:00:28 +00003162 }
bellardbc51c5c2004-03-17 23:46:04 +00003163 if (intel_syntax)
3164 if (mod != 0 || (base & 7) == 5)
3165 {
3166 /* Don't print zero displacements. */
3167 if (disp != 0)
3168 {
3169 if ((bfd_signed_vma) disp > 0)
3170 {
3171 *obufp++ = '+';
3172 *obufp = '\0';
3173 }
3174
3175 print_operand_value (scratchbuf, 0, disp);
3176 oappend (scratchbuf);
3177 }
3178 }
3179
3180 *obufp++ = close_char;
3181 *obufp = '\0';
bellarddc990652003-03-19 00:00:28 +00003182 }
bellardbc51c5c2004-03-17 23:46:04 +00003183 else if (intel_syntax)
3184 {
3185 if (mod != 0 || (base & 7) == 5)
3186 {
3187 if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
3188 | PREFIX_ES | PREFIX_FS | PREFIX_GS))
3189 ;
3190 else
3191 {
3192 oappend (names_seg[ds_reg - es_reg]);
3193 oappend (":");
3194 }
3195 print_operand_value (scratchbuf, 1, disp);
3196 oappend (scratchbuf);
3197 }
3198 }
bellarddc990652003-03-19 00:00:28 +00003199 }
3200 else
3201 { /* 16 bit address mode */
3202 switch (mod)
3203 {
3204 case 0:
bellardbc51c5c2004-03-17 23:46:04 +00003205 if ((rm & 7) == 6)
bellarddc990652003-03-19 00:00:28 +00003206 {
3207 disp = get16 ();
3208 if ((disp & 0x8000) != 0)
3209 disp -= 0x10000;
3210 }
3211 break;
3212 case 1:
3213 FETCH_DATA (the_info, codep + 1);
3214 disp = *codep++;
3215 if ((disp & 0x80) != 0)
3216 disp -= 0x100;
3217 break;
3218 case 2:
3219 disp = get16 ();
3220 if ((disp & 0x8000) != 0)
3221 disp -= 0x10000;
3222 break;
3223 }
3224
bellardbc51c5c2004-03-17 23:46:04 +00003225 if (!intel_syntax)
3226 if (mod != 0 || (rm & 7) == 6)
3227 {
3228 print_operand_value (scratchbuf, 0, disp);
3229 oappend (scratchbuf);
3230 }
bellarddc990652003-03-19 00:00:28 +00003231
bellardbc51c5c2004-03-17 23:46:04 +00003232 if (mod != 0 || (rm & 7) != 6)
bellarddc990652003-03-19 00:00:28 +00003233 {
bellardbc51c5c2004-03-17 23:46:04 +00003234 *obufp++ = open_char;
3235 *obufp = '\0';
3236 oappend (index16[rm + add]);
3237 *obufp++ = close_char;
3238 *obufp = '\0';
bellarddc990652003-03-19 00:00:28 +00003239 }
3240 }
bellarddc990652003-03-19 00:00:28 +00003241}
3242
bellardbc51c5c2004-03-17 23:46:04 +00003243static void
3244OP_G (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003245 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003246 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003247{
bellardbc51c5c2004-03-17 23:46:04 +00003248 int add = 0;
3249 USED_REX (REX_EXTX);
3250 if (rex & REX_EXTX)
3251 add += 8;
3252 switch (bytemode)
bellarddc990652003-03-19 00:00:28 +00003253 {
3254 case b_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003255 USED_REX (0);
3256 if (rex)
3257 oappend (names8rex[reg + add]);
3258 else
3259 oappend (names8[reg + add]);
bellarddc990652003-03-19 00:00:28 +00003260 break;
3261 case w_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003262 oappend (names16[reg + add]);
bellarddc990652003-03-19 00:00:28 +00003263 break;
3264 case d_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003265 oappend (names32[reg + add]);
3266 break;
3267 case q_mode:
3268 oappend (names64[reg + add]);
bellarddc990652003-03-19 00:00:28 +00003269 break;
3270 case v_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003271 USED_REX (REX_MODE64);
3272 if (rex & REX_MODE64)
3273 oappend (names64[reg + add]);
3274 else if (sizeflag & DFLAG)
3275 oappend (names32[reg + add]);
bellarddc990652003-03-19 00:00:28 +00003276 else
bellardbc51c5c2004-03-17 23:46:04 +00003277 oappend (names16[reg + add]);
3278 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00003279 break;
3280 default:
bellardbc51c5c2004-03-17 23:46:04 +00003281 oappend (INTERNAL_DISASSEMBLER_ERROR);
bellarddc990652003-03-19 00:00:28 +00003282 break;
3283 }
bellarddc990652003-03-19 00:00:28 +00003284}
3285
bellardbc51c5c2004-03-17 23:46:04 +00003286static bfd_vma
3287get64 ()
3288{
3289 bfd_vma x;
3290#ifdef BFD64
3291 unsigned int a;
3292 unsigned int b;
3293
3294 FETCH_DATA (the_info, codep + 8);
3295 a = *codep++ & 0xff;
3296 a |= (*codep++ & 0xff) << 8;
3297 a |= (*codep++ & 0xff) << 16;
3298 a |= (*codep++ & 0xff) << 24;
3299 b = *codep++ & 0xff;
3300 b |= (*codep++ & 0xff) << 8;
3301 b |= (*codep++ & 0xff) << 16;
3302 b |= (*codep++ & 0xff) << 24;
3303 x = a + ((bfd_vma) b << 32);
3304#else
3305 abort ();
3306 x = 0;
3307#endif
3308 return x;
3309}
3310
3311static bfd_signed_vma
bellarddc990652003-03-19 00:00:28 +00003312get32 ()
3313{
bellardbc51c5c2004-03-17 23:46:04 +00003314 bfd_signed_vma x = 0;
bellarddc990652003-03-19 00:00:28 +00003315
3316 FETCH_DATA (the_info, codep + 4);
bellardbc51c5c2004-03-17 23:46:04 +00003317 x = *codep++ & (bfd_signed_vma) 0xff;
3318 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
3319 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
3320 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
3321 return x;
3322}
3323
3324static bfd_signed_vma
3325get32s ()
3326{
3327 bfd_signed_vma x = 0;
3328
3329 FETCH_DATA (the_info, codep + 4);
3330 x = *codep++ & (bfd_signed_vma) 0xff;
3331 x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
3332 x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
3333 x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
3334
3335 x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
3336
3337 return x;
bellarddc990652003-03-19 00:00:28 +00003338}
3339
3340static int
3341get16 ()
3342{
3343 int x = 0;
3344
3345 FETCH_DATA (the_info, codep + 2);
3346 x = *codep++ & 0xff;
3347 x |= (*codep++ & 0xff) << 8;
bellardbc51c5c2004-03-17 23:46:04 +00003348 return x;
bellarddc990652003-03-19 00:00:28 +00003349}
3350
3351static void
bellardbc51c5c2004-03-17 23:46:04 +00003352set_op (op, riprel)
3353 bfd_vma op;
3354 int riprel;
bellarddc990652003-03-19 00:00:28 +00003355{
3356 op_index[op_ad] = op_ad;
bellardbc51c5c2004-03-17 23:46:04 +00003357 if (mode_64bit)
3358 {
3359 op_address[op_ad] = op;
3360 op_riprel[op_ad] = riprel;
3361 }
3362 else
3363 {
3364 /* Mask to get a 32-bit address. */
3365 op_address[op_ad] = op & 0xffffffff;
3366 op_riprel[op_ad] = riprel & 0xffffffff;
3367 }
bellarddc990652003-03-19 00:00:28 +00003368}
3369
bellardbc51c5c2004-03-17 23:46:04 +00003370static void
3371OP_REG (code, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003372 int code;
bellardbc51c5c2004-03-17 23:46:04 +00003373 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003374{
bellardbc51c5c2004-03-17 23:46:04 +00003375 const char *s;
3376 int add = 0;
3377 USED_REX (REX_EXTZ);
3378 if (rex & REX_EXTZ)
3379 add = 8;
3380
3381 switch (code)
bellarddc990652003-03-19 00:00:28 +00003382 {
bellardbc51c5c2004-03-17 23:46:04 +00003383 case indir_dx_reg:
3384 if (intel_syntax)
3385 s = "[dx]";
bellarddc990652003-03-19 00:00:28 +00003386 else
bellardbc51c5c2004-03-17 23:46:04 +00003387 s = "(%dx)";
3388 break;
3389 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
3390 case sp_reg: case bp_reg: case si_reg: case di_reg:
3391 s = names16[code - ax_reg + add];
3392 break;
3393 case es_reg: case ss_reg: case cs_reg:
3394 case ds_reg: case fs_reg: case gs_reg:
3395 s = names_seg[code - es_reg + add];
3396 break;
3397 case al_reg: case ah_reg: case cl_reg: case ch_reg:
3398 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
3399 USED_REX (0);
3400 if (rex)
3401 s = names8rex[code - al_reg + add];
3402 else
3403 s = names8[code - al_reg];
3404 break;
3405 case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
3406 case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
3407 if (mode_64bit)
3408 {
3409 s = names64[code - rAX_reg + add];
3410 break;
3411 }
3412 code += eAX_reg - rAX_reg;
3413 /* Fall through. */
3414 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
3415 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
3416 USED_REX (REX_MODE64);
3417 if (rex & REX_MODE64)
3418 s = names64[code - eAX_reg + add];
3419 else if (sizeflag & DFLAG)
3420 s = names32[code - eAX_reg + add];
3421 else
3422 s = names16[code - eAX_reg + add];
3423 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00003424 break;
3425 default:
bellardbc51c5c2004-03-17 23:46:04 +00003426 s = INTERNAL_DISASSEMBLER_ERROR;
bellarddc990652003-03-19 00:00:28 +00003427 break;
3428 }
3429 oappend (s);
bellarddc990652003-03-19 00:00:28 +00003430}
3431
bellardbc51c5c2004-03-17 23:46:04 +00003432static void
3433OP_IMREG (code, sizeflag)
3434 int code;
3435 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003436{
bellardbc51c5c2004-03-17 23:46:04 +00003437 const char *s;
3438
3439 switch (code)
3440 {
3441 case indir_dx_reg:
3442 if (intel_syntax)
3443 s = "[dx]";
3444 else
3445 s = "(%dx)";
3446 break;
3447 case ax_reg: case cx_reg: case dx_reg: case bx_reg:
3448 case sp_reg: case bp_reg: case si_reg: case di_reg:
3449 s = names16[code - ax_reg];
3450 break;
3451 case es_reg: case ss_reg: case cs_reg:
3452 case ds_reg: case fs_reg: case gs_reg:
3453 s = names_seg[code - es_reg];
3454 break;
3455 case al_reg: case ah_reg: case cl_reg: case ch_reg:
3456 case dl_reg: case dh_reg: case bl_reg: case bh_reg:
3457 USED_REX (0);
3458 if (rex)
3459 s = names8rex[code - al_reg];
3460 else
3461 s = names8[code - al_reg];
3462 break;
3463 case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
3464 case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
3465 USED_REX (REX_MODE64);
3466 if (rex & REX_MODE64)
3467 s = names64[code - eAX_reg];
3468 else if (sizeflag & DFLAG)
3469 s = names32[code - eAX_reg];
3470 else
3471 s = names16[code - eAX_reg];
3472 used_prefixes |= (prefixes & PREFIX_DATA);
3473 break;
3474 default:
3475 s = INTERNAL_DISASSEMBLER_ERROR;
3476 break;
3477 }
3478 oappend (s);
3479}
3480
3481static void
3482OP_I (bytemode, sizeflag)
3483 int bytemode;
3484 int sizeflag;
3485{
3486 bfd_signed_vma op;
3487 bfd_signed_vma mask = -1;
3488
3489 switch (bytemode)
bellarddc990652003-03-19 00:00:28 +00003490 {
3491 case b_mode:
3492 FETCH_DATA (the_info, codep + 1);
bellardbc51c5c2004-03-17 23:46:04 +00003493 op = *codep++;
3494 mask = 0xff;
bellarddc990652003-03-19 00:00:28 +00003495 break;
bellardbc51c5c2004-03-17 23:46:04 +00003496 case q_mode:
3497 if (mode_64bit)
3498 {
3499 op = get32s ();
3500 break;
3501 }
3502 /* Fall through. */
bellarddc990652003-03-19 00:00:28 +00003503 case v_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003504 USED_REX (REX_MODE64);
3505 if (rex & REX_MODE64)
3506 op = get32s ();
3507 else if (sizeflag & DFLAG)
3508 {
3509 op = get32 ();
3510 mask = 0xffffffff;
3511 }
bellarddc990652003-03-19 00:00:28 +00003512 else
bellardbc51c5c2004-03-17 23:46:04 +00003513 {
3514 op = get16 ();
3515 mask = 0xfffff;
3516 }
3517 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00003518 break;
3519 case w_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003520 mask = 0xfffff;
bellarddc990652003-03-19 00:00:28 +00003521 op = get16 ();
3522 break;
3523 default:
bellardbc51c5c2004-03-17 23:46:04 +00003524 oappend (INTERNAL_DISASSEMBLER_ERROR);
3525 return;
bellarddc990652003-03-19 00:00:28 +00003526 }
bellardbc51c5c2004-03-17 23:46:04 +00003527
3528 op &= mask;
3529 scratchbuf[0] = '$';
3530 print_operand_value (scratchbuf + 1, 1, op);
3531 oappend (scratchbuf + intel_syntax);
3532 scratchbuf[0] = '\0';
bellarddc990652003-03-19 00:00:28 +00003533}
3534
bellardbc51c5c2004-03-17 23:46:04 +00003535static void
3536OP_I64 (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003537 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003538 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003539{
bellardbc51c5c2004-03-17 23:46:04 +00003540 bfd_signed_vma op;
3541 bfd_signed_vma mask = -1;
3542
3543 if (!mode_64bit)
3544 {
3545 OP_I (bytemode, sizeflag);
3546 return;
3547 }
3548
3549 switch (bytemode)
3550 {
3551 case b_mode:
3552 FETCH_DATA (the_info, codep + 1);
3553 op = *codep++;
3554 mask = 0xff;
3555 break;
3556 case v_mode:
3557 USED_REX (REX_MODE64);
3558 if (rex & REX_MODE64)
3559 op = get64 ();
3560 else if (sizeflag & DFLAG)
3561 {
3562 op = get32 ();
3563 mask = 0xffffffff;
3564 }
3565 else
3566 {
3567 op = get16 ();
3568 mask = 0xfffff;
3569 }
3570 used_prefixes |= (prefixes & PREFIX_DATA);
3571 break;
3572 case w_mode:
3573 mask = 0xfffff;
3574 op = get16 ();
3575 break;
3576 default:
3577 oappend (INTERNAL_DISASSEMBLER_ERROR);
3578 return;
3579 }
3580
3581 op &= mask;
3582 scratchbuf[0] = '$';
3583 print_operand_value (scratchbuf + 1, 1, op);
3584 oappend (scratchbuf + intel_syntax);
3585 scratchbuf[0] = '\0';
3586}
3587
3588static void
3589OP_sI (bytemode, sizeflag)
3590 int bytemode;
3591 int sizeflag;
3592{
3593 bfd_signed_vma op;
3594 bfd_signed_vma mask = -1;
3595
3596 switch (bytemode)
bellarddc990652003-03-19 00:00:28 +00003597 {
3598 case b_mode:
3599 FETCH_DATA (the_info, codep + 1);
3600 op = *codep++;
3601 if ((op & 0x80) != 0)
3602 op -= 0x100;
bellardbc51c5c2004-03-17 23:46:04 +00003603 mask = 0xffffffff;
bellarddc990652003-03-19 00:00:28 +00003604 break;
3605 case v_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003606 USED_REX (REX_MODE64);
3607 if (rex & REX_MODE64)
3608 op = get32s ();
3609 else if (sizeflag & DFLAG)
3610 {
3611 op = get32s ();
3612 mask = 0xffffffff;
3613 }
bellarddc990652003-03-19 00:00:28 +00003614 else
3615 {
bellardbc51c5c2004-03-17 23:46:04 +00003616 mask = 0xffffffff;
3617 op = get16 ();
bellarddc990652003-03-19 00:00:28 +00003618 if ((op & 0x8000) != 0)
3619 op -= 0x10000;
3620 }
bellardbc51c5c2004-03-17 23:46:04 +00003621 used_prefixes |= (prefixes & PREFIX_DATA);
bellarddc990652003-03-19 00:00:28 +00003622 break;
3623 case w_mode:
3624 op = get16 ();
bellardbc51c5c2004-03-17 23:46:04 +00003625 mask = 0xffffffff;
bellarddc990652003-03-19 00:00:28 +00003626 if ((op & 0x8000) != 0)
3627 op -= 0x10000;
3628 break;
3629 default:
bellardbc51c5c2004-03-17 23:46:04 +00003630 oappend (INTERNAL_DISASSEMBLER_ERROR);
3631 return;
bellarddc990652003-03-19 00:00:28 +00003632 }
bellardbc51c5c2004-03-17 23:46:04 +00003633
3634 scratchbuf[0] = '$';
3635 print_operand_value (scratchbuf + 1, 1, op);
3636 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00003637}
3638
bellardbc51c5c2004-03-17 23:46:04 +00003639static void
3640OP_J (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003641 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003642 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003643{
bellardbc51c5c2004-03-17 23:46:04 +00003644 bfd_vma disp;
3645 bfd_vma mask = -1;
3646
3647 switch (bytemode)
bellarddc990652003-03-19 00:00:28 +00003648 {
3649 case b_mode:
3650 FETCH_DATA (the_info, codep + 1);
3651 disp = *codep++;
3652 if ((disp & 0x80) != 0)
3653 disp -= 0x100;
3654 break;
3655 case v_mode:
bellardbc51c5c2004-03-17 23:46:04 +00003656 if (sizeflag & DFLAG)
3657 disp = get32s ();
bellarddc990652003-03-19 00:00:28 +00003658 else
3659 {
3660 disp = get16 ();
bellardbc51c5c2004-03-17 23:46:04 +00003661 /* For some reason, a data16 prefix on a jump instruction
bellarddc990652003-03-19 00:00:28 +00003662 means that the pc is masked to 16 bits after the
3663 displacement is added! */
3664 mask = 0xffff;
3665 }
3666 break;
3667 default:
bellardbc51c5c2004-03-17 23:46:04 +00003668 oappend (INTERNAL_DISASSEMBLER_ERROR);
3669 return;
bellarddc990652003-03-19 00:00:28 +00003670 }
3671 disp = (start_pc + codep - start_codep + disp) & mask;
bellardbc51c5c2004-03-17 23:46:04 +00003672 set_op (disp, 0);
3673 print_operand_value (scratchbuf, 1, disp);
bellarddc990652003-03-19 00:00:28 +00003674 oappend (scratchbuf);
bellarddc990652003-03-19 00:00:28 +00003675}
3676
bellardbc51c5c2004-03-17 23:46:04 +00003677static void
3678OP_SEG (dummy, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003679 int dummy;
bellardbc51c5c2004-03-17 23:46:04 +00003680 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003681{
bellardbc51c5c2004-03-17 23:46:04 +00003682 oappend (names_seg[reg]);
bellarddc990652003-03-19 00:00:28 +00003683}
3684
bellardbc51c5c2004-03-17 23:46:04 +00003685static void
3686OP_DIR (dummy, sizeflag)
3687 int dummy;
3688 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003689{
3690 int seg, offset;
bellardbc51c5c2004-03-17 23:46:04 +00003691
3692 if (sizeflag & DFLAG)
bellarddc990652003-03-19 00:00:28 +00003693 {
bellardbc51c5c2004-03-17 23:46:04 +00003694 offset = get32 ();
3695 seg = get16 ();
bellarddc990652003-03-19 00:00:28 +00003696 }
bellardbc51c5c2004-03-17 23:46:04 +00003697 else
3698 {
3699 offset = get16 ();
3700 seg = get16 ();
3701 }
3702 used_prefixes |= (prefixes & PREFIX_DATA);
3703 if (intel_syntax)
3704 sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
3705 else
3706 sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
3707 oappend (scratchbuf);
bellarddc990652003-03-19 00:00:28 +00003708}
3709
bellardbc51c5c2004-03-17 23:46:04 +00003710static void
3711OP_OFF (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003712 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003713 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003714{
bellardbc51c5c2004-03-17 23:46:04 +00003715 bfd_vma off;
bellarddc990652003-03-19 00:00:28 +00003716
bellardbc51c5c2004-03-17 23:46:04 +00003717 append_seg ();
bellarddc990652003-03-19 00:00:28 +00003718
bellardbc51c5c2004-03-17 23:46:04 +00003719 if ((sizeflag & AFLAG) || mode_64bit)
bellarddc990652003-03-19 00:00:28 +00003720 off = get32 ();
3721 else
3722 off = get16 ();
bellardbc51c5c2004-03-17 23:46:04 +00003723
3724 if (intel_syntax)
3725 {
3726 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
3727 | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
3728 {
3729 oappend (names_seg[ds_reg - es_reg]);
3730 oappend (":");
3731 }
3732 }
3733 print_operand_value (scratchbuf, 1, off);
bellarddc990652003-03-19 00:00:28 +00003734 oappend (scratchbuf);
bellarddc990652003-03-19 00:00:28 +00003735}
3736
bellardbc51c5c2004-03-17 23:46:04 +00003737static void
3738OP_OFF64 (bytemode, sizeflag)
3739 int bytemode;
3740 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003741{
bellardbc51c5c2004-03-17 23:46:04 +00003742 bfd_vma off;
3743
3744 if (!mode_64bit)
3745 {
3746 OP_OFF (bytemode, sizeflag);
3747 return;
3748 }
3749
3750 append_seg ();
3751
3752 off = get64 ();
3753
3754 if (intel_syntax)
3755 {
3756 if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
3757 | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
3758 {
3759 oappend (names_seg[ds_reg - es_reg]);
3760 oappend (":");
3761 }
3762 }
3763 print_operand_value (scratchbuf, 1, off);
3764 oappend (scratchbuf);
bellarddc990652003-03-19 00:00:28 +00003765}
3766
bellardbc51c5c2004-03-17 23:46:04 +00003767static void
3768ptr_reg (code, sizeflag)
3769 int code;
3770 int sizeflag;
3771{
3772 const char *s;
3773 if (intel_syntax)
3774 oappend ("[");
3775 else
3776 oappend ("(");
3777
3778 USED_REX (REX_MODE64);
3779 if (rex & REX_MODE64)
3780 {
3781 if (!(sizeflag & AFLAG))
3782 s = names32[code - eAX_reg];
3783 else
3784 s = names64[code - eAX_reg];
3785 }
3786 else if (sizeflag & AFLAG)
3787 s = names32[code - eAX_reg];
3788 else
3789 s = names16[code - eAX_reg];
3790 oappend (s);
3791 if (intel_syntax)
3792 oappend ("]");
3793 else
3794 oappend (")");
3795}
3796
3797static void
3798OP_ESreg (code, sizeflag)
3799 int code;
3800 int sizeflag;
3801{
3802 oappend ("%es:" + intel_syntax);
3803 ptr_reg (code, sizeflag);
3804}
3805
3806static void
3807OP_DSreg (code, sizeflag)
3808 int code;
3809 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003810{
3811 if ((prefixes
3812 & (PREFIX_CS
3813 | PREFIX_DS
3814 | PREFIX_SS
3815 | PREFIX_ES
3816 | PREFIX_FS
3817 | PREFIX_GS)) == 0)
3818 prefixes |= PREFIX_DS;
bellardbc51c5c2004-03-17 23:46:04 +00003819 append_seg ();
3820 ptr_reg (code, sizeflag);
bellarddc990652003-03-19 00:00:28 +00003821}
3822
bellardbc51c5c2004-03-17 23:46:04 +00003823static void
3824OP_C (dummy, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003825 int dummy;
bellardbc51c5c2004-03-17 23:46:04 +00003826 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003827{
bellardbc51c5c2004-03-17 23:46:04 +00003828 int add = 0;
3829 USED_REX (REX_EXTX);
3830 if (rex & REX_EXTX)
3831 add = 8;
3832 sprintf (scratchbuf, "%%cr%d", reg + add);
3833 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00003834}
3835
bellardbc51c5c2004-03-17 23:46:04 +00003836static void
3837OP_D (dummy, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003838 int dummy;
bellardbc51c5c2004-03-17 23:46:04 +00003839 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003840{
bellardbc51c5c2004-03-17 23:46:04 +00003841 int add = 0;
3842 USED_REX (REX_EXTX);
3843 if (rex & REX_EXTX)
3844 add = 8;
3845 if (intel_syntax)
3846 sprintf (scratchbuf, "db%d", reg + add);
3847 else
3848 sprintf (scratchbuf, "%%db%d", reg + add);
bellarddc990652003-03-19 00:00:28 +00003849 oappend (scratchbuf);
bellarddc990652003-03-19 00:00:28 +00003850}
3851
bellardbc51c5c2004-03-17 23:46:04 +00003852static void
3853OP_T (dummy, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003854 int dummy;
bellardbc51c5c2004-03-17 23:46:04 +00003855 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003856{
bellarddc990652003-03-19 00:00:28 +00003857 sprintf (scratchbuf, "%%tr%d", reg);
bellardbc51c5c2004-03-17 23:46:04 +00003858 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00003859}
3860
bellardbc51c5c2004-03-17 23:46:04 +00003861static void
3862OP_Rd (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003863 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003864 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003865{
bellardbc51c5c2004-03-17 23:46:04 +00003866 if (mod == 3)
3867 OP_E (bytemode, sizeflag);
3868 else
3869 BadOp ();
bellarddc990652003-03-19 00:00:28 +00003870}
3871
bellardbc51c5c2004-03-17 23:46:04 +00003872static void
3873OP_MMX (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003874 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003875 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003876{
bellardbc51c5c2004-03-17 23:46:04 +00003877 int add = 0;
3878 USED_REX (REX_EXTX);
3879 if (rex & REX_EXTX)
3880 add = 8;
3881 used_prefixes |= (prefixes & PREFIX_DATA);
3882 if (prefixes & PREFIX_DATA)
3883 sprintf (scratchbuf, "%%xmm%d", reg + add);
3884 else
3885 sprintf (scratchbuf, "%%mm%d", reg + add);
3886 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00003887}
3888
bellardbc51c5c2004-03-17 23:46:04 +00003889static void
3890OP_XMM (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003891 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003892 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003893{
bellardbc51c5c2004-03-17 23:46:04 +00003894 int add = 0;
3895 USED_REX (REX_EXTX);
3896 if (rex & REX_EXTX)
3897 add = 8;
3898 sprintf (scratchbuf, "%%xmm%d", reg + add);
3899 oappend (scratchbuf + intel_syntax);
3900}
3901
3902static void
3903OP_EM (bytemode, sizeflag)
3904 int bytemode;
3905 int sizeflag;
3906{
3907 int add = 0;
bellarddc990652003-03-19 00:00:28 +00003908 if (mod != 3)
bellardbc51c5c2004-03-17 23:46:04 +00003909 {
3910 OP_E (bytemode, sizeflag);
3911 return;
3912 }
3913 USED_REX (REX_EXTZ);
3914 if (rex & REX_EXTZ)
3915 add = 8;
bellarddc990652003-03-19 00:00:28 +00003916
bellardbc51c5c2004-03-17 23:46:04 +00003917 /* Skip mod/rm byte. */
3918 MODRM_CHECK;
bellarddc990652003-03-19 00:00:28 +00003919 codep++;
bellardbc51c5c2004-03-17 23:46:04 +00003920 used_prefixes |= (prefixes & PREFIX_DATA);
3921 if (prefixes & PREFIX_DATA)
3922 sprintf (scratchbuf, "%%xmm%d", rm + add);
3923 else
3924 sprintf (scratchbuf, "%%mm%d", rm + add);
3925 oappend (scratchbuf + intel_syntax);
bellarddc990652003-03-19 00:00:28 +00003926}
3927
bellardbc51c5c2004-03-17 23:46:04 +00003928static void
3929OP_EX (bytemode, sizeflag)
bellarddc990652003-03-19 00:00:28 +00003930 int bytemode;
bellardbc51c5c2004-03-17 23:46:04 +00003931 int sizeflag;
bellarddc990652003-03-19 00:00:28 +00003932{
bellardbc51c5c2004-03-17 23:46:04 +00003933 int add = 0;
3934 if (mod != 3)
3935 {
3936 OP_E (bytemode, sizeflag);
3937 return;
3938 }
3939 USED_REX (REX_EXTZ);
3940 if (rex & REX_EXTZ)
3941 add = 8;
3942
3943 /* Skip mod/rm byte. */
3944 MODRM_CHECK;
3945 codep++;
3946 sprintf (scratchbuf, "%%xmm%d", rm + add);
3947 oappend (scratchbuf + intel_syntax);
3948}
3949
3950static void
3951OP_MS (bytemode, sizeflag)
3952 int bytemode;
3953 int sizeflag;
3954{
3955 if (mod == 3)
3956 OP_EM (bytemode, sizeflag);
3957 else
3958 BadOp ();
3959}
3960
3961static void
3962OP_XS (bytemode, sizeflag)
3963 int bytemode;
3964 int sizeflag;
3965{
3966 if (mod == 3)
3967 OP_EX (bytemode, sizeflag);
3968 else
3969 BadOp ();
3970}
3971
3972static const char *Suffix3DNow[] = {
3973/* 00 */ NULL, NULL, NULL, NULL,
3974/* 04 */ NULL, NULL, NULL, NULL,
3975/* 08 */ NULL, NULL, NULL, NULL,
3976/* 0C */ "pi2fw", "pi2fd", NULL, NULL,
3977/* 10 */ NULL, NULL, NULL, NULL,
3978/* 14 */ NULL, NULL, NULL, NULL,
3979/* 18 */ NULL, NULL, NULL, NULL,
3980/* 1C */ "pf2iw", "pf2id", NULL, NULL,
3981/* 20 */ NULL, NULL, NULL, NULL,
3982/* 24 */ NULL, NULL, NULL, NULL,
3983/* 28 */ NULL, NULL, NULL, NULL,
3984/* 2C */ NULL, NULL, NULL, NULL,
3985/* 30 */ NULL, NULL, NULL, NULL,
3986/* 34 */ NULL, NULL, NULL, NULL,
3987/* 38 */ NULL, NULL, NULL, NULL,
3988/* 3C */ NULL, NULL, NULL, NULL,
3989/* 40 */ NULL, NULL, NULL, NULL,
3990/* 44 */ NULL, NULL, NULL, NULL,
3991/* 48 */ NULL, NULL, NULL, NULL,
3992/* 4C */ NULL, NULL, NULL, NULL,
3993/* 50 */ NULL, NULL, NULL, NULL,
3994/* 54 */ NULL, NULL, NULL, NULL,
3995/* 58 */ NULL, NULL, NULL, NULL,
3996/* 5C */ NULL, NULL, NULL, NULL,
3997/* 60 */ NULL, NULL, NULL, NULL,
3998/* 64 */ NULL, NULL, NULL, NULL,
3999/* 68 */ NULL, NULL, NULL, NULL,
4000/* 6C */ NULL, NULL, NULL, NULL,
4001/* 70 */ NULL, NULL, NULL, NULL,
4002/* 74 */ NULL, NULL, NULL, NULL,
4003/* 78 */ NULL, NULL, NULL, NULL,
4004/* 7C */ NULL, NULL, NULL, NULL,
4005/* 80 */ NULL, NULL, NULL, NULL,
4006/* 84 */ NULL, NULL, NULL, NULL,
4007/* 88 */ NULL, NULL, "pfnacc", NULL,
4008/* 8C */ NULL, NULL, "pfpnacc", NULL,
4009/* 90 */ "pfcmpge", NULL, NULL, NULL,
4010/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt",
4011/* 98 */ NULL, NULL, "pfsub", NULL,
4012/* 9C */ NULL, NULL, "pfadd", NULL,
4013/* A0 */ "pfcmpgt", NULL, NULL, NULL,
4014/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1",
4015/* A8 */ NULL, NULL, "pfsubr", NULL,
4016/* AC */ NULL, NULL, "pfacc", NULL,
4017/* B0 */ "pfcmpeq", NULL, NULL, NULL,
4018/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw",
4019/* B8 */ NULL, NULL, NULL, "pswapd",
4020/* BC */ NULL, NULL, NULL, "pavgusb",
4021/* C0 */ NULL, NULL, NULL, NULL,
4022/* C4 */ NULL, NULL, NULL, NULL,
4023/* C8 */ NULL, NULL, NULL, NULL,
4024/* CC */ NULL, NULL, NULL, NULL,
4025/* D0 */ NULL, NULL, NULL, NULL,
4026/* D4 */ NULL, NULL, NULL, NULL,
4027/* D8 */ NULL, NULL, NULL, NULL,
4028/* DC */ NULL, NULL, NULL, NULL,
4029/* E0 */ NULL, NULL, NULL, NULL,
4030/* E4 */ NULL, NULL, NULL, NULL,
4031/* E8 */ NULL, NULL, NULL, NULL,
4032/* EC */ NULL, NULL, NULL, NULL,
4033/* F0 */ NULL, NULL, NULL, NULL,
4034/* F4 */ NULL, NULL, NULL, NULL,
4035/* F8 */ NULL, NULL, NULL, NULL,
4036/* FC */ NULL, NULL, NULL, NULL,
4037};
4038
4039static void
4040OP_3DNowSuffix (bytemode, sizeflag)
4041 int bytemode;
4042 int sizeflag;
4043{
4044 const char *mnemonic;
4045
4046 FETCH_DATA (the_info, codep + 1);
4047 /* AMD 3DNow! instructions are specified by an opcode suffix in the
4048 place where an 8-bit immediate would normally go. ie. the last
4049 byte of the instruction. */
4050 obufp = obuf + strlen (obuf);
4051 mnemonic = Suffix3DNow[*codep++ & 0xff];
4052 if (mnemonic)
4053 oappend (mnemonic);
4054 else
4055 {
4056 /* Since a variable sized modrm/sib chunk is between the start
4057 of the opcode (0x0f0f) and the opcode suffix, we need to do
4058 all the modrm processing first, and don't know until now that
4059 we have a bad opcode. This necessitates some cleaning up. */
4060 op1out[0] = '\0';
4061 op2out[0] = '\0';
4062 BadOp ();
4063 }
4064}
4065
4066static const char *simd_cmp_op[] = {
4067 "eq",
4068 "lt",
4069 "le",
4070 "unord",
4071 "neq",
4072 "nlt",
4073 "nle",
4074 "ord"
4075};
4076
4077static void
4078OP_SIMD_Suffix (bytemode, sizeflag)
4079 int bytemode;
4080 int sizeflag;
4081{
4082 unsigned int cmp_type;
4083
4084 FETCH_DATA (the_info, codep + 1);
4085 obufp = obuf + strlen (obuf);
4086 cmp_type = *codep++ & 0xff;
4087 if (cmp_type < 8)
4088 {
4089 char suffix1 = 'p', suffix2 = 's';
4090 used_prefixes |= (prefixes & PREFIX_REPZ);
4091 if (prefixes & PREFIX_REPZ)
4092 suffix1 = 's';
4093 else
4094 {
4095 used_prefixes |= (prefixes & PREFIX_DATA);
4096 if (prefixes & PREFIX_DATA)
4097 suffix2 = 'd';
4098 else
4099 {
4100 used_prefixes |= (prefixes & PREFIX_REPNZ);
4101 if (prefixes & PREFIX_REPNZ)
4102 suffix1 = 's', suffix2 = 'd';
4103 }
4104 }
4105 sprintf (scratchbuf, "cmp%s%c%c",
4106 simd_cmp_op[cmp_type], suffix1, suffix2);
4107 used_prefixes |= (prefixes & PREFIX_REPZ);
4108 oappend (scratchbuf);
4109 }
4110 else
4111 {
4112 /* We have a bad extension byte. Clean up. */
4113 op1out[0] = '\0';
4114 op2out[0] = '\0';
4115 BadOp ();
4116 }
4117}
4118
4119static void
4120SIMD_Fixup (extrachar, sizeflag)
4121 int extrachar;
4122 int sizeflag;
4123{
4124 /* Change movlps/movhps to movhlps/movlhps for 2 register operand
4125 forms of these instructions. */
4126 if (mod == 3)
4127 {
4128 char *p = obuf + strlen (obuf);
4129 *(p + 1) = '\0';
4130 *p = *(p - 1);
4131 *(p - 1) = *(p - 2);
4132 *(p - 2) = *(p - 3);
4133 *(p - 3) = extrachar;
4134 }
4135}
4136
4137static void
4138BadOp (void)
4139{
4140 /* Throw away prefixes and 1st. opcode byte. */
4141 codep = insn_codep + 1;
4142 oappend ("(bad)");
bellarddc990652003-03-19 00:00:28 +00004143}