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