From 99700d6febe92cfcd0ce5b62cad8472020e6c248 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 11 May 2012 12:59:23 +0000 Subject: [PATCH] PR 13503 * reloc.c: Add new ENUM for BFD_RELOC_AVR_8_LO, BFD_RELOC_AVR_8_HI, BFD_RELOC_AVR_8_HHI. * bfd-in2.h: Regenerate. * libbfd.h: Regenrate. * elf32-avr.c (elf_avr_howto_table): Add entries for R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8. (avr_reloc_map): Add RELOC mappings for R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8. * config/tc-avr.c (exp_mod_pm): Remove variable. (exp_mod_data_t): New typedef. (pexp_mod_data, exp_mod_data): New variables. (avr_parse_cons_expression): Scan through exp_mod_data[] to find data expression modifiers "pm", "gs", "lo8", hi8", "hhi8", "hh8" and set pexp_mod_data accordingly to be used in avr_cons_fix_new. (avr_cons_fix_new): Handle new data expression modifiers shipped in pexp_mod_data. (md_apply_fix): Handle BFD_RELOC_AVR_8_LO, BFD_RELOC_AVR_8_HI, BFD_RELOC_AVR_8_HHI. * elf/avr.h (RELOC_NUMBERS): Add values for R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8. --- bfd/ChangeLog | 12 ++++ bfd/bfd-in2.h | 12 ++++ bfd/elf32-avr.c | 47 ++++++++++++++- bfd/libbfd.h | 3 + bfd/reloc.c | 15 +++++ gas/ChangeLog | 14 +++++ gas/config/tc-avr.c | 130 ++++++++++++++++++++++++++++++------------ include/elf/ChangeLog | 6 ++ include/elf/avr.h | 26 +++++---- 9 files changed, 218 insertions(+), 47 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e776f41dda6..e958f63e021 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2012-05-11 Georg-Johann Lay * elf64-x86-64.c (elf_x86_64_relocate_section): Use int in x32 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index a66c74f3355..a087115c699 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -4088,6 +4088,18 @@ instructions */ instructions */ BFD_RELOC_AVR_6_ADIW, +/* This is a 8 bit reloc for the AVR that stores bits 0..7 of a symbol +in .byte lo8(symbol) */ + BFD_RELOC_AVR_8_LO, + +/* This is a 8 bit reloc for the AVR that stores bits 8..15 of a symbol +in .byte hi8(symbol) */ + BFD_RELOC_AVR_8_HI, + +/* This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol +in .byte hhi8(symbol) */ + BFD_RELOC_AVR_8_HHI, + /* Renesas RL78 Relocations. */ BFD_RELOC_RL78_NEG8, BFD_RELOC_RL78_NEG16, diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index 9fb72f583f5..582cdaee9fa 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -517,6 +517,48 @@ static reloc_howto_type elf_avr_howto_table[] = 0x000000ff, /* src_mask */ 0x000000ff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* lo8-part to use in .byte lo8(sym). */ + HOWTO (R_AVR_8_LO8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_LO8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* hi8-part to use in .byte hi8(sym). */ + HOWTO (R_AVR_8_HI8, /* type */ + 8, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_HI8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* hhi8-part to use in .byte hhi8(sym). */ + HOWTO (R_AVR_8_HHI8, /* type */ + 16, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_HHI8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; /* Map BFD reloc types to AVR ELF reloc types. */ @@ -555,7 +597,10 @@ static const struct avr_reloc_map avr_reloc_map[] = { BFD_RELOC_AVR_LDI, R_AVR_LDI }, { BFD_RELOC_AVR_6, R_AVR_6 }, { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW }, - { BFD_RELOC_8, R_AVR_8 } + { BFD_RELOC_8, R_AVR_8 }, + { BFD_RELOC_AVR_8_LO, R_AVR_8_LO8 }, + { BFD_RELOC_AVR_8_HI, R_AVR_8_HI8 }, + { BFD_RELOC_AVR_8_HHI, R_AVR_8_HHI8 } }; /* Meant to be filled one day with the wrap around address for the diff --git a/bfd/libbfd.h b/bfd/libbfd.h index e4acdb0cfa9..026b0778c85 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1867,6 +1867,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_AVR_LDI", "BFD_RELOC_AVR_6", "BFD_RELOC_AVR_6_ADIW", + "BFD_RELOC_AVR_8_LO", + "BFD_RELOC_AVR_8_HI", + "BFD_RELOC_AVR_8_HHI", "BFD_RELOC_RL78_NEG8", "BFD_RELOC_RL78_NEG16", "BFD_RELOC_RL78_NEG24", diff --git a/bfd/reloc.c b/bfd/reloc.c index 29c54c8767a..e5dd8bc7cb4 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -4360,6 +4360,21 @@ ENUM ENUMDOC This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw instructions +ENUM + BFD_RELOC_AVR_8_LO +ENUMDOC + This is a 8 bit reloc for the AVR that stores bits 0..7 of a symbol + in .byte lo8(symbol) +ENUM + BFD_RELOC_AVR_8_HI +ENUMDOC + This is a 8 bit reloc for the AVR that stores bits 8..15 of a symbol + in .byte hi8(symbol) +ENUM + BFD_RELOC_AVR_8_HHI +ENUMDOC + This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol + in .byte hhi8(symbol) ENUM BFD_RELOC_RL78_NEG8 diff --git a/gas/ChangeLog b/gas/ChangeLog index c9048e3c568..82ef7b7dee0 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2012-05-11 Georg-Johann Lay * config/tc-i386.c (tc_gen_reloc): Use bfd_signed_vma in x32 diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c index 42eda2fd1bc..b2f2de2b8f7 100644 --- a/gas/config/tc-avr.c +++ b/gas/config/tc-avr.c @@ -1,7 +1,7 @@ /* tc-avr.c -- Assembler code for the ATMEL AVR Copyright 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2012 Free Software Foundation, Inc. Contributed by Denis Chertykov This file is part of GAS, the GNU Assembler. @@ -65,19 +65,19 @@ static struct mcu_type_s mcu_types[] = { {"avr1", AVR_ISA_AVR1, bfd_mach_avr1}, /* TODO: insruction set for avr2 architecture should be AVR_ISA_AVR2, - but set to AVR_ISA_AVR25 for some following version - of GCC (from 4.3) for backward compatibility. */ + but set to AVR_ISA_AVR25 for some following version + of GCC (from 4.3) for backward compatibility. */ {"avr2", AVR_ISA_AVR25, bfd_mach_avr2}, {"avr25", AVR_ISA_AVR25, bfd_mach_avr25}, -/* TODO: insruction set for avr3 architecture should be AVR_ISA_AVR3, - but set to AVR_ISA_AVR3_ALL for some following version +/* TODO: insruction set for avr3 architecture should be AVR_ISA_AVR3, + but set to AVR_ISA_AVR3_ALL for some following version of GCC (from 4.3) for backward compatibility. */ {"avr3", AVR_ISA_AVR3_ALL, bfd_mach_avr3}, {"avr31", AVR_ISA_AVR31, bfd_mach_avr31}, {"avr35", AVR_ISA_AVR35, bfd_mach_avr35}, {"avr4", AVR_ISA_AVR4, bfd_mach_avr4}, -/* TODO: insruction set for avr5 architecture should be AVR_ISA_AVR5, - but set to AVR_ISA_AVR51 for some following version +/* TODO: insruction set for avr5 architecture should be AVR_ISA_AVR5, + but set to AVR_ISA_AVR51 for some following version of GCC (from 4.3) for backward compatibility. */ {"avr5", AVR_ISA_AVR51, bfd_mach_avr5}, {"avr51", AVR_ISA_AVR51, bfd_mach_avr51}, @@ -1013,7 +1013,7 @@ avr_operand (struct avr_opcodes_s *opcode, op_mask |= (x << 4); } break; - + case '?': break; @@ -1334,7 +1334,19 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg) } break; - default: + case BFD_RELOC_AVR_8_LO: + *where = 0xff & value; + break; + + case BFD_RELOC_AVR_8_HI: + *where = 0xff & (value >> 8); + break; + + case BFD_RELOC_AVR_8_HHI: + *where = 0xff & (value >> 16); + break; + + default: as_fatal (_("line %d: unknown relocation type: 0x%x"), fixP->fx_line, fixP->fx_r_type); break; @@ -1465,40 +1477,75 @@ md_assemble (char *str) } } -/* Flag to pass `pm' mode between `avr_parse_cons_expression' and - `avr_cons_fix_new'. */ -static int exp_mod_pm = 0; +typedef struct +{ + /* Name of the expression modifier allowed with .byte, .word, etc. */ + const char *name; + + /* Only allowed with n bytes of data. */ + int nbytes; + + /* Associated RELOC. */ + bfd_reloc_code_real_type reloc; + + /* Part of the error message. */ + const char *error; +} exp_mod_data_t; + +static const exp_mod_data_t exp_mod_data[] = +{ + /* Default, must be first. */ + { "", 0, BFD_RELOC_16, "" }, + /* Divides by 2 to get word address. Generate Stub. */ + { "gs", 2, BFD_RELOC_AVR_16_PM, "`gs' " }, + { "pm", 2, BFD_RELOC_AVR_16_PM, "`pm' " }, + /* The following are used together with avr-gcc's __memx address space + in order to initialize a 24-bit pointer variable with a 24-bit address. + For address in flash, hhi8 will contain the flash segment if the + symbol is located in flash. If the symbol is located in RAM; hhi8 + will contain 0x80 which matches avr-gcc's notion of how 24-bit RAM/flash + addresses linearize address space. */ + { "lo8", 1, BFD_RELOC_AVR_8_LO, "`lo8' " }, + { "hi8", 1, BFD_RELOC_AVR_8_HI, "`hi8' " }, + { "hhi8", 1, BFD_RELOC_AVR_8_HHI, "`hhi8' " }, + { "hh8", 1, BFD_RELOC_AVR_8_HHI, "`hh8' " }, + /* End of list. */ + { NULL, 0, 0, NULL } +}; + +/* Data to pass between `avr_parse_cons_expression' and `avr_cons_fix_new'. */ +static const exp_mod_data_t *pexp_mod_data = &exp_mod_data[0]; -/* Parse special CONS expression: pm (expression) - or alternatively: gs (expression). - These are used for addressing program memory. - Relocation: BFD_RELOC_AVR_16_PM. */ +/* Parse special CONS expression: pm (expression) or alternatively + gs (expression). These are used for addressing program memory. Moreover, + define lo8 (expression), hi8 (expression) and hhi8 (expression). */ void avr_parse_cons_expression (expressionS *exp, int nbytes) { + const exp_mod_data_t *pexp = &exp_mod_data[0]; char *tmp; - exp_mod_pm = 0; + pexp_mod_data = pexp; tmp = input_line_pointer = skip_space (input_line_pointer); - if (nbytes == 2) + /* The first entry of exp_mod_data[] contains an entry if no + expression modifier is present. Skip it. */ + + for (pexp++; pexp->name; pexp++) { - char *pm_name1 = "pm"; - char *pm_name2 = "gs"; - int len = strlen (pm_name1); - /* len must be the same for both pm identifiers. */ + int len = strlen (pexp->name); - if (strncasecmp (input_line_pointer, pm_name1, len) == 0 - || strncasecmp (input_line_pointer, pm_name2, len) == 0) + if (nbytes == pexp->nbytes + && strncasecmp (input_line_pointer, pexp->name, len) == 0) { input_line_pointer = skip_space (input_line_pointer + len); if (*input_line_pointer == '(') { input_line_pointer = skip_space (input_line_pointer + 1); - exp_mod_pm = 1; + pexp_mod_data = pexp; expression (exp); if (*input_line_pointer == ')') @@ -1506,13 +1553,15 @@ avr_parse_cons_expression (expressionS *exp, int nbytes) else { as_bad (_("`)' required")); - exp_mod_pm = 0; + pexp_mod_data = &exp_mod_data[0]; } return; } input_line_pointer = tmp; + + break; } } @@ -1525,8 +1574,11 @@ avr_cons_fix_new (fragS *frag, int nbytes, expressionS *exp) { - if (exp_mod_pm == 0) + int bad = 0; + + switch (pexp_mod_data->reloc) { + default: if (nbytes == 1) fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_8); else if (nbytes == 2) @@ -1534,16 +1586,24 @@ avr_cons_fix_new (fragS *frag, else if (nbytes == 4) fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_32); else - as_bad (_("illegal %srelocation size: %d"), "", nbytes); - } - else - { - if (nbytes == 2) - fix_new_exp (frag, where, nbytes, exp, FALSE, BFD_RELOC_AVR_16_PM); + bad = 1; + break; + + case BFD_RELOC_AVR_16_PM: + case BFD_RELOC_AVR_8_LO: + case BFD_RELOC_AVR_8_HI: + case BFD_RELOC_AVR_8_HHI: + if (nbytes == pexp_mod_data->nbytes) + fix_new_exp (frag, where, nbytes, exp, FALSE, pexp_mod_data->reloc); else - as_bad (_("illegal %srelocation size: %d"), "`pm' ", nbytes); - exp_mod_pm = 0; + bad = 1; + break; } + + if (bad) + as_bad (_("illegal %srelocation size: %d"), pexp_mod_data->error, nbytes); + + pexp_mod_data = &exp_mod_data[0]; } void diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index ab9b2deae3a..a405d8b980f 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,9 @@ +2012-05-11 Georg-Johann Lay * xgate.h: Mininal file to support XGATE relocations. diff --git a/include/elf/avr.h b/include/elf/avr.h index 11d43f96684..6e3b308990f 100644 --- a/include/elf/avr.h +++ b/include/elf/avr.h @@ -1,5 +1,6 @@ /* AVR ELF support for BFD. - Copyright 1999, 2000, 2004, 2006, 2010 Free Software Foundation, Inc. + Copyright 1999, 2000, 2004, 2006, 2010, 2012 + Free Software Foundation, Inc. Contributed by Denis Chertykov This file is part of BFD, the Binary File Descriptor library. @@ -30,16 +31,16 @@ as reference for the relocations so that linker relaxation is possible. */ #define EF_AVR_LINKRELAX_PREPARED 0x80 -#define E_AVR_MACH_AVR1 1 -#define E_AVR_MACH_AVR2 2 -#define E_AVR_MACH_AVR25 25 -#define E_AVR_MACH_AVR3 3 -#define E_AVR_MACH_AVR31 31 -#define E_AVR_MACH_AVR35 35 -#define E_AVR_MACH_AVR4 4 -#define E_AVR_MACH_AVR5 5 -#define E_AVR_MACH_AVR51 51 -#define E_AVR_MACH_AVR6 6 +#define E_AVR_MACH_AVR1 1 +#define E_AVR_MACH_AVR2 2 +#define E_AVR_MACH_AVR25 25 +#define E_AVR_MACH_AVR3 3 +#define E_AVR_MACH_AVR31 31 +#define E_AVR_MACH_AVR35 35 +#define E_AVR_MACH_AVR4 4 +#define E_AVR_MACH_AVR5 5 +#define E_AVR_MACH_AVR51 51 +#define E_AVR_MACH_AVR6 6 #define E_AVR_MACH_XMEGA1 101 #define E_AVR_MACH_XMEGA2 102 #define E_AVR_MACH_XMEGA3 103 @@ -77,6 +78,9 @@ START_RELOC_NUMBERS (elf_avr_reloc_type) RELOC_NUMBER (R_AVR_LO8_LDI_GS, 24) RELOC_NUMBER (R_AVR_HI8_LDI_GS, 25) RELOC_NUMBER (R_AVR_8, 26) + RELOC_NUMBER (R_AVR_8_LO8, 27) + RELOC_NUMBER (R_AVR_8_HI8, 28) + RELOC_NUMBER (R_AVR_8_HHI8, 29) END_RELOC_NUMBERS (R_AVR_max) #endif /* _ELF_AVR_H */ -- 2.30.2