mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
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.
This commit is contained in:
parent
3819af136d
commit
7ef3addbe1
@ -1,3 +1,13 @@
|
||||
2017-08-29 Jozef Lawrynowicz <jozef.l@somniumtech.com>
|
||||
|
||||
* 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 <alexander.fedotov@nxp.com>
|
||||
Edmar Wienskoski <edmar.wienskoski@nxp.com
|
||||
|
||||
|
@ -676,6 +676,8 @@ static bfd_boolean warn_interrupt_nops = TRUE;
|
||||
#define OPTION_MCPU 'c'
|
||||
#define OPTION_MOVE_DATA 'd'
|
||||
static bfd_boolean move_data = FALSE;
|
||||
#define OPTION_DATA_REGION 'r'
|
||||
static bfd_boolean upper_data_region_in_use = FALSE;
|
||||
|
||||
enum
|
||||
{
|
||||
@ -1448,6 +1450,12 @@ md_parse_option (int c, const char * arg)
|
||||
case OPTION_MOVE_DATA:
|
||||
move_data = TRUE;
|
||||
return 1;
|
||||
|
||||
case OPTION_DATA_REGION:
|
||||
if (strcmp (arg, "upper") == 0
|
||||
|| strcmp (arg, "either") == 0)
|
||||
upper_data_region_in_use = TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1478,14 +1486,19 @@ msp430_make_init_symbols (const char * name)
|
||||
|
||||
/* 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. */
|
||||
full. Hence the need to define the crt0 symbol.
|
||||
The linker may create upper or either data sections, even when none exist
|
||||
at the moment, so use the value of the data-region flag to determine if
|
||||
the symbol is needed. */
|
||||
if (strncmp (name, ".either.data", 12) == 0
|
||||
|| strncmp (name, ".upper.data", 11) == 0)
|
||||
|| strncmp (name, ".upper.data", 11) == 0
|
||||
|| upper_data_region_in_use)
|
||||
(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)
|
||||
|| strncmp (name, ".either.bss", 11) == 0
|
||||
|| upper_data_region_in_use)
|
||||
(void) symbol_find_or_make ("__crt0_init_highbss");
|
||||
}
|
||||
|
||||
@ -1570,6 +1583,7 @@ struct option md_longopts[] =
|
||||
{"mY", no_argument, NULL, OPTION_NO_WARN_INTR_NOPS},
|
||||
{"my", no_argument, NULL, OPTION_WARN_INTR_NOPS},
|
||||
{"md", no_argument, NULL, OPTION_MOVE_DATA},
|
||||
{"mdata-region", required_argument, NULL, OPTION_DATA_REGION},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
@ -1601,6 +1615,9 @@ md_show_usage (FILE * stream)
|
||||
_(" -my - warn about missing NOPs after changing interrupts (default)\n"));
|
||||
fprintf (stream,
|
||||
_(" -md - Force copying of data from ROM to RAM at startup\n"));
|
||||
fprintf (stream,
|
||||
_(" -mdata-region={none|lower|upper|either} - select region data will be\n"
|
||||
" placed in.\n"));
|
||||
}
|
||||
|
||||
symbolS *
|
||||
|
@ -107,6 +107,19 @@ disables warnings about missing NOP instructions.
|
||||
mark the object file as one that requires data to copied from ROM to
|
||||
RAM at execution startup. Disabled by default.
|
||||
|
||||
@item -mdata-region=@var{region}
|
||||
Select the region data will be placed in.
|
||||
Region placement is performed by the compiler and linker. The only effect this
|
||||
option will have on the assembler is that if @var{upper} or @var{either} is
|
||||
selected, then the symbols to initialise high data and bss will be defined.
|
||||
Valid @var{region} values are:
|
||||
@table @code
|
||||
@item none
|
||||
@item lower
|
||||
@item upper
|
||||
@item either
|
||||
@end table
|
||||
|
||||
@end table
|
||||
|
||||
@node MSP430 Syntax
|
||||
|
6
gas/testsuite/gas/msp430/high-data-bss-sym.d
Normal file
6
gas/testsuite/gas/msp430/high-data-bss-sym.d
Normal file
@ -0,0 +1,6 @@
|
||||
#objdump: -t
|
||||
#name: Check symbols to initialise high data and high bss have been defined
|
||||
#...
|
||||
.*__crt0_move_highdata.*
|
||||
.*__crt0_init_highbss.*
|
||||
#pass
|
19
gas/testsuite/gas/msp430/high-data-bss-sym.s
Normal file
19
gas/testsuite/gas/msp430/high-data-bss-sym.s
Normal file
@ -0,0 +1,19 @@
|
||||
.file "main.c"
|
||||
.text
|
||||
.balign 2
|
||||
.global main
|
||||
.type main, @function
|
||||
main:
|
||||
; start of function
|
||||
; framesize_regs: 0
|
||||
; framesize_locals: 0
|
||||
; framesize_outgoing: 0
|
||||
; framesize: 0
|
||||
; elim ap -> fp 2
|
||||
; elim fp -> sp 0
|
||||
; saved regs:(none)
|
||||
; start of prologue
|
||||
; end of prologue
|
||||
.L2:
|
||||
BR #.L2
|
||||
.size main, .-main
|
@ -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" } }
|
||||
}
|
||||
|
33
ld/ChangeLog
33
ld/ChangeLog
@ -1,3 +1,36 @@
|
||||
2017-08-29 Jozef Lawrynowicz <jozef.l@somniumtech.com>
|
||||
|
||||
* 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 <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/21997
|
||||
|
@ -32,6 +32,7 @@ fragment <<EOF
|
||||
#include "bfdlink.h"
|
||||
|
||||
#include "ld.h"
|
||||
#include "getopt.h"
|
||||
#include "ldmain.h"
|
||||
#include "ldmisc.h"
|
||||
#include "ldexp.h"
|
||||
@ -39,6 +40,29 @@ fragment <<EOF
|
||||
#include "ldfile.h"
|
||||
#include "ldemul.h"
|
||||
#include "libiberty.h"
|
||||
#include <ldgram.h>
|
||||
|
||||
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 <<EOF
|
||||
|
||||
static unsigned int
|
||||
data_statement_size (lang_data_statement_type *d)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
switch (d->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,71 +265,580 @@ 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)
|
||||
{
|
||||
os = upper;
|
||||
if (upper == NULL)
|
||||
{
|
||||
einfo ("%P: error: no section named %s or %s in linker script\n", lower_name, upper_name);
|
||||
einfo ("%P: error: no section named %s or %s in linker script\n",
|
||||
lower_name, upper_name);
|
||||
goto end;
|
||||
}
|
||||
else if (lower == NULL)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
/* 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 os;
|
||||
return lower;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
fragment <<EOF
|
||||
|
||||
static bfd_boolean
|
||||
change_output_section (lang_statement_union_type ** head,
|
||||
asection *s,
|
||||
lang_output_section_statement_type * new_output_section)
|
||||
{
|
||||
asection *is;
|
||||
lang_statement_union_type * prev = NULL;
|
||||
lang_statement_union_type * curr;
|
||||
|
||||
curr = *head;
|
||||
while (curr != NULL)
|
||||
{
|
||||
switch (curr->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
|
||||
{
|
||||
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 ();
|
||||
|
||||
/* 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[] = { };
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 (either_name);
|
||||
}
|
||||
|
||||
static void
|
||||
eval_lower_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 * output_sec;
|
||||
lang_output_section_statement_type * lower;
|
||||
lang_output_section_statement_type * upper;
|
||||
|
||||
static bfd_size_type *lower_size = 0;
|
||||
static bfd_size_type lower_size_rom = 0;
|
||||
static bfd_size_type lower_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 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 =
|
||||
{
|
||||
${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
|
||||
${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},
|
||||
|
@ -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
|
||||
|
3
ld/testsuite/ld-msp430-elf/main-bss-lower.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-bss-lower.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .lower.bss:
|
||||
#pass
|
3
ld/testsuite/ld-msp430-elf/main-bss-upper.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-bss-upper.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .upper.bss:
|
||||
#pass
|
3
ld/testsuite/ld-msp430-elf/main-const-lower.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-const-lower.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .lower.rodata:
|
||||
#pass
|
3
ld/testsuite/ld-msp430-elf/main-const-upper.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-const-upper.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .upper.rodata:
|
||||
#pass
|
3
ld/testsuite/ld-msp430-elf/main-text-lower.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-text-lower.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .lower.text:
|
||||
#pass
|
6
ld/testsuite/ld-msp430-elf/main-text-upper.d
Normal file
6
ld/testsuite/ld-msp430-elf/main-text-upper.d
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
.*: file format.*msp430.*
|
||||
|
||||
|
||||
Disassembly of section .upper.text:
|
||||
#...
|
3
ld/testsuite/ld-msp430-elf/main-var-lower.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-var-lower.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .lower.data:
|
||||
#pass
|
3
ld/testsuite/ld-msp430-elf/main-var-upper.d
Normal file
3
ld/testsuite/ld-msp430-elf/main-var-upper.d
Normal file
@ -0,0 +1,3 @@
|
||||
#...
|
||||
Disassembly of section .upper.data:
|
||||
#pass
|
78
ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s
Normal file
78
ld/testsuite/ld-msp430-elf/main-with-data-bss-unique-sec.s
Normal file
@ -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
|
74
ld/testsuite/ld-msp430-elf/main-with-data-bss.s
Normal file
74
ld/testsuite/ld-msp430-elf/main-with-data-bss.s
Normal file
@ -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
|
@ -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
|
59
ld/testsuite/ld-msp430-elf/main-with-text-rodata.s
Normal file
59
ld/testsuite/ld-msp430-elf/main-with-text-rodata.s
Normal file
@ -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
|
141
ld/testsuite/ld-msp430-elf/msp430-elf.exp
Normal file
141
ld/testsuite/ld-msp430-elf/msp430-elf.exp
Normal file
@ -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
|
54
ld/testsuite/ld-msp430-elf/msp430-no-lower.ld
Normal file
54
ld/testsuite/ld-msp430-elf/msp430-no-lower.ld
Normal file
@ -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.*)
|
||||
}
|
||||
}
|
49
ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld
Normal file
49
ld/testsuite/ld-msp430-elf/msp430-tiny-ram.ld
Normal file
@ -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
|
||||
}
|
48
ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld
Normal file
48
ld/testsuite/ld-msp430-elf/msp430-tiny-rom.ld
Normal file
@ -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
|
||||
}
|
78
ld/testsuite/ld-msp430-elf/msp430.ld
Normal file
78
ld/testsuite/ld-msp430-elf/msp430.ld
Normal file
@ -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.*)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user