mips.md: Complete the unfinished R4000 multiply/shift errata workaround.
* config/mips/mips.md: Complete the unfinished R4000 multiply/shift errata workaround. Improve documentation. (hazard): Use TARGET_FIX_R4000 to decide whether an "imul" instruction has a hilo hazard. (mulsi3, mulsi3_internal, mulsi3_r4000): Use TARGET_FIX_R4000. (muldi3, muldi3_internal): Likewise. (muldi3_internal2): Remove, replacing with... (muldi3_mult3, muldi3_r4000): ...these new patterns. (mulsidi3): Take the errata into account. (mulsidi3_32bit): Remove, replacing with... (mulsidi3_32bit_internal, mulsidi3_32bit_r4000): ...these new patterns. (mulsidi3_64bit, mulsidi3_64bit_parts): Disable if TARGET_FIX_R4000. (umulsidi3): Take the errata into account. (umulsidi3_32bit): Remove, replacing with.. (umulsidi3_32bit_internal, umulsidi3_32bit_r4000): ...these patterns. (umulsi3_highpart, umulsi3_highpart_internal): Disable if TARGET_FIX_R4000. (smulsi3_highpart, smulsi3_highpart_internal): Likewise. (smuldi3_highpart, umuldi3_highpart): Likewise. * doc/invoke.texi: Document the errata workaround. From-SVN: r78622
This commit is contained in:
parent
4649040309
commit
bddbfe5f67
3 changed files with 150 additions and 40 deletions
|
@ -1,3 +1,26 @@
|
|||
2004-02-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
|
||||
|
||||
* config/mips/mips.md: Complete the unfinished R4000
|
||||
multiply/shift errata workaround. Improve documentation.
|
||||
(hazard): Use TARGET_FIX_R4000 to decide whether an "imul" instruction
|
||||
has a hilo hazard.
|
||||
(mulsi3, mulsi3_internal, mulsi3_r4000): Use TARGET_FIX_R4000.
|
||||
(muldi3, muldi3_internal): Likewise.
|
||||
(muldi3_internal2): Remove, replacing with...
|
||||
(muldi3_mult3, muldi3_r4000): ...these new patterns.
|
||||
(mulsidi3): Take the errata into account.
|
||||
(mulsidi3_32bit): Remove, replacing with...
|
||||
(mulsidi3_32bit_internal, mulsidi3_32bit_r4000): ...these new patterns.
|
||||
(mulsidi3_64bit, mulsidi3_64bit_parts): Disable if TARGET_FIX_R4000.
|
||||
(umulsidi3): Take the errata into account.
|
||||
(umulsidi3_32bit): Remove, replacing with..
|
||||
(umulsidi3_32bit_internal, umulsidi3_32bit_r4000): ...these patterns.
|
||||
(umulsi3_highpart, umulsi3_highpart_internal): Disable if
|
||||
TARGET_FIX_R4000.
|
||||
(smulsi3_highpart, smulsi3_highpart_internal): Likewise.
|
||||
(smuldi3_highpart, umuldi3_highpart): Likewise.
|
||||
* doc/invoke.texi: Document the errata workaround.
|
||||
|
||||
2004-02-28 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
|
||||
|
||||
* config/mips/mips-protos.h (mips_idiv_insns): Declare.
|
||||
|
|
|
@ -233,7 +233,7 @@
|
|||
|
||||
;; The r4000 multiplication patterns include an mflo instruction.
|
||||
(and (eq_attr "type" "imul")
|
||||
(ne (symbol_ref "TARGET_MIPS4000") (const_int 0)))
|
||||
(ne (symbol_ref "TARGET_FIX_R4000") (const_int 0)))
|
||||
(const_string "hilo")
|
||||
|
||||
(and (eq_attr "type" "hilo")
|
||||
|
@ -1420,9 +1420,51 @@
|
|||
(set_attr "length" "8")])
|
||||
|
||||
|
||||
;; ??? The R4000 (only) has a cpu bug. If a double-word shift executes while
|
||||
;; a multiply is in progress, it may give an incorrect result. Avoid
|
||||
;; this by keeping the mflo with the mult on the R4000.
|
||||
;; The original R4000 has a cpu bug. If a double-word or a variable
|
||||
;; shift executes while an integer multiplication is in progress, the
|
||||
;; shift may give an incorrect result. Avoid this by keeping the mflo
|
||||
;; with the mult on the R4000.
|
||||
;;
|
||||
;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
|
||||
;; (also valid for MIPS R4000MC processors):
|
||||
;;
|
||||
;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to
|
||||
;; this errata description.
|
||||
;; The following code sequence causes the R4000 to incorrectly
|
||||
;; execute the Double Shift Right Arithmetic 32 (dsra32)
|
||||
;; instruction. If the dsra32 instruction is executed during an
|
||||
;; integer multiply, the dsra32 will only shift by the amount in
|
||||
;; specified in the instruction rather than the amount plus 32
|
||||
;; bits.
|
||||
;; instruction 1: mult rs,rt integer multiply
|
||||
;; instruction 2-12: dsra32 rd,rt,rs doubleword shift
|
||||
;; right arithmetic + 32
|
||||
;; Workaround: A dsra32 instruction placed after an integer
|
||||
;; multiply should not be one of the 11 instructions after the
|
||||
;; multiply instruction."
|
||||
;;
|
||||
;; and:
|
||||
;;
|
||||
;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by
|
||||
;; the following description.
|
||||
;; All extended shifts (shift by n+32) and variable shifts (32 and
|
||||
;; 64-bit versions) may produce incorrect results under the
|
||||
;; following conditions:
|
||||
;; 1) An integer multiply is currently executing
|
||||
;; 2) These types of shift instructions are executed immediately
|
||||
;; following an integer divide instruction.
|
||||
;; Workaround:
|
||||
;; 1) Make sure no integer multiply is running wihen these
|
||||
;; instruction are executed. If this cannot be predicted at
|
||||
;; compile time, then insert a "mfhi" to R0 instruction
|
||||
;; immediately after the integer multiply instruction. This
|
||||
;; will cause the integer multiply to complete before the shift
|
||||
;; is executed.
|
||||
;; 2) Separate integer divide and these two classes of shift
|
||||
;; instructions by another instruction or a noop."
|
||||
;;
|
||||
;; These processors have PRId values of 0x00004220 and 0x00004300,
|
||||
;; respectively.
|
||||
|
||||
(define_expand "mulsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
|
@ -1432,7 +1474,7 @@
|
|||
{
|
||||
if (GENERATE_MULT3_SI || TARGET_MAD)
|
||||
emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
|
||||
else if (!TARGET_MIPS4000 || TARGET_MIPS16)
|
||||
else if (!TARGET_FIX_R4000)
|
||||
emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
|
||||
else
|
||||
emit_insn (gen_mulsi3_r4000 (operands[0], operands[1], operands[2]));
|
||||
|
@ -1498,7 +1540,7 @@
|
|||
(mult:SI (match_operand:SI 1 "register_operand" "d")
|
||||
(match_operand:SI 2 "register_operand" "d")))
|
||||
(clobber (match_scratch:SI 3 "=h"))]
|
||||
"!TARGET_MIPS4000 || TARGET_MIPS16"
|
||||
"!TARGET_FIX_R4000"
|
||||
"mult\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")])
|
||||
|
@ -1509,7 +1551,7 @@
|
|||
(match_operand:SI 2 "register_operand" "d")))
|
||||
(clobber (match_scratch:SI 3 "=h"))
|
||||
(clobber (match_scratch:SI 4 "=l"))]
|
||||
"TARGET_MIPS4000 && !TARGET_MIPS16"
|
||||
"TARGET_FIX_R4000"
|
||||
"mult\t%1,%2\;mflo\t%0"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")
|
||||
|
@ -1829,42 +1871,47 @@
|
|||
(match_operand:DI 2 "register_operand" "")))]
|
||||
"TARGET_64BIT"
|
||||
{
|
||||
if (GENERATE_MULT3_DI || TARGET_MIPS4000)
|
||||
emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2]));
|
||||
else
|
||||
if (GENERATE_MULT3_DI)
|
||||
emit_insn (gen_muldi3_mult3 (operands[0], operands[1], operands[2]));
|
||||
else if (!TARGET_FIX_R4000)
|
||||
emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
|
||||
else
|
||||
emit_insn (gen_muldi3_r4000 (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "muldi3_mult3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(mult:DI (match_operand:DI 1 "register_operand" "d")
|
||||
(match_operand:DI 2 "register_operand" "d")))
|
||||
(clobber (match_scratch:DI 3 "=h"))
|
||||
(clobber (match_scratch:DI 4 "=l"))]
|
||||
"TARGET_64BIT && GENERATE_MULT3_DI"
|
||||
"dmult\t%0,%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "muldi3_internal"
|
||||
[(set (match_operand:DI 0 "register_operand" "=l")
|
||||
(mult:DI (match_operand:DI 1 "register_operand" "d")
|
||||
(match_operand:DI 2 "register_operand" "d")))
|
||||
(clobber (match_scratch:DI 3 "=h"))]
|
||||
"TARGET_64BIT && !TARGET_MIPS4000"
|
||||
"TARGET_64BIT && !TARGET_FIX_R4000"
|
||||
"dmult\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "muldi3_internal2"
|
||||
(define_insn "muldi3_r4000"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(mult:DI (match_operand:DI 1 "register_operand" "d")
|
||||
(match_operand:DI 2 "register_operand" "d")))
|
||||
(clobber (match_scratch:DI 3 "=h"))
|
||||
(clobber (match_scratch:DI 4 "=l"))]
|
||||
"TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000)"
|
||||
{
|
||||
if (GENERATE_MULT3_DI)
|
||||
return "dmult\t%0,%1,%2";
|
||||
else
|
||||
return "dmult\t%1,%2\;mflo\t%0";
|
||||
}
|
||||
"TARGET_64BIT && TARGET_FIX_R4000"
|
||||
"dmult\t%1,%2\;mflo\t%0"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "DI")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "GENERATE_MULT3_DI") (const_int 0))
|
||||
(const_int 4)
|
||||
(const_int 8)))])
|
||||
(set_attr "length" "8")])
|
||||
|
||||
;; ??? We could define a mulditi3 pattern when TARGET_64BIT.
|
||||
|
||||
|
@ -1877,25 +1924,43 @@
|
|||
(clobber (scratch:DI))
|
||||
(clobber (scratch:DI))
|
||||
(clobber (scratch:DI))])]
|
||||
""
|
||||
"!TARGET_64BIT || !TARGET_FIX_R4000"
|
||||
{
|
||||
if (!TARGET_64BIT)
|
||||
{
|
||||
emit_insn (gen_mulsidi3_32bit (operands[0], operands[1], operands[2]));
|
||||
if (!TARGET_FIX_R4000)
|
||||
emit_insn (gen_mulsidi3_32bit_internal (operands[0], operands[1],
|
||||
operands[2]));
|
||||
else
|
||||
emit_insn (gen_mulsidi3_32bit_r4000 (operands[0], operands[1],
|
||||
operands[2]));
|
||||
DONE;
|
||||
}
|
||||
})
|
||||
|
||||
(define_insn "mulsidi3_32bit"
|
||||
(define_insn "mulsidi3_32bit_internal"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(mult:DI
|
||||
(sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
|
||||
(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
|
||||
"!TARGET_64BIT"
|
||||
"!TARGET_64BIT && !TARGET_FIX_R4000"
|
||||
"mult\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "mulsidi3_32bit_r4000"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(mult:DI
|
||||
(sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
|
||||
(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
|
||||
(clobber (match_scratch:DI 3 "=l"))
|
||||
(clobber (match_scratch:DI 4 "=h"))]
|
||||
"!TARGET_64BIT && TARGET_FIX_R4000"
|
||||
"mult\t%1,%2\;mflo\t%L0;mfhi\t%M0"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
(define_insn_and_split "*mulsidi3_64bit"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(mult:DI (match_operator:DI 1 "extend_operator"
|
||||
|
@ -1905,7 +1970,8 @@
|
|||
(clobber (match_scratch:DI 5 "=l"))
|
||||
(clobber (match_scratch:DI 6 "=h"))
|
||||
(clobber (match_scratch:DI 7 "=d"))]
|
||||
"TARGET_64BIT && GET_CODE (operands[1]) == GET_CODE (operands[2])"
|
||||
"TARGET_64BIT && !TARGET_FIX_R4000
|
||||
&& GET_CODE (operands[1]) == GET_CODE (operands[2])"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel
|
||||
|
@ -1956,7 +2022,8 @@
|
|||
(match_operator:DI 4 "extend_operator" [(match_dup 2)])
|
||||
(match_operator:DI 5 "extend_operator" [(match_dup 3)]))
|
||||
(const_int 32)))]
|
||||
"TARGET_64BIT && GET_CODE (operands[4]) == GET_CODE (operands[5])"
|
||||
"TARGET_64BIT && !TARGET_FIX_R4000
|
||||
&& GET_CODE (operands[4]) == GET_CODE (operands[5])"
|
||||
{
|
||||
if (GET_CODE (operands[4]) == SIGN_EXTEND)
|
||||
return "mult\t%2,%3";
|
||||
|
@ -1975,26 +2042,43 @@
|
|||
(clobber (scratch:DI))
|
||||
(clobber (scratch:DI))
|
||||
(clobber (scratch:DI))])]
|
||||
""
|
||||
"!TARGET_64BIT || !TARGET_FIX_R4000"
|
||||
{
|
||||
if (!TARGET_64BIT)
|
||||
{
|
||||
emit_insn (gen_umulsidi3_32bit (operands[0], operands[1],
|
||||
operands[2]));
|
||||
if (!TARGET_FIX_R4000)
|
||||
emit_insn (gen_umulsidi3_32bit_internal (operands[0], operands[1],
|
||||
operands[2]));
|
||||
else
|
||||
emit_insn (gen_umulsidi3_32bit_r4000 (operands[0], operands[1],
|
||||
operands[2]));
|
||||
DONE;
|
||||
}
|
||||
})
|
||||
|
||||
(define_insn "umulsidi3_32bit"
|
||||
(define_insn "umulsidi3_32bit_internal"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
(mult:DI
|
||||
(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
|
||||
(zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
|
||||
"!TARGET_64BIT"
|
||||
"!TARGET_64BIT && !TARGET_FIX_R4000"
|
||||
"multu\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "umulsidi3_32bit_r4000"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(mult:DI
|
||||
(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
|
||||
(zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))
|
||||
(clobber (match_scratch:DI 3 "=l"))
|
||||
(clobber (match_scratch:DI 4 "=h"))]
|
||||
"!TARGET_64BIT && TARGET_FIX_R4000"
|
||||
"multu\t%1,%2\;mflo\t%L0;mfhi\t%M0"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
;; Widening multiply with negation.
|
||||
(define_insn "*muls_di"
|
||||
[(set (match_operand:DI 0 "register_operand" "=x")
|
||||
|
@ -2064,7 +2148,7 @@
|
|||
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
|
||||
(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
|
||||
(const_int 32))))]
|
||||
""
|
||||
"ISA_HAS_MULHI || !TARGET_FIX_R4000"
|
||||
{
|
||||
if (ISA_HAS_MULHI)
|
||||
emit_insn (gen_umulsi3_highpart_mulhi_internal (operands[0], operands[1],
|
||||
|
@ -2083,7 +2167,7 @@
|
|||
(zero_extend:DI (match_operand:SI 2 "register_operand" "d")))
|
||||
(const_int 32))))
|
||||
(clobber (match_scratch:SI 3 "=l"))]
|
||||
"!ISA_HAS_MULHI"
|
||||
"!ISA_HAS_MULHI && !TARGET_FIX_R4000"
|
||||
"multu\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")
|
||||
|
@ -2131,7 +2215,7 @@
|
|||
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
|
||||
(sign_extend:DI (match_operand:SI 2 "register_operand" "")))
|
||||
(const_int 32))))]
|
||||
""
|
||||
"ISA_HAS_MULHI || !TARGET_FIX_R4000"
|
||||
{
|
||||
if (ISA_HAS_MULHI)
|
||||
emit_insn (gen_smulsi3_highpart_mulhi_internal (operands[0], operands[1],
|
||||
|
@ -2150,7 +2234,7 @@
|
|||
(sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
|
||||
(const_int 32))))
|
||||
(clobber (match_scratch:SI 3 "=l"))]
|
||||
"!ISA_HAS_MULHI"
|
||||
"!ISA_HAS_MULHI && !TARGET_FIX_R4000"
|
||||
"mult\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "SI")
|
||||
|
@ -2199,7 +2283,7 @@
|
|||
(sign_extend:TI (match_operand:DI 2 "register_operand" "d")))
|
||||
(const_int 64))))
|
||||
(clobber (match_scratch:DI 3 "=l"))]
|
||||
"TARGET_64BIT"
|
||||
"TARGET_64BIT && !TARGET_FIX_R4000"
|
||||
"dmult\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "DI")])
|
||||
|
@ -2213,7 +2297,7 @@
|
|||
(zero_extend:TI (match_operand:DI 2 "register_operand" "d")))
|
||||
(const_int 64))))
|
||||
(clobber (match_scratch:DI 3 "=l"))]
|
||||
"TARGET_64BIT"
|
||||
"TARGET_64BIT && !TARGET_FIX_R4000"
|
||||
"dmultu\t%1,%2"
|
||||
[(set_attr "type" "imul")
|
||||
(set_attr "mode" "DI")])
|
||||
|
|
|
@ -8055,6 +8055,9 @@ Work around certain R4000 CPU errata:
|
|||
@item
|
||||
A double-word or a variable shift may give an incorrect result if executed
|
||||
immediately after starting an integer division.
|
||||
@item
|
||||
A double-word or a variable shift may give an incorrect result if executed
|
||||
while an integer multiplication is in progress.
|
||||
@end itemize
|
||||
|
||||
@item -mfix-sb1
|
||||
|
|
Loading…
Add table
Reference in a new issue