mips-protos.h (mips_push_asm_switch): New function.
gcc/ * config/mips/mips-protos.h (mips_push_asm_switch): New function. (mips_pop_asm_switch): Likewise. * config/mips/mips.c (set_noreorder, set_nomacro, set_noat): Replace with... (mips_noreorder, mips_nomacro, mips_noat): ...these new variables. (mips_push_asm_switch_1, mips_pop_asm_switch_1): New functions. (mips_push_asm_switch, mips_pop_asm_switch): Likewise. (mips_print_operand_punctuation): Use them. Check mips_noreorder instead of set_noreorder. (mips_output_function_prologue): Use the new functions. (mips_output_function_epilogue): Likewise. (mips_need_noat_wrapper_p): New function, split out from... (mips_final_prescan_insn, mips_final_postscan_insn): ...here. Use mips_push_asm_switch and mips_pop_asm_switch. * config/mips/mips.h (FUNCTION_PROFILER): Use mips_push_asm_switch and mips_pop_asm_switch. (ASM_OUTPUT_REG_POP): Likewise. (DBR_OUTPUT_SEQEND): Remove boilerplate comment. Use mips_pop_asm_switch. (mips_asm_switch): New structure. (set_noreorder, set_nomacro): Replace with... (mips_noreorder, mips_nomacro, mips_noat): ...these new variables. * config/mips/mips.md (fix_truncdfsi2_macro): Use mips_nomacro instead of set_nomacro. (fix_truncsfsi2_macro): Likewise. (cprestore): Likewise. (hazard): Use mips_noreorder instead of set_noreorder. * config/mips/sdemtk.h (FUNCTION_PROFILER): As for mips.h. From-SVN: r150803
This commit is contained in:
parent
3eb96d01d4
commit
cf5fb4b0d5
|
@ -1,3 +1,34 @@
|
|||
2009-08-16 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* config/mips/mips-protos.h (mips_push_asm_switch): New function.
|
||||
(mips_pop_asm_switch): Likewise.
|
||||
* config/mips/mips.c (set_noreorder, set_nomacro, set_noat): Replace
|
||||
with...
|
||||
(mips_noreorder, mips_nomacro, mips_noat): ...these new variables.
|
||||
(mips_push_asm_switch_1, mips_pop_asm_switch_1): New functions.
|
||||
(mips_push_asm_switch, mips_pop_asm_switch): Likewise.
|
||||
(mips_print_operand_punctuation): Use them. Check mips_noreorder
|
||||
instead of set_noreorder.
|
||||
(mips_output_function_prologue): Use the new functions.
|
||||
(mips_output_function_epilogue): Likewise.
|
||||
(mips_need_noat_wrapper_p): New function, split out from...
|
||||
(mips_final_prescan_insn, mips_final_postscan_insn): ...here.
|
||||
Use mips_push_asm_switch and mips_pop_asm_switch.
|
||||
* config/mips/mips.h (FUNCTION_PROFILER): Use mips_push_asm_switch
|
||||
and mips_pop_asm_switch.
|
||||
(ASM_OUTPUT_REG_POP): Likewise.
|
||||
(DBR_OUTPUT_SEQEND): Remove boilerplate comment.
|
||||
Use mips_pop_asm_switch.
|
||||
(mips_asm_switch): New structure.
|
||||
(set_noreorder, set_nomacro): Replace with...
|
||||
(mips_noreorder, mips_nomacro, mips_noat): ...these new variables.
|
||||
* config/mips/mips.md (fix_truncdfsi2_macro): Use mips_nomacro
|
||||
instead of set_nomacro.
|
||||
(fix_truncsfsi2_macro): Likewise.
|
||||
(cprestore): Likewise.
|
||||
(hazard): Use mips_noreorder instead of set_noreorder.
|
||||
* config/mips/sdemtk.h (FUNCTION_PROFILER): As for mips.h.
|
||||
|
||||
2009-08-16 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/alpha/alpha.c (alpha_and_function): Handle NULL_RTX returned
|
||||
|
|
|
@ -254,6 +254,8 @@ extern void mips_conditional_register_usage (void);
|
|||
extern void mips_order_regs_for_local_alloc (void);
|
||||
extern HOST_WIDE_INT mips_debugger_offset (rtx, HOST_WIDE_INT);
|
||||
|
||||
extern void mips_push_asm_switch (struct mips_asm_switch *);
|
||||
extern void mips_pop_asm_switch (struct mips_asm_switch *);
|
||||
extern void mips_print_operand (FILE *, rtx, int);
|
||||
extern void mips_print_operand_address (FILE *, rtx);
|
||||
extern void mips_output_external (FILE *, tree, const char *);
|
||||
|
|
|
@ -440,9 +440,9 @@ int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
|
|||
int mips_dwarf_regno[FIRST_PSEUDO_REGISTER];
|
||||
|
||||
/* The nesting depth of the PRINT_OPERAND '%(', '%<' and '%[' constructs. */
|
||||
int set_noreorder;
|
||||
int set_nomacro;
|
||||
static int set_noat;
|
||||
struct mips_asm_switch mips_noreorder = { "reorder", 0 };
|
||||
struct mips_asm_switch mips_nomacro = { "macro", 0 };
|
||||
struct mips_asm_switch mips_noat = { "at", 0 };
|
||||
|
||||
/* True if we're writing out a branch-likely instruction rather than a
|
||||
normal branch. */
|
||||
|
@ -6989,6 +6989,45 @@ mips_print_operand_reloc (FILE *file, rtx op, enum mips_symbol_context context,
|
|||
fputc (')', file);
|
||||
}
|
||||
|
||||
/* Start a new block with the given asm switch enabled. If we need
|
||||
to print a directive, emit PREFIX before it and SUFFIX after it. */
|
||||
|
||||
static void
|
||||
mips_push_asm_switch_1 (struct mips_asm_switch *asm_switch,
|
||||
const char *prefix, const char *suffix)
|
||||
{
|
||||
if (asm_switch->nesting_level == 0)
|
||||
fprintf (asm_out_file, "%s.set\tno%s%s", prefix, asm_switch->name, suffix);
|
||||
asm_switch->nesting_level++;
|
||||
}
|
||||
|
||||
/* Likewise, but end a block. */
|
||||
|
||||
static void
|
||||
mips_pop_asm_switch_1 (struct mips_asm_switch *asm_switch,
|
||||
const char *prefix, const char *suffix)
|
||||
{
|
||||
gcc_assert (asm_switch->nesting_level);
|
||||
asm_switch->nesting_level--;
|
||||
if (asm_switch->nesting_level == 0)
|
||||
fprintf (asm_out_file, "%s.set\t%s%s", prefix, asm_switch->name, suffix);
|
||||
}
|
||||
|
||||
/* Wrappers around mips_push_asm_switch_1 and mips_pop_asm_switch_1
|
||||
that either print a complete line or print nothing. */
|
||||
|
||||
void
|
||||
mips_push_asm_switch (struct mips_asm_switch *asm_switch)
|
||||
{
|
||||
mips_push_asm_switch_1 (asm_switch, "\t", "\n");
|
||||
}
|
||||
|
||||
void
|
||||
mips_pop_asm_switch (struct mips_asm_switch *asm_switch)
|
||||
{
|
||||
mips_pop_asm_switch_1 (asm_switch, "\t", "\n");
|
||||
}
|
||||
|
||||
/* Print the text for PRINT_OPERAND punctation character CH to FILE.
|
||||
The punctuation characters are:
|
||||
|
||||
|
@ -7019,36 +7058,27 @@ mips_print_operand_punctuation (FILE *file, int ch)
|
|||
switch (ch)
|
||||
{
|
||||
case '(':
|
||||
if (set_noreorder++ == 0)
|
||||
fputs (".set\tnoreorder\n\t", file);
|
||||
mips_push_asm_switch_1 (&mips_noreorder, "", "\n\t");
|
||||
break;
|
||||
|
||||
case ')':
|
||||
gcc_assert (set_noreorder > 0);
|
||||
if (--set_noreorder == 0)
|
||||
fputs ("\n\t.set\treorder", file);
|
||||
mips_pop_asm_switch_1 (&mips_noreorder, "\n\t", "");
|
||||
break;
|
||||
|
||||
case '[':
|
||||
if (set_noat++ == 0)
|
||||
fputs (".set\tnoat\n\t", file);
|
||||
mips_push_asm_switch_1 (&mips_noat, "", "\n\t");
|
||||
break;
|
||||
|
||||
case ']':
|
||||
gcc_assert (set_noat > 0);
|
||||
if (--set_noat == 0)
|
||||
fputs ("\n\t.set\tat", file);
|
||||
mips_pop_asm_switch_1 (&mips_noat, "\n\t", "");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if (set_nomacro++ == 0)
|
||||
fputs (".set\tnomacro\n\t", file);
|
||||
mips_push_asm_switch_1 (&mips_nomacro, "", "\n\t");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
gcc_assert (set_nomacro > 0);
|
||||
if (--set_nomacro == 0)
|
||||
fputs ("\n\t.set\tmacro", file);
|
||||
mips_pop_asm_switch_1 (&mips_nomacro, "\n\t", "");
|
||||
break;
|
||||
|
||||
case '*':
|
||||
|
@ -7060,7 +7090,7 @@ mips_print_operand_punctuation (FILE *file, int ch)
|
|||
break;
|
||||
|
||||
case '#':
|
||||
if (set_noreorder != 0)
|
||||
if (mips_noreorder.nesting_level > 0)
|
||||
fputs ("\n\tnop", file);
|
||||
break;
|
||||
|
||||
|
@ -7068,7 +7098,7 @@ mips_print_operand_punctuation (FILE *file, int ch)
|
|||
/* Print an extra newline so that the delayed insn is separated
|
||||
from the following ones. This looks neater and is consistent
|
||||
with non-nop delayed sequences. */
|
||||
if (set_noreorder != 0 && final_sequence == 0)
|
||||
if (mips_noreorder.nesting_level > 0 && final_sequence == 0)
|
||||
fputs ("\n\tnop\n", file);
|
||||
break;
|
||||
|
||||
|
@ -9267,14 +9297,23 @@ mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
|
|||
output_asm_insn ("sll\t$2,16", 0);
|
||||
output_asm_insn ("addu\t$2,$3", 0);
|
||||
}
|
||||
/* .cpload must be in a .set noreorder but not a .set nomacro block. */
|
||||
else if (!cfun->machine->all_noreorder_p)
|
||||
output_asm_insn ("%(.cpload\t%^%)", 0);
|
||||
else
|
||||
output_asm_insn ("%(.cpload\t%^\n\t%<", 0);
|
||||
{
|
||||
/* .cpload must be in a .set noreorder but not a
|
||||
.set nomacro block. */
|
||||
mips_push_asm_switch (&mips_noreorder);
|
||||
output_asm_insn (".cpload\t%^", 0);
|
||||
if (!cfun->machine->all_noreorder_p)
|
||||
mips_pop_asm_switch (&mips_noreorder);
|
||||
else
|
||||
mips_push_asm_switch (&mips_nomacro);
|
||||
}
|
||||
}
|
||||
else if (cfun->machine->all_noreorder_p)
|
||||
output_asm_insn ("%(%<", 0);
|
||||
{
|
||||
mips_push_asm_switch (&mips_noreorder);
|
||||
mips_push_asm_switch (&mips_nomacro);
|
||||
}
|
||||
|
||||
/* Tell the assembler which register we're using as the global
|
||||
pointer. This is needed for thunks, since they can use either
|
||||
|
@ -9296,10 +9335,8 @@ mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
|
|||
|
||||
if (cfun->machine->all_noreorder_p)
|
||||
{
|
||||
/* Avoid using %>%) since it adds excess whitespace. */
|
||||
output_asm_insn (".set\tmacro", 0);
|
||||
output_asm_insn (".set\treorder", 0);
|
||||
set_noreorder = set_nomacro = 0;
|
||||
mips_pop_asm_switch (&mips_nomacro);
|
||||
mips_pop_asm_switch (&mips_noreorder);
|
||||
}
|
||||
|
||||
/* Get the function name the same way that toplev.c does before calling
|
||||
|
@ -14763,36 +14800,38 @@ mips_at_reg_p (rtx *x, void *data ATTRIBUTE_UNUSED)
|
|||
return REG_P (*x) && REGNO (*x) == AT_REGNUM;
|
||||
}
|
||||
|
||||
/* Return true if INSN needs to be wrapped in ".set noat".
|
||||
INSN has NOPERANDS operands, stored in OPVEC. */
|
||||
|
||||
static bool
|
||||
mips_need_noat_wrapper_p (rtx insn, rtx *opvec, int noperands)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (recog_memoized (insn) >= 0)
|
||||
for (i = 0; i < noperands; i++)
|
||||
if (for_each_rtx (&opvec[i], mips_at_reg_p, NULL))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Implement FINAL_PRESCAN_INSN. */
|
||||
|
||||
void
|
||||
mips_final_prescan_insn (rtx insn, rtx *opvec, int noperands)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We need to emit ".set noat" before an instruction that accesses
|
||||
$1 (AT). */
|
||||
if (recog_memoized (insn) >= 0)
|
||||
for (i = 0; i < noperands; i++)
|
||||
if (for_each_rtx (&opvec[i], mips_at_reg_p, NULL))
|
||||
if (set_noat++ == 0)
|
||||
fprintf (asm_out_file, "\t.set\tnoat\n");
|
||||
if (mips_need_noat_wrapper_p (insn, opvec, noperands))
|
||||
mips_push_asm_switch (&mips_noat);
|
||||
}
|
||||
|
||||
/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN. */
|
||||
|
||||
static void
|
||||
mips_final_postscan_insn (FILE *file, rtx insn, rtx *opvec, int noperands)
|
||||
mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx insn,
|
||||
rtx *opvec, int noperands)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Close any ".set noat" block opened by mips_final_prescan_insn. */
|
||||
if (recog_memoized (insn) >= 0)
|
||||
for (i = 0; i < noperands; i++)
|
||||
if (for_each_rtx (&opvec[i], mips_at_reg_p, NULL))
|
||||
if (--set_noat == 0)
|
||||
fprintf (file, "\t.set\tat\n");
|
||||
if (mips_need_noat_wrapper_p (insn, opvec, noperands))
|
||||
mips_pop_asm_switch (&mips_noat);
|
||||
}
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
|
|
|
@ -2364,7 +2364,7 @@ typedef struct mips_args {
|
|||
else \
|
||||
fprintf (FILE, "\tla\t%s,_mcount\n", reg_names[GP_REG_FIRST + 3]); \
|
||||
} \
|
||||
fprintf (FILE, "\t.set\tnoat\n"); \
|
||||
mips_push_asm_switch (&mips_noat); \
|
||||
fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
|
||||
reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \
|
||||
/* _mcount treats $2 as the static chain register. */ \
|
||||
|
@ -2384,7 +2384,7 @@ typedef struct mips_args {
|
|||
fprintf (FILE, "\tjalr\t%s\n", reg_names[GP_REG_FIRST + 3]); \
|
||||
else \
|
||||
fprintf (FILE, "\tjal\t_mcount\n"); \
|
||||
fprintf (FILE, "\t.set\tat\n"); \
|
||||
mips_pop_asm_switch (&mips_noat); \
|
||||
/* _mcount treats $2 as the static chain register. */ \
|
||||
if (cfun->static_chain_decl != NULL) \
|
||||
fprintf (FILE, "\tmove\t%s,%s\n", reg_names[STATIC_CHAIN_REGNUM], \
|
||||
|
@ -2778,32 +2778,13 @@ typedef struct mips_args {
|
|||
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) mips_print_operand_punct[CODE]
|
||||
#define PRINT_OPERAND_ADDRESS mips_print_operand_address
|
||||
|
||||
/* A C statement, to be executed after all slot-filler instructions
|
||||
have been output. If necessary, call `dbr_sequence_length' to
|
||||
determine the number of slots filled in a sequence (zero if not
|
||||
currently outputting a sequence), to decide how many no-ops to
|
||||
output, or whatever.
|
||||
|
||||
Don't define this macro if it has nothing to do, but it is
|
||||
helpful in reading assembly output if the extent of the delay
|
||||
sequence is made explicit (e.g. with white space).
|
||||
|
||||
Note that output routines for instructions with delay slots must
|
||||
be prepared to deal with not being output as part of a sequence
|
||||
(i.e. when the scheduling pass is not run, or when no slot
|
||||
fillers could be found.) The variable `final_sequence' is null
|
||||
when not processing a sequence, otherwise it contains the
|
||||
`sequence' rtx being output. */
|
||||
|
||||
#define DBR_OUTPUT_SEQEND(STREAM) \
|
||||
do \
|
||||
{ \
|
||||
if (set_nomacro > 0 && --set_nomacro == 0) \
|
||||
fputs ("\t.set\tmacro\n", STREAM); \
|
||||
\
|
||||
if (set_noreorder > 0 && --set_noreorder == 0) \
|
||||
fputs ("\t.set\treorder\n", STREAM); \
|
||||
\
|
||||
/* Undo the effect of '%*'. */ \
|
||||
mips_pop_asm_switch (&mips_nomacro); \
|
||||
mips_pop_asm_switch (&mips_noreorder); \
|
||||
/* Emit a blank line after the delay slot for emphasis. */ \
|
||||
fputs ("\n", STREAM); \
|
||||
} \
|
||||
while (0)
|
||||
|
@ -2996,9 +2977,7 @@ while (0)
|
|||
#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
|
||||
do \
|
||||
{ \
|
||||
if (! set_noreorder) \
|
||||
fprintf (STREAM, "\t.set\tnoreorder\n"); \
|
||||
\
|
||||
mips_push_asm_switch (&mips_noreorder); \
|
||||
fprintf (STREAM, "\t%s\t%s,0(%s)\n\t%s\t%s,%s,8\n", \
|
||||
TARGET_64BIT ? "ld" : "lw", \
|
||||
reg_names[REGNO], \
|
||||
|
@ -3006,9 +2985,7 @@ do \
|
|||
TARGET_64BIT ? "daddu" : "addu", \
|
||||
reg_names[STACK_POINTER_REGNUM], \
|
||||
reg_names[STACK_POINTER_REGNUM]); \
|
||||
\
|
||||
if (! set_noreorder) \
|
||||
fprintf (STREAM, "\t.set\treorder\n"); \
|
||||
mips_pop_asm_switch (&mips_noreorder); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
@ -3406,13 +3383,23 @@ while (0)
|
|||
#define MIPS_SYNC_EXCHANGE_12_NONZERO_OP "\tor\t%@,%@,%4\n"
|
||||
|
||||
#ifndef USED_FOR_TARGET
|
||||
/* Information about ".set noFOO; ...; .set FOO" blocks. */
|
||||
struct mips_asm_switch {
|
||||
/* The FOO in the description above. */
|
||||
const char *name;
|
||||
|
||||
/* The current block nesting level, or 0 if we aren't in a block. */
|
||||
int nesting_level;
|
||||
};
|
||||
|
||||
extern const enum reg_class mips_regno_to_class[];
|
||||
extern bool mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
|
||||
extern bool mips_print_operand_punct[256];
|
||||
extern const char *current_function_file; /* filename current function is in */
|
||||
extern int num_source_filenames; /* current .file # */
|
||||
extern int set_noreorder; /* # of nested .set noreorder's */
|
||||
extern int set_nomacro; /* # of nested .set nomacro's */
|
||||
extern struct mips_asm_switch mips_noreorder;
|
||||
extern struct mips_asm_switch mips_nomacro;
|
||||
extern struct mips_asm_switch mips_noat;
|
||||
extern int mips_dbx_regno[];
|
||||
extern int mips_dwarf_regno[];
|
||||
extern bool mips_split_p[];
|
||||
|
|
|
@ -3204,7 +3204,7 @@
|
|||
(clobber (match_scratch:DF 2 "=d"))]
|
||||
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W"
|
||||
{
|
||||
if (set_nomacro)
|
||||
if (mips_nomacro.nesting_level > 0)
|
||||
return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro";
|
||||
else
|
||||
return "trunc.w.d %0,%1,%2";
|
||||
|
@ -3241,7 +3241,7 @@
|
|||
(clobber (match_scratch:SF 2 "=d"))]
|
||||
"TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W"
|
||||
{
|
||||
if (set_nomacro)
|
||||
if (mips_nomacro.nesting_level > 0)
|
||||
return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro";
|
||||
else
|
||||
return "trunc.w.s %0,%1,%2";
|
||||
|
@ -4790,7 +4790,7 @@
|
|||
UNSPEC_CPRESTORE)]
|
||||
""
|
||||
{
|
||||
if (set_nomacro && which_alternative == 1)
|
||||
if (mips_nomacro.nesting_level > 0 && which_alternative == 1)
|
||||
return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro";
|
||||
else
|
||||
return ".cprestore\t%0";
|
||||
|
@ -6259,7 +6259,7 @@
|
|||
[(const_int 1)]
|
||||
""
|
||||
{
|
||||
if (set_noreorder)
|
||||
if (mips_noreorder.nesting_level > 0)
|
||||
return "nop";
|
||||
else
|
||||
return "#nop";
|
||||
|
|
|
@ -93,7 +93,7 @@ extern void mips_sync_icache (void *beg, unsigned long len);
|
|||
#undef FUNCTION_PROFILER
|
||||
#define FUNCTION_PROFILER(FILE, LABELNO) \
|
||||
{ \
|
||||
fprintf (FILE, "\t.set\tnoat\n"); \
|
||||
mips_push_asm_switch (&mips_noat); \
|
||||
/* _mcount treats $2 as the static chain register. */ \
|
||||
if (cfun->static_chain_decl != NULL) \
|
||||
fprintf (FILE, "\tmove\t%s,%s\n", reg_names[2], \
|
||||
|
@ -103,7 +103,7 @@ extern void mips_sync_icache (void *beg, unsigned long len);
|
|||
reg_names[GP_REG_FIRST + (TARGET_MIPS16 ? 3 : 1)], \
|
||||
reg_names[GP_REG_FIRST + 31]); \
|
||||
fprintf (FILE, "\tjal\t_mcount\n"); \
|
||||
fprintf (FILE, "\t.set\tat\n"); \
|
||||
mips_pop_asm_switch (&mips_noat); \
|
||||
/* _mcount treats $2 as the static chain register. */ \
|
||||
if (cfun->static_chain_decl != NULL) \
|
||||
fprintf (FILE, "\tmove\t%s,%s\n", reg_names[STATIC_CHAIN_REGNUM], \
|
||||
|
|
Loading…
Reference in New Issue