aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r--opcodes/i386-dis.c81
1 files changed, 60 insertions, 21 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 7cda14e..b534698 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -47,7 +47,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define UNIXWARE_COMPAT 1
#endif
-
static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
struct dis_private
@@ -59,6 +58,27 @@ struct dis_private
jmp_buf bailout;
};
+/* The opcode for the fwait instruction, which we treat as a prefix
+ when we can. */
+#define FWAIT_OPCODE (0x9b)
+
+/* Flags for the prefixes for the current instruction. See below. */
+static int prefixes;
+
+/* Flags stored in PREFIXES. */
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADDR 0x400
+#define PREFIX_FWAIT 0x800
+
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
to ADDR (exclusive) are valid. Returns 1 for success, longjmps
on error. */
@@ -81,7 +101,16 @@ fetch_data (info, addr)
info);
if (status != 0)
{
- (*info->memory_error_func) (status, start, info);
+ /* If we have found an fwait prefix and an fwait opcode, then
+ print_insn_i386 will arrange to print an instruction after we
+ longjmp, and we don't want to print an error message here.
+ This hack is required because we treat fwait as a prefix, but
+ since fwait is really an instruction we want to print a
+ standalone fwait correctly. */
+ if ((prefixes & PREFIX_FWAIT) == 0
+ || memchr (priv->the_buffer, FWAIT_OPCODE,
+ priv->max_fetched - priv->the_buffer) == NULL)
+ (*info->memory_error_func) (status, start, info);
longjmp (priv->bailout, 1);
}
else
@@ -1848,21 +1877,6 @@ static const struct dis386 prefix_user_table[][2] = {
#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
-#define PREFIX_REPZ 1
-#define PREFIX_REPNZ 2
-#define PREFIX_LOCK 4
-#define PREFIX_CS 8
-#define PREFIX_SS 0x10
-#define PREFIX_DS 0x20
-#define PREFIX_ES 0x40
-#define PREFIX_FS 0x80
-#define PREFIX_GS 0x100
-#define PREFIX_DATA 0x200
-#define PREFIX_ADDR 0x400
-#define PREFIX_FWAIT 0x800
-
-static int prefixes;
-
static void
ckprefix ()
{
@@ -1905,7 +1919,7 @@ ckprefix ()
case 0x67:
prefixes |= PREFIX_ADDR;
break;
- case 0x9b:
+ case FWAIT_OPCODE:
/* fwait is really an instruction. If there are prefixes
before the fwait, they belong to the fwait, *not* to the
following instruction. */
@@ -2008,9 +2022,6 @@ print_insn_i386 (pc, info)
info->private_data = (PTR) &priv;
priv.max_fetched = priv.the_buffer;
priv.insn_start = pc;
- if (setjmp (priv.bailout) != 0)
- /* Error return. */
- return -1;
obuf[0] = 0;
op1out[0] = 0;
@@ -2024,6 +2035,34 @@ print_insn_i386 (pc, info)
start_codep = inbuf;
codep = inbuf;
+ if (setjmp (priv.bailout) != 0)
+ {
+ /* Getting here means we tried for data but didn't get it. That
+ means we have an incomplete instruction of some sort.
+ However, we need to check at least one case here: fwait is a
+ complete instruction, although we treat it as a prefix. */
+ if (prefixes & PREFIX_FWAIT)
+ {
+ unsigned char *p;
+
+ p = memchr (inbuf, FWAIT_OPCODE, codep - inbuf);
+ if (p != NULL)
+ {
+ (*info->fprintf_func) (info->stream, "fwait");
+ return (p + 1) - inbuf;
+ }
+ }
+
+ if (codep > inbuf)
+ {
+ /* This will at least let objdump print the bytes followed
+ by the error message generated by fetch_data. */
+ return codep - inbuf;
+ }
+
+ return -1;
+ }
+
ckprefix ();
insn_codep = codep;