From 0385e82a5e543b98343b84c2f641e33a5e267eab Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Fri, 16 Aug 2019 14:16:58 +0100
Subject: [PATCH] MSP430: Add new Data Region GNU object attribute
---
bfd/elf32-msp430.c | 82 ++++++----
binutils/readelf.c | 32 +++-
gas/config/tc-msp430.c | 140 +++++++++++++++++-
gas/doc/as.texi | 17 +++
gas/doc/c-msp430.texi | 12 ++
gas/testsuite/gas/msp430/attr-430-small-bad.d | 4 +
gas/testsuite/gas/msp430/attr-430-small-bad.l | 4 +
.../gas/msp430/attr-430-small-good.d | 6 +
gas/testsuite/gas/msp430/attr-430-small.s | 3 +
.../gas/msp430/attr-430x-large-any-bad.d | 4 +
.../gas/msp430/attr-430x-large-any-bad.l | 4 +
.../gas/msp430/attr-430x-large-any-good.d | 6 +
.../gas/msp430/attr-430x-large-any.s | 4 +
.../gas/msp430/attr-430x-large-lower-bad.d | 4 +
.../gas/msp430/attr-430x-large-lower-bad.l | 3 +
.../gas/msp430/attr-430x-large-lower-good.d | 6 +
.../gas/msp430/attr-430x-large-lower.s | 4 +
gas/testsuite/gas/msp430/msp430.exp | 6 +
include/elf/msp430.h | 42 ++++++
ld/testsuite/ld-msp430-elf/attr-gnu-main.s | 8 +
ld/testsuite/ld-msp430-elf/attr-gnu-obj.s | 2 +
.../attr-gnu-region-lower-upper.d | 6 +
.../ld-msp430-elf/attr-gnu-region-lower.d | 12 ++
.../ld-msp430-elf/attr-gnu-region-upper.d | 13 ++
ld/testsuite/ld-msp430-elf/msp430-elf.exp | 12 +-
25 files changed, 402 insertions(+), 34 deletions(-)
create mode 100644 gas/testsuite/gas/msp430/attr-430-small-bad.d
create mode 100644 gas/testsuite/gas/msp430/attr-430-small-bad.l
create mode 100644 gas/testsuite/gas/msp430/attr-430-small-good.d
create mode 100644 gas/testsuite/gas/msp430/attr-430-small.s
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-any-bad.d
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-any-bad.l
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-any-good.d
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-any.s
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-lower-bad.d
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-lower-bad.l
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-lower-good.d
create mode 100644 gas/testsuite/gas/msp430/attr-430x-large-lower.s
create mode 100644 ld/testsuite/ld-msp430-elf/attr-gnu-main.s
create mode 100644 ld/testsuite/ld-msp430-elf/attr-gnu-obj.s
create mode 100644 ld/testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d
create mode 100644 ld/testsuite/ld-msp430-elf/attr-gnu-region-lower.d
create mode 100644 ld/testsuite/ld-msp430-elf/attr-gnu-region-upper.d
@@ -2408,15 +2408,15 @@ data_model (int model)
}
}
-/* Merge MSPABI object attributes from IBFD into OBFD.
+/* Merge MSPABI and GNU object attributes from IBFD into OBFD.
Raise an error if there are conflicting attributes. */
static bfd_boolean
-elf32_msp430_merge_mspabi_attributes (bfd *ibfd, struct bfd_link_info *info)
+elf32_msp430_merge_msp430_attributes (bfd *ibfd, struct bfd_link_info *info)
{
bfd *obfd = info->output_bfd;
- obj_attribute *in_attr;
- obj_attribute *out_attr;
+ obj_attribute *in_msp_attr, *in_gnu_attr;
+ obj_attribute *out_msp_attr, *out_gnu_attr;
bfd_boolean result = TRUE;
static bfd * first_input_bfd = NULL;
@@ -2435,45 +2435,47 @@ elf32_msp430_merge_mspabi_attributes (bfd *ibfd, struct bfd_link_info *info)
{
_bfd_elf_copy_obj_attributes (ibfd, obfd);
- out_attr = elf_known_obj_attributes_proc (obfd);
+ out_msp_attr = elf_known_obj_attributes_proc (obfd);
/* Use the Tag_null value to indicate that
the attributes have been initialized. */
- out_attr[0].i = 1;
+ out_msp_attr[0].i = 1;
first_input_bfd = ibfd;
return TRUE;
}
- in_attr = elf_known_obj_attributes_proc (ibfd);
- out_attr = elf_known_obj_attributes_proc (obfd);
+ in_msp_attr = elf_known_obj_attributes_proc (ibfd);
+ out_msp_attr = elf_known_obj_attributes_proc (obfd);
+ in_gnu_attr = elf_known_obj_attributes (ibfd) [OBJ_ATTR_GNU];
+ out_gnu_attr = elf_known_obj_attributes (obfd) [OBJ_ATTR_GNU];
/* The ISAs must be the same. */
- if (in_attr[OFBA_MSPABI_Tag_ISA].i != out_attr[OFBA_MSPABI_Tag_ISA].i)
+ if (in_msp_attr[OFBA_MSPABI_Tag_ISA].i != out_msp_attr[OFBA_MSPABI_Tag_ISA].i)
{
_bfd_error_handler
/* xgettext:c-format */
(_("error: %pB uses %s instructions but %pB uses %s"),
- ibfd, isa_type (in_attr[OFBA_MSPABI_Tag_ISA].i),
- first_input_bfd, isa_type (out_attr[OFBA_MSPABI_Tag_ISA].i));
+ ibfd, isa_type (in_msp_attr[OFBA_MSPABI_Tag_ISA].i),
+ first_input_bfd, isa_type (out_msp_attr[OFBA_MSPABI_Tag_ISA].i));
result = FALSE;
}
/* The code models must be the same. */
- if (in_attr[OFBA_MSPABI_Tag_Code_Model].i !=
- out_attr[OFBA_MSPABI_Tag_Code_Model].i)
+ if (in_msp_attr[OFBA_MSPABI_Tag_Code_Model].i !=
+ out_msp_attr[OFBA_MSPABI_Tag_Code_Model].i)
{
_bfd_error_handler
/* xgettext:c-format */
(_("error: %pB uses the %s code model whereas %pB uses the %s code model"),
- ibfd, code_model (in_attr[OFBA_MSPABI_Tag_Code_Model].i),
- first_input_bfd, code_model (out_attr[OFBA_MSPABI_Tag_Code_Model].i));
+ ibfd, code_model (in_msp_attr[OFBA_MSPABI_Tag_Code_Model].i),
+ first_input_bfd, code_model (out_msp_attr[OFBA_MSPABI_Tag_Code_Model].i));
result = FALSE;
}
/* The large code model is only supported by the MSP430X. */
- if (in_attr[OFBA_MSPABI_Tag_Code_Model].i == 2
- && out_attr[OFBA_MSPABI_Tag_ISA].i != 2)
+ if (in_msp_attr[OFBA_MSPABI_Tag_Code_Model].i == 2
+ && out_msp_attr[OFBA_MSPABI_Tag_ISA].i != 2)
{
_bfd_error_handler
/* xgettext:c-format */
@@ -2483,41 +2485,65 @@ elf32_msp430_merge_mspabi_attributes (bfd *ibfd, struct bfd_link_info *info)
}
/* The data models must be the same. */
- if (in_attr[OFBA_MSPABI_Tag_Data_Model].i !=
- out_attr[OFBA_MSPABI_Tag_Data_Model].i)
+ if (in_msp_attr[OFBA_MSPABI_Tag_Data_Model].i !=
+ out_msp_attr[OFBA_MSPABI_Tag_Data_Model].i)
{
_bfd_error_handler
/* xgettext:c-format */
(_("error: %pB uses the %s data model whereas %pB uses the %s data model"),
- ibfd, data_model (in_attr[OFBA_MSPABI_Tag_Data_Model].i),
- first_input_bfd, data_model (out_attr[OFBA_MSPABI_Tag_Data_Model].i));
+ ibfd, data_model (in_msp_attr[OFBA_MSPABI_Tag_Data_Model].i),
+ first_input_bfd, data_model (out_msp_attr[OFBA_MSPABI_Tag_Data_Model].i));
result = FALSE;
}
/* The small code model requires the use of the small data model. */
- if (in_attr[OFBA_MSPABI_Tag_Code_Model].i == 1
- && out_attr[OFBA_MSPABI_Tag_Data_Model].i != 1)
+ if (in_msp_attr[OFBA_MSPABI_Tag_Code_Model].i == 1
+ && out_msp_attr[OFBA_MSPABI_Tag_Data_Model].i != 1)
{
_bfd_error_handler
/* xgettext:c-format */
(_("error: %pB uses the small code model but %pB uses the %s data model"),
ibfd, first_input_bfd,
- data_model (out_attr[OFBA_MSPABI_Tag_Data_Model].i));
+ data_model (out_msp_attr[OFBA_MSPABI_Tag_Data_Model].i));
result = FALSE;
}
/* The large data models are only supported by the MSP430X. */
- if (in_attr[OFBA_MSPABI_Tag_Data_Model].i > 1
- && out_attr[OFBA_MSPABI_Tag_ISA].i != 2)
+ if (in_msp_attr[OFBA_MSPABI_Tag_Data_Model].i > 1
+ && out_msp_attr[OFBA_MSPABI_Tag_ISA].i != 2)
{
_bfd_error_handler
/* xgettext:c-format */
(_("error: %pB uses the %s data model but %pB only uses MSP430 instructions"),
- ibfd, data_model (in_attr[OFBA_MSPABI_Tag_Data_Model].i),
+ ibfd, data_model (in_msp_attr[OFBA_MSPABI_Tag_Data_Model].i),
first_input_bfd);
result = FALSE;
}
+ /* Just ignore the data region unless the large memory model is in use.
+ We have already checked that ibfd and obfd use the same memory model. */
+ if ((in_msp_attr[OFBA_MSPABI_Tag_Code_Model].i
+ == OFBA_MSPABI_Val_Code_Model_LARGE)
+ && (in_msp_attr[OFBA_MSPABI_Tag_Data_Model].i
+ == OFBA_MSPABI_Val_Data_Model_LARGE))
+ {
+ /* We cannot allow "lower region only" to be linked with any other
+ values (i.e. ANY or NONE).
+ Before this attribute existed, "ANY" region was the default. */
+ bfd_boolean ibfd_lower_region_used
+ = (in_gnu_attr[Tag_GNU_MSP430_Data_Region].i == Val_GNU_MSP430_Data_Region_Lower);
+ bfd_boolean obfd_lower_region_used
+ = (out_gnu_attr[Tag_GNU_MSP430_Data_Region].i == Val_GNU_MSP430_Data_Region_Lower);
+ if (ibfd_lower_region_used != obfd_lower_region_used)
+ {
+ _bfd_error_handler
+ (_("error: %pB can use the upper region for data, but %pB assumes data is exclusively in lower memory"),
+ ibfd_lower_region_used ? obfd : ibfd,
+ ibfd_lower_region_used ? ibfd : obfd);
+ result = FALSE;
+ }
+ }
+
return result;
}
@@ -2536,7 +2562,7 @@ elf32_msp430_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
max (bfd_get_mach (ibfd), bfd_get_mach (obfd)));
#undef max
- return elf32_msp430_merge_mspabi_attributes (ibfd, info);
+ return elf32_msp430_merge_msp430_attributes (ibfd, info);
}
static bfd_boolean
@@ -15731,6 +15731,36 @@ display_msp430x_attribute (unsigned char * p,
return p;
}
+static unsigned char *
+display_msp430_gnu_attribute (unsigned char * p,
+ unsigned int tag,
+ const unsigned char * const end)
+{
+ if (tag == Tag_GNU_MSP430_Data_Region)
+ {
+ unsigned int len;
+ int val;
+
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_GNU_MSP430_Data_Region: ");
+
+ switch (val)
+ {
+ case Val_GNU_MSP430_Data_Region_Any:
+ printf (_("Any Region\n"));
+ break;
+ case Val_GNU_MSP430_Data_Region_Lower:
+ printf (_("Lower Region Only\n"));
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ }
+ return p;
+ }
+ return display_tag_value (tag & 1, p, end);
+}
+
struct riscv_attr_tag_t {
const char *name;
int tag;
@@ -19555,7 +19585,7 @@ process_arch_specific (Filedata * filedata)
case EM_MSP430:
return process_attributes (filedata, "mspabi", SHT_MSP430_ATTRIBUTES,
display_msp430x_attribute,
- display_generic_attribute);
+ display_msp430_gnu_attribute);
case EM_RISCV:
return process_attributes (filedata, "riscv", SHT_RISCV_ATTRIBUTES,
@@ -689,6 +689,8 @@ static bfd_boolean do_unknown_interrupt_nops = TRUE;
static bfd_boolean move_data = FALSE;
#define OPTION_DATA_REGION 'r'
static bfd_boolean upper_data_region_in_use = FALSE;
+/* The default is to use the lower region only. */
+static bfd_boolean lower_data_region_only = TRUE;
enum
{
@@ -1473,6 +1475,13 @@ md_parse_option (int c, const char * arg)
if (strcmp (arg, "upper") == 0
|| strcmp (arg, "either") == 0)
upper_data_region_in_use = TRUE;
+ if (strcmp (arg, "upper") == 0
+ || strcmp (arg, "either") == 0
+ /* With data-region=none, the compiler has generated code assuming data
+ could be in the upper region, but nothing has been explicitly placed
+ there. */
+ || strcmp (arg, "none") == 0)
+ lower_data_region_only = FALSE;
return 1;
}
@@ -1598,6 +1607,114 @@ msp430_refsym (int arg ATTRIBUTE_UNUSED)
(void) symbol_find_or_make (sym_name);
}
+/* Handle a .mspabi_attribute or .gnu_attribute directive.
+ attr_type is 0 for .mspabi_attribute or 1 for .gnu_attribute.
+ This is only used for validating the attributes in the assembly file against
+ the options gas has been invoked with. If the attributes and options are
+ compatible then we add the attributes to the assembly file in
+ msp430_md_end. */
+static void
+msp430_object_attribute (int attr_type)
+{
+ char tag_name_s[32];
+ char tag_value_s[32];
+ int tag_name, tag_value;
+ /* First operand is the tag name, second is the tag value e.g.
+ ".mspabi_attribute 4, 2". */
+ input_line_pointer = extract_operand (input_line_pointer, tag_name_s, 32);
+ input_line_pointer = extract_operand (input_line_pointer, tag_value_s, 32);
+ tag_name = atoi (tag_name_s);
+ tag_value = atoi (tag_value_s);
+ /* If the attribute directive is present, the tag_value should never be set
+ to 0. */
+ if (tag_name == 0 || tag_value == 0)
+ as_bad (_("bad arguments \"%s\" and/or \"%s\" in %s directive"),
+ tag_name_s, tag_value_s, (attr_type ? ".gnu_attribute"
+ : ".mspabi_attribute"));
+ else if (attr_type == 0)
+ /* Handle .mspabi_attribute. */
+ switch (tag_name)
+ {
+ case OFBA_MSPABI_Tag_ISA:
+ switch (tag_value)
+ {
+ case OFBA_MSPABI_Val_ISA_MSP430:
+ if (target_is_430x ())
+ as_bad (_("file was compiled for the 430 ISA but the %s ISA is selected"),
+ (target_is_430xv2 () ? "430X" : "430Xv2"));
+ break;
+ case OFBA_MSPABI_Val_ISA_MSP430X:
+ if (!target_is_430x ())
+ as_bad (_("file was compiled for the 430X ISA but the 430 ISA is selected"));
+ break;
+ default:
+ as_bad (_("unknown MSPABI build attribute value '%d' for OFBA_MSPABI_Tag_ISA(%d) "
+ "in .mspabi_attribute directive"), tag_value, OFBA_MSPABI_Tag_ISA);
+ break;
+ }
+ break;
+ case OFBA_MSPABI_Tag_Code_Model:
+ /* Fall through. */
+ case OFBA_MSPABI_Tag_Data_Model:
+ /* FIXME: Might we want to set the memory model to large if the assembly
+ file has the large model attribute, but -ml has not been passed? */
+ switch (tag_value)
+ {
+ case OFBA_MSPABI_Val_Code_Model_SMALL:
+ if (large_model)
+ as_bad (_("file was compiled for the small memory model, but the large memory "
+ "model is selected"));
+ break;
+ case OFBA_MSPABI_Val_Code_Model_LARGE:
+ if (!large_model)
+ as_bad (_("file was compiled for the large memory model, but the small memory "
+ "model is selected"));
+ break;
+ default:
+ as_bad (_("unknown MSPABI build attribute value '%d' for %s(%d) "
+ "in .mspabi_attribute directive"), tag_value,
+ (tag_name == OFBA_MSPABI_Tag_Code_Model
+ ? "OFBA_MSPABI_Tag_Code_Model"
+ : "OFBA_MSPABI_Tag_Data_Model"),
+ (tag_name == OFBA_MSPABI_Tag_Code_Model
+ ? OFBA_MSPABI_Tag_Code_Model
+ : OFBA_MSPABI_Tag_Data_Model));
+ break;
+ }
+ break;
+ default:
+ as_bad (_("unknown MSPABI build attribute tag '%d' in .mspabi_attribute directive"), tag_name);
+ break;
+ }
+ else if (attr_type == 1)
+ /* Handle .gnu_attribute. */
+ switch (tag_name)
+ {
+ case Tag_GNU_MSP430_Data_Region:
+ /* This attribute is only applicable in the large memory model. */
+ if (!large_model)
+ break;
+ switch (tag_value)
+ {
+ case Val_GNU_MSP430_Data_Region_Lower:
+ if (!lower_data_region_only)
+ as_bad (_("file was compiled assuming all data will be in the lower memory region, "
+ "but the upper region is in use"));
+ break;
+ case Val_GNU_MSP430_Data_Region_Any:
+ if (lower_data_region_only)
+ as_bad (_("file was compiled assuming data could be in the upper memory region, "
+ "but the lower data region is exclusively in use"));
+ break;
+ default:
+ as_bad (_("unknown GNU build attribute value '%d' for Tag_GNU_MSP430_Data_Region(%d) "
+ "in .gnu_attribute directive"), tag_value, Tag_GNU_MSP430_Data_Region);
+ }
+ }
+ else
+ as_bad (_("internal: unexpected argument '%d' to msp430_object_attribute"), attr_type);
+}
+
const pseudo_typeS md_pseudo_table[] =
{
{"arch", msp430_set_arch, OPTION_MMCU},
@@ -1611,6 +1728,8 @@ const pseudo_typeS md_pseudo_table[] =
{"refsym", msp430_refsym, 0},
{"comm", msp430_comm, 0},
{"lcomm", msp430_lcomm, 0},
+ {"mspabi_attribute", msp430_object_attribute, 0},
+ {"gnu_attribute", msp430_object_attribute, 1},
{NULL, NULL, 0}
};
@@ -4919,7 +5038,7 @@ msp430_fix_adjustable (struct fix *fixp ATTRIBUTE_UNUSED)
return FALSE;
}
-/* Set the contents of the .MSP430.attributes section. */
+/* Set the contents of the .MSP430.attributes and .GNU.attributes sections. */
void
msp430_md_end (void)
@@ -4936,14 +5055,27 @@ msp430_md_end (void)
as_warn (_(WARN_NOP_AT_EOF));
}
+ /* We have already emitted an error if any of the following attributes
+ disagree with the attributes in the input assembly file. See
+ msp430_object_attribute. */
bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_ISA,
- target_is_430x () ? 2 : 1);
+ target_is_430x () ? OFBA_MSPABI_Val_ISA_MSP430X
+ : OFBA_MSPABI_Val_ISA_MSP430);
bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_Code_Model,
- large_model ? 2 : 1);
+ large_model ? OFBA_MSPABI_Val_Code_Model_LARGE
+ : OFBA_MSPABI_Val_Code_Model_SMALL);
bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_Data_Model,
- large_model ? 2 : 1);
+ large_model ? OFBA_MSPABI_Val_Code_Model_LARGE
+ : OFBA_MSPABI_Val_Code_Model_SMALL);
+
+ /* The data region GNU attribute is ignored for the small memory model. */
+ if (large_model)
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_GNU, Tag_GNU_MSP430_Data_Region,
+ lower_data_region_only
+ ? Val_GNU_MSP430_Data_Region_Lower
+ : Val_GNU_MSP430_Data_Region_Any );
}
/* Returns FALSE if there is a msp430 specific reason why the
@@ -7585,6 +7585,23 @@ The vector ABI used by this object file. The value will be:
@end itemize
@end table
+@subsection MSP430 Attributes
+
+@table @r
+@item Tag_GNU_MSP430_Data_Region (4)
+The data region used by this object file. The value will be:
+
+@itemize @bullet
+@item
+0 for files not using the large memory model.
+@item
+1 for files which have been compiled with the condition that all
+data is in the lower memory region, i.e. below address 0x10000.
+@item
+2 for files which allow data to be placed in the full 20-bit memory range.
+@end itemize
+@end table
+
@node Defining New Object Attributes
@section Defining New Object Attributes
@@ -322,6 +322,18 @@ exist purely for pulling in object files from archives. Note that
this reloc is not sufficient to prevent garbage collection; use a
KEEP() directive in the linker file to preserve such objects.
+@cindex @code{mspabi_attribute} directive, MSP430
+@item .mspabi_attribute
+This directive tells the assembler what the MSPABI build attributes for this
+file are. This is used for validating the command line options passed to
+the assembler against the options the original source file was compiled with.
+The expected format is:
+@samp{.mspabi_attribute tag_name, tag_value}
+For example, to set the tag @code{OFBA_MSPABI_Tag_ISA} to @code{MSP430X}:
+@samp{.mspabi_attribute 4, 2}
+
+See the @cite{MSP430 EABI, document slaa534} for the details on tag names and
+values.
@end table
@node MSP430 Opcodes
new file mode 100644
@@ -0,0 +1,4 @@
+#name: Error when 430 ISA and small memory model object attributes conflict with options
+#source: attr-430-small.s
+#as: -mdata-region=none -ml
+#error_output: attr-430-small-bad.l
new file mode 100644
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: file was compiled for the 430 ISA but the 430X ISA is selected
+[^:]*:2: Error: file was compiled for the small memory model, but the large memory model is selected
+[^:]*:3: Error: file was compiled for the small memory model, but the large memory model is selected
new file mode 100644
@@ -0,0 +1,6 @@
+#name: 430 ISA and small memory model object attributes
+#source: attr-430-small.s
+#as: -mcpu=msp430
+#objdump: -t
+
+#pass
new file mode 100644
@@ -0,0 +1,3 @@
+.mspabi_attribute 4, 1 ; OFBA_MSPABI_Tag_ISA == 430
+.mspabi_attribute 6, 1 ; OFBA_MSPABI_Tag_Code_Model == Small
+.mspabi_attribute 8, 1 ; OFBA_MSPABI_Tag_Data_Model == Small
new file mode 100644
@@ -0,0 +1,4 @@
+#name: Error when 430X ISA, large memory model and any data region object attributes conflict with options
+#source: attr-430x-large-any.s
+#as: -mcpu=msp430 -ml
+#error_output: attr-430x-large-any-bad.l
new file mode 100644
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: file was compiled for the 430X ISA but the 430 ISA is selected
+[^:]*:4: Error: file was compiled assuming data could be in the upper memory region, but the lower data region is exclusively in use
+
new file mode 100644
@@ -0,0 +1,6 @@
+#name: 430X ISA, large memory model and any data region object attributes
+#source: attr-430x-large-any.s
+#as: -ml -mdata-region=none
+#objdump: -t
+
+#pass
new file mode 100644
@@ -0,0 +1,4 @@
+.mspabi_attribute 4, 2 ; OFBA_MSPABI_Tag_ISA == 430x
+.mspabi_attribute 6, 2 ; OFBA_MSPABI_Tag_Code_Model == Large
+.mspabi_attribute 8, 2 ; OFBA_MSPABI_Tag_Data_Model == Large
+.gnu_attribute 4, 2 ; Tag_GNU_MSP430_Data_Region == Any
new file mode 100644
@@ -0,0 +1,4 @@
+#name: Error when 430X ISA, large memory model and lower data region object attributes conflict with options
+#source: attr-430x-large-lower.s
+#as: -mdata-region=none -mcpu=msp430 -ml
+#error_output: attr-430x-large-lower-bad.l
new file mode 100644
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:1: Error: file was compiled for the 430X ISA but the 430 ISA is selected
+[^:]*:4: Error: file was compiled assuming all data will be in the lower memory region, but the upper region is in use
new file mode 100644
@@ -0,0 +1,6 @@
+#name: 430X ISA, large memory model and lower data region object attributes
+#source: attr-430x-large-lower.s
+#as: -ml
+#objdump: -t
+
+#pass
new file mode 100644
@@ -0,0 +1,4 @@
+.mspabi_attribute 4, 2 ; OFBA_MSPABI_Tag_ISA == 430x
+.mspabi_attribute 6, 2 ; OFBA_MSPABI_Tag_Code_Model == Large
+.mspabi_attribute 8, 2 ; OFBA_MSPABI_Tag_Data_Model == Large
+.gnu_attribute 4, 1 ; Tag_GNU_MSP430_Data_Region == Lower
@@ -46,4 +46,10 @@ if [expr [istarget "msp430-*-*"]] then {
run_dump_test "preinit-array"
run_dump_test "init-array"
run_dump_test "fini-array"
+ run_dump_test "attr-430-small-bad"
+ run_dump_test "attr-430-small-good"
+ run_dump_test "attr-430x-large-lower-bad"
+ run_dump_test "attr-430x-large-lower-good"
+ run_dump_test "attr-430x-large-any-bad"
+ run_dump_test "attr-430x-large-any-good"
}
@@ -58,6 +58,48 @@
#define OFBA_MSPABI_Tag_ISA 4
#define OFBA_MSPABI_Tag_Code_Model 6
#define OFBA_MSPABI_Tag_Data_Model 8
+#define OFBA_MSPABI_Tag_enum_size 10 /* Unused by GNU. */
+
+/* GNU Object attribute tags. */
+enum
+{
+ /* 0-3 are generic. */
+
+ /* Define a GNU attribute for keeping track of whether the compiler has
+ generated code assuming that the upper region could be in use.
+ Added by the assembler based on the -mdata-region option.
+ FIXME: GCC should be generating the attribute.
+ This tag is ignored unless the large memory model is in use. */
+ Tag_GNU_MSP430_Data_Region = 4,
+};
+
+/* Object attribute values. */
+enum
+{
+ /* Values defined for OFBA_MSPABI_Tag_ISA. */
+ OFBA_MSPABI_Val_ISA_NONE = 0,
+ OFBA_MSPABI_Val_ISA_MSP430 = 1,
+ OFBA_MSPABI_Val_ISA_MSP430X = 2,
+
+ /* Values defined for OFBA_MSPABI_Tag_Code_Model. */
+ OFBA_MSPABI_Val_Code_Model_NONE = 0,
+ OFBA_MSPABI_Val_Code_Model_SMALL = 1,
+ OFBA_MSPABI_Val_Code_Model_LARGE = 2,
+
+ /* Values defined for OFBA_MSPABI_Tag_Data_Model. */
+ OFBA_MSPABI_Val_Data_Model_NONE = 0,
+ OFBA_MSPABI_Val_Data_Model_SMALL = 1,
+ OFBA_MSPABI_Val_Data_Model_LARGE = 2,
+ OFBA_MSPABI_Val_Data_Model_RESTRICTED = 3, /* Unused by GNU. */
+
+ /* Values defined for Tag_GNU_MSP430_Data_Region. */
+ Val_GNU_MSP430_Data_Region_NONE = 0,
+ /* The default data region. Assumes all data is below address 0x10000. */
+ Val_GNU_MSP430_Data_Region_Lower = 1,
+ /* Set if -mdata-region={none,upper,either}. Assumes
+ data could be placed at or above address 0x10000. */
+ Val_GNU_MSP430_Data_Region_Any = 2,
+};
/* Relocations. */
START_RELOC_NUMBERS (elf_msp430_reloc_type)
new file mode 100644
@@ -0,0 +1,8 @@
+.text
+ .balign 2
+ .global main
+ .type main, @function
+main:
+.L2:
+ BRA #.L2
+ .size main, .-main
new file mode 100644
@@ -0,0 +1,2 @@
+.text
+ .comm a,2,2
new file mode 100644
@@ -0,0 +1,6 @@
+#name: prevent merging of lower and upper attributes
+#source: attr-gnu-main.s -ml -mdata-region=lower
+#source: attr-gnu-obj.s -ml -mdata-region=upper
+#ld:
+#error: .*can use the upper region for data, but.*assumes data is exclusively in lower memory.*
+#error: .*failed to merge target specific data of file.*
new file mode 100644
@@ -0,0 +1,12 @@
+#source: attr-gnu-main.s -ml -mdata-region=lower
+#source: attr-gnu-obj.s -ml
+#readelf: -A
+
+Attribute Section: mspabi
+File Attributes
+ Tag_ISA: MSP430X
+ Tag_Code_Model: Large
+ Tag_Data_Model: Large
+Attribute Section: gnu
+File Attributes
+ Tag_GNU_MSP430_Data_Region: Lower Region Only
new file mode 100644
@@ -0,0 +1,13 @@
+#source: attr-gnu-main.s -ml -mdata-region=upper
+#source: attr-gnu-obj.s -ml -mdata-region=none
+#ld: --data-region=either
+#readelf: -A
+
+Attribute Section: mspabi
+File Attributes
+ Tag_ISA: MSP430X
+ Tag_Code_Model: Large
+ Tag_Data_Model: Large
+Attribute Section: gnu
+File Attributes
+ Tag_GNU_MSP430_Data_Region: Any Region
@@ -46,6 +46,7 @@ if { ![istarget "msp430*elf*"] } {
# treated as a sign of an error and FAILs the test.
#
#
+
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"}
@@ -162,7 +163,7 @@ set msp430warntests {
{{ld warn-no-lower-data.r}} "warn-no-lower-data"}
}
-# Don't run section shuffle tests when msp430 ISA is selected
+# Don't run further tests when msp430 ISA is selected
if {[string match "*-mcpu=msp430 *" [board_info [target_info name] multilib_flags]]
|| [string match "*-mcpu=msp430" [board_info [target_info name] multilib_flags]]} {
return
@@ -173,3 +174,12 @@ run_ld_link_tests $msp430eithershuffletests
run_ld_link_tests $msp430warntests
run_dump_test valid-map
+
+# Don't run data region tests if a data region is specified
+if {[string match "*-mdata-region*" [board_info [target_info name] multilib_flags]]} {
+ return
+}
+# GNU object attribute dump tests
+run_dump_test attr-gnu-region-lower
+run_dump_test attr-gnu-region-upper
+run_dump_test attr-gnu-region-lower-upper
--
2.17.1