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:
parent
42751cf354
commit
7d4210142a
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user