aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2001-11-14 03:15:28 +0000
committerAlan Modra <amodra@gmail.com>2001-11-14 03:15:28 +0000
commite396998b180f1f9b4dea47eef990f696d73cf940 (patch)
tree28af8cb3ac04140e306333d01b87978e4de65401
parentd7dfd553d70967ef7384c7cf5b5474b8c4dc68c2 (diff)
downloadgdb-e396998b180f1f9b4dea47eef990f696d73cf940.zip
gdb-e396998b180f1f9b4dea47eef990f696d73cf940.tar.gz
gdb-e396998b180f1f9b4dea47eef990f696d73cf940.tar.bz2
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.
-rw-r--r--binutils/ChangeLog4
-rw-r--r--binutils/doc/binutils.texi13
-rw-r--r--include/ChangeLog4
-rw-r--r--include/dis-asm.h1
-rw-r--r--opcodes/ChangeLog13
-rw-r--r--opcodes/disassemble.c6
-rw-r--r--opcodes/i386-dis.c199
7 files changed, 159 insertions, 81 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index a35ea64..66cb990 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 45878cb..8a48607 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -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
diff --git a/include/ChangeLog b/include/ChangeLog
index 03663a4..4fea6f2 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -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.
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 96f1dcf..1a4f287 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -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*));
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 84237c0..1805306 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -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
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index ef2756d..3a978d4 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -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
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 9a16d52..6926dab 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -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,51 +1855,127 @@ 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);
}
-static int
+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;
- 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)