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.
This commit is contained in:
Nick Clifton 2004-12-22 14:25:42 +00:00
parent 76a5626062
commit 750bce0ee1
7 changed files with 207 additions and 45 deletions

View file

@ -1,3 +1,11 @@
2004-12-22 Klaus Rudolph <lts-rudolph@gmx.de>
* 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 <amodra@bigpond.net.au> 2004-12-22 Alan Modra <amodra@bigpond.net.au>
* elflink.c (_bfd_elf_merge_symbol): Treat old definitions from * elflink.c (_bfd_elf_merge_symbol): Treat old definitions from

View file

@ -1686,10 +1686,10 @@ enum bfd_architecture
#define bfd_mach_sh_dsp 0x2d #define bfd_mach_sh_dsp 0x2d
#define bfd_mach_sh2a 0x2a #define bfd_mach_sh2a 0x2a
#define bfd_mach_sh2a_nofpu 0x2b #define bfd_mach_sh2a_nofpu 0x2b
#define bfd_mach_sh2a_fake1 0x2a1 #define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
#define bfd_mach_sh2a_fake2 0x2a2 #define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
#define bfd_mach_sh2a_fake3 0x2a3 #define bfd_mach_sh2a_or_sh4 0x2a3
#define bfd_mach_sh2a_fake4 0x2a4 #define bfd_mach_sh2a_or_sh3e 0x2a4
#define bfd_mach_sh2e 0x2e #define bfd_mach_sh2e 0x2e
#define bfd_mach_sh3 0x30 #define bfd_mach_sh3 0x30
#define bfd_mach_sh3_nommu 0x31 #define bfd_mach_sh3_nommu 0x31
@ -3163,6 +3163,18 @@ value of SUBI insn. */
into 22 bits. */ into 22 bits. */
BFD_RELOC_AVR_CALL, 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. */ /* Direct 12 bit. */
BFD_RELOC_390_12, BFD_RELOC_390_12,

View file

@ -3,21 +3,21 @@
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru> Contributed by Denis Chertykov <denisc@overta.ru>
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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h" #include "bfd.h"
#include "sysdep.h" #include "sysdep.h"
@ -323,12 +323,57 @@ static reloc_howto_type elf_avr_howto_table[] =
23, /* bitsize */ 23, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */ complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */ bfd_elf_generic_reloc, /* special_function */
"R_AVR_CALL", /* name */ "R_AVR_CALL", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0xffffffff, /* src_mask */ 0xffffffff, /* src_mask */
0xffffffff, /* dst_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 */ 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_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_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_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 * static reloc_howto_type *
@ -561,6 +609,39 @@ avr_final_link_relocate (howto, input_bfd, input_section,
bfd_put_16 (input_bfd, x, contents); bfd_put_16 (input_bfd, x, contents);
break; 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: case R_AVR_HI8_LDI:
contents += rel->r_offset; contents += rel->r_offset;
srel = (bfd_signed_vma) relocation + rel->r_addend; srel = (bfd_signed_vma) relocation + rel->r_addend;

View file

@ -1,3 +1,13 @@
2004-12-22 Klaus Rudolph <lts-rudolph@gmx.de>
* 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 <andrew.stubbs@st.com> 2004-12-16 Andrew Stubbs <andrew.stubbs@st.com>
* config/tc-sh64.c (shmedia_md_apply_fix3): Add missing * config/tc-sh64.c (shmedia_md_apply_fix3): Add missing

View file

@ -1,6 +1,6 @@
/* tc-avr.c -- Assembler code for the ATMEL AVR /* 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 <denisc@overta.ru> Contributed by Denis Chertykov <denisc@overta.ru>
This file is part of GAS, the GNU Assembler. This file is part of GAS, the GNU Assembler.
@ -557,6 +557,31 @@ avr_operands (opcode, line)
return bin; 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. /* Parse one instruction operand.
Return operand bitmask. Also fixups can be generated. */ Return operand bitmask. Also fixups can be generated. */
@ -695,10 +720,11 @@ avr_operand (opcode, where, op, line)
str = skip_space (str); str = skip_space (str);
if (*str++ == '+') if (*str++ == '+')
{ {
unsigned int x; input_line_pointer = str;
x = avr_get_constant (str, 63); avr_offset_expression (& op_expr);
str = input_line_pointer; 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; break;
@ -750,13 +776,11 @@ avr_operand (opcode, where, op, line)
break; break;
case 'K': case 'K':
{ input_line_pointer = str;
unsigned int x; avr_offset_expression (& op_expr);
str = input_line_pointer;
x = avr_get_constant (str, 63); fix_new_exp (frag_now, where, 3,
str = input_line_pointer; & op_expr, FALSE, BFD_RELOC_AVR_6_ADIW);
op_mask |= (x & 0xf) | ((x & 0x30) << 2);
}
break; break;
case 'S': case 'S':
@ -936,6 +960,27 @@ md_apply_fix3 (fixP, valP, seg)
bfd_putl16 ((bfd_vma) (value >> 1), where); bfd_putl16 ((bfd_vma) (value >> 1), where);
break; 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: case BFD_RELOC_AVR_LO8_LDI:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where); bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
break; break;
@ -1227,10 +1272,8 @@ avr_ldi_expression (exp)
if (x < -255 || x > 255) if (x < -255 || x > 255)
as_warn (_("constant out of 8-bit range: %d"), x); 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 /* Flag to pass `pm' mode between `avr_parse_cons_expression' and

View file

@ -1,3 +1,8 @@
2004-12-22 Klaus Rudolph <lts-rudolph@gmx.de>
* include/elf/avr.h (R_AVR_LDI, R_AVR_6, R_AVR_6_ADIW): New
relocs.
2004-12-16 Richard Sandiford <rsandifo@redhat.com> 2004-12-16 Richard Sandiford <rsandifo@redhat.com>
* v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc. * v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc.

View file

@ -1,22 +1,22 @@
/* AVR ELF support for BFD. /* AVR ELF support for BFD.
Copyright 1999, 2000 Free Software Foundation, Inc. Copyright 1999, 2000, 2004 Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru> Contributed by Denis Chertykov <denisc@overta.ru>
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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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., along with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _ELF_AVR_H #ifndef _ELF_AVR_H
#define _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_HI8_LDI_PM_NEG, 16)
RELOC_NUMBER (R_AVR_HH8_LDI_PM_NEG, 17) RELOC_NUMBER (R_AVR_HH8_LDI_PM_NEG, 17)
RELOC_NUMBER (R_AVR_CALL, 18) 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) END_RELOC_NUMBERS (R_AVR_max)
#endif /* _ELF_AVR_H */ #endif /* _ELF_AVR_H */