From 6d51cc90102eddcc8b988b400a70b015e69b2274 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 2 Feb 2014 15:58:38 +0000 Subject: [PATCH] mips.c (mips_one_only_stub): New class. gcc/ * 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. From-SVN: r207400 --- gcc/ChangeLog | 12 ++++++ gcc/config/mips/mips.c | 92 ++++++++++++++++++++++++++++++++---------- 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9635722c9f4..3311e2b0a69 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-02-02 Richard Sandiford + + * 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 PR target/60017 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 59c0b26d16e..12cecde8473 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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_. */ #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; +} + +/* 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"); +} /* 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); } } - -/* 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; } /* 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); } /* Make the last instruction frame-related and note that it performs