aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r--gcc/config/mips/mips.md562
1 files changed, 421 insertions, 141 deletions
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 18d4a76c303..6dde18bf372 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3,7 +3,7 @@
;; Changes by Michael Meissner, meissner@osf.org
;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
;; Brendan Eich, brendan@microunity.com.
-;; Copyright (C) 1989, 90-97, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 90-98, 1999 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -1735,7 +1735,7 @@
&& !TARGET_MIPS16"
"*
{
- static char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" };
+ static const char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" };
if (which_alternative == 2)
return \"#\";
return madd[which_alternative];
@@ -2228,7 +2228,7 @@
;; a divide by power of 2 with a shift, and then the remainder is no longer
;; available.
-(define_insn "divmodsi4"
+(define_expand "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")))
@@ -2239,21 +2239,44 @@
(clobber (match_scratch:SI 5 "=h"))
(clobber (match_scratch:SI 6 "=a"))]
"optimize"
- "*
+ "
{
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"div\\t%0,%1,%2\";
-
- if (find_reg_note (insn, REG_UNUSED, operands[0]))
- return \"rem\\t%3,%1,%2\";
+ emit_insn (gen_divmodsi4_internal (operands[0], operands[1], operands[2],
+ operands[3]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
+}")
- return \"div\\t%0,%1,%2\;mfhi\\t%3\";
-}"
+(define_insn "divmodsi4_internal"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (div:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (set (match_operand:SI 3 "register_operand" "=h")
+ (mod:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:SI 6 "=a"))]
+ "optimize"
+ "div\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "14")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
-(define_insn "divmoddi4"
+(define_expand "divmoddi4"
[(set (match_operand:DI 0 "register_operand" "=d")
(div:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "se_register_operand" "d")))
@@ -2264,21 +2287,44 @@
(clobber (match_scratch:DI 5 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && optimize"
- "*
+ "
{
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"ddiv\\t%0,%1,%2\";
-
- if (find_reg_note (insn, REG_UNUSED, operands[0]))
- return \"drem\\t%3,%1,%2\";
+ emit_insn (gen_divmoddi4_internal (operands[0], operands[1], operands[2],
+ operands[3]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
+}")
- return \"ddiv\\t%0,%1,%2\;mfhi\\t%3\";
-}"
+(define_insn "divmoddi4_internal"
+ [(set (match_operand:DI 0 "register_operand" "=l")
+ (div:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
+ (set (match_operand:DI 3 "register_operand" "=h")
+ (mod:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:DI 6 "=a"))]
+ "TARGET_64BIT && optimize"
+ "ddiv\\t$0,%1,%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "DI")
- (set_attr "length" "15")]) ;; various tests for dividing by 0 and such
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
-(define_insn "udivmodsi4"
+(define_expand "udivmodsi4"
[(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")))
@@ -2289,21 +2335,35 @@
(clobber (match_scratch:SI 5 "=h"))
(clobber (match_scratch:SI 6 "=a"))]
"optimize"
- "*
+ "
{
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"divu\\t%0,%1,%2\";
-
- if (find_reg_note (insn, REG_UNUSED, operands[0]))
- return \"remu\\t%3,%1,%2\";
+ emit_insn (gen_udivmodsi4_internal (operands[0], operands[1], operands[2],
+ operands[3]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
+}")
- return \"divu\\t%0,%1,%2\;mfhi\\t%3\";
-}"
+(define_insn "udivmodsi4_internal"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (udiv:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (set (match_operand:SI 3 "register_operand" "=h")
+ (umod:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:SI 6 "=a"))]
+ "optimize"
+ "divu\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "8")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
-(define_insn "udivmoddi4"
+(define_expand "udivmoddi4"
[(set (match_operand:DI 0 "register_operand" "=d")
(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "se_register_operand" "d")))
@@ -2314,220 +2374,418 @@
(clobber (match_scratch:DI 5 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && optimize"
+ "
+{
+ emit_insn (gen_udivmoddi4_internal (operands[0], operands[1], operands[2],
+ operands[3]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
+}")
+
+(define_insn "udivmoddi4_internal"
+ [(set (match_operand:DI 0 "register_operand" "=l")
+ (udiv:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
+ (set (match_operand:DI 3 "register_operand" "=h")
+ (umod:DI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:DI 6 "=a"))]
+ "TARGET_64BIT && optimize"
+ "ddivu\\t$0,%1,%2"
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
+;; Division trap
+
+(define_expand "div_trap"
+ [(trap_if (eq (match_operand 0 "register_operand" "d")
+ (match_operand 1 "true_reg_or_0_operand" "dJ"))
+ (match_operand 2 "immediate_operand" ""))]
+ ""
+ "
+{
+ if (TARGET_MIPS16)
+ emit_insn (gen_div_trap_mips16 (operands[0],operands[1],operands[2]));
+ else
+ emit_insn (gen_div_trap_normal (operands[0],operands[1],operands[2]));
+ DONE;
+}")
+
+(define_insn "div_trap_normal"
+ [(trap_if (eq (match_operand 0 "register_operand" "d")
+ (match_operand 1 "true_reg_or_0_operand" "dJ"))
+ (match_operand 2 "immediate_operand" ""))]
+ "!TARGET_MIPS16"
"*
{
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"ddivu\\t%0,%1,%2\";
+ rtx link;
+ int have_dep_anti = 0;
- if (find_reg_note (insn, REG_UNUSED, operands[0]))
- return \"dremu\\t%3,%1,%2\";
+ /* For divmod if one division is not needed then we don't need an extra
+ divide by zero trap, which is anti dependent on previous trap */
+ for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
- return \"ddivu\\t%0,%1,%2\;mfhi\\t%3\";
+ if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link)
+ && GET_CODE (XEXP (link, 0)) == INSN
+ && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF
+ && REGNO (operands[1]) == 0)
+ have_dep_anti = 1;
+ if (! have_dep_anti)
+ {
+ if (GENERATE_BRANCHLIKELY)
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return \"%(beql\\t%0,$0,1f\\n\\tbreak\\t%2\\n1:%)\";
+ else
+ return \"%(beql\\t%0,%1,1f\\n\\tbreak\\t%2\\n1:%)\";
+ }
+ else
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return \"%(bne\\t%0,$0,1f\\n\\tnop\\n\\tbreak\\t%2\\n1:%)\";
+ else
+ return \"%(bne\\t%0,%1,1f\\n\\tnop\\n\\tbreak\\t%2\\n1:%)\";
+ }
+ }
+ return \"\";
}"
- [(set_attr "type" "idiv")
- (set_attr "mode" "DI")
- (set_attr "length" "8")]) ;; various tests for dividing by 0 and such
+ [(set_attr "type" "unknown")
+ (set_attr "length" "3")])
+
+
+;; The mips16 bne insns is a macro which uses reg 24 as an intermediate.
+
+(define_insn "div_trap_mips16"
+ [(trap_if (eq (match_operand 0 "register_operand" "d")
+ (match_operand 1 "true_reg_or_0_operand" "dJ"))
+ (match_operand 2 "immediate_operand" ""))
+ (clobber (reg:SI 24))]
+ "TARGET_MIPS16"
+ "*
+{
+ rtx link;
+ int have_dep_anti = 0;
+
+ /* For divmod if one division is not needed then we don't need an extra
+ divide by zero trap, which is anti dependent on previous trap */
+ for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
+
+ if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link)
+ && GET_CODE (XEXP (link, 0)) == INSN
+ && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF
+ && REGNO (operands[1]) == 0)
+ have_dep_anti = 1;
+ if (! have_dep_anti)
+ {
+ /* No branch delay slots on mips16. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return \"%(bnez\\t%0,1f\\n\\tbreak\\t%2\\n1:%)\";
+ else
+ return \"%(bne\\t%0,%1,1f\\n\\tbreak\\t%2\\n1:%)\";
+ }
+ return \"\";
+}"
+ [(set_attr "type" "unknown")
+ (set_attr "length" "3")])
(define_expand "divsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=l")
(div:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))
- (clobber (match_scratch:SI 3 "=l"))
- (clobber (match_scratch:SI 4 "=h"))
- (clobber (match_scratch:SI 6 "=a"))]
+ (match_operand:SI 2 "register_operand" "d")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
}")
(define_insn "divsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=l")
(div:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))]
+ (match_operand:SI 2 "nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
- "div\\t%0,%1,%2"
+ "div\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "13")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "divdi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=l")
(div:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))
- (clobber (match_scratch:DI 3 "=l"))
- (clobber (match_scratch:DI 4 "=h"))
- (clobber (match_scratch:DI 6 "=a"))]
+ (match_operand:DI 2 "se_register_operand" "d")))
+ (clobber (match_scratch:DI 3 "=h"))
+ (clobber (match_scratch:DI 4 "=a"))]
"TARGET_64BIT && !optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (DImode, operands[2]);
+ emit_insn (gen_divdi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
}")
(define_insn "divdi3_internal"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=l")
(div:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"TARGET_64BIT && !optimize"
- "ddiv\\t%0,%1,%2"
+ "ddiv\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")
- (set_attr "length" "14")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "modsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=h")
(mod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))
+ (match_operand:SI 2 "register_operand" "d")))
(clobber (match_scratch:SI 3 "=l"))
- (clobber (match_scratch:SI 4 "=h"))
- (clobber (match_scratch:SI 6 "=a"))]
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_modsi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (SImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
}")
(define_insn "modsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=h")
(mod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))]
+ (match_operand:SI 2 "nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=l"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
- "rem\\t%0,%1,%2"
+ "div\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "13")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "moddi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=h")
(mod:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (match_operand:DI 2 "se_register_operand" "d")))
(clobber (match_scratch:DI 3 "=l"))
- (clobber (match_scratch:DI 4 "=h"))
- (clobber (match_scratch:DI 6 "=a"))]
+ (clobber (match_scratch:DI 4 "=a"))]
"TARGET_64BIT && !optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (DImode, operands[2]);
+ emit_insn (gen_moddi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+ if (TARGET_CHECK_RANGE_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (-1)),
+ GEN_INT (0x6)));
+ emit_insn (gen_div_trap (operands[2],
+ copy_to_mode_reg (DImode, GEN_INT (0x80000000)),
+ GEN_INT (0x6)));
+ }
+
+ DONE;
}")
(define_insn "moddi3_internal"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=h")
(mod:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=l"))
+ (clobber (match_scratch:SI 4 "=a"))]
"TARGET_64BIT && !optimize"
- "drem\\t%0,%1,%2"
+ "ddiv\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")
- (set_attr "length" "14")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "udivsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=l")
(udiv:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))
- (clobber (match_scratch:SI 3 "=l"))
- (clobber (match_scratch:SI 4 "=h"))
- (clobber (match_scratch:SI 6 "=a"))]
+ (match_operand:SI 2 "register_operand" "d")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_udivsi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
}")
(define_insn "udivsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=l")
(udiv:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))]
+ (match_operand:SI 2 "nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
- "divu\\t%0,%1,%2"
+ "divu\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "7")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "udivdi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=l")
(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))
- (clobber (match_scratch:DI 3 "=l"))
- (clobber (match_scratch:DI 4 "=h"))
- (clobber (match_scratch:DI 6 "=a"))]
+ (match_operand:DI 2 "se_register_operand" "di")))
+ (clobber (match_scratch:DI 3 "=h"))
+ (clobber (match_scratch:DI 4 "=a"))]
"TARGET_64BIT && !optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (DImode, operands[2]);
+ emit_insn (gen_udivdi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
}")
(define_insn "udivdi3_internal"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=l")
(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=a"))]
"TARGET_64BIT && !optimize"
- "ddivu\\t%0,%1,%2"
+ "ddivu\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")
- (set_attr "length" "7")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "umodsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=h")
(umod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))
+ (match_operand:SI 2 "register_operand" "d")))
(clobber (match_scratch:SI 3 "=l"))
- (clobber (match_scratch:SI 4 "=h"))
- (clobber (match_scratch:SI 6 "=a"))]
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_umodsi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
}")
(define_insn "umodsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=h")
(umod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonmemory_operand" "di")))]
+ (match_operand:SI 2 "nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=l"))
+ (clobber (match_scratch:SI 4 "=a"))]
"!optimize"
- "remu\\t%0,%1,%2"
+ "divu\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
- (set_attr "length" "7")]) ;; various tests for dividing by 0 and such
+ (set_attr "length" "1")])
(define_expand "umoddi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=h")
(umod:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (match_operand:DI 2 "se_register_operand" "di")))
(clobber (match_scratch:DI 3 "=l"))
- (clobber (match_scratch:DI 4 "=h"))
- (clobber (match_scratch:DI 6 "=a"))]
+ (clobber (match_scratch:DI 4 "=a"))]
"TARGET_64BIT && !optimize"
"
{
- /* MIPS16 needs div/rem ops in registers. */
- if (TARGET_MIPS16)
- operands[2] = force_reg (DImode, operands[2]);
+ emit_insn (gen_umoddi3_internal (operands[0], operands[1], operands[2]));
+ if (!TARGET_NO_CHECK_ZERO_DIV)
+ {
+ emit_insn (gen_div_trap (operands[2],
+ GEN_INT (0),
+ GEN_INT (0x7)));
+ }
+
+ DONE;
}")
(define_insn "umoddi3_internal"
- [(set (match_operand:DI 0 "register_operand" "=d")
+ [(set (match_operand:DI 0 "register_operand" "=h")
(umod:DI (match_operand:DI 1 "se_register_operand" "d")
- (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
+ (clobber (match_scratch:SI 3 "=l"))
+ (clobber (match_scratch:SI 4 "=a"))]
"TARGET_64BIT && !optimize"
- "dremu\\t%0,%1,%2"
+ "ddivu\\t$0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "DI")
- (set_attr "length" "7")]) ;; various tests for dividing by 0 and such
-
+ (set_attr "length" "1")])
;;
;; ....................
@@ -4382,7 +4640,7 @@ move\\t%0,%z4\\n\\
rtx offset = const0_rtx;
rtx addr = XEXP (operands[1], 0);
rtx mem_addr = eliminate_constant_term (addr, &offset);
- char *ret;
+ const char *ret;
if (TARGET_STATS)
mips_count_memory_refs (operands[1], 2);
@@ -4441,7 +4699,7 @@ move\\t%0,%z4\\n\\
rtx offset = const0_rtx;
rtx addr = XEXP (operands[1], 0);
rtx mem_addr = eliminate_constant_term (addr, &offset);
- char *ret;
+ const char *ret;
if (TARGET_STATS)
mips_count_memory_refs (operands[1], 2);
@@ -4803,6 +5061,7 @@ move\\t%0,%z4\\n\\
emit_move_insn (gen_rtx (REG, SImode, 64), scratch);
emit_move_insn (scratch, loword);
emit_move_insn (gen_rtx (REG, SImode, 65), scratch);
+ emit_insn (gen_rtx_USE (VOIDmode, operands[0]));
}
else
{
@@ -4811,6 +5070,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[0]));
}
DONE;
}
@@ -4822,6 +5082,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64)));
emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
DONE;
}
/* This handles moves between a float register and HI/LO. */
@@ -4851,6 +5112,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[0]));
DONE;
}
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM)
@@ -4879,6 +5141,7 @@ move\\t%0,%z4\\n\\
emit_move_insn (hiword, scratch);
emit_move_insn (scratch, gen_rtx (REG, SImode, 65));
emit_move_insn (loword, scratch);
+ emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
}
else if (TARGET_MIPS16 && ! M16_REG_P (REGNO (operands[0])))
{
@@ -4893,6 +5156,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_ashldi3 (scratch2, scratch2, GEN_INT (32)));
emit_insn (gen_iordi3 (scratch, scratch, scratch2));
emit_insn (gen_movdi (operands[0], scratch));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
}
else
{
@@ -4902,6 +5166,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64)));
emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
}
DONE;
}
@@ -5225,6 +5490,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_movsi (gen_rtx (REG, SImode, 65), operands[1]));
emit_insn (gen_ashrsi3 (operands[2], operands[1], GEN_INT (31)));
emit_insn (gen_movsi (gen_rtx (REG, SImode, 64), operands[2]));
+ emit_insn (gen_rtx_USE (VOIDmode, operands[0]));
DONE;
}
/* Use a mult to reload LO on mips16. ??? This is hideous. */
@@ -8761,7 +9027,7 @@ move\\t%0,%z4\\n\\
/* ??? I don't know why this is necessary. This works around an
assembler problem that appears when a label is defined, then referenced
in a switch table, then used in a `j' instruction. */
- else if (mips_abi != ABI_32)
+ else if (mips_abi != ABI_32 && mips_abi != ABI_O64)
return \"%*b\\t%l0\";
else
return \"%*j\\t%l0\";
@@ -8952,7 +9218,7 @@ move\\t%0,%z4\\n\\
"*
{
/* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */
- if (mips_abi == ABI_32)
+ if (mips_abi == ABI_32 || mips_abi == ABI_O64)
output_asm_insn (\".cpadd\\t%0\", operands);
return \"%*j\\t%0\";
}"
@@ -9537,7 +9803,8 @@ move\\t%0,%z4\\n\\
(call (mem:SI (match_operand:SI 1 "register_operand" "r"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
- "!(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS"
+ "!TARGET_MIPS16
+ && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS"
"%*jal\\t%3,%1"
[(set_attr "type" "call")
(set_attr "mode" "none")
@@ -9548,7 +9815,20 @@ move\\t%0,%z4\\n\\
(call (mem:DI (match_operand:DI 1 "se_register_operand" "r"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
- "Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS"
+ "!TARGET_MIPS16
+ && Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS"
+ "%*jal\\t%3,%1"
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "1")])
+
+(define_insn "call_value_internal3c"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "e"))
+ (match_operand 2 "" "i")))
+ (clobber (match_operand:SI 3 "register_operand" "=y"))]
+ "TARGET_MIPS16 && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS
+ && GET_CODE (operands[3]) == REG && REGNO (operands[3]) == 31"
"%*jal\\t%3,%1"
[(set_attr "type" "call")
(set_attr "mode" "none")