binutils/ChangeLog

* doc/binutils.texi (objdump): Document x86 -M options.
include/ChangeLog
 	* dis-asm.h (print_insn_i386): Declare.
opcodes/ChangeLog
	* disassemble.c (disassembler): Call print_insn_i386.
	* i386-dis.c (SUFFIX_ALWAYS): Define.
	(struct dis_private): Add orig_sizeflag.
	(print_insn_i386): Make it a wrapper, calling..
	(print_insn): ..The old body of print_insn_i386.  Avoid longjmp
	warning without using volatile by moving orig_sizeflag to priv,
	and removing inbuf.  Parse disassembler_options.
	(print_insn_i386_att, print_insn_i386_intel): Move initialisation
	code to print_insn.
	(putop): Remove #ifdef SUFFIX_ALWAYS.
This commit is contained in:
Alan Modra 2001-11-14 03:15:28 +00:00
parent d7dfd553d7
commit e396998b18
7 changed files with 157 additions and 79 deletions

View file

@ -1,3 +1,7 @@
2001-11-14 Alan Modra <amodra@bigpond.net.au>
* doc/binutils.texi (objdump): Document x86 -M options.
2001-11-13 Keith Walker <keith.walker@arm.com>
* readelf.c (read_and_display_attr_value): New function to

View file

@ -1569,6 +1569,19 @@ using the switch @option{--disassembler-options=force-thumb}. This can be
useful when attempting to disassemble thumb code produced by other
compilers.
For the x86, some of the options duplicate functions of the @option{-m}
switch, but allow finer grained control. Multiple selections from the
following may be specified as a comma separated string.
@option{x86_64}, @option{i386} and @option{i8086} select disassembly for
the given architecture. @option{intel} and @option{att} select between
intel syntax mode and AT&T syntax mode. @option{addr32},
@option{addr16}, @option{data32} and @option{data16} specify the default
address size and operand size. These four options will be overridden if
@option{x86_64}, @option{i386} or @option{i8086} appear later in the
option string. Lastly, @option{suffix}, when in AT&T mode,
instructs the dissassembler to print a mnemonic suffix even when the
suffix could be inferred by the operands.
@item -p
@itemx --private-headers
Print information that is specific to the object file format. The exact

View file

@ -1,3 +1,7 @@
2001-11-14 Alan Modra <amodra@bigpond.net.au>
* dis-asm.h (print_insn_i386): Declare.
2001-11-11 Timothy Wall <twall@alum.mit.edu>
* dis-asm.h: Fix comment to refer to octets rather than bytes.

View file

@ -177,6 +177,7 @@ typedef int (*disassembler_ftype)
extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info *));
extern int print_insn_i386_att PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_i386_intel PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_ia64 PARAMS ((bfd_vma, disassemble_info*));

View file

@ -1,3 +1,16 @@
2001-11-14 Alan Modra <amodra@bigpond.net.au>
* disassemble.c (disassembler): Call print_insn_i386.
* i386-dis.c (SUFFIX_ALWAYS): Define.
(struct dis_private): Add orig_sizeflag.
(print_insn_i386): Make it a wrapper, calling..
(print_insn): ..The old body of print_insn_i386. Avoid longjmp
warning without using volatile by moving orig_sizeflag to priv,
and removing inbuf. Parse disassembler_options.
(print_insn_i386_att, print_insn_i386_intel): Move initialisation
code to print_insn.
(putop): Remove #ifdef SUFFIX_ALWAYS.
2001-11-11 Timothy Wall <twall@alum.mit.edu>
* tic54x-dis.c: Use revised opcode structure. Export opcode

View file

@ -150,11 +150,7 @@ disassembler (abfd)
#endif
#ifdef ARCH_i386
case bfd_arch_i386:
if (bfd_get_mach (abfd) == bfd_mach_i386_i386_intel_syntax
|| bfd_get_mach (abfd) == bfd_mach_x86_64_intel_syntax)
disassemble = print_insn_i386_intel;
else
disassemble = print_insn_i386_att;
disassemble = print_insn_i386;
break;
#endif
#ifdef ARCH_i860

View file

@ -52,7 +52,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
static void ckprefix PARAMS ((void));
static const char *prefix_name PARAMS ((int, int));
static int print_insn_i386 PARAMS ((bfd_vma, disassemble_info *));
static int print_insn PARAMS ((bfd_vma, disassemble_info *));
static void dofloat PARAMS ((int));
static void OP_ST PARAMS ((int, int));
static void OP_STi PARAMS ((int, int));
@ -101,6 +101,7 @@ struct dis_private {
bfd_byte *max_fetched;
bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start;
int orig_sizeflag;
jmp_buf bailout;
};
@ -298,9 +299,7 @@ fetch_data (info, addr)
#define loop_jcxz_flag NULL, loop_jcxz_mode
/* bits in sizeflag */
#if 0 /* Leave undefined until someone adds the extra flag to objdump. */
#define SUFFIX_ALWAYS 4
#endif
#define AFLAG 2
#define DFLAG 1
@ -442,9 +441,9 @@ struct dis386 {
'N' => print 'n' if instruction has no wait "prefix"
'O' => print 'd', or 'o'
'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
or suffix_always is true
print 'q' if rex prefix is present.
'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always is true
. or suffix_always is true. print 'q' if rex prefix is present.
'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
. is true
'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
'S' => print 'w', 'l' or 'q' if suffix_always is true
'T' => print 'q' in 64bit mode and behave as 'P' otherwise
@ -1837,25 +1836,17 @@ static char close_char;
static char separator_char;
static char scale_char;
/* Here for backwards compatibility. When gdb stops using
print_insn_i386_att and print_insn_i386_intel these functions can
disappear, and print_insn_i386 be merged into print_insn. */
int
print_insn_i386_att (pc, info)
bfd_vma pc;
disassemble_info *info;
{
intel_syntax = 0;
names64 = att_names64;
names32 = att_names32;
names16 = att_names16;
names8 = att_names8;
names8rex = att_names8rex;
names_seg = att_names_seg;
index16 = att_index16;
open_char = '(';
close_char = ')';
separator_char = ',';
scale_char = ',';
return print_insn_i386 (pc, info);
return print_insn (pc, info);
}
int
@ -1864,23 +1855,22 @@ print_insn_i386_intel (pc, info)
disassemble_info *info;
{
intel_syntax = 1;
names64 = intel_names64;
names32 = intel_names32;
names16 = intel_names16;
names8 = intel_names8;
names8rex = intel_names8rex;
names_seg = intel_names_seg;
index16 = intel_index16;
open_char = '[';
close_char = ']';
separator_char = '+';
scale_char = '*';
return print_insn_i386 (pc, info);
return print_insn (pc, info);
}
int
print_insn_i386 (pc, info)
bfd_vma pc;
disassemble_info *info;
{
intel_syntax = -1;
return print_insn (pc, info);
}
static int
print_insn_i386 (pc, info)
print_insn (pc, info)
bfd_vma pc;
disassemble_info *info;
{
@ -1890,25 +1880,102 @@ print_insn_i386 (pc, info)
char *first, *second, *third;
int needcomma;
unsigned char uses_SSE_prefix;
VOLATILE int sizeflag;
VOLATILE int orig_sizeflag;
int sizeflag;
const char *p;
struct dis_private priv;
bfd_byte *inbuf = priv.the_buffer;
mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
|| info->mach == bfd_mach_x86_64);
if (intel_syntax == -1)
intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
|| info->mach == bfd_mach_x86_64_intel_syntax);
if (info->mach == bfd_mach_i386_i386
|| info->mach == bfd_mach_x86_64
|| info->mach == bfd_mach_i386_i386_intel_syntax
|| info->mach == bfd_mach_x86_64_intel_syntax)
sizeflag = AFLAG | DFLAG;
priv.orig_sizeflag = AFLAG | DFLAG;
else if (info->mach == bfd_mach_i386_i8086)
sizeflag = 0;
priv.orig_sizeflag = 0;
else
abort ();
orig_sizeflag = sizeflag;
for (p = info->disassembler_options; p != NULL; )
{
if (strncmp (p, "x86_64", 6) == 0)
{
mode_64bit = 1;
priv.orig_sizeflag = AFLAG | DFLAG;
}
else if (strncmp (p, "i386", 4) == 0)
{
mode_64bit = 0;
priv.orig_sizeflag = AFLAG | DFLAG;
}
else if (strncmp (p, "i8086", 5) == 0)
{
mode_64bit = 0;
priv.orig_sizeflag = 0;
}
else if (strncmp (p, "intel", 5) == 0)
{
intel_syntax = 1;
}
else if (strncmp (p, "att", 3) == 0)
{
intel_syntax = 0;
}
else if (strncmp (p, "addr", 4) == 0)
{
if (p[4] == '1' && p[5] == '6')
priv.orig_sizeflag &= ~AFLAG;
else if (p[4] == '3' && p[5] == '2')
priv.orig_sizeflag |= AFLAG;
}
else if (strncmp (p, "data", 4) == 0)
{
if (p[4] == '1' && p[5] == '6')
priv.orig_sizeflag &= ~DFLAG;
else if (p[4] == '3' && p[5] == '2')
priv.orig_sizeflag |= DFLAG;
}
else if (strncmp (p, "suffix", 6) == 0)
priv.orig_sizeflag |= SUFFIX_ALWAYS;
p = strchr (p, ',');
if (p != NULL)
p++;
}
if (intel_syntax)
{
names64 = intel_names64;
names32 = intel_names32;
names16 = intel_names16;
names8 = intel_names8;
names8rex = intel_names8rex;
names_seg = intel_names_seg;
index16 = intel_index16;
open_char = '[';
close_char = ']';
separator_char = '+';
scale_char = '*';
}
else
{
names64 = att_names64;
names32 = att_names32;
names16 = att_names16;
names8 = att_names8;
names8rex = att_names8rex;
names_seg = att_names_seg;
index16 = att_index16;
open_char = '(';
close_char = ')';
separator_char = ',';
scale_char = ',';
}
/* The output looks better if we put 7 bytes on a line, since that
puts most long word instructions on a single line. */
@ -1927,26 +1994,26 @@ print_insn_i386 (pc, info)
the_info = info;
start_pc = pc;
start_codep = inbuf;
codep = inbuf;
start_codep = priv.the_buffer;
codep = priv.the_buffer;
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. Just
print the first byte as a prefix or a .byte pseudo-op. */
if (codep > 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 > priv.the_buffer)
{
name = prefix_name (inbuf[0], orig_sizeflag);
name = prefix_name (priv.the_buffer[0], priv.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]);
(unsigned int) priv.the_buffer[0]);
}
return 1;
@ -1959,6 +2026,7 @@ print_insn_i386 (pc, info)
ckprefix ();
insn_codep = codep;
sizeflag = priv.orig_sizeflag;
FETCH_DATA (info, codep + 1);
two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
@ -1970,7 +2038,7 @@ print_insn_i386 (pc, info)
/* fwait not followed by floating point instruction. Print the
first prefix, which is probably fwait itself. */
name = prefix_name (inbuf[0], orig_sizeflag);
name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name);
@ -2116,7 +2184,7 @@ print_insn_i386 (pc, info)
{
const char *name;
name = prefix_name (inbuf[0], orig_sizeflag);
name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name);
@ -2125,7 +2193,7 @@ print_insn_i386 (pc, info)
if (rex & ~rex_used)
{
const char *name;
name = prefix_name (rex | 0x40, orig_sizeflag);
name = prefix_name (rex | 0x40, priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s ", name);
@ -2189,7 +2257,7 @@ print_insn_i386 (pc, info)
(*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+ op_address[op_index[i]]), info);
}
return codep - inbuf;
return codep - priv.the_buffer;
}
static const char *float_mem[] = {
@ -2548,20 +2616,14 @@ putop (template, sizeflag)
case 'A':
if (intel_syntax)
break;
if (mod != 3
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
*obufp++ = 'b';
break;
case 'B':
if (intel_syntax)
break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'b';
#endif
break;
case 'E': /* For jcxz/jecxz */
if (sizeflag & AFLAG)
@ -2571,11 +2633,7 @@ putop (template, sizeflag)
case 'F':
if (intel_syntax)
break;
if ((prefixes & PREFIX_ADDR)
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
{
if (sizeflag & AFLAG)
*obufp++ = 'l';
@ -2602,10 +2660,8 @@ putop (template, sizeflag)
case 'L':
if (intel_syntax)
break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'l';
#endif
break;
case 'N':
if ((prefixes & PREFIX_FWAIT) == 0)
@ -2634,10 +2690,7 @@ putop (template, sizeflag)
break;
if ((prefixes & PREFIX_DATA)
|| (rex & REX_MODE64)
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
|| (sizeflag & SUFFIX_ALWAYS))
{
USED_REX (REX_MODE64);
if (rex & REX_MODE64)
@ -2665,11 +2718,7 @@ putop (template, sizeflag)
if (intel_syntax)
break;
USED_REX (REX_MODE64);
if (mod != 3
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
{
if (rex & REX_MODE64)
*obufp++ = 'q';
@ -2718,7 +2767,6 @@ putop (template, sizeflag)
case 'S':
if (intel_syntax)
break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
{
if (rex & REX_MODE64)
@ -2732,7 +2780,6 @@ putop (template, sizeflag)
used_prefixes |= (prefixes & PREFIX_DATA);
}
}
#endif
break;
case 'X':
if (prefixes & PREFIX_DATA)