From 750bce0ee10ab816e29d8f01733ad000466181fb Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 22 Dec 2004 14:25:42 +0000 Subject: [PATCH] Add support for the new R_AVR_LDI, R_AVR_6 and R_AVR_6_ADIW relocs for the LDI, ADIW/SBIW and LDD/STD instructions. --- bfd/ChangeLog | 8 ++++ bfd/bfd-in2.h | 20 ++++++-- bfd/elf32-avr.c | 109 ++++++++++++++++++++++++++++++++++++------ gas/ChangeLog | 10 ++++ gas/config/tc-avr.c | 71 +++++++++++++++++++++------ include/elf/ChangeLog | 5 ++ include/elf/avr.h | 29 ++++++----- 7 files changed, 207 insertions(+), 45 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cfebc7451d1..0524c5b3b1e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2004-12-22 Klaus Rudolph + + * reloc.c: Add new relocs R_AVR_LDI, R_AVR_6, R_AVR_6_ADIW. + * bfd-in2.h: Regenerate. + * elf32-avr.c (elf_avr_nowto_table): Add the new relocs. + (avr_reloc_map): Likewise. + (avr_final_link_relocate): Likewise. + 2004-12-22 Alan Modra * elflink.c (_bfd_elf_merge_symbol): Treat old definitions from diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8f7a3d42519..d6b65032440 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1686,10 +1686,10 @@ enum bfd_architecture #define bfd_mach_sh_dsp 0x2d #define bfd_mach_sh2a 0x2a #define bfd_mach_sh2a_nofpu 0x2b -#define bfd_mach_sh2a_fake1 0x2a1 -#define bfd_mach_sh2a_fake2 0x2a2 -#define bfd_mach_sh2a_fake3 0x2a3 -#define bfd_mach_sh2a_fake4 0x2a4 +#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1 +#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2 +#define bfd_mach_sh2a_or_sh4 0x2a3 +#define bfd_mach_sh2a_or_sh3e 0x2a4 #define bfd_mach_sh2e 0x2e #define bfd_mach_sh3 0x30 #define bfd_mach_sh3_nommu 0x31 @@ -3163,6 +3163,18 @@ value of SUBI insn. */ into 22 bits. */ BFD_RELOC_AVR_CALL, +/* This is a 16 bit reloc for the AVR that stores all needed bits +for absolute addressing with ldi with overflow check to linktime */ + BFD_RELOC_AVR_LDI, + +/* This is a 6 bit reloc for the AVR that stores offset for ldd/std +instructions */ + BFD_RELOC_AVR_6, + +/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw +instructions */ + BFD_RELOC_AVR_6_ADIW, + /* Direct 12 bit. */ BFD_RELOC_390_12, diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index 1026bfb15c8..9b0e8b53bfa 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -3,21 +3,21 @@ Free Software Foundation, Inc. Contributed by Denis Chertykov -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -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 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 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 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. -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. */ + 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. */ #include "bfd.h" #include "sysdep.h" @@ -323,12 +323,57 @@ static reloc_howto_type elf_avr_howto_table[] = 23, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_CALL", /* name */ FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* A 16 bit absolute relocation of 16 bit address. + For LDI command. */ + HOWTO (R_AVR_LDI, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_LDI", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* A 6 bit absolute relocation of 6 bit offset. + For ldd/sdd command. */ + HOWTO (R_AVR_6, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 6, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_6", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* A 6 bit absolute relocation of 6 bit offset. + For sbiw/adiw command. */ + HOWTO (R_AVR_6_ADIW, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 6, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_6_ADIW", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE) /* pcrel_offset */ }; @@ -360,7 +405,10 @@ struct avr_reloc_map { BFD_RELOC_AVR_LO8_LDI_PM_NEG, R_AVR_LO8_LDI_PM_NEG }, { BFD_RELOC_AVR_HI8_LDI_PM_NEG, R_AVR_HI8_LDI_PM_NEG }, { BFD_RELOC_AVR_HH8_LDI_PM_NEG, R_AVR_HH8_LDI_PM_NEG }, - { BFD_RELOC_AVR_CALL, R_AVR_CALL } + { BFD_RELOC_AVR_CALL, R_AVR_CALL }, + { BFD_RELOC_AVR_LDI, R_AVR_LDI }, + { BFD_RELOC_AVR_6, R_AVR_6 }, + { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW } }; static reloc_howto_type * @@ -561,6 +609,39 @@ avr_final_link_relocate (howto, input_bfd, input_section, bfd_put_16 (input_bfd, x, contents); break; + case R_AVR_LDI: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation + rel->r_addend; + if ((srel & 0xffff) > 255) + /* Remove offset for data/eeprom section. */ + return bfd_reloc_overflow; + x = bfd_get_16 (input_bfd, contents); + x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); + bfd_put_16 (input_bfd, x, contents); + break; + + case R_AVR_6: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation + rel->r_addend; + if (((srel & 0xffff) > 63) || (srel < 0)) + /* Remove offset for data/eeprom section. */ + return bfd_reloc_overflow; + x = bfd_get_16 (input_bfd, contents); + x = (x & 0xd3f8) | ((srel & 7) | ((srel & (3 << 3)) << 7) | ((srel & (1 << 5)) << 8)); + bfd_put_16 (input_bfd, x, contents); + break; + + case R_AVR_6_ADIW: + contents += rel->r_offset; + srel = (bfd_signed_vma) relocation + rel->r_addend; + if (((srel & 0xffff) > 63) || (srel < 0)) + /* Remove offset for data/eeprom section. */ + return bfd_reloc_overflow; + x = bfd_get_16 (input_bfd, contents); + x = (x & 0xff30) | (srel & 0xf) | ((srel & 0x30) << 2); + bfd_put_16 (input_bfd, x, contents); + break; + case R_AVR_HI8_LDI: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; diff --git a/gas/ChangeLog b/gas/ChangeLog index 7018ad5ef7d..47e0ecf80e7 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2004-12-22 Klaus Rudolph + + * config/tc-avr.c: Add support for the new R_AVR_LDI, R_AVR_6 and + R_AVR_6_ADIW relocs for the LDI, ADIW/SBIW and LDD/STD + instructions. + (avr_offset_expression): New function to parse offsets for LDI + instructions. + (avr_operand): Use it. + (md_apply_fix3): Generate the relocs. + 2004-12-16 Andrew Stubbs * config/tc-sh64.c (shmedia_md_apply_fix3): Add missing diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 31bb780c4a2..c0c2e3bdffa 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -1,6 +1,6 @@ /* tc-avr.c -- Assembler code for the ATMEL AVR - Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Contributed by Denis Chertykov This file is part of GAS, the GNU Assembler. @@ -557,6 +557,31 @@ avr_operands (opcode, line) return bin; } +/* Parse for ldd/std offset */ + +static void +avr_offset_expression (expressionS *exp) +{ + char *str = input_line_pointer; + char *tmp; + char op[8]; + + tmp = str; + str = extract_word (str, op, sizeof (op)); + + input_line_pointer = tmp; + expression (exp); + + /* Warn about expressions that fail to use lo8 (). */ + if (exp->X_op == O_constant) + { + int x = exp->X_add_number; + + if (x < -255 || x > 255) + as_warn (_("constant out of 8-bit range: %d"), x); + } +} + /* Parse one instruction operand. Return operand bitmask. Also fixups can be generated. */ @@ -695,10 +720,11 @@ avr_operand (opcode, where, op, line) str = skip_space (str); if (*str++ == '+') { - unsigned int x; - x = avr_get_constant (str, 63); + input_line_pointer = str; + avr_offset_expression (& op_expr); str = input_line_pointer; - op_mask |= (x & 7) | ((x & (3 << 3)) << 7) | ((x & (1 << 5)) << 8); + fix_new_exp (frag_now, where, 3, + &op_expr, FALSE, BFD_RELOC_AVR_6); } } break; @@ -750,13 +776,11 @@ avr_operand (opcode, where, op, line) break; case 'K': - { - unsigned int x; - - x = avr_get_constant (str, 63); - str = input_line_pointer; - op_mask |= (x & 0xf) | ((x & 0x30) << 2); - } + input_line_pointer = str; + avr_offset_expression (& op_expr); + str = input_line_pointer; + fix_new_exp (frag_now, where, 3, + & op_expr, FALSE, BFD_RELOC_AVR_6_ADIW); break; case 'S': @@ -936,6 +960,27 @@ md_apply_fix3 (fixP, valP, seg) bfd_putl16 ((bfd_vma) (value >> 1), where); break; + case BFD_RELOC_AVR_LDI: + if (value > 255) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where); + break; + + case BFD_RELOC_AVR_6: + if ((value > 63) || (value < 0)) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | ((value & 7) | ((value & (3 << 3)) << 7) | ((value & (1 << 5)) << 8)), where); + break; + + case BFD_RELOC_AVR_6_ADIW: + if ((value > 63) || (value < 0)) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("operand out of range: %ld"), value); + bfd_putl16 ((bfd_vma) insn | (value & 0xf) | ((value & 0x30) << 2), where); + break; + case BFD_RELOC_AVR_LO8_LDI: bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where); break; @@ -1227,10 +1272,8 @@ avr_ldi_expression (exp) if (x < -255 || x > 255) as_warn (_("constant out of 8-bit range: %d"), x); } - else - as_warn (_("expression possibly out of 8-bit range")); - return BFD_RELOC_AVR_LO8_LDI; + return BFD_RELOC_AVR_LDI; } /* Flag to pass `pm' mode between `avr_parse_cons_expression' and diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index ea49947f593..0c49618cc08 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,8 @@ +2004-12-22 Klaus Rudolph + + * include/elf/avr.h (R_AVR_LDI, R_AVR_6, R_AVR_6_ADIW): New + relocs. + 2004-12-16 Richard Sandiford * v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc. diff --git a/include/elf/avr.h b/include/elf/avr.h index 59cf0734715..86905cf0999 100644 --- a/include/elf/avr.h +++ b/include/elf/avr.h @@ -1,22 +1,22 @@ /* AVR ELF support for BFD. - Copyright 1999, 2000 Free Software Foundation, Inc. + Copyright 1999, 2000, 2004 Free Software Foundation, Inc. Contributed by Denis Chertykov -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -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 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 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 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. -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. */ + 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. */ #ifndef _ELF_AVR_H #define _ELF_AVR_H @@ -53,6 +53,9 @@ START_RELOC_NUMBERS (elf_avr_reloc_type) RELOC_NUMBER (R_AVR_HI8_LDI_PM_NEG, 16) RELOC_NUMBER (R_AVR_HH8_LDI_PM_NEG, 17) RELOC_NUMBER (R_AVR_CALL, 18) + RELOC_NUMBER (R_AVR_LDI, 19) + RELOC_NUMBER (R_AVR_6, 20) + RELOC_NUMBER (R_AVR_6_ADIW, 21) END_RELOC_NUMBERS (R_AVR_max) #endif /* _ELF_AVR_H */ -- 2.30.2