gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 Feb 2014 15:58:38 +0000 (15:58 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 Feb 2014 15:58:38 +0000 (15:58 +0000)
* config/mips/mips.c (mips_one_only_stub): New class.
(mips_need_mips16_rdhwr_p): Replace with...
(mips16_rdhwr_stub): ...this new variable.
(mips16_stub_call_address): New function.
(mips16_rdhwr_one_only_stub): New class.
(mips_expand_thread_pointer): Use mips16_stub_call_address.
(mips_output_mips16_rdhwr): Delete.
(mips_finish_stub): New function.
(mips_code_end): Use it to handle rdhwr stubs.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207400 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c

index 9635722..3311e2b 100644 (file)
@@ -1,3 +1,15 @@
+2014-02-02  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * config/mips/mips.c (mips_one_only_stub): New class.
+       (mips_need_mips16_rdhwr_p): Replace with...
+       (mips16_rdhwr_stub): ...this new variable.
+       (mips16_stub_call_address): New function.
+       (mips16_rdhwr_one_only_stub): New class.
+       (mips_expand_thread_pointer): Use mips16_stub_call_address.
+       (mips_output_mips16_rdhwr): Delete.
+       (mips_finish_stub): New function.
+       (mips_code_end): Use it to handle rdhwr stubs.
+
 2014-02-02  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/60017
index 59c0b26..12cecde 100644 (file)
@@ -275,12 +275,27 @@ enum mips_builtin_type {
 enum mips_fp_condition {
   MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
 };
+#undef DECLARE_MIPS_COND
 
 /* Index X provides the string representation of MIPS_FP_COND_<X>.  */
 #define STRINGIFY(X) #X
 static const char *const mips_fp_conditions[] = {
   MIPS_FP_CONDITIONS (STRINGIFY)
 };
+#undef STRINGIFY
+
+/* A class used to control a comdat-style stub that we output in each
+   translation unit that needs it.  */
+class mips_one_only_stub {
+public:
+  virtual ~mips_one_only_stub () {}
+
+  /* Return the name of the stub.  */
+  virtual const char *get_name () = 0;
+
+  /* Output the body of the function to asm_out_file.  */
+  virtual void output_body () = 0;
+};
 
 /* Tuning information that is automatically derived from other sources
    (such as the scheduler).  */
@@ -626,8 +641,8 @@ struct target_globals *mips16_globals;
    and returned from mips_sched_reorder2.  */
 static int cached_can_issue_more;
 
-/* True if the output uses __mips16_rdhwr.  */
-static bool mips_need_mips16_rdhwr_p;
+/* The stub for __mips16_rdhwr, if used.  */
+static mips_one_only_stub *mips16_rdhwr_stub;
 
 /* Index R is the smallest register class that contains register R.  */
 const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
@@ -1606,6 +1621,45 @@ mips16_stub_function (const char *name)
   SYMBOL_REF_FLAGS (x) |= (SYMBOL_FLAG_EXTERNAL | SYMBOL_FLAG_FUNCTION);
   return x;
 }
+
+/* Return a legitimate call address for STUB, given that STUB is a MIPS16
+   support function.  */
+
+static rtx
+mips16_stub_call_address (mips_one_only_stub *stub)
+{
+  rtx fn = mips16_stub_function (stub->get_name ());
+  SYMBOL_REF_FLAGS (fn) |= SYMBOL_FLAG_LOCAL;
+  if (!call_insn_operand (fn, VOIDmode))
+    fn = force_reg (Pmode, fn);
+  return fn;
+}
+\f
+/* A stub for moving the thread pointer into TLS_GET_TP_REGNUM.  */
+
+class mips16_rdhwr_one_only_stub : public mips_one_only_stub
+{
+  virtual const char *get_name ();
+  virtual void output_body ();
+};
+
+const char *
+mips16_rdhwr_one_only_stub::get_name ()
+{
+  return "__mips16_rdhwr";
+}
+
+void
+mips16_rdhwr_one_only_stub::output_body ()
+{
+  fprintf (asm_out_file,
+          "\t.set\tpush\n"
+          "\t.set\tmips32r2\n"
+          "\t.set\tnoreorder\n"
+          "\trdhwr\t$3,$29\n"
+          "\t.set\tpop\n"
+          "\tj\t$31\n");
+}
 \f
 /* Return true if symbols of type TYPE require a GOT access.  */
 
@@ -3070,11 +3124,9 @@ mips_expand_thread_pointer (rtx tp)
 
   if (TARGET_MIPS16)
     {
-      mips_need_mips16_rdhwr_p = true;
-      fn = mips16_stub_function ("__mips16_rdhwr");
-      SYMBOL_REF_FLAGS (fn) |= SYMBOL_FLAG_LOCAL;
-      if (!call_insn_operand (fn, VOIDmode))
-       fn = force_reg (Pmode, fn);
+      if (!mips16_rdhwr_stub)
+       mips16_rdhwr_stub = new mips16_rdhwr_one_only_stub ();
+      fn = mips16_stub_call_address (mips16_rdhwr_stub);
       emit_insn (PMODE_INSN (gen_tls_get_tp_mips16, (tp, fn)));
     }
   else
@@ -6204,25 +6256,24 @@ mips_end_function_definition (const char *name)
       fputs ("\n", asm_out_file);
     }
 }
-\f
-/* Output a definition of the __mips16_rdhwr function.  */
+
+/* If *STUB_PTR points to a stub, output a comdat-style definition for it,
+   then free *STUB_PTR.  */
 
 static void
-mips_output_mips16_rdhwr (void)
+mips_finish_stub (mips_one_only_stub **stub_ptr)
 {
-  const char *name;
+  mips_one_only_stub *stub = *stub_ptr;
+  if (!stub)
+    return;
 
-  name = "__mips16_rdhwr";
+  const char *name = stub->get_name ();
   mips_start_unique_function (name);
   mips_start_function_definition (name, false);
-  fprintf (asm_out_file,
-          "\t.set\tpush\n"
-          "\t.set\tmips32r2\n"
-          "\t.set\tnoreorder\n"
-          "\trdhwr\t$3,$29\n"
-          "\t.set\tpop\n"
-          "\tj\t$31\n");
+  stub->output_body ();
   mips_end_function_definition (name);
+  delete stub;
+  *stub_ptr = 0;
 }
 \f
 /* Return true if calls to X can use R_MIPS_CALL* relocations.  */
@@ -8906,8 +8957,7 @@ mips_file_start (void)
 static void
 mips_code_end (void)
 {
-  if (mips_need_mips16_rdhwr_p)
-    mips_output_mips16_rdhwr ();
+  mips_finish_stub (&mips16_rdhwr_stub);
 }
 \f
 /* Make the last instruction frame-related and note that it performs