2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/kdbg/i386/i386-dis.c
5 * PURPOSE: No purpose listed.
7 * PROGRAMMERS: No programmer listed.
14 /* ReactOS compatibility stuff. */
17 typedef enum bfd_flavour
19 bfd_target_unknown_flavour
,
21 typedef enum bfd_architecture
25 typedef ULONG_PTR bfd_vma
;
26 typedef unsigned char bfd_byte
;
27 enum bfd_endian
{ BFD_ENDIAN_BIG
, BIG_ENDIAN_LITTLE
, BFD_ENDIAN_UNKNOWN
};
29 typedef LONG_PTR bfd_signed_vma
;
30 #define bfd_mach_x86_64_intel_syntax 0
31 #define bfd_mach_x86_64 1
32 #define bfd_mach_i386_i386_intel_syntax 2
33 #define bfd_mach_i386_i386 3
34 #define bfd_mach_i386_i8086 4
35 #define abort() DbgBreakPoint();
37 #define ATTRIBUTE_UNUSED
38 extern int sprintf(char *str
, const char *format
, ...);
39 #define sprintf_vma(BUF, VMA) sprintf(BUF, "%p", VMA)
42 struct disassemble_info
;
45 print_insn_i386 (bfd_vma pc
, struct disassemble_info
*info
);
48 KdbpPrintDisasm(void* Ignored
, const char* fmt
, ...)
51 static char buffer
[256];
55 ret
= vsprintf(buffer
, fmt
, ap
);
56 DbgPrint("%s", buffer
);
62 KdbpNopPrintDisasm(void* Ignored
, const char* fmt
, ...)
68 KdbpReadMemory(ULONG_PTR Addr
, unsigned char* Data
, unsigned int Length
,
69 struct disassemble_info
* Ignored
)
71 return KdbpSafeReadMemory(Data
, (void *)Addr
, Length
); /* 0 means no error */
75 KdbpMemoryError(int Status
, ULONG_PTR Addr
,
76 struct disassemble_info
* Ignored
)
81 KdbpPrintAddressInCode(ULONG_PTR Addr
, struct disassemble_info
* Ignored
)
83 if (!KdbSymPrintAddress((void*)Addr
))
85 DbgPrint("<%p>", Addr
);
90 KdbpNopPrintAddress(ULONG_PTR Addr
, struct disassemble_info
* Ignored
)
97 KdbpGetInstLength(IN ULONG_PTR Address
)
99 disassemble_info info
;
101 info
.fprintf_func
= KdbpNopPrintDisasm
;
103 info
.application_data
= NULL
;
104 info
.flavour
= bfd_target_unknown_flavour
;
105 info
.arch
= bfd_arch_i386
;
106 info
.mach
= bfd_mach_x86_64
;
109 info
.read_memory_func
= KdbpReadMemory
;
110 info
.memory_error_func
= KdbpMemoryError
;
111 info
.print_address_func
= KdbpNopPrintAddress
;
112 info
.symbol_at_address_func
= NULL
;
114 info
.buffer_vma
= info
.buffer_length
= 0;
115 info
.bytes_per_chunk
= 0;
116 info
.display_endian
= BIG_ENDIAN_LITTLE
;
117 info
.disassembler_options
= NULL
;
119 return(print_insn_i386(Address
, &info
));
123 KdbpDisassemble(IN ULONG_PTR Address
, IN ULONG IntelSyntax
)
125 disassemble_info info
;
127 info
.fprintf_func
= KdbpPrintDisasm
;
129 info
.application_data
= NULL
;
130 info
.flavour
= bfd_target_unknown_flavour
;
131 info
.arch
= bfd_arch_i386
;
132 info
.mach
= IntelSyntax
? bfd_mach_i386_i386_intel_syntax
: bfd_mach_i386_i386
;
135 info
.read_memory_func
= KdbpReadMemory
;
136 info
.memory_error_func
= KdbpMemoryError
;
137 info
.print_address_func
= KdbpPrintAddressInCode
;
138 info
.symbol_at_address_func
= NULL
;
140 info
.buffer_vma
= info
.buffer_length
= 0;
141 info
.bytes_per_chunk
= 0;
142 info
.display_endian
= BIG_ENDIAN_LITTLE
;
143 info
.disassembler_options
= NULL
;
145 return(print_insn_i386(Address
, &info
));
148 /* Print i386 instructions for GDB, the GNU debugger.
149 Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
151 Free Software Foundation, Inc.
153 This file is part of GDB.
155 This program is free software; you can redistribute it and/or modify
156 it under the terms of the GNU General Public License as published by
157 the Free Software Foundation; either version 2 of the License, or
158 (at your option) any later version.
160 This program is distributed in the hope that it will be useful,
161 but WITHOUT ANY WARRANTY; without even the implied warranty of
162 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163 GNU General Public License for more details.
165 You should have received a copy of the GNU General Public License along
166 with this program; if not, write to the Free Software Foundation, Inc.,
167 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
171 * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
173 * modified by John Hassey (hassey@dg-rtp.dg.com)
174 * x86-64 support added by Jan Hubicka (jh@suse.cz)
178 * The main tables describing the instructions is essentially a copy
179 * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
180 * Programmers Manual. Usually, there is a capital letter, followed
181 * by a small letter. The capital letter tell the addressing mode,
182 * and the small letter tells about the operand size. Refer to
183 * the Intel manual for details.
196 #ifndef UNIXWARE_COMPAT
197 /* Set non-zero for broken, compatible instructions. Set to zero for
198 non-broken opcodes. */
199 #define UNIXWARE_COMPAT 1
202 static int fetch_data
PARAMS ((struct disassemble_info
*, bfd_byte
*));
203 static void ckprefix
PARAMS ((void));
204 static const char *prefix_name
PARAMS ((int, int));
205 static int print_insn
PARAMS ((bfd_vma
, disassemble_info
*));
206 static void dofloat
PARAMS ((int));
207 static void OP_ST
PARAMS ((int, int));
208 static void OP_STi
PARAMS ((int, int));
209 static int putop
PARAMS ((const char *, int));
210 static void oappend
PARAMS ((const char *));
211 static void append_seg
PARAMS ((void));
212 static void OP_indirE
PARAMS ((int, int));
213 static void print_operand_value
PARAMS ((char *, int, bfd_vma
));
214 static void OP_E
PARAMS ((int, int));
215 static void OP_G
PARAMS ((int, int));
216 static bfd_vma get64
PARAMS ((void));
217 static bfd_signed_vma get32
PARAMS ((void));
218 static bfd_signed_vma get32s
PARAMS ((void));
219 static int get16
PARAMS ((void));
220 static void set_op
PARAMS ((bfd_vma
, int));
221 static void OP_REG
PARAMS ((int, int));
222 static void OP_IMREG
PARAMS ((int, int));
223 static void OP_I
PARAMS ((int, int));
224 static void OP_I64
PARAMS ((int, int));
225 static void OP_sI
PARAMS ((int, int));
226 static void OP_J
PARAMS ((int, int));
227 static void OP_SEG
PARAMS ((int, int));
228 static void OP_DIR
PARAMS ((int, int));
229 static void OP_OFF
PARAMS ((int, int));
230 static void OP_OFF64
PARAMS ((int, int));
231 static void ptr_reg
PARAMS ((int, int));
232 static void OP_ESreg
PARAMS ((int, int));
233 static void OP_DSreg
PARAMS ((int, int));
234 static void OP_C
PARAMS ((int, int));
235 static void OP_D
PARAMS ((int, int));
236 static void OP_T
PARAMS ((int, int));
237 static void OP_Rd
PARAMS ((int, int));
238 static void OP_MMX
PARAMS ((int, int));
239 static void OP_XMM
PARAMS ((int, int));
240 static void OP_EM
PARAMS ((int, int));
241 static void OP_EX
PARAMS ((int, int));
242 static void OP_MS
PARAMS ((int, int));
243 static void OP_XS
PARAMS ((int, int));
244 static void OP_3DNowSuffix
PARAMS ((int, int));
245 static void OP_SIMD_Suffix
PARAMS ((int, int));
246 static void SIMD_Fixup
PARAMS ((int, int));
247 static void BadOp
PARAMS ((void));
250 /* Points to first byte not fetched. */
251 bfd_byte
*max_fetched
;
252 bfd_byte the_buffer
[MAXLEN
];
258 /* The opcode for the fwait instruction, which we treat as a prefix
260 #define FWAIT_OPCODE (0x9b)
262 /* Set to 1 for 64bit mode disassembly. */
263 static int mode_64bit
= 1;
265 /* Flags for the prefixes for the current instruction. See below. */
268 /* REX prefix the current instruction. See below. */
270 /* Bits of REX we've already used. */
276 /* Mark parts used in the REX prefix. When we are testing for
277 empty prefix (for 8bit register REX extension), just mask it
278 out. Otherwise test for REX bit is excuse for existence of REX
279 only in case value is nonzero. */
280 #define USED_REX(value) \
283 rex_used |= (rex & value) ? (value) | 0x40 : 0; \
288 /* Flags for prefixes which we somehow handled when printing the
289 current instruction. */
290 static int used_prefixes
;
292 /* Flags stored in PREFIXES. */
293 #define PREFIX_REPZ 1
294 #define PREFIX_REPNZ 2
295 #define PREFIX_LOCK 4
297 #define PREFIX_SS 0x10
298 #define PREFIX_DS 0x20
299 #define PREFIX_ES 0x40
300 #define PREFIX_FS 0x80
301 #define PREFIX_GS 0x100
302 #define PREFIX_DATA 0x200
303 #define PREFIX_ADDR 0x400
304 #define PREFIX_FWAIT 0x800
306 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
307 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
309 #define FETCH_DATA(info, addr) \
310 ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
311 ? 1 : fetch_data ((info), (addr)))
314 fetch_data (info
, addr
)
315 struct disassemble_info
*info
;
319 struct dis_private
*priv
= (struct dis_private
*) info
->private_data
;
320 bfd_vma start
= priv
->insn_start
+ (priv
->max_fetched
- priv
->the_buffer
);
322 status
= (*info
->read_memory_func
) (start
,
324 addr
- priv
->max_fetched
,
328 /* If we did manage to read at least one byte, then
329 print_insn_i386 will do something sensible. Otherwise, print
330 an error. We do that here because this is where we know
332 if (priv
->max_fetched
== priv
->the_buffer
)
333 (*info
->memory_error_func
) (status
, start
, info
);
334 longjmp (priv
->bailout
, 1);
337 priv
->max_fetched
= addr
;
343 #define Eb OP_E, b_mode
344 #define Ev OP_E, v_mode
345 #define Ed OP_E, d_mode
346 #define indirEb OP_indirE, b_mode
347 #define indirEv OP_indirE, v_mode
348 #define Ew OP_E, w_mode
349 #define Ma OP_E, v_mode
350 #define M OP_E, 0 /* lea, lgdt, etc. */
351 #define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
352 #define Gb OP_G, b_mode
353 #define Gv OP_G, v_mode
354 #define Gd OP_G, d_mode
355 #define Gw OP_G, w_mode
356 #define Rd OP_Rd, d_mode
357 #define Rm OP_Rd, m_mode
358 #define Ib OP_I, b_mode
359 #define sIb OP_sI, b_mode /* sign extened byte */
360 #define Iv OP_I, v_mode
361 #define Iq OP_I, q_mode
362 #define Iv64 OP_I64, v_mode
363 #define Iw OP_I, w_mode
364 #define Jb OP_J, b_mode
365 #define Jv OP_J, v_mode
366 #define Cm OP_C, m_mode
367 #define Dm OP_D, m_mode
368 #define Td OP_T, d_mode
370 #define RMeAX OP_REG, eAX_reg
371 #define RMeBX OP_REG, eBX_reg
372 #define RMeCX OP_REG, eCX_reg
373 #define RMeDX OP_REG, eDX_reg
374 #define RMeSP OP_REG, eSP_reg
375 #define RMeBP OP_REG, eBP_reg
376 #define RMeSI OP_REG, eSI_reg
377 #define RMeDI OP_REG, eDI_reg
378 #define RMrAX OP_REG, rAX_reg
379 #define RMrBX OP_REG, rBX_reg
380 #define RMrCX OP_REG, rCX_reg
381 #define RMrDX OP_REG, rDX_reg
382 #define RMrSP OP_REG, rSP_reg
383 #define RMrBP OP_REG, rBP_reg
384 #define RMrSI OP_REG, rSI_reg
385 #define RMrDI OP_REG, rDI_reg
386 #define RMAL OP_REG, al_reg
387 #define RMAL OP_REG, al_reg
388 #define RMCL OP_REG, cl_reg
389 #define RMDL OP_REG, dl_reg
390 #define RMBL OP_REG, bl_reg
391 #define RMAH OP_REG, ah_reg
392 #define RMCH OP_REG, ch_reg
393 #define RMDH OP_REG, dh_reg
394 #define RMBH OP_REG, bh_reg
395 #define RMAX OP_REG, ax_reg
396 #define RMDX OP_REG, dx_reg
398 #define eAX OP_IMREG, eAX_reg
399 #define eBX OP_IMREG, eBX_reg
400 #define eCX OP_IMREG, eCX_reg
401 #define eDX OP_IMREG, eDX_reg
402 #define eSP OP_IMREG, eSP_reg
403 #define eBP OP_IMREG, eBP_reg
404 #define eSI OP_IMREG, eSI_reg
405 #define eDI OP_IMREG, eDI_reg
406 #define AL OP_IMREG, al_reg
407 #define AL OP_IMREG, al_reg
408 #define CL OP_IMREG, cl_reg
409 #define DL OP_IMREG, dl_reg
410 #define BL OP_IMREG, bl_reg
411 #define AH OP_IMREG, ah_reg
412 #define CH OP_IMREG, ch_reg
413 #define DH OP_IMREG, dh_reg
414 #define BH OP_IMREG, bh_reg
415 #define AX OP_IMREG, ax_reg
416 #define DX OP_IMREG, dx_reg
417 #define indirDX OP_IMREG, indir_dx_reg
419 #define Sw OP_SEG, w_mode
421 #define Ob OP_OFF, b_mode
422 #define Ob64 OP_OFF64, b_mode
423 #define Ov OP_OFF, v_mode
424 #define Ov64 OP_OFF64, v_mode
425 #define Xb OP_DSreg, eSI_reg
426 #define Xv OP_DSreg, eSI_reg
427 #define Yb OP_ESreg, eDI_reg
428 #define Yv OP_ESreg, eDI_reg
429 #define DSBX OP_DSreg, eBX_reg
431 #define es OP_REG, es_reg
432 #define ss OP_REG, ss_reg
433 #define cs OP_REG, cs_reg
434 #define ds OP_REG, ds_reg
435 #define fs OP_REG, fs_reg
436 #define gs OP_REG, gs_reg
440 #define EM OP_EM, v_mode
441 #define EX OP_EX, v_mode
442 #define MS OP_MS, v_mode
443 #define XS OP_XS, v_mode
445 #define OPSUF OP_3DNowSuffix, 0
446 #define OPSIMD OP_SIMD_Suffix, 0
448 #define cond_jump_flag NULL, cond_jump_mode
449 #define loop_jcxz_flag NULL, loop_jcxz_mode
451 /* bits in sizeflag */
452 #define SUFFIX_ALWAYS 4
456 #define b_mode 1 /* byte operand */
457 #define v_mode 2 /* operand size depends on prefixes */
458 #define w_mode 3 /* word operand */
459 #define d_mode 4 /* double word operand */
460 #define q_mode 5 /* quad word operand */
462 #define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */
463 #define cond_jump_mode 8
464 #define loop_jcxz_mode 9
509 #define indir_dx_reg 150
513 #define USE_PREFIX_USER_TABLE 3
514 #define X86_64_SPECIAL 4
516 #define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
518 #define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0
519 #define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0
520 #define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0
521 #define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0
522 #define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0
523 #define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0
524 #define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0
525 #define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0
526 #define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0
527 #define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0
528 #define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
529 #define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
530 #define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
531 #define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
532 #define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
533 #define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
534 #define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
535 #define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
536 #define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
537 #define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
538 #define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
539 #define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
540 #define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
542 #define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0
543 #define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0
544 #define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0
545 #define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0
546 #define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0
547 #define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0
548 #define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0
549 #define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0
550 #define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0
551 #define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0
552 #define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
553 #define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
554 #define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
555 #define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
556 #define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
557 #define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
558 #define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
559 #define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
560 #define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
561 #define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
562 #define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
563 #define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
564 #define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
565 #define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
566 #define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
567 #define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
568 #define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
570 #define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0
572 typedef void (*op_rtn
) PARAMS ((int bytemode
, int sizeflag
));
584 /* Upper case letters in the instruction names here are macros.
585 'A' => print 'b' if no register operands or suffix_always is true
586 'B' => print 'b' if suffix_always is true
587 'E' => print 'e' if 32-bit form of jcxz
588 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
589 'H' => print ",pt" or ",pn" branch hint
590 'L' => print 'l' if suffix_always is true
591 'N' => print 'n' if instruction has no wait "prefix"
592 'O' => print 'd', or 'o'
593 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
594 . or suffix_always is true. print 'q' if rex prefix is present.
595 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
597 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
598 'S' => print 'w', 'l' or 'q' if suffix_always is true
599 'T' => print 'q' in 64bit mode and behave as 'P' otherwise
600 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
601 'X' => print 's', 'd' depending on data16 prefix (for XMM)
602 'W' => print 'b' or 'w' ("w" or "de" in intel mode)
603 'Y' => 'q' if instruction has an REX 64bit overwrite prefix
605 Many of the above letters print nothing in Intel mode. See "putop"
608 Braces '{' and '}', and vertical bars '|', indicate alternative
609 mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
610 modes. In cases where there are only two alternatives, the X86_64
611 instruction is reserved, and "(bad)" is printed.
614 static const struct dis386 dis386
[] = {
616 { "addB", Eb
, Gb
, XX
},
617 { "addS", Ev
, Gv
, XX
},
618 { "addB", Gb
, Eb
, XX
},
619 { "addS", Gv
, Ev
, XX
},
620 { "addB", AL
, Ib
, XX
},
621 { "addS", eAX
, Iv
, XX
},
622 { "push{T|}", es
, XX
, XX
},
623 { "pop{T|}", es
, XX
, XX
},
625 { "orB", Eb
, Gb
, XX
},
626 { "orS", Ev
, Gv
, XX
},
627 { "orB", Gb
, Eb
, XX
},
628 { "orS", Gv
, Ev
, XX
},
629 { "orB", AL
, Ib
, XX
},
630 { "orS", eAX
, Iv
, XX
},
631 { "push{T|}", cs
, XX
, XX
},
632 { "(bad)", XX
, XX
, XX
}, /* 0x0f extended opcode escape */
634 { "adcB", Eb
, Gb
, XX
},
635 { "adcS", Ev
, Gv
, XX
},
636 { "adcB", Gb
, Eb
, XX
},
637 { "adcS", Gv
, Ev
, XX
},
638 { "adcB", AL
, Ib
, XX
},
639 { "adcS", eAX
, Iv
, XX
},
640 { "push{T|}", ss
, XX
, XX
},
641 { "popT|}", ss
, XX
, XX
},
643 { "sbbB", Eb
, Gb
, XX
},
644 { "sbbS", Ev
, Gv
, XX
},
645 { "sbbB", Gb
, Eb
, XX
},
646 { "sbbS", Gv
, Ev
, XX
},
647 { "sbbB", AL
, Ib
, XX
},
648 { "sbbS", eAX
, Iv
, XX
},
649 { "push{T|}", ds
, XX
, XX
},
650 { "pop{T|}", ds
, XX
, XX
},
652 { "andB", Eb
, Gb
, XX
},
653 { "andS", Ev
, Gv
, XX
},
654 { "andB", Gb
, Eb
, XX
},
655 { "andS", Gv
, Ev
, XX
},
656 { "andB", AL
, Ib
, XX
},
657 { "andS", eAX
, Iv
, XX
},
658 { "(bad)", XX
, XX
, XX
}, /* SEG ES prefix */
659 { "daa{|}", XX
, XX
, XX
},
661 { "subB", Eb
, Gb
, XX
},
662 { "subS", Ev
, Gv
, XX
},
663 { "subB", Gb
, Eb
, XX
},
664 { "subS", Gv
, Ev
, XX
},
665 { "subB", AL
, Ib
, XX
},
666 { "subS", eAX
, Iv
, XX
},
667 { "(bad)", XX
, XX
, XX
}, /* SEG CS prefix */
668 { "das{|}", XX
, XX
, XX
},
670 { "xorB", Eb
, Gb
, XX
},
671 { "xorS", Ev
, Gv
, XX
},
672 { "xorB", Gb
, Eb
, XX
},
673 { "xorS", Gv
, Ev
, XX
},
674 { "xorB", AL
, Ib
, XX
},
675 { "xorS", eAX
, Iv
, XX
},
676 { "(bad)", XX
, XX
, XX
}, /* SEG SS prefix */
677 { "aaa{|}", XX
, XX
, XX
},
679 { "cmpB", Eb
, Gb
, XX
},
680 { "cmpS", Ev
, Gv
, XX
},
681 { "cmpB", Gb
, Eb
, XX
},
682 { "cmpS", Gv
, Ev
, XX
},
683 { "cmpB", AL
, Ib
, XX
},
684 { "cmpS", eAX
, Iv
, XX
},
685 { "(bad)", XX
, XX
, XX
}, /* SEG DS prefix */
686 { "aas{|}", XX
, XX
, XX
},
688 { "inc{S|}", RMeAX
, XX
, XX
},
689 { "inc{S|}", RMeCX
, XX
, XX
},
690 { "inc{S|}", RMeDX
, XX
, XX
},
691 { "inc{S|}", RMeBX
, XX
, XX
},
692 { "inc{S|}", RMeSP
, XX
, XX
},
693 { "inc{S|}", RMeBP
, XX
, XX
},
694 { "inc{S|}", RMeSI
, XX
, XX
},
695 { "inc{S|}", RMeDI
, XX
, XX
},
697 { "dec{S|}", RMeAX
, XX
, XX
},
698 { "dec{S|}", RMeCX
, XX
, XX
},
699 { "dec{S|}", RMeDX
, XX
, XX
},
700 { "dec{S|}", RMeBX
, XX
, XX
},
701 { "dec{S|}", RMeSP
, XX
, XX
},
702 { "dec{S|}", RMeBP
, XX
, XX
},
703 { "dec{S|}", RMeSI
, XX
, XX
},
704 { "dec{S|}", RMeDI
, XX
, XX
},
706 { "pushS", RMrAX
, XX
, XX
},
707 { "pushS", RMrCX
, XX
, XX
},
708 { "pushS", RMrDX
, XX
, XX
},
709 { "pushS", RMrBX
, XX
, XX
},
710 { "pushS", RMrSP
, XX
, XX
},
711 { "pushS", RMrBP
, XX
, XX
},
712 { "pushS", RMrSI
, XX
, XX
},
713 { "pushS", RMrDI
, XX
, XX
},
715 { "popS", RMrAX
, XX
, XX
},
716 { "popS", RMrCX
, XX
, XX
},
717 { "popS", RMrDX
, XX
, XX
},
718 { "popS", RMrBX
, XX
, XX
},
719 { "popS", RMrSP
, XX
, XX
},
720 { "popS", RMrBP
, XX
, XX
},
721 { "popS", RMrSI
, XX
, XX
},
722 { "popS", RMrDI
, XX
, XX
},
724 { "pusha{P|}", XX
, XX
, XX
},
725 { "popa{P|}", XX
, XX
, XX
},
726 { "bound{S|}", Gv
, Ma
, XX
},
728 { "(bad)", XX
, XX
, XX
}, /* seg fs */
729 { "(bad)", XX
, XX
, XX
}, /* seg gs */
730 { "(bad)", XX
, XX
, XX
}, /* op size prefix */
731 { "(bad)", XX
, XX
, XX
}, /* adr size prefix */
733 { "pushT", Iq
, XX
, XX
},
734 { "imulS", Gv
, Ev
, Iv
},
735 { "pushT", sIb
, XX
, XX
},
736 { "imulS", Gv
, Ev
, sIb
},
737 { "ins{b||b|}", Yb
, indirDX
, XX
},
738 { "ins{R||R|}", Yv
, indirDX
, XX
},
739 { "outs{b||b|}", indirDX
, Xb
, XX
},
740 { "outs{R||R|}", indirDX
, Xv
, XX
},
742 { "joH", Jb
, XX
, cond_jump_flag
},
743 { "jnoH", Jb
, XX
, cond_jump_flag
},
744 { "jbH", Jb
, XX
, cond_jump_flag
},
745 { "jaeH", Jb
, XX
, cond_jump_flag
},
746 { "jeH", Jb
, XX
, cond_jump_flag
},
747 { "jneH", Jb
, XX
, cond_jump_flag
},
748 { "jbeH", Jb
, XX
, cond_jump_flag
},
749 { "jaH", Jb
, XX
, cond_jump_flag
},
751 { "jsH", Jb
, XX
, cond_jump_flag
},
752 { "jnsH", Jb
, XX
, cond_jump_flag
},
753 { "jpH", Jb
, XX
, cond_jump_flag
},
754 { "jnpH", Jb
, XX
, cond_jump_flag
},
755 { "jlH", Jb
, XX
, cond_jump_flag
},
756 { "jgeH", Jb
, XX
, cond_jump_flag
},
757 { "jleH", Jb
, XX
, cond_jump_flag
},
758 { "jgH", Jb
, XX
, cond_jump_flag
},
762 { "(bad)", XX
, XX
, XX
},
764 { "testB", Eb
, Gb
, XX
},
765 { "testS", Ev
, Gv
, XX
},
766 { "xchgB", Eb
, Gb
, XX
},
767 { "xchgS", Ev
, Gv
, XX
},
769 { "movB", Eb
, Gb
, XX
},
770 { "movS", Ev
, Gv
, XX
},
771 { "movB", Gb
, Eb
, XX
},
772 { "movS", Gv
, Ev
, XX
},
773 { "movQ", Ev
, Sw
, XX
},
774 { "leaS", Gv
, M
, XX
},
775 { "movQ", Sw
, Ev
, XX
},
776 { "popU", Ev
, XX
, XX
},
778 { "nop", XX
, XX
, XX
},
779 /* FIXME: NOP with REPz prefix is called PAUSE. */
780 { "xchgS", RMeCX
, eAX
, XX
},
781 { "xchgS", RMeDX
, eAX
, XX
},
782 { "xchgS", RMeBX
, eAX
, XX
},
783 { "xchgS", RMeSP
, eAX
, XX
},
784 { "xchgS", RMeBP
, eAX
, XX
},
785 { "xchgS", RMeSI
, eAX
, XX
},
786 { "xchgS", RMeDI
, eAX
, XX
},
788 { "cW{tR||tR|}", XX
, XX
, XX
},
789 { "cR{tO||tO|}", XX
, XX
, XX
},
790 { "lcall{T|}", Ap
, XX
, XX
},
791 { "(bad)", XX
, XX
, XX
}, /* fwait */
792 { "pushfT", XX
, XX
, XX
},
793 { "popfT", XX
, XX
, XX
},
794 { "sahf{|}", XX
, XX
, XX
},
795 { "lahf{|}", XX
, XX
, XX
},
797 { "movB", AL
, Ob64
, XX
},
798 { "movS", eAX
, Ov64
, XX
},
799 { "movB", Ob64
, AL
, XX
},
800 { "movS", Ov64
, eAX
, XX
},
801 { "movs{b||b|}", Yb
, Xb
, XX
},
802 { "movs{R||R|}", Yv
, Xv
, XX
},
803 { "cmps{b||b|}", Xb
, Yb
, XX
},
804 { "cmps{R||R|}", Xv
, Yv
, XX
},
806 { "testB", AL
, Ib
, XX
},
807 { "testS", eAX
, Iv
, XX
},
808 { "stosB", Yb
, AL
, XX
},
809 { "stosS", Yv
, eAX
, XX
},
810 { "lodsB", AL
, Xb
, XX
},
811 { "lodsS", eAX
, Xv
, XX
},
812 { "scasB", AL
, Yb
, XX
},
813 { "scasS", eAX
, Yv
, XX
},
815 { "movB", RMAL
, Ib
, XX
},
816 { "movB", RMCL
, Ib
, XX
},
817 { "movB", RMDL
, Ib
, XX
},
818 { "movB", RMBL
, Ib
, XX
},
819 { "movB", RMAH
, Ib
, XX
},
820 { "movB", RMCH
, Ib
, XX
},
821 { "movB", RMDH
, Ib
, XX
},
822 { "movB", RMBH
, Ib
, XX
},
824 { "movS", RMeAX
, Iv64
, XX
},
825 { "movS", RMeCX
, Iv64
, XX
},
826 { "movS", RMeDX
, Iv64
, XX
},
827 { "movS", RMeBX
, Iv64
, XX
},
828 { "movS", RMeSP
, Iv64
, XX
},
829 { "movS", RMeBP
, Iv64
, XX
},
830 { "movS", RMeSI
, Iv64
, XX
},
831 { "movS", RMeDI
, Iv64
, XX
},
835 { "retT", Iw
, XX
, XX
},
836 { "retT", XX
, XX
, XX
},
837 { "les{S|}", Gv
, Mp
, XX
},
838 { "ldsS", Gv
, Mp
, XX
},
839 { "movA", Eb
, Ib
, XX
},
840 { "movQ", Ev
, Iv
, XX
},
842 { "enterT", Iw
, Ib
, XX
},
843 { "leaveT", XX
, XX
, XX
},
844 { "lretP", Iw
, XX
, XX
},
845 { "lretP", XX
, XX
, XX
},
846 { "int3", XX
, XX
, XX
},
847 { "int", Ib
, XX
, XX
},
848 { "into{|}", XX
, XX
, XX
},
849 { "iretP", XX
, XX
, XX
},
855 { "aam{|}", sIb
, XX
, XX
},
856 { "aad{|}", sIb
, XX
, XX
},
857 { "(bad)", XX
, XX
, XX
},
858 { "xlat", DSBX
, XX
, XX
},
869 { "loopneFH", Jb
, XX
, loop_jcxz_flag
},
870 { "loopeFH", Jb
, XX
, loop_jcxz_flag
},
871 { "loopFH", Jb
, XX
, loop_jcxz_flag
},
872 { "jEcxzH", Jb
, XX
, loop_jcxz_flag
},
873 { "inB", AL
, Ib
, XX
},
874 { "inS", eAX
, Ib
, XX
},
875 { "outB", Ib
, AL
, XX
},
876 { "outS", Ib
, eAX
, XX
},
878 { "callT", Jv
, XX
, XX
},
879 { "jmpT", Jv
, XX
, XX
},
880 { "ljmp{T|}", Ap
, XX
, XX
},
881 { "jmp", Jb
, XX
, XX
},
882 { "inB", AL
, indirDX
, XX
},
883 { "inS", eAX
, indirDX
, XX
},
884 { "outB", indirDX
, AL
, XX
},
885 { "outS", indirDX
, eAX
, XX
},
887 { "(bad)", XX
, XX
, XX
}, /* lock prefix */
888 { "(bad)", XX
, XX
, XX
},
889 { "(bad)", XX
, XX
, XX
}, /* repne */
890 { "(bad)", XX
, XX
, XX
}, /* repz */
891 { "hlt", XX
, XX
, XX
},
892 { "cmc", XX
, XX
, XX
},
896 { "clc", XX
, XX
, XX
},
897 { "stc", XX
, XX
, XX
},
898 { "cli", XX
, XX
, XX
},
899 { "sti", XX
, XX
, XX
},
900 { "cld", XX
, XX
, XX
},
901 { "std", XX
, XX
, XX
},
906 static const struct dis386 dis386_twobyte
[] = {
910 { "larS", Gv
, Ew
, XX
},
911 { "lslS", Gv
, Ew
, XX
},
912 { "(bad)", XX
, XX
, XX
},
913 { "syscall", XX
, XX
, XX
},
914 { "clts", XX
, XX
, XX
},
915 { "sysretP", XX
, XX
, XX
},
917 { "invd", XX
, XX
, XX
},
918 { "wbinvd", XX
, XX
, XX
},
919 { "(bad)", XX
, XX
, XX
},
920 { "ud2a", XX
, XX
, XX
},
921 { "(bad)", XX
, XX
, XX
},
923 { "femms", XX
, XX
, XX
},
924 { "", MX
, EM
, OPSUF
}, /* See OP_3DNowSuffix. */
928 { "movlpX", XM
, EX
, SIMD_Fixup
, 'h' }, /* really only 2 operands */
929 { "movlpX", EX
, XM
, SIMD_Fixup
, 'h' },
930 { "unpcklpX", XM
, EX
, XX
},
931 { "unpckhpX", XM
, EX
, XX
},
932 { "movhpX", XM
, EX
, SIMD_Fixup
, 'l' },
933 { "movhpX", EX
, XM
, SIMD_Fixup
, 'l' },
936 { "(bad)", XX
, XX
, XX
},
937 { "(bad)", XX
, XX
, XX
},
938 { "(bad)", XX
, XX
, XX
},
939 { "(bad)", XX
, XX
, XX
},
940 { "(bad)", XX
, XX
, XX
},
941 { "(bad)", XX
, XX
, XX
},
942 { "(bad)", XX
, XX
, XX
},
944 { "movL", Rm
, Cm
, XX
},
945 { "movL", Rm
, Dm
, XX
},
946 { "movL", Cm
, Rm
, XX
},
947 { "movL", Dm
, Rm
, XX
},
948 { "movL", Rd
, Td
, XX
},
949 { "(bad)", XX
, XX
, XX
},
950 { "movL", Td
, Rd
, XX
},
951 { "(bad)", XX
, XX
, XX
},
953 { "movapX", XM
, EX
, XX
},
954 { "movapX", EX
, XM
, XX
},
956 { "movntpX", Ev
, XM
, XX
},
959 { "ucomisX", XM
,EX
, XX
},
960 { "comisX", XM
,EX
, XX
},
962 { "wrmsr", XX
, XX
, XX
},
963 { "rdtsc", XX
, XX
, XX
},
964 { "rdmsr", XX
, XX
, XX
},
965 { "rdpmc", XX
, XX
, XX
},
966 { "sysenter", XX
, XX
, XX
},
967 { "sysexit", XX
, XX
, XX
},
968 { "(bad)", XX
, XX
, XX
},
969 { "(bad)", XX
, XX
, XX
},
971 { "(bad)", XX
, XX
, XX
},
972 { "(bad)", XX
, XX
, XX
},
973 { "(bad)", XX
, XX
, XX
},
974 { "(bad)", XX
, XX
, XX
},
975 { "(bad)", XX
, XX
, XX
},
976 { "(bad)", XX
, XX
, XX
},
977 { "(bad)", XX
, XX
, XX
},
978 { "(bad)", XX
, XX
, XX
},
980 { "cmovo", Gv
, Ev
, XX
},
981 { "cmovno", Gv
, Ev
, XX
},
982 { "cmovb", Gv
, Ev
, XX
},
983 { "cmovae", Gv
, Ev
, XX
},
984 { "cmove", Gv
, Ev
, XX
},
985 { "cmovne", Gv
, Ev
, XX
},
986 { "cmovbe", Gv
, Ev
, XX
},
987 { "cmova", Gv
, Ev
, XX
},
989 { "cmovs", Gv
, Ev
, XX
},
990 { "cmovns", Gv
, Ev
, XX
},
991 { "cmovp", Gv
, Ev
, XX
},
992 { "cmovnp", Gv
, Ev
, XX
},
993 { "cmovl", Gv
, Ev
, XX
},
994 { "cmovge", Gv
, Ev
, XX
},
995 { "cmovle", Gv
, Ev
, XX
},
996 { "cmovg", Gv
, Ev
, XX
},
998 { "movmskpX", Gd
, XS
, XX
},
1002 { "andpX", XM
, EX
, XX
},
1003 { "andnpX", XM
, EX
, XX
},
1004 { "orpX", XM
, EX
, XX
},
1005 { "xorpX", XM
, EX
, XX
},
1016 { "punpcklbw", MX
, EM
, XX
},
1017 { "punpcklwd", MX
, EM
, XX
},
1018 { "punpckldq", MX
, EM
, XX
},
1019 { "packsswb", MX
, EM
, XX
},
1020 { "pcmpgtb", MX
, EM
, XX
},
1021 { "pcmpgtw", MX
, EM
, XX
},
1022 { "pcmpgtd", MX
, EM
, XX
},
1023 { "packuswb", MX
, EM
, XX
},
1025 { "punpckhbw", MX
, EM
, XX
},
1026 { "punpckhwd", MX
, EM
, XX
},
1027 { "punpckhdq", MX
, EM
, XX
},
1028 { "packssdw", MX
, EM
, XX
},
1031 { "movd", MX
, Ed
, XX
},
1038 { "pcmpeqb", MX
, EM
, XX
},
1039 { "pcmpeqw", MX
, EM
, XX
},
1040 { "pcmpeqd", MX
, EM
, XX
},
1041 { "emms", XX
, XX
, XX
},
1043 { "(bad)", XX
, XX
, XX
},
1044 { "(bad)", XX
, XX
, XX
},
1045 { "(bad)", XX
, XX
, XX
},
1046 { "(bad)", XX
, XX
, XX
},
1047 { "(bad)", XX
, XX
, XX
},
1048 { "(bad)", XX
, XX
, XX
},
1052 { "joH", Jv
, XX
, cond_jump_flag
},
1053 { "jnoH", Jv
, XX
, cond_jump_flag
},
1054 { "jbH", Jv
, XX
, cond_jump_flag
},
1055 { "jaeH", Jv
, XX
, cond_jump_flag
},
1056 { "jeH", Jv
, XX
, cond_jump_flag
},
1057 { "jneH", Jv
, XX
, cond_jump_flag
},
1058 { "jbeH", Jv
, XX
, cond_jump_flag
},
1059 { "jaH", Jv
, XX
, cond_jump_flag
},
1061 { "jsH", Jv
, XX
, cond_jump_flag
},
1062 { "jnsH", Jv
, XX
, cond_jump_flag
},
1063 { "jpH", Jv
, XX
, cond_jump_flag
},
1064 { "jnpH", Jv
, XX
, cond_jump_flag
},
1065 { "jlH", Jv
, XX
, cond_jump_flag
},
1066 { "jgeH", Jv
, XX
, cond_jump_flag
},
1067 { "jleH", Jv
, XX
, cond_jump_flag
},
1068 { "jgH", Jv
, XX
, cond_jump_flag
},
1070 { "seto", Eb
, XX
, XX
},
1071 { "setno", Eb
, XX
, XX
},
1072 { "setb", Eb
, XX
, XX
},
1073 { "setae", Eb
, XX
, XX
},
1074 { "sete", Eb
, XX
, XX
},
1075 { "setne", Eb
, XX
, XX
},
1076 { "setbe", Eb
, XX
, XX
},
1077 { "seta", Eb
, XX
, XX
},
1079 { "sets", Eb
, XX
, XX
},
1080 { "setns", Eb
, XX
, XX
},
1081 { "setp", Eb
, XX
, XX
},
1082 { "setnp", Eb
, XX
, XX
},
1083 { "setl", Eb
, XX
, XX
},
1084 { "setge", Eb
, XX
, XX
},
1085 { "setle", Eb
, XX
, XX
},
1086 { "setg", Eb
, XX
, XX
},
1088 { "pushT", fs
, XX
, XX
},
1089 { "popT", fs
, XX
, XX
},
1090 { "cpuid", XX
, XX
, XX
},
1091 { "btS", Ev
, Gv
, XX
},
1092 { "shldS", Ev
, Gv
, Ib
},
1093 { "shldS", Ev
, Gv
, CL
},
1094 { "(bad)", XX
, XX
, XX
},
1095 { "(bad)", XX
, XX
, XX
},
1097 { "pushT", gs
, XX
, XX
},
1098 { "popT", gs
, XX
, XX
},
1099 { "rsm", XX
, XX
, XX
},
1100 { "btsS", Ev
, Gv
, XX
},
1101 { "shrdS", Ev
, Gv
, Ib
},
1102 { "shrdS", Ev
, Gv
, CL
},
1104 { "imulS", Gv
, Ev
, XX
},
1106 { "cmpxchgB", Eb
, Gb
, XX
},
1107 { "cmpxchgS", Ev
, Gv
, XX
},
1108 { "lssS", Gv
, Mp
, XX
},
1109 { "btrS", Ev
, Gv
, XX
},
1110 { "lfsS", Gv
, Mp
, XX
},
1111 { "lgsS", Gv
, Mp
, XX
},
1112 { "movz{bR|x|bR|x}", Gv
, Eb
, XX
},
1113 { "movz{wR|x|wR|x}", Gv
, Ew
, XX
}, /* yes, there really is movzww ! */
1115 { "(bad)", XX
, XX
, XX
},
1116 { "ud2b", XX
, XX
, XX
},
1118 { "btcS", Ev
, Gv
, XX
},
1119 { "bsfS", Gv
, Ev
, XX
},
1120 { "bsrS", Gv
, Ev
, XX
},
1121 { "movs{bR|x|bR|x}", Gv
, Eb
, XX
},
1122 { "movs{wR|x|wR|x}", Gv
, Ew
, XX
}, /* yes, there really is movsww ! */
1124 { "xaddB", Eb
, Gb
, XX
},
1125 { "xaddS", Ev
, Gv
, XX
},
1127 { "movntiS", Ev
, Gv
, XX
},
1128 { "pinsrw", MX
, Ed
, Ib
},
1129 { "pextrw", Gd
, MS
, Ib
},
1130 { "shufpX", XM
, EX
, Ib
},
1133 { "bswap", RMeAX
, XX
, XX
},
1134 { "bswap", RMeCX
, XX
, XX
},
1135 { "bswap", RMeDX
, XX
, XX
},
1136 { "bswap", RMeBX
, XX
, XX
},
1137 { "bswap", RMeSP
, XX
, XX
},
1138 { "bswap", RMeBP
, XX
, XX
},
1139 { "bswap", RMeSI
, XX
, XX
},
1140 { "bswap", RMeDI
, XX
, XX
},
1142 { "(bad)", XX
, XX
, XX
},
1143 { "psrlw", MX
, EM
, XX
},
1144 { "psrld", MX
, EM
, XX
},
1145 { "psrlq", MX
, EM
, XX
},
1146 { "paddq", MX
, EM
, XX
},
1147 { "pmullw", MX
, EM
, XX
},
1149 { "pmovmskb", Gd
, MS
, XX
},
1151 { "psubusb", MX
, EM
, XX
},
1152 { "psubusw", MX
, EM
, XX
},
1153 { "pminub", MX
, EM
, XX
},
1154 { "pand", MX
, EM
, XX
},
1155 { "paddusb", MX
, EM
, XX
},
1156 { "paddusw", MX
, EM
, XX
},
1157 { "pmaxub", MX
, EM
, XX
},
1158 { "pandn", MX
, EM
, XX
},
1160 { "pavgb", MX
, EM
, XX
},
1161 { "psraw", MX
, EM
, XX
},
1162 { "psrad", MX
, EM
, XX
},
1163 { "pavgw", MX
, EM
, XX
},
1164 { "pmulhuw", MX
, EM
, XX
},
1165 { "pmulhw", MX
, EM
, XX
},
1169 { "psubsb", MX
, EM
, XX
},
1170 { "psubsw", MX
, EM
, XX
},
1171 { "pminsw", MX
, EM
, XX
},
1172 { "por", MX
, EM
, XX
},
1173 { "paddsb", MX
, EM
, XX
},
1174 { "paddsw", MX
, EM
, XX
},
1175 { "pmaxsw", MX
, EM
, XX
},
1176 { "pxor", MX
, EM
, XX
},
1178 { "(bad)", XX
, XX
, XX
},
1179 { "psllw", MX
, EM
, XX
},
1180 { "pslld", MX
, EM
, XX
},
1181 { "psllq", MX
, EM
, XX
},
1182 { "pmuludq", MX
, EM
, XX
},
1183 { "pmaddwd", MX
, EM
, XX
},
1184 { "psadbw", MX
, EM
, XX
},
1187 { "psubb", MX
, EM
, XX
},
1188 { "psubw", MX
, EM
, XX
},
1189 { "psubd", MX
, EM
, XX
},
1190 { "psubq", MX
, EM
, XX
},
1191 { "paddb", MX
, EM
, XX
},
1192 { "paddw", MX
, EM
, XX
},
1193 { "paddd", MX
, EM
, XX
},
1194 { "(bad)", XX
, XX
, XX
}
1197 static const unsigned char onebyte_has_modrm
[256] = {
1198 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1199 /* ------------------------------- */
1200 /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
1201 /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
1202 /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
1203 /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
1204 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
1205 /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
1206 /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
1207 /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
1208 /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
1209 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
1210 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
1211 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
1212 /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
1213 /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
1214 /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
1215 /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
1216 /* ------------------------------- */
1217 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1220 static const unsigned char twobyte_has_modrm
[256] = {
1221 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1222 /* ------------------------------- */
1223 /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
1224 /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
1225 /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
1226 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1227 /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
1228 /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
1229 /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
1230 /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
1231 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1232 /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
1233 /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */
1234 /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
1235 /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
1236 /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
1237 /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
1238 /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
1239 /* ------------------------------- */
1240 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1243 static const unsigned char twobyte_uses_SSE_prefix
[256] = {
1244 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1245 /* ------------------------------- */
1246 /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
1247 /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
1248 /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
1249 /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1250 /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
1251 /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
1252 /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
1253 /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */
1254 /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1255 /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
1256 /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
1257 /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
1258 /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
1259 /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
1260 /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
1261 /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
1262 /* ------------------------------- */
1263 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1266 static char obuf
[100];
1268 static char scratchbuf
[100];
1269 static unsigned char *start_codep
;
1270 static unsigned char *insn_codep
;
1271 static unsigned char *codep
;
1272 static disassemble_info
*the_info
;
1276 static unsigned char need_modrm
;
1278 /* If we are accessing mod/rm/reg without need_modrm set, then the
1279 values are stale. Hitting this abort likely indicates that you
1280 need to update onebyte_has_modrm or twobyte_has_modrm. */
1281 #define MODRM_CHECK if (!need_modrm) abort ()
1283 static const char **names64
;
1284 static const char **names32
;
1285 static const char **names16
;
1286 static const char **names8
;
1287 static const char **names8rex
;
1288 static const char **names_seg
;
1289 static const char **index16
;
1291 static const char *intel_names64
[] = {
1292 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1293 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1295 static const char *intel_names32
[] = {
1296 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
1297 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
1299 static const char *intel_names16
[] = {
1300 "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
1301 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
1303 static const char *intel_names8
[] = {
1304 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
1306 static const char *intel_names8rex
[] = {
1307 "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1308 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
1310 static const char *intel_names_seg
[] = {
1311 "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
1313 static const char *intel_index16
[] = {
1314 "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
1317 static const char *att_names64
[] = {
1318 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1319 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
1321 static const char *att_names32
[] = {
1322 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
1323 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
1325 static const char *att_names16
[] = {
1326 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
1327 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
1329 static const char *att_names8
[] = {
1330 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
1332 static const char *att_names8rex
[] = {
1333 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
1334 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
1336 static const char *att_names_seg
[] = {
1337 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
1339 static const char *att_index16
[] = {
1340 "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
1343 static const struct dis386 grps
[][8] = {
1346 { "addA", Eb
, Ib
, XX
},
1347 { "orA", Eb
, Ib
, XX
},
1348 { "adcA", Eb
, Ib
, XX
},
1349 { "sbbA", Eb
, Ib
, XX
},
1350 { "andA", Eb
, Ib
, XX
},
1351 { "subA", Eb
, Ib
, XX
},
1352 { "xorA", Eb
, Ib
, XX
},
1353 { "cmpA", Eb
, Ib
, XX
}
1357 { "addQ", Ev
, Iv
, XX
},
1358 { "orQ", Ev
, Iv
, XX
},
1359 { "adcQ", Ev
, Iv
, XX
},
1360 { "sbbQ", Ev
, Iv
, XX
},
1361 { "andQ", Ev
, Iv
, XX
},
1362 { "subQ", Ev
, Iv
, XX
},
1363 { "xorQ", Ev
, Iv
, XX
},
1364 { "cmpQ", Ev
, Iv
, XX
}
1368 { "addQ", Ev
, sIb
, XX
},
1369 { "orQ", Ev
, sIb
, XX
},
1370 { "adcQ", Ev
, sIb
, XX
},
1371 { "sbbQ", Ev
, sIb
, XX
},
1372 { "andQ", Ev
, sIb
, XX
},
1373 { "subQ", Ev
, sIb
, XX
},
1374 { "xorQ", Ev
, sIb
, XX
},
1375 { "cmpQ", Ev
, sIb
, XX
}
1379 { "rolA", Eb
, Ib
, XX
},
1380 { "rorA", Eb
, Ib
, XX
},
1381 { "rclA", Eb
, Ib
, XX
},
1382 { "rcrA", Eb
, Ib
, XX
},
1383 { "shlA", Eb
, Ib
, XX
},
1384 { "shrA", Eb
, Ib
, XX
},
1385 { "(bad)", XX
, XX
, XX
},
1386 { "sarA", Eb
, Ib
, XX
},
1390 { "rolQ", Ev
, Ib
, XX
},
1391 { "rorQ", Ev
, Ib
, XX
},
1392 { "rclQ", Ev
, Ib
, XX
},
1393 { "rcrQ", Ev
, Ib
, XX
},
1394 { "shlQ", Ev
, Ib
, XX
},
1395 { "shrQ", Ev
, Ib
, XX
},
1396 { "(bad)", XX
, XX
, XX
},
1397 { "sarQ", Ev
, Ib
, XX
},
1401 { "rolA", Eb
, XX
, XX
},
1402 { "rorA", Eb
, XX
, XX
},
1403 { "rclA", Eb
, XX
, XX
},
1404 { "rcrA", Eb
, XX
, XX
},
1405 { "shlA", Eb
, XX
, XX
},
1406 { "shrA", Eb
, XX
, XX
},
1407 { "(bad)", XX
, XX
, XX
},
1408 { "sarA", Eb
, XX
, XX
},
1412 { "rolQ", Ev
, XX
, XX
},
1413 { "rorQ", Ev
, XX
, XX
},
1414 { "rclQ", Ev
, XX
, XX
},
1415 { "rcrQ", Ev
, XX
, XX
},
1416 { "shlQ", Ev
, XX
, XX
},
1417 { "shrQ", Ev
, XX
, XX
},
1418 { "(bad)", XX
, XX
, XX
},
1419 { "sarQ", Ev
, XX
, XX
},
1423 { "rolA", Eb
, CL
, XX
},
1424 { "rorA", Eb
, CL
, XX
},
1425 { "rclA", Eb
, CL
, XX
},
1426 { "rcrA", Eb
, CL
, XX
},
1427 { "shlA", Eb
, CL
, XX
},
1428 { "shrA", Eb
, CL
, XX
},
1429 { "(bad)", XX
, XX
, XX
},
1430 { "sarA", Eb
, CL
, XX
},
1434 { "rolQ", Ev
, CL
, XX
},
1435 { "rorQ", Ev
, CL
, XX
},
1436 { "rclQ", Ev
, CL
, XX
},
1437 { "rcrQ", Ev
, CL
, XX
},
1438 { "shlQ", Ev
, CL
, XX
},
1439 { "shrQ", Ev
, CL
, XX
},
1440 { "(bad)", XX
, XX
, XX
},
1441 { "sarQ", Ev
, CL
, XX
}
1445 { "testA", Eb
, Ib
, XX
},
1446 { "(bad)", Eb
, XX
, XX
},
1447 { "notA", Eb
, XX
, XX
},
1448 { "negA", Eb
, XX
, XX
},
1449 { "mulA", Eb
, XX
, XX
}, /* Don't print the implicit %al register, */
1450 { "imulA", Eb
, XX
, XX
}, /* to distinguish these opcodes from other */
1451 { "divA", Eb
, XX
, XX
}, /* mul/imul opcodes. Do the same for div */
1452 { "idivA", Eb
, XX
, XX
} /* and idiv for consistency. */
1456 { "testQ", Ev
, Iv
, XX
},
1457 { "(bad)", XX
, XX
, XX
},
1458 { "notQ", Ev
, XX
, XX
},
1459 { "negQ", Ev
, XX
, XX
},
1460 { "mulQ", Ev
, XX
, XX
}, /* Don't print the implicit register. */
1461 { "imulQ", Ev
, XX
, XX
},
1462 { "divQ", Ev
, XX
, XX
},
1463 { "idivQ", Ev
, XX
, XX
},
1467 { "incA", Eb
, XX
, XX
},
1468 { "decA", Eb
, XX
, XX
},
1469 { "(bad)", XX
, XX
, XX
},
1470 { "(bad)", XX
, XX
, XX
},
1471 { "(bad)", XX
, XX
, XX
},
1472 { "(bad)", XX
, XX
, XX
},
1473 { "(bad)", XX
, XX
, XX
},
1474 { "(bad)", XX
, XX
, XX
},
1478 { "incQ", Ev
, XX
, XX
},
1479 { "decQ", Ev
, XX
, XX
},
1480 { "callT", indirEv
, XX
, XX
},
1481 { "lcallT", indirEv
, XX
, XX
},
1482 { "jmpT", indirEv
, XX
, XX
},
1483 { "ljmpT", indirEv
, XX
, XX
},
1484 { "pushU", Ev
, XX
, XX
},
1485 { "(bad)", XX
, XX
, XX
},
1489 { "sldtQ", Ev
, XX
, XX
},
1490 { "strQ", Ev
, XX
, XX
},
1491 { "lldt", Ew
, XX
, XX
},
1492 { "ltr", Ew
, XX
, XX
},
1493 { "verr", Ew
, XX
, XX
},
1494 { "verw", Ew
, XX
, XX
},
1495 { "(bad)", XX
, XX
, XX
},
1496 { "(bad)", XX
, XX
, XX
}
1500 { "sgdtQ", M
, XX
, XX
},
1501 { "sidtQ", M
, XX
, XX
},
1502 { "lgdtQ", M
, XX
, XX
},
1503 { "lidtQ", M
, XX
, XX
},
1504 { "smswQ", Ev
, XX
, XX
},
1505 { "(bad)", XX
, XX
, XX
},
1506 { "lmsw", Ew
, XX
, XX
},
1507 { "invlpg", Ew
, XX
, XX
},
1511 { "(bad)", XX
, XX
, XX
},
1512 { "(bad)", XX
, XX
, XX
},
1513 { "(bad)", XX
, XX
, XX
},
1514 { "(bad)", XX
, XX
, XX
},
1515 { "btQ", Ev
, Ib
, XX
},
1516 { "btsQ", Ev
, Ib
, XX
},
1517 { "btrQ", Ev
, Ib
, XX
},
1518 { "btcQ", Ev
, Ib
, XX
},
1522 { "(bad)", XX
, XX
, XX
},
1523 { "cmpxchg8b", Ev
, XX
, XX
},
1524 { "(bad)", XX
, XX
, XX
},
1525 { "(bad)", XX
, XX
, XX
},
1526 { "(bad)", XX
, XX
, XX
},
1527 { "(bad)", XX
, XX
, XX
},
1528 { "(bad)", XX
, XX
, XX
},
1529 { "(bad)", XX
, XX
, XX
},
1533 { "(bad)", XX
, XX
, XX
},
1534 { "(bad)", XX
, XX
, XX
},
1535 { "psrlw", MS
, Ib
, XX
},
1536 { "(bad)", XX
, XX
, XX
},
1537 { "psraw", MS
, Ib
, XX
},
1538 { "(bad)", XX
, XX
, XX
},
1539 { "psllw", MS
, Ib
, XX
},
1540 { "(bad)", XX
, XX
, XX
},
1544 { "(bad)", XX
, XX
, XX
},
1545 { "(bad)", XX
, XX
, XX
},
1546 { "psrld", MS
, Ib
, XX
},
1547 { "(bad)", XX
, XX
, XX
},
1548 { "psrad", MS
, Ib
, XX
},
1549 { "(bad)", XX
, XX
, XX
},
1550 { "pslld", MS
, Ib
, XX
},
1551 { "(bad)", XX
, XX
, XX
},
1555 { "(bad)", XX
, XX
, XX
},
1556 { "(bad)", XX
, XX
, XX
},
1557 { "psrlq", MS
, Ib
, XX
},
1558 { "psrldq", MS
, Ib
, XX
},
1559 { "(bad)", XX
, XX
, XX
},
1560 { "(bad)", XX
, XX
, XX
},
1561 { "psllq", MS
, Ib
, XX
},
1562 { "pslldq", MS
, Ib
, XX
},
1566 { "fxsave", Ev
, XX
, XX
},
1567 { "fxrstor", Ev
, XX
, XX
},
1568 { "ldmxcsr", Ev
, XX
, XX
},
1569 { "stmxcsr", Ev
, XX
, XX
},
1570 { "(bad)", XX
, XX
, XX
},
1571 { "lfence", None
, XX
, XX
},
1572 { "mfence", None
, XX
, XX
},
1573 { "sfence", None
, XX
, XX
},
1574 /* FIXME: the sfence with memory operand is clflush! */
1578 { "prefetchnta", Ev
, XX
, XX
},
1579 { "prefetcht0", Ev
, XX
, XX
},
1580 { "prefetcht1", Ev
, XX
, XX
},
1581 { "prefetcht2", Ev
, XX
, XX
},
1582 { "(bad)", XX
, XX
, XX
},
1583 { "(bad)", XX
, XX
, XX
},
1584 { "(bad)", XX
, XX
, XX
},
1585 { "(bad)", XX
, XX
, XX
},
1589 { "prefetch", Eb
, XX
, XX
},
1590 { "prefetchw", Eb
, XX
, XX
},
1591 { "(bad)", XX
, XX
, XX
},
1592 { "(bad)", XX
, XX
, XX
},
1593 { "(bad)", XX
, XX
, XX
},
1594 { "(bad)", XX
, XX
, XX
},
1595 { "(bad)", XX
, XX
, XX
},
1596 { "(bad)", XX
, XX
, XX
},
1600 static const struct dis386 prefix_user_table
[][4] = {
1603 { "addps", XM
, EX
, XX
},
1604 { "addss", XM
, EX
, XX
},
1605 { "addpd", XM
, EX
, XX
},
1606 { "addsd", XM
, EX
, XX
},
1610 { "", XM
, EX
, OPSIMD
}, /* See OP_SIMD_SUFFIX. */
1611 { "", XM
, EX
, OPSIMD
},
1612 { "", XM
, EX
, OPSIMD
},
1613 { "", XM
, EX
, OPSIMD
},
1617 { "cvtpi2ps", XM
, EM
, XX
},
1618 { "cvtsi2ssY", XM
, Ev
, XX
},
1619 { "cvtpi2pd", XM
, EM
, XX
},
1620 { "cvtsi2sdY", XM
, Ev
, XX
},
1624 { "cvtps2pi", MX
, EX
, XX
},
1625 { "cvtss2siY", Gv
, EX
, XX
},
1626 { "cvtpd2pi", MX
, EX
, XX
},
1627 { "cvtsd2siY", Gv
, EX
, XX
},
1631 { "cvttps2pi", MX
, EX
, XX
},
1632 { "cvttss2siY", Gv
, EX
, XX
},
1633 { "cvttpd2pi", MX
, EX
, XX
},
1634 { "cvttsd2siY", Gv
, EX
, XX
},
1638 { "divps", XM
, EX
, XX
},
1639 { "divss", XM
, EX
, XX
},
1640 { "divpd", XM
, EX
, XX
},
1641 { "divsd", XM
, EX
, XX
},
1645 { "maxps", XM
, EX
, XX
},
1646 { "maxss", XM
, EX
, XX
},
1647 { "maxpd", XM
, EX
, XX
},
1648 { "maxsd", XM
, EX
, XX
},
1652 { "minps", XM
, EX
, XX
},
1653 { "minss", XM
, EX
, XX
},
1654 { "minpd", XM
, EX
, XX
},
1655 { "minsd", XM
, EX
, XX
},
1659 { "movups", XM
, EX
, XX
},
1660 { "movss", XM
, EX
, XX
},
1661 { "movupd", XM
, EX
, XX
},
1662 { "movsd", XM
, EX
, XX
},
1666 { "movups", EX
, XM
, XX
},
1667 { "movss", EX
, XM
, XX
},
1668 { "movupd", EX
, XM
, XX
},
1669 { "movsd", EX
, XM
, XX
},
1673 { "mulps", XM
, EX
, XX
},
1674 { "mulss", XM
, EX
, XX
},
1675 { "mulpd", XM
, EX
, XX
},
1676 { "mulsd", XM
, EX
, XX
},
1680 { "rcpps", XM
, EX
, XX
},
1681 { "rcpss", XM
, EX
, XX
},
1682 { "(bad)", XM
, EX
, XX
},
1683 { "(bad)", XM
, EX
, XX
},
1687 { "rsqrtps", XM
, EX
, XX
},
1688 { "rsqrtss", XM
, EX
, XX
},
1689 { "(bad)", XM
, EX
, XX
},
1690 { "(bad)", XM
, EX
, XX
},
1694 { "sqrtps", XM
, EX
, XX
},
1695 { "sqrtss", XM
, EX
, XX
},
1696 { "sqrtpd", XM
, EX
, XX
},
1697 { "sqrtsd", XM
, EX
, XX
},
1701 { "subps", XM
, EX
, XX
},
1702 { "subss", XM
, EX
, XX
},
1703 { "subpd", XM
, EX
, XX
},
1704 { "subsd", XM
, EX
, XX
},
1708 { "(bad)", XM
, EX
, XX
},
1709 { "cvtdq2pd", XM
, EX
, XX
},
1710 { "cvttpd2dq", XM
, EX
, XX
},
1711 { "cvtpd2dq", XM
, EX
, XX
},
1715 { "cvtdq2ps", XM
, EX
, XX
},
1716 { "cvttps2dq",XM
, EX
, XX
},
1717 { "cvtps2dq",XM
, EX
, XX
},
1718 { "(bad)", XM
, EX
, XX
},
1722 { "cvtps2pd", XM
, EX
, XX
},
1723 { "cvtss2sd", XM
, EX
, XX
},
1724 { "cvtpd2ps", XM
, EX
, XX
},
1725 { "cvtsd2ss", XM
, EX
, XX
},
1729 { "maskmovq", MX
, MS
, XX
},
1730 { "(bad)", XM
, EX
, XX
},
1731 { "maskmovdqu", XM
, EX
, XX
},
1732 { "(bad)", XM
, EX
, XX
},
1736 { "movq", MX
, EM
, XX
},
1737 { "movdqu", XM
, EX
, XX
},
1738 { "movdqa", XM
, EX
, XX
},
1739 { "(bad)", XM
, EX
, XX
},
1743 { "movq", EM
, MX
, XX
},
1744 { "movdqu", EX
, XM
, XX
},
1745 { "movdqa", EX
, XM
, XX
},
1746 { "(bad)", EX
, XM
, XX
},
1750 { "(bad)", EX
, XM
, XX
},
1751 { "movq2dq", XM
, MS
, XX
},
1752 { "movq", EX
, XM
, XX
},
1753 { "movdq2q", MX
, XS
, XX
},
1757 { "pshufw", MX
, EM
, Ib
},
1758 { "pshufhw", XM
, EX
, Ib
},
1759 { "pshufd", XM
, EX
, Ib
},
1760 { "pshuflw", XM
, EX
, Ib
},
1764 { "movd", Ed
, MX
, XX
},
1765 { "movq", XM
, EX
, XX
},
1766 { "movd", Ed
, XM
, XX
},
1767 { "(bad)", Ed
, XM
, XX
},
1771 { "(bad)", MX
, EX
, XX
},
1772 { "(bad)", XM
, EX
, XX
},
1773 { "punpckhqdq", XM
, EX
, XX
},
1774 { "(bad)", XM
, EX
, XX
},
1778 { "movntq", Ev
, MX
, XX
},
1779 { "(bad)", Ev
, XM
, XX
},
1780 { "movntdq", Ev
, XM
, XX
},
1781 { "(bad)", Ev
, XM
, XX
},
1785 { "(bad)", MX
, EX
, XX
},
1786 { "(bad)", XM
, EX
, XX
},
1787 { "punpcklqdq", XM
, EX
, XX
},
1788 { "(bad)", XM
, EX
, XX
},
1792 static const struct dis386 x86_64_table
[][2] = {
1794 { "arpl", Ew
, Gw
, XX
},
1795 { "movs{||lq|xd}", Gv
, Ed
, XX
},
1799 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
1811 FETCH_DATA (the_info
, codep
+ 1);
1815 /* REX prefixes family. */
1838 prefixes
|= PREFIX_REPZ
;
1841 prefixes
|= PREFIX_REPNZ
;
1844 prefixes
|= PREFIX_LOCK
;
1847 prefixes
|= PREFIX_CS
;
1850 prefixes
|= PREFIX_SS
;
1853 prefixes
|= PREFIX_DS
;
1856 prefixes
|= PREFIX_ES
;
1859 prefixes
|= PREFIX_FS
;
1862 prefixes
|= PREFIX_GS
;
1865 prefixes
|= PREFIX_DATA
;
1868 prefixes
|= PREFIX_ADDR
;
1871 /* fwait is really an instruction. If there are prefixes
1872 before the fwait, they belong to the fwait, *not* to the
1873 following instruction. */
1876 prefixes
|= PREFIX_FWAIT
;
1880 prefixes
= PREFIX_FWAIT
;
1885 /* Rex is ignored when followed by another prefix. */
1888 oappend (prefix_name (rex
, 0));
1896 /* Return the name of the prefix byte PREF, or NULL if PREF is not a
1900 prefix_name (pref
, sizeflag
)
1906 /* REX prefixes family. */
1958 return (sizeflag
& DFLAG
) ? "data16" : "data32";
1961 return (sizeflag
& AFLAG
) ? "addr32" : "addr64";
1963 return ((sizeflag
& AFLAG
) && !mode_64bit
) ? "addr16" : "addr32";
1971 static char op1out
[100], op2out
[100], op3out
[100];
1972 static int op_ad
, op_index
[3];
1973 static bfd_vma op_address
[3];
1974 static bfd_vma op_riprel
[3];
1975 static bfd_vma start_pc
;
1978 * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1979 * (see topic "Redundant prefixes" in the "Differences from 8086"
1980 * section of the "Virtual 8086 Mode" chapter.)
1981 * 'pc' should be the address of this instruction, it will
1982 * be used to print the target address if this is a relative jump or call
1983 * The function returns the length of this instruction in bytes.
1986 static char intel_syntax
;
1987 static char open_char
;
1988 static char close_char
;
1989 static char separator_char
;
1990 static char scale_char
;
1992 /* Here for backwards compatibility. When gdb stops using
1993 print_insn_i386_att and print_insn_i386_intel these functions can
1994 disappear, and print_insn_i386 be merged into print_insn. */
1996 print_insn_i386_att (pc
, info
)
1998 disassemble_info
*info
;
2002 return print_insn (pc
, info
);
2006 print_insn_i386_intel (pc
, info
)
2008 disassemble_info
*info
;
2012 return print_insn (pc
, info
);
2016 print_insn_i386 (pc
, info
)
2018 disassemble_info
*info
;
2022 return print_insn (pc
, info
);
2026 print_insn (pc
, info
)
2028 disassemble_info
*info
;
2030 const struct dis386
*dp
;
2033 char *first
, *second
, *third
;
2035 unsigned char uses_SSE_prefix
;
2038 struct dis_private priv
;
2040 mode_64bit
= (info
->mach
== bfd_mach_x86_64_intel_syntax
2041 || info
->mach
== bfd_mach_x86_64
);
2043 if (intel_syntax
== -1)
2044 intel_syntax
= (info
->mach
== bfd_mach_i386_i386_intel_syntax
2045 || info
->mach
== bfd_mach_x86_64_intel_syntax
);
2047 if (info
->mach
== bfd_mach_i386_i386
2048 || info
->mach
== bfd_mach_x86_64
2049 || info
->mach
== bfd_mach_i386_i386_intel_syntax
2050 || info
->mach
== bfd_mach_x86_64_intel_syntax
)
2051 priv
.orig_sizeflag
= AFLAG
| DFLAG
;
2052 else if (info
->mach
== bfd_mach_i386_i8086
)
2053 priv
.orig_sizeflag
= 0;
2058 for (p
= info
->disassembler_options
; p
!= NULL
; )
2060 if (strncmp (p
, "x86-64", 6) == 0)
2063 priv
.orig_sizeflag
= AFLAG
| DFLAG
;
2065 else if (strncmp (p
, "i386", 4) == 0)
2068 priv
.orig_sizeflag
= AFLAG
| DFLAG
;
2070 else if (strncmp (p
, "i8086", 5) == 0)
2073 priv
.orig_sizeflag
= 0;
2075 else if (strncmp (p
, "intel", 5) == 0)
2079 else if (strncmp (p
, "att", 3) == 0)
2083 else if (strncmp (p
, "addr", 4) == 0)
2085 if (p
[4] == '1' && p
[5] == '6')
2086 priv
.orig_sizeflag
&= ~AFLAG
;
2087 else if (p
[4] == '3' && p
[5] == '2')
2088 priv
.orig_sizeflag
|= AFLAG
;
2090 else if (strncmp (p
, "data", 4) == 0)
2092 if (p
[4] == '1' && p
[5] == '6')
2093 priv
.orig_sizeflag
&= ~DFLAG
;
2094 else if (p
[4] == '3' && p
[5] == '2')
2095 priv
.orig_sizeflag
|= DFLAG
;
2097 else if (strncmp (p
, "suffix", 6) == 0)
2098 priv
.orig_sizeflag
|= SUFFIX_ALWAYS
;
2100 p
= strchr (p
, ',');
2106 priv
.orig_sizeflag
= AFLAG
| DFLAG
;
2112 names64
= intel_names64
;
2113 names32
= intel_names32
;
2114 names16
= intel_names16
;
2115 names8
= intel_names8
;
2116 names8rex
= intel_names8rex
;
2117 names_seg
= intel_names_seg
;
2118 index16
= intel_index16
;
2121 separator_char
= '+';
2126 names64
= att_names64
;
2127 names32
= att_names32
;
2128 names16
= att_names16
;
2129 names8
= att_names8
;
2130 names8rex
= att_names8rex
;
2131 names_seg
= att_names_seg
;
2132 index16
= att_index16
;
2135 separator_char
= ',';
2139 /* The output looks better if we put 7 bytes on a line, since that
2140 puts most long word instructions on a single line. */
2141 info
->bytes_per_line
= 7;
2143 info
->private_data
= (PTR
) &priv
;
2144 priv
.max_fetched
= priv
.the_buffer
;
2145 priv
.insn_start
= pc
;
2152 op_index
[0] = op_index
[1] = op_index
[2] = -1;
2156 start_codep
= priv
.the_buffer
;
2157 codep
= priv
.the_buffer
;
2159 if (_setjmp (priv
.bailout
) != 0)
2163 /* Getting here means we tried for data but didn't get it. That
2164 means we have an incomplete instruction of some sort. Just
2165 print the first byte as a prefix or a .byte pseudo-op. */
2166 if (codep
> priv
.the_buffer
)
2168 name
= prefix_name (priv
.the_buffer
[0], priv
.orig_sizeflag
);
2170 (*info
->fprintf_func
) (info
->stream
, "%s", name
);
2173 /* Just print the first byte as a .byte instruction. */
2174 (*info
->fprintf_func
) (info
->stream
, ".byte 0x%x",
2175 (unsigned int) priv
.the_buffer
[0]);
2188 sizeflag
= priv
.orig_sizeflag
;
2190 FETCH_DATA (info
, codep
+ 1);
2191 two_source_ops
= (*codep
== 0x62) || (*codep
== 0xc8);
2193 if ((prefixes
& PREFIX_FWAIT
)
2194 && ((*codep
< 0xd8) || (*codep
> 0xdf)))
2198 /* fwait not followed by floating point instruction. Print the
2199 first prefix, which is probably fwait itself. */
2200 name
= prefix_name (priv
.the_buffer
[0], priv
.orig_sizeflag
);
2202 name
= INTERNAL_DISASSEMBLER_ERROR
;
2203 (*info
->fprintf_func
) (info
->stream
, "%s", name
);
2209 FETCH_DATA (info
, codep
+ 2);
2210 dp
= &dis386_twobyte
[*++codep
];
2211 need_modrm
= twobyte_has_modrm
[*codep
];
2212 uses_SSE_prefix
= twobyte_uses_SSE_prefix
[*codep
];
2216 dp
= &dis386
[*codep
];
2217 need_modrm
= onebyte_has_modrm
[*codep
];
2218 uses_SSE_prefix
= 0;
2222 if (!uses_SSE_prefix
&& (prefixes
& PREFIX_REPZ
))
2225 used_prefixes
|= PREFIX_REPZ
;
2227 if (!uses_SSE_prefix
&& (prefixes
& PREFIX_REPNZ
))
2230 used_prefixes
|= PREFIX_REPNZ
;
2232 if (prefixes
& PREFIX_LOCK
)
2235 used_prefixes
|= PREFIX_LOCK
;
2238 if (prefixes
& PREFIX_ADDR
)
2241 if (dp
->bytemode3
!= loop_jcxz_mode
|| intel_syntax
)
2243 if ((sizeflag
& AFLAG
) || mode_64bit
)
2244 oappend ("addr32 ");
2246 oappend ("addr16 ");
2247 used_prefixes
|= PREFIX_ADDR
;
2251 if (!uses_SSE_prefix
&& (prefixes
& PREFIX_DATA
))
2254 if (dp
->bytemode3
== cond_jump_mode
2255 && dp
->bytemode1
== v_mode
2258 if (sizeflag
& DFLAG
)
2259 oappend ("data32 ");
2261 oappend ("data16 ");
2262 used_prefixes
|= PREFIX_DATA
;
2268 FETCH_DATA (info
, codep
+ 1);
2269 mod
= (*codep
>> 6) & 3;
2270 reg
= (*codep
>> 3) & 7;
2274 if (dp
->name
== NULL
&& dp
->bytemode1
== FLOATCODE
)
2281 if (dp
->name
== NULL
)
2283 switch (dp
->bytemode1
)
2286 dp
= &grps
[dp
->bytemode2
][reg
];
2289 case USE_PREFIX_USER_TABLE
:
2291 used_prefixes
|= (prefixes
& PREFIX_REPZ
);
2292 if (prefixes
& PREFIX_REPZ
)
2296 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2297 if (prefixes
& PREFIX_DATA
)
2301 used_prefixes
|= (prefixes
& PREFIX_REPNZ
);
2302 if (prefixes
& PREFIX_REPNZ
)
2306 dp
= &prefix_user_table
[dp
->bytemode2
][index
];
2309 case X86_64_SPECIAL
:
2310 dp
= &x86_64_table
[dp
->bytemode2
][mode_64bit
];
2314 oappend (INTERNAL_DISASSEMBLER_ERROR
);
2319 if (putop (dp
->name
, sizeflag
) == 0)
2324 (*dp
->op1
) (dp
->bytemode1
, sizeflag
);
2329 (*dp
->op2
) (dp
->bytemode2
, sizeflag
);
2334 (*dp
->op3
) (dp
->bytemode3
, sizeflag
);
2338 /* See if any prefixes were not used. If so, print the first one
2339 separately. If we don't do this, we'll wind up printing an
2340 instruction stream which does not precisely correspond to the
2341 bytes we are disassembling. */
2342 if ((prefixes
& ~used_prefixes
) != 0)
2346 name
= prefix_name (priv
.the_buffer
[0], priv
.orig_sizeflag
);
2348 name
= INTERNAL_DISASSEMBLER_ERROR
;
2349 (*info
->fprintf_func
) (info
->stream
, "%s", name
);
2352 if (rex
& ~rex_used
)
2355 name
= prefix_name (rex
| 0x40, priv
.orig_sizeflag
);
2357 name
= INTERNAL_DISASSEMBLER_ERROR
;
2358 (*info
->fprintf_func
) (info
->stream
, "%s ", name
);
2361 obufp
= obuf
+ strlen (obuf
);
2362 for (i
= strlen (obuf
); i
< 6; i
++)
2365 (*info
->fprintf_func
) (info
->stream
, "%s", obuf
);
2367 /* The enter and bound instructions are printed with operands in the same
2368 order as the intel book; everything else is printed in reverse order. */
2369 if (intel_syntax
|| two_source_ops
)
2374 op_ad
= op_index
[0];
2375 op_index
[0] = op_index
[2];
2376 op_index
[2] = op_ad
;
2387 if (op_index
[0] != -1 && !op_riprel
[0])
2388 (*info
->print_address_func
) ((bfd_vma
) op_address
[op_index
[0]], info
);
2390 (*info
->fprintf_func
) (info
->stream
, "%s", first
);
2396 (*info
->fprintf_func
) (info
->stream
, ",");
2397 if (op_index
[1] != -1 && !op_riprel
[1])
2398 (*info
->print_address_func
) ((bfd_vma
) op_address
[op_index
[1]], info
);
2400 (*info
->fprintf_func
) (info
->stream
, "%s", second
);
2406 (*info
->fprintf_func
) (info
->stream
, ",");
2407 if (op_index
[2] != -1 && !op_riprel
[2])
2408 (*info
->print_address_func
) ((bfd_vma
) op_address
[op_index
[2]], info
);
2410 (*info
->fprintf_func
) (info
->stream
, "%s", third
);
2412 for (i
= 0; i
< 3; i
++)
2413 if (op_index
[i
] != -1 && op_riprel
[i
])
2415 (*info
->fprintf_func
) (info
->stream
, " # ");
2416 (*info
->print_address_func
) ((bfd_vma
) (start_pc
+ codep
- start_codep
2417 + op_address
[op_index
[i
]]), info
);
2419 return codep
- priv
.the_buffer
;
2422 static const char *float_mem
[] = {
2498 #define STi OP_STi, 0
2500 #define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
2501 #define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
2502 #define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
2503 #define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
2504 #define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
2505 #define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
2506 #define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
2507 #define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
2508 #define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
2510 static const struct dis386 float_reg
[][8] = {
2513 { "fadd", ST
, STi
, XX
},
2514 { "fmul", ST
, STi
, XX
},
2515 { "fcom", STi
, XX
, XX
},
2516 { "fcomp", STi
, XX
, XX
},
2517 { "fsub", ST
, STi
, XX
},
2518 { "fsubr", ST
, STi
, XX
},
2519 { "fdiv", ST
, STi
, XX
},
2520 { "fdivr", ST
, STi
, XX
},
2524 { "fld", STi
, XX
, XX
},
2525 { "fxch", STi
, XX
, XX
},
2527 { "(bad)", XX
, XX
, XX
},
2535 { "fcmovb", ST
, STi
, XX
},
2536 { "fcmove", ST
, STi
, XX
},
2537 { "fcmovbe",ST
, STi
, XX
},
2538 { "fcmovu", ST
, STi
, XX
},
2539 { "(bad)", XX
, XX
, XX
},
2541 { "(bad)", XX
, XX
, XX
},
2542 { "(bad)", XX
, XX
, XX
},
2546 { "fcmovnb",ST
, STi
, XX
},
2547 { "fcmovne",ST
, STi
, XX
},
2548 { "fcmovnbe",ST
, STi
, XX
},
2549 { "fcmovnu",ST
, STi
, XX
},
2551 { "fucomi", ST
, STi
, XX
},
2552 { "fcomi", ST
, STi
, XX
},
2553 { "(bad)", XX
, XX
, XX
},
2557 { "fadd", STi
, ST
, XX
},
2558 { "fmul", STi
, ST
, XX
},
2559 { "(bad)", XX
, XX
, XX
},
2560 { "(bad)", XX
, XX
, XX
},
2562 { "fsub", STi
, ST
, XX
},
2563 { "fsubr", STi
, ST
, XX
},
2564 { "fdiv", STi
, ST
, XX
},
2565 { "fdivr", STi
, ST
, XX
},
2567 { "fsubr", STi
, ST
, XX
},
2568 { "fsub", STi
, ST
, XX
},
2569 { "fdivr", STi
, ST
, XX
},
2570 { "fdiv", STi
, ST
, XX
},
2575 { "ffree", STi
, XX
, XX
},
2576 { "(bad)", XX
, XX
, XX
},
2577 { "fst", STi
, XX
, XX
},
2578 { "fstp", STi
, XX
, XX
},
2579 { "fucom", STi
, XX
, XX
},
2580 { "fucomp", STi
, XX
, XX
},
2581 { "(bad)", XX
, XX
, XX
},
2582 { "(bad)", XX
, XX
, XX
},
2586 { "faddp", STi
, ST
, XX
},
2587 { "fmulp", STi
, ST
, XX
},
2588 { "(bad)", XX
, XX
, XX
},
2591 { "fsubp", STi
, ST
, XX
},
2592 { "fsubrp", STi
, ST
, XX
},
2593 { "fdivp", STi
, ST
, XX
},
2594 { "fdivrp", STi
, ST
, XX
},
2596 { "fsubrp", STi
, ST
, XX
},
2597 { "fsubp", STi
, ST
, XX
},
2598 { "fdivrp", STi
, ST
, XX
},
2599 { "fdivp", STi
, ST
, XX
},
2604 { "ffreep", STi
, XX
, XX
},
2605 { "(bad)", XX
, XX
, XX
},
2606 { "(bad)", XX
, XX
, XX
},
2607 { "(bad)", XX
, XX
, XX
},
2609 { "fucomip",ST
, STi
, XX
},
2610 { "fcomip", ST
, STi
, XX
},
2611 { "(bad)", XX
, XX
, XX
},
2615 static char *fgrps
[][8] = {
2618 "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2623 "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
2628 "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
2633 "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
2638 "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
2643 "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2648 "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
2649 "fNsetpm(287 only)","(bad)","(bad)","(bad)",
2654 "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2659 "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
2667 const struct dis386
*dp
;
2668 unsigned char floatop
;
2670 floatop
= codep
[-1];
2674 putop (float_mem
[(floatop
- 0xd8) * 8 + reg
], sizeflag
);
2676 if (floatop
== 0xdb)
2677 OP_E (x_mode
, sizeflag
);
2678 else if (floatop
== 0xdd)
2679 OP_E (d_mode
, sizeflag
);
2681 OP_E (v_mode
, sizeflag
);
2684 /* Skip mod/rm byte. */
2688 dp
= &float_reg
[floatop
- 0xd8][reg
];
2689 if (dp
->name
== NULL
)
2691 putop (fgrps
[dp
->bytemode1
][rm
], sizeflag
);
2693 /* Instruction fnstsw is only one with strange arg. */
2694 if (floatop
== 0xdf && codep
[-1] == 0xe0)
2695 strcpy (op1out
, names16
[0]);
2699 putop (dp
->name
, sizeflag
);
2703 (*dp
->op1
) (dp
->bytemode1
, sizeflag
);
2706 (*dp
->op2
) (dp
->bytemode2
, sizeflag
);
2711 OP_ST (bytemode
, sizeflag
)
2712 int bytemode ATTRIBUTE_UNUSED
;
2713 int sizeflag ATTRIBUTE_UNUSED
;
2719 OP_STi (bytemode
, sizeflag
)
2720 int bytemode ATTRIBUTE_UNUSED
;
2721 int sizeflag ATTRIBUTE_UNUSED
;
2723 sprintf (scratchbuf
, "%%st(%d)", rm
);
2724 oappend (scratchbuf
+ intel_syntax
);
2727 /* Capital letters in template are macros. */
2729 putop (template, sizeflag
)
2730 const char *template;
2736 for (p
= template; *p
; p
++)
2755 /* Alternative not valid. */
2756 strcpy (obuf
, "(bad)");
2760 else if (*p
== '\0')
2778 if (mod
!= 3 || (sizeflag
& SUFFIX_ALWAYS
))
2784 if (sizeflag
& SUFFIX_ALWAYS
)
2787 case 'E': /* For jcxz/jecxz */
2790 if (sizeflag
& AFLAG
)
2796 if (sizeflag
& AFLAG
)
2798 used_prefixes
|= (prefixes
& PREFIX_ADDR
);
2803 if ((prefixes
& PREFIX_ADDR
) || (sizeflag
& SUFFIX_ALWAYS
))
2805 if (sizeflag
& AFLAG
)
2806 *obufp
++ = mode_64bit
? 'q' : 'l';
2808 *obufp
++ = mode_64bit
? 'l' : 'w';
2809 used_prefixes
|= (prefixes
& PREFIX_ADDR
);
2815 if ((prefixes
& (PREFIX_CS
| PREFIX_DS
)) == PREFIX_CS
2816 || (prefixes
& (PREFIX_CS
| PREFIX_DS
)) == PREFIX_DS
)
2818 used_prefixes
|= prefixes
& (PREFIX_CS
| PREFIX_DS
);
2821 if (prefixes
& PREFIX_DS
)
2830 if (sizeflag
& SUFFIX_ALWAYS
)
2834 if ((prefixes
& PREFIX_FWAIT
) == 0)
2837 used_prefixes
|= PREFIX_FWAIT
;
2840 USED_REX (REX_MODE64
);
2841 if (rex
& REX_MODE64
)
2858 if ((prefixes
& PREFIX_DATA
)
2859 || (rex
& REX_MODE64
)
2860 || (sizeflag
& SUFFIX_ALWAYS
))
2862 USED_REX (REX_MODE64
);
2863 if (rex
& REX_MODE64
)
2867 if (sizeflag
& DFLAG
)
2871 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2887 USED_REX (REX_MODE64
);
2888 if (mod
!= 3 || (sizeflag
& SUFFIX_ALWAYS
))
2890 if (rex
& REX_MODE64
)
2894 if (sizeflag
& DFLAG
)
2898 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2903 USED_REX (REX_MODE64
);
2906 if (rex
& REX_MODE64
)
2911 else if (sizeflag
& DFLAG
)
2924 if (rex
& REX_MODE64
)
2926 else if (sizeflag
& DFLAG
)
2931 if (!(rex
& REX_MODE64
))
2932 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2937 if (sizeflag
& SUFFIX_ALWAYS
)
2939 if (rex
& REX_MODE64
)
2943 if (sizeflag
& DFLAG
)
2947 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2952 if (prefixes
& PREFIX_DATA
)
2956 used_prefixes
|= (prefixes
& PREFIX_DATA
);
2961 if (rex
& REX_MODE64
)
2963 USED_REX (REX_MODE64
);
2967 /* implicit operand size 'l' for i386 or 'q' for x86-64 */
2969 /* operand size flag for cwtl, cbtw */
2973 else if (sizeflag
& DFLAG
)
2984 if (sizeflag
& DFLAG
)
2995 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3008 obufp
+= strlen (s
);
3014 if (prefixes
& PREFIX_CS
)
3016 used_prefixes
|= PREFIX_CS
;
3017 oappend ("%cs:" + intel_syntax
);
3019 if (prefixes
& PREFIX_DS
)
3021 used_prefixes
|= PREFIX_DS
;
3022 oappend ("%ds:" + intel_syntax
);
3024 if (prefixes
& PREFIX_SS
)
3026 used_prefixes
|= PREFIX_SS
;
3027 oappend ("%ss:" + intel_syntax
);
3029 if (prefixes
& PREFIX_ES
)
3031 used_prefixes
|= PREFIX_ES
;
3032 oappend ("%es:" + intel_syntax
);
3034 if (prefixes
& PREFIX_FS
)
3036 used_prefixes
|= PREFIX_FS
;
3037 oappend ("%fs:" + intel_syntax
);
3039 if (prefixes
& PREFIX_GS
)
3041 used_prefixes
|= PREFIX_GS
;
3042 oappend ("%gs:" + intel_syntax
);
3047 OP_indirE (bytemode
, sizeflag
)
3053 OP_E (bytemode
, sizeflag
);
3057 print_operand_value (buf
, hex
, disp
)
3070 sprintf_vma (tmp
, disp
);
3071 for (i
= 0; tmp
[i
] == '0' && tmp
[i
+ 1]; i
++);
3072 strcpy (buf
+ 2, tmp
+ i
);
3076 bfd_signed_vma v
= disp
;
3083 /* Check for possible overflow on 0x8000000000000000. */
3086 strcpy (buf
, "9223372036854775808");
3100 tmp
[28 - i
] = (v
% 10) + '0';
3104 strcpy (buf
, tmp
+ 29 - i
);
3110 sprintf (buf
, "0x%x", (unsigned int) disp
);
3112 sprintf (buf
, "%d", (int) disp
);
3117 OP_E (bytemode
, sizeflag
)
3124 USED_REX (REX_EXTZ
);
3128 /* Skip mod/rm byte. */
3139 oappend (names8rex
[rm
+ add
]);
3141 oappend (names8
[rm
+ add
]);
3144 oappend (names16
[rm
+ add
]);
3147 oappend (names32
[rm
+ add
]);
3150 oappend (names64
[rm
+ add
]);
3154 oappend (names64
[rm
+ add
]);
3156 oappend (names32
[rm
+ add
]);
3159 USED_REX (REX_MODE64
);
3160 if (rex
& REX_MODE64
)
3161 oappend (names64
[rm
+ add
]);
3162 else if (sizeflag
& DFLAG
)
3163 oappend (names32
[rm
+ add
]);
3165 oappend (names16
[rm
+ add
]);
3166 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3169 if (!(codep
[-2] == 0xAE && codep
[-1] == 0xF8 /* sfence */)
3170 && !(codep
[-2] == 0xAE && codep
[-1] == 0xF0 /* mfence */)
3171 && !(codep
[-2] == 0xAE && codep
[-1] == 0xe8 /* lfence */))
3172 BadOp (); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
3175 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3184 if ((sizeflag
& AFLAG
) || mode_64bit
) /* 32 bit address mode */
3199 FETCH_DATA (the_info
, codep
+ 1);
3200 scale
= (*codep
>> 6) & 3;
3201 index
= (*codep
>> 3) & 7;
3203 USED_REX (REX_EXTY
);
3204 USED_REX (REX_EXTZ
);
3215 if ((base
& 7) == 5)
3218 if (mode_64bit
&& !havesib
&& (sizeflag
& AFLAG
))
3224 FETCH_DATA (the_info
, codep
+ 1);
3226 if ((disp
& 0x80) != 0)
3235 if (mod
!= 0 || (base
& 7) == 5)
3237 print_operand_value (scratchbuf
, !riprel
, disp
);
3238 oappend (scratchbuf
);
3246 if (havebase
|| (havesib
&& (index
!= 4 || scale
!= 0)))
3253 oappend ("BYTE PTR ");
3256 oappend ("WORD PTR ");
3259 oappend ("DWORD PTR ");
3262 oappend ("QWORD PTR ");
3266 oappend ("DWORD PTR ");
3268 oappend ("QWORD PTR ");
3271 oappend ("XWORD PTR ");
3277 *obufp
++ = open_char
;
3278 if (intel_syntax
&& riprel
)
3281 USED_REX (REX_EXTZ
);
3282 if (!havesib
&& (rex
& REX_EXTZ
))
3285 oappend (mode_64bit
&& (sizeflag
& AFLAG
)
3286 ? names64
[base
] : names32
[base
]);
3295 *obufp
++ = separator_char
;
3298 sprintf (scratchbuf
, "%s",
3299 mode_64bit
&& (sizeflag
& AFLAG
)
3300 ? names64
[index
] : names32
[index
]);
3303 sprintf (scratchbuf
, ",%s",
3304 mode_64bit
&& (sizeflag
& AFLAG
)
3305 ? names64
[index
] : names32
[index
]);
3306 oappend (scratchbuf
);
3310 && bytemode
!= b_mode
3311 && bytemode
!= w_mode
3312 && bytemode
!= v_mode
))
3314 *obufp
++ = scale_char
;
3316 sprintf (scratchbuf
, "%d", 1 << scale
);
3317 oappend (scratchbuf
);
3321 if (mod
!= 0 || (base
& 7) == 5)
3323 /* Don't print zero displacements. */
3326 if ((bfd_signed_vma
) disp
> 0)
3332 print_operand_value (scratchbuf
, 0, disp
);
3333 oappend (scratchbuf
);
3337 *obufp
++ = close_char
;
3340 else if (intel_syntax
)
3342 if (mod
!= 0 || (base
& 7) == 5)
3344 if (prefixes
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
3345 | PREFIX_ES
| PREFIX_FS
| PREFIX_GS
))
3349 oappend (names_seg
[ds_reg
- es_reg
]);
3352 print_operand_value (scratchbuf
, 1, disp
);
3353 oappend (scratchbuf
);
3358 { /* 16 bit address mode */
3365 if ((disp
& 0x8000) != 0)
3370 FETCH_DATA (the_info
, codep
+ 1);
3372 if ((disp
& 0x80) != 0)
3377 if ((disp
& 0x8000) != 0)
3383 if (mod
!= 0 || (rm
& 7) == 6)
3385 print_operand_value (scratchbuf
, 0, disp
);
3386 oappend (scratchbuf
);
3389 if (mod
!= 0 || (rm
& 7) != 6)
3391 *obufp
++ = open_char
;
3393 oappend (index16
[rm
+ add
]);
3394 *obufp
++ = close_char
;
3401 OP_G (bytemode
, sizeflag
)
3406 USED_REX (REX_EXTX
);
3414 oappend (names8rex
[reg
+ add
]);
3416 oappend (names8
[reg
+ add
]);
3419 oappend (names16
[reg
+ add
]);
3422 oappend (names32
[reg
+ add
]);
3425 oappend (names64
[reg
+ add
]);
3428 USED_REX (REX_MODE64
);
3429 if (rex
& REX_MODE64
)
3430 oappend (names64
[reg
+ add
]);
3431 else if (sizeflag
& DFLAG
)
3432 oappend (names32
[reg
+ add
]);
3434 oappend (names16
[reg
+ add
]);
3435 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3438 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3451 FETCH_DATA (the_info
, codep
+ 8);
3452 a
= *codep
++ & 0xff;
3453 a
|= (*codep
++ & 0xff) << 8;
3454 a
|= (*codep
++ & 0xff) << 16;
3455 a
|= (*codep
++ & 0xff) << 24;
3456 b
= *codep
++ & 0xff;
3457 b
|= (*codep
++ & 0xff) << 8;
3458 b
|= (*codep
++ & 0xff) << 16;
3459 b
|= (*codep
++ & 0xff) << 24;
3460 x
= a
+ ((bfd_vma
) b
<< 32);
3468 static bfd_signed_vma
3471 bfd_signed_vma x
= 0;
3473 FETCH_DATA (the_info
, codep
+ 4);
3474 x
= *codep
++ & (bfd_signed_vma
) 0xff;
3475 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 8;
3476 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 16;
3477 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 24;
3481 static bfd_signed_vma
3484 bfd_signed_vma x
= 0;
3486 FETCH_DATA (the_info
, codep
+ 4);
3487 x
= *codep
++ & (bfd_signed_vma
) 0xff;
3488 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 8;
3489 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 16;
3490 x
|= (*codep
++ & (bfd_signed_vma
) 0xff) << 24;
3492 x
= (x
^ ((bfd_signed_vma
) 1 << 31)) - ((bfd_signed_vma
) 1 << 31);
3502 FETCH_DATA (the_info
, codep
+ 2);
3503 x
= *codep
++ & 0xff;
3504 x
|= (*codep
++ & 0xff) << 8;
3513 op_index
[op_ad
] = op_ad
;
3516 op_address
[op_ad
] = op
;
3517 op_riprel
[op_ad
] = riprel
;
3521 /* Mask to get a 32-bit address. */
3522 op_address
[op_ad
] = op
& 0xffffffff;
3523 op_riprel
[op_ad
] = riprel
& 0xffffffff;
3528 OP_REG (code
, sizeflag
)
3534 USED_REX (REX_EXTZ
);
3546 case ax_reg
: case cx_reg
: case dx_reg
: case bx_reg
:
3547 case sp_reg
: case bp_reg
: case si_reg
: case di_reg
:
3548 s
= names16
[code
- ax_reg
+ add
];
3550 case es_reg
: case ss_reg
: case cs_reg
:
3551 case ds_reg
: case fs_reg
: case gs_reg
:
3552 s
= names_seg
[code
- es_reg
+ add
];
3554 case al_reg
: case ah_reg
: case cl_reg
: case ch_reg
:
3555 case dl_reg
: case dh_reg
: case bl_reg
: case bh_reg
:
3558 s
= names8rex
[code
- al_reg
+ add
];
3560 s
= names8
[code
- al_reg
];
3562 case rAX_reg
: case rCX_reg
: case rDX_reg
: case rBX_reg
:
3563 case rSP_reg
: case rBP_reg
: case rSI_reg
: case rDI_reg
:
3566 s
= names64
[code
- rAX_reg
+ add
];
3569 code
+= eAX_reg
- rAX_reg
;
3571 case eAX_reg
: case eCX_reg
: case eDX_reg
: case eBX_reg
:
3572 case eSP_reg
: case eBP_reg
: case eSI_reg
: case eDI_reg
:
3573 USED_REX (REX_MODE64
);
3574 if (rex
& REX_MODE64
)
3575 s
= names64
[code
- eAX_reg
+ add
];
3576 else if (sizeflag
& DFLAG
)
3577 s
= names32
[code
- eAX_reg
+ add
];
3579 s
= names16
[code
- eAX_reg
+ add
];
3580 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3583 s
= INTERNAL_DISASSEMBLER_ERROR
;
3590 OP_IMREG (code
, sizeflag
)
3604 case ax_reg
: case cx_reg
: case dx_reg
: case bx_reg
:
3605 case sp_reg
: case bp_reg
: case si_reg
: case di_reg
:
3606 s
= names16
[code
- ax_reg
];
3608 case es_reg
: case ss_reg
: case cs_reg
:
3609 case ds_reg
: case fs_reg
: case gs_reg
:
3610 s
= names_seg
[code
- es_reg
];
3612 case al_reg
: case ah_reg
: case cl_reg
: case ch_reg
:
3613 case dl_reg
: case dh_reg
: case bl_reg
: case bh_reg
:
3616 s
= names8rex
[code
- al_reg
];
3618 s
= names8
[code
- al_reg
];
3620 case eAX_reg
: case eCX_reg
: case eDX_reg
: case eBX_reg
:
3621 case eSP_reg
: case eBP_reg
: case eSI_reg
: case eDI_reg
:
3622 USED_REX (REX_MODE64
);
3623 if (rex
& REX_MODE64
)
3624 s
= names64
[code
- eAX_reg
];
3625 else if (sizeflag
& DFLAG
)
3626 s
= names32
[code
- eAX_reg
];
3628 s
= names16
[code
- eAX_reg
];
3629 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3632 s
= INTERNAL_DISASSEMBLER_ERROR
;
3639 OP_I (bytemode
, sizeflag
)
3644 bfd_signed_vma mask
= -1;
3649 FETCH_DATA (the_info
, codep
+ 1);
3661 USED_REX (REX_MODE64
);
3662 if (rex
& REX_MODE64
)
3664 else if (sizeflag
& DFLAG
)
3674 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3681 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3686 scratchbuf
[0] = '$';
3687 print_operand_value (scratchbuf
+ 1, 1, op
);
3688 oappend (scratchbuf
+ intel_syntax
);
3689 scratchbuf
[0] = '\0';
3693 OP_I64 (bytemode
, sizeflag
)
3698 bfd_signed_vma mask
= -1;
3702 OP_I (bytemode
, sizeflag
);
3709 FETCH_DATA (the_info
, codep
+ 1);
3714 USED_REX (REX_MODE64
);
3715 if (rex
& REX_MODE64
)
3717 else if (sizeflag
& DFLAG
)
3727 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3734 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3739 scratchbuf
[0] = '$';
3740 print_operand_value (scratchbuf
+ 1, 1, op
);
3741 oappend (scratchbuf
+ intel_syntax
);
3742 scratchbuf
[0] = '\0';
3746 OP_sI (bytemode
, sizeflag
)
3751 bfd_signed_vma mask
= -1;
3756 FETCH_DATA (the_info
, codep
+ 1);
3758 if ((op
& 0x80) != 0)
3763 USED_REX (REX_MODE64
);
3764 if (rex
& REX_MODE64
)
3766 else if (sizeflag
& DFLAG
)
3775 if ((op
& 0x8000) != 0)
3778 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3783 if ((op
& 0x8000) != 0)
3787 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3791 scratchbuf
[0] = '$';
3792 print_operand_value (scratchbuf
+ 1, 1, op
);
3793 oappend (scratchbuf
+ intel_syntax
);
3797 OP_J (bytemode
, sizeflag
)
3807 FETCH_DATA (the_info
, codep
+ 1);
3809 if ((disp
& 0x80) != 0)
3813 if (sizeflag
& DFLAG
)
3818 /* For some reason, a data16 prefix on a jump instruction
3819 means that the pc is masked to 16 bits after the
3820 displacement is added! */
3825 oappend (INTERNAL_DISASSEMBLER_ERROR
);
3828 disp
= (start_pc
+ codep
- start_codep
+ disp
) & mask
;
3830 print_operand_value (scratchbuf
, 1, disp
);
3831 oappend (scratchbuf
);
3835 OP_SEG (dummy
, sizeflag
)
3836 int dummy ATTRIBUTE_UNUSED
;
3837 int sizeflag ATTRIBUTE_UNUSED
;
3839 oappend (names_seg
[reg
]);
3843 OP_DIR (dummy
, sizeflag
)
3844 int dummy ATTRIBUTE_UNUSED
;
3849 if (sizeflag
& DFLAG
)
3859 used_prefixes
|= (prefixes
& PREFIX_DATA
);
3861 sprintf (scratchbuf
, "0x%x,0x%x", seg
, offset
);
3863 sprintf (scratchbuf
, "$0x%x,$0x%x", seg
, offset
);
3864 oappend (scratchbuf
);
3868 OP_OFF (bytemode
, sizeflag
)
3869 int bytemode ATTRIBUTE_UNUSED
;
3876 if ((sizeflag
& AFLAG
) || mode_64bit
)
3883 if (!(prefixes
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
3884 | PREFIX_ES
| PREFIX_FS
| PREFIX_GS
)))
3886 oappend (names_seg
[ds_reg
- es_reg
]);
3890 print_operand_value (scratchbuf
, 1, off
);
3891 oappend (scratchbuf
);
3895 OP_OFF64 (bytemode
, sizeflag
)
3896 int bytemode ATTRIBUTE_UNUSED
;
3897 int sizeflag ATTRIBUTE_UNUSED
;
3903 OP_OFF (bytemode
, sizeflag
);
3913 if (!(prefixes
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
3914 | PREFIX_ES
| PREFIX_FS
| PREFIX_GS
)))
3916 oappend (names_seg
[ds_reg
- es_reg
]);
3920 print_operand_value (scratchbuf
, 1, off
);
3921 oappend (scratchbuf
);
3925 ptr_reg (code
, sizeflag
)
3935 USED_REX (REX_MODE64
);
3936 if (rex
& REX_MODE64
)
3938 if (!(sizeflag
& AFLAG
))
3939 s
= names32
[code
- eAX_reg
];
3941 s
= names64
[code
- eAX_reg
];
3943 else if (sizeflag
& AFLAG
)
3944 s
= names32
[code
- eAX_reg
];
3946 s
= names16
[code
- eAX_reg
];
3955 OP_ESreg (code
, sizeflag
)
3959 oappend ("%es:" + intel_syntax
);
3960 ptr_reg (code
, sizeflag
);
3964 OP_DSreg (code
, sizeflag
)
3975 prefixes
|= PREFIX_DS
;
3977 ptr_reg (code
, sizeflag
);
3981 OP_C (dummy
, sizeflag
)
3982 int dummy ATTRIBUTE_UNUSED
;
3983 int sizeflag ATTRIBUTE_UNUSED
;
3986 USED_REX (REX_EXTX
);
3989 sprintf (scratchbuf
, "%%cr%d", reg
+ add
);
3990 oappend (scratchbuf
+ intel_syntax
);
3994 OP_D (dummy
, sizeflag
)
3995 int dummy ATTRIBUTE_UNUSED
;
3996 int sizeflag ATTRIBUTE_UNUSED
;
3999 USED_REX (REX_EXTX
);
4003 sprintf (scratchbuf
, "db%d", reg
+ add
);
4005 sprintf (scratchbuf
, "%%db%d", reg
+ add
);
4006 oappend (scratchbuf
);
4010 OP_T (dummy
, sizeflag
)
4011 int dummy ATTRIBUTE_UNUSED
;
4012 int sizeflag ATTRIBUTE_UNUSED
;
4014 sprintf (scratchbuf
, "%%tr%d", reg
);
4015 oappend (scratchbuf
+ intel_syntax
);
4019 OP_Rd (bytemode
, sizeflag
)
4024 OP_E (bytemode
, sizeflag
);
4030 OP_MMX (bytemode
, sizeflag
)
4031 int bytemode ATTRIBUTE_UNUSED
;
4032 int sizeflag ATTRIBUTE_UNUSED
;
4035 USED_REX (REX_EXTX
);
4038 used_prefixes
|= (prefixes
& PREFIX_DATA
);
4039 if (prefixes
& PREFIX_DATA
)
4040 sprintf (scratchbuf
, "%%xmm%d", reg
+ add
);
4042 sprintf (scratchbuf
, "%%mm%d", reg
+ add
);
4043 oappend (scratchbuf
+ intel_syntax
);
4047 OP_XMM (bytemode
, sizeflag
)
4048 int bytemode ATTRIBUTE_UNUSED
;
4049 int sizeflag ATTRIBUTE_UNUSED
;
4052 USED_REX (REX_EXTX
);
4055 sprintf (scratchbuf
, "%%xmm%d", reg
+ add
);
4056 oappend (scratchbuf
+ intel_syntax
);
4060 OP_EM (bytemode
, sizeflag
)
4067 OP_E (bytemode
, sizeflag
);
4070 USED_REX (REX_EXTZ
);
4074 /* Skip mod/rm byte. */
4077 used_prefixes
|= (prefixes
& PREFIX_DATA
);
4078 if (prefixes
& PREFIX_DATA
)
4079 sprintf (scratchbuf
, "%%xmm%d", rm
+ add
);
4081 sprintf (scratchbuf
, "%%mm%d", rm
+ add
);
4082 oappend (scratchbuf
+ intel_syntax
);
4086 OP_EX (bytemode
, sizeflag
)
4093 OP_E (bytemode
, sizeflag
);
4096 USED_REX (REX_EXTZ
);
4100 /* Skip mod/rm byte. */
4103 sprintf (scratchbuf
, "%%xmm%d", rm
+ add
);
4104 oappend (scratchbuf
+ intel_syntax
);
4108 OP_MS (bytemode
, sizeflag
)
4113 OP_EM (bytemode
, sizeflag
);
4119 OP_XS (bytemode
, sizeflag
)
4124 OP_EX (bytemode
, sizeflag
);
4129 static const char *Suffix3DNow
[] = {
4130 /* 00 */ NULL
, NULL
, NULL
, NULL
,
4131 /* 04 */ NULL
, NULL
, NULL
, NULL
,
4132 /* 08 */ NULL
, NULL
, NULL
, NULL
,
4133 /* 0C */ "pi2fw", "pi2fd", NULL
, NULL
,
4134 /* 10 */ NULL
, NULL
, NULL
, NULL
,
4135 /* 14 */ NULL
, NULL
, NULL
, NULL
,
4136 /* 18 */ NULL
, NULL
, NULL
, NULL
,
4137 /* 1C */ "pf2iw", "pf2id", NULL
, NULL
,
4138 /* 20 */ NULL
, NULL
, NULL
, NULL
,
4139 /* 24 */ NULL
, NULL
, NULL
, NULL
,
4140 /* 28 */ NULL
, NULL
, NULL
, NULL
,
4141 /* 2C */ NULL
, NULL
, NULL
, NULL
,
4142 /* 30 */ NULL
, NULL
, NULL
, NULL
,
4143 /* 34 */ NULL
, NULL
, NULL
, NULL
,
4144 /* 38 */ NULL
, NULL
, NULL
, NULL
,
4145 /* 3C */ NULL
, NULL
, NULL
, NULL
,
4146 /* 40 */ NULL
, NULL
, NULL
, NULL
,
4147 /* 44 */ NULL
, NULL
, NULL
, NULL
,
4148 /* 48 */ NULL
, NULL
, NULL
, NULL
,
4149 /* 4C */ NULL
, NULL
, NULL
, NULL
,
4150 /* 50 */ NULL
, NULL
, NULL
, NULL
,
4151 /* 54 */ NULL
, NULL
, NULL
, NULL
,
4152 /* 58 */ NULL
, NULL
, NULL
, NULL
,
4153 /* 5C */ NULL
, NULL
, NULL
, NULL
,
4154 /* 60 */ NULL
, NULL
, NULL
, NULL
,
4155 /* 64 */ NULL
, NULL
, NULL
, NULL
,
4156 /* 68 */ NULL
, NULL
, NULL
, NULL
,
4157 /* 6C */ NULL
, NULL
, NULL
, NULL
,
4158 /* 70 */ NULL
, NULL
, NULL
, NULL
,
4159 /* 74 */ NULL
, NULL
, NULL
, NULL
,
4160 /* 78 */ NULL
, NULL
, NULL
, NULL
,
4161 /* 7C */ NULL
, NULL
, NULL
, NULL
,
4162 /* 80 */ NULL
, NULL
, NULL
, NULL
,
4163 /* 84 */ NULL
, NULL
, NULL
, NULL
,
4164 /* 88 */ NULL
, NULL
, "pfnacc", NULL
,
4165 /* 8C */ NULL
, NULL
, "pfpnacc", NULL
,
4166 /* 90 */ "pfcmpge", NULL
, NULL
, NULL
,
4167 /* 94 */ "pfmin", NULL
, "pfrcp", "pfrsqrt",
4168 /* 98 */ NULL
, NULL
, "pfsub", NULL
,
4169 /* 9C */ NULL
, NULL
, "pfadd", NULL
,
4170 /* A0 */ "pfcmpgt", NULL
, NULL
, NULL
,
4171 /* A4 */ "pfmax", NULL
, "pfrcpit1", "pfrsqit1",
4172 /* A8 */ NULL
, NULL
, "pfsubr", NULL
,
4173 /* AC */ NULL
, NULL
, "pfacc", NULL
,
4174 /* B0 */ "pfcmpeq", NULL
, NULL
, NULL
,
4175 /* B4 */ "pfmul", NULL
, "pfrcpit2", "pfmulhrw",
4176 /* B8 */ NULL
, NULL
, NULL
, "pswapd",
4177 /* BC */ NULL
, NULL
, NULL
, "pavgusb",
4178 /* C0 */ NULL
, NULL
, NULL
, NULL
,
4179 /* C4 */ NULL
, NULL
, NULL
, NULL
,
4180 /* C8 */ NULL
, NULL
, NULL
, NULL
,
4181 /* CC */ NULL
, NULL
, NULL
, NULL
,
4182 /* D0 */ NULL
, NULL
, NULL
, NULL
,
4183 /* D4 */ NULL
, NULL
, NULL
, NULL
,
4184 /* D8 */ NULL
, NULL
, NULL
, NULL
,
4185 /* DC */ NULL
, NULL
, NULL
, NULL
,
4186 /* E0 */ NULL
, NULL
, NULL
, NULL
,
4187 /* E4 */ NULL
, NULL
, NULL
, NULL
,
4188 /* E8 */ NULL
, NULL
, NULL
, NULL
,
4189 /* EC */ NULL
, NULL
, NULL
, NULL
,
4190 /* F0 */ NULL
, NULL
, NULL
, NULL
,
4191 /* F4 */ NULL
, NULL
, NULL
, NULL
,
4192 /* F8 */ NULL
, NULL
, NULL
, NULL
,
4193 /* FC */ NULL
, NULL
, NULL
, NULL
,
4197 OP_3DNowSuffix (bytemode
, sizeflag
)
4198 int bytemode ATTRIBUTE_UNUSED
;
4199 int sizeflag ATTRIBUTE_UNUSED
;
4201 const char *mnemonic
;
4203 FETCH_DATA (the_info
, codep
+ 1);
4204 /* AMD 3DNow! instructions are specified by an opcode suffix in the
4205 place where an 8-bit immediate would normally go. ie. the last
4206 byte of the instruction. */
4207 obufp
= obuf
+ strlen (obuf
);
4208 mnemonic
= Suffix3DNow
[*codep
++ & 0xff];
4213 /* Since a variable sized modrm/sib chunk is between the start
4214 of the opcode (0x0f0f) and the opcode suffix, we need to do
4215 all the modrm processing first, and don't know until now that
4216 we have a bad opcode. This necessitates some cleaning up. */
4223 static const char *simd_cmp_op
[] = {
4235 OP_SIMD_Suffix (bytemode
, sizeflag
)
4236 int bytemode ATTRIBUTE_UNUSED
;
4237 int sizeflag ATTRIBUTE_UNUSED
;
4239 unsigned int cmp_type
;
4241 FETCH_DATA (the_info
, codep
+ 1);
4242 obufp
= obuf
+ strlen (obuf
);
4243 cmp_type
= *codep
++ & 0xff;
4246 char suffix1
= 'p', suffix2
= 's';
4247 used_prefixes
|= (prefixes
& PREFIX_REPZ
);
4248 if (prefixes
& PREFIX_REPZ
)
4252 used_prefixes
|= (prefixes
& PREFIX_DATA
);
4253 if (prefixes
& PREFIX_DATA
)
4257 used_prefixes
|= (prefixes
& PREFIX_REPNZ
);
4258 if (prefixes
& PREFIX_REPNZ
)
4259 suffix1
= 's', suffix2
= 'd';
4262 sprintf (scratchbuf
, "cmp%s%c%c",
4263 simd_cmp_op
[cmp_type
], suffix1
, suffix2
);
4264 used_prefixes
|= (prefixes
& PREFIX_REPZ
);
4265 oappend (scratchbuf
);
4269 /* We have a bad extension byte. Clean up. */
4277 SIMD_Fixup (extrachar
, sizeflag
)
4279 int sizeflag ATTRIBUTE_UNUSED
;
4281 /* Change movlps/movhps to movhlps/movlhps for 2 register operand
4282 forms of these instructions. */
4285 char *p
= obuf
+ strlen (obuf
);
4288 *(p
- 1) = *(p
- 2);
4289 *(p
- 2) = *(p
- 3);
4290 *(p
- 3) = extrachar
;
4297 /* Throw away prefixes and 1st. opcode byte. */
4298 codep
= insn_codep
+ 1;