aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/nios2
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/nios2')
-rw-r--r--gcc/config/nios2/constraints.md4
-rw-r--r--gcc/config/nios2/nios2-protos.h1
-rw-r--r--gcc/config/nios2/nios2.c94
-rw-r--r--gcc/config/nios2/nios2.opt6
4 files changed, 88 insertions, 17 deletions
diff --git a/gcc/config/nios2/constraints.md b/gcc/config/nios2/constraints.md
index c6c53926..51f71cf 100644
--- a/gcc/config/nios2/constraints.md
+++ b/gcc/config/nios2/constraints.md
@@ -95,8 +95,8 @@
(match_test "TARGET_ARCH_R2 && ANDCLEAR_INT (ival)")))
(define_constraint "S"
- "An immediate stored in small data, accessible by GP."
- (match_test "gprel_constant_p (op)"))
+ "An immediate stored in small data, accessible by GP, or by offset from r0."
+ (match_test "gprel_constant_p (op) || r0rel_constant_p (op)"))
(define_constraint "T"
"A constant unspec offset representing a relocation."
diff --git a/gcc/config/nios2/nios2-protos.h b/gcc/config/nios2/nios2-protos.h
index 6df65bb..84d450b 100644
--- a/gcc/config/nios2/nios2-protos.h
+++ b/gcc/config/nios2/nios2-protos.h
@@ -52,6 +52,7 @@ extern const char * nios2_add_insn_asm (rtx_insn *, rtx *);
extern bool nios2_legitimate_pic_operand_p (rtx);
extern bool gprel_constant_p (rtx);
+extern bool r0rel_constant_p (rtx);
extern bool nios2_regno_ok_for_base_p (int, bool);
extern bool nios2_unspec_reloc_p (rtx);
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 3aade7b..cdd5e9a 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -106,6 +106,7 @@ static bool custom_code_conflict = false;
/* State for command-line options. */
regex_t nios2_gprel_sec_regex;
+regex_t nios2_r0rel_sec_regex;
/* Definition of builtin function types for nios2. */
@@ -1375,22 +1376,30 @@ nios2_option_override (void)
nios2_gpopt_option = gpopt_local;
}
- /* GP-relative addressing doesn't make sense for PIC. */
+ /* GP-relative and r0-relative addressing don't make sense for PIC. */
if (flag_pic)
- {
+ {
if (nios2_gpopt_option != gpopt_none)
- error ("-mgpopt not supported with PIC.");
+ error ("-mgpopt not supported with PIC.");
if (nios2_gprel_sec)
- error ("-mgprel-sec= not supported with PIC.");
+ error ("-mgprel-sec= not supported with PIC.");
+ if (nios2_r0rel_sec)
+ error ("-mr0rel-sec= not supported with PIC.");
}
- /* Process -mgprel-sec=. */
+ /* Process -mgprel-sec= and -m0rel-sec=. */
if (nios2_gprel_sec)
{
if (regcomp (&nios2_gprel_sec_regex, nios2_gprel_sec,
REG_EXTENDED | REG_NOSUB))
error ("-mgprel-sec= argument is not a valid regular expression.");
}
+ if (nios2_r0rel_sec)
+ {
+ if (regcomp (&nios2_r0rel_sec_regex, nios2_r0rel_sec,
+ REG_EXTENDED | REG_NOSUB))
+ error ("-mr0rel-sec= argument is not a valid regular expression.");
+ }
/* If we don't have mul, we don't have mulx either! */
if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
@@ -1478,7 +1487,7 @@ nios2_rtx_costs (rtx x, machine_mode mode,
case SYMBOL_REF:
case CONST:
case CONST_DOUBLE:
- if (gprel_constant_p (x))
+ if (gprel_constant_p (x) || r0rel_constant_p (x))
{
*total = COSTS_N_INSNS (1);
return true;
@@ -2028,6 +2037,7 @@ nios2_symbolic_constant_p (rtx x)
return (SYMBOL_REF_P (base)
&& !SYMBOL_REF_TLS_MODEL (base)
&& !gprel_constant_p (base)
+ && !r0rel_constant_p (base)
&& SMALL_INT (INTVAL (offset)));
}
return false;
@@ -2129,7 +2139,7 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
/* Else, fall through. */
case CONST:
- if (gprel_constant_p (operand))
+ if (gprel_constant_p (operand) || r0rel_constant_p (operand))
return true;
/* Else, fall through. */
@@ -2294,6 +2304,14 @@ nios2_small_section_name_p (const char *section)
&& regexec (&nios2_gprel_sec_regex, section, 0, NULL, 0) == 0));
}
+/* Return true if SECTION is a r0-relative section name. */
+static bool
+nios2_r0rel_section_name_p (const char *section)
+{
+ return (nios2_r0rel_sec
+ && regexec (&nios2_r0rel_sec_regex, section, 0, NULL, 0) == 0);
+}
+
/* Return true if EXP should be placed in the small data section. */
static bool
nios2_in_small_data_p (const_tree exp)
@@ -2400,6 +2418,33 @@ nios2_symbol_ref_in_small_data_p (rtx sym)
}
}
+/* Likewise for r0-relative addressing. */
+static bool
+nios2_symbol_ref_in_r0rel_data_p (rtx sym)
+{
+ tree decl;
+
+ gcc_assert (GET_CODE (sym) == SYMBOL_REF);
+ decl = SYMBOL_REF_DECL (sym);
+
+ /* TLS variables are not accessed through r0. */
+ if (SYMBOL_REF_TLS_MODEL (sym) != 0)
+ return false;
+
+ /* On Nios II R2, there is no r0-relative relocation that can be
+ used with "io" instructions. So, if we are implicitly generating
+ those instructions, we cannot emit r0-relative accesses. */
+ if (TARGET_ARCH_R2
+ && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
+ return false;
+
+ /* If the user has explicitly placed the symbol in a r0rel section
+ via an attribute, generate r0-relative addressing. */
+ if (decl && DECL_SECTION_NAME (decl))
+ return nios2_r0rel_section_name_p (DECL_SECTION_NAME (decl));
+ return false;
+}
+
/* Implement TARGET_SECTION_TYPE_FLAGS. */
static unsigned int
@@ -2633,8 +2678,9 @@ nios2_emit_move_sequence (rtx *operands, machine_mode mode)
return true;
}
}
- else if (gprel_constant_p (from))
- /* Handled directly by movsi_internal as gp + offset. */
+ else if (gprel_constant_p (from) || r0rel_constant_p (from))
+ /* Handled directly by movsi_internal as gp + offset
+ or r0 + offset. */
;
else if (nios2_large_constant_p (from))
/* This case covers either a regular symbol reference or an UNSPEC
@@ -2984,6 +3030,20 @@ gprel_constant_p (rtx op)
return false;
}
+/* Likewise if this is a zero-relative accessible reference. */
+bool
+r0rel_constant_p (rtx op)
+{
+ if (GET_CODE (op) == SYMBOL_REF
+ && nios2_symbol_ref_in_r0rel_data_p (op))
+ return true;
+ else if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS)
+ return r0rel_constant_p (XEXP (XEXP (op, 0), 0));
+
+ return false;
+}
+
/* Return the name string for a supported unspec reloc offset. */
static const char *
nios2_unspec_reloc_name (int unspec)
@@ -3048,7 +3108,13 @@ nios2_print_operand_address (FILE *file, machine_mode mode, rtx op)
fprintf (file, ")(%s)", reg_names[GP_REGNO]);
return;
}
-
+ else if (r0rel_constant_p (op))
+ {
+ fprintf (file, "%%lo(");
+ output_addr_const (file, op);
+ fprintf (file, ")(r0)");
+ return;
+ }
break;
case PLUS:
@@ -4654,8 +4720,8 @@ nios2_cdx_narrow_form_p (rtx_insn *insn)
|| TARGET_BYPASS_CACHE)
return false;
addr = XEXP (mem, 0);
- /* GP-based references are never narrow. */
- if (gprel_constant_p (addr))
+ /* GP-based and R0-based references are never narrow. */
+ if (gprel_constant_p (addr) || r0rel_constant_p (addr))
return false;
/* %lo requires a 16-bit relocation and is never narrow. */
if (GET_CODE (addr) == LO_SUM)
@@ -4701,8 +4767,8 @@ nios2_cdx_narrow_form_p (rtx_insn *insn)
|| TARGET_BYPASS_CACHE)
return false;
addr = XEXP (mem, 0);
- /* GP-based references are never narrow. */
- if (gprel_constant_p (addr))
+ /* GP-based and r0-based references are never narrow. */
+ if (gprel_constant_p (addr) || r0rel_constant_p (addr))
return false;
/* %lo requires a 16-bit relocation and is never narrow. */
if (GET_CODE (addr) == LO_SUM)
diff --git a/gcc/config/nios2/nios2.opt b/gcc/config/nios2/nios2.opt
index d08405e..a50dbee 100644
--- a/gcc/config/nios2/nios2.opt
+++ b/gcc/config/nios2/nios2.opt
@@ -589,4 +589,8 @@ Enable generation of R2 CDX instructions.
mgprel-sec=
Target RejectNegative Joined Var(nios2_gprel_sec) Init(NULL)
-Regular expression matching additional GP-addressible small-data section names.
+Regular expression matching additional GP-addressible section names.
+
+mr0rel-sec=
+Target RejectNegative Joined Var(nios2_r0rel_sec) Init(NULL)
+Regular expression matching section names for r0-relative addressing.