Makefile.in (insn-emit.o): Depend on $(INTEGRATE_H).
authorRichard Sandiford <richard@codesourcery.com>
Thu, 12 Apr 2007 17:59:57 +0000 (17:59 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 12 Apr 2007 17:59:57 +0000 (17:59 +0000)
gcc/
* Makefile.in (insn-emit.o): Depend on $(INTEGRATE_H).
* genemit.c (main): Emit #include "integrate.h".
* config/mips/mips-protos.h (SYMBOL_HALF): New mips_symbol_type.
(LOADGP_RTP): New mips_loadgp_style.
* config/mips/mips.h: Include config/vxworks-dummy.h.
(TARGET_RTP_PIC): New macro.
(TARGET_USE_GOT): Return true for TARGET_RTP_PIC.
(TARGET_USE_PIC_FN_ADDR_REG): Return true for TARGET_VXWORKS_RTP.
(ASM_OUTPUT_ADDR_DIFF_ELT): Emit function-relative case tables
for TARGET_RTP_PIC.
* config/mips/vxworks.h (SUBTARGET_ASM_SPEC): Define.  Pass down
-mvxworks-pic when using -mrtp and a PIC option.
* config/mips/mips.c (mips_classify_symbol): Return SYMBOL_GOT_DISP
for RTP PIC.
(mips_symbolic_constant_p, mips_symbolic_address_p)
(mips_symbol_insns): Handle SYMBOL_HALF.
(override_options): Warn about -G and -mrtp being used together.
Initialize mips_lo_relocs[SYMBOL_HALF].
(mips_current_loadgp_style): Return LOADGP_RTP for RTP PIC.
(mips_emit_loadgp): Handle LOADGP_RTP.
(mips_in_small_data_p): Return false for TARGET_VXWORKS_RTP.
* config/mips/mips.md (loadgp_rtp): New insn and splitter.
(tablejump): Handle function-relative case table entries if
TARGET_RTP_PIC.
* config/mips/predicates.md (symbol_ref_operand): New predicate.

From-SVN: r123757

gcc/ChangeLog
gcc/Makefile.in
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/predicates.md
gcc/config/mips/vxworks.h
gcc/genemit.c

index aff318411cbda392e30fb72acaf770bcec196688..1003b0fb2e2cda6de45d7d0c33fc3b602032720f 100644 (file)
@@ -1,3 +1,31 @@
+2007-04-12  Richard Sandiford  <richard@codesourcery.com>
+
+       * Makefile.in (insn-emit.o): Depend on $(INTEGRATE_H).
+       * genemit.c (main): Emit #include "integrate.h".
+       * config/mips/mips-protos.h (SYMBOL_HALF): New mips_symbol_type.
+       (LOADGP_RTP): New mips_loadgp_style.
+       * config/mips/mips.h: Include config/vxworks-dummy.h.
+       (TARGET_RTP_PIC): New macro.
+       (TARGET_USE_GOT): Return true for TARGET_RTP_PIC.
+       (TARGET_USE_PIC_FN_ADDR_REG): Return true for TARGET_VXWORKS_RTP.
+       (ASM_OUTPUT_ADDR_DIFF_ELT): Emit function-relative case tables
+       for TARGET_RTP_PIC.
+       * config/mips/vxworks.h (SUBTARGET_ASM_SPEC): Define.  Pass down
+       -mvxworks-pic when using -mrtp and a PIC option.
+       * config/mips/mips.c (mips_classify_symbol): Return SYMBOL_GOT_DISP
+       for RTP PIC.
+       (mips_symbolic_constant_p, mips_symbolic_address_p)
+       (mips_symbol_insns): Handle SYMBOL_HALF.
+       (override_options): Warn about -G and -mrtp being used together.
+       Initialize mips_lo_relocs[SYMBOL_HALF].
+       (mips_current_loadgp_style): Return LOADGP_RTP for RTP PIC.
+       (mips_emit_loadgp): Handle LOADGP_RTP.
+       (mips_in_small_data_p): Return false for TARGET_VXWORKS_RTP.
+       * config/mips/mips.md (loadgp_rtp): New insn and splitter.
+       (tablejump): Handle function-relative case table entries if
+       TARGET_RTP_PIC.
+       * config/mips/predicates.md (symbol_ref_operand): New predicate.
+
 2007-04-12  Richard Sandiford  <richard@codesourcery.com>
 
        * config/mips/mips.md (load_call<mode>): Allow any general register.
index eeca0dc20a3e57ab31340d075cddc6656ef0f6cc..9d9146ea66f49112344cfdd85ec699adb25999d6 100644 (file)
@@ -2847,7 +2847,7 @@ insn-automata.o : insn-automata.c $(CONFIG_H) $(SYSTEM_H) coretypes.h     \
 insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)  \
   $(RTL_H) $(EXPR_H) $(REAL_H) output.h insn-config.h $(OPTABS_H)      \
   reload.h $(RECOG_H) toplev.h $(FUNCTION_H) $(FLAGS_H) hard-reg-set.h \
-  $(RESOURCE_H) $(TM_P_H) $(BASIC_BLOCK_H) tm-constrs.h
+  $(RESOURCE_H) $(TM_P_H) $(BASIC_BLOCK_H) $(INTEGRATE_H) tm-constrs.h
 insn-extract.o : insn-extract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h    \
   $(TM_H) $(RTL_H) toplev.h insn-config.h $(RECOG_H)
 insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h        $(TM_H) \
index 78cdc1ae6693cee91d23aca9856a61681ccfcfde..94fe227d190c05348166421631c66eabb91601d0 100644 (file)
@@ -82,7 +82,11 @@ Boston, MA 02110-1301, USA.  */
 
    SYMBOL_64_LOW
        For a 64-bit symbolic address X, this is the value of
-       (%hi(X) << 16) + %lo(X).  */
+       (%hi(X) << 16) + %lo(X).
+
+   SYMBOL_HALF
+       An UNSPEC wrapper around any kind of address.  It represents the
+       low 16 bits of that address.  */
 enum mips_symbol_type {
   SYMBOL_GENERAL,
   SYMBOL_SMALL_DATA,
@@ -101,9 +105,10 @@ enum mips_symbol_type {
   SYMBOL_TPREL,
   SYMBOL_64_HIGH,
   SYMBOL_64_MID,
-  SYMBOL_64_LOW
+  SYMBOL_64_LOW,
+  SYMBOL_HALF
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_64_LOW + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_HALF + 1)
 
 /* Identifiers a style of $gp initialization sequence.
 
@@ -119,12 +124,16 @@ enum mips_symbol_type {
        by .cpsetup).
 
    LOADGP_ABSOLUTE
-       The GNU absolute sequence, as generated by loadgp_absolute.  */
+       The GNU absolute sequence, as generated by loadgp_absolute.
+
+   LOADGP_RTP
+       The VxWorks RTP PIC sequence, as generated by loadgp_rtp.  */
 enum mips_loadgp_style {
   LOADGP_NONE,
   LOADGP_OLDABI,
   LOADGP_NEWABI,
-  LOADGP_ABSOLUTE
+  LOADGP_ABSOLUTE,
+  LOADGP_RTP
 };
 
 extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
index 9100e998c7663a2724e67cdc57250765a761fdc6..b67210934ae2a15d9e470b5464acbb2413b9c417 100644 (file)
@@ -1245,6 +1245,9 @@ mips_symbol_binds_local_p (rtx x)
 static enum mips_symbol_type
 mips_classify_symbol (rtx x)
 {
+  if (TARGET_RTP_PIC)
+    return SYMBOL_GOT_DISP;
+
   if (GET_CODE (x) == LABEL_REF)
     {
       if (TARGET_MIPS16)
@@ -1385,6 +1388,7 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
     case SYMBOL_TPREL:
     case SYMBOL_GOTTPREL:
     case SYMBOL_TLS:
+    case SYMBOL_HALF:
       return false;
     }
   gcc_unreachable ();
@@ -1484,6 +1488,7 @@ mips_symbolic_address_p (enum mips_symbol_type symbol_type,
     case SYMBOL_64_HIGH:
     case SYMBOL_64_MID:
     case SYMBOL_64_LOW:
+    case SYMBOL_HALF:
       return true;
     }
   gcc_unreachable ();
@@ -1630,6 +1635,7 @@ mips_symbol_insns (enum mips_symbol_type type)
       return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2);
 
     case SYMBOL_SMALL_DATA:
+    case SYMBOL_HALF:
       return 1;
 
     case SYMBOL_CONSTANT_POOL:
@@ -4886,6 +4892,9 @@ override_options (void)
        warning (0, "%<-G%> is incompatible with %<-mabicalls%>");
     }
 
+  if (TARGET_VXWORKS_RTP && mips_section_threshold > 0)
+    warning (0, "-G and -mrtp are incompatible");
+
   /* mips_split_addresses is a half-way house between explicit
      relocations and the traditional assembler macros.  It can
      split absolute 32-bit symbolic constants into a high/lo_sum
@@ -5192,6 +5201,8 @@ override_options (void)
   mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
   mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
 
+  mips_lo_relocs[SYMBOL_HALF] = "%half(";
+
   /* We don't have a thread pointer access instruction on MIPS16, or
      appropriate TLS relocations.  */
   if (TARGET_MIPS16)
@@ -6573,6 +6584,9 @@ mips_current_loadgp_style (void)
   if (!TARGET_USE_GOT || cfun->machine->global_pointer == 0)
     return LOADGP_NONE;
 
+  if (TARGET_RTP_PIC)
+    return LOADGP_RTP;
+
   if (TARGET_ABSOLUTE_ABICALLS)
     return LOADGP_ABSOLUTE;
 
@@ -6589,7 +6603,7 @@ static GTY(()) rtx mips_gnu_local_gp;
 static void
 mips_emit_loadgp (void)
 {
-  rtx addr, offset, incoming_address;
+  rtx addr, offset, incoming_address, base, index;
 
   switch (mips_current_loadgp_style ())
     {
@@ -6611,6 +6625,14 @@ mips_emit_loadgp (void)
        emit_insn (gen_loadgp_blockage ());
       break;
 
+    case LOADGP_RTP:
+      base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (VXWORKS_GOTT_BASE));
+      index = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (VXWORKS_GOTT_INDEX));
+      emit_insn (gen_loadgp_rtp (base, index));
+      if (!TARGET_EXPLICIT_RELOCS)
+       emit_insn (gen_loadgp_blockage ());
+      break;
+
     default:
       break;
     }
@@ -7313,9 +7335,9 @@ mips_in_small_data_p (tree decl)
   if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
     return false;
 
-  /* We don't yet generate small-data references for -mabicalls.  See related
-     -G handling in override_options.  */
-  if (TARGET_ABICALLS)
+  /* We don't yet generate small-data references for -mabicalls or
+     VxWorks RTP code.  See the related -G handling in override_options.  */
+  if (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
     return false;
 
   if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
index af8a7f4ba2a2c359a50f9979ff874bb55b04d353..6cf42a7249f8a29185bd9d8c8a2bc85f04965ed8 100644 (file)
@@ -24,6 +24,8 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
 
+#include "config/vxworks-dummy.h"
+
 /* MIPS external variables defined in mips.c.  */
 
 /* Which processor to schedule for.  Since there is no difference between
@@ -143,6 +145,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
 \f
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
+/* True if we are generating position-independent VxWorks RTP code.  */
+#define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic)
+
 /* True if the call patterns should be split into a jalr followed by
    an instruction to restore $gp.  It is only safe to split the load
    from the call when every use of $gp is explicit.  */
@@ -178,7 +183,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
   (!TARGET_MIPS16 && (!TARGET_USE_GOT || TARGET_EXPLICIT_RELOCS))
 
 /* True if we need to use a global offset table to access some symbols.  */
-#define TARGET_USE_GOT TARGET_ABICALLS
+#define TARGET_USE_GOT (TARGET_ABICALLS || TARGET_RTP_PIC)
 
 /* True if TARGET_USE_GOT and if $gp is a call-clobbered register.  */
 #define TARGET_CALL_CLOBBERED_GP (TARGET_ABICALLS && TARGET_OLDABI)
@@ -186,8 +191,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* True if TARGET_USE_GOT and if $gp is a call-saved register.  */
 #define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP)
 
-/* True if indirect calls must use register class PIC_FN_ADDR_REG.  */
-#define TARGET_USE_PIC_FN_ADDR_REG TARGET_ABICALLS
+/* True if indirect calls must use register class PIC_FN_ADDR_REG.
+   This is true for both the PIC and non-PIC VxWorks RTP modes.  */
+#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
 
 /* True if .gpword or .gpdword should be used for switch tables.
 
@@ -2578,6 +2584,16 @@ do {                                                                     \
     fprintf (STREAM, "\t%s\t%sL%d\n",                                  \
             ptr_mode == DImode ? ".gpdword" : ".gpword",               \
             LOCAL_LABEL_PREFIX, VALUE);                                \
+  else if (TARGET_RTP_PIC)                                             \
+    {                                                                  \
+      /* Make the entry relative to the start of the function.  */     \
+      rtx fnsym = XEXP (DECL_RTL (current_function_decl), 0);          \
+      fprintf (STREAM, "\t%s\t%sL%d-",                                 \
+              Pmode == DImode ? ".dword" : ".word",                    \
+              LOCAL_LABEL_PREFIX, VALUE);                              \
+      assemble_name (STREAM, XSTR (fnsym, 0));                         \
+      fprintf (STREAM, "\n");                                          \
+    }                                                                  \
   else                                                                 \
     fprintf (STREAM, "\t%s\t%sL%d\n",                                  \
             ptr_mode == DImode ? ".dword" : ".word",                   \
index 8fb78ca90ff307b767e43c729f7befaafe650b2e..2178481808d1d6c98b751a69fa259d21e1d96123 100644 (file)
    (set_attr "mode"    "none")
    (set_attr "length"  "0")])
 
+;; Initialize $gp for RTP PIC.  Operand 0 is the __GOTT_BASE__ symbol
+;; and operand 1 is the __GOTT_INDEX__ symbol.
+(define_insn "loadgp_rtp"
+  [(unspec_volatile [(match_operand 0 "symbol_ref_operand")
+                    (match_operand 1 "symbol_ref_operand")] UNSPEC_LOADGP)]
+  "mips_current_loadgp_style () == LOADGP_RTP"
+  "#"
+  [(set_attr "length" "12")])
+
+(define_split
+  [(unspec_volatile [(match_operand:P 0 "symbol_ref_operand")
+                    (match_operand:P 1 "symbol_ref_operand")] UNSPEC_LOADGP)]
+  "mips_current_loadgp_style () == LOADGP_RTP"
+  [(set (match_dup 2) (high:P (match_dup 3)))
+   (set (match_dup 2) (unspec:P [(match_dup 2)
+                                (match_dup 3)] UNSPEC_LOAD_GOT))
+   (set (match_dup 2) (unspec:P [(match_dup 2)
+                                (match_dup 4)] UNSPEC_LOAD_GOT))]
+{
+  operands[2] = pic_offset_table_rtx;
+  operands[3] = mips_unspec_address (operands[0], SYMBOL_GENERAL);
+  operands[4] = mips_unspec_address (operands[1], SYMBOL_HALF);
+})
+
 ;; Emit a .cprestore directive, which normally expands to a single store
 ;; instruction.  Note that we continue to use .cprestore for explicit reloc
 ;; code so that jals inside inline asms will work correctly.
   else if (TARGET_GPWORD)
     operands[0] = expand_binop (Pmode, add_optab, operands[0],
                                pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
+  else if (TARGET_RTP_PIC)
+    {
+      /* When generating RTP PIC, we use case table entries that are relative
+        to the start of the function.  Add the function's address to the
+        value we loaded.  */
+      rtx start = get_hard_reg_initial_val (Pmode, PIC_FUNCTION_ADDR_REGNUM);
+      operands[0] = expand_binop (ptr_mode, add_optab, operands[0],
+                                 start, 0, 0, OPTAB_WIDEN);
+    }
 
   if (Pmode == SImode)
     emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
index 9f6cc955df2d4b1a2e1aa9d55bde5a3b6a61ced2..16035c8cb2b1949404c3234f995a5d3917172c88 100644 (file)
   return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_PAGE_OFST;
 })
 
+(define_predicate "symbol_ref_operand"
+  (match_code "symbol_ref"))
+
 (define_predicate "stack_operand"
   (and (match_code "mem")
        (match_test "mips_stack_address_p (XEXP (op, 0), GET_MODE (op))")))
index 574221f3f997de0b97e74d8951d4b9e9ce75ed78..5b6b026e9c4579e5626ffcab7cb2a3e42464a75f 100644 (file)
@@ -86,3 +86,6 @@ VXWORKS_LINK_SPEC
 /* No _mcount profiling on VxWorks.  */
 #undef FUNCTION_PROFILER
 #define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER
+
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "%{mrtp:%{fPIC|fpic:-mvxworks-pic}}"
index a367f46a8ccbf0029f97cdee6de243e8e92a944d..64fb312f609cc85964a0df8f5e6322159e157727 100644 (file)
@@ -857,6 +857,7 @@ from the machine description file `md'.  */\n\n");
   printf ("#include \"tm-constrs.h\"\n");
   printf ("#include \"ggc.h\"\n\n");
   printf ("#include \"basic-block.h\"\n\n");
+  printf ("#include \"integrate.h\"\n\n");
   printf ("#define FAIL return (end_sequence (), _val)\n");
   printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");