From 837a17b36c9e297f4bf33727e25dfa9f38360c17 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 5 May 2015 13:38:00 +0100 Subject: 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. --- ld/emultempl/msp430.em | 298 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 ld/emultempl/msp430.em (limited to 'ld/emultempl') 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 <