From 837a17b36c9e297f4bf33727e25dfa9f38360c17 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 5 May 2015 13:38:00 +0100 Subject: [PATCH] Add support to the MSP430 linker for the automatic placement of code and data into either low or high memory regions. gas * config/tc-msp430.c (MAX_OP_LEN): Increase to 4096. (msp430_make_init_symbols): New function. (msp430_section): Call it. (msp430_frob_section): Likewise. ld * emulparams/msp430elf.sh (TEMPLATE_NAME): Change to msp430. * scripttempl/msp430.sc (.text): Add .lower.text and .either.text. (.data): Add .lower.data and .either.data. (.bss): Add .lower.bss and .either.bss. (.rodata): Add .lower.rodata and .either.rodata. * emultempl/msp430.em: New file. Implements a new orphan placement algorithm that divides sections between lower and upper memory regions. * Makefile.am (emsp430elf.c): Depend upon msp430.em. *emsp430X.c): Likewise. * Makefine.in: Regenerate. --- gas/ChangeLog | 7 + gas/config/tc-msp430.c | 40 ++++-- ld/ChangeLog | 14 ++ ld/Makefile.am | 2 + ld/Makefile.in | 2 + ld/emulparams/msp430elf.sh | 2 +- ld/emultempl/msp430.em | 298 ++++++++++++++++++++++++++++++++++++++++++ ld/scripttempl/elf32msp430.sc | 20 ++- 8 files changed, 369 insertions(+), 16 deletions(-) create mode 100644 ld/emultempl/msp430.em diff --git a/gas/ChangeLog b/gas/ChangeLog index 13b6705..30831ae 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2015-05-05 Nick Clifton + + * config/tc-msp430.c (MAX_OP_LEN): Increase to 4096. + (msp430_make_init_symbols): New function. + (msp430_section): Call it. + (msp430_frob_section): Likewise. + 2015-05-02 Max Filippov * config/tc-xtensa.c (cached_fixupS, fixup_cacheS): New typedefs. diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 2891c13..5307746 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -255,7 +255,7 @@ relax_typeS md_relax_table[] = }; -#define MAX_OP_LEN 256 +#define MAX_OP_LEN 4096 typedef enum msp_isa { @@ -840,14 +840,11 @@ md_parse_option (int c, char * arg) The code which initializes these sections should have a global label for these symbols, and should be marked with KEEP() in the - linker script. - */ + linker script. */ + static void -msp430_section (int arg) +msp430_make_init_symbols (const char * name) { - char * saved_ilp = input_line_pointer; - char * name = obj_elf_section_name (); - if (strncmp (name, ".bss", 4) == 0 || strncmp (name, ".gnu.linkonce.b.", 16) == 0) (void) symbol_find_or_make ("__crt0_init_bss"); @@ -856,6 +853,27 @@ msp430_section (int arg) || strncmp (name, ".gnu.linkonce.d.", 16) == 0) (void) symbol_find_or_make ("__crt0_movedata"); + /* Note - data assigned to the .either.data section may end up being + placed in the .upper.data section if the .lower.data section is + full. Hence the need to define the crt0 symbol. */ + if (strncmp (name, ".either.data", 12) == 0 + || strncmp (name, ".upper.data", 11) == 0) + (void) symbol_find_or_make ("__crt0_move_highdata"); + + /* See note about .either.data above. */ + if (strncmp (name, ".upper.bss", 10) == 0 + || strncmp (name, ".either.bss", 11) == 0) + (void) symbol_find_or_make ("__crt0_init_highbss"); +} + +static void +msp430_section (int arg) +{ + char * saved_ilp = input_line_pointer; + char * name = obj_elf_section_name (); + + msp430_make_init_symbols (name); + input_line_pointer = saved_ilp; obj_elf_section (arg); } @@ -868,13 +886,7 @@ msp430_frob_section (asection *sec) if (sec->size == 0) return; - if (strncmp (name, ".bss", 4) == 0 - || strncmp (name, ".gnu.linkonce.b.", 16) == 0) - (void) symbol_find_or_make ("__crt0_init_bss"); - - if (strncmp (name, ".data", 5) == 0 - || strncmp (name, ".gnu.linkonce.d.", 16) == 0) - (void) symbol_find_or_make ("__crt0_movedata"); + msp430_make_init_symbols (name); } static void diff --git a/ld/ChangeLog b/ld/ChangeLog index 3448bba..243bf5f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,17 @@ +2015-05-05 Nick Clifton + + * emulparams/msp430elf.sh (TEMPLATE_NAME): Change to msp430. + * scripttempl/msp430.sc (.text): Add .lower.text and .either.text. + (.data): Add .lower.data and .either.data. + (.bss): Add .lower.bss and .either.bss. + (.rodata): Add .lower.rodata and .either.rodata. + * emultempl/msp430.em: New file. Implements a new orphan + placement algorithm that divides sections between lower and upper + memory regions. + * Makefile.am (emsp430elf.c): Depend upon msp430.em. + *emsp430X.c): Likewise. + * Makefine.in: Regenerate. + 2015-04-28 Andreas Schwab PR ld/18344 diff --git a/ld/Makefile.am b/ld/Makefile.am index 15f8994..ee22e75 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -1529,9 +1529,11 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} emsp430elf.c: $(srcdir)/emulparams/msp430elf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} emsp430X.c: $(srcdir)/emulparams/msp430elf.sh $(srcdir)/emulparams/msp430X.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} ends32elf.c: $(srcdir)/emulparams/nds32elf.sh \ diff --git a/ld/Makefile.in b/ld/Makefile.in index 169fae1..2d8b09d 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -3027,9 +3027,11 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} emsp430elf.c: $(srcdir)/emulparams/msp430elf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} emsp430X.c: $(srcdir)/emulparams/msp430elf.sh $(srcdir)/emulparams/msp430X.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} ends32elf.c: $(srcdir)/emulparams/nds32elf.sh \ diff --git a/ld/emulparams/msp430elf.sh b/ld/emulparams/msp430elf.sh index b459698..a76e9ee 100644 --- a/ld/emulparams/msp430elf.sh +++ b/ld/emulparams/msp430elf.sh @@ -3,7 +3,7 @@ # This called by genscripts_extra.sh SCRIPT_NAME=elf32msp430 -TEMPLATE_NAME=generic +TEMPLATE_NAME=msp430 EXTRA_EM_FILE=genelf OUTPUT_FORMAT="elf32-msp430" MACHINE= diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em new file mode 100644 index 0000000..0eff3f0 --- /dev/null +++ b/ld/emultempl/msp430.em @@ -0,0 +1,298 @@ +# This shell script emits a C file. -*- C -*- +# It does some substitutions. +fragment <> e${EMULATION_NAME}.c +echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c +echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c +echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c +echo ' ; else return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c +echo '; }' >> e${EMULATION_NAME}.c + +else +# Scripts read from the filesystem. + +fragment <header.type) + { + case lang_input_section_enum: + if (l->input_section.section->flags & SEC_ALLOC) + amount += l->input_section.section->size; + break; + + case lang_constructors_statement_enum: + case lang_assignment_statement_enum: + break; + + case lang_wild_statement_enum: + amount += scan_children (l->wild_statement.children.head); + break; + + default: + fprintf (stderr, "msp430 orphan placer: unhandled lang type %d\n", l->header.type); + break; + } + + l = l->header.next; + } + + return amount; +} + +/* Place an orphan section. We use this to put .either sections + into either their lower or their upper equivalents. */ + +static lang_output_section_statement_type * +gld${EMULATION_NAME}_place_orphan (asection * s, + const char * secname, + int constraint) +{ + char * lower_name; + char * upper_name; + char * name; + lang_output_section_statement_type * lower; + lang_output_section_statement_type * upper; + lang_output_section_statement_type * os; + + if ((s->flags & SEC_ALLOC) == 0) + return NULL; + + if (link_info.relocatable) + return NULL; + + /* If constraints are involved let the linker handle the placement normally. */ + if (constraint != 0) + return NULL; + + /* We only need special handling for .either sections. */ + if (strncmp (secname, ".either.", 8) != 0) + return NULL; + + /* Skip the .either prefix. */ + secname += 7; + + /* Compute the names of the corresponding upper and lower + sections. If the input section name contains another period, + only use the part of the name before the second dot. */ + if (strchr (secname + 1, '.') != NULL) + { + name = ACONCAT ((secname, NULL)); + + * strchr (name + 1, '.') = 0; + } + else + name = (char *) secname; + + lower_name = ACONCAT ((".lower", name, NULL)); + upper_name = ACONCAT ((".upper", name, NULL)); + + /* Find the corresponding lower and upper sections. */ + lower = lang_output_section_find (lower_name); + upper = lang_output_section_find (upper_name); + /* If the upper section does not exist, try again without the suffix. */ + if (upper == NULL) + upper = lang_output_section_find (name); + + if (lower == NULL) + { + os = upper; + if (upper == NULL) + { + einfo ("%P: error: no section named %s or %s in linker script\n", lower_name, upper_name); + return NULL; + } + } + else if (upper == NULL) + os = lower; + else if (lower->region == NULL) + os = lower; + /* If the section is too big for the region containing + the lower section then do not even try to use it. */ + else if (lower->region->length < s->size) + os = upper; + else + { + bfd_size_type amount = 0; + struct lang_output_section_statement_struct * p; + + amount += scan_children (lower->children.head); + + /* Also check forwards for other statements assigned to the same region. */ + for (p = lower->next; p != NULL; p = p->next) + if (p->region == lower->region) + amount += scan_children (p->children.head); + + /* Scan backwards as well. */ + for (p = lower->prev; p != NULL; p = p->prev) + if (p->region == lower->region) + amount += scan_children (p->children.head); + + if (amount + s->size >= lower->region->length) + os = upper; + else + os = lower; + } + + lang_add_section (& os->children, s, NULL, os); + return os; +} +EOF +fi + +fragment < data ${RELOCATING+AT> text}} - + .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : { ${RELOCATING+. = ALIGN(2);} ${RELOCATING+ PROVIDE (__bss_start = .) ; } + *(.lower.bss.* .lower.bss) + ${RELOCATING+. = ALIGN(2);} *(.bss) + *(.either.bss.* .either.bss) *(COMMON) ${RELOCATING+ PROVIDE (__bss_end = .) ; } ${RELOCATING+ _end = . ; } -- 2.7.4