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> 2001-11-13 Keith Walker <keith.walker@arm.com>
* readelf.c (read_and_display_attr_value): New function to * 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 useful when attempting to disassemble thumb code produced by other
compilers. 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 @item -p
@itemx --private-headers @itemx --private-headers
Print information that is specific to the object file format. The exact 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> 2001-11-11 Timothy Wall <twall@alum.mit.edu>
* dis-asm.h: Fix comment to refer to octets rather than bytes. * 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_big_mips PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_little_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_att PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_i386_intel 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*)); 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> 2001-11-11 Timothy Wall <twall@alum.mit.edu>
* tic54x-dis.c: Use revised opcode structure. Export opcode * tic54x-dis.c: Use revised opcode structure. Export opcode

View file

@ -150,11 +150,7 @@ disassembler (abfd)
#endif #endif
#ifdef ARCH_i386 #ifdef ARCH_i386
case bfd_arch_i386: case bfd_arch_i386:
if (bfd_get_mach (abfd) == bfd_mach_i386_i386_intel_syntax disassemble = print_insn_i386;
|| bfd_get_mach (abfd) == bfd_mach_x86_64_intel_syntax)
disassemble = print_insn_i386_intel;
else
disassemble = print_insn_i386_att;
break; break;
#endif #endif
#ifdef ARCH_i860 #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 int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
static void ckprefix PARAMS ((void)); static void ckprefix PARAMS ((void));
static const char *prefix_name PARAMS ((int, int)); 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 dofloat PARAMS ((int));
static void OP_ST PARAMS ((int, int)); static void OP_ST PARAMS ((int, int));
static void OP_STi PARAMS ((int, int)); static void OP_STi PARAMS ((int, int));
@ -101,6 +101,7 @@ struct dis_private {
bfd_byte *max_fetched; bfd_byte *max_fetched;
bfd_byte the_buffer[MAXLEN]; bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start; bfd_vma insn_start;
int orig_sizeflag;
jmp_buf bailout; jmp_buf bailout;
}; };
@ -298,9 +299,7 @@ fetch_data (info, addr)
#define loop_jcxz_flag NULL, loop_jcxz_mode #define loop_jcxz_flag NULL, loop_jcxz_mode
/* bits in sizeflag */ /* bits in sizeflag */
#if 0 /* Leave undefined until someone adds the extra flag to objdump. */
#define SUFFIX_ALWAYS 4 #define SUFFIX_ALWAYS 4
#endif
#define AFLAG 2 #define AFLAG 2
#define DFLAG 1 #define DFLAG 1
@ -442,9 +441,9 @@ struct dis386 {
'N' => print 'n' if instruction has no wait "prefix" 'N' => print 'n' if instruction has no wait "prefix"
'O' => print 'd', or 'o' 'O' => print 'd', or 'o'
'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
or suffix_always is true . or suffix_always is true. print 'q' if rex prefix is present.
print 'q' if rex prefix is present. 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always is true . is true
'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode) 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
'S' => print 'w', 'l' or 'q' if suffix_always is true 'S' => print 'w', 'l' or 'q' if suffix_always is true
'T' => print 'q' in 64bit mode and behave as 'P' otherwise '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 separator_char;
static char scale_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 int
print_insn_i386_att (pc, info) print_insn_i386_att (pc, info)
bfd_vma pc; bfd_vma pc;
disassemble_info *info; disassemble_info *info;
{ {
intel_syntax = 0; 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 int
@ -1864,6 +1855,101 @@ print_insn_i386_intel (pc, info)
disassemble_info *info; disassemble_info *info;
{ {
intel_syntax = 1; intel_syntax = 1;
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 (pc, info)
bfd_vma pc;
disassemble_info *info;
{
const struct dis386 *dp;
int i;
int two_source_ops;
char *first, *second, *third;
int needcomma;
unsigned char uses_SSE_prefix;
int sizeflag;
const char *p;
struct dis_private priv;
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)
priv.orig_sizeflag = AFLAG | DFLAG;
else if (info->mach == bfd_mach_i386_i8086)
priv.orig_sizeflag = 0;
else
abort ();
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; names64 = intel_names64;
names32 = intel_names32; names32 = intel_names32;
names16 = intel_names16; names16 = intel_names16;
@ -1875,40 +1961,21 @@ print_insn_i386_intel (pc, info)
close_char = ']'; close_char = ']';
separator_char = '+'; separator_char = '+';
scale_char = '*'; scale_char = '*';
}
return print_insn_i386 (pc, info);
}
static int
print_insn_i386 (pc, info)
bfd_vma pc;
disassemble_info *info;
{
const struct dis386 *dp;
int i;
int two_source_ops;
char *first, *second, *third;
int needcomma;
unsigned char uses_SSE_prefix;
VOLATILE int sizeflag;
VOLATILE int orig_sizeflag;
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 (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;
else if (info->mach == bfd_mach_i386_i8086)
sizeflag = 0;
else else
abort (); {
orig_sizeflag = sizeflag; 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 /* The output looks better if we put 7 bytes on a line, since that
puts most long word instructions on a single line. */ puts most long word instructions on a single line. */
@ -1927,8 +1994,8 @@ print_insn_i386 (pc, info)
the_info = info; the_info = info;
start_pc = pc; start_pc = pc;
start_codep = inbuf; start_codep = priv.the_buffer;
codep = inbuf; codep = priv.the_buffer;
if (setjmp (priv.bailout) != 0) if (setjmp (priv.bailout) != 0)
{ {
@ -1937,16 +2004,16 @@ print_insn_i386 (pc, info)
/* Getting here means we tried for data but didn't get it. That /* Getting here means we tried for data but didn't get it. That
means we have an incomplete instruction of some sort. Just means we have an incomplete instruction of some sort. Just
print the first byte as a prefix or a .byte pseudo-op. */ print the first byte as a prefix or a .byte pseudo-op. */
if (codep > inbuf) 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) if (name != NULL)
(*info->fprintf_func) (info->stream, "%s", name); (*info->fprintf_func) (info->stream, "%s", name);
else else
{ {
/* Just print the first byte as a .byte instruction. */ /* Just print the first byte as a .byte instruction. */
(*info->fprintf_func) (info->stream, ".byte 0x%x", (*info->fprintf_func) (info->stream, ".byte 0x%x",
(unsigned int) inbuf[0]); (unsigned int) priv.the_buffer[0]);
} }
return 1; return 1;
@ -1959,6 +2026,7 @@ print_insn_i386 (pc, info)
ckprefix (); ckprefix ();
insn_codep = codep; insn_codep = codep;
sizeflag = priv.orig_sizeflag;
FETCH_DATA (info, codep + 1); FETCH_DATA (info, codep + 1);
two_source_ops = (*codep == 0x62) || (*codep == 0xc8); 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 /* fwait not followed by floating point instruction. Print the
first prefix, which is probably fwait itself. */ 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) if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR; name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name); (*info->fprintf_func) (info->stream, "%s", name);
@ -2116,7 +2184,7 @@ print_insn_i386 (pc, info)
{ {
const char *name; const char *name;
name = prefix_name (inbuf[0], orig_sizeflag); name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL) if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR; name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name); (*info->fprintf_func) (info->stream, "%s", name);
@ -2125,7 +2193,7 @@ print_insn_i386 (pc, info)
if (rex & ~rex_used) if (rex & ~rex_used)
{ {
const char *name; const char *name;
name = prefix_name (rex | 0x40, orig_sizeflag); name = prefix_name (rex | 0x40, priv.orig_sizeflag);
if (name == NULL) if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR; name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s ", name); (*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 (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+ op_address[op_index[i]]), info); + op_address[op_index[i]]), info);
} }
return codep - inbuf; return codep - priv.the_buffer;
} }
static const char *float_mem[] = { static const char *float_mem[] = {
@ -2548,20 +2616,14 @@ putop (template, sizeflag)
case 'A': case 'A':
if (intel_syntax) if (intel_syntax)
break; break;
if (mod != 3 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
*obufp++ = 'b'; *obufp++ = 'b';
break; break;
case 'B': case 'B':
if (intel_syntax) if (intel_syntax)
break; break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS) if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'b'; *obufp++ = 'b';
#endif
break; break;
case 'E': /* For jcxz/jecxz */ case 'E': /* For jcxz/jecxz */
if (sizeflag & AFLAG) if (sizeflag & AFLAG)
@ -2571,11 +2633,7 @@ putop (template, sizeflag)
case 'F': case 'F':
if (intel_syntax) if (intel_syntax)
break; break;
if ((prefixes & PREFIX_ADDR) if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
{ {
if (sizeflag & AFLAG) if (sizeflag & AFLAG)
*obufp++ = 'l'; *obufp++ = 'l';
@ -2602,10 +2660,8 @@ putop (template, sizeflag)
case 'L': case 'L':
if (intel_syntax) if (intel_syntax)
break; break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS) if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'l'; *obufp++ = 'l';
#endif
break; break;
case 'N': case 'N':
if ((prefixes & PREFIX_FWAIT) == 0) if ((prefixes & PREFIX_FWAIT) == 0)
@ -2634,10 +2690,7 @@ putop (template, sizeflag)
break; break;
if ((prefixes & PREFIX_DATA) if ((prefixes & PREFIX_DATA)
|| (rex & REX_MODE64) || (rex & REX_MODE64)
#ifdef SUFFIX_ALWAYS || (sizeflag & SUFFIX_ALWAYS))
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
{ {
USED_REX (REX_MODE64); USED_REX (REX_MODE64);
if (rex & REX_MODE64) if (rex & REX_MODE64)
@ -2665,11 +2718,7 @@ putop (template, sizeflag)
if (intel_syntax) if (intel_syntax)
break; break;
USED_REX (REX_MODE64); USED_REX (REX_MODE64);
if (mod != 3 if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
#ifdef SUFFIX_ALWAYS
|| (sizeflag & SUFFIX_ALWAYS)
#endif
)
{ {
if (rex & REX_MODE64) if (rex & REX_MODE64)
*obufp++ = 'q'; *obufp++ = 'q';
@ -2718,7 +2767,6 @@ putop (template, sizeflag)
case 'S': case 'S':
if (intel_syntax) if (intel_syntax)
break; break;
#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS) if (sizeflag & SUFFIX_ALWAYS)
{ {
if (rex & REX_MODE64) if (rex & REX_MODE64)
@ -2732,7 +2780,6 @@ putop (template, sizeflag)
used_prefixes |= (prefixes & PREFIX_DATA); used_prefixes |= (prefixes & PREFIX_DATA);
} }
} }
#endif
break; break;
case 'X': case 'X':
if (prefixes & PREFIX_DATA) if (prefixes & PREFIX_DATA)