]> gcc.gnu.org Git - gcc.git/commitdiff
rx.opt (mpid): Define.
authorDJ Delorie <dj@redhat.com>
Wed, 5 Oct 2011 15:07:21 +0000 (11:07 -0400)
committerNick Clifton <nickc@gcc.gnu.org>
Wed, 5 Oct 2011 15:07:21 +0000 (15:07 +0000)
* 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.

Co-Authored-By: Nick Clifton <nickc@redhat.com>
From-SVN: r179558

gcc/ChangeLog
gcc/config/rx/constraints.md
gcc/config/rx/rx-protos.h
gcc/config/rx/rx.c
gcc/config/rx/rx.h
gcc/config/rx/rx.md
gcc/config/rx/rx.opt
gcc/config/rx/t-rx
gcc/doc/invoke.texi

index e6bf96d9c92fe18d96ca79b9ec74bd8df4aef26d..4bdda3dff023cdd36650fa974169db2e7b6930e3 100644 (file)
@@ -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
index 9f7dc9ff81678eced70f82191574f00dc5851393..7822914acbbfda85ce3b9064ac7f3ddee7d24db8 100644 (file)
@@ -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.
        )
   )
 )
+
+(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")
+       )
+  )
+)
index 56d69316905bb66bfc601c23a9e6dec3f181c71e..365bf66babd9f1316e8e15b71f59c5a5f4ad7f09 100644 (file)
@@ -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);
index dcf693a63376f3c1a1956ee10c40912c0b7ad2a2..6ff9418c9d8a078141da4dae1323af053b5d3997 100644 (file)
 #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;
 \f
+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);
 \f
+/* 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"
index 67e8ce1c5772831ade8c50f12887d1eaa100ccc2..10b16bda2616144353a953272f673127b569305c 100644 (file)
 #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)
 \f
 /* 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)
index 5ce1c3976f33bbce1a3381b222de3359054248c6..708f9444ca95b3b13657e90fc3476249d1363710 100644 (file)
@@ -73,6 +73,8 @@
    (UNSPEC_BUILTIN_SAT     49)
    (UNSPEC_BUILTIN_SETPSW  50)
    (UNSPEC_BUILTIN_WAIT           51)
+
+   (UNSPEC_PID_ADDR       52)
   ]
 )
 
        (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")]
        (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;
 
 (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"
   [(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")))
   "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)))]
+  ""
+  ""
+)
index 4a84effdcdb33e8c8fb43a11315a4ace3c5e405d..308bf0c8ada0474c9973134b43c52afa5b51d38b 100644 (file)
@@ -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.
index 3889314398151a6d464b277acfbda9907cafaaae..ad667bcc5c9e7284a142aa3a2e8405787b2d0f30 100644 (file)
@@ -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
 
index e0df77a0c415ce310a6a58795d5d5f81ad907e17..df18871cfd28b850f236fd693493fd8c716d6c6e 100644 (file)
@@ -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}}
This page took 0.13463 seconds and 5 git commands to generate.