Commit c235ddf2 by DJ Delorie Committed by Richard Sandiford

mips.h (MASK_FIX_VR4122, [...]): New macros.

	* config/mips/mips.h (MASK_FIX_VR4122, TARGET_FIX_VR4122): New macros.
	(TARGET_SWITCHES): Add -mfix-vr4122-bugs and -mno-fix-vr4122-bugs.
	(ASM_SPEC): Pass down -mfix-vr4122-bugs.
	* config/mips/mips.c (mips_avoid_hazards): Don't emit whole functions
	in .set noreorder and .set nomacro if TARGET_FIX_VR4122.
	(mips_init_libfuncs): Use special functions for divsi3 and modsi3
	if TARGET_FIX_VR4122.
	* config/mips/mips.md (define_attr length): Account for nops inserted
	after macc and dmult when using -mfix-vr4122-bugs.
	(umuldi3_highpart, divmodsi4, divmoddi4): Disable if TARGET_FIX_VR4122.
	* config/mips/t-vr (LIB2FUNCS_STATIC_EXTRA): Define instead of
	LIB2FUNCS_EXTRA.  Add config/mips/vr4122-div.S.
	* config/mips/vr4122-div.S: New file.
	* doc/invoke.texi: Document -mfix-vr4122-bugs.

Co-Authored-By: Richard Sandiford <rsandifo@redhat.com>

From-SVN: r79912
parent cf768d70
2004-03-24 DJ Delorie <dj@redhat.com>
Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.h (MASK_FIX_VR4122, TARGET_FIX_VR4122): New macros.
(TARGET_SWITCHES): Add -mfix-vr4122-bugs and -mno-fix-vr4122-bugs.
(ASM_SPEC): Pass down -mfix-vr4122-bugs.
* config/mips/mips.c (mips_avoid_hazards): Don't emit whole functions
in .set noreorder and .set nomacro if TARGET_FIX_VR4122.
(mips_init_libfuncs): Use special functions for divsi3 and modsi3
if TARGET_FIX_VR4122.
* config/mips/mips.md (define_attr length): Account for nops inserted
after macc and dmult when using -mfix-vr4122-bugs.
(umuldi3_highpart, divmodsi4, divmoddi4): Disable if TARGET_FIX_VR4122.
* config/mips/t-vr (LIB2FUNCS_STATIC_EXTRA): Define instead of
LIB2FUNCS_EXTRA. Add config/mips/vr4122-div.S.
* config/mips/vr4122-div.S: New file.
* doc/invoke.texi: Document -mfix-vr4122-bugs.
2004-03-24 Richard Sandiford <rsandifo@redhat.com> 2004-03-24 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.h (PROCESSOR_R4130): New processor_type. * config/mips/mips.h (PROCESSOR_R4130): New processor_type.
......
...@@ -8721,8 +8721,10 @@ mips_avoid_hazards (void) ...@@ -8721,8 +8721,10 @@ mips_avoid_hazards (void)
cfun->machine->ignore_hazard_length_p = true; cfun->machine->ignore_hazard_length_p = true;
shorten_branches (get_insns ()); shorten_branches (get_insns ());
/* The profiler code uses assembler macros. */ /* The profiler code uses assembler macros. -mfix-vr4122-bugs
cfun->machine->all_noreorder_p = !current_function_profile; relies on assembler nop insertion. */
cfun->machine->all_noreorder_p = (!current_function_profile
&& !TARGET_FIX_VR4122);
last_insn = 0; last_insn = 0;
hilo_delay = 2; hilo_delay = 2;
...@@ -8760,14 +8762,23 @@ mips_reorg (void) ...@@ -8760,14 +8762,23 @@ mips_reorg (void)
} }
} }
/* We need to use a special set of functions to handle hard floating /* This function does three things:
point code in mips16 mode. Also, allow for --enable-gofast. */
- Register the special divsi3 and modsi3 functions if -mfix-vr4122-bugs.
- Register the mips16 hardware floating point stubs.
- Register the gofast functions if selected using --enable-gofast. */
#include "config/gofast.h" #include "config/gofast.h"
static void static void
mips_init_libfuncs (void) mips_init_libfuncs (void)
{ {
if (TARGET_FIX_VR4122)
{
set_optab_libfunc (sdiv_optab, SImode, "__vr4122_divsi3");
set_optab_libfunc (smod_optab, SImode, "__vr4122_modsi3");
}
if (TARGET_MIPS16 && mips16_hard_float) if (TARGET_MIPS16 && mips16_hard_float)
{ {
set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3"); set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
......
...@@ -173,6 +173,7 @@ extern const struct mips_cpu_info *mips_tune_info; ...@@ -173,6 +173,7 @@ extern const struct mips_cpu_info *mips_tune_info;
#define MASK_FIX_R4000 0x01000000 /* Work around R4000 errata. */ #define MASK_FIX_R4000 0x01000000 /* Work around R4000 errata. */
#define MASK_FIX_R4400 0x02000000 /* Work around R4400 errata. */ #define MASK_FIX_R4400 0x02000000 /* Work around R4400 errata. */
#define MASK_FIX_SB1 0x04000000 /* Work around SB-1 errata. */ #define MASK_FIX_SB1 0x04000000 /* Work around SB-1 errata. */
#define MASK_FIX_VR4122 0x08000000 /* Work-around VR4122 errata. */
/* Debug switches, not documented */ /* Debug switches, not documented */
#define MASK_DEBUG 0 /* unused */ #define MASK_DEBUG 0 /* unused */
...@@ -256,6 +257,7 @@ extern const struct mips_cpu_info *mips_tune_info; ...@@ -256,6 +257,7 @@ extern const struct mips_cpu_info *mips_tune_info;
/* Work around R4400 errata. */ /* Work around R4400 errata. */
#define TARGET_FIX_R4400 (target_flags & MASK_FIX_R4400) #define TARGET_FIX_R4400 (target_flags & MASK_FIX_R4400)
#define TARGET_FIX_VR4122 (target_flags & MASK_FIX_VR4122)
/* True if we should use NewABI-style relocation operators for /* True if we should use NewABI-style relocation operators for
symbolic addresses. This is never true for mips16 code, symbolic addresses. This is never true for mips16 code,
...@@ -606,6 +608,10 @@ extern const struct mips_cpu_info *mips_tune_info; ...@@ -606,6 +608,10 @@ extern const struct mips_cpu_info *mips_tune_info;
N_("Work around R4400 errata")}, \ N_("Work around R4400 errata")}, \
{"no-fix-r4400", -MASK_FIX_R4400, \ {"no-fix-r4400", -MASK_FIX_R4400, \
N_("Don't work around R4400 errata")}, \ N_("Don't work around R4400 errata")}, \
{"fix-vr4122-bugs", MASK_FIX_VR4122, \
N_("Work around certain VR4122 errata")}, \
{"no-fix-vr4122-bugs", -MASK_FIX_VR4122, \
N_("Don't work around certain VR4122 errata")}, \
{"check-zero-division",-MASK_NO_CHECK_ZERO_DIV, \ {"check-zero-division",-MASK_NO_CHECK_ZERO_DIV, \
N_("Trap on integer divide by zero")}, \ N_("Trap on integer divide by zero")}, \
{"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV, \ {"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV, \
...@@ -1109,6 +1115,7 @@ extern const struct mips_cpu_info *mips_tune_info; ...@@ -1109,6 +1115,7 @@ extern const struct mips_cpu_info *mips_tune_info;
%{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \ %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
%{mips32} %{mips32r2} %{mips64} \ %{mips32} %{mips32r2} %{mips64} \
%{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \ %{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
%{mfix-vr4122-bugs} \
%(subtarget_asm_optimizing_spec) \ %(subtarget_asm_optimizing_spec) \
%(subtarget_asm_debugging_spec) \ %(subtarget_asm_debugging_spec) \
%{membedded-pic} \ %{membedded-pic} \
......
...@@ -212,6 +212,21 @@ ...@@ -212,6 +212,21 @@
(ne (symbol_ref "TARGET_MIPS16") (const_int 0))) (ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
(const_int 8) (const_int 8)
;; Various VR4122 errata require a nop to be inserted after a macc
;; instruction. The assembler does this for us, so account for
;; the worst-case length here.
(and (eq_attr "type" "imadd")
(ne (symbol_ref "TARGET_FIX_VR4122") (const_int 0)))
(const_int 8)
;; VR4122 errata MD(4): if there are consecutive dmult instructions,
;; the result of the second one is missed. The assembler should work
;; around this by inserting a nop after the first dmult.
(and (eq_attr "type" "imul")
(and (eq_attr "mode" "DI")
(ne (symbol_ref "TARGET_FIX_VR4122") (const_int 0))))
(const_int 8)
(eq_attr "type" "idiv") (eq_attr "type" "idiv")
(symbol_ref "mips_idiv_insns () * 4") (symbol_ref "mips_idiv_insns () * 4")
] (const_int 4))) ] (const_int 4)))
...@@ -2300,6 +2315,8 @@ ...@@ -2300,6 +2315,8 @@
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
;; Disable this pattern for -mfix-vr4122-bugs. This is for VR4122 errata
;; MD(0), which says that dmultu does not always produce the correct result.
(define_insn "umuldi3_highpart" (define_insn "umuldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=h") [(set (match_operand:DI 0 "register_operand" "=h")
(truncate:DI (truncate:DI
...@@ -2309,7 +2326,7 @@ ...@@ -2309,7 +2326,7 @@
(zero_extend:TI (match_operand:DI 2 "register_operand" "d"))) (zero_extend:TI (match_operand:DI 2 "register_operand" "d")))
(const_int 64)))) (const_int 64))))
(clobber (match_scratch:DI 3 "=l"))] (clobber (match_scratch:DI 3 "=l"))]
"TARGET_64BIT && !TARGET_FIX_R4000" "TARGET_64BIT && !TARGET_FIX_R4000 && !TARGET_FIX_VR4122"
"dmultu\t%1,%2" "dmultu\t%1,%2"
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
...@@ -2583,6 +2600,8 @@ ...@@ -2583,6 +2600,8 @@
(const_int 8) (const_int 8)
(const_int 4)))]) (const_int 4)))])
;; VR4122 errata MD(A1): signed division instructions do not work correctly
;; with negative operands. We use special libgcc functions instead.
(define_insn "divmodsi4" (define_insn "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=l") [(set (match_operand:SI 0 "register_operand" "=l")
(div:SI (match_operand:SI 1 "register_operand" "d") (div:SI (match_operand:SI 1 "register_operand" "d")
...@@ -2590,7 +2609,7 @@ ...@@ -2590,7 +2609,7 @@
(set (match_operand:SI 3 "register_operand" "=h") (set (match_operand:SI 3 "register_operand" "=h")
(mod:SI (match_dup 1) (mod:SI (match_dup 1)
(match_dup 2)))] (match_dup 2)))]
"" "!TARGET_FIX_VR4122"
{ return mips_output_division ("div\t$0,%1,%2", operands); } { return mips_output_division ("div\t$0,%1,%2", operands); }
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
...@@ -2602,7 +2621,7 @@ ...@@ -2602,7 +2621,7 @@
(set (match_operand:DI 3 "register_operand" "=h") (set (match_operand:DI 3 "register_operand" "=h")
(mod:DI (match_dup 1) (mod:DI (match_dup 1)
(match_dup 2)))] (match_dup 2)))]
"TARGET_64BIT" "TARGET_64BIT && !TARGET_FIX_VR4122"
{ return mips_output_division ("ddiv\t$0,%1,%2", operands); } { return mips_output_division ("ddiv\t$0,%1,%2", operands); }
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
......
...@@ -7,7 +7,8 @@ CRTSTUFF_T_CFLAGS = -G 0 ...@@ -7,7 +7,8 @@ CRTSTUFF_T_CFLAGS = -G 0
# without the $gp register. # without the $gp register.
TARGET_LIBGCC2_CFLAGS = -G 0 TARGET_LIBGCC2_CFLAGS = -G 0
LIB2FUNCS_EXTRA = $(srcdir)/config/mips/mips16.S LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/mips16.S \
$(srcdir)/config/mips/vr4122-div.S
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
# Assemble startup files. # Assemble startup files.
......
/* Support file for -mfix-vr4122-bugs.
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This file contains functions which implement divsi3 and modsi3 for
-mfix-vr4122-bugs. div and ddiv do not give the correct result
when one of the operands is negative. */
.set nomips16
#define DIV \
xor $3,$4,$5 /* t = x ^ y */ ; \
li $2,0x80000000; \
.set noreorder; \
bgez $4,1f /* x >= 0 */; \
and $3,$3,$2 /* t = (x ^ y) & 0x80000000 in delay slot */ ;\
.set reorder; \
subu $4,$0,$4 /* x = -x */ ; \
1:; \
.set noreorder; \
bgez $5,2f /* y >= 0 */ ; \
nop; \
subu $5,$0,$5 /* y = -y */ ; \
.set reorder; \
2:; \
divu $0,$4,$5; /* we use divu because of INT_MIN */ \
.set noreorder; \
bne $5,$0,3f; \
nop; \
break 7 /* division on zero y */ ; \
3:; \
.set reorder; \
mflo $2 /* r = x / y */ ; \
.set noreorder; \
beq $3,$0,4f /* t == 0 */ ; \
nop; \
subu $2,$0,$2 /* r = -r */ ; \
.set reorder; \
4:
.globl __vr4122_divsi3
.ent __vr4122_divsi3
__vr4122_divsi3:
DIV
j $31
.end __vr4122_divsi3
.globl __vr4122_modsi3
.ent __vr4122_modsi3
__vr4122_modsi3:
move $6,$4 # x1 = x
move $7,$5 # y1 = y
DIV
mult $2,$7 # r = r * y1
mflo $2
.set noreorder
j $31
subu $2,$6,$2 # r = x1 - r in delay slot
.end __vr4122_modsi3
...@@ -479,7 +479,7 @@ in the following sections. ...@@ -479,7 +479,7 @@ in the following sections.
-mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol -mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol
-mmad -mno-mad -mfused-madd -mno-fused-madd -nocpp @gol -mmad -mno-mad -mfused-madd -mno-fused-madd -nocpp @gol
-mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400 @gol -mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400 @gol
-mfix-sb1 -mno-fix-sb1 @gol -mfix-vr4122-bugs -mno-fix-vr4122-bugs -mfix-sb1 -mno-fix-sb1 @gol
-mflush-func=@var{func} -mno-flush-func @gol -mflush-func=@var{func} -mno-flush-func @gol
-mbranch-likely -mno-branch-likely} -mbranch-likely -mno-branch-likely}
...@@ -8092,6 +8092,24 @@ A double-word or a variable shift may give an incorrect result if executed ...@@ -8092,6 +8092,24 @@ A double-word or a variable shift may give an incorrect result if executed
immediately after starting an integer division. immediately after starting an integer division.
@end itemize @end itemize
@item -mfix-vr4122-bugs
@itemx -mno-fix-vr4122-bugs
@opindex mfix-vr4122-bugs
Work around certain VR4122 errata:
@itemize @minus
@item
@code{dmultu} does not always produce the correct result.
@item
@code{div} and @code{ddiv} do not always produce the correct result if one
of the operands is negative.
@end itemize
The workarounds for the division errata rely on special functions in
@file{libgcc.a}. At present, these functions are only provided by
the @code{mips64vr*-elf} configurations.
Other VR4122 errata require a nop to be inserted between certain pairs of
instructions. These errata are handled by the assembler, not by GCC itself.
@item -mfix-sb1 @item -mfix-sb1
@itemx -mno-fix-sb1 @itemx -mno-fix-sb1
@opindex mfix-sb1 @opindex mfix-sb1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment