aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1999-06-13 17:04:42 +0000
committerIan Lance Taylor <ian@airs.com>1999-06-13 17:04:42 +0000
commit7d4210142a44bb1b2f121b7b82db3da3ec9fc374 (patch)
tree84cfa7faffa88dd56fbbdec3907302d0f31a1885
parent42751cf354f999d77243bdf2171602bfc08fce5f (diff)
downloadgdb-7d4210142a44bb1b2f121b7b82db3da3ec9fc374.zip
gdb-7d4210142a44bb1b2f121b7b82db3da3ec9fc374.tar.gz
gdb-7d4210142a44bb1b2f121b7b82db3da3ec9fc374.tar.bz2
Rework last checkin to the following:
* i386-dis.c (FWAIT_OPCODE): Define. (used_prefixes): New static variable. (fetch_data): Don't print an error message if we have already fetched some bytes successfully. (ckprefix): Clear used_prefixes. Use FWAIT_OPCODE, not 0x9b. (prefix_name): New static function. (print_insn_i386): If setjmp fails, indicating a data error, but we have managed to fetch some bytes, print the first one as a prefix or a .byte pseudo-op. If fwait is followed by a non floating point instruction, print the first prefix. Set used_prefixes when prefixes are used. If any prefixes were not used after disassembling the instruction, print the first prefix instead of printing the instruction. (putop): Set used_prefixes when prefixes are used. (append_seg, OP_E, OP_G, OP_REG, OP_I, OP_sI, OP_J): Likewise. (OP_DIR, OP_SIMD_Suffix): Likewise.
-rw-r--r--opcodes/i386-dis.c181
1 files changed, 142 insertions, 39 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index b534698..0dcbc62 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -65,6 +65,10 @@ struct dis_private
/* Flags for the prefixes for the current instruction. See below. */
static int prefixes;
+/* Flags for prefixes which we somehow handled when printing the
+ current instruction. */
+static int used_prefixes;
+
/* Flags stored in PREFIXES. */
#define PREFIX_REPZ 1
#define PREFIX_REPNZ 2
@@ -101,15 +105,11 @@ fetch_data (info, addr)
info);
if (status != 0)
{
- /* 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)
+ /* If we did manage to read at least one byte, then
+ print_insn_i386 will do something sensible. Otherwise, print
+ an error. We do that here because this is where we know
+ STATUS. */
+ if (priv->max_fetched == priv->the_buffer)
(*info->memory_error_func) (status, start, info);
longjmp (priv->bailout, 1);
}
@@ -230,6 +230,7 @@ static void dofloat PARAMS ((int sizeflag));
static int get16 PARAMS ((void));
static int get32 PARAMS ((void));
static void ckprefix PARAMS ((void));
+static const char *prefix_name PARAMS ((int, int));
static void ptr_reg PARAMS ((int, int));
static void BadOp PARAMS ((void));
@@ -1881,6 +1882,7 @@ static void
ckprefix ()
{
prefixes = 0;
+ used_prefixes = 0;
while (1)
{
FETCH_DATA (the_info, codep + 1);
@@ -1938,6 +1940,45 @@ ckprefix ()
}
}
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+ prefix byte. */
+
+static const char *
+prefix_name (pref, sizeflag)
+ int pref;
+ int sizeflag;
+{
+ switch (pref)
+ {
+ case 0xf3:
+ return "repz";
+ case 0xf2:
+ return "repnz";
+ case 0xf0:
+ return "lock";
+ case 0x2e:
+ return "cs";
+ case 0x36:
+ return "ss";
+ case 0x3e:
+ return "ds";
+ case 0x26:
+ return "es";
+ case 0x64:
+ return "fs";
+ case 0x65:
+ return "gs";
+ case 0x66:
+ return (sizeflag & DFLAG) ? "data16" : "data32";
+ case 0x67:
+ return (sizeflag & AFLAG) ? "addr16" : "addr32";
+ case FWAIT_OPCODE:
+ return "fwait";
+ default:
+ return NULL;
+ }
+}
+
static char op1out[100], op2out[100], op3out[100];
static int op_ad, op_index[3];
static unsigned int op_address[3];
@@ -2002,7 +2043,7 @@ print_insn_i386 (pc, info)
int needcomma;
unsigned char need_modrm;
unsigned char uses_f3_prefix;
- int sizeflag;
+ int sizeflag, orig_sizeflag;
struct dis_private priv;
bfd_byte *inbuf = priv.the_buffer;
@@ -2014,6 +2055,7 @@ print_insn_i386 (pc, info)
sizeflag = 0;
else
abort ();
+ orig_sizeflag = sizeflag;
/* The output looks better if we put 6 bytes on a line, since that
puts most long word instructions on a single line. */
@@ -2037,27 +2079,24 @@ print_insn_i386 (pc, info)
if (setjmp (priv.bailout) != 0)
{
+ const char *name;
+
/* 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)
+ means we have an incomplete instruction of some sort. Just
+ print the first byte as a prefix or a .byte pseudo-op. */
+ if (codep > inbuf)
{
- unsigned char *p;
-
- p = memchr (inbuf, FWAIT_OPCODE, codep - inbuf);
- if (p != NULL)
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name != NULL)
+ (*info->fprintf_func) (info->stream, "%s", name);
+ else
{
- (*info->fprintf_func) (info->stream, "fwait");
- return (p + 1) - inbuf;
+ /* Just print the first byte as a .byte instruction. */
+ (*info->fprintf_func) (info->stream, ".byte 0x%x",
+ (unsigned int) inbuf[0]);
}
- }
- 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;
}
return -1;
@@ -2075,10 +2114,15 @@ print_insn_i386 (pc, info)
if ((prefixes & PREFIX_FWAIT)
&& ((*codep < 0xd8) || (*codep > 0xdf)))
{
- /* fwait not followed by floating point instruction. */
- (*info->fprintf_func) (info->stream, "fwait");
- /* There may be other prefixes. Skip any before the fwait. */
- return codep - inbuf;
+ const char *name;
+
+ /* fwait not followed by floating point instruction. Print the
+ first prefix, which is probably fwait itself. */
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
}
if (*codep == 0x0f)
@@ -2103,11 +2147,20 @@ print_insn_i386 (pc, info)
codep++;
if (!uses_f3_prefix && (prefixes & PREFIX_REPZ))
- oappend ("repz ");
+ {
+ oappend ("repz ");
+ used_prefixes |= PREFIX_REPZ;
+ }
if (prefixes & PREFIX_REPNZ)
- oappend ("repnz ");
+ {
+ oappend ("repnz ");
+ used_prefixes |= PREFIX_REPNZ;
+ }
if (prefixes & PREFIX_LOCK)
- oappend ("lock ");
+ {
+ oappend ("lock ");
+ used_prefixes |= PREFIX_LOCK;
+ }
if (prefixes & PREFIX_DATA)
sizeflag ^= DFLAG;
@@ -2119,6 +2172,7 @@ print_insn_i386 (pc, info)
oappend ("addr32 ");
else
oappend ("addr16 ");
+ used_prefixes |= PREFIX_ADDR;
}
if (need_modrm)
@@ -2144,6 +2198,7 @@ print_insn_i386 (pc, info)
break;
case USE_PREFIX_USER_TABLE:
dp = &prefix_user_table[dp->bytemode1][prefixes & PREFIX_REPZ ? 1 : 0];
+ used_prefixes |= (prefixes & PREFIX_REPZ);
break;
default:
oappend (INTERNAL_DISASSEMBLER_ERROR);
@@ -2169,6 +2224,21 @@ print_insn_i386 (pc, info)
(*dp->op3)(dp->bytemode3, sizeflag);
}
+ /* See if any prefixes were not used. If so, print the first one
+ separately. If we don't do this, we'll wind up printing an
+ instruction stream which does not precisely correspond to the
+ bytes we are disassembling. */
+ if ((prefixes & ~used_prefixes) != 0)
+ {
+ const char *name;
+
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
+ }
+
obufp = obuf + strlen (obuf);
for (i = strlen (obuf); i < 6; i++)
oappend (" ");
@@ -2656,6 +2726,8 @@ putop (template, sizeflag)
case 'N':
if ((prefixes & PREFIX_FWAIT) == 0)
*obufp++ = 'n';
+ else
+ used_prefixes |= PREFIX_FWAIT;
break;
case 'P':
if (intel_syntax)
@@ -2670,6 +2742,7 @@ putop (template, sizeflag)
*obufp++ = 'l';
else
*obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
}
break;
case 'Q':
@@ -2685,6 +2758,7 @@ putop (template, sizeflag)
*obufp++ = 'l';
else
*obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
}
break;
case 'R':
@@ -2708,6 +2782,7 @@ putop (template, sizeflag)
else
*obufp++ = 'w';
}
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
case 'S':
if (intel_syntax)
@@ -2719,6 +2794,7 @@ putop (template, sizeflag)
*obufp++ = 'l';
else
*obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
}
#endif
break;
@@ -2740,6 +2816,7 @@ putop (template, sizeflag)
*obufp++ = 'w';
}
}
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
}
}
@@ -2758,17 +2835,35 @@ static void
append_seg ()
{
if (prefixes & PREFIX_CS)
- oappend ("%cs:");
+ {
+ oappend ("%cs:");
+ used_prefixes |= PREFIX_CS;
+ }
if (prefixes & PREFIX_DS)
- oappend ("%ds:");
+ {
+ oappend ("%ds:");
+ used_prefixes |= PREFIX_DS;
+ }
if (prefixes & PREFIX_SS)
- oappend ("%ss:");
+ {
+ oappend ("%ss:");
+ used_prefixes |= PREFIX_SS;
+ }
if (prefixes & PREFIX_ES)
- oappend ("%es:");
+ {
+ oappend ("%es:");
+ used_prefixes |= PREFIX_ES;
+ }
if (prefixes & PREFIX_FS)
- oappend ("%fs:");
+ {
+ oappend ("%fs:");
+ used_prefixes |= PREFIX_FS;
+ }
if (prefixes & PREFIX_GS)
- oappend ("%gs:");
+ {
+ oappend ("%gs:");
+ used_prefixes |= PREFIX_GS;
+ }
}
static void
@@ -2809,6 +2904,7 @@ OP_E (bytemode, sizeflag)
oappend (names32[rm]);
else
oappend (names16[rm]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
case 0:
if ( !(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */))
@@ -3031,6 +3127,7 @@ OP_G (bytemode, sizeflag)
oappend (names32[reg]);
else
oappend (names16[reg]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
default:
oappend (INTERNAL_DISASSEMBLER_ERROR);
@@ -3100,6 +3197,7 @@ OP_REG (code, sizeflag)
s = names32[code - eAX_reg];
else
s = names16[code - eAX_reg];
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
default:
s = INTERNAL_DISASSEMBLER_ERROR;
@@ -3126,6 +3224,7 @@ OP_I (bytemode, sizeflag)
op = get32 ();
else
op = get16 ();
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
case w_mode:
op = get16 ();
@@ -3167,6 +3266,7 @@ OP_sI (bytemode, sizeflag)
if ((op & 0x8000) != 0)
op -= 0x10000;
}
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
case w_mode:
op = get16 ();
@@ -3211,6 +3311,7 @@ OP_J (bytemode, sizeflag)
displacement is added! */
mask = 0xffff;
}
+ used_prefixes |= (prefixes & PREFIX_DATA);
break;
default:
oappend (INTERNAL_DISASSEMBLER_ERROR);
@@ -3253,6 +3354,7 @@ OP_DIR (dummy, sizeflag)
offset = get16 ();
seg = get16 ();
}
+ used_prefixes |= (prefixes & PREFIX_DATA);
sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
oappend (scratchbuf);
}
@@ -3549,6 +3651,7 @@ OP_SIMD_Suffix (bytemode, sizeflag)
sprintf (scratchbuf, "cmp%s%cs",
simd_cmp_op[cmp_type],
prefixes & PREFIX_REPZ ? 's' : 'p');
+ used_prefixes |= (prefixes & PREFIX_REPZ);
oappend (scratchbuf);
}
else