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
This commit is contained in:
parent
6c90f13715
commit
6d51cc9010
2 changed files with 83 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
|
Loading…
Add table
Reference in a new issue