From 7ef3addbe195b6283d0baf59e081146dfb211c97 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Tue, 29 Aug 2017 17:18:43 +0100 Subject: [PATCH] Improve MSP430 section placement. ld * emultempl/msp430.em (change_output_section): New function. (move_prefixed_section): New function. (add_region_prefix): New function. (msp430_elf_after_open): New function. (gld${EMULATION_NAME}_add_options): Implement. (gld${EMULATION_NAME}_list_options): Implement. (gld${EMULATION_NAME}_handle_option): Implement. * ld.texinfo: Document new options. * testsuite/ld-msp430-elf/main-bss-lower.d: New. * testsuite/ld-msp430-elf/main-bss-upper.d: New. * testsuite/ld-msp430-elf/main-const-lower.d: New. * testsuite/ld-msp430-elf/main-const-upper.d: New. * testsuite/ld-msp430-elf/main-text-lower.d: New. * testsuite/ld-msp430-elf/main-text-upper.d: New. * testsuite/ld-msp430-elf/main-var-lower.d: New. * testsuite/ld-msp430-elf/main-var-upper.d: New. * testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s: New. * testsuite/ld-msp430-elf/main-with-data-bss.s: New. * testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s: New. * testsuite/ld-msp430-elf/main-with-text-rodata.s: New. * testsuite/ld-msp430-elf/msp430-elf.exp: New. * testsuite/ld-msp430-elf/msp430-no-lower.ld: New. * testsuite/ld-msp430-elf/msp430.ld: New. * emultempl/msp430.em (data_statement_size): New. (eval_upper_either_sections): New. (eval_lower_either_sections): New. (intermediate_relax_sections): New. (msp430_elf_after_allocation): New. * emultempl/msp430.em (gld${EMULATION_NAME}_place_orphan): Always place sections in the lower region. gas * config/tc-msp430.c (md_parse_option): Define high data and high bss symbols if -mdata-region is passed. Define -mdata-region open. * doc/c-msp430.texi: Document -mdata-region. * testsuite/gas/msp430/high-data-bss-sym.d: New test. * testsuite/gas/msp430/high-data-bss-sym.s: New. * testsuite/gas/msp430/msp430.exp: Add -mdata-region tests. --- gas/ChangeLog | 10 + gas/config/tc-msp430.c | 23 +- gas/doc/c-msp430.texi | 13 + gas/testsuite/gas/msp430/high-data-bss-sym.d | 6 + gas/testsuite/gas/msp430/high-data-bss-sym.s | 19 + gas/testsuite/gas/msp430/msp430.exp | 2 + ld/ChangeLog | 33 ++ ld/emultempl/msp430.em | 653 +++++++++++++++++++-- ld/ld.texinfo | 23 + ld/testsuite/ld-msp430-elf/main-bss-lower.d | 3 + ld/testsuite/ld-msp430-elf/main-bss-upper.d | 3 + ld/testsuite/ld-msp430-elf/main-const-lower.d | 3 + ld/testsuite/ld-msp430-elf/main-const-upper.d | 3 + ld/testsuite/ld-msp430-elf/main-text-lower.d | 3 + ld/testsuite/ld-msp430-elf/main-text-upper.d | 6 + ld/testsuite/ld-msp430-elf/main-var-lower.d | 3 + ld/testsuite/ld-msp430-elf/main-var-upper.d | 3 + .../ld-msp430-elf/main-with-data-bss-unique-sec.s | 78 +++ ld/testsuite/ld-msp430-elf/main-with-data-bss.s | 74 +++ .../main-with-text-rodata-unique-sec.s | 59 ++ ld/testsuite/ld-msp430-elf/main-with-text-rodata.s | 59 ++ ld/testsuite/ld-msp430-elf/msp430-elf.exp | 141 +++++ ld/testsuite/ld-msp430-elf/msp430-no-lower.ld | 54 ++ ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld | 49 ++ ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld | 48 ++ ld/testsuite/ld-msp430-elf/msp430.ld | 78 +++ 26 files changed, 1401 insertions(+), 48 deletions(-) create mode 100644 gas/testsuite/gas/msp430/high-data-bss-sym.d create mode 100644 gas/testsuite/gas/msp430/high-data-bss-sym.s create mode 100644 ld/testsuite/ld-msp430-elf/main-bss-lower.d create mode 100644 ld/testsuite/ld-msp430-elf/main-bss-upper.d create mode 100644 ld/testsuite/ld-msp430-elf/main-const-lower.d create mode 100644 ld/testsuite/ld-msp430-elf/main-const-upper.d create mode 100644 ld/testsuite/ld-msp430-elf/main-text-lower.d create mode 100644 ld/testsuite/ld-msp430-elf/main-text-upper.d create mode 100644 ld/testsuite/ld-msp430-elf/main-var-lower.d create mode 100644 ld/testsuite/ld-msp430-elf/main-var-upper.d create mode 100644 ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s create mode 100644 ld/testsuite/ld-msp430-elf/main-with-data-bss.s create mode 100644 ld/testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s create mode 100644 ld/testsuite/ld-msp430-elf/main-with-text-rodata.s create mode 100644 ld/testsuite/ld-msp430-elf/msp430-elf.exp create mode 100644 ld/testsuite/ld-msp430-elf/msp430-no-lower.ld create mode 100644 ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld create mode 100644 ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld create mode 100644 ld/testsuite/ld-msp430-elf/msp430.ld diff --git a/gas/ChangeLog b/gas/ChangeLog index 8bea1df..3e250d3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2017-08-29 Jozef Lawrynowicz + + * config/tc-msp430.c (md_parse_option): Define high data and high + bss symbols if -mdata-region is passed. + Define -mdata-region open. + * doc/c-msp430.texi: Document -mdata-region. + * testsuite/gas/msp430/high-data-bss-sym.d: New test. + * testsuite/gas/msp430/high-data-bss-sym.s: New. + * testsuite/gas/msp430/msp430.exp: Add -mdata-region tests. + 2017-08-23 Alexander Fedotov Edmar Wienskoski fp 2 +; elim fp -> sp 0 +; saved regs:(none) + ; start of prologue + ; end of prologue +.L2: + BR #.L2 + .size main, .-main diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp index b83e1ac..0dfb271 100644 --- a/gas/testsuite/gas/msp430/msp430.exp +++ b/gas/testsuite/gas/msp430/msp430.exp @@ -24,4 +24,6 @@ if [expr [istarget "msp430-*-*"]] then { run_dump_test "bad" run_dump_test "errata_warns" run_dump_test "errata_fixes" + run_dump_test "high-data-bss-sym" { { as "-mdata-region=upper" } } + run_dump_test "high-data-bss-sym" { { as "-mdata-region=either" } } } diff --git a/ld/ChangeLog b/ld/ChangeLog index 06b8c25..8569569 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,36 @@ +2017-08-29 Jozef Lawrynowicz + + * emultempl/msp430.em (change_output_section): New function. + (move_prefixed_section): New function. + (add_region_prefix): New function. + (msp430_elf_after_open): New function. + (gld${EMULATION_NAME}_add_options): Implement. + (gld${EMULATION_NAME}_list_options): Implement. + (gld${EMULATION_NAME}_handle_option): Implement. + * ld.texinfo: Document new options. + * testsuite/ld-msp430-elf/main-bss-lower.d: New. + * testsuite/ld-msp430-elf/main-bss-upper.d: New. + * testsuite/ld-msp430-elf/main-const-lower.d: New. + * testsuite/ld-msp430-elf/main-const-upper.d: New. + * testsuite/ld-msp430-elf/main-text-lower.d: New. + * testsuite/ld-msp430-elf/main-text-upper.d: New. + * testsuite/ld-msp430-elf/main-var-lower.d: New. + * testsuite/ld-msp430-elf/main-var-upper.d: New. + * testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s: New. + * testsuite/ld-msp430-elf/main-with-data-bss.s: New. + * testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s: New. + * testsuite/ld-msp430-elf/main-with-text-rodata.s: New. + * testsuite/ld-msp430-elf/msp430-elf.exp: New. + * testsuite/ld-msp430-elf/msp430-no-lower.ld: New. + * testsuite/ld-msp430-elf/msp430.ld: New. + * emultempl/msp430.em (data_statement_size): New. + (eval_upper_either_sections): New. + (eval_lower_either_sections): New. + (intermediate_relax_sections): New. + (msp430_elf_after_allocation): New. + * emultempl/msp430.em (gld${EMULATION_NAME}_place_orphan): Always + place sections in the lower region. + 2017-08-26 H.J. Lu PR ld/21997 diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em index 949fea0..f1bbc85 100644 --- a/ld/emultempl/msp430.em +++ b/ld/emultempl/msp430.em @@ -32,6 +32,7 @@ fragment < + +enum regions +{ + REGION_NONE = 0, + REGION_LOWER, + REGION_UPPER, + REGION_EITHER = 3, +}; + +enum either_placement_stage +{ + LOWER_TO_UPPER, + UPPER_TO_LOWER, +}; + +enum { ROM, RAM }; + +static int data_region = REGION_NONE; +static int code_region = REGION_NONE; +static bfd_boolean disable_sec_transformation = FALSE; + +#define MAX_PREFIX_LENGTH 7 EOF @@ -124,6 +148,32 @@ fi if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then fragment <type) + { + case QUAD: + case SQUAD: + size = QUAD_SIZE; + break; + case LONG: + size = LONG_SIZE; + break; + case SHORT: + size = SHORT_SIZE; + break; + case BYTE: + size = BYTE_SIZE; + break; + default: + einfo ("%P: error: unhandled data_statement size\n"); + FAIL (); + } + return size; +} + /* Helper function for place_orphan that computes the size of sections already mapped to the given statement. */ @@ -143,12 +193,17 @@ scan_children (lang_statement_union_type * l) case lang_constructors_statement_enum: case lang_assignment_statement_enum: + case lang_padding_statement_enum: break; case lang_wild_statement_enum: amount += scan_children (l->wild_statement.children.head); break; + case lang_data_statement_enum: + amount += data_statement_size (&l->data_statement); + break; + default: fprintf (stderr, "msp430 orphan placer: unhandled lang type %d\n", l->header.type); break; @@ -174,7 +229,6 @@ gld${EMULATION_NAME}_place_orphan (asection * s, char * buf = NULL; 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; @@ -211,62 +265,571 @@ gld${EMULATION_NAME}_place_orphan (asection * s, /* 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) + if (lower == NULL && upper == NULL) + { + einfo ("%P: error: no section named %s or %s in linker script\n", + lower_name, upper_name); + goto end; + } + else 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); + lower = lang_output_section_find (name); + if (lower == NULL) + { + einfo ("%P: error: no section named %s in linker script\n", name); goto end; } } - 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; + + /* Always place orphaned sections in lower. Optimal placement of either + sections is performed later, once section sizes have been finalized. */ + lang_add_section (& lower->children, s, NULL, lower); + end: + free (upper_name); + free (lower_name); + if (buf) + free (buf); + return lower; +} +EOF +fi + +fragment <header.type) + { + case lang_input_section_enum: + is = curr->input_section.section; + if (is == s) + { + s->output_section = NULL; + lang_add_section (& (new_output_section->children), s, NULL, + new_output_section); + /* Remove the section from the old output section. */ + if (prev == NULL) + *head = curr->header.next; + else + prev->header.next = curr->header.next; + return TRUE; + } + break; + case lang_wild_statement_enum: + if (change_output_section (&(curr->wild_statement.children.head), + s, new_output_section)) + return TRUE; + break; + default: + break; + } + prev = curr; + curr = curr->header.next; + } + return FALSE; +} + +static void +move_prefixed_section (asection *s, char *new_name, + lang_output_section_statement_type * new_output_sec) +{ + s->name = new_name; + if (s->output_section == NULL) + lang_add_section (& (new_output_sec->children), s, NULL, new_output_sec); else { - bfd_size_type amount = 0; - struct lang_output_section_statement_struct * p; + lang_output_section_statement_type * curr_output_sec + = lang_output_section_find (s->output_section->name); + change_output_section (&(curr_output_sec->children.head), s, + new_output_sec); + } +} + +static void +add_region_prefix (bfd *abfd, asection *s, + ATTRIBUTE_UNUSED void *unused) +{ + const char *curr_name = bfd_get_section_name (abfd, s); + char * base_name; + char * new_input_sec_name = NULL; + char * new_output_sec_name = NULL; + int region = REGION_NONE; + + if (strncmp (curr_name, ".text", 5) == 0) + { + region = code_region; + base_name = concat (".text", NULL); + } + else if (strncmp (curr_name, ".data", 5) == 0) + { + region = data_region; + base_name = concat (".data", NULL); + } + else if (strncmp (curr_name, ".bss", 4) == 0) + { + region = data_region; + base_name = concat (".bss", NULL); + } + else if (strncmp (curr_name, ".rodata", 7) == 0) + { + region = data_region; + base_name = concat (".rodata", NULL); + } + else + return; + + switch (region) + { + case REGION_NONE: + break; + case REGION_UPPER: + new_input_sec_name = concat (".upper", curr_name, NULL); + new_output_sec_name = concat (".upper", base_name, NULL); + lang_output_section_statement_type * upper + = lang_output_section_find (new_output_sec_name); + if (upper != NULL) + { + move_prefixed_section (s, new_input_sec_name, upper); + } + else + einfo ("%P: error: no section named %s in linker script\n", + new_output_sec_name); + break; + case REGION_LOWER: + new_input_sec_name = concat (".lower", curr_name, NULL); + new_output_sec_name = concat (".lower", base_name, NULL); + lang_output_section_statement_type * lower + = lang_output_section_find (new_output_sec_name); + if (lower != NULL) + { + move_prefixed_section (s, new_input_sec_name, lower); + } + else + einfo ("%P: error: no section named %s in linker script\n", + new_output_sec_name); + break; + case REGION_EITHER: + s->name = concat (".either", curr_name, NULL); + break; + default: + /* Unreachable. */ + FAIL (); + break; + } + free (base_name); + if (new_input_sec_name) + { + free (new_input_sec_name); + free (new_output_sec_name); + } +} + +static void +msp430_elf_after_open (void) +{ + bfd *abfd; + + gld${EMULATION_NAME}_after_open (); - amount += scan_children (lower->children.head); + /* If neither --code-region or --data-region have been passed, do not + transform sections names. */ + if ((code_region == REGION_NONE && data_region == REGION_NONE) + || disable_sec_transformation) + return; + + for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) + bfd_map_over_sections (abfd, add_region_prefix, NULL); +} + +#define OPTION_CODE_REGION 321 +#define OPTION_DATA_REGION (OPTION_CODE_REGION + 1) +#define OPTION_DISABLE_TRANS (OPTION_CODE_REGION + 2) + +static void +gld${EMULATION_NAME}_add_options + (int ns, char **shortopts, int nl, struct option **longopts, + int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED) +{ + static const char xtra_short[] = { }; - /* 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); + static const struct option xtra_long[] = + { + { "code-region", required_argument, NULL, OPTION_CODE_REGION }, + { "data-region", required_argument, NULL, OPTION_DATA_REGION }, + { "disable-sec-transformation", no_argument, NULL, + OPTION_DISABLE_TRANS }, + { NULL, no_argument, NULL, 0 } + }; + + *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short)); + memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short)); + *longopts = (struct option *) + xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long)); + memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long)); +} - /* Scan backwards as well. */ - for (p = lower->prev; p != NULL; p = p->prev) - if (p->region == lower->region) - amount += scan_children (p->children.head); +static void +gld${EMULATION_NAME}_list_options (FILE * file) +{ + fprintf (file, _("\ + --code-region={either,lower,upper,none}\n\ + \tTransform .text* sections to {either,lower,upper,none}.text* sections.\n\ + --data-region={either,lower,upper,none}\n\ + \tTransform .data*, .rodata* and .bss* sections to\n\ + {either,lower,upper,none}.{bss,data,rodata}* sections\n\ + --disable-sec-transformation\n\ + \tDisable transformation of .{text,data,bss,rodata}* sections to\n\ + \tadd the {either,lower,upper,none} prefixes\n")); +} - if (amount + s->size >= lower->region->length) - os = upper; +static bfd_boolean +gld${EMULATION_NAME}_handle_option (int optc) +{ + switch (optc) + { + case OPTION_CODE_REGION: + if (strcmp (optarg, "upper") == 0) + code_region = REGION_UPPER; + else if (strcmp (optarg, "lower") == 0) + code_region = REGION_LOWER; + else if (strcmp (optarg, "either") == 0) + code_region = REGION_EITHER; + else if (strcmp (optarg, "none") == 0) + code_region = REGION_NONE; + else if (strlen (optarg) == 0) + { + einfo (_("%P: --code-region requires an argument: \ + {upper,lower,either,none}\n")); + return FALSE; + } else - os = lower; + { + einfo (_("%P: error: unrecognized argument to --code-region= option: \ + \"%s\"\n"), optarg); + return FALSE; + } + break; + + case OPTION_DATA_REGION: + if (strcmp (optarg, "upper") == 0) + data_region = REGION_UPPER; + else if (strcmp (optarg, "lower") == 0) + data_region = REGION_LOWER; + else if (strcmp (optarg, "either") == 0) + data_region = REGION_EITHER; + else if (strcmp (optarg, "none") == 0) + data_region = REGION_NONE; + else if (strlen (optarg) == 0) + { + einfo (_("%P: --data-region requires an argument: \ + {upper,lower,either,none}\n")); + return FALSE; + } + else + { + einfo (_("%P: error: unrecognized argument to --data-region= option: \ + \"%s\"\n"), optarg); + return FALSE; + } + break; + + case OPTION_DISABLE_TRANS: + disable_sec_transformation = TRUE; + break; + + default: + return FALSE; + } + return TRUE; +} + +static void +eval_upper_either_sections (bfd *abfd, asection *s, void *data) +{ + char * base_sec_name; + const char * curr_name; + char * either_name; + int curr_region; + + lang_output_section_statement_type * lower; + lang_output_section_statement_type * upper; + static bfd_size_type *lower_size = 0; + static bfd_size_type *upper_size = 0; + static bfd_size_type lower_size_rom = 0; + static bfd_size_type lower_size_ram = 0; + static bfd_size_type upper_size_rom = 0; + static bfd_size_type upper_size_ram = 0; + + if ((s->flags & SEC_ALLOC) == 0) + return; + if (bfd_link_relocatable (&link_info)) + return; + + base_sec_name = (char *) data; + curr_name = bfd_get_section_name (abfd, s); + + /* Only concerned with .either input sections in the upper output section. */ + either_name = concat (".either", base_sec_name, NULL); + if (strncmp (curr_name, either_name, strlen (either_name)) != 0 + || strncmp (s->output_section->name, ".upper", 6) != 0) + goto end; + + lower = lang_output_section_find (concat (".lower", base_sec_name, NULL)); + upper = lang_output_section_find (concat (".upper", base_sec_name, NULL)); + + if (upper == NULL || upper->region == NULL) + goto end; + else if (lower == NULL) + lower = lang_output_section_find (base_sec_name); + if (lower == NULL || lower->region == NULL) + goto end; + + if (strcmp (base_sec_name, ".text") == 0 + || strcmp (base_sec_name, ".rodata") == 0) + curr_region = ROM; + else + curr_region = RAM; + + if (curr_region == ROM) + { + if (lower_size_rom == 0) + { + lower_size_rom = lower->region->current - lower->region->origin; + upper_size_rom = upper->region->current - upper->region->origin; + } + lower_size = &lower_size_rom; + upper_size = &upper_size_rom; + } + else if (curr_region == RAM) + { + if (lower_size_ram == 0) + { + lower_size_ram = lower->region->current - lower->region->origin; + upper_size_ram = upper->region->current - upper->region->origin; + } + lower_size = &lower_size_ram; + upper_size = &upper_size_ram; } - lang_add_section (& os->children, s, NULL, os); + /* Move sections in the upper region that would fit in the lower + region to the lower region. */ + if (*lower_size + s->size < lower->region->length) + { + if (change_output_section (&(upper->children.head), s, lower)) + { + *upper_size -= s->size; + *lower_size += s->size; + } + } end: - free (upper_name); - free (lower_name); - if (buf) - free (buf); - return os; + free (either_name); } -EOF -fi -fragment <flags & SEC_ALLOC) == 0) + return; + if (bfd_link_relocatable (&link_info)) + return; + + base_sec_name = (char *) data; + curr_name = bfd_get_section_name (abfd, s); + + /* Only concerned with .either input sections in the lower or "default" + output section i.e. not in the upper output section. */ + either_name = concat (".either", base_sec_name, NULL); + if (strncmp (curr_name, either_name, strlen (either_name)) != 0 + || strncmp (s->output_section->name, ".upper", 6) == 0) + return; + + if (strcmp (base_sec_name, ".text") == 0 + || strcmp (base_sec_name, ".rodata") == 0) + curr_region = ROM; + else + curr_region = RAM; + + output_sec = lang_output_section_find (s->output_section->name); + + /* If the output_section doesn't exist, this has already been reported in + place_orphan, so don't need to warn again. */ + if (output_sec == NULL || output_sec->region == NULL) + goto end; + + /* lower and output_sec might be the same, but in some cases an .either + section can end up in base_sec_name if it hasn't been placed by + place_orphan. */ + lower = lang_output_section_find (concat (".lower", base_sec_name, NULL)); + upper = lang_output_section_find (concat (".upper", base_sec_name, NULL)); + if (upper == NULL) + goto end; + + if (curr_region == ROM) + { + if (lower_size_rom == 0) + { + /* Get the size of other items in the lower region that aren't the + sections to be moved around. */ + lower_size_rom + = (output_sec->region->current - output_sec->region->origin) + - scan_children (output_sec->children.head); + if (output_sec != lower && lower != NULL) + lower_size_rom -= scan_children (lower->children.head); + } + lower_size = &lower_size_rom; + } + else if (curr_region == RAM) + { + if (lower_size_ram == 0) + { + lower_size_ram + = (output_sec->region->current - output_sec->region->origin) + - scan_children (output_sec->children.head); + if (output_sec != lower && lower != NULL) + lower_size_ram -= scan_children (lower->children.head); + } + lower_size = &lower_size_ram; + } + /* Move sections that cause the lower region to overflow to the upper region. */ + if (*lower_size + s->size > output_sec->region->length) + change_output_section (&(output_sec->children.head), s, upper); + else + *lower_size += s->size; + end: + free (either_name); +} + +/* This function is similar to lang_relax_sections, but without the size + evaluation code that is always executed after relaxation. */ +static void +intermediate_relax_sections (void) +{ + int i = link_info.relax_pass; + + /* The backend can use it to determine the current pass. */ + link_info.relax_pass = 0; + + while (i--) + { + bfd_boolean relax_again; + + link_info.relax_trip = -1; + do + { + link_info.relax_trip++; + + lang_do_assignments (lang_assigning_phase_enum); + + lang_reset_memory_regions (); + + relax_again = FALSE; + lang_size_sections (&relax_again, FALSE); + } + while (relax_again); + + link_info.relax_pass++; + } +} + +static void +msp430_elf_after_allocation (void) +{ + int relax_count = 0; + int i; + /* Go over each section twice, once to place either sections that don't fit + in lower into upper, and then again to move any sections in upper that + fit in lower into lower. */ + for (i = 0; i < 8; i++) + { + int placement_stage = (i < 4) ? LOWER_TO_UPPER : UPPER_TO_LOWER; + char * base_sec_name; + lang_output_section_statement_type * upper; + + switch (i % 4) + { + case 0: + base_sec_name = concat (".text", NULL); + break; + case 1: + base_sec_name = concat (".data", NULL); + break; + case 2: + base_sec_name = concat (".bss", NULL); + break; + case 3: + base_sec_name = concat (".rodata", NULL); + break; + } + upper = lang_output_section_find (concat (".upper", base_sec_name, NULL)); + if (upper != NULL) + { + /* Can't just use one iteration over the all the sections to make + both lower->upper and upper->lower transformations because the + iterator encounters upper sections before all lower sections have + been examined. */ + bfd *abfd; + + if (placement_stage == LOWER_TO_UPPER) + { + /* Perform relaxation and get the final size of sections + before trying to fit .either sections in the correct + ouput sections. */ + if (relax_count == 0) + { + intermediate_relax_sections (); + relax_count++; + } + for (abfd = link_info.input_bfds; abfd != NULL; + abfd = abfd->link.next) + { + bfd_map_over_sections (abfd, eval_lower_either_sections, + base_sec_name); + } + } + else if (placement_stage == UPPER_TO_LOWER) + { + /* Relax again before moving upper->lower. */ + if (relax_count == 1) + { + intermediate_relax_sections (); + relax_count++; + } + for (abfd = link_info.input_bfds; abfd != NULL; + abfd = abfd->link.next) + { + bfd_map_over_sections (abfd, eval_upper_either_sections, + base_sec_name); + } + } + + } + free (base_sec_name); + } + gld${EMULATION_NAME}_after_allocation (); +} struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { @@ -274,8 +837,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_SYSLIB-syslib_default}, ${LDEMUL_HLL-hll_default}, ${LDEMUL_AFTER_PARSE-after_parse_default}, - ${LDEMUL_AFTER_OPEN-after_open_default}, - ${LDEMUL_AFTER_ALLOCATION-after_allocation_default}, + msp430_elf_after_open, + msp430_elf_after_allocation, ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, ${LDEMUL_BEFORE_ALLOCATION-before_allocation_default}, @@ -288,10 +851,10 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, ${LDEMUL_SET_SYMBOLS-NULL}, ${LDEMUL_PARSE_ARGS-NULL}, - ${LDEMUL_ADD_OPTIONS-NULL}, - ${LDEMUL_HANDLE_OPTION-NULL}, + gld${EMULATION_NAME}_add_options, + gld${EMULATION_NAME}_handle_option, ${LDEMUL_UNRECOGNIZED_FILE-NULL}, - ${LDEMUL_LIST_OPTIONS-NULL}, + gld${EMULATION_NAME}_list_options, ${LDEMUL_RECOGNIZED_FILE-NULL}, ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, ${LDEMUL_NEW_VERS_PATTERN-NULL}, diff --git a/ld/ld.texinfo b/ld/ld.texinfo index bbfa9fd..ba19cd7 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -7260,6 +7260,29 @@ Denotes a portion of RAM located above @samp{.bss} section. The last two sections are used by gcc. @end table +@table @option +@cindex MSP430 Options +@kindex --code-region +@item --code-region=[either,lower,upper,none] +This will transform .text* sections to [either,lower,upper].text* sections. The +argument passed to GCC for -mcode-region is propagated to the linker +using this option. + +@kindex --data-region +@item --data-region=[either,lower,upper,none] +This will transform .data*, .bss* and .rodata* sections to +[either,lower,upper].[data,bss,rodata]* sections. The argument passed to GCC +for -mdata-region is propagated to the linker using this option. + +@kindex --disable-sec-transformation +@item --disable-sec-transformation +Prevent the transformation of sections as specified by the @code{--code-region} +and @code{--data-region} options. +This is useful if you are compiling and linking using a single call to the GCC +wrapper, and want to compile the source files using -m[code,data]-region but +not transform the sections for prebuilt libraries and objects. +@end table + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ld-msp430-elf/main-bss-lower.d b/ld/testsuite/ld-msp430-elf/main-bss-lower.d new file mode 100644 index 0000000..6007420 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-bss-lower.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .lower.bss: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-bss-upper.d b/ld/testsuite/ld-msp430-elf/main-bss-upper.d new file mode 100644 index 0000000..2f6376a7 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-bss-upper.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .upper.bss: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-const-lower.d b/ld/testsuite/ld-msp430-elf/main-const-lower.d new file mode 100644 index 0000000..8549961 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-const-lower.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .lower.rodata: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-const-upper.d b/ld/testsuite/ld-msp430-elf/main-const-upper.d new file mode 100644 index 0000000..c84d649 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-const-upper.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .upper.rodata: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-text-lower.d b/ld/testsuite/ld-msp430-elf/main-text-lower.d new file mode 100644 index 0000000..446a305 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-text-lower.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .lower.text: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-text-upper.d b/ld/testsuite/ld-msp430-elf/main-text-upper.d new file mode 100644 index 0000000..f7ae6af --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-text-upper.d @@ -0,0 +1,6 @@ + +.*: file format.*msp430.* + + +Disassembly of section .upper.text: +#... diff --git a/ld/testsuite/ld-msp430-elf/main-var-lower.d b/ld/testsuite/ld-msp430-elf/main-var-lower.d new file mode 100644 index 0000000..f520cf5 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-var-lower.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .lower.data: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-var-upper.d b/ld/testsuite/ld-msp430-elf/main-var-upper.d new file mode 100644 index 0000000..fc3d712 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-var-upper.d @@ -0,0 +1,3 @@ +#... +Disassembly of section .upper.data: +#pass diff --git a/ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s b/ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s new file mode 100644 index 0000000..7774804 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s @@ -0,0 +1,78 @@ + .file "main-with-data-bss.c" + .global glob_var_array + .section .data.glob_var_array,"aw",@progbits + .balign 2 + .type glob_var_array, @object + .size glob_var_array, 20 +glob_var_array: + .short 0 + .short 1 + .short 2 + .short 3 + .short 4 + .short 5 + .short 6 + .short 7 + .short 8 + .short 9 + .section .bss.glob_bss_array,"aw",@nobits + .balign 2 + .type glob_bss_array, @object + .size glob_bss_array, 20 +glob_bss_array: + .zero 20 + .section .text.main,"ax",@progbits + .balign 2 + .global main + .type main, @function +main: +; start of function +; framesize_regs: 0 +; framesize_locals: 2 +; framesize_outgoing: 0 +; framesize: 2 +; elim ap -> fp 2 +; elim fp -> sp 2 +; saved regs:(none) + ; start of prologue + SUB.W #2, R1 + ; end of prologue + MOV.W #0, @R1 + BR #.L2 +.L7: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_var_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L3 +.L4: + BR #.L4 +.L3: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_bss_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L5 +.L6: + BR #.L6 +.L5: + ADD.W #1, @R1 +.L2: + MOV.B #9, R12 + CMP.W @R1, R12 { JGE .L7 + MOV.B #0, R12 + ; start of epilogue + .refsym __crt0_call_exit + ADD.W #2, R1 + RET + .size main, .-main diff --git a/ld/testsuite/ld-msp430-elf/main-with-data-bss.s b/ld/testsuite/ld-msp430-elf/main-with-data-bss.s new file mode 100644 index 0000000..a406b64 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-with-data-bss.s @@ -0,0 +1,74 @@ + .file "main-with-data-bss.c" + .global glob_var_array +.data + .balign 2 + .type glob_var_array, @object + .size glob_var_array, 20 +glob_var_array: + .short 0 + .short 1 + .short 2 + .short 3 + .short 4 + .short 5 + .short 6 + .short 7 + .short 8 + .short 9 + .local glob_bss_array + .comm glob_bss_array,20,2 +.text + .balign 2 + .global main + .type main, @function +main: +; start of function +; framesize_regs: 0 +; framesize_locals: 2 +; framesize_outgoing: 0 +; framesize: 2 +; elim ap -> fp 2 +; elim fp -> sp 2 +; saved regs:(none) + ; start of prologue + SUB.W #2, R1 + ; end of prologue + MOV.W #0, @R1 + BR #.L2 +.L7: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_var_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L3 +.L4: + BR #.L4 +.L3: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_bss_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L5 +.L6: + BR #.L6 +.L5: + ADD.W #1, @R1 +.L2: + MOV.B #9, R12 + CMP.W @R1, R12 { JGE .L7 + MOV.B #0, R12 + ; start of epilogue + .refsym __crt0_call_exit + ADD.W #2, R1 + RET + .size main, .-main diff --git a/ld/testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s b/ld/testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s new file mode 100644 index 0000000..398cf74 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-with-text-rodata-unique-sec.s @@ -0,0 +1,59 @@ + .file "main-with-text-rodata.c" + .global glob_const_array + .section .rodata.glob_const_array,"a",@progbits + .balign 2 + .type glob_const_array, @object + .size glob_const_array, 20 +glob_const_array: + .short 0 + .short 1 + .short 2 + .short 3 + .short 4 + .short 5 + .short 6 + .short 7 + .short 8 + .short 9 + .section .text.main,"ax",@progbits + .balign 2 + .global main + .type main, @function +main: +; start of function +; framesize_regs: 0 +; framesize_locals: 2 +; framesize_outgoing: 0 +; framesize: 2 +; elim ap -> fp 2 +; elim fp -> sp 2 +; saved regs:(none) + ; start of prologue + SUB.W #2, R1 + ; end of prologue + MOV.W #0, @R1 + BR #.L2 +.L5: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_const_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L3 +.L4: + BR #.L4 +.L3: + ADD.W #1, @R1 +.L2: + MOV.B #9, R12 + CMP.W @R1, R12 { JGE .L5 + MOV.B #0, R12 + ; start of epilogue + .refsym __crt0_call_exit + ADD.W #2, R1 + RET + .size main, .-main diff --git a/ld/testsuite/ld-msp430-elf/main-with-text-rodata.s b/ld/testsuite/ld-msp430-elf/main-with-text-rodata.s new file mode 100644 index 0000000..225b5d4 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/main-with-text-rodata.s @@ -0,0 +1,59 @@ + .file "main-with-text-rodata.c" + .global glob_const_array + .section .rodata + .balign 2 + .type glob_const_array, @object + .size glob_const_array, 20 +glob_const_array: + .short 0 + .short 1 + .short 2 + .short 3 + .short 4 + .short 5 + .short 6 + .short 7 + .short 8 + .short 9 +.text + .balign 2 + .global main + .type main, @function +main: +; start of function +; framesize_regs: 0 +; framesize_locals: 2 +; framesize_outgoing: 0 +; framesize: 2 +; elim ap -> fp 2 +; elim fp -> sp 2 +; saved regs:(none) + ; start of prologue + SUB.W #2, R1 + ; end of prologue + MOV.W #0, @R1 + BR #.L2 +.L5: + MOV.W @R1, R12 + ADD.W R12, R12 + ADD.W #glob_const_array, R12 + MOV.W @R12, R13 + MOV.W R13, R12 + ADD.W R12, R12 + ADD.W R13, R12 + rpt #2 { rlax.w R12 + SUB.W R13, R12 + CMP.W #110, R12 { JNE .L3 +.L4: + BR #.L4 +.L3: + ADD.W #1, @R1 +.L2: + MOV.B #9, R12 + CMP.W @R1, R12 { JGE .L5 + MOV.B #0, R12 + ; start of epilogue + .refsym __crt0_call_exit + ADD.W #2, R1 + RET + .size main, .-main diff --git a/ld/testsuite/ld-msp430-elf/msp430-elf.exp b/ld/testsuite/ld-msp430-elf/msp430-elf.exp new file mode 100644 index 0000000..fa396aa --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/msp430-elf.exp @@ -0,0 +1,141 @@ +# Expect script for various MSP430 ELF tests. +# Copyright (C) 2002-2015 Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# 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 3 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. +# +# 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., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. +# + +if { ![istarget "msp430*elf*"] } { + return +} + +# List contains test-items with 3 items followed by 2 lists and one more item: +# 0:name 1:ld early options 2:ld late options 3:assembler options +# 4:filenames of assembler files 5: action and options. 6: name of output file + +# Actions: +# objdump: Apply objdump options on result. Compare with regex (last arg). +# nm: Apply nm options on result. Compare with regex (last arg). +# readelf: Apply readelf options on result. Compare with regex (last arg). + +set msp430regionprefixtests { + {"Move main() to .upper.text" "-T msp430.ld --code-region=upper" + "" "" {main-with-text-rodata.s} {{objdump -d main-text-upper.d}} "main-upper"} + {"Move main() to .upper.text. No .lower.text in ld script" "-T msp430-no-lower.ld --code-region=upper" + "" "" {main-with-text-rodata.s} {{objdump -d main-text-upper.d}} "main-upper"} + {"Move main() to .lower.text" "-T msp430.ld --code-region=lower" + "" "" {main-with-text-rodata.s} {{objdump -d main-text-lower.d}} "main-lower"} + {"Move \"either\" main() to .lower.text" "-T msp430.ld --code-region=either" + "" "" {main-with-text-rodata.s} {{objdump -d main-text-lower.d}} "main-either"} + + {"Move glob_var to .upper.data" "-T msp430.ld --data-region=upper" + "" "" {main-with-data-bss.s} {{objdump -D main-var-upper.d}} "main-var-upper"} + {"Move glob_var to .upper.data. No .lower.data in ld script" "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-data-bss.s} {{objdump -D main-var-upper.d}} "main-var-upper"} + {"Move glob_var to .lower.data" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss.s} {{objdump -D main-var-lower.d}} "main-var-lower"} + {"Move \"either\" glob_var to .lower.data" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss.s} {{objdump -D main-var-lower.d}} "main-var-lower"} + + {"Move glob_zero to .upper.bss" "-T msp430.ld --data-region=upper" + "" "" {main-with-data-bss.s} {{objdump -D main-bss-upper.d}} "main-bss-upper"} + {"Move glob_zero to .upper.bss. No .lower.bss in ld script." "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-data-bss.s} {{objdump -D main-bss-upper.d}} "main-bss-upper"} + {"Move glob_zero to .lower.bss" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss.s} {{objdump -D main-bss-lower.d}} "main-bss-lower"} + {"Move \"either\" glob_zero to .lower.bss" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss.s} {{objdump -D main-bss-lower.d}} "main-bss-lower"} + + {"Move glob_const to .upper.rodata" "-T msp430.ld --data-region=upper" + "" "" {main-with-text-rodata.s} {{objdump -D main-const-upper.d}} "main-const-upper"} + {"Move glob_const to .upper.rodata. No .lower.rodata in ld script." "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-text-rodata.s} {{objdump -D main-const-upper.d}} "main-const-upper"} + {"Move glob_const to .lower.rodata" "-T msp430.ld --data-region=lower" + "" "" {main-with-text-rodata.s} {{objdump -D main-const-lower.d}} "main-const-lower"} + {"Move \"either\" glob_const to .lower.rodata" "-T msp430.ld --data-region=lower" + "" "" {main-with-text-rodata.s} {{objdump -D main-const-lower.d}} "main-const-lower"} +} + +set msp430regionprefixuniquesectiontests { + {"Move main() to .upper.text, with -ffunction/data-sections" "-T msp430.ld --code-region=upper" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -d main-text-upper.d}} "main-upper"} + {"Move main() to .upper.text. No .lower.text in ld script, with -ffunction/data-sections" "-T msp430-no-lower.ld --code-region=upper" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -d main-text-upper.d}} "main-upper"} + {"Move main() to .lower.text, with -ffunction/data-sections" "-T msp430.ld --code-region=lower" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -d main-text-lower.d}} "main-lower"} + {"Move \"either\" main() to .lower.text, with -ffunction/data-sections" "-T msp430.ld --code-region=either" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -d main-text-lower.d}} "main-either"} + + {"Move glob_var to .upper.data, with -ffunction/data-sections" "-T msp430.ld --data-region=upper" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-var-upper.d}} "main-var-upper"} + {"Move glob_var to .upper.data. No .lower.data in ld script, with -ffunction/data-sections" "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-var-upper.d}} "main-var-upper"} + {"Move glob_var to .lower.data, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-var-lower.d}} "main-var-lower"} + {"Move \"either\" glob_var to .lower.data, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-var-lower.d}} "main-var-lower"} + + {"Move glob_zero to .upper.bss, with -ffunction/data-sections" "-T msp430.ld --data-region=upper" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-bss-upper.d}} "main-bss-upper"} + {"Move glob_zero to .upper.bss. No .lower.bss in ld script., with -ffunction/data-sections" "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-bss-upper.d}} "main-bss-upper"} + {"Move glob_zero to .lower.bss, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-bss-lower.d}} "main-bss-lower"} + {"Move \"either\" glob_zero to .lower.bss, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-data-bss-unique-sec.s} {{objdump -D main-bss-lower.d}} "main-bss-lower"} + + {"Move glob_const to .upper.rodata, with -ffunction/data-sections" "-T msp430.ld --data-region=upper" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -D main-const-upper.d}} "main-const-upper"} + {"Move glob_const to .upper.rodata. No .lower.rodata in ld script., with -ffunction/data-sections" "-T msp430-no-lower.ld --data-region=upper" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -D main-const-upper.d}} "main-const-upper"} + {"Move glob_const to .lower.rodata, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -D main-const-lower.d}} "main-const-lower"} + {"Move \"either\" glob_const to .lower.rodata, with -ffunction/data-sections" "-T msp430.ld --data-region=lower" + "" "" {main-with-text-rodata-unique-sec.s} {{objdump -D main-const-lower.d}} "main-const-lower"} +} + +set msp430eithershuffletests { + {"Move \"either\" main() to .upper.text when it doesn\'t fit in .lower.text" + "-T msp430-tiny-rom.ld --code-region=either --data-region=either" "" "" {main-with-text-rodata.s} + {{objdump -d main-text-upper.d}} "either-to-upper-text"} + {"Move \"either\" glob_var_array to .upper.data when it doesn\'t fit in .lower.data" + "-T msp430-tiny-ram.ld --data-region=either" "" "" {main-with-data-bss.s} + {{objdump -D main-var-upper.d}} "either-to-upper-data"} + {"Move \"either\" glob_bss_array to .upper.bss when it doesn\'t fit in .lower.bss" + "-T msp430-tiny-ram.ld --data-region=either" "" "" {main-with-data-bss.s} + {{objdump -D main-bss-upper.d}} "either-to-upper-bss"} + {"Move \"either\" glob_const_array to .upper.rodata when it doesn\'t fit in .lower.rodata" + "-T msp430-tiny-rom.ld --code-region=either --data-region=either" "" "" {main-with-text-rodata.s} + {{objdump -D main-const-upper.d}} "either-to-upper-const"} + + {"Move \"either\" main() to .upper.text when it doesn\'t fit in .lower.text, with -ffunction/data-sections" + "-T msp430-tiny-rom.ld --code-region=either --data-region=either" "" "" {main-with-text-rodata-unique-sec.s} + {{objdump -d main-text-upper.d}} "either-to-upper-text-unique-sec"} + {"Move \"either\" glob_var_array to .upper.data when it doesn\'t fit in .lower.data, with -ffunction/data-sections" + "-T msp430-tiny-ram.ld --data-region=either" "" "" {main-with-data-bss-unique-sec.s} + {{objdump -D main-var-upper.d}} "either-to-upper-data-unique-sec"} + {"Move \"either\" glob_bss_array to .upper.bss when it doesn\'t fit in .lower.bss, with -ffunction/data-sections" + "-T msp430-tiny-ram.ld --data-region=either" "" "" {main-with-data-bss-unique-sec.s} + {{objdump -D main-bss-upper.d}} "either-to-upper-bss-unique-sec"} + {"Move \"either\" glob_const_array to .upper.rodata when it doesn\'t fit in .lower.rodata, with -ffunction/data-sections" + "-T msp430-tiny-rom.ld --code-region=either --data-region=either" "" "" {main-with-text-rodata-unique-sec.s} + {{objdump -D main-const-upper.d}} "either-to-upper-const-unique-sec"} +} + +run_ld_link_tests $msp430regionprefixtests +run_ld_link_tests $msp430regionprefixuniquesectiontests +run_ld_link_tests $msp430eithershuffletests diff --git a/ld/testsuite/ld-msp430-elf/msp430-no-lower.ld b/ld/testsuite/ld-msp430-elf/msp430-no-lower.ld new file mode 100644 index 0000000..f9a2847 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/msp430-no-lower.ld @@ -0,0 +1,54 @@ +/* Script for ld testsuite */ +OUTPUT_ARCH(msp430) +ENTRY(_start) + +SECTIONS +{ + .text : + { + PROVIDE (_start = .); + . = ALIGN(2); + *(.text .stub .text.* .gnu.linkonce.t.* .text:*) + } + + .rodata : + { + *(.rodata.* .rodata) + } + + .data : + { + . = ALIGN(2); + *(.data.* .data) + } + + .bss : + { + . = ALIGN(2); + *(.bss.* .bss) + } + + .upper.text : + { + . = ALIGN(2); + *(.upper.text.* .upper.text) + } + + .upper.rodata : + { + . = ALIGN(2); + *(.upper.rodata .upper.rodata.*) + } + + .upper.data : + { + . = ALIGN(2); + *(.upper.data .upper.data.*) + } + + .upper.bss : + { + . = ALIGN(2); + *(.upper.bss .upper.bss.*) + } +} diff --git a/ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld b/ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld new file mode 100644 index 0000000..e2e6f2f --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld @@ -0,0 +1,49 @@ +/* Script for ld testsuite */ +OUTPUT_ARCH(msp430) +ENTRY(_start) + +MEMORY +{ + RAM : ORIGIN = 0x0, LENGTH = 0x2 + ROM : ORIGIN = 0x2, LENGTH = 0x1fe + HIFRAM : ORIGIN = 0x200, LENGTH = 0x1000 +} + +SECTIONS +{ + .text : + { + PROVIDE (_start = .); + . = ALIGN(2); + *(.text .stub .text.* .gnu.linkonce.t.* .text:*) + } > ROM + + .rodata : + { + *(.upper.rodata.* .rodata) + } > ROM + + .data : + { + . = ALIGN(2); + *(.data.* .data) + } > RAM AT> ROM + + .bss : + { + . = ALIGN(2); + *(.bss.* .bss) + } > RAM + + .upper.data : + { + . = ALIGN(2); + *(.upper.data.* .upper.data) + } > HIFRAM AT> ROM + + .upper.bss : + { + . = ALIGN(2); + *(.upper.bss.* .upper.bss) + } > HIFRAM +} diff --git a/ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld b/ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld new file mode 100644 index 0000000..3e26379 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld @@ -0,0 +1,48 @@ +/* Script for ld testsuite */ +OUTPUT_ARCH(msp430) +ENTRY(_start) + +MEMORY +{ + ROM : ORIGIN = 0x0, LENGTH = 0x2 + RAM : ORIGIN = 0x2, LENGTH = 0x1fe + HIROM : ORIGIN = 0x200, LENGTH = 0x1000 +} + +SECTIONS +{ + .text : + { + PROVIDE (_start = .); + . = ALIGN(2); + *(.text .stub .text.* .gnu.linkonce.t.* .text:*) + } > ROM + + .rodata : + { + *(.rodata.* .rodata) + } > ROM + + .data : + { + . = ALIGN(2); + *(.data.* .data) + } > RAM AT> ROM + + .bss : + { + . = ALIGN(2); + *(.bss.* .bss) + } > RAM + + .upper.text : + { + . = ALIGN(2); + *(.upper.text.* .upper.text) + } > HIROM + + .upper.rodata : + { + *(.upper.rodata.* .upper.rodata) + } > HIROM +} diff --git a/ld/testsuite/ld-msp430-elf/msp430.ld b/ld/testsuite/ld-msp430-elf/msp430.ld new file mode 100644 index 0000000..9c30836 --- /dev/null +++ b/ld/testsuite/ld-msp430-elf/msp430.ld @@ -0,0 +1,78 @@ +/* Script for ld testsuite */ +OUTPUT_ARCH(msp430) +ENTRY(_start) + +SECTIONS +{ + .lower.data : + { + . = ALIGN(2); + *(.lower.data .lower.data.*) + } + + .lower.bss : + { + . = ALIGN(2); + *(.lower.bss .lower.bss.*) + } + + .lower.text : + { + PROVIDE (_start = .); + . = ALIGN(2); + *(.lower.text.* .lower.text) + } + + .lower.rodata : + { + . = ALIGN(2); + *(.lower.rodata .lower.rodata.*) + } + + .text : + { + . = ALIGN(2); + *(.text .stub .text.* .gnu.linkonce.t.* .text:*) + } + + .rodata : + { + *(.rodata.* .rodata) + } + + .data : + { + . = ALIGN(2); + *(.data.* .data) + } + + .bss : + { + . = ALIGN(2); + *(.bss.* .bss) + } + + .upper.text : + { + . = ALIGN(2); + *(.upper.text.* .upper.text) + } + + .upper.rodata : + { + . = ALIGN(2); + *(.upper.rodata .upper.rodata.*) + } + + .upper.data : + { + . = ALIGN(2); + *(.upper.data .upper.data.*) + } + + .upper.bss : + { + . = ALIGN(2); + *(.upper.bss .upper.bss.*) + } +} -- 2.7.4