aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozef.l@mittosystems.com>2019-10-07 15:58:19 +0000
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>2019-10-07 15:58:19 +0000
commit8682b1a508e5ba9bd2e1b2b4d298bf7d07a37f80 (patch)
tree0ca5ebb630b7aaee342feadcf29e07af6e22fd9b /gcc/config
parent0b06099d407225a28f12ed600ae561aa8317dfc9 (diff)
downloadgcc-8682b1a508e5ba9bd2e1b2b4d298bf7d07a37f80.zip
gcc-8682b1a508e5ba9bd2e1b2b4d298bf7d07a37f80.tar.gz
gcc-8682b1a508e5ba9bd2e1b2b4d298bf7d07a37f80.tar.bz2
MSP430: Don't generate 430X insns when handling data in the lower memory region
gcc/ChangeLog: 2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com> * config.in: Regenerate. * config/msp430/constraints.md: Fix docstring for "Ys" constraint. Add new "Yx" constraint. * config/msp430/driver-msp430.c (msp430_propagate_region_opt): New spec function. * config/msp430/msp430-protos.h (msp430_op_not_in_high_mem): New prototype. * config/msp430/msp430.c (msp430_option_override): Allow the lower code/data region to be selected in the small memory model. (msp430_section_attr): Don't warn if the "section" and "lower" attributes are used together. (msp430_handle_generic_attribute): Likewise. (msp430_var_in_low_mem): New function. (TARGET_ENCODE_SECTION_INFO): Define. (msp430_encode_section_info): New function. (gen_prefix): Return early in the small memory model. Require TARGET_USE_LOWER_REGION_PREFIX to be set before adding the ".lower" prefix if -m{code,data}-region=lower have been passed. (msp430_output_aligned_decl_common): Emit common symbols when -mdata-region=lower is passed unless TARGET_USE_LOWER_REGION_PREFIX is set. (TARGET_ASM_FILE_END): Define. (msp430_file_end): New function. (msp430_do_not_relax_short_jumps): Allow relaxation when function will be in the lower region. (msp430_op_not_in_high_mem): New function. (msp430_print_operand): Check "msp430_op_not_in_high_mem" for the 'X' operand selector. Clarify comment for 'x' operand selector. * config/msp430/msp430.h (LINK_SPEC): Propagate -m{code,data}-region to the linker via spec function msp430_propagate_region_opt. (msp430_propagate_region_opt): New prototype. (EXTRA_SPEC_FUNCTIONS): Add msp430_propagate_region_opt. (SYMBOL_FLAG_LOW_MEM): Define. * config/msp430/msp430.md (addsipsi3): Add missing "%X" operand selector. (zero_extendqihi2): Fix operand number used by "%X" selector. (zero_extendqisi2): Likewise. (zero_extendhisi2): Likewise. (movqi): Use "Yx" constraint in place of "%X" operand selector. (movhi): Likewise. (addqi3): Likewise. (addhi3): Likewise. (addsi3): Likewise. (addhi3_cy): Likewise. (addchi4_cy): Likewise. (subqi3): Likewise. (subhi3): Likewise. (subsi3): Likewise. (bic<mode>3): Likewise. (and<mode>3): Likewise. (ior<mode>3): Likewise. (xor<mode>3): Likewise. (slli_1): Add missing "%X" operand selector. (slll_1): Likewise. (slll_2): Likewise. (srai_1): Likewise. (sral_1): Likewise. (sral_2): Likewise. (srli_1): Likewise. (srll_1): Likewise. (cbranchqi4_real): Use "Yx" constraint in place of "%X" operand selector. (cbranchhi4_real): Likewise. (cbranchqi4_reversed): Likewise. (cbranchhi4_reversed): Likewise. (*bitbranch<mode>4): Likewise. (*bitbranch<mode>4_z): Remove unnecessary "%x" operand selector. * config/msp430/msp430.opt (mcode-region=): Set default to MSP430_REGION_LOWER. Improve docstring. (mdata-region=): Likewise. (muse-lower-region-prefix): New option. * config/msp430/t-msp430 (MULTILIB_OPTIONS): Add mdata-region=none multilib. (MULTILIB_MATCHES): Set mdata-region={upper,either} to match mdata-region=none multilib. MULTILIB_EXCEPTIONS: Remove. MULTILIB_REQUIRED: Define. * configure: Regenerate. * configure.ac: Define HAVE_AS_GNU_ATTRIBUTE and HAVE_AS_MSPABI_ATTRIBUTE if GAS version >= 2.33.50. * doc/extend.texi: Clarify comment for {upper,lower,either} function attributes. Add separate description for "lower" variable attribute. gcc/testsuite/ChangeLog: 2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com> * gcc.target/msp430/430x-insns.c: New test. * gcc.target/msp430/data-attributes-2.c: Remove dg-warning directives for conflicts between the "section" and "lower" attributes. * gcc.target/msp430/msp430.exp (check_effective_target_msp430_region_not_lower): New. (check_effective_target_msp430_region_lower): New. * gcc.target/msp430/object-attributes-430.c: New test. * gcc.target/msp430/object-attributes-default.c: New test. * gcc.target/msp430/object-attributes-mlarge-any-region.c: New test. * gcc.target/msp430/object-attributes-mlarge.c: New test. From-SVN: r276665
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/msp430/constraints.md10
-rw-r--r--gcc/config/msp430/driver-msp430.c13
-rw-r--r--gcc/config/msp430/msp430-protos.h1
-rw-r--r--gcc/config/msp430/msp430.c214
-rw-r--r--gcc/config/msp430/msp430.h13
-rw-r--r--gcc/config/msp430/msp430.md176
-rw-r--r--gcc/config/msp430/msp430.opt12
-rw-r--r--gcc/config/msp430/t-msp43011
8 files changed, 326 insertions, 124 deletions
diff --git a/gcc/config/msp430/constraints.md b/gcc/config/msp430/constraints.md
index 7ef249d..4422b2b 100644
--- a/gcc/config/msp430/constraints.md
+++ b/gcc/config/msp430/constraints.md
@@ -69,9 +69,11 @@
;; These are memory references that are safe to use without the X suffix,
-;; because we know/assume they need not index across the 64k boundary.
+;; because we know/assume they need not index across the 64K boundary.
+;; Note that for a PSImode memory operand, we always need to use the X suffix,
+;; regardless of what this constraint decides.
(define_constraint "Ys"
- "Memory reference, stack only."
+ "Memory reference, indexed or indirect register addressing modes."
(and (match_code "mem")
(ior
(and (match_code "plus" "0")
@@ -93,3 +95,7 @@
(match_test ("REGNO (XEXP (XEXP (op, 0), 0)) != SP_REGNO")))
))))
+(define_constraint "Yx"
+ "Memory reference, in lower memory below address 0x10000."
+ (and (match_code "mem")
+ (match_test "msp430_op_not_in_high_mem (op)")))
diff --git a/gcc/config/msp430/driver-msp430.c b/gcc/config/msp430/driver-msp430.c
index 0a3d1e1..c37b169 100644
--- a/gcc/config/msp430/driver-msp430.c
+++ b/gcc/config/msp430/driver-msp430.c
@@ -149,3 +149,16 @@ msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED,
return "-lmul_none";
}
+
+/* Spec function. Propagate -m{code,data}-region= to the linker, unless the
+ lower region has been specified without -muse-lower-region-prefix also being
+ used. */
+const char *
+msp430_propagate_region_opt (int argc, const char **argv)
+{
+ if (strcmp (argv[0], "lower") != 0)
+ return argv[0];
+ else if ((argc == 2) && (strcmp (argv[1], "-muse-lower-region-prefix") == 0))
+ return argv[0]; /* argv[0] == "lower". */
+ return "none";
+}
diff --git a/gcc/config/msp430/msp430-protos.h b/gcc/config/msp430/msp430-protos.h
index 267b6f5..1c1757f 100644
--- a/gcc/config/msp430/msp430-protos.h
+++ b/gcc/config/msp430/msp430-protos.h
@@ -47,5 +47,6 @@ void msp430_split_movsi (rtx *);
void msp430_start_function (FILE *, const char *, tree);
rtx msp430_subreg (machine_mode, rtx, machine_mode, int);
bool msp430_use_f5_series_hwmult (void);
+bool msp430_op_not_in_high_mem (rtx op);
#endif /* GCC_MSP430_PROTOS_H */
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 6430823..354b4dd 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -35,6 +35,7 @@
#include "tm_p.h"
#include "regs.h"
#include "emit-rtl.h"
+#include "varasm.h"
#include "diagnostic-core.h"
#include "fold-const.h"
#include "stor-layout.h"
@@ -263,9 +264,6 @@ msp430_option_override (void)
else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_UPPER)
error ("%<-mcode-region=upper%> requires the large memory model "
"(%<-mlarge%>)");
- else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_LOWER)
- error ("%<-mcode-region=lower%> requires the large memory model "
- "(%<-mlarge%>)");
if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_EITHER)
error ("%<-mdata-region=either%> requires the large memory model "
@@ -273,10 +271,6 @@ msp430_option_override (void)
else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_UPPER)
error ("%<-mdata-region=upper%> requires the large memory model "
"(%<-mlarge%>)");
- else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_LOWER)
- error ("%<-mdata-region=lower%> requires the large memory model "
- "(%<-mlarge%>)");
-
if (flag_exceptions || flag_non_call_exceptions
|| flag_unwind_tables || flag_asynchronous_unwind_tables)
@@ -1386,7 +1380,7 @@ msp430_section_attr (tree * node,
if (has_attr (ATTR_NOINIT, *node))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<noinit%>");
- else if (has_attr ("section", *node))
+ else if (has_attr ("section", *node) && !TREE_NAME_EQ (name, "lower"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<section%>");
/* It does not make sense to use upper/lower/either attributes without
@@ -1564,12 +1558,14 @@ msp430_handle_generic_attribute (tree *node,
{
const char *message = NULL;
+ /* The front end has set up an exclusion between the "noinit" and "section"
+ attributes. */
if (!(TREE_NAME_EQ (name, ATTR_NOINIT) || TREE_NAME_EQ (name, "section")))
return NULL_TREE;
- /* The front end has set up an exclusion between the "noinit" and "section"
- attributes. */
- if (has_attr (ATTR_LOWER, *node))
+ /* We allow the "lower" attribute to be used on variables with the "section"
+ attribute. */
+ if (has_attr (ATTR_LOWER, *node) && !TREE_NAME_EQ (name, "section"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<lower%>");
else if (has_attr (ATTR_UPPER, *node))
@@ -1591,6 +1587,55 @@ msp430_handle_generic_attribute (tree *node,
return NULL_TREE;
}
+/* Given a non-automatic VAR_DECL which can possibly have a section, return
+ true if the variable will definitely be placed in the lower memory
+ region (below address 0x10000). */
+static bool
+msp430_var_in_low_mem (tree decl)
+{
+ gcc_assert (VAR_P (decl));
+
+ /* "noinit" variables are always placed in the lower memory region. */
+ if (has_attr (ATTR_UPPER, decl)
+ || has_attr (ATTR_EITHER, decl)
+ || has_attr (ATTR_PERSIST, decl)
+ /* Unless the variable is marked with the lower or noinit attribute, we
+ cannot assume that it is in the lower region if it is marked with the
+ section attribute or -mdata-region={upper,either,none} have been
+ passed.
+ The noinit and section attributes conflict. */
+ || (!has_attr (ATTR_LOWER, decl) && !has_attr (ATTR_NOINIT, decl)
+ && (has_attr ("section", decl)
+ || msp430_data_region == MSP430_REGION_UPPER
+ || msp430_data_region == MSP430_REGION_EITHER
+ || msp430_data_region == MSP430_REGION_ANY)))
+ return false;
+ return true;
+}
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO msp430_encode_section_info
+
+/* Encode whether a SYMBOL_REF is definitely in the lower memory region. */
+static void
+msp430_encode_section_info (tree decl, rtx rtl, int first)
+{
+ rtx symbol;
+ default_encode_section_info (decl, rtl, first);
+
+ /* Careful not to prod global register variables. */
+ if (!MEM_P (rtl))
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
+ if (VAR_P (decl)
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+ && msp430_var_in_low_mem (decl))
+ SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOW_MEM;
+}
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
@@ -1744,15 +1789,17 @@ gen_prefix (tree decl)
if (has_section_name (".lowtext", decl))
return NULL;
- /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
+ /* Memory regions require the large memory model. */
+ if (!TARGET_LARGE)
+ return NULL;
+
+ /* Note that we always apply the lower prefix when the attribute has been
+ used. But we only apply the lower prefix when the lower region has been
+ specified by a command line option if -muse-lower-region-prefix has also
+ been passed. */
if (has_attr (ATTR_LOWER, decl))
return lower_prefix;
- /* If we are compiling for the MSP430 then we do not support the upper
- region. */
- if (! msp430x)
- return NULL;
-
if (has_attr (ATTR_UPPER, decl))
return upper_prefix;
@@ -1761,7 +1808,8 @@ gen_prefix (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- if (msp430_code_region == MSP430_REGION_LOWER)
+ if ((msp430_code_region == MSP430_REGION_LOWER)
+ && TARGET_USE_LOWER_REGION_PREFIX)
return lower_prefix;
if (msp430_code_region == MSP430_REGION_UPPER)
@@ -1772,7 +1820,8 @@ gen_prefix (tree decl)
}
else
{
- if (msp430_data_region == MSP430_REGION_LOWER)
+ if ((msp430_data_region == MSP430_REGION_LOWER)
+ && TARGET_USE_LOWER_REGION_PREFIX)
return lower_prefix;
if (msp430_data_region == MSP430_REGION_UPPER)
@@ -1966,7 +2015,6 @@ msp430_unique_section (tree decl, int reloc)
/* Emit a declaration of a common symbol.
If a data region is in use then put the symbol into the
equivalent .bss section instead. */
-
void
msp430_output_aligned_decl_common (FILE * stream,
const tree decl,
@@ -1976,7 +2024,9 @@ msp430_output_aligned_decl_common (FILE * stream,
{
/* Only emit a common symbol if the variable does not have a specific section
assigned. */
- if (msp430_data_region == MSP430_REGION_ANY
+ if ((msp430_data_region == MSP430_REGION_ANY
+ || ((msp430_data_region == MSP430_REGION_LOWER)
+ && !TARGET_USE_LOWER_REGION_PREFIX))
&& !(decl != NULL_TREE && DECL_SECTION_NAME (decl))
&& !has_attr (ATTR_EITHER, decl)
&& !has_attr (ATTR_LOWER, decl)
@@ -2021,6 +2071,78 @@ msp430_output_aligned_decl_common (FILE * stream,
}
}
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END msp430_file_end
+
+/* Emit MSPABI and GNU object attributes.
+ Tags and values for MSPABI attributes are:
+ OFBA_MSPABI_Tag_ISA 4
+ MSP430 1
+ MSP430X 2
+ OFBA_MSPABI_Tag_Code_Model 6
+ Small 1
+ Large 2
+ OFBA_MSPABI_Tag_Data_Model 8
+ Small 1
+ Large 2
+ Restricted 3 (Unused by GNU)
+ OFBA_MSPABI_Tag_enum_size 10 (Unused by GNU)
+ Note that Code_Model and Data_Model are always equal for GNU.
+ We define a new .gnu_attribute to keep track of the data region used.
+ Tag_GNU_MSP430_Data_Region 4
+ LOWER 1
+ ANY 2
+ See binutils-gdb/include/elf/msp430.h for the full details. */
+static void
+msp430_file_end (void)
+{
+#ifdef HAVE_AS_GNU_ATTRIBUTE
+ /* Enum for tag names. */
+ enum
+ {
+ OFBA_MSPABI_Tag_ISA = 4,
+ OFBA_MSPABI_Tag_Code_Model = 6,
+ OFBA_MSPABI_Tag_Data_Model = 8,
+ Tag_GNU_MSP430_Data_Region = 4
+ };
+ /* Enum for tag values. */
+ enum
+ {
+ OFBA_MSPABI_Val_ISA_MSP430 = 1,
+ OFBA_MSPABI_Val_ISA_MSP430X = 2,
+ OFBA_MSPABI_Val_Model_Small = 1,
+ OFBA_MSPABI_Val_Model_Large = 2,
+ Tag_GNU_MSP430_Data_Region_Lower = 1,
+ Tag_GNU_MSP430_Data_Region_Any = 2
+ };
+ /* .mspabi_attribute is a GNU assembler directive only. The assembler will
+ construct a .MSP430.attributes section based on the options it is invoked
+ with. The values it reads from these directives are used for validating
+ those options. */
+ const char *msp_attr = ".mspabi_attribute";
+ const char *gnu_attr = ".gnu_attribute";
+
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_ISA. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp_attr, OFBA_MSPABI_Tag_ISA,
+ msp430x ? OFBA_MSPABI_Val_ISA_MSP430X : OFBA_MSPABI_Val_ISA_MSP430);
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_Code_Model. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp_attr, OFBA_MSPABI_Tag_Code_Model,
+ TARGET_LARGE ? OFBA_MSPABI_Val_Model_Large
+ : OFBA_MSPABI_Val_Model_Small);
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_Data_Model. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp_attr, OFBA_MSPABI_Tag_Data_Model,
+ TARGET_LARGE ? OFBA_MSPABI_Val_Model_Large
+ : OFBA_MSPABI_Val_Model_Small);
+#ifdef HAVE_AS_MSPABI_ATTRIBUTE
+ /* Emit .gnu_attribute directive for Tag_GNU_MSP430_Data_Region. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", gnu_attr, Tag_GNU_MSP430_Data_Region,
+ msp430_data_region == MSP430_REGION_LOWER
+ ? Tag_GNU_MSP430_Data_Region_Lower
+ : Tag_GNU_MSP430_Data_Region_Any);
+#endif
+#endif
+}
+
bool
msp430_do_not_relax_short_jumps (void)
{
@@ -2031,9 +2153,7 @@ msp430_do_not_relax_short_jumps (void)
end up in a low section. */
return
msp430_code_region == MSP430_REGION_EITHER
- || msp430_code_region == MSP430_REGION_LOWER
- || has_attr (ATTR_EITHER, current_function_decl)
- || has_attr (ATTR_LOWER, current_function_decl);
+ || has_attr (ATTR_EITHER, current_function_decl);
}
enum msp430_builtin
@@ -3074,6 +3194,36 @@ msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
msp430_print_operand_raw (file, addr);
}
+/* Determine whether an RTX is definitely not a MEM referencing an address in
+ the upper memory region. Returns true if we've decided the address will be
+ in the lower memory region, or the RTX is not a MEM. Returns false
+ otherwise. */
+bool
+msp430_op_not_in_high_mem (rtx op)
+{
+ rtx op0;
+
+ if (!TARGET_LARGE || !MEM_P (op))
+ return true;
+
+ op0 = XEXP (op, 0);
+
+ if (SYMBOL_REF_P (op0) && (SYMBOL_REF_FLAGS (op0) & SYMBOL_FLAG_LOW_MEM))
+ /* msp430_encode_section_info decided this mem will be in lower
+ memory. */
+ return true;
+
+ /* Catch (mem (const (plus ((symbol_ref) (const_int))))) e.g. &addr+2. */
+ if ((GET_CODE (op0) == CONST)
+ && (GET_CODE (XEXP (op0, 0)) == PLUS)
+ && (SYMBOL_REF_P (XEXP (XEXP (op0, 0), 0)))
+ && (SYMBOL_REF_FLAGS (XEXP (XEXP (op0, 0), 0)) & SYMBOL_FLAG_LOW_MEM))
+ return true;
+
+ /* Return false when undecided. */
+ return false;
+}
+
#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND msp430_print_operand
@@ -3245,15 +3395,21 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case 'X':
/* This is used to turn, for example, an ADD opcode into an ADDX
- opcode when we're using 20-bit addresses. */
- if (TARGET_LARGE || GET_MODE (op) == PSImode)
+ opcode when we're using 20-bit addresses.
+ This can be used for insns which have only one operand which might be
+ a mem.
+ If an insn has two different operands which could be memory operands,
+ then the "Yx" constraint must be used to determine if the X suffix is
+ required by checking both operands. */
+ if (GET_MODE (op) == PSImode
+ || !msp430_op_not_in_high_mem (op))
fprintf (file, "X");
- /* We don't care which operand we use, but we want 'X' in the MD
- file, so we do it this way. */
return;
case 'x':
- /* Similarly, but only for PSImodes. BIC, for example, needs this. */
+ /* Similarly, but only for PSImodes. BIC, and other insn patterns using
+ the QHI mode iterator (which includes, QI, HI, and PSImode) use
+ this. */
if (GET_MODE (op) == PSImode)
fprintf (file, "X");
return;
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index 3449bd4..f885de2 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -71,7 +71,10 @@ extern bool msp430x;
is enabled (the GDB testsuite relies upon unused entities not being
deleted). */
#define LINK_SPEC "%{mrelax:--relax} %{mlarge:%{!r:%{!g:--gc-sections}}} " \
- "%{mcode-region=*:--code-region=%*} %{mdata-region=*:--data-region=%*}"
+ "%{mcode-region=*:--code-region=%:" \
+ "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
+ "%{mdata-region=*:--data-region=%:" \
+ "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
#define DRIVER_SELF_SPECS \
" %{!mlarge:%{mcode-region=*:%{mdata-region=*:%e-mcode-region and " \
@@ -90,12 +93,16 @@ extern const char * msp430_select_hwmult_lib (int, const char **);
extern const char * msp430_select_cpu (int, const char **);
extern const char * msp430_set_driver_var (int, const char **);
extern const char * msp430_check_path_for_devices (int, const char **);
+extern const char *msp430_propagate_region_opt (int, const char **);
+/* There must be a trailing comma after the last item, see gcc.c
+ "static_spec_functions". */
# define EXTRA_SPEC_FUNCTIONS \
{ "msp430_hwmult_lib", msp430_select_hwmult_lib }, \
{ "msp430_select_cpu", msp430_select_cpu }, \
{ "msp430_set_driver_var", msp430_set_driver_var }, \
- { "msp430_check_path_for_devices", msp430_check_path_for_devices },
+ { "msp430_check_path_for_devices", msp430_check_path_for_devices }, \
+ { "msp430_propagate_region_opt", msp430_propagate_region_opt },
/* Specify the libraries to include on the linker command line.
@@ -482,3 +489,5 @@ typedef struct
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
msp430_output_aligned_decl_common ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+#define SYMBOL_FLAG_LOW_MEM (SYMBOL_FLAG_MACH_DEP << 0)
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index f6d6889..c72f7aa 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -190,22 +190,22 @@
)
(define_insn "movqi"
- [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
+ [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
+ (match_operand:QI 1 "msp_general_operand" "riYsYx,rmi"))]
""
"@
MOV.B\t%1, %0
- MOV%X0.B\t%1, %0"
+ MOVX.B\t%1, %0"
)
(define_insn "movhi"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
- (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))]
+ [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYsYx,rm")
+ (match_operand:HI 1 "msp_general_operand" "N,riYsYx,rmi"))]
""
"@
MOV.B\t%1, %0
MOV.W\t%1, %0
- MOV%X0.W\t%1, %0"
+ MOVX.W\t%1, %0"
)
(define_expand "movsi"
@@ -241,7 +241,7 @@
"msp430_split_movsi (operands);"
)
-;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
+;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
(define_insn "movpsi"
[(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,r,r,Ya,rm")
(match_operand:PSI 1 "msp_general_operand" "N,O,riYa,r,rmi"))]
@@ -289,23 +289,23 @@
)
(define_insn "addqi3"
- [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
+ [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(plus:QI (match_operand:QI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "msp_general_operand" "riYs,rmi")))]
+ (match_operand:QI 2 "msp_general_operand" "riYsYx,rmi")))]
""
"@
ADD.B\t%2, %0
- ADD%X0.B\t%2, %0"
+ ADDX.B\t%2, %0"
)
(define_insn "addhi3"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,rm")
+ [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_general_operand" "riYs,rmi")))]
+ (match_operand:HI 2 "msp_general_operand" "riYsYx,rmi")))]
""
"@
ADD.W\t%2, %0
- ADD%X0.W\t%2, %0"
+ ADDX.W\t%2, %0"
)
; This pattern is needed in order to avoid reload problems.
@@ -317,17 +317,17 @@
(plus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand 2 "general_operand" "rmi")))]
""
- "ADD.W\t%L2, %L0 { ADDC.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
+ "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
)
(define_insn "addsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&rYsYx,rm")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "r,mi")))]
+ (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
""
"@
ADD\t%L2, %L0 { ADDC\t%H2, %H0
- ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
+ ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
)
; Version of addhi that exposes the carry operations, for SImode adds.
@@ -358,9 +358,9 @@
; that are not single_set() very well.
(define_insn "addhi3_cy"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
+ [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_nonimmediate_operand" "r,rm")))
+ (match_operand:HI 2 "msp_nonimmediate_operand" "rYsYxi,rm")))
(set (reg:BI CARRY)
(truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 2)))
@@ -369,7 +369,7 @@
""
"@
ADD\t%2, %1 ; cy
- ADD%X0\t%2, %1 ; cy"
+ ADDX\t%2, %1 ; cy"
)
(define_insn "addhi3_cy_i"
@@ -389,15 +389,15 @@
; Version of addhi that adds the carry, for SImode adds.
(define_insn "addchi4_cy"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
+ [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(plus:HI (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_general_operand" "ri,rmi"))
+ (match_operand:HI 2 "msp_general_operand" "riYsYx,rmi"))
(zero_extend:HI (reg:BI CARRY))))
]
""
"@
ADDC\t%2, %1
- ADDC%X0\t%2, %1"
+ ADDCX\t%2, %1"
)
; Split an SImode add into two HImode adds, keeping track of the carry
@@ -458,36 +458,38 @@
;; Alternatives 2 and 3 are to handle cases generated by reload.
(define_insn "subqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rYsYx, rm, &?r, ?&r")
(minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
- (match_operand:QI 2 "general_operand" " riYs, rmi, rmi, r")))]
+ (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
""
"@
SUB.B\t%2, %0
- SUB%X0.B\t%2, %0
- MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
+ SUBX.B\t%2, %0
+ MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
)
;; Alternatives 2 and 3 are to handle cases generated by reload.
(define_insn "subhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rYsYx, rm, &?r, ?&r")
(minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
- (match_operand:HI 2 "general_operand" " riYs, rmi, rmi, r")))]
+ (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
""
"@
SUB.W\t%2, %0
- SUB%X0.W\t%2, %0
- MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
+ SUBX.W\t%2, %0
+ MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
)
(define_insn "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=&rm")
- (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:SI 2 "general_operand" "rmi")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&rYsYx,m")
+ (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "riYsYx,mi")))]
""
- "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
+ "@
+ SUB\t%L2, %L0 { SUBC\t%H2, %H0
+ SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
)
(define_insn "*bic<mode>_cg"
@@ -501,44 +503,44 @@
)
(define_insn "bic<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand" "rYs,rmn"))
+ [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
+ (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand" "rYsYx,rmn"))
(match_operand:QHI 2 "msp_nonimmediate_operand" "0,0")))]
""
"@
BIC%x0%b0\t%1, %0
- BIC%X0%b0\t%1, %0"
+ BICX%b0\t%1, %0"
)
(define_insn "and<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
+ [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYsYx,rm")
(and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0,0")
- (match_operand:QHI 2 "msp_general_operand" "N,riYs,rmi")))]
+ (match_operand:QHI 2 "msp_general_operand" "N,riYsYx,rmi")))]
""
"@
AND%x0.B\t%2, %0
AND%x0%b0\t%2, %0
- AND%X0%b0\t%2, %0"
+ ANDX%b0\t%2, %0"
)
(define_insn "ior<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
+ [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
+ (match_operand:QHI 2 "msp_general_operand" "riYsYx,rmi")))]
""
"@
BIS%x0%b0\t%2, %0
- BIS%X0%b0\t%2, %0"
+ BISX%b0\t%2, %0"
)
(define_insn "xor<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
+ [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYsYx,rm")
(xor:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
+ (match_operand:QHI 2 "msp_general_operand" "riYsYx,rmi")))]
""
"@
XOR%x0%b0\t%2, %0
- XOR%X0%b0\t%2, %0"
+ XORX%b0\t%2, %0"
)
;; Macro : XOR #~0, %0
@@ -567,7 +569,7 @@
"@
AND\t#0xff, %0
MOV.B\t%1, %0
- MOV%X0.B\t%1, %0
+ MOV%X1.B\t%1, %0
AND%X0\t#0xff, %0"
)
@@ -621,7 +623,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=r")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
""
- "MOV.B\t%1,%L0 { CLR\t%H0"
+ "MOV%X1.B\t%1,%L0 { CLR\t%H0"
)
(define_insn "zero_extendhisi2"
@@ -629,7 +631,7 @@
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))]
""
"@
- MOV.W\t#0,%H0
+ MOV%X0.W\t#0,%H0
MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
)
@@ -782,7 +784,7 @@
(ashift:HI (match_operand:HI 1 "general_operand" "0")
(const_int 1)))]
""
- "RLA.W\t%0" ;; Note - this is a macro for ADD
+ "RLA%X0.W\t%0" ;; Note - this is a macro for ADD
)
(define_insn "430x_shift_left"
@@ -802,7 +804,7 @@
(ashift:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "RLA.W\t%L0 { RLC.W\t%H0"
+ "RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
)
(define_insn "slll_2"
@@ -810,7 +812,7 @@
(ashift:SI (match_operand:SI 1 "general_operand" "0")
(const_int 2)))]
""
- "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
+ "RLA%X0.W\t%L0 { RLC%X0.W\t%H0 { RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
)
(define_expand "ashlsi3"
@@ -867,7 +869,7 @@
(ashiftrt:HI (match_operand:HI 1 "msp_general_operand" "0")
(const_int 1)))]
""
- "RRA.W\t%0"
+ "RRA%X0.W\t%0"
)
(define_insn "430x_arithmetic_shift_right"
@@ -903,7 +905,7 @@
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "RRA.W\t%H0 { RRC.W\t%L0"
+ "RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_insn "sral_2"
@@ -911,7 +913,7 @@
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 2)))]
""
- "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
+ "RRA%X0.W\t%H0 { RRC%X0.W\t%L0 { RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_expand "ashrsi3"
@@ -968,7 +970,7 @@
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
(const_int 1)))]
""
- "CLRC { RRC.W\t%0"
+ "CLRC { RRC%X0.W\t%0"
)
(define_insn "430x_logical_shift_right"
@@ -994,7 +996,7 @@
(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
+ "CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_insn "srll_2x"
@@ -1188,8 +1190,8 @@
(define_insn "cbranchqi4_real"
[(set (pc) (if_then_else
(match_operator 0 "msp430_cmp_operator"
- [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
- (match_operand:QI 2 "general_operand" "rYsi,rmi")])
+ [(match_operand:QI 1 "nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QI 2 "general_operand" "rYsYxi,rmi")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1197,14 +1199,14 @@
""
"@
CMP.B\t%2, %1 { J%0\t%l3
- CMP%X0.B\t%2, %1 { J%0\t%l3"
+ CMPX.B\t%2, %1 { J%0\t%l3"
)
(define_insn "cbranchhi4_real"
[(set (pc) (if_then_else
(match_operator 0 "msp430_cmp_operator"
- [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
- (match_operand:HI 2 "general_operand" "rYsi,rmi")])
+ [(match_operand:HI 1 "nonimmediate_operand" "rYsYx,rm")
+ (match_operand:HI 2 "general_operand" "rYsYxi,rmi")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1222,12 +1224,12 @@
{
return which_alternative == 0 ?
\"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
- \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
+ \"CMPX.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
}
return which_alternative == 0 ?
\"CMP.W\t%2, %1 { J%0\t%l3\" :
- \"CMP%X0.W\t%2, %1 { J%0\t%l3\";
+ \"CMPX.W\t%2, %1 { J%0\t%l3\";
"
[(set (attr "length")
(if_then_else
@@ -1257,8 +1259,8 @@
(define_insn "cbranchqi4_reversed"
[(set (pc) (if_then_else
(match_operator 0 "msp430_reversible_cmp_operator"
- [(match_operand:QI 1 "general_operand" "rYsi,rmi")
- (match_operand:QI 2 "general_operand" "rYs,rm")])
+ [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
+ (match_operand:QI 2 "general_operand" "rYsYx,rm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1266,14 +1268,14 @@
""
"@
CMP.B\t%1, %2 { J%R0\t%l3
- CMP%X0.B\t%1, %2 { J%R0\t%l3"
+ CMPX.B\t%1, %2 { J%R0\t%l3"
)
(define_insn "cbranchhi4_reversed"
[(set (pc) (if_then_else
(match_operator 0 "msp430_reversible_cmp_operator"
- [(match_operand:HI 1 "general_operand" "rYsi,rmi")
- (match_operand:HI 2 "general_operand" "rYs,rm")])
+ [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
+ (match_operand:HI 2 "general_operand" "rYsYx,rm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1281,13 +1283,13 @@
""
"@
CMP.W\t%1, %2 { J%R0\t%l3
- CMP%X0.W\t%1, %2 { J%R0\t%l3"
+ CMPX.W\t%1, %2 { J%R0\t%l3"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
- (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi"))
+ (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp_general_operand" "rYsYxi,rmi"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
@@ -1296,46 +1298,52 @@
""
"@
BIT%x0%b0\t%1, %0 { JNE\t%l2
- BIT%X0%b0\t%1, %0 { JNE\t%l2"
+ BITX%b0\t%1, %0 { JNE\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp_general_operand" "rYsYxi,rmi"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
""
- "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JEQ\t%l2
+ BITX%b0\t%1, %0 { JEQ\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp_general_operand" "rYsYxi,rmi"))
(const_int 0))
(pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
- "BIT%X0%b0\t%1, %0 { JNE\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JNE\t%l2
+ BITX%b0\t%1, %0 { JNE\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp_general_operand" "rYsYxi,rmi"))
(const_int 0))
(pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
- "BIT%X0%b0\t%1, %0 { JEQ\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JEQ\t%l2
+ BITX%b0\t%1, %0 { JEQ\t%l2"
)
;;------------------------------------------------------------
@@ -1368,7 +1376,7 @@
(clobber (reg:BI CARRY))
]
""
- "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2"
+ "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
)
(define_insn "*bitbranch<mode>4_z"
diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt
index cbbe0fa..2db2906 100644
--- a/gcc/config/msp430/msp430.opt
+++ b/gcc/config/msp430/msp430.opt
@@ -67,12 +67,16 @@ EnumValue
Enum(msp430_hwmult_types) String(f5series) Value(MSP430_HWMULT_F5SERIES)
mcode-region=
-Target Joined RejectNegative Report ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_ANY)
-Specify whether functions should be placed into low or high memory.
+Target Joined RejectNegative Report ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Specify whether functions should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
mdata-region=
-Target Joined RejectNegative Report ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_ANY)
-Specify whether variables should be placed into low or high memory.
+Target Joined RejectNegative Report ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Specify whether variables should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
+
+muse-lower-region-prefix
+Target Mask(USE_LOWER_REGION_PREFIX) Report
+Add the .lower prefix to section names when compiling with -m{code,data}-region=lower (disabled by default).
Enum
Name(msp430_regions) Type(enum msp430_regions)
diff --git a/gcc/config/msp430/t-msp430 b/gcc/config/msp430/t-msp430
index b956510..f8ba775 100644
--- a/gcc/config/msp430/t-msp430
+++ b/gcc/config/msp430/t-msp430
@@ -28,17 +28,22 @@ msp430-devices.o: $(srcdir)/config/msp430/msp430-devices.c \
# Enable multilibs:
-MULTILIB_OPTIONS = mcpu=msp430 mlarge
-MULTILIB_DIRNAMES = 430 large
+MULTILIB_OPTIONS = mcpu=msp430 mlarge mdata-region=none
+MULTILIB_DIRNAMES = 430 large full-memory-range
# Match -mcpu=430
MULTILIB_MATCHES = mcpu?msp430=mcpu?430
+# These options are equivalent in terms of the multilib required for them
+MULTILIB_MATCHES += mdata-region?none=mdata-region?upper
+MULTILIB_MATCHES += mdata-region?none=mdata-region?either
# The correct multilib for a given mmcu is selected without the need for
# hard-coded data here, because DRIVER_SELF_SPECS will place the correct
# -mcpu option for a given mcu onto the command line.
-MULTILIB_EXCEPTIONS = mcpu=msp430/mlarge
+MULTILIB_REQUIRED = mcpu=msp430
+MULTILIB_REQUIRED += mlarge
+MULTILIB_REQUIRED += mlarge/mdata-region=none
MULTILIB_EXTRA_OPTS =