summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-05 15:07:21 +0000
committernickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-05 15:07:21 +0000
commit6e5073011542bb3b0ba144b74c2054fda70ed8b1 (patch)
treee5fb262a785e8b7adabd978c621ce0fdb1684ad5 /gcc
parent87b533973970ef09f94167d428fbc63331045d96 (diff)
downloadgcc-6e5073011542bb3b0ba144b74c2054fda70ed8b1.tar.gz
* config/rx/rx.opt (mpid): Define.
* config/rx/t-rx (MULTILIB_OPTIONS): Add -mpid (MULTILIB_DIRNAMES): Add pid. * config/rx/rx.c (rx_gp_base_regnum_val, rx_pid_base_regnum_val) (rx_num_interrupt_regs): New variable. (rx_gp_base_regnum): New function. Returns the number of the small data area register. (rx_pid_base_regnum): New function. Returns the number of the pid base register. (rx_decl_for_addr): New function. Returns the symbolic part of a MEM. (rx_pid_data_operand): New function. Returns whether an object is in the position independent data area. (rx_legitimize_address): New function. Puts undecided PID objects in the PID data area. (rx_is_legitimate_address): Add support for PID operands. (rx_print_operand_address): Likewise. (rx_print_operand): Likewise. (rx_maybe_pidify_operand): New function. Determine if an operand is suitable for PID addressing. (rx_gen_move_template): Add PID support. (rx_conditional_register_usage): Likewise. (rx_option_override): Initialise rx_num_interrupt_regs. (rx_is_legitimate_constant): Add support for PID constants. (TARGET_LEGITIMIZE_ADDRESS): Define. * config/rx/constraints.md (Rpid): Define. (Rpda): Define. * config/rx/rx.md (UNSPEC_PID_ADDR): Define. (tablejump): Add PID support. (mov<>): Likewise. (mov<>_internal): Likewise. (addsi3): Convert to an expander. Add PID support. (pid_addr): New pattern. * config/rx/rx.h (CPP_SPEC): Define. (ASM_SPEC): Pass -mpid and -mint-register on to assembler. (CASE_VECTOR_PC_RELATIVE): Define. (JUMP_TABLES_IN_TEXT_SECTION): Enable for PID mode. * config/rx/rx-protos.h (rx_maybe_pidify_operand): Prototype. * doc/invoke.texi (RX Options): Document -mpid command line option. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179558 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog44
-rw-r--r--gcc/config/rx/constraints.md22
-rw-r--r--gcc/config/rx/rx-protos.h1
-rw-r--r--gcc/config/rx/rx.c246
-rw-r--r--gcc/config/rx/rx.h32
-rw-r--r--gcc/config/rx/rx.md52
-rw-r--r--gcc/config/rx/rx.opt6
-rw-r--r--gcc/config/rx/t-rx4
-rw-r--r--gcc/doc/invoke.texi46
9 files changed, 412 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e6bf96d9c92..4bdda3dff02 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,47 @@
+2011-10-05 DJ Delorie <dj@redhat.com>
+ Nick Clifton <nickc@redhat.com>
+
+ * config/rx/rx.opt (mpid): Define.
+ * config/rx/t-rx (MULTILIB_OPTIONS): Add -mpid
+ (MULTILIB_DIRNAMES): Add pid.
+ * config/rx/rx.c (rx_gp_base_regnum_val, rx_pid_base_regnum_val)
+ (rx_num_interrupt_regs): New variable.
+ (rx_gp_base_regnum): New function. Returns the number of the
+ small data area register.
+ (rx_pid_base_regnum): New function. Returns the number of the pid
+ base register.
+ (rx_decl_for_addr): New function. Returns the symbolic part of a
+ MEM.
+ (rx_pid_data_operand): New function. Returns whether an object is
+ in the position independent data area.
+ (rx_legitimize_address): New function. Puts undecided PID
+ objects in the PID data area.
+ (rx_is_legitimate_address): Add support for PID operands.
+ (rx_print_operand_address): Likewise.
+ (rx_print_operand): Likewise.
+ (rx_maybe_pidify_operand): New function. Determine if an operand
+ is suitable for PID addressing.
+ (rx_gen_move_template): Add PID support.
+ (rx_conditional_register_usage): Likewise.
+ (rx_option_override): Initialise rx_num_interrupt_regs.
+ (rx_is_legitimate_constant): Add support for PID constants.
+ (TARGET_LEGITIMIZE_ADDRESS): Define.
+ * config/rx/constraints.md (Rpid): Define.
+ (Rpda): Define.
+ * config/rx/rx.md (UNSPEC_PID_ADDR): Define.
+ (tablejump): Add PID support.
+ (mov<>): Likewise.
+ (mov<>_internal): Likewise.
+ (addsi3): Convert to an expander. Add PID support.
+ (pid_addr): New pattern.
+ * config/rx/rx.h (CPP_SPEC): Define.
+ (ASM_SPEC): Pass -mpid and -mint-register on to assembler.
+ (CASE_VECTOR_PC_RELATIVE): Define.
+ (JUMP_TABLES_IN_TEXT_SECTION): Enable for PID mode.
+ * config/rx/rx-protos.h (rx_maybe_pidify_operand): Prototype.
+ * doc/invoke.texi (RX Options): Document -mpid command line
+ option.
+
2011-10-05 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38885
diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md
index 9f7dc9ff816..7822914acbb 100644
--- a/gcc/config/rx/constraints.md
+++ b/gcc/config/rx/constraints.md
@@ -1,5 +1,5 @@
;; Constraint definitions for Renesas RX.
-;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2009, 2010. 2011 Free Software Foundation, Inc.
;; Contributed by Red Hat.
;;
;; This file is part of GCC.
@@ -86,3 +86,23 @@
)
)
)
+
+(define_constraint "Rpid"
+ "A MEM to a PID variable"
+ (and (match_code "mem")
+ (and (match_code "plus" "0")
+ (and (match_code "reg,subreg" "00")
+ (match_code "unspec" "01")
+ )
+ )
+ )
+)
+
+(define_constraint "Rpda"
+ "An address to a PID variable"
+ (and (match_code "plus" "")
+ (and (match_code "reg,subreg" "0")
+ (match_code "unspec" "1")
+ )
+ )
+)
diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h
index 56d69316905..365bf66babd 100644
--- a/gcc/config/rx/rx-protos.h
+++ b/gcc/config/rx/rx-protos.h
@@ -35,6 +35,7 @@ extern bool rx_is_legitimate_constant (enum machine_mode, rtx);
extern bool rx_is_restricted_memory_address (rtx,
enum machine_mode);
extern bool rx_match_ccmode (rtx, enum machine_mode);
+extern rtx rx_maybe_pidify_operand (rtx, int);
extern void rx_notice_update_cc (rtx, rtx);
extern void rx_split_cbranch (enum machine_mode, enum rtx_code,
rtx, rtx, rtx);
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index dcf693a6337..6ff9418c9d8 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -51,7 +51,43 @@
#include "target-def.h"
#include "langhooks.h"
#include "opts.h"
+
+static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_num_interrupt_regs;
+static unsigned int
+rx_gp_base_regnum (void)
+{
+ if (rx_gp_base_regnum_val == INVALID_REGNUM)
+ gcc_unreachable ();
+ return rx_gp_base_regnum_val;
+}
+
+static unsigned int
+rx_pid_base_regnum (void)
+{
+ if (rx_pid_base_regnum_val == INVALID_REGNUM)
+ gcc_unreachable ();
+ return rx_pid_base_regnum_val;
+}
+
+/* Find a SYMBOL_REF in a "standard" MEM address and return its decl. */
+
+static tree
+rx_decl_for_addr (rtx op)
+{
+ if (GET_CODE (op) == MEM)
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+ while (GET_CODE (op) == PLUS)
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == SYMBOL_REF)
+ return SYMBOL_REF_DECL (op);
+ return NULL_TREE;
+}
+
static void rx_print_operand (FILE *, rtx, int);
#define CC_FLAG_S (1 << 0)
@@ -63,6 +99,67 @@ static void rx_print_operand (FILE *, rtx, int);
static unsigned int flags_from_mode (enum machine_mode mode);
static unsigned int flags_from_code (enum rtx_code code);
+/* Return true if OP is a reference to an object in a PID data area. */
+
+enum pid_type
+{
+ PID_NOT_PID = 0, /* The object is not in the PID data area. */
+ PID_ENCODED, /* The object is in the PID data area. */
+ PID_UNENCODED /* The object will be placed in the PID data area, but it has not been placed there yet. */
+};
+
+static enum pid_type
+rx_pid_data_operand (rtx op)
+{
+ tree op_decl;
+
+ if (!TARGET_PID)
+ return PID_NOT_PID;
+
+ if (GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 0)) == REG
+ && GET_CODE (XEXP (op, 1)) == CONST
+ && GET_CODE (XEXP (XEXP (op, 1), 0)) == UNSPEC)
+ return PID_ENCODED;
+
+ op_decl = rx_decl_for_addr (op);
+
+ if (op_decl)
+ {
+ if (TREE_READONLY (op_decl))
+ return PID_UNENCODED;
+ }
+ else
+ {
+ /* Sigh, some special cases. */
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF)
+ return PID_UNENCODED;
+ }
+
+ return PID_NOT_PID;
+}
+
+static rtx
+rx_legitimize_address (rtx x,
+ rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (rx_pid_data_operand (x) == PID_UNENCODED)
+ {
+ rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);
+ return rv;
+ }
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && REG_P (XEXP (XEXP (x, 0), 0))
+ && REG_P (XEXP (x, 1)))
+ return force_reg (SImode, x);
+
+ return x;
+}
+
/* Return true if OP is a reference to an object in a small data area. */
static bool
@@ -93,6 +190,16 @@ rx_is_legitimate_address (enum machine_mode mode, rtx x,
Post-increment Register Indirect. */
return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
+ switch (rx_pid_data_operand (x))
+ {
+ case PID_UNENCODED:
+ return false;
+ case PID_ENCODED:
+ return true;
+ default:
+ break;
+ }
+
if (GET_CODE (x) == PLUS)
{
rtx arg1 = XEXP (x, 0);
@@ -337,15 +444,17 @@ rx_print_operand_address (FILE * file, rtx addr)
{
addr = XEXP (addr, 0);
gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
-
- addr = XVECEXP (addr, 0, 0);
+
+ /* FIXME: Putting this case label here is an appalling abuse of the C language. */
+ case UNSPEC:
+ addr = XVECEXP (addr, 0, 0);
gcc_assert (CONST_INT_P (addr));
}
/* Fall through. */
case LABEL_REF:
case SYMBOL_REF:
fprintf (file, "#");
-
+ /* Fall through. */
default:
output_addr_const (file, addr);
break;
@@ -389,9 +498,11 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
%B Print an integer comparison name.
%C Print a control register name.
%F Print a condition code flag name.
+ %G Register used for small-data-area addressing
%H Print high part of a DImode register, integer or address.
%L Print low part of a DImode register, integer or address.
%N Print the negation of the immediate value.
+ %P Register used for PID addressing
%Q If the operand is a MEM, then correctly generate
register indirect or register relative addressing.
%R Like %Q but for zero-extending loads. */
@@ -400,6 +511,16 @@ static void
rx_print_operand (FILE * file, rtx op, int letter)
{
bool unsigned_load = false;
+ bool print_hash = true;
+
+ if (letter == 'A'
+ && ((GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC)
+ || GET_CODE (op) == UNSPEC))
+ {
+ print_hash = false;
+ letter = 0;
+ }
switch (letter)
{
@@ -538,6 +659,10 @@ rx_print_operand (FILE * file, rtx op, int letter)
}
break;
+ case 'G':
+ fprintf (file, "%s", reg_names [rx_gp_base_regnum ()]);
+ break;
+
case 'H':
switch (GET_CODE (op))
{
@@ -599,6 +724,10 @@ rx_print_operand (FILE * file, rtx op, int letter)
rx_print_integer (file, - INTVAL (op));
break;
+ case 'P':
+ fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
+ break;
+
case 'R':
gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
unsigned_load = true;
@@ -667,6 +796,24 @@ rx_print_operand (FILE * file, rtx op, int letter)
/* Fall through. */
default:
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC)
+ op = XEXP (op, 0);
+ else if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ {
+ if (print_hash)
+ fprintf (file, "#");
+ fprintf (file, "(");
+ rx_print_operand (file, XEXP (XEXP (op, 0), 0), 'A');
+ fprintf (file, " + ");
+ output_addr_const (file, XEXP (XEXP (op, 0), 1));
+ fprintf (file, ")");
+ return;
+ }
+
switch (GET_CODE (op))
{
case MULT:
@@ -721,20 +868,52 @@ rx_print_operand (FILE * file, rtx op, int letter)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- fprintf (file, TARGET_AS100_SYNTAX ? "#0%lxH" : "#0x%lx", val);
+ if (print_hash)
+ fprintf (file, "#");
+ fprintf (file, TARGET_AS100_SYNTAX ? "0%lxH" : "0x%lx", val);
break;
}
case CONST_INT:
- fprintf (file, "#");
+ if (print_hash)
+ fprintf (file, "#");
rx_print_integer (file, INTVAL (op));
break;
- case SYMBOL_REF:
+ case UNSPEC:
+ switch (XINT (op, 1))
+ {
+ case UNSPEC_PID_ADDR:
+ {
+ rtx sym, add;
+
+ if (print_hash)
+ fprintf (file, "#");
+ sym = XVECEXP (op, 0, 0);
+ add = NULL_RTX;
+ fprintf (file, "(");
+ if (GET_CODE (sym) == PLUS)
+ {
+ add = XEXP (sym, 1);
+ sym = XEXP (sym, 0);
+ }
+ output_addr_const (file, sym);
+ if (add != NULL_RTX)
+ {
+ fprintf (file, "+");
+ output_addr_const (file, add);
+ }
+ fprintf (file, "-__pid_base");
+ fprintf (file, ")");
+ return;
+ }
+ }
+ /* Fall through */
+
case CONST:
+ case SYMBOL_REF:
case LABEL_REF:
case CODE_LABEL:
- case UNSPEC:
rx_print_operand_address (file, op);
break;
@@ -745,6 +924,29 @@ rx_print_operand (FILE * file, rtx op, int letter)
}
}
+/* Maybe convert an operand into its PID format. */
+
+rtx
+rx_maybe_pidify_operand (rtx op, int copy_to_reg)
+{
+ if (rx_pid_data_operand (op) == PID_UNENCODED)
+ {
+ if (GET_CODE (op) == MEM)
+ {
+ rtx a = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), XEXP (op, 0));
+ op = replace_equiv_address (op, a);
+ }
+ else
+ {
+ op = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), op);
+ }
+
+ if (copy_to_reg)
+ op = copy_to_mode_reg (GET_MODE (op), op);
+ }
+ return op;
+}
+
/* Returns an assembler template for a move instruction. */
char *
@@ -784,13 +986,15 @@ rx_gen_move_template (rtx * operands, bool is_movu)
gcc_unreachable ();
}
- if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
- src_template = "%%gp(%A1)[r13]";
+ if (MEM_P (src) && rx_pid_data_operand (XEXP (src, 0)) == PID_UNENCODED)
+ src_template = "(%A1-__pid_base)[%P1]";
+ else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
+ src_template = "%%gp(%A1)[%G1]";
else
src_template = "%1";
if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
- dst_template = "%%gp(%A0)[r13]";
+ dst_template = "%%gp(%A0)[%G0]";
else
dst_template = "%0";
@@ -996,8 +1200,21 @@ rx_conditional_register_usage (void)
{
static bool using_fixed_regs = false;
+ if (TARGET_PID)
+ {
+ rx_pid_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+ fixed_regs[rx_pid_base_regnum_val] = call_used_regs [rx_pid_base_regnum_val] = 1;
+ }
+
if (rx_small_data_limit > 0)
- fixed_regs[GP_BASE_REGNUM] = call_used_regs [GP_BASE_REGNUM] = 1;
+ {
+ if (TARGET_PID)
+ rx_gp_base_regnum_val = rx_pid_base_regnum_val - 1;
+ else
+ rx_gp_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+
+ fixed_regs[rx_gp_base_regnum_val] = call_used_regs [rx_gp_base_regnum_val] = 1;
+ }
if (use_fixed_regs != using_fixed_regs)
{
@@ -2338,8 +2555,10 @@ rx_option_override (void)
fixed_regs[13] = call_used_regs [13] = 1;
/* Fall through. */
case 0:
+ rx_num_interrupt_regs = opt->value;
break;
default:
+ rx_num_interrupt_regs = 0;
/* Error message already given because rx_handle_option
returned false. */
break;
@@ -2444,7 +2663,7 @@ rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
return true;
case UNSPEC:
- return XINT (x, 1) == UNSPEC_CONST;
+ return XINT (x, 1) == UNSPEC_CONST || XINT (x, 1) == UNSPEC_PID_ADDR;
default:
/* FIXME: Can this ever happen ? */
@@ -3031,6 +3250,9 @@ rx_adjust_insn_length (rtx insn, int current_length)
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rx_is_legitimate_constant
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS rx_legitimize_address
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rx.h"
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index 67e8ce1c577..10b16bda261 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -63,6 +63,13 @@
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+#undef CPP_SPEC
+#define CPP_SPEC "\
+%{mpid:-D_RX_PID=1} \
+%{mint-register=*:-D_RX_INT_REGISTERS=%*} \
+%{msmall-data-limit*:-D_RX_SMALL_DATA} \
+"
+
#undef ASM_SPEC
#define ASM_SPEC "\
%{mbig-endian-data:-mbig-endian-data} \
@@ -70,6 +77,8 @@
%{!m64bit-doubles:-m32bit-doubles} \
%{msmall-data-limit*:-msmall-data-limit} \
%{mrelax:-relax} \
+%{mpid} \
+%{mint-register=*} \
"
#undef LIB_SPEC
@@ -200,14 +209,17 @@ enum reg_class
#define STRUCT_VAL_REGNUM 15
#define CC_REGNUM 16
-/* This is the register which is used to hold the address of the start
- of the small data area, if that feature is being used. Note - this
- register must not be call_used because otherwise library functions
- that are compiled without small data support might clobber it.
+/* This is the register which will probably be used to hold the address of
+ the start of the small data area, if -msmall-data-limit is being used,
+ or the address of the constant data area if -mpid is being used. If both
+ features are in use then two consecutive registers will be used.
- FIXME: The function gcc/config/rx/rx.c:rx_gen_move_template() has a
- built in copy of this register's name, rather than constructing the
- name from this #define. */
+ Note - these registers must not be call_used because otherwise library
+ functions that are compiled without -msmall-data-limit/-mpid support
+ might clobber them.
+
+ Note that the actual values used depends on other options; use
+ rx_gp_base_regnum() and rx_pid_base_regnum() instead. */
#define GP_BASE_REGNUM 13
#define ELIMINABLE_REGS \
@@ -444,13 +456,15 @@ typedef unsigned int CUMULATIVE_ARGS;
VALUE)
/* This is how to output an element of a case-vector that is relative.
- Note: The local label referenced by the "3b" below is emitted by
+ Note: The local label referenced by the "1b" below is emitted by
the tablejump insn. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
fprintf (FILE, TARGET_AS100_SYNTAX \
? "\t.LWORD L%d - ?-\n" : "\t.long .L%d - 1b\n", VALUE)
+#define CASE_VECTOR_PC_RELATIVE (TARGET_PID)
+
#define ASM_OUTPUT_SIZE_DIRECTIVE(STREAM, NAME, SIZE) \
do \
{ \
@@ -595,7 +609,7 @@ typedef unsigned int CUMULATIVE_ARGS;
/* For PIC put jump tables into the text section so that the offsets that
they contain are always computed between two same-section symbols. */
-#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
+#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_PID || flag_pic)
/* This is a version of REG_P that also returns TRUE for SUBREGs. */
#define RX_REG_P(rtl) (REG_P (rtl) || GET_CODE (rtl) == SUBREG)
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index 5ce1c3976f3..708f9444ca9 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -73,6 +73,8 @@
(UNSPEC_BUILTIN_SAT 49)
(UNSPEC_BUILTIN_SETPSW 50)
(UNSPEC_BUILTIN_WAIT 51)
+
+ (UNSPEC_PID_ADDR 52)
]
)
@@ -330,9 +332,9 @@
(match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
- { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
- : "\n1:\tbra\t%0")
- : "\n1:jmp\t%0";
+ { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
+ : "\n1:\tbra\t%0")
+ : "\n1:jmp\t%0";
}
[(set_attr "timings" "33")
(set_attr "length" "2")]
@@ -556,8 +558,18 @@
(match_operand:register_modes 1 "general_operand"))]
""
{
- if (MEM_P (operand0) && MEM_P (operand1))
- operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
+ operands[0] = rx_maybe_pidify_operand (operands[0], 0);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 0);
+ if (GET_CODE (operands[0]) != REG
+ && GET_CODE (operands[1]) == PLUS)
+ operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
+ if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
+ {
+ emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
+ DONE;
+ }
if (CONST_INT_P (operand1)
&& ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
FAIL;
@@ -566,13 +578,13 @@
(define_insn "*mov<register_modes:mode>_internal"
[(set (match_operand:register_modes
- 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
+ 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r")
(match_operand:register_modes
- 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
+ 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
""
{ return rx_gen_move_template (operands, false); }
- [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
- (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
+ [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
+ (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
)
(define_insn "extend<small_int_modes:mode>si2"
@@ -830,7 +842,20 @@
[(set_attr "length" "2,3")]
)
-(define_insn "addsi3"
+(define_expand "addsi3"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "rx_source_operand" "")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+ "
+ operands[0] = rx_maybe_pidify_operand (operands[0], 1);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 1);
+ operands[2] = rx_maybe_pidify_operand (operands[2], 1);
+ "
+)
+
+(define_insn "addsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
(match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
@@ -2583,3 +2608,10 @@
"nop"
[(set_attr "length" "1")]
)
+
+(define_expand "pid_addr"
+ [(plus:SI (match_operand:SI 0)
+ (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
+ ""
+ ""
+)
diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt
index 4a84effdcdb..308bf0c8ada 100644
--- a/gcc/config/rx/rx.opt
+++ b/gcc/config/rx/rx.opt
@@ -112,3 +112,9 @@ Specifies the number of registers to reserve for interrupt handlers.
msave-acc-in-interrupts
Target Mask(SAVE_ACC_REGISTER)
Specifies whether interrupt functions should save and restore the accumulator register.
+
+;---------------------------------------------------
+
+mpid
+Target Mask(PID)
+Enables Position-Independent-Data (PID) mode.
diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx
index 38893143981..ad667bcc5c9 100644
--- a/gcc/config/rx/t-rx
+++ b/gcc/config/rx/t-rx
@@ -20,8 +20,8 @@
# Enable multilibs:
-MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data
-MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data
+MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mpid
+MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid
MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e0df77a0c41..df18871cfd2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -828,6 +828,7 @@ See RS/6000 and PowerPC Options.
-mrelax@gol
-mmax-constant-size=@gol
-mint-register=@gol
+-mpid@gol
-msave-acc-in-interrupts}
@emph{S/390 and zSeries Options}
@@ -16576,10 +16577,11 @@ which can be placed into the small data area. Using the small data
area can lead to smaller and faster code, but the size of area is
limited and it is up to the programmer to ensure that the area does
not overflow. Also when the small data area is used one of the RX's
-registers (@code{r13}) is reserved for use pointing to this area, so
-it is no longer available for use by the compiler. This could result
-in slower and/or larger code if variables which once could have been
-held in @code{r13} are now pushed onto the stack.
+registers (usually @code{r13}) is reserved for use pointing to this
+area, so it is no longer available for use by the compiler. This
+could result in slower and/or larger code if variables which once
+could have been held in the reserved register are now pushed onto the
+stack.
Note, common variables (variables which have not been initialised) and
constants are not placed into the small data area as they are assigned
@@ -16588,9 +16590,10 @@ to other sections in the output executable.
The default value is zero, which disables this feature. Note, this
feature is not enabled by default with higher optimization levels
(@option{-O2} etc) because of the potentially detrimental effects of
-reserving register @code{r13}. It is up to the programmer to
-experiment and discover whether this feature is of benefit to their
-program.
+reserving a register. It is up to the programmer to experiment and
+discover whether this feature is of benefit to their program. See the
+description of the @option{-mpid} option for a description of how the
+actual register to hold the small data area pointer is chosen.
@item -msim
@itemx -mno-sim
@@ -16645,6 +16648,35 @@ the accumulator register, for example because it performs 64-bit
multiplications. The default is to ignore the accumulator as this
makes the interrupt handlers faster.
+@item -mpid
+@itemx -mno-pid
+@opindex mpid
+@opindex mno-pid
+Enables the generation of position independent data. When enabled any
+access to constant data will done via an offset from a base address
+held in a register. This allows the location of constant data to be
+determined at run-time without requiring the executable to be
+relocated, which is a benefit to embedded applications with tight
+memory constraints. Data that can be modified is not affected by this
+option.
+
+Note, using this feature reserves a register, usually @code{r13}, for
+the constant data base address. This can result in slower and/or
+larger code, especially in complicated functions.
+
+The actual register chosen to hold the constant data base address
+depends upon whether the @option{-msmall-data-limit} and/or the
+@option{-mint-register} command line options are enabled. Starting
+with register @code{r13} and proceeding downwards, registers are
+allocated first to satisfy the requirements of @option{-mint-register},
+then @option{-mpid} and finally @option{-msmall-data-limit}. Thus it
+is possible for the small data area register to be @code{r8} if both
+@option{-mint-register=4} and @option{-mpid} are specified on the
+command line.
+
+By default this feature is not enabled. The default can be restored
+via the @option{-mno-pid} command line option.
+
@end table
@emph{Note:} The generic GCC command line @option{-ffixed-@var{reg}}