/* Disassemble AVR instructions.
- Copyright 1999, 2000 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru>
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This file is part of libopcodes.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include <assert.h>
#include "sysdep.h"
char *name;
char *constraints;
char *opcode;
- int insn_size; /* in words */
+ int insn_size; /* In words. */
int isa;
unsigned int bin_opcode;
};
{NULL, NULL, NULL, 0, 0, 0}
};
-static int avr_operand (unsigned int, unsigned int, unsigned int, int,
- char *, char *, int, int *, bfd_vma *);
+static const char * comment_start = "0x";
static int
avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constraint,
/* Any register operand. */
case 'r':
if (regs)
- insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* source register */
+ insn = (insn & 0xf) | ((insn & 0x0200) >> 5); /* Source register. */
else
- insn = (insn & 0x01f0) >> 4; /* destination register */
+ insn = (insn & 0x01f0) >> 4; /* Destination register. */
sprintf (buf, "r%d", insn);
break;
case 0x100e: xyz = "-X"; break;
default: xyz = "??"; ok = 0;
}
- sprintf (buf, xyz);
+ strcpy (buf, xyz);
if (AVR_UNDEF_P (insn))
sprintf (comment, _("undefined"));
case 'h':
*sym = 1;
*sym_addr = ((((insn & 1) | ((insn & 0x1f0) >> 3)) << 16) | insn2) * 2;
- sprintf (buf, "0x");
+ /* See PR binutils/2454. Ideally we would like to display the hex
+ value of the address only once, but this would mean recoding
+ objdump_print_address() which would affect many targets. */
+ sprintf (buf, "%#lx", (unsigned long) *sym_addr);
+ strcpy (comment, comment_start);
break;
case 'L':
sprintf (buf, ".%+-8d", rel_addr);
*sym = 1;
*sym_addr = pc + 2 + rel_addr;
- sprintf (comment, "0x");
+ strcpy (comment, comment_start);
}
break;
case 'l':
{
int rel_addr = ((((insn >> 3) & 0x7f) ^ 0x40) - 0x40) * 2;
+
sprintf (buf, ".%+-8d", rel_addr);
*sym = 1;
*sym_addr = pc + 2 + rel_addr;
- sprintf (comment, "0x");
+ strcpy (comment, comment_start);
}
break;
case 'P':
{
unsigned int x;
+
x = (insn & 0xf);
x |= (insn >> 5) & 0x30;
sprintf (buf, "0x%02x", x);
return ok;
}
-static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
-
static unsigned short
-avrdis_opcode (addr, info)
- bfd_vma addr;
- disassemble_info *info;
+avrdis_opcode (bfd_vma addr, disassemble_info *info)
{
bfd_byte buffer[2];
int status;
- status = info->read_memory_func(addr, buffer, 2, info);
- if (status != 0)
- {
- info->memory_error_func(status, addr, info);
- return -1;
- }
- return bfd_getl16 (buffer);
+
+ status = info->read_memory_func (addr, buffer, 2, info);
+
+ if (status == 0)
+ return bfd_getl16 (buffer);
+
+ info->memory_error_func (status, addr, info);
+ return -1;
}
int
-print_insn_avr(addr, info)
- bfd_vma addr;
- disassemble_info *info;
+print_insn_avr (bfd_vma addr, disassemble_info *info)
{
unsigned int insn, insn2;
const struct avr_opcodes_s *opcode;
int sym_op1 = 0, sym_op2 = 0;
bfd_vma sym_addr1, sym_addr2;
+
if (!initialized)
{
unsigned int nopcodes;
+ /* PR 4045: Try to avoid duplicating the 0x prefix that
+ objdump_print_addr() will put on addresses when there
+ is no symbol table available. */
+ if (info->symtab_size == 0)
+ comment_start = " ";
+
nopcodes = sizeof (avr_opcodes) / sizeof (struct avr_opcodes_s);
- avr_bin_masks = (unsigned int *)
- xmalloc (nopcodes * sizeof (unsigned int));
+ avr_bin_masks = xmalloc (nopcodes * sizeof (unsigned int));
for (opcode = avr_opcodes, maskptr = avr_bin_masks;
opcode->name;
for (opcode = avr_opcodes, maskptr = avr_bin_masks;
opcode->name;
opcode++, maskptr++)
- {
- if ((insn & *maskptr) == opcode->bin_opcode)
- break;
- }
+ if ((insn & *maskptr) == opcode->bin_opcode)
+ break;
/* Special case: disassemble `ldd r,b+0' as `ld r,b', and
`std b+0,r' as `st b,r' (next entry in the table). */