aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf32-msp430.c87
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/readelf.c32
-rw-r--r--gas/ChangeLog24
-rw-r--r--gas/config/tc-msp430.c146
-rw-r--r--gas/doc/as.texi17
-rw-r--r--gas/doc/c-msp430.texi12
-rw-r--r--gas/testsuite/gas/msp430/attr-430-small-bad.d4
-rw-r--r--gas/testsuite/gas/msp430/attr-430-small-bad.l4
-rw-r--r--gas/testsuite/gas/msp430/attr-430-small-good.d6
-rw-r--r--gas/testsuite/gas/msp430/attr-430-small.s3
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-any-bad.d4
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-any-bad.l3
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-any-good.d6
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-any.s4
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-lower-bad.d4
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-lower-bad.l3
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-lower-good.d6
-rw-r--r--gas/testsuite/gas/msp430/attr-430x-large-lower.s4
-rw-r--r--gas/testsuite/gas/msp430/msp430.exp6
-rw-r--r--include/ChangeLog5
-rw-r--r--include/elf/msp430.h41
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/testsuite/ld-msp430-elf/attr-gnu-main.s8
-rw-r--r--ld/testsuite/ld-msp430-elf/attr-gnu-obj.s2
-rw-r--r--ld/testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d6
-rw-r--r--ld/testsuite/ld-msp430-elf/attr-gnu-region-lower.d12
-rw-r--r--ld/testsuite/ld-msp430-elf/attr-gnu-region-upper.d13
-rw-r--r--ld/testsuite/ld-msp430-elf/msp430-elf.exp12
30 files changed, 461 insertions, 34 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7273718..6062d38 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * elf32-msp430.c (elf32_msp430_merge_mspabi_attributes): Rename to..
+ (elf32_msp430_merge_msp430_attributes): Add support for merging
+ the GNU object attribute for data region.
+
2019-10-07 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_size_dynamic_sections): Do allocate
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index 4dcc8d4..d581dbc 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -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,48 @@ 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 +2486,69 @@ 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 +2567,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
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 00a1a1d..b9e2fcf 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * readelf.c (display_msp430_gnu_attribute): New.
+ (process_arch_specific): Use msp430 specific handler for GNU
+ attributes.
+
2019-09-30 Nick Alcock <nick.alcock@oracle.com>
* objdump.c (main): Fix tabdamage.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 2a9d145..de77237 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -15738,6 +15738,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;
@@ -19562,7 +19592,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,
diff --git a/gas/ChangeLog b/gas/ChangeLog
index abb8bf0..41bcaa3 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,27 @@
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/tc-msp430.c (md_parse_option): Set lower_data_region_only
+ to FALSE if the data region is set to "upper", "either" or "none".
+ (msp430_object_attribute): New.
+ (md_pseudo_table): Handle .mspabi_attribute and .gnu_attribute.
+ (msp430_md_end): Replace hard-coded attribute values with enums.
+ Handle data region object attribute.
+ * doc/as.texi: Document MSP430 Data Region object attribute.
+ * doc/c-msp430.texi: Document the .mspabi_attribute directive.
+ * testsuite/gas/msp430/attr-430-small-bad.d: New test.
+ * testsuite/gas/msp430/attr-430-small-bad.l: New test.
+ * testsuite/gas/msp430/attr-430-small-good.d: New test.
+ * testsuite/gas/msp430/attr-430-small.s: New test.
+ * testsuite/gas/msp430/attr-430x-large-any-bad.d: New test.
+ * testsuite/gas/msp430/attr-430x-large-any-bad.l: New test.
+ * testsuite/gas/msp430/attr-430x-large-any-good.d: New test.
+ * testsuite/gas/msp430/attr-430x-large-any.s: New test.
+ * testsuite/gas/msp430/attr-430x-large-lower-bad.d: New test.
+ * testsuite/gas/msp430/attr-430x-large-lower-bad.l: New test.
+ * testsuite/gas/msp430/attr-430x-large-lower-good.d: New test.
+ * testsuite/gas/msp430/attr-430x-large-lower.s: New test.
+ * testsuite/gas/msp430/msp430.exp: Run new tests.
+
2019-10-07 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (check_string): Make reported operand number
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index 56d2024..41413f0 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -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,120 @@ 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 +1734,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 +5044,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 +5061,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
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index b4598e8..93e80f9 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -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
diff --git a/gas/doc/c-msp430.texi b/gas/doc/c-msp430.texi
index 516c0038..3691f21 100644
--- a/gas/doc/c-msp430.texi
+++ b/gas/doc/c-msp430.texi
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430-small-bad.d b/gas/testsuite/gas/msp430/attr-430-small-bad.d
new file mode 100644
index 0000000..302ba57
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430-small-bad.d
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430-small-bad.l b/gas/testsuite/gas/msp430/attr-430-small-bad.l
new file mode 100644
index 0000000..c339ecf
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430-small-bad.l
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430-small-good.d b/gas/testsuite/gas/msp430/attr-430-small-good.d
new file mode 100644
index 0000000..5f3137f
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430-small-good.d
@@ -0,0 +1,6 @@
+#name: 430 ISA and small memory model object attributes
+#source: attr-430-small.s
+#as: -mcpu=msp430
+#objdump: -t
+
+#pass
diff --git a/gas/testsuite/gas/msp430/attr-430-small.s b/gas/testsuite/gas/msp430/attr-430-small.s
new file mode 100644
index 0000000..2bdb1db
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430-small.s
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-any-bad.d b/gas/testsuite/gas/msp430/attr-430x-large-any-bad.d
new file mode 100644
index 0000000..6793f7c
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-any-bad.d
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-any-bad.l b/gas/testsuite/gas/msp430/attr-430x-large-any-bad.l
new file mode 100644
index 0000000..c7f2282
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-any-bad.l
@@ -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 data could be in the upper memory region, but the lower data region is exclusively in use
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-any-good.d b/gas/testsuite/gas/msp430/attr-430x-large-any-good.d
new file mode 100644
index 0000000..603aab1
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-any-good.d
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-any.s b/gas/testsuite/gas/msp430/attr-430x-large-any.s
new file mode 100644
index 0000000..593c171
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-any.s
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.d b/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.d
new file mode 100644
index 0000000..fb7e5ca
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.d
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.l b/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.l
new file mode 100644
index 0000000..a21b640
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-lower-bad.l
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-lower-good.d b/gas/testsuite/gas/msp430/attr-430x-large-lower-good.d
new file mode 100644
index 0000000..c4a395c
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-lower-good.d
@@ -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
diff --git a/gas/testsuite/gas/msp430/attr-430x-large-lower.s b/gas/testsuite/gas/msp430/attr-430x-large-lower.s
new file mode 100644
index 0000000..4ab0b5d
--- /dev/null
+++ b/gas/testsuite/gas/msp430/attr-430x-large-lower.s
@@ -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
diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp
index 9c7a197..ef3164d 100644
--- a/gas/testsuite/gas/msp430/msp430.exp
+++ b/gas/testsuite/gas/msp430/msp430.exp
@@ -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"
}
diff --git a/include/ChangeLog b/include/ChangeLog
index c409344..13b15f0 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * elf/msp430.h: Add enums for MSPABI and GNU object attribute tag
+ names and values.
+
2019-09-23 Nick Alcock <nick.alcock@oracle.com>
* ctf-api.h (ctf_cuname_set): Can now fail, returning int.
diff --git a/include/elf/msp430.h b/include/elf/msp430.h
index e060804..ce2cf5b 100644
--- a/include/elf/msp430.h
+++ b/include/elf/msp430.h
@@ -58,6 +58,47 @@
#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.
+ 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)
diff --git a/ld/ChangeLog b/ld/ChangeLog
index ddec8c7..a545765 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,12 @@
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * testsuite/ld-msp430-elf/attr-gnu-main.s: New test.
+ * testsuite/ld-msp430-elf/attr-gnu-obj.s: New test.
+ * testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d: New test.
+ * testsuite/ld-msp430-elf/attr-gnu-region-lower.d: New test.
+ * testsuite/ld-msp430-elf/attr-gnu-region-upper.d: New test.
+ * testsuite/ld-msp430-elf/msp430-elf.exp: Run new tests.
+
2019-10-07 Alan Modra <amodra@gmail.com>
* ldmisc.c (vfinfo): Save and restore bfd_error around bfd
diff --git a/ld/testsuite/ld-msp430-elf/attr-gnu-main.s b/ld/testsuite/ld-msp430-elf/attr-gnu-main.s
new file mode 100644
index 0000000..e07a58c
--- /dev/null
+++ b/ld/testsuite/ld-msp430-elf/attr-gnu-main.s
@@ -0,0 +1,8 @@
+.text
+ .balign 2
+ .global main
+ .type main, @function
+main:
+.L2:
+ BRA #.L2
+ .size main, .-main
diff --git a/ld/testsuite/ld-msp430-elf/attr-gnu-obj.s b/ld/testsuite/ld-msp430-elf/attr-gnu-obj.s
new file mode 100644
index 0000000..d256e40
--- /dev/null
+++ b/ld/testsuite/ld-msp430-elf/attr-gnu-obj.s
@@ -0,0 +1,2 @@
+.text
+ .comm a,2,2
diff --git a/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d b/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d
new file mode 100644
index 0000000..70f8e35
--- /dev/null
+++ b/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower-upper.d
@@ -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.*
diff --git a/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower.d b/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower.d
new file mode 100644
index 0000000..57345aa
--- /dev/null
+++ b/ld/testsuite/ld-msp430-elf/attr-gnu-region-lower.d
@@ -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
diff --git a/ld/testsuite/ld-msp430-elf/attr-gnu-region-upper.d b/ld/testsuite/ld-msp430-elf/attr-gnu-region-upper.d
new file mode 100644
index 0000000..225968d
--- /dev/null
+++ b/ld/testsuite/ld-msp430-elf/attr-gnu-region-upper.d
@@ -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
diff --git a/ld/testsuite/ld-msp430-elf/msp430-elf.exp b/ld/testsuite/ld-msp430-elf/msp430-elf.exp
index b6f3151..08620b5 100644
--- a/ld/testsuite/ld-msp430-elf/msp430-elf.exp
+++ b/ld/testsuite/ld-msp430-elf/msp430-elf.exp
@@ -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