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.
This commit is contained in:
Ian Lance Taylor 1999-06-13 17:04:42 +00:00
parent 42751cf354
commit 7d4210142a

View File

@ -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)
{
unsigned char *p;
p = memchr (inbuf, FWAIT_OPCODE, codep - inbuf);
if (p != NULL)
{
(*info->fprintf_func) (info->stream, "fwait");
return (p + 1) - inbuf;
}
}
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)
{
/* This will at least let objdump print the bytes followed
by the error message generated by fetch_data. */
return codep - inbuf;
name = prefix_name (inbuf[0], orig_sizeflag);
if (name != NULL)
(*info->fprintf_func) (info->stream, "%s", name);
else
{
/* Just print the first byte as a .byte instruction. */
(*info->fprintf_func) (info->stream, ".byte 0x%x",
(unsigned int) inbuf[0]);
}
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