X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Favr-dis.c;h=9a8ae33a066c1215bbdbd3954eab6cfc14bbcaab;hb=70ad5bfff3eeec62753ac4483bab8b7467dd3dd0;hp=0a2bd361444e0b52b303663cbb506dc27051ba24;hpb=c4f5c3d74c9a860cf1c762e2deb906212a71864c;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/avr-dis.c b/opcodes/avr-dis.c index 0a2bd36144..9a8ae33a06 100644 --- a/opcodes/avr-dis.c +++ b/opcodes/avr-dis.c @@ -1,25 +1,27 @@ /* Disassemble AVR instructions. - Copyright 1999, 2000, 2002, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1999-2014 Free Software Foundation, Inc. Contributed by Denis Chertykov - This program is free software; you can redistribute it and/or modify + This file is part of libopcodes. + + 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 2 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 3, or (at your option) + any later version. - 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. + 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. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include #include "sysdep.h" +#include #include "dis-asm.h" #include "opintl.h" #include "libiberty.h" @@ -43,9 +45,11 @@ const struct avr_opcodes_s avr_opcodes[] = {NULL, NULL, NULL, 0, 0, 0} }; +static const char * comment_start = "0x"; + static int avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constraint, - char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr) + char *opcode_str, char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr) { int ok = 1; *sym = 0; @@ -104,7 +108,7 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra case 0x100e: xyz = "-X"; break; default: xyz = "??"; ok = 0; } - sprintf (buf, xyz); + strcpy (buf, xyz); if (AVR_UNDEF_P (insn)) sprintf (comment, _("undefined")); @@ -113,8 +117,19 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra case 'z': *buf++ = 'Z'; - if (insn & 0x1) - *buf++ = '+'; + + /* Check for post-increment. */ + char *s; + for (s = opcode_str; *s; ++s) + { + if (*s == '+') + { + if (insn & (1 << (15 - (s - opcode_str)))) + *buf++ = '+'; + break; + } + } + *buf = '\0'; if (AVR_UNDEF_P (insn)) sprintf (comment, _("undefined")); @@ -144,8 +159,7 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra 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); - sprintf (comment, "0x"); - + strcpy (comment, comment_start); break; case 'L': @@ -154,17 +168,18 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra 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; @@ -222,6 +237,10 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra } break; + case 'E': + sprintf (buf, "%d", (insn >> 4) & 15); + break; + case '?': *buf = '\0'; break; @@ -267,10 +286,17 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) 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 = xmalloc (nopcodes * sizeof (unsigned int)); @@ -319,7 +345,8 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) if (opcode->name) { - char *op = opcode->constraints; + char *constraints = opcode->constraints; + char *opcode_str = opcode->opcode; insn2 = 0; ok = 1; @@ -330,14 +357,14 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) cmd_len = 4; } - if (*op && *op != '?') + if (*constraints && *constraints != '?') { - int regs = REGISTER_P (*op); + int regs = REGISTER_P (*constraints); - ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0, &sym_op1, &sym_addr1); + ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1); - if (ok && *(++op) == ',') - ok = avr_operand (insn, insn2, addr, *(++op), op2, + if (ok && *(++constraints) == ',') + ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2, *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2); } }