mips-protos.h (mips_idiv_insns): Declare.
* config/mips/mips-protos.h (mips_idiv_insns): Declare. * config/mips/mips.h (MASK_FIX_SB1): Bump. (MASK_FIX_R4000, TARGET_FIX_R4000): New macros. (TARGET_SWITCHES): Add -mfix-r4000 and -mno-fix-r4000. * config/mips/mips.c (mips_idiv_insns): New function. (override_options): Make -march=r4000 imply -mfix-r4000 by default. (mips_output_division): Add a workaround for the R4000 divide/shift errata. * config/mips/mips.md (length): Use mips_idiv_insns() to calculate the length of an "idiv" instruction. * doc/invoke.texi: Document the new switches. From-SVN: r78621
This commit is contained in:
parent
1b2c37673a
commit
4649040309
6 changed files with 88 additions and 13 deletions
|
@ -1,3 +1,17 @@
|
|||
2004-02-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
|
||||
|
||||
* config/mips/mips-protos.h (mips_idiv_insns): Declare.
|
||||
* config/mips/mips.h (MASK_FIX_SB1): Bump.
|
||||
(MASK_FIX_R4000, TARGET_FIX_R4000): New macros.
|
||||
(TARGET_SWITCHES): Add -mfix-r4000 and -mno-fix-r4000.
|
||||
* config/mips/mips.c (mips_idiv_insns): New function.
|
||||
(override_options): Make -march=r4000 imply -mfix-r4000 by default.
|
||||
(mips_output_division): Add a workaround for the R4000 divide/shift
|
||||
errata.
|
||||
* config/mips/mips.md (length): Use mips_idiv_insns() to calculate
|
||||
the length of an "idiv" instruction.
|
||||
* doc/invoke.texi: Document the new switches.
|
||||
|
||||
2004-02-28 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* doc/tm.texi (IS_COSTLY_DEPENDENCE): Change to
|
||||
|
|
|
@ -30,6 +30,7 @@ extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, int);
|
|||
extern int mips_address_insns (rtx, enum machine_mode);
|
||||
extern int mips_const_insns (rtx);
|
||||
extern int mips_fetch_insns (rtx);
|
||||
extern int mips_idiv_insns (void);
|
||||
extern bool mips_legitimate_address_p (enum machine_mode, rtx, int);
|
||||
extern bool mips_legitimize_address (rtx *, enum machine_mode);
|
||||
extern rtx mips_gotoff_page (rtx);
|
||||
|
|
|
@ -1350,6 +1350,27 @@ mips_fetch_insns (rtx x)
|
|||
}
|
||||
|
||||
|
||||
/* Return the number of instructions needed for an integer division. */
|
||||
|
||||
int
|
||||
mips_idiv_insns (void)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = 1;
|
||||
if (TARGET_CHECK_ZERO_DIV)
|
||||
{
|
||||
if (TARGET_MIPS16)
|
||||
count += 2;
|
||||
else
|
||||
count += 3;
|
||||
}
|
||||
if (TARGET_FIX_R4000)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* Return truth value of whether OP can be used as an operands
|
||||
where a register or 16 bit unsigned integer is needed. */
|
||||
|
||||
|
@ -5111,6 +5132,12 @@ override_options (void)
|
|||
mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
|
||||
mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
|
||||
}
|
||||
|
||||
/* Default to working around R4000 errata only if the processor
|
||||
was selected explicitly. */
|
||||
if ((target_flags_explicit & MASK_FIX_R4000) == 0
|
||||
&& mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
|
||||
target_flags |= MASK_FIX_R4000;
|
||||
}
|
||||
|
||||
/* Implement CONDITIONAL_REGISTER_USAGE. */
|
||||
|
@ -9185,21 +9212,37 @@ mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p,
|
|||
/* Used to output div or ddiv instruction DIVISION, which has the
|
||||
operands given by OPERANDS. If we need a divide-by-zero check,
|
||||
output the instruction and return an asm string that traps if
|
||||
operand 2 is zero. Otherwise just return DIVISION itself. */
|
||||
operand 2 is zero.
|
||||
|
||||
The original R4000 has a cpu bug. If a double-word or a variable
|
||||
shift executes immediately after starting an integer division, the
|
||||
shift may give an incorrect result. Avoid this by adding a nop on
|
||||
the R4000. See quotations of errata #16 and #28 from "MIPS
|
||||
R4000PC/SC Errata, Processor Revision 2.2 and 3.0" in mips.md for
|
||||
details.
|
||||
|
||||
Otherwise just return DIVISION itself. */
|
||||
|
||||
const char *
|
||||
mips_output_division (const char *division, rtx *operands)
|
||||
{
|
||||
const char *s = division;
|
||||
|
||||
if (TARGET_CHECK_ZERO_DIV)
|
||||
{
|
||||
output_asm_insn (division, operands);
|
||||
output_asm_insn (s, operands);
|
||||
|
||||
if (TARGET_MIPS16)
|
||||
return "bnez\t%2,1f\n\tbreak\t7\n1:";
|
||||
s = "bnez\t%2,1f\n\tbreak\t7\n1:";
|
||||
else
|
||||
return "bne\t%2,%.,1f%#\n\tbreak\t7\n1:";
|
||||
s = "bne\t%2,%.,1f%#\n\tbreak\t7\n1:";
|
||||
}
|
||||
return division;
|
||||
if (TARGET_FIX_R4000)
|
||||
{
|
||||
output_asm_insn (s, operands);
|
||||
s = "nop";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL
|
||||
|
|
|
@ -169,7 +169,8 @@ extern const struct mips_cpu_info *mips_tune_info;
|
|||
#define MASK_UNINIT_CONST_IN_RODATA \
|
||||
0x00800000 /* Store uninitialized
|
||||
consts in rodata */
|
||||
#define MASK_FIX_SB1 0x01000000 /* Work around SB-1 errata. */
|
||||
#define MASK_FIX_R4000 0x01000000 /* Work around R4000 errata. */
|
||||
#define MASK_FIX_SB1 0x02000000 /* Work around SB-1 errata. */
|
||||
|
||||
/* Debug switches, not documented */
|
||||
#define MASK_DEBUG 0 /* unused */
|
||||
|
@ -248,6 +249,9 @@ extern const struct mips_cpu_info *mips_tune_info;
|
|||
|
||||
#define TARGET_FIX_SB1 (target_flags & MASK_FIX_SB1)
|
||||
|
||||
/* Work around R4000 errata. */
|
||||
#define TARGET_FIX_R4000 (target_flags & MASK_FIX_R4000)
|
||||
|
||||
/* True if we should use NewABI-style relocation operators for
|
||||
symbolic addresses. This is never true for mips16 code,
|
||||
which has its own conventions. */
|
||||
|
@ -588,6 +592,10 @@ extern const struct mips_cpu_info *mips_tune_info;
|
|||
N_("Work around errata for early SB-1 revision 2 cores")}, \
|
||||
{"no-fix-sb1", -MASK_FIX_SB1, \
|
||||
N_("Don't work around errata for early SB-1 revision 2 cores")}, \
|
||||
{"fix-r4000", MASK_FIX_R4000, \
|
||||
N_("Work around R4000 errata")}, \
|
||||
{"no-fix-r4000", -MASK_FIX_R4000, \
|
||||
N_("Don't work around R4000 errata")}, \
|
||||
{"check-zero-division",-MASK_NO_CHECK_ZERO_DIV, \
|
||||
N_("Trap on integer divide by zero")}, \
|
||||
{"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV, \
|
||||
|
|
|
@ -204,11 +204,8 @@
|
|||
(ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
|
||||
(const_int 8)
|
||||
|
||||
(and (eq_attr "type" "idiv")
|
||||
(ne (symbol_ref "TARGET_CHECK_ZERO_DIV") (const_int 0)))
|
||||
(cond [(ne (symbol_ref "TARGET_MIPS16") (const_int 0))
|
||||
(const_int 12)]
|
||||
(const_int 16))
|
||||
(eq_attr "type" "idiv")
|
||||
(symbol_ref "mips_idiv_insns () * 4")
|
||||
] (const_int 4)))
|
||||
|
||||
;; Attribute describing the processor. This attribute must match exactly
|
||||
|
|
|
@ -478,8 +478,9 @@ in the following sections.
|
|||
-mcheck-zero-division -mno-check-zero-division @gol
|
||||
-mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol
|
||||
-mmad -mno-mad -mfused-madd -mno-fused-madd -nocpp @gol
|
||||
-mfix-sb1 -mno-fix-sb1 -mflush-func=@var{func} @gol
|
||||
-mno-flush-func -mbranch-likely -mno-branch-likely}
|
||||
-mfix-r4000 -mno-fix-r4000 -mfix-sb1 -mno-fix-sb1 @gol
|
||||
-mflush-func=@var{func} -mno-flush-func @gol
|
||||
-mbranch-likely -mno-branch-likely}
|
||||
|
||||
@emph{i386 and x86-64 Options}
|
||||
@gccoptlist{-mtune=@var{cpu-type} -march=@var{cpu-type} @gol
|
||||
|
@ -8045,6 +8046,17 @@ circumstances.
|
|||
Tell the MIPS assembler to not run its preprocessor over user
|
||||
assembler files (with a @samp{.s} suffix) when assembling them.
|
||||
|
||||
@item -mfix-r4000
|
||||
@itemx -mno-fix-r4000
|
||||
@opindex mfix-r4000
|
||||
@opindex mno-fix-r4000
|
||||
Work around certain R4000 CPU errata:
|
||||
@itemize @minus
|
||||
@item
|
||||
A double-word or a variable shift may give an incorrect result if executed
|
||||
immediately after starting an integer division.
|
||||
@end itemize
|
||||
|
||||
@item -mfix-sb1
|
||||
@itemx -mno-fix-sb1
|
||||
@opindex mfix-sb1
|
||||
|
|
Loading…
Add table
Reference in a new issue