Commit 08c2951c by Stan Cox Committed by Stan Cox

mips.md (divmodsi4*, [...]): Add -mcheck-range-division/ -mcheck-zero-division checking.

* mips.md (divmodsi4*, divmoddi4*, udivmodsi4*, udivmoddi4): Add -mcheck-range-division/
-mcheck-zero-division checking.  Avoid as macro expansion.  Use hi/lo as destination
register.
(div_trap): New.
(divsi3*, divdi3*, modsi3*, moddi3*, udivsi3*, udivdi3*, umodsi3*,
umoddi3*): Add -mcheck-range-division/-mcheck-zero-division checking.
Avoid as macro expansion.  Use hi/lo as destination register.
* mips.h (MASK_CHECK_RANGE_DIV): New.
(MASK_NO_CHECK_ZERO_DIV): New.
(ELIMINABLE_REGS): Added GP_REG_FIRST + 31.
(CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): Allow for getting
return address for leaf functions out of r31 to support
builtin_return_address.

From-SVN: r24047
parent 1f5fb51f
Tue Dec 1 16:45:49 1998 Stan Cox <scox@cygnus.com>
* mips.md (divmodsi4*, divmoddi4*, udivmodsi4*, udivmoddi4): Add
-mcheck-range-division/-mcheck-zero-division checking. Avoid as macro
expansion. Use hi/lo as destination register.
(div_trap): New.
(divsi3*, divdi3*, modsi3*, moddi3*, udivsi3*, udivdi3*, umodsi3*,
umoddi3*): Add -mcheck-range-division/-mcheck-zero-division checking.
Avoid as macro expansion. Use hi/lo as destination register.
* mips.h (MASK_CHECK_RANGE_DIV): New.
(MASK_NO_CHECK_ZERO_DIV): New.
(ELIMINABLE_REGS): Added GP_REG_FIRST + 31.
(CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): Allow for getting
return address for leaf functions out of r31 to support
builtin_return_address.
Tue Dec 1 15:03:30 1998 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl> Tue Dec 1 15:03:30 1998 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
* jump.c (jump_optimize): Call regs_set_between_p with PREV_INSN(x), * jump.c (jump_optimize): Call regs_set_between_p with PREV_INSN(x),
......
...@@ -336,16 +336,18 @@ extern void mips_select_section (); ...@@ -336,16 +336,18 @@ extern void mips_select_section ();
#define MASK_4300_MUL_FIX 0x00080000 /* Work-around early Vr4300 CPU bug */ #define MASK_4300_MUL_FIX 0x00080000 /* Work-around early Vr4300 CPU bug */
#define MASK_MIPS3900 0x00100000 /* like -mips1 only 3900 */ #define MASK_MIPS3900 0x00100000 /* like -mips1 only 3900 */
#define MASK_MIPS16 0x01000000 /* Generate mips16 code */ #define MASK_MIPS16 0x01000000 /* Generate mips16 code */
#define MASK_NO_CHECK_ZERO_DIV 0x04000000 /* divide by zero checking */
#define MASK_CHECK_RANGE_DIV 0x08000000 /* divide result range checking */
/* Dummy switches used only in spec's*/ /* Dummy switches used only in spec's*/
#define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */ #define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */
/* Debug switches, not documented */ /* Debug switches, not documented */
#define MASK_DEBUG 0x40000000 /* Eliminate version # in .s file */ #define MASK_DEBUG 0 /* Eliminate version # in .s file */
#define MASK_DEBUG_A 0x20000000 /* don't allow <label>($reg) addrs */ #define MASK_DEBUG_A 0x40000000 /* don't allow <label>($reg) addrs */
#define MASK_DEBUG_B 0x10000000 /* GO_IF_LEGITIMATE_ADDRESS debug */ #define MASK_DEBUG_B 0x20000000 /* GO_IF_LEGITIMATE_ADDRESS debug */
#define MASK_DEBUG_C 0x08000000 /* don't expand seq, etc. */ #define MASK_DEBUG_C 0x10000000 /* don't expand seq, etc. */
#define MASK_DEBUG_D 0x04000000 /* don't do define_split's */ #define MASK_DEBUG_D 0 /* don't do define_split's */
#define MASK_DEBUG_E 0 /* function_arg debug */ #define MASK_DEBUG_E 0 /* function_arg debug */
#define MASK_DEBUG_F 0 #define MASK_DEBUG_F 0
#define MASK_DEBUG_G 0 /* don't support 64 bit arithmetic */ #define MASK_DEBUG_G 0 /* don't support 64 bit arithmetic */
...@@ -425,6 +427,9 @@ extern void mips_select_section (); ...@@ -425,6 +427,9 @@ extern void mips_select_section ();
#define TARGET_4300_MUL_FIX (target_flags & MASK_4300_MUL_FIX) #define TARGET_4300_MUL_FIX (target_flags & MASK_4300_MUL_FIX)
#define TARGET_NO_CHECK_ZERO_DIV (target_flags & MASK_NO_CHECK_ZERO_DIV)
#define TARGET_CHECK_RANGE_DIV (target_flags & MASK_CHECK_RANGE_DIV)
/* This is true if we must enable the assembly language file switching /* This is true if we must enable the assembly language file switching
code. */ code. */
...@@ -490,6 +495,10 @@ extern void mips_select_section (); ...@@ -490,6 +495,10 @@ extern void mips_select_section ();
{"no-fix4300", -MASK_4300_MUL_FIX}, \ {"no-fix4300", -MASK_4300_MUL_FIX}, \
{"4650", MASK_MAD | MASK_SINGLE_FLOAT}, \ {"4650", MASK_MAD | MASK_SINGLE_FLOAT}, \
{"3900", MASK_MIPS3900}, \ {"3900", MASK_MIPS3900}, \
{"check-zero-division",-MASK_NO_CHECK_ZERO_DIV}, \
{"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV}, \
{"check-range-division",MASK_CHECK_RANGE_DIV}, \
{"no-check-range-division",-MASK_CHECK_RANGE_DIV}, \
{"debug", MASK_DEBUG}, \ {"debug", MASK_DEBUG}, \
{"debuga", MASK_DEBUG_A}, \ {"debuga", MASK_DEBUG_A}, \
{"debugb", MASK_DEBUG_B}, \ {"debugb", MASK_DEBUG_B}, \
...@@ -2144,6 +2153,7 @@ extern struct mips_frame_info current_frame_info; ...@@ -2144,6 +2153,7 @@ extern struct mips_frame_info current_frame_info;
{ RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 30}, \ { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 30}, \
{ RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 17}, \ { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 17}, \
{ RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 31}, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \ { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}} { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
...@@ -2169,11 +2179,14 @@ extern struct mips_frame_info current_frame_info; ...@@ -2169,11 +2179,14 @@ extern struct mips_frame_info current_frame_info;
*/ */
#define CAN_ELIMINATE(FROM, TO) \ #define CAN_ELIMINATE(FROM, TO) \
((TO) == HARD_FRAME_POINTER_REGNUM \ (((FROM) == RETURN_ADDRESS_POINTER_REGNUM && (! leaf_function_p () \
|| TO == GP_REG_FIRST + 31 && leaf_function_p)) \
|| ((FROM) != RETURN_ADDRESS_POINTER_REGNUM \
&& ((TO) == HARD_FRAME_POINTER_REGNUM \
|| ((TO) == STACK_POINTER_REGNUM && ! frame_pointer_needed \ || ((TO) == STACK_POINTER_REGNUM && ! frame_pointer_needed \
&& ! (TARGET_MIPS16 && TARGET_64BIT) \ && ! (TARGET_MIPS16 && TARGET_64BIT) \
&& (! TARGET_MIPS16 \ && (! TARGET_MIPS16 \
|| compute_frame_size (get_frame_size ()) < 32768))) || compute_frame_size (get_frame_size ()) < 32768)))))
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It
specifies the initial difference between the specified pair of specifies the initial difference between the specified pair of
...@@ -2206,7 +2219,9 @@ extern struct mips_frame_info current_frame_info; ...@@ -2206,7 +2219,9 @@ extern struct mips_frame_info current_frame_info;
/* Some ABIs store 64 bits to the stack, but Pmode is 32 bits, \ /* Some ABIs store 64 bits to the stack, but Pmode is 32 bits, \
so we must add 4 bytes to the offset to get the right value. */ \ so we must add 4 bytes to the offset to get the right value. */ \
else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM) \ else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM) \
(OFFSET) = current_frame_info.gp_sp_offset \ if (leaf_function_p ()) \
(OFFSET) = 0; \
else (OFFSET) = current_frame_info.gp_sp_offset \
+ ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) \ + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) \
* (BYTES_BIG_ENDIAN != 0)); \ * (BYTES_BIG_ENDIAN != 0)); \
} }
......
...@@ -2228,7 +2228,7 @@ ...@@ -2228,7 +2228,7 @@
;; a divide by power of 2 with a shift, and then the remainder is no longer ;; a divide by power of 2 with a shift, and then the remainder is no longer
;; available. ;; available.
(define_insn "divmodsi4" (define_expand "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "register_operand" "d") (div:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d"))) (match_operand:SI 2 "register_operand" "d")))
...@@ -2239,21 +2239,46 @@ ...@@ -2239,21 +2239,46 @@
(clobber (match_scratch:SI 5 "=h")) (clobber (match_scratch:SI 5 "=h"))
(clobber (match_scratch:SI 6 "=a"))] (clobber (match_scratch:SI 6 "=a"))]
"optimize" "optimize"
"* "
{ {
if (find_reg_note (insn, REG_UNUSED, operands[3])) rtx label;
return \"div\\t%0,%1,%2\";
if (find_reg_note (insn, REG_UNUSED, operands[0])) emit_insn (gen_divmodsi4_internal (operands[0], operands[1], operands[2],
return \"rem\\t%3,%1,%2\"; operands[3]));
if (!TARGET_NO_CHECK_ZERO_DIV)
{
emit_insn (gen_div_trap (operands[2],
copy_to_mode_reg (SImode, 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 "type" "idiv")
(set_attr "mode" "SI") (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") [(set (match_operand:DI 0 "register_operand" "=d")
(div:DI (match_operand:DI 1 "se_register_operand" "d") (div:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "se_register_operand" "d"))) (match_operand:DI 2 "se_register_operand" "d")))
...@@ -2264,21 +2289,46 @@ ...@@ -2264,21 +2289,46 @@
(clobber (match_scratch:DI 5 "=h")) (clobber (match_scratch:DI 5 "=h"))
(clobber (match_scratch:DI 6 "=a"))] (clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && optimize" "TARGET_64BIT && optimize"
"* "
{ {
if (find_reg_note (insn, REG_UNUSED, operands[3])) rtx label;
return \"ddiv\\t%0,%1,%2\";
if (find_reg_note (insn, REG_UNUSED, operands[0])) emit_insn (gen_divmoddi4_internal (operands[0], operands[1], operands[2],
return \"drem\\t%3,%1,%2\"; operands[3]));
if (!TARGET_NO_CHECK_ZERO_DIV)
{
emit_insn (gen_div_trap (operands[2],
copy_to_mode_reg (DImode, 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 "type" "idiv")
(set_attr "mode" "DI") (set_attr "mode" "SI")
(set_attr "length" "15")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_insn "udivmodsi4" (define_expand "udivmodsi4"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "register_operand" "d") (udiv:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d"))) (match_operand:SI 2 "register_operand" "d")))
...@@ -2289,21 +2339,37 @@ ...@@ -2289,21 +2339,37 @@
(clobber (match_scratch:SI 5 "=h")) (clobber (match_scratch:SI 5 "=h"))
(clobber (match_scratch:SI 6 "=a"))] (clobber (match_scratch:SI 6 "=a"))]
"optimize" "optimize"
"* "
{ {
if (find_reg_note (insn, REG_UNUSED, operands[3])) rtx label;
return \"divu\\t%0,%1,%2\";
if (find_reg_note (insn, REG_UNUSED, operands[0])) emit_insn (gen_udivmodsi4_internal (operands[0], operands[1], operands[2],
return \"remu\\t%3,%1,%2\"; operands[3]));
if (!TARGET_NO_CHECK_ZERO_DIV)
{
emit_insn (gen_div_trap (operands[2],
copy_to_mode_reg (SImode, 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 "type" "idiv")
(set_attr "mode" "SI") (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") [(set (match_operand:DI 0 "register_operand" "=d")
(udiv:DI (match_operand:DI 1 "se_register_operand" "d") (udiv:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "se_register_operand" "d"))) (match_operand:DI 2 "se_register_operand" "d")))
...@@ -2314,220 +2380,372 @@ ...@@ -2314,220 +2380,372 @@
(clobber (match_scratch:DI 5 "=h")) (clobber (match_scratch:DI 5 "=h"))
(clobber (match_scratch:DI 6 "=a"))] (clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && optimize" "TARGET_64BIT && optimize"
"
{
rtx label;
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],
copy_to_mode_reg (DImode, 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_insn "div_trap"
[(trap_if (eq (match_operand 0 "register_operand" "d")
(match_operand 1 "reg_or_0_operand" "dJ"))
(match_operand 2 "immediate_operand" ""))]
""
"* "*
{ {
if (find_reg_note (insn, REG_UNUSED, operands[3])) rtx link;
return \"ddivu\\t%0,%1,%2\"; int have_dep_anti = 0;
if (find_reg_note (insn, REG_UNUSED, operands[0])) /* For divmod if one division is not needed then we don't need an extra
return \"dremu\\t%3,%1,%2\"; 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 (PATTERN (XEXP (link, 0))) == TRAP_IF
&& REGNO (operands[1]) == 0)
have_dep_anti = 1;
if (! have_dep_anti)
if (GENERATE_BRANCHLIKELY)
return \"%(beql\\t%0,%1,.+8\\n\\tbreak\\t%2%)\";
else
return \"%(bne\\t%0,%1,.+12\\n\\tnop\\n\\tbreak\\t%2%)\";
}" }"
[(set_attr "type" "idiv") [(set_attr "type" "unknown")
(set_attr "mode" "DI") (set_attr "length" "2")])
(set_attr "length" "8")]) ;; various tests for dividing by 0 and such
(define_expand "divsi3" (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") (div: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 3 "=h"))
(clobber (match_scratch:SI 4 "=h")) (clobber (match_scratch:SI 4 "=a"))]
(clobber (match_scratch:SI 6 "=a"))]
"!optimize" "!optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (SImode, 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" (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") (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" "!optimize"
"div\\t%0,%1,%2" "div\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "13")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "divdi3" (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") (div: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 3 "=h"))
(clobber (match_scratch:DI 4 "=h")) (clobber (match_scratch:DI 4 "=a"))]
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && !optimize" "TARGET_64BIT && !optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (DImode, 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" (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") (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" "TARGET_64BIT && !optimize"
"ddiv\\t%0,%1,%2" "ddiv\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "14")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "modsi3" (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") (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 3 "=l"))
(clobber (match_scratch:SI 4 "=h")) (clobber (match_scratch:SI 4 "=a"))]
(clobber (match_scratch:SI 6 "=a"))]
"!optimize" "!optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (SImode, 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" (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") (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" "!optimize"
"rem\\t%0,%1,%2" "div\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "13")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "moddi3" (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") (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 3 "=l"))
(clobber (match_scratch:DI 4 "=h")) (clobber (match_scratch:DI 4 "=a"))]
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && !optimize" "TARGET_64BIT && !optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (DImode, 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" (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") (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" "TARGET_64BIT && !optimize"
"drem\\t%0,%1,%2" "ddiv\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "14")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "udivsi3" (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") (udiv: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 3 "=h"))
(clobber (match_scratch:SI 4 "=h")) (clobber (match_scratch:SI 4 "=a"))]
(clobber (match_scratch:SI 6 "=a"))]
"!optimize" "!optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (SImode, GEN_INT (0)),
GEN_INT (0x7)));
}
DONE;
}") }")
(define_insn "udivsi3_internal" (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") (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" "!optimize"
"divu\\t%0,%1,%2" "divu\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "7")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "udivdi3" (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") (udiv: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 3 "=h"))
(clobber (match_scratch:DI 4 "=h")) (clobber (match_scratch:DI 4 "=a"))]
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && !optimize" "TARGET_64BIT && !optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (DImode, GEN_INT (0)),
GEN_INT (0x7)));
}
DONE;
}") }")
(define_insn "udivdi3_internal" (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") (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" "TARGET_64BIT && !optimize"
"ddivu\\t%0,%1,%2" "ddivu\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "7")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "umodsi3" (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") (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 3 "=l"))
(clobber (match_scratch:SI 4 "=h")) (clobber (match_scratch:SI 4 "=a"))]
(clobber (match_scratch:SI 6 "=a"))]
"!optimize" "!optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (SImode, GEN_INT (0)),
GEN_INT (0x7)));
}
DONE;
}") }")
(define_insn "umodsi3_internal" (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") (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" "!optimize"
"remu\\t%0,%1,%2" "divu\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "7")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
(define_expand "umoddi3" (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") (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 3 "=l"))
(clobber (match_scratch:DI 4 "=h")) (clobber (match_scratch:DI 4 "=a"))]
(clobber (match_scratch:DI 6 "=a"))]
"TARGET_64BIT && !optimize" "TARGET_64BIT && !optimize"
" "
{ {
/* MIPS16 needs div/rem ops in registers. */ rtx label;
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],
copy_to_mode_reg (DImode, GEN_INT (0)),
GEN_INT (0x7)));
}
DONE;
}") }")
(define_insn "umoddi3_internal" (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") (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" "TARGET_64BIT && !optimize"
"dremu\\t%0,%1,%2" "ddivu\\t$0,%1,%2"
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "7")]) ;; various tests for dividing by 0 and such (set_attr "length" "1")])
;; ;;
;; .................... ;; ....................
......
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